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

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