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