source: webkit/trunk/JavaScriptCore/kjs/internal.cpp@ 10586

Last change on this file since 10586 was 10586, checked in by ggaren, 20 years ago
  • Oops. The 4263434 change was only appropriate on the branch. Rolling out.

Reviewed by eric.

  • kjs/internal.cpp: (KJS::InterpreterImp::mark):
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 27.5 KB
Line 
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 1999-2002 Harri Porten ([email protected])
4 * Copyright (C) 2001 Peter Kelly ([email protected])
5 * Copyright (C) 2004 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#include <stdio.h>
25#include <math.h>
26#include <assert.h>
27
28#include "array_object.h"
29#include "bool_object.h"
30#include "collector.h"
31#include "context.h"
32#include "date_object.h"
33#include "debugger.h"
34#include "error_object.h"
35#include "function_object.h"
36#include "internal.h"
37#include "interpreter_map.h"
38#include "lexer.h"
39#include "math_object.h"
40#include "nodes.h"
41#include "number_object.h"
42#include "object.h"
43#include "object_object.h"
44#include "operations.h"
45#include "regexp_object.h"
46#include "string_object.h"
47
48#if WIN32
49#include <float.h>
50#define copysign(a, b) _copysign(a, b)
51#endif
52
53extern int kjsyyparse();
54
55using namespace KXMLCore;
56
57namespace KJS {
58
59#if !APPLE_CHANGES
60
61#ifdef WORDS_BIGENDIAN
62 const unsigned char NaN_Bytes[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 };
63 const unsigned char Inf_Bytes[] = { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 };
64#elif defined(arm)
65 const unsigned char NaN_Bytes[] = { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 };
66 const unsigned char Inf_Bytes[] = { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 };
67#else
68 const unsigned char NaN_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f };
69 const unsigned char Inf_Bytes[] = { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f };
70#endif
71
72 const double NaN = *(const double*) NaN_Bytes;
73 const double Inf = *(const double*) Inf_Bytes;
74
75#endif // APPLE_CHANGES
76
77#if !KJS_MULTIPLE_THREADS
78
79static inline void initializeInterpreterLock() { }
80static inline void lockInterpreter() { }
81static inline void unlockInterpreter() { }
82
83const int interpreterLockCount = 1;
84
85#else
86
87static pthread_once_t interpreterLockOnce = PTHREAD_ONCE_INIT;
88static pthread_mutex_t interpreterLock;
89static int interpreterLockCount = 0;
90
91static void initializeInterpreterLock()
92{
93 pthread_mutexattr_t attr;
94
95 pthread_mutexattr_init(&attr);
96 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
97
98 pthread_mutex_init(&interpreterLock, &attr);
99}
100
101static inline void lockInterpreter()
102{
103 pthread_once(&interpreterLockOnce, initializeInterpreterLock);
104 pthread_mutex_lock(&interpreterLock);
105 interpreterLockCount++;
106 Collector::registerThread();
107}
108
109static inline void unlockInterpreter()
110{
111 interpreterLockCount--;
112 pthread_mutex_unlock(&interpreterLock);
113}
114
115#endif
116
117// ------------------------------ UndefinedImp ---------------------------------
118
119ValueImp *UndefinedImp::toPrimitive(ExecState */*exec*/, Type) const
120{
121 return const_cast<UndefinedImp *>(this);
122}
123
124bool UndefinedImp::toBoolean(ExecState */*exec*/) const
125{
126 return false;
127}
128
129double UndefinedImp::toNumber(ExecState */*exec*/) const
130{
131 return NaN;
132}
133
134UString UndefinedImp::toString(ExecState */*exec*/) const
135{
136 return "undefined";
137}
138
139ObjectImp *UndefinedImp::toObject(ExecState *exec) const
140{
141 return throwError(exec, TypeError, "Undefined value");
142}
143
144// ------------------------------ NullImp --------------------------------------
145
146ValueImp *NullImp::toPrimitive(ExecState */*exec*/, Type) const
147{
148 return const_cast<NullImp *>(this);
149}
150
151bool NullImp::toBoolean(ExecState */*exec*/) const
152{
153 return false;
154}
155
156double NullImp::toNumber(ExecState */*exec*/) const
157{
158 return 0.0;
159}
160
161UString NullImp::toString(ExecState */*exec*/) const
162{
163 return "null";
164}
165
166ObjectImp *NullImp::toObject(ExecState *exec) const
167{
168 return throwError(exec, TypeError, "Null value");
169}
170
171// ------------------------------ BooleanImp -----------------------------------
172
173ValueImp *BooleanImp::toPrimitive(ExecState */*exec*/, Type) const
174{
175 return const_cast<BooleanImp *>(this);
176}
177
178bool BooleanImp::toBoolean(ExecState */*exec*/) const
179{
180 return val;
181}
182
183double BooleanImp::toNumber(ExecState */*exec*/) const
184{
185 return val ? 1.0 : 0.0;
186}
187
188UString BooleanImp::toString(ExecState */*exec*/) const
189{
190 return val ? "true" : "false";
191}
192
193ObjectImp *BooleanImp::toObject(ExecState *exec) const
194{
195 List args;
196 args.append(const_cast<BooleanImp*>(this));
197 return static_cast<ObjectImp *>(exec->lexicalInterpreter()->builtinBoolean()->construct(exec,args));
198}
199
200// ------------------------------ StringImp ------------------------------------
201
202ValueImp *StringImp::toPrimitive(ExecState */*exec*/, Type) const
203{
204 return const_cast<StringImp *>(this);
205}
206
207bool StringImp::toBoolean(ExecState */*exec*/) const
208{
209 return (val.size() > 0);
210}
211
212double StringImp::toNumber(ExecState */*exec*/) const
213{
214 return val.toDouble();
215}
216
217UString StringImp::toString(ExecState */*exec*/) const
218{
219 return val;
220}
221
222ObjectImp *StringImp::toObject(ExecState *exec) const
223{
224 List args;
225 args.append(const_cast<StringImp*>(this));
226 return static_cast<ObjectImp *>(exec->lexicalInterpreter()->builtinString()->construct(exec, args));
227}
228
229// ------------------------------ NumberImp ------------------------------------
230
231ValueImp *NumberImp::toPrimitive(ExecState *, Type) const
232{
233 return const_cast<NumberImp *>(this);
234}
235
236bool NumberImp::toBoolean(ExecState *) const
237{
238 return !((val == 0) /* || (iVal() == N0) */ || isNaN(val));
239}
240
241double NumberImp::toNumber(ExecState *) const
242{
243 return val;
244}
245
246UString NumberImp::toString(ExecState *) const
247{
248 if (val == 0.0) // +0.0 or -0.0
249 return "0";
250 return UString::from(val);
251}
252
253ObjectImp *NumberImp::toObject(ExecState *exec) const
254{
255 List args;
256 args.append(const_cast<NumberImp*>(this));
257 return static_cast<ObjectImp *>(exec->lexicalInterpreter()->builtinNumber()->construct(exec,args));
258}
259
260bool NumberImp::getUInt32(uint32_t& uint32) const
261{
262 uint32 = (uint32_t)val;
263 return (double)uint32 == val;
264}
265
266// ------------------------------ LabelStack -----------------------------------
267
268bool LabelStack::push(const Identifier &id)
269{
270 if (contains(id))
271 return false;
272
273 StackElem *newtos = new StackElem;
274 newtos->id = id;
275 newtos->prev = tos;
276 tos = newtos;
277 return true;
278}
279
280bool LabelStack::contains(const Identifier &id) const
281{
282 if (id.isEmpty())
283 return true;
284
285 for (StackElem *curr = tos; curr; curr = curr->prev)
286 if (curr->id == id)
287 return true;
288
289 return false;
290}
291
292// ------------------------------ ContextImp -----------------------------------
293
294// ECMA 10.2
295ContextImp::ContextImp(ObjectImp *glob, InterpreterImp *interpreter, ObjectImp *thisV, CodeType type,
296 ContextImp *callingCon, FunctionImp *func, const List *args)
297 : _interpreter(interpreter), _function(func), _arguments(args)
298{
299 m_codeType = type;
300 _callingContext = callingCon;
301
302 // create and initialize activation object (ECMA 10.1.6)
303 if (type == FunctionCode || type == AnonymousCode ) {
304 activation = new ActivationImp(func, *args);
305 variable = activation;
306 } else {
307 activation = NULL;
308 variable = glob;
309 }
310
311 // ECMA 10.2
312 switch(type) {
313 case EvalCode:
314 if (_callingContext) {
315 scope = _callingContext->scopeChain();
316 variable = _callingContext->variableObject();
317 thisVal = _callingContext->thisValue();
318 break;
319 } // else same as GlobalCode
320 case GlobalCode:
321 scope.clear();
322 scope.push(glob);
323 thisVal = static_cast<ObjectImp*>(glob);
324 break;
325 case FunctionCode:
326 case AnonymousCode:
327 if (type == FunctionCode) {
328 scope = func->scope();
329 scope.push(activation);
330 } else {
331 scope.clear();
332 scope.push(glob);
333 scope.push(activation);
334 }
335 variable = activation; // TODO: DontDelete ? (ECMA 10.2.3)
336 thisVal = thisV;
337 break;
338 }
339
340 _interpreter->setContext(this);
341}
342
343ContextImp::~ContextImp()
344{
345 _interpreter->setContext(_callingContext);
346}
347
348void ContextImp::mark()
349{
350 for (ContextImp *context = this; context; context = context->_callingContext) {
351 context->scope.mark();
352 }
353}
354
355// ------------------------------ Parser ---------------------------------------
356
357static SharedPtr<ProgramNode> *progNode;
358int Parser::sid = 0;
359
360const int initialCapacity = 64;
361const int growthFactor = 2;
362
363static int numNewNodes;
364static int newNodesCapacity;
365static Node **newNodes;
366
367void Parser::saveNewNode(Node *node)
368{
369 if (numNewNodes == newNodesCapacity) {
370 newNodesCapacity = (newNodesCapacity == 0) ? initialCapacity : newNodesCapacity * growthFactor;
371 newNodes = (Node **)realloc(newNodes, sizeof(Node *) * newNodesCapacity);
372 }
373
374 newNodes[numNewNodes++] = node;
375}
376
377static void clearNewNodes()
378{
379 for (int i = 0; i < numNewNodes; i++) {
380 if (newNodes[i]->refcount() == 0)
381 delete newNodes[i];
382 }
383 delete newNodes;
384 newNodes = 0;
385 numNewNodes = 0;
386 newNodesCapacity = 0;
387}
388
389SharedPtr<ProgramNode> Parser::parse(const UString &sourceURL, int startingLineNumber,
390 const UChar *code, unsigned int length, int *sourceId,
391 int *errLine, UString *errMsg)
392{
393 if (errLine)
394 *errLine = -1;
395 if (errMsg)
396 *errMsg = 0;
397 if (!progNode)
398 progNode = new SharedPtr<ProgramNode>;
399
400 Lexer::curr()->setCode(sourceURL, startingLineNumber, code, length);
401 *progNode = 0;
402 sid++;
403 if (sourceId)
404 *sourceId = sid;
405 // Enable this (and the #define YYDEBUG in grammar.y) to debug a parse error
406 //extern int kjsyydebug;
407 //kjsyydebug=1;
408 int parseError = kjsyyparse();
409 bool lexError = Lexer::curr()->sawError();
410 Lexer::curr()->doneParsing();
411 SharedPtr<ProgramNode> prog = *progNode;
412 *progNode = 0;
413
414 clearNewNodes();
415
416 if (parseError || lexError) {
417 int eline = Lexer::curr()->lineNo();
418 if (errLine)
419 *errLine = eline;
420 if (errMsg)
421 *errMsg = "Parse error";
422 return SharedPtr<ProgramNode>();
423 }
424
425 return prog;
426}
427
428void Parser::accept(ProgramNode *prog)
429{
430 *progNode = prog;
431}
432
433// ------------------------------ InterpreterImp -------------------------------
434
435InterpreterImp* InterpreterImp::s_hook = 0L;
436
437void InterpreterImp::globalInit()
438{
439 ConstantValues::init();
440}
441
442void InterpreterImp::globalClear()
443{
444 ConstantValues::clear();
445}
446
447InterpreterImp::InterpreterImp(Interpreter *interp, ObjectImp *glob)
448 : globExec(interp, 0)
449 , _context(0)
450{
451 // add this interpreter to the global chain
452 // as a root set for garbage collection
453 InterpreterLock lock;
454
455 m_interpreter = interp;
456 if (s_hook) {
457 prev = s_hook;
458 next = s_hook->next;
459 s_hook->next->prev = this;
460 s_hook->next = this;
461 } else {
462 // This is the first interpreter
463 s_hook = next = prev = this;
464 globalInit();
465 }
466
467 InterpreterMap::setInterpreterForGlobalObject(this, glob);
468
469 global = glob;
470 dbg = 0;
471 m_compatMode = Interpreter::NativeMode;
472
473 // initialize properties of the global object
474 initGlobalObject();
475
476 recursion = 0;
477}
478
479void InterpreterImp::lock()
480{
481 lockInterpreter();
482}
483
484int InterpreterImp::lockCount()
485{
486 return interpreterLockCount;
487}
488
489void InterpreterImp::unlock()
490{
491 unlockInterpreter();
492}
493
494 void InterpreterImp::initGlobalObject()
495{
496 Identifier::init();
497
498 // Contructor prototype objects (Object.prototype, Array.prototype etc)
499
500 FunctionPrototypeImp *funcProto = new FunctionPrototypeImp(&globExec);
501 b_FunctionPrototype = funcProto;
502 ObjectPrototypeImp *objProto = new ObjectPrototypeImp(&globExec, funcProto);
503 b_ObjectPrototype = objProto;
504 funcProto->setPrototype(b_ObjectPrototype);
505
506 ArrayPrototypeImp *arrayProto = new ArrayPrototypeImp(&globExec, objProto);
507 b_ArrayPrototype = arrayProto;
508 StringPrototypeImp *stringProto = new StringPrototypeImp(&globExec, objProto);
509 b_StringPrototype = stringProto;
510 BooleanPrototypeImp *booleanProto = new BooleanPrototypeImp(&globExec, objProto, funcProto);
511 b_BooleanPrototype = booleanProto;
512 NumberPrototypeImp *numberProto = new NumberPrototypeImp(&globExec, objProto, funcProto);
513 b_NumberPrototype = numberProto;
514 DatePrototypeImp *dateProto = new DatePrototypeImp(&globExec, objProto);
515 b_DatePrototype = dateProto;
516 RegExpPrototypeImp *regexpProto = new RegExpPrototypeImp(&globExec, objProto, funcProto);
517 b_RegExpPrototype = regexpProto;
518 ErrorPrototypeImp *errorProto = new ErrorPrototypeImp(&globExec, objProto, funcProto);
519 b_ErrorPrototype = errorProto;
520
521 static_cast<ObjectImp*>(global)->setPrototype(b_ObjectPrototype);
522
523 // Constructors (Object, Array, etc.)
524 b_Object = new ObjectObjectImp(&globExec, objProto, funcProto);
525 b_Function = new FunctionObjectImp(&globExec, funcProto);
526 b_Array = new ArrayObjectImp(&globExec, funcProto, arrayProto);
527 b_String = new StringObjectImp(&globExec, funcProto, stringProto);
528 b_Boolean = new BooleanObjectImp(&globExec, funcProto, booleanProto);
529 b_Number = new NumberObjectImp(&globExec, funcProto, numberProto);
530 b_Date = new DateObjectImp(&globExec, funcProto, dateProto);
531 b_RegExp = new RegExpObjectImp(&globExec, funcProto, regexpProto);
532 b_Error = new ErrorObjectImp(&globExec, funcProto, errorProto);
533
534 // Error object prototypes
535 b_evalErrorPrototype = new NativeErrorPrototypeImp(&globExec, errorProto, EvalError, "EvalError", "EvalError");
536 b_rangeErrorPrototype = new NativeErrorPrototypeImp(&globExec, errorProto, RangeError, "RangeError", "RangeError");
537 b_referenceErrorPrototype = new NativeErrorPrototypeImp(&globExec, errorProto, ReferenceError, "ReferenceError", "ReferenceError");
538 b_syntaxErrorPrototype = new NativeErrorPrototypeImp(&globExec, errorProto, SyntaxError, "SyntaxError", "SyntaxError");
539 b_typeErrorPrototype = new NativeErrorPrototypeImp(&globExec, errorProto, TypeError, "TypeError", "TypeError");
540 b_uriErrorPrototype = new NativeErrorPrototypeImp(&globExec, errorProto, URIError, "URIError", "URIError");
541
542 // Error objects
543 b_evalError = new NativeErrorImp(&globExec, funcProto, b_evalErrorPrototype);
544 b_rangeError = new NativeErrorImp(&globExec, funcProto, b_rangeErrorPrototype);
545 b_referenceError = new NativeErrorImp(&globExec, funcProto, b_referenceErrorPrototype);
546 b_syntaxError = new NativeErrorImp(&globExec, funcProto, b_syntaxErrorPrototype);
547 b_typeError = new NativeErrorImp(&globExec, funcProto, b_typeErrorPrototype);
548 b_uriError = new NativeErrorImp(&globExec, funcProto, b_uriErrorPrototype);
549
550 // ECMA 15.3.4.1
551 funcProto->put(&globExec, "constructor", b_Function, DontEnum);
552
553 global->put(&globExec, "Object", b_Object, DontEnum);
554 global->put(&globExec, "Function", b_Function, DontEnum);
555 global->put(&globExec, "Array", b_Array, DontEnum);
556 global->put(&globExec, "Boolean", b_Boolean, DontEnum);
557 global->put(&globExec, "String", b_String, DontEnum);
558 global->put(&globExec, "Number", b_Number, DontEnum);
559 global->put(&globExec, "Date", b_Date, DontEnum);
560 global->put(&globExec, "RegExp", b_RegExp, DontEnum);
561 global->put(&globExec, "Error", b_Error, DontEnum);
562 // Using Internal for those to have something != 0
563 // (see kjs_window). Maybe DontEnum would be ok too ?
564 global->put(&globExec, "EvalError",b_evalError, Internal);
565 global->put(&globExec, "RangeError",b_rangeError, Internal);
566 global->put(&globExec, "ReferenceError",b_referenceError, Internal);
567 global->put(&globExec, "SyntaxError",b_syntaxError, Internal);
568 global->put(&globExec, "TypeError",b_typeError, Internal);
569 global->put(&globExec, "URIError",b_uriError, Internal);
570
571 // Set the "constructor" property of all builtin constructors
572 objProto->put(&globExec, "constructor", b_Object, DontEnum | DontDelete | ReadOnly);
573 funcProto->put(&globExec, "constructor", b_Function, DontEnum | DontDelete | ReadOnly);
574 arrayProto->put(&globExec, "constructor", b_Array, DontEnum | DontDelete | ReadOnly);
575 booleanProto->put(&globExec, "constructor", b_Boolean, DontEnum | DontDelete | ReadOnly);
576 stringProto->put(&globExec, "constructor", b_String, DontEnum | DontDelete | ReadOnly);
577 numberProto->put(&globExec, "constructor", b_Number, DontEnum | DontDelete | ReadOnly);
578 dateProto->put(&globExec, "constructor", b_Date, DontEnum | DontDelete | ReadOnly);
579 regexpProto->put(&globExec, "constructor", b_RegExp, DontEnum | DontDelete | ReadOnly);
580 errorProto->put(&globExec, "constructor", b_Error, DontEnum | DontDelete | ReadOnly);
581 b_evalErrorPrototype->put(&globExec, "constructor", b_evalError, DontEnum | DontDelete | ReadOnly);
582 b_rangeErrorPrototype->put(&globExec, "constructor", b_rangeError, DontEnum | DontDelete | ReadOnly);
583 b_referenceErrorPrototype->put(&globExec, "constructor", b_referenceError, DontEnum | DontDelete | ReadOnly);
584 b_syntaxErrorPrototype->put(&globExec, "constructor", b_syntaxError, DontEnum | DontDelete | ReadOnly);
585 b_typeErrorPrototype->put(&globExec, "constructor", b_typeError, DontEnum | DontDelete | ReadOnly);
586 b_uriErrorPrototype->put(&globExec, "constructor", b_uriError, DontEnum | DontDelete | ReadOnly);
587
588 // built-in values
589 global->put(&globExec, "NaN", jsNaN(), DontEnum|DontDelete);
590 global->put(&globExec, "Infinity", Number(Inf), DontEnum|DontDelete);
591 global->put(&globExec, "undefined", Undefined(), DontEnum|DontDelete);
592
593 // built-in functions
594 global->put(&globExec, "eval", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::Eval, 1), DontEnum);
595 global->put(&globExec, "parseInt", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::ParseInt, 2), DontEnum);
596 global->put(&globExec, "parseFloat", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::ParseFloat, 1), DontEnum);
597 global->put(&globExec, "isNaN", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::IsNaN, 1), DontEnum);
598 global->put(&globExec, "isFinite", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::IsFinite, 1), DontEnum);
599 global->put(&globExec, "escape", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::Escape, 1), DontEnum);
600 global->put(&globExec, "unescape", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::UnEscape, 1), DontEnum);
601 global->put(&globExec, "decodeURI", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::DecodeURI, 1), DontEnum);
602 global->put(&globExec, "decodeURIComponent", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::DecodeURIComponent, 1), DontEnum);
603 global->put(&globExec, "encodeURI", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::EncodeURI, 1), DontEnum);
604 global->put(&globExec, "encodeURIComponent", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::EncodeURIComponent, 1), DontEnum);
605#ifndef NDEBUG
606 global->put(&globExec, "kjsprint", new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::KJSPrint, 1), DontEnum);
607#endif
608
609 // built-in objects
610 global->put(&globExec, "Math", new MathObjectImp(&globExec, objProto), DontEnum);
611}
612
613InterpreterImp::~InterpreterImp()
614{
615 if (dbg)
616 dbg->detach(m_interpreter);
617 clear();
618}
619
620void InterpreterImp::clear()
621{
622 //fprintf(stderr,"InterpreterImp::clear\n");
623 // remove from global chain (see init())
624 InterpreterLock lock;
625
626 next->prev = prev;
627 prev->next = next;
628 s_hook = next;
629 if (s_hook == this)
630 {
631 // This was the last interpreter
632 s_hook = 0L;
633 globalClear();
634 }
635 InterpreterMap::removeInterpreterForGlobalObject(global);
636}
637
638void InterpreterImp::mark()
639{
640 ConstantValues::mark();
641 if (m_interpreter)
642 m_interpreter->mark();
643 if (_context)
644 _context->mark();
645 if (global)
646 global->mark();
647 if (globExec._exception)
648 globExec._exception->mark();
649}
650
651bool InterpreterImp::checkSyntax(const UString &code)
652{
653 InterpreterLock lock;
654
655 // Parser::parse() returns 0 in a syntax error occurs, so we just check for that
656 SharedPtr<ProgramNode> progNode = Parser::parse(UString(), 0, code.data(),code.size(),0,0,0);
657 return progNode;
658}
659
660Completion InterpreterImp::evaluate(const UString &code, ValueImp *thisV, const UString &sourceURL, int startingLineNumber)
661{
662 InterpreterLock lock;
663
664 // prevent against infinite recursion
665 if (recursion >= 20) {
666#if APPLE_CHANGES
667 Completion result = Completion(Throw, Error::create(&globExec, GeneralError, "Recursion too deep"));
668 return result;
669#else
670 return Completion(Throw,Error::create(&globExec, GeneralError, "Recursion too deep"));
671#endif
672 }
673
674 // parse the source code
675 int sid;
676 int errLine;
677 UString errMsg;
678 SharedPtr<ProgramNode> progNode = Parser::parse(sourceURL, startingLineNumber, code.data(),code.size(),&sid,&errLine,&errMsg);
679
680 // notify debugger that source has been parsed
681 if (dbg) {
682 bool cont = dbg->sourceParsed(&globExec, sid, sourceURL, code, errLine);
683 if (!cont)
684 return Completion(Break);
685 }
686
687 // no program node means a syntax error occurred
688 if (!progNode) {
689 ObjectImp *err = Error::create(&globExec, SyntaxError, errMsg, errLine, sid, &sourceURL);
690 return Completion(Throw,err);
691 }
692
693 globExec.clearException();
694
695 recursion++;
696
697 ObjectImp *globalObj = globalObject();
698 ObjectImp *thisObj = globalObject();
699
700 if (thisV) {
701 // "this" must be an object... use same rules as Function.prototype.apply()
702 if (thisV->isUndefinedOrNull())
703 thisObj = globalObject();
704 else {
705 thisObj = thisV->toObject(&globExec);
706 }
707 }
708
709 Completion res;
710 if (globExec.hadException()) {
711 // the thisArg->toObject() conversion above might have thrown an exception - if so,
712 // propagate it back
713 res = Completion(Throw, globExec.exception());
714 }
715 else {
716 // execute the code
717 ContextImp ctx(globalObj, this, thisObj);
718 ExecState newExec(m_interpreter, &ctx);
719 progNode->processVarDecls(&newExec);
720 res = progNode->execute(&newExec);
721 }
722
723 recursion--;
724
725 return res;
726}
727
728void InterpreterImp::saveBuiltins (SavedBuiltins &builtins) const
729{
730 if (!builtins._internal) {
731 builtins._internal = new SavedBuiltinsInternal;
732 }
733
734 builtins._internal->b_Object = b_Object;
735 builtins._internal->b_Function = b_Function;
736 builtins._internal->b_Array = b_Array;
737 builtins._internal->b_Boolean = b_Boolean;
738 builtins._internal->b_String = b_String;
739 builtins._internal->b_Number = b_Number;
740 builtins._internal->b_Date = b_Date;
741 builtins._internal->b_RegExp = b_RegExp;
742 builtins._internal->b_Error = b_Error;
743
744 builtins._internal->b_ObjectPrototype = b_ObjectPrototype;
745 builtins._internal->b_FunctionPrototype = b_FunctionPrototype;
746 builtins._internal->b_ArrayPrototype = b_ArrayPrototype;
747 builtins._internal->b_BooleanPrototype = b_BooleanPrototype;
748 builtins._internal->b_StringPrototype = b_StringPrototype;
749 builtins._internal->b_NumberPrototype = b_NumberPrototype;
750 builtins._internal->b_DatePrototype = b_DatePrototype;
751 builtins._internal->b_RegExpPrototype = b_RegExpPrototype;
752 builtins._internal->b_ErrorPrototype = b_ErrorPrototype;
753
754 builtins._internal->b_evalError = b_evalError;
755 builtins._internal->b_rangeError = b_rangeError;
756 builtins._internal->b_referenceError = b_referenceError;
757 builtins._internal->b_syntaxError = b_syntaxError;
758 builtins._internal->b_typeError = b_typeError;
759 builtins._internal->b_uriError = b_uriError;
760
761 builtins._internal->b_evalErrorPrototype = b_evalErrorPrototype;
762 builtins._internal->b_rangeErrorPrototype = b_rangeErrorPrototype;
763 builtins._internal->b_referenceErrorPrototype = b_referenceErrorPrototype;
764 builtins._internal->b_syntaxErrorPrototype = b_syntaxErrorPrototype;
765 builtins._internal->b_typeErrorPrototype = b_typeErrorPrototype;
766 builtins._internal->b_uriErrorPrototype = b_uriErrorPrototype;
767}
768
769void InterpreterImp::restoreBuiltins (const SavedBuiltins &builtins)
770{
771 if (!builtins._internal) {
772 return;
773 }
774
775 b_Object = builtins._internal->b_Object;
776 b_Function = builtins._internal->b_Function;
777 b_Array = builtins._internal->b_Array;
778 b_Boolean = builtins._internal->b_Boolean;
779 b_String = builtins._internal->b_String;
780 b_Number = builtins._internal->b_Number;
781 b_Date = builtins._internal->b_Date;
782 b_RegExp = builtins._internal->b_RegExp;
783 b_Error = builtins._internal->b_Error;
784
785 b_ObjectPrototype = builtins._internal->b_ObjectPrototype;
786 b_FunctionPrototype = builtins._internal->b_FunctionPrototype;
787 b_ArrayPrototype = builtins._internal->b_ArrayPrototype;
788 b_BooleanPrototype = builtins._internal->b_BooleanPrototype;
789 b_StringPrototype = builtins._internal->b_StringPrototype;
790 b_NumberPrototype = builtins._internal->b_NumberPrototype;
791 b_DatePrototype = builtins._internal->b_DatePrototype;
792 b_RegExpPrototype = builtins._internal->b_RegExpPrototype;
793 b_ErrorPrototype = builtins._internal->b_ErrorPrototype;
794
795 b_evalError = builtins._internal->b_evalError;
796 b_rangeError = builtins._internal->b_rangeError;
797 b_referenceError = builtins._internal->b_referenceError;
798 b_syntaxError = builtins._internal->b_syntaxError;
799 b_typeError = builtins._internal->b_typeError;
800 b_uriError = builtins._internal->b_uriError;
801
802 b_evalErrorPrototype = builtins._internal->b_evalErrorPrototype;
803 b_rangeErrorPrototype = builtins._internal->b_rangeErrorPrototype;
804 b_referenceErrorPrototype = builtins._internal->b_referenceErrorPrototype;
805 b_syntaxErrorPrototype = builtins._internal->b_syntaxErrorPrototype;
806 b_typeErrorPrototype = builtins._internal->b_typeErrorPrototype;
807 b_uriErrorPrototype = builtins._internal->b_uriErrorPrototype;
808}
809
810InterpreterImp *InterpreterImp::interpreterWithGlobalObject(ObjectImp *global)
811{
812 return InterpreterMap::getInterpreterForGlobalObject(global);
813}
814
815
816// ------------------------------ InternalFunctionImp --------------------------
817
818const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
819
820InternalFunctionImp::InternalFunctionImp()
821{
822}
823
824InternalFunctionImp::InternalFunctionImp(FunctionPrototypeImp *funcProto)
825 : ObjectImp(funcProto)
826{
827}
828
829bool InternalFunctionImp::implementsHasInstance() const
830{
831 return true;
832}
833
834bool InternalFunctionImp::hasInstance(ExecState *exec, ValueImp *value)
835{
836 if (!value->isObject())
837 return false;
838
839 ValueImp *prot = get(exec,prototypePropertyName);
840 if (!prot->isObject() && !prot->isNull()) {
841 throwError(exec, TypeError, "Invalid prototype encountered in instanceof operation.");
842 return false;
843 }
844
845 ObjectImp *v = static_cast<ObjectImp *>(value);
846 while ((v = v->prototype()->getObject())) {
847 if (v == prot)
848 return true;
849 }
850 return false;
851}
852
853// ------------------------------ global functions -----------------------------
854
855double roundValue(ExecState *exec, ValueImp *v)
856{
857 double d = v->toNumber(exec);
858 double ad = fabs(d);
859 if (ad == 0 || isNaN(d) || isInf(d))
860 return d;
861 return copysign(floor(ad), d);
862}
863
864#ifndef NDEBUG
865#include <stdio.h>
866void printInfo(ExecState *exec, const char *s, ValueImp *o, int lineno)
867{
868 if (!o)
869 fprintf(stderr, "KJS: %s: (null)", s);
870 else {
871 ValueImp *v = o;
872
873 UString name;
874 switch (v->type()) {
875 case UnspecifiedType:
876 name = "Unspecified";
877 break;
878 case UndefinedType:
879 name = "Undefined";
880 break;
881 case NullType:
882 name = "Null";
883 break;
884 case BooleanType:
885 name = "Boolean";
886 break;
887 case StringType:
888 name = "String";
889 break;
890 case NumberType:
891 name = "Number";
892 break;
893 case ObjectType:
894 name = static_cast<ObjectImp *>(v)->className();
895 if (name.isNull())
896 name = "(unknown class)";
897 break;
898 }
899 UString vString = v->toString(exec);
900 if ( vString.size() > 50 )
901 vString = vString.substr( 0, 50 ) + "...";
902 // Can't use two UString::ascii() in the same fprintf call
903 CString tempString( vString.cstring() );
904
905 fprintf(stderr, "KJS: %s: %s : %s (%p)",
906 s, tempString.c_str(), name.ascii(), (void*)v);
907
908 if (lineno >= 0)
909 fprintf(stderr, ", line %d\n",lineno);
910 else
911 fprintf(stderr, "\n");
912 }
913}
914#endif
915
916}
Note: See TracBrowser for help on using the repository browser.