source: webkit/trunk/JavaScriptCore/kjs/interpreter.h@ 10701

Last change on this file since 10701 was 10563, checked in by mjs, 20 years ago

Reviewed by Geoff.

  • fixed <rdar://problem/4214783> REGRESSION: kjs_fast_malloc crash due to lack of locking on multiple threads (seen selecting volumes in the installer)

Make sure to lock using the InterpreterLock class in all places that need it
(including anything that uses the collector, the parser, the protect count hash table,
and anything that allocates via fast_malloc).

Also added assertions to ensure that the locking rules are followed for the relevant
resources.

  • Makefile.am:
  • bindings/NP_jsobject.cpp: (identifierFromNPIdentifier): (_NPN_Invoke): (_NPN_Evaluate): (_NPN_GetProperty): (_NPN_SetProperty): (_NPN_RemoveProperty): (_NPN_HasProperty): (_NPN_HasMethod): (_NPN_SetException):
  • bindings/jni/jni_jsobject.cpp: (JSObject::call): (JSObject::eval): (JSObject::getMember): (JSObject::setMember): (JSObject::removeMember): (JSObject::getSlot): (JSObject::setSlot): (JSObject::toString): (JSObject::convertJObjectToValue):
  • bindings/objc/WebScriptObject.mm: (-[WebScriptObject callWebScriptMethod:withArguments:]): (-[WebScriptObject evaluateWebScript:]): (-[WebScriptObject setValue:forKey:]): (-[WebScriptObject valueForKey:]): (-[WebScriptObject removeWebScriptKey:]): (-[WebScriptObject stringRepresentation]): (-[WebScriptObject webScriptValueAtIndex:]): (-[WebScriptObject setWebScriptValueAtIndex:value:]): (+[WebScriptObject _convertValueToObjcValue:KJS::originExecutionContext:Bindings::executionContext:Bindings::]):
  • bindings/runtime.cpp: (Instance::createRuntimeObject):
  • bindings/runtime_root.h:
  • bindings/testbindings.cpp: (main):
  • bindings/testbindings.mm: (main):
  • kjs/fast_malloc.cpp: (KJS::kjs_fast_malloc): (KJS::kjs_fast_calloc): (KJS::kjs_fast_free): (KJS::kjs_fast_realloc):
  • kjs/fast_malloc.h:
  • kjs/identifier.h:
  • kjs/internal.cpp: (InterpreterImp::InterpreterImp): (InterpreterImp::clear): (InterpreterImp::mark): (InterpreterImp::checkSyntax): (InterpreterImp::evaluate):
  • kjs/internal.h: (KJS::InterpreterImp::globalObject):
  • kjs/interpreter.cpp: (Interpreter::evaluate):
  • kjs/interpreter.h: (KJS::InterpreterLock::InterpreterLock): (KJS::InterpreterLock::~InterpreterLock):
  • kjs/nodes.h:
  • kjs/protect.h: (KJS::ProtectedValue::ProtectedValue): (KJS::ProtectedValue::~ProtectedValue): (KJS::ProtectedValue::operator=): (KJS::ProtectedObject::ProtectedObject): (KJS::ProtectedObject::~ProtectedObject): (KJS::ProtectedObject::operator=): (KJS::ProtectedReference::ProtectedReference): (KJS::ProtectedReference::~ProtectedReference): (KJS::ProtectedReference::operator=):
  • kjs/protected_object.h:
  • kjs/protected_values.cpp: (KJS::ProtectedValues::getProtectCount): (KJS::ProtectedValues::increaseProtectCount): (KJS::ProtectedValues::decreaseProtectCount):
  • kjs/string_object.cpp: (StringObjectImp::StringObjectImp):
  • kjs/testkjs.cpp: (main):
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.1 KB
Line 
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 1999-2001 Harri Porten ([email protected])
4 * Copyright (C) 2001 Peter Kelly ([email protected])
5 * Copyright (C) 2003 Apple Computer, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#ifndef _KJS_INTERPRETER_H_
25#define _KJS_INTERPRETER_H_
26
27#include "value.h"
28#include "types.h"
29
30namespace KJS {
31
32 class ContextImp;
33 class InterpreterImp;
34 class RuntimeMethodImp;
35 class ScopeChain;
36
37 namespace Bindings {
38 class RootObject;
39 }
40
41 /**
42 * Represents an execution context, as specified by section 10 of the ECMA
43 * spec.
44 *
45 * An execution context contains information about the current state of the
46 * script - the scope for variable lookup, the value of "this", etc. A new
47 * execution context is entered whenever global code is executed (e.g. with
48 * Interpreter::evaluate()), a function is called (see
49 * Object::call()), or the builtin "eval" function is executed.
50 *
51 * Most inheritable functions in the KJS api take a ExecState pointer as
52 * their first parameter. This can be used to obtain a handle to the current
53 * execution context.
54 *
55 * Note: Context objects are wrapper classes/smart pointers for the internal
56 * KJS ContextImp type. When one context variable is assigned to another, it
57 * is still referencing the same internal object.
58 */
59 class Context {
60 public:
61 Context(ContextImp *i) : rep(i) { }
62
63 ContextImp *imp() const { return rep; }
64
65 /**
66 * Returns the scope chain for this execution context. This is used for
67 * variable lookup, with the list being searched from start to end until a
68 * variable is found.
69 *
70 * @return The execution context's scope chain
71 */
72 const ScopeChain &scopeChain() const;
73
74 /**
75 * Returns the variable object for the execution context. This contains a
76 * property for each variable declared in the execution context.
77 *
78 * @return The execution context's variable object
79 */
80 ObjectImp *variableObject() const;
81
82 /**
83 * Returns the "this" value for the execution context. This is the value
84 * returned when a script references the special variable "this". It should
85 * always be an Object, unless application-specific code has passed in a
86 * different type.
87 *
88 * The object that is used as the "this" value depends on the type of
89 * execution context - for global contexts, the global object is used. For
90 * function objewcts, the value is given by the caller (e.g. in the case of
91 * obj.func(), obj would be the "this" value). For code executed by the
92 * built-in "eval" function, the this value is the same as the calling
93 * context.
94 *
95 * @return The execution context's "this" value
96 */
97 ObjectImp *thisValue() const;
98
99 /**
100 * Returns the context from which the current context was invoked. For
101 * global code this will be a null context (i.e. one for which
102 * isNull() returns true). You should check isNull() on the returned
103 * value before calling any of it's methods.
104 *
105 * @return The calling execution context
106 */
107 const Context callingContext() const;
108
109 /**
110 * The line number on which the current statement begins
111 * NOTE: Only for source compatibility, JSC does not support this method.
112 */
113 int curStmtFirstLine() const { return 0; }
114
115 private:
116 ContextImp *rep;
117 };
118
119 class SavedBuiltinsInternal;
120
121 class SavedBuiltins {
122 friend class InterpreterImp;
123 public:
124 SavedBuiltins();
125 ~SavedBuiltins();
126 private:
127 SavedBuiltinsInternal *_internal;
128 };
129
130 /**
131 * Interpreter objects can be used to evaluate ECMAScript code. Each
132 * interpreter has a global object which is used for the purposes of code
133 * evaluation, and also provides access to built-in properties such as
134 * " Object" and "Number".
135 */
136 class Interpreter {
137 public:
138 /**
139 * Creates a new interpreter. The supplied object will be used as the global
140 * object for all scripts executed with this interpreter. During
141 * constuction, all the standard properties such as "Object" and "Number"
142 * will be added to the global object.
143 *
144 * Note: You should not use the same global object for multiple
145 * interpreters.
146 *
147 * This is due do the fact that the built-in properties are set in the
148 * constructor, and if these objects have been modified from another
149 * interpreter (e.g. a script modifying String.prototype), the changes will
150 * be overridden.
151 *
152 * @param global The object to use as the global object for this interpreter
153 */
154 Interpreter(ObjectImp *global);
155 /**
156 * Creates a new interpreter. A global object will be created and
157 * initialized with the standard global properties.
158 */
159 Interpreter();
160 virtual ~Interpreter();
161
162 /**
163 * Returns the object that is used as the global object during all script
164 * execution performed by this interpreter
165 */
166 ObjectImp *globalObject() const;
167
168 void initGlobalObject();
169
170 static void lock();
171 static void unlock();
172 static int lockCount();
173
174 /**
175 * Returns the execution state object which can be used to execute
176 * scripts using this interpreter at a the "global" level, i.e. one
177 * with a execution context that has the global object as the "this"
178 * value, and who's scope chain contains only the global object.
179 *
180 * Note: this pointer remains constant for the life of the interpreter
181 * and should not be manually deleted.
182 *
183 * @return The interpreter global execution state object
184 */
185 ExecState *globalExec();
186
187 /**
188 * Parses the supplied ECMAScript code and checks for syntax errors.
189 *
190 * @param code The code to check
191 * @return true if there were no syntax errors in the code, otherwise false
192 */
193 bool checkSyntax(const UString &code);
194
195 /**
196 * Evaluates the supplied ECMAScript code.
197 *
198 * Since this method returns a Completion, you should check the type of
199 * completion to detect an error or before attempting to access the returned
200 * value. For example, if an error occurs during script execution and is not
201 * caught by the script, the completion type will be Throw.
202 *
203 * If the supplied code is invalid, a SyntaxError will be thrown.
204 *
205 * @param code The code to evaluate
206 * @param thisV The value to pass in as the "this" value for the script
207 * execution. This should either be Null() or an Object.
208 * @return A completion object representing the result of the execution.
209 */
210 Completion evaluate(const UString &sourceURL, int startingLineNumber, const UString &code, ValueImp *thisV = NULL);
211
212 // Overload of evaluate to keep JavaScriptGlue both source and binary compatible.
213 Completion evaluate(const UString &code, ValueImp *thisV = NULL, const UString &sourceFilename = UString());
214
215 /**
216 * @internal
217 *
218 * Returns the implementation object associated with this interpreter.
219 * Only useful for internal KJS operations.
220 */
221 InterpreterImp *imp() const { return rep; }
222
223 /**
224 * Returns the builtin "Object" object. This is the object that was set
225 * as a property of the global object during construction; if the property
226 * is replaced by script code, this method will still return the original
227 * object.
228 *
229 * @return The builtin "Object" object
230 */
231 ObjectImp *builtinObject() const;
232
233 /**
234 * Returns the builtin "Function" object.
235 */
236 ObjectImp *builtinFunction() const;
237
238 /**
239 * Returns the builtin "Array" object.
240 */
241 ObjectImp *builtinArray() const;
242
243 /**
244 * Returns the builtin "Boolean" object.
245 */
246 ObjectImp *builtinBoolean() const;
247
248 /**
249 * Returns the builtin "String" object.
250 */
251 ObjectImp *builtinString() const;
252
253 /**
254 * Returns the builtin "Number" object.
255 */
256 ObjectImp *builtinNumber() const;
257
258 /**
259 * Returns the builtin "Date" object.
260 */
261 ObjectImp *builtinDate() const;
262
263 /**
264 * Returns the builtin "RegExp" object.
265 */
266 ObjectImp *builtinRegExp() const;
267
268 /**
269 * Returns the builtin "Error" object.
270 */
271 ObjectImp *builtinError() const;
272
273 /**
274 * Returns the builtin "Object.prototype" object.
275 */
276 ObjectImp *builtinObjectPrototype() const;
277
278 /**
279 * Returns the builtin "Function.prototype" object.
280 */
281 ObjectImp *builtinFunctionPrototype() const;
282
283 /**
284 * Returns the builtin "Array.prototype" object.
285 */
286 ObjectImp *builtinArrayPrototype() const;
287
288 /**
289 * Returns the builtin "Boolean.prototype" object.
290 */
291 ObjectImp *builtinBooleanPrototype() const;
292
293 /**
294 * Returns the builtin "String.prototype" object.
295 */
296 ObjectImp *builtinStringPrototype() const;
297
298 /**
299 * Returns the builtin "Number.prototype" object.
300 */
301 ObjectImp *builtinNumberPrototype() const;
302
303 /**
304 * Returns the builtin "Date.prototype" object.
305 */
306 ObjectImp *builtinDatePrototype() const;
307
308 /**
309 * Returns the builtin "RegExp.prototype" object.
310 */
311 ObjectImp *builtinRegExpPrototype() const;
312
313 /**
314 * Returns the builtin "Error.prototype" object.
315 */
316 ObjectImp *builtinErrorPrototype() const;
317
318 /**
319 * The initial value of "Error" global property
320 */
321 ObjectImp *builtinEvalError() const;
322 ObjectImp *builtinRangeError() const;
323 ObjectImp *builtinReferenceError() const;
324 ObjectImp *builtinSyntaxError() const;
325 ObjectImp *builtinTypeError() const;
326 ObjectImp *builtinURIError() const;
327
328 ObjectImp *builtinEvalErrorPrototype() const;
329 ObjectImp *builtinRangeErrorPrototype() const;
330 ObjectImp *builtinReferenceErrorPrototype() const;
331 ObjectImp *builtinSyntaxErrorPrototype() const;
332 ObjectImp *builtinTypeErrorPrototype() const;
333 ObjectImp *builtinURIErrorPrototype() const;
334
335 enum CompatMode { NativeMode, IECompat, NetscapeCompat };
336 /**
337 * Call this to enable a compatibility mode with another browser.
338 * (by default konqueror is in "native mode").
339 * Currently, in KJS, this only changes the behavior of Date::getYear()
340 * which returns the full year under IE.
341 */
342 void setCompatMode(CompatMode mode);
343 CompatMode compatMode() const;
344
345 /**
346 * Called by InterpreterImp during the mark phase of the garbage collector
347 * Default implementation does nothing, this exist for classes that reimplement Interpreter.
348 */
349 virtual void mark() {}
350
351 /**
352 * Provides a way to distinguish derived classes.
353 * Only useful if you reimplement Interpreter and if different kind of
354 * interpreters are created in the same process.
355 * The base class returns 0, the ECMA-bindings interpreter returns 1.
356 */
357 virtual int rtti() { return 0; }
358
359#ifdef KJS_DEBUG_MEM
360 /**
361 * @internal
362 */
363 static void finalCheck();
364#endif
365
366#if APPLE_CHANGES
367 static bool shouldPrintExceptions();
368 static void setShouldPrintExceptions(bool);
369#endif
370
371 void saveBuiltins (SavedBuiltins &) const;
372 void restoreBuiltins (const SavedBuiltins &);
373
374#if APPLE_CHANGES
375 /**
376 * Determine if the value is a global object (for any interpreter). This may
377 * be difficult to determine for multiple uses of JSC in a process that are
378 * logically independent of each other. In the case of WebCore, this method
379 * is used to determine if an object is the Window object so we can perform
380 * security checks.
381 */
382 virtual bool isGlobalObject(ValueImp *v) { return false; }
383
384 /**
385 * Find the interpreter for a particular global object. This should really
386 * be a static method, but we can't do that is C++. Again, as with isGlobalObject()
387 * implementation really need to know about all instances of Interpreter
388 * created in an application to correctly implement this method. The only
389 * override of this method is currently in WebCore.
390 */
391 virtual Interpreter *interpreterForGlobalObject (const ValueImp *imp) { return 0; }
392
393 /**
394 * Determine if the it is 'safe' to execute code in the target interpreter from an
395 * object that originated in this interpreter. This check is used to enforce WebCore
396 * cross frame security rules. In particular, attempts to access 'bound' objects are
397 * not allowed unless isSafeScript returns true.
398 */
399 virtual bool isSafeScript (const Interpreter *target) { return true; }
400
401 virtual void *createLanguageInstanceForValue (ExecState *exec, int language, ObjectImp *value, const Bindings::RootObject *origin, const Bindings::RootObject *current);
402#endif
403
404 // This is a workaround to avoid accessing the global variables for these identifiers in
405 // important property lookup functions, to avoid taking PIC branches in Mach-O binaries
406 const Identifier& argumentsIdentifier() { return *m_argumentsPropertyName; }
407 const Identifier& specialPrototypeIdentifier() { return *m_specialPrototypePropertyName; }
408
409 private:
410 InterpreterImp *rep;
411
412 const Identifier *m_argumentsPropertyName;
413 const Identifier *m_specialPrototypePropertyName;
414
415 /**
416 * This constructor is not implemented, in order to prevent
417 * copy-construction of Interpreter objects. You should always pass around
418 * pointers to an interpreter instance instead.
419 */
420 Interpreter(const Interpreter&);
421
422 /**
423 * This constructor is not implemented, in order to prevent assignment of
424 * Interpreter objects. You should always pass around pointers to an
425 * interpreter instance instead.
426 */
427 Interpreter operator=(const Interpreter&);
428
429 protected:
430 virtual void virtual_hook( int id, void* data );
431 };
432
433 /**
434 * Represents the current state of script execution. This object allows you
435 * obtain a handle the interpreter that is currently executing the script,
436 * and also the current execution state context.
437 */
438 class ExecState {
439 friend class InterpreterImp;
440 friend class FunctionImp;
441#if APPLE_CHANGES
442 friend class RuntimeMethodImp;
443#endif
444
445 friend class GlobalFuncImp;
446 public:
447 /**
448 * Returns the interpreter associated with this execution state
449 *
450 * @return The interpreter executing the script
451 */
452 Interpreter *dynamicInterpreter() const { return _interpreter; }
453
454 // for compatibility
455 Interpreter *interpreter() const { return dynamicInterpreter(); }
456
457 /**
458 * Returns the interpreter associated with the current scope's
459 * global object
460 *
461 * @return The interpreter currently in scope
462 */
463 Interpreter *lexicalInterpreter() const;
464
465 /**
466 * Returns the execution context associated with this execution state
467 *
468 * @return The current execution state context
469 */
470 Context context() const { return _context; }
471
472 void setException(ValueImp *e) { _exception = e; }
473 void clearException() { _exception = NULL; }
474 ValueImp *exception() const { return _exception; }
475 bool hadException() const { return _exception; }
476
477 private:
478 ExecState(Interpreter *interp, ContextImp *con)
479 : _interpreter(interp), _context(con), _exception(NULL) { }
480 Interpreter *_interpreter;
481 ContextImp *_context;
482 ValueImp *_exception;
483 };
484
485 class InterpreterLock
486 {
487 public:
488 InterpreterLock() { Interpreter::lock(); }
489 ~InterpreterLock() { Interpreter::unlock(); }
490 private:
491 InterpreterLock(const InterpreterLock &);
492 InterpreterLock &operator =(const InterpreterLock &);
493 };
494
495} // namespace
496
497#endif // _KJS_INTERPRETER_H_
Note: See TracBrowser for help on using the repository browser.