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