source: webkit/trunk/JavaScriptCore/kjs/interpreter.cpp@ 14951

Last change on this file since 14951 was 14951, checked in by ggaren, 19 years ago

JavaScriptCore:

Reviewed by Anders.


  • First cut at C API to JavaScript. Includes a unit test, 'testapi.c', and the outline of a test app, 'minidom.c'.


Includes one change to JSC internals: Rename propList to getPropertyList and have it
take its target property list by reference so that subclasses can
add properties to the list before calling through to their superclasses.


Also, I just ran prepare-ChangeLog in about 10 seconds, and I would like
to give a shout-out to that.


  • API/APICast.h: Added. (toJS): (toRef):
  • API/JSBase.h: Added.
  • API/JSCallbackObject.cpp: Added. (KJS::): (KJS::JSCallbackObject::JSCallbackObject): (KJS::JSCallbackObject::~JSCallbackObject): (KJS::JSCallbackObject::className): (KJS::JSCallbackObject::getOwnPropertySlot): (KJS::JSCallbackObject::put): (KJS::JSCallbackObject::deleteProperty): (KJS::JSCallbackObject::implementsConstruct): (KJS::JSCallbackObject::construct): (KJS::JSCallbackObject::implementsCall): (KJS::JSCallbackObject::callAsFunction): (KJS::JSCallbackObject::getPropertyList): (KJS::JSCallbackObject::toBoolean): (KJS::JSCallbackObject::toNumber): (KJS::JSCallbackObject::toString): (KJS::JSCallbackObject::setPrivate): (KJS::JSCallbackObject::getPrivate): (KJS::JSCallbackObject::cachedValueGetter): (KJS::JSCallbackObject::callbackGetter):
  • API/JSCallbackObject.h: Added. (KJS::JSCallbackObject::classInfo):
  • API/JSCharBufferRef.cpp: Added. (JSStringMake): (JSCharBufferCreate): (JSCharBufferCreateUTF8): (JSCharBufferRetain): (JSCharBufferRelease): (JSValueCopyStringValue): (JSCharBufferGetLength): (JSCharBufferGetCharactersPtr): (JSCharBufferGetCharacters): (JSCharBufferGetMaxLengthUTF8): (JSCharBufferGetCharactersUTF8): (JSCharBufferIsEqual): (JSCharBufferIsEqualUTF8): (JSCharBufferCreateWithCFString): (CFStringCreateWithJSCharBuffer):
  • API/JSCharBufferRef.h: Added.
  • API/JSContextRef.cpp: Added. (JSContextCreate): (JSContextDestroy): (JSContextGetGlobalObject): (JSEvaluate): (JSCheckSyntax): (JSContextHasException): (JSContextGetException): (JSContextClearException): (JSContextSetException):
  • API/JSContextRef.h: Added.
  • API/JSObjectRef.cpp: Added. (JSValueToObject): (JSObjectMake): (JSFunctionMake): (JSObjectGetDescription): (JSObjectGetPrototype): (JSObjectSetPrototype): (JSObjectHasProperty): (JSObjectGetProperty): (JSObjectSetProperty): (JSObjectDeleteProperty): (JSObjectGetPrivate): (JSObjectSetPrivate): (JSObjectIsFunction): (JSObjectCallAsFunction): (JSObjectIsConstructor): (JSObjectCallAsConstructor): (JSPropertyListEnumerator::JSPropertyListEnumerator): (JSObjectCreatePropertyEnumerator): (JSPropertyEnumeratorGetNext): (JSPropertyEnumeratorRetain): (JSPropertyEnumeratorRelease): (JSPropertyListAdd):
  • API/JSObjectRef.h: Added.
  • API/JSValueRef.cpp: Added. (JSValueGetType): (JSValueIsUndefined): (JSValueIsNull): (JSValueIsBoolean): (JSValueIsNumber): (JSValueIsString): (JSValueIsObject): (JSValueIsEqual): (JSValueIsStrictEqual): (JSUndefinedMake): (JSNullMake): (JSBooleanMake): (JSNumberMake): (JSValueToBoolean): (JSValueToNumber): (JSGCProtect): (JSGCUnprotect): (JSGCCollect):
  • API/JSValueRef.h: Added.
  • API/JavaScriptCore.h: Added.
  • API/minidom.c: Added. (main):
  • API/minidom.html: Added.
  • API/minidom.js: Added.
  • API/testapi.c: Added. (assertEqualsAsBoolean): (assertEqualsAsNumber): (assertEqualsAsUTF8String): (assertEqualsAsCharactersPtr): (assertEqualsAsCharacters): (MyObject_initialize): (MyObject_copyDescription): (MyObject_hasProperty): (MyObject_getProperty): (MyObject_setProperty): (MyObject_deleteProperty): (MyObject_getPropertyList): (MyObject_callAsFunction): (MyObject_callAsConstructor): (MyObject_convertToType): (MyObject_finalize): (print_callAsFunction): (main): (createStringWithContentsOfFile):
  • API/testapi.js: Added.
  • ChangeLog:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bindings/npruntime_impl.h:
  • kjs/array_instance.h:
  • kjs/array_object.cpp: (ArrayInstance::getPropertyList):
  • kjs/interpreter.cpp: (KJS::Interpreter::evaluate):
  • kjs/nodes.cpp: (ForInNode::execute):
  • kjs/object.cpp: (KJS::JSObject::put): (KJS::JSObject::canPut): (KJS::JSObject::deleteProperty): (KJS::JSObject::propertyIsEnumerable): (KJS::JSObject::getPropertyAttributes): (KJS::JSObject::getPropertyList):
  • kjs/object.h:
  • kjs/property_map.cpp: (KJS::PropertyMap::get):
  • kjs/property_map.h:
  • kjs/scope_chain.cpp: (KJS::ScopeChain::print):
  • kjs/string_object.cpp: (StringInstance::getPropertyList):
  • kjs/string_object.h:
  • kjs/ustring.h: (KJS::UString::Rep::ref):

JavaScriptGlue:

Reviewed by Anders.


  • Required for JS API: Rename propList to getPropertyList and have it take its target property list by reference so that subclasses can add properties to the list before calling through to their superclasses.
  • JSUtils.cpp: (KJSValueToCFTypeInternal):
  • JSValueWrapper.cpp: (JSValueWrapper::JSObjectCopyPropertyNames):
  • UserObjectImp.cpp: (UserObjectImp::getPropertyList):
  • UserObjectImp.h:
  • Property svn:eol-style set to native
File size: 26.0 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2001 Harri Porten ([email protected])
5 * Copyright (C) 2001 Peter Kelly ([email protected])
6 * Copyright (C) 2003 Apple Computer, Inc.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#include "config.h"
26#include "interpreter.h"
27
28#include "SavedBuiltins.h"
29#include "array_object.h"
30#include "bool_object.h"
31#include "collector.h"
32#include "context.h"
33#include "date_object.h"
34#include "debugger.h"
35#include "error_object.h"
36#include "function_object.h"
37#include "internal.h"
38#include "math_object.h"
39#include "nodes.h"
40#include "number_object.h"
41#include "object.h"
42#include "object_object.h"
43#include "operations.h"
44#include "regexp_object.h"
45#include "string_object.h"
46#include "types.h"
47#include "value.h"
48
49#if PLATFORM(MAC)
50#include "runtime.h"
51#endif
52
53#if HAVE(SYS_TIME_H)
54#include <sys/time.h>
55#endif
56
57#include <assert.h>
58#include <math.h>
59#include <stdio.h>
60
61namespace KJS {
62
63class TimeoutChecker {
64public:
65 void startTimeoutCheck(Interpreter*);
66 void stopTimeoutCheck(Interpreter*);
67 void pauseTimeoutCheck(Interpreter*);
68 void resumeTimeoutCheck(Interpreter*);
69
70private:
71#if HAVE(SYS_TIME_H)
72 static Interpreter* s_executingInterpreter;
73 static void alarmHandler(int);
74
75 Interpreter* m_oldInterpreter;
76 itimerval m_oldtv;
77 itimerval m_pausetv;
78 void (*m_oldAlarmHandler)(int);
79#endif
80};
81
82#if HAVE(SYS_TIME_H)
83Interpreter* TimeoutChecker::s_executingInterpreter = 0;
84#endif
85
86void TimeoutChecker::startTimeoutCheck(Interpreter *interpreter)
87{
88 if (!interpreter->m_timeoutTime)
89 return;
90
91 interpreter->m_startTimeoutCheckCount++;
92
93#if HAVE(SYS_TIME_H)
94 if (s_executingInterpreter == interpreter)
95 return;
96
97 // Block signals
98 m_oldAlarmHandler = signal(SIGALRM, SIG_IGN);
99
100 m_oldInterpreter = s_executingInterpreter;
101 s_executingInterpreter = interpreter;
102
103 itimerval tv = {
104 { interpreter->m_timeoutTime / 1000, (interpreter->m_timeoutTime % 1000) * 1000 },
105 { interpreter->m_timeoutTime / 1000, (interpreter->m_timeoutTime % 1000) * 1000 }
106 };
107 setitimer(ITIMER_REAL, &tv, &m_oldtv);
108
109 // Unblock signals
110 signal(SIGALRM, alarmHandler);
111#endif
112}
113
114void TimeoutChecker::stopTimeoutCheck(Interpreter* interpreter)
115{
116 if (!interpreter->m_timeoutTime)
117 return;
118
119 ASSERT(interpreter->m_startTimeoutCheckCount > 0);
120
121 interpreter->m_startTimeoutCheckCount--;
122
123 if (interpreter->m_startTimeoutCheckCount != 0)
124 return;
125
126#if HAVE(SYS_TIME_H)
127 signal(SIGALRM, SIG_IGN);
128
129 s_executingInterpreter = m_oldInterpreter;
130
131 setitimer(ITIMER_REAL, &m_oldtv, 0L);
132 signal(SIGALRM, m_oldAlarmHandler);
133#endif
134}
135
136#if HAVE(SYS_TIME_H)
137void TimeoutChecker::alarmHandler(int)
138{
139 s_executingInterpreter->m_timedOut = true;
140}
141#endif
142
143void TimeoutChecker::pauseTimeoutCheck(Interpreter* interpreter)
144{
145 if (interpreter->m_startTimeoutCheckCount == 0)
146 return;
147
148#if HAVE(SYS_TIME_H)
149 ASSERT(interpreter == s_executingInterpreter);
150
151 void (*currentSignalHandler)(int);
152
153 // Block signal
154 currentSignalHandler = signal(SIGALRM, SIG_IGN);
155
156 if (currentSignalHandler != alarmHandler) {
157 signal(SIGALRM, currentSignalHandler);
158 return;
159 }
160
161 setitimer(ITIMER_REAL, 0L, &m_pausetv);
162#endif
163
164 interpreter->m_pauseTimeoutCheckCount++;
165}
166
167void TimeoutChecker::resumeTimeoutCheck(Interpreter* interpreter)
168{
169 if (interpreter->m_startTimeoutCheckCount == 0)
170 return;
171
172#if HAVE(SYS_TIME_H)
173 ASSERT(interpreter == s_executingInterpreter);
174#endif
175
176 interpreter->m_pauseTimeoutCheckCount--;
177
178 if (interpreter->m_pauseTimeoutCheckCount != 0)
179 return;
180
181#if HAVE(SYS_TIME_H)
182 void (*currentSignalHandler)(int);
183
184 // Check so we have the right handler
185 currentSignalHandler = signal(SIGALRM, SIG_IGN);
186
187 if (currentSignalHandler != SIG_IGN) {
188 signal(SIGALRM, currentSignalHandler);
189 return;
190 }
191
192 setitimer(ITIMER_REAL, &m_pausetv, 0L);
193
194 // Unblock signal
195 currentSignalHandler = signal(SIGALRM, alarmHandler);
196#endif
197}
198
199Interpreter* Interpreter::s_hook = 0;
200
201typedef HashMap<JSObject*, Interpreter*> InterpreterMap;
202static inline InterpreterMap &interpreterMap()
203{
204 static InterpreterMap* map = new InterpreterMap;
205 return* map;
206}
207
208Interpreter::Interpreter(JSObject* globalObject)
209 : m_timeoutTime(0)
210 , m_globalExec(this, 0)
211 , m_globalObject(globalObject)
212 , m_argumentsPropertyName(&argumentsPropertyName)
213 , m_specialPrototypePropertyName(&specialPrototypePropertyName)
214 , m_timeoutChecker(0)
215 , m_timedOut(false)
216 , m_startTimeoutCheckCount(0)
217 , m_pauseTimeoutCheckCount(0)
218{
219 init();
220}
221
222Interpreter::Interpreter()
223 : m_timeoutTime(0)
224 , m_globalExec(this, 0)
225 , m_globalObject(new JSObject())
226 , m_argumentsPropertyName(&argumentsPropertyName)
227 , m_specialPrototypePropertyName(&specialPrototypePropertyName)
228 , m_timeoutChecker(0)
229 , m_timedOut(false)
230 , m_startTimeoutCheckCount(0)
231 , m_pauseTimeoutCheckCount(0)
232{
233 init();
234}
235
236void Interpreter::init()
237{
238 JSLock lock;
239
240 m_recursion = 0;
241 m_debugger= 0;
242 m_context = 0;
243 m_compatMode = NativeMode;
244
245 interpreterMap().set(m_globalObject, this);
246
247 if (s_hook) {
248 prev = s_hook;
249 next = s_hook->next;
250 s_hook->next->prev = this;
251 s_hook->next = this;
252 } else {
253 // This is the first interpreter
254 s_hook = next = prev = this;
255 }
256
257 initGlobalObject();
258}
259
260Interpreter::~Interpreter()
261{
262 JSLock lock;
263
264 ASSERT (m_startTimeoutCheckCount == 0);
265 ASSERT (m_pauseTimeoutCheckCount == 0);
266
267 delete m_timeoutChecker;
268
269 if (m_debugger)
270 m_debugger->detach(this);
271
272 next->prev = prev;
273 prev->next = next;
274 s_hook = next;
275 if (s_hook == this)
276 {
277 // This was the last interpreter
278 s_hook = 0;
279 }
280
281 interpreterMap().remove(m_globalObject);
282}
283
284JSObject* Interpreter::globalObject() const
285{
286 return m_globalObject;
287}
288
289void Interpreter::initGlobalObject()
290{
291 Identifier::init();
292
293 FunctionPrototype *funcProto = new FunctionPrototype(&m_globalExec);
294 m_FunctionPrototype = funcProto;
295 ObjectPrototype *objProto = new ObjectPrototype(&m_globalExec, funcProto);
296 m_ObjectPrototype = objProto;
297 funcProto->setPrototype(m_ObjectPrototype);
298
299 ArrayPrototype *arrayProto = new ArrayPrototype(&m_globalExec, objProto);
300 m_ArrayPrototype = arrayProto;
301 StringPrototype *stringProto = new StringPrototype(&m_globalExec, objProto);
302 m_StringPrototype = stringProto;
303 BooleanPrototype *booleanProto = new BooleanPrototype(&m_globalExec, objProto, funcProto);
304 m_BooleanPrototype = booleanProto;
305 NumberPrototype *numberProto = new NumberPrototype(&m_globalExec, objProto, funcProto);
306 m_NumberPrototype = numberProto;
307 DatePrototype *dateProto = new DatePrototype(&m_globalExec, objProto);
308 m_DatePrototype = dateProto;
309 RegExpPrototype *regexpProto = new RegExpPrototype(&m_globalExec, objProto, funcProto);
310 m_RegExpPrototype = regexpProto;
311 ErrorPrototype *errorProto = new ErrorPrototype(&m_globalExec, objProto, funcProto);
312 m_ErrorPrototype = errorProto;
313
314 JSObject* o = m_globalObject;
315 while (o->prototype()->isObject())
316 o = static_cast<JSObject*>(o->prototype());
317 o->setPrototype(m_ObjectPrototype);
318
319 // Constructors (Object, Array, etc.)
320 m_Object = new ObjectObjectImp(&m_globalExec, objProto, funcProto);
321 m_Function = new FunctionObjectImp(&m_globalExec, funcProto);
322 m_Array = new ArrayObjectImp(&m_globalExec, funcProto, arrayProto);
323 m_String = new StringObjectImp(&m_globalExec, funcProto, stringProto);
324 m_Boolean = new BooleanObjectImp(&m_globalExec, funcProto, booleanProto);
325 m_Number = new NumberObjectImp(&m_globalExec, funcProto, numberProto);
326 m_Date = new DateObjectImp(&m_globalExec, funcProto, dateProto);
327 m_RegExp = new RegExpObjectImp(&m_globalExec, funcProto, regexpProto);
328 m_Error = new ErrorObjectImp(&m_globalExec, funcProto, errorProto);
329
330 // Error object prototypes
331 m_EvalErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, EvalError, "EvalError", "EvalError");
332 m_RangeErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, RangeError, "RangeError", "RangeError");
333 m_ReferenceErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, ReferenceError, "ReferenceError", "ReferenceError");
334 m_SyntaxErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, SyntaxError, "SyntaxError", "SyntaxError");
335 m_TypeErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, TypeError, "TypeError", "TypeError");
336 m_UriErrorPrototype = new NativeErrorPrototype(&m_globalExec, errorProto, URIError, "URIError", "URIError");
337
338 // Error objects
339 m_EvalError = new NativeErrorImp(&m_globalExec, funcProto, m_EvalErrorPrototype);
340 m_RangeError = new NativeErrorImp(&m_globalExec, funcProto, m_RangeErrorPrototype);
341 m_ReferenceError = new NativeErrorImp(&m_globalExec, funcProto, m_ReferenceErrorPrototype);
342 m_SyntaxError = new NativeErrorImp(&m_globalExec, funcProto, m_SyntaxErrorPrototype);
343 m_TypeError = new NativeErrorImp(&m_globalExec, funcProto, m_TypeErrorPrototype);
344 m_UriError = new NativeErrorImp(&m_globalExec, funcProto, m_UriErrorPrototype);
345
346 // ECMA 15.3.4.1
347 funcProto->put(&m_globalExec, constructorPropertyName, m_Function, DontEnum);
348
349 m_globalObject->put(&m_globalExec, "Object", m_Object, DontEnum);
350 m_globalObject->put(&m_globalExec, "Function", m_Function, DontEnum);
351 m_globalObject->put(&m_globalExec, "Array", m_Array, DontEnum);
352 m_globalObject->put(&m_globalExec, "Boolean", m_Boolean, DontEnum);
353 m_globalObject->put(&m_globalExec, "String", m_String, DontEnum);
354 m_globalObject->put(&m_globalExec, "Number", m_Number, DontEnum);
355 m_globalObject->put(&m_globalExec, "Date", m_Date, DontEnum);
356 m_globalObject->put(&m_globalExec, "RegExp", m_RegExp, DontEnum);
357 m_globalObject->put(&m_globalExec, "Error", m_Error, DontEnum);
358 // Using Internal for those to have something != 0
359 // (see kjs_window). Maybe DontEnum would be ok too ?
360 m_globalObject->put(&m_globalExec, "EvalError",m_EvalError, Internal);
361 m_globalObject->put(&m_globalExec, "RangeError",m_RangeError, Internal);
362 m_globalObject->put(&m_globalExec, "ReferenceError",m_ReferenceError, Internal);
363 m_globalObject->put(&m_globalExec, "SyntaxError",m_SyntaxError, Internal);
364 m_globalObject->put(&m_globalExec, "TypeError",m_TypeError, Internal);
365 m_globalObject->put(&m_globalExec, "URIError",m_UriError, Internal);
366
367 // Set the constructorPropertyName property of all builtin constructors
368 objProto->put(&m_globalExec, constructorPropertyName, m_Object, DontEnum | DontDelete | ReadOnly);
369 funcProto->put(&m_globalExec, constructorPropertyName, m_Function, DontEnum | DontDelete | ReadOnly);
370 arrayProto->put(&m_globalExec, constructorPropertyName, m_Array, DontEnum | DontDelete | ReadOnly);
371 booleanProto->put(&m_globalExec, constructorPropertyName, m_Boolean, DontEnum | DontDelete | ReadOnly);
372 stringProto->put(&m_globalExec, constructorPropertyName, m_String, DontEnum | DontDelete | ReadOnly);
373 numberProto->put(&m_globalExec, constructorPropertyName, m_Number, DontEnum | DontDelete | ReadOnly);
374 dateProto->put(&m_globalExec, constructorPropertyName, m_Date, DontEnum | DontDelete | ReadOnly);
375 regexpProto->put(&m_globalExec, constructorPropertyName, m_RegExp, DontEnum | DontDelete | ReadOnly);
376 errorProto->put(&m_globalExec, constructorPropertyName, m_Error, DontEnum | DontDelete | ReadOnly);
377 m_EvalErrorPrototype->put(&m_globalExec, constructorPropertyName, m_EvalError, DontEnum | DontDelete | ReadOnly);
378 m_RangeErrorPrototype->put(&m_globalExec, constructorPropertyName, m_RangeError, DontEnum | DontDelete | ReadOnly);
379 m_ReferenceErrorPrototype->put(&m_globalExec, constructorPropertyName, m_ReferenceError, DontEnum | DontDelete | ReadOnly);
380 m_SyntaxErrorPrototype->put(&m_globalExec, constructorPropertyName, m_SyntaxError, DontEnum | DontDelete | ReadOnly);
381 m_TypeErrorPrototype->put(&m_globalExec, constructorPropertyName, m_TypeError, DontEnum | DontDelete | ReadOnly);
382 m_UriErrorPrototype->put(&m_globalExec, constructorPropertyName, m_UriError, DontEnum | DontDelete | ReadOnly);
383
384 // built-in values
385 m_globalObject->put(&m_globalExec, "NaN", jsNaN(), DontEnum|DontDelete);
386 m_globalObject->put(&m_globalExec, "Infinity", jsNumber(Inf), DontEnum|DontDelete);
387 m_globalObject->put(&m_globalExec, "undefined", jsUndefined(), DontEnum|DontDelete);
388
389 // built-in functions
390 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::Eval, 1, "eval"), DontEnum);
391 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::ParseInt, 2, "parseInt"), DontEnum);
392 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::ParseFloat, 1, "parseFloat"), DontEnum);
393 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::IsNaN, 1, "isNaN"), DontEnum);
394 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::IsFinite, 1, "isFinite"), DontEnum);
395 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::Escape, 1, "escape"), DontEnum);
396 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::UnEscape, 1, "unescape"), DontEnum);
397 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::DecodeURI, 1, "decodeURI"), DontEnum);
398 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::DecodeURIComponent, 1, "decodeURIComponent"), DontEnum);
399 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::EncodeURI, 1, "encodeURI"), DontEnum);
400 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::EncodeURIComponent, 1, "encodeURIComponent"), DontEnum);
401#ifndef NDEBUG
402 m_globalObject->putDirectFunction(new GlobalFuncImp(&m_globalExec, funcProto, GlobalFuncImp::KJSPrint, 1, "kjsprint"), DontEnum);
403#endif
404
405 // built-in objects
406 m_globalObject->put(&m_globalExec, "Math", new MathObjectImp(&m_globalExec, objProto), DontEnum);
407}
408
409ExecState* Interpreter::globalExec()
410{
411 return &m_globalExec;
412}
413
414bool Interpreter::checkSyntax(const UString &code)
415{
416 JSLock lock;
417
418 // Parser::parse() returns 0 in a syntax error occurs
419 RefPtr<ProgramNode> progNode = Parser::parse(UString(), 0, code.data(), code.size(), 0, 0, 0);
420 return progNode;
421}
422
423Completion Interpreter::evaluate(const UString& sourceURL, int startingLineNumber, const UString& code, JSValue* thisV)
424{
425 return evaluate(sourceURL, startingLineNumber, code.data(), code.size(), thisV);
426}
427
428Completion Interpreter::evaluate(const UString& sourceURL, int startingLineNumber, const UChar* code, int codeLength, JSValue* thisV)
429{
430 JSLock lock;
431
432 // prevent against infinite recursion
433 if (m_recursion >= 20)
434 return Completion(Throw, Error::create(&m_globalExec, GeneralError, "Recursion too deep"));
435
436 // parse the source code
437 int sid;
438 int errLine;
439 UString errMsg;
440 RefPtr<ProgramNode> progNode = Parser::parse(sourceURL, startingLineNumber, code, codeLength, &sid, &errLine, &errMsg);
441
442 // notify debugger that source has been parsed
443 if (m_debugger) {
444 bool cont = m_debugger->sourceParsed(&m_globalExec, sid, sourceURL, UString(code, codeLength), errLine);
445 if (!cont)
446 return Completion(Break);
447 }
448
449 // no program node means a syntax error occurred
450 if (!progNode)
451 return Completion(Throw, Error::create(&m_globalExec, SyntaxError, errMsg, errLine, sid, &sourceURL));
452
453 m_globalExec.clearException();
454
455 m_recursion++;
456
457 JSObject* globalObj = m_globalObject;
458 JSObject* thisObj = globalObj;
459
460 // "this" must be an object... use same rules as Function.prototype.apply()
461 if (thisV && !thisV->isUndefinedOrNull())
462 thisObj = thisV->toObject(&m_globalExec);
463
464 Completion res;
465 if (m_globalExec.hadException())
466 // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it
467 res = Completion(Throw, m_globalExec.exception());
468 else {
469 // execute the code
470 Context ctx(globalObj, this, thisObj, progNode.get());
471 ExecState newExec(this, &ctx);
472 progNode->processVarDecls(&newExec);
473 res = progNode->execute(&newExec);
474 }
475
476 m_recursion--;
477
478 if (shouldPrintExceptions() && res.complType() == Throw) {
479 JSLock lock;
480 ExecState* exec = globalExec();
481 CString f = sourceURL.UTF8String();
482 CString message = res.value()->toObject(exec)->toString(exec).UTF8String();
483 int line = res.value()->toObject(exec)->get(exec, "line")->toUInt32(exec);
484#if PLATFORM(WIN_OS)
485 printf("%s line %d: %s\n", f.c_str(), line, message.c_str());
486#else
487 printf("[%d] %s line %d: %s\n", getpid(), f.c_str(), line, message.c_str());
488#endif
489 }
490
491 return res;
492}
493
494JSObject *Interpreter::builtinObject() const
495{
496 return m_Object;
497}
498
499JSObject *Interpreter::builtinFunction() const
500{
501 return m_Function;
502}
503
504JSObject *Interpreter::builtinArray() const
505{
506 return m_Array;
507}
508
509JSObject *Interpreter::builtinBoolean() const
510{
511 return m_Boolean;
512}
513
514JSObject *Interpreter::builtinString() const
515{
516 return m_String;
517}
518
519JSObject *Interpreter::builtinNumber() const
520{
521 return m_Number;
522}
523
524JSObject *Interpreter::builtinDate() const
525{
526 return m_Date;
527}
528
529JSObject *Interpreter::builtinRegExp() const
530{
531 return m_RegExp;
532}
533
534JSObject *Interpreter::builtinError() const
535{
536 return m_Error;
537}
538
539JSObject *Interpreter::builtinObjectPrototype() const
540{
541 return m_ObjectPrototype;
542}
543
544JSObject *Interpreter::builtinFunctionPrototype() const
545{
546 return m_FunctionPrototype;
547}
548
549JSObject *Interpreter::builtinArrayPrototype() const
550{
551 return m_ArrayPrototype;
552}
553
554JSObject *Interpreter::builtinBooleanPrototype() const
555{
556 return m_BooleanPrototype;
557}
558
559JSObject *Interpreter::builtinStringPrototype() const
560{
561 return m_StringPrototype;
562}
563
564JSObject *Interpreter::builtinNumberPrototype() const
565{
566 return m_NumberPrototype;
567}
568
569JSObject *Interpreter::builtinDatePrototype() const
570{
571 return m_DatePrototype;
572}
573
574JSObject *Interpreter::builtinRegExpPrototype() const
575{
576 return m_RegExpPrototype;
577}
578
579JSObject *Interpreter::builtinErrorPrototype() const
580{
581 return m_ErrorPrototype;
582}
583
584JSObject *Interpreter::builtinEvalError() const
585{
586 return m_EvalError;
587}
588
589JSObject *Interpreter::builtinRangeError() const
590{
591 return m_RangeError;
592}
593
594JSObject *Interpreter::builtinReferenceError() const
595{
596 return m_ReferenceError;
597}
598
599JSObject *Interpreter::builtinSyntaxError() const
600{
601 return m_SyntaxError;
602}
603
604JSObject *Interpreter::builtinTypeError() const
605{
606 return m_TypeError;
607}
608
609JSObject *Interpreter::builtinURIError() const
610{
611 return m_UriError;
612}
613
614JSObject *Interpreter::builtinEvalErrorPrototype() const
615{
616 return m_EvalErrorPrototype;
617}
618
619JSObject *Interpreter::builtinRangeErrorPrototype() const
620{
621 return m_RangeErrorPrototype;
622}
623
624JSObject *Interpreter::builtinReferenceErrorPrototype() const
625{
626 return m_ReferenceErrorPrototype;
627}
628
629JSObject *Interpreter::builtinSyntaxErrorPrototype() const
630{
631 return m_SyntaxErrorPrototype;
632}
633
634JSObject *Interpreter::builtinTypeErrorPrototype() const
635{
636 return m_TypeErrorPrototype;
637}
638
639JSObject *Interpreter::builtinURIErrorPrototype() const
640{
641 return m_UriErrorPrototype;
642}
643
644bool Interpreter::collect()
645{
646 return Collector::collect();
647}
648
649void Interpreter::mark(bool)
650{
651 if (m_context)
652 m_context->mark();
653 if (m_globalObject && !m_globalObject->marked())
654 m_globalObject->mark();
655 if (m_globalExec.exception() && !m_globalExec.exception()->marked())
656 m_globalExec.exception()->mark();
657}
658
659Interpreter* Interpreter::interpreterWithGlobalObject(JSObject* globalObject)
660{
661 return interpreterMap().get(globalObject);
662}
663
664#ifdef KJS_DEBUG_MEM
665#include "lexer.h"
666void Interpreter::finalCheck()
667{
668 fprintf(stderr,"Interpreter::finalCheck()\n");
669 Collector::collect();
670
671 Node::finalCheck();
672 Collector::finalCheck();
673 Lexer::globalClear();
674 UString::globalClear();
675}
676#endif
677
678static bool printExceptions = false;
679
680bool Interpreter::shouldPrintExceptions()
681{
682 return printExceptions;
683}
684
685void Interpreter::setShouldPrintExceptions(bool print)
686{
687 printExceptions = print;
688}
689
690// bindings are OS X WebKit-only for now
691#if PLATFORM(MAC)
692void *Interpreter::createLanguageInstanceForValue(ExecState *exec, int language, JSObject *value, const Bindings::RootObject *origin, const Bindings::RootObject *current)
693{
694 return Bindings::Instance::createLanguageInstanceForValue (exec, (Bindings::Instance::BindingLanguage)language, value, origin, current);
695}
696#endif
697
698void Interpreter::saveBuiltins (SavedBuiltins& builtins) const
699{
700 if (!builtins._internal)
701 builtins._internal = new SavedBuiltinsInternal;
702
703 builtins._internal->m_Object = m_Object;
704 builtins._internal->m_Function = m_Function;
705 builtins._internal->m_Array = m_Array;
706 builtins._internal->m_Boolean = m_Boolean;
707 builtins._internal->m_String = m_String;
708 builtins._internal->m_Number = m_Number;
709 builtins._internal->m_Date = m_Date;
710 builtins._internal->m_RegExp = m_RegExp;
711 builtins._internal->m_Error = m_Error;
712
713 builtins._internal->m_ObjectPrototype = m_ObjectPrototype;
714 builtins._internal->m_FunctionPrototype = m_FunctionPrototype;
715 builtins._internal->m_ArrayPrototype = m_ArrayPrototype;
716 builtins._internal->m_BooleanPrototype = m_BooleanPrototype;
717 builtins._internal->m_StringPrototype = m_StringPrototype;
718 builtins._internal->m_NumberPrototype = m_NumberPrototype;
719 builtins._internal->m_DatePrototype = m_DatePrototype;
720 builtins._internal->m_RegExpPrototype = m_RegExpPrototype;
721 builtins._internal->m_ErrorPrototype = m_ErrorPrototype;
722
723 builtins._internal->m_EvalError = m_EvalError;
724 builtins._internal->m_RangeError = m_RangeError;
725 builtins._internal->m_ReferenceError = m_ReferenceError;
726 builtins._internal->m_SyntaxError = m_SyntaxError;
727 builtins._internal->m_TypeError = m_TypeError;
728 builtins._internal->m_UriError = m_UriError;
729
730 builtins._internal->m_EvalErrorPrototype = m_EvalErrorPrototype;
731 builtins._internal->m_RangeErrorPrototype = m_RangeErrorPrototype;
732 builtins._internal->m_ReferenceErrorPrototype = m_ReferenceErrorPrototype;
733 builtins._internal->m_SyntaxErrorPrototype = m_SyntaxErrorPrototype;
734 builtins._internal->m_TypeErrorPrototype = m_TypeErrorPrototype;
735 builtins._internal->m_UriErrorPrototype = m_UriErrorPrototype;
736}
737
738void Interpreter::restoreBuiltins (const SavedBuiltins& builtins)
739{
740 if (!builtins._internal)
741 return;
742
743 m_Object = builtins._internal->m_Object;
744 m_Function = builtins._internal->m_Function;
745 m_Array = builtins._internal->m_Array;
746 m_Boolean = builtins._internal->m_Boolean;
747 m_String = builtins._internal->m_String;
748 m_Number = builtins._internal->m_Number;
749 m_Date = builtins._internal->m_Date;
750 m_RegExp = builtins._internal->m_RegExp;
751 m_Error = builtins._internal->m_Error;
752
753 m_ObjectPrototype = builtins._internal->m_ObjectPrototype;
754 m_FunctionPrototype = builtins._internal->m_FunctionPrototype;
755 m_ArrayPrototype = builtins._internal->m_ArrayPrototype;
756 m_BooleanPrototype = builtins._internal->m_BooleanPrototype;
757 m_StringPrototype = builtins._internal->m_StringPrototype;
758 m_NumberPrototype = builtins._internal->m_NumberPrototype;
759 m_DatePrototype = builtins._internal->m_DatePrototype;
760 m_RegExpPrototype = builtins._internal->m_RegExpPrototype;
761 m_ErrorPrototype = builtins._internal->m_ErrorPrototype;
762
763 m_EvalError = builtins._internal->m_EvalError;
764 m_RangeError = builtins._internal->m_RangeError;
765 m_ReferenceError = builtins._internal->m_ReferenceError;
766 m_SyntaxError = builtins._internal->m_SyntaxError;
767 m_TypeError = builtins._internal->m_TypeError;
768 m_UriError = builtins._internal->m_UriError;
769
770 m_EvalErrorPrototype = builtins._internal->m_EvalErrorPrototype;
771 m_RangeErrorPrototype = builtins._internal->m_RangeErrorPrototype;
772 m_ReferenceErrorPrototype = builtins._internal->m_ReferenceErrorPrototype;
773 m_SyntaxErrorPrototype = builtins._internal->m_SyntaxErrorPrototype;
774 m_TypeErrorPrototype = builtins._internal->m_TypeErrorPrototype;
775 m_UriErrorPrototype = builtins._internal->m_UriErrorPrototype;
776}
777
778void Interpreter::startTimeoutCheck()
779{
780 if (!m_timeoutChecker)
781 m_timeoutChecker = new TimeoutChecker;
782
783 m_timeoutChecker->startTimeoutCheck(this);
784}
785
786void Interpreter::stopTimeoutCheck()
787{
788 ASSERT(m_timeoutChecker);
789
790 m_timeoutChecker->stopTimeoutCheck(this);
791}
792
793void Interpreter::pauseTimeoutCheck()
794{
795 ASSERT(m_timeoutChecker);
796
797 m_timeoutChecker->pauseTimeoutCheck(this);
798}
799
800void Interpreter::resumeTimeoutCheck()
801{
802 ASSERT(m_timeoutChecker);
803
804 m_timeoutChecker->resumeTimeoutCheck(this);
805}
806
807bool Interpreter::handleTimeout()
808{
809 m_timedOut = false;
810
811 pauseTimeoutCheck();
812 bool retval = shouldInterruptScript();
813 resumeTimeoutCheck();
814
815 return retval;
816}
817
818
819SavedBuiltins::SavedBuiltins() :
820 _internal(0)
821{
822}
823
824SavedBuiltins::~SavedBuiltins()
825{
826 delete _internal;
827}
828
829}
Note: See TracBrowser for help on using the repository browser.