e35ca94da9bb813d8a1402fc6b6f1d15cd0c6592
[WebKit-https.git] / JavaScriptCore / kjs / internal.cpp
1 /*
2  *  This file is part of the KDE libraries
3  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
4  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
5  *  Copyright (C) 2004 Apple Computer, Inc.
6  *
7  *  This library is free software; you can redistribute it and/or
8  *  modify it under the terms of the GNU Library General Public
9  *  License as published by the Free Software Foundation; either
10  *  version 2 of the License, or (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  *  Library General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Library General Public License
18  *  along with this library; see the file COPYING.LIB.  If not, write to
19  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  *  Boston, MA 02110-1301, USA.
21  *
22  */
23
24 #include "config.h"
25 #include "internal.h"
26
27 #include "array_object.h"
28 #include "bool_object.h"
29 #include "collector.h"
30 #include "context.h"
31 #include "date_object.h"
32 #include "debugger.h"
33 #include "error_object.h"
34 #include "function_object.h"
35 #include "lexer.h"
36 #include "math_object.h"
37 #include "nodes.h"
38 #include "number_object.h"
39 #include "object.h"
40 #include "object_object.h"
41 #include "operations.h"
42 #include "regexp_object.h"
43 #include "string_object.h"
44 #include <assert.h>
45 #include <kxmlcore/HashMap.h>
46 #include <kxmlcore/HashSet.h>
47 #include <kxmlcore/Vector.h>
48 #include <math.h>
49 #include <stdio.h>
50
51 namespace KJS {
52
53 #if PLATFORM(WIN_OS)
54 #define copysign _copysign
55 #endif
56
57 // ------------------------------ StringImp ------------------------------------
58
59 JSValue *StringImp::toPrimitive(ExecState *, JSType) const
60 {
61   return const_cast<StringImp *>(this);
62 }
63
64 bool StringImp::toBoolean(ExecState *) const
65 {
66   return (val.size() > 0);
67 }
68
69 double StringImp::toNumber(ExecState *) const
70 {
71   return val.toDouble();
72 }
73
74 UString StringImp::toString(ExecState *) const
75 {
76   return val;
77 }
78
79 JSObject *StringImp::toObject(ExecState *exec) const
80 {
81     return new StringInstance(exec->lexicalInterpreter()->builtinStringPrototype(), val);
82 }
83
84 // ------------------------------ NumberImp ------------------------------------
85
86 JSValue *NumberImp::toPrimitive(ExecState *, JSType) const
87 {
88   return const_cast<NumberImp *>(this);
89 }
90
91 bool NumberImp::toBoolean(ExecState *) const
92 {
93   return val < 0.0 || val > 0.0; // false for NaN
94 }
95
96 double NumberImp::toNumber(ExecState *) const
97 {
98   return val;
99 }
100
101 UString NumberImp::toString(ExecState *) const
102 {
103   if (val == 0.0) // +0.0 or -0.0
104     return "0";
105   return UString::from(val);
106 }
107
108 JSObject *NumberImp::toObject(ExecState *exec) const
109 {
110   List args;
111   args.append(const_cast<NumberImp*>(this));
112   return static_cast<JSObject *>(exec->lexicalInterpreter()->builtinNumber()->construct(exec,args));
113 }
114
115 // FIXME: We can optimize this to work like JSValue::getUInt32. I'm ignoring it for now
116 // because it never shows up on profiles.
117 bool NumberImp::getUInt32(uint32_t& uint32) const
118 {
119   uint32 = (uint32_t)val;
120   return (double)uint32 == val;
121 }
122
123 // --------------------------- GetterSetterImp ---------------------------------
124 void GetterSetterImp::mark()
125 {
126     if (getter && !getter->marked())
127         getter->mark();
128     if (setter && !setter->marked())
129         setter->mark();
130 }
131
132 JSValue *GetterSetterImp::toPrimitive(ExecState*, JSType) const
133 {
134     assert(false);
135     return jsNull();
136 }
137
138 bool GetterSetterImp::toBoolean(ExecState*) const
139 {
140     assert(false);
141     return false;
142 }
143
144 double GetterSetterImp::toNumber(ExecState *) const
145 {
146     assert(false);
147     return 0.0;
148 }
149
150 UString GetterSetterImp::toString(ExecState *) const
151 {
152     assert(false);
153     return UString::null();
154 }
155
156 JSObject *GetterSetterImp::toObject(ExecState *exec) const
157 {
158     assert(false);
159     return jsNull()->toObject(exec);
160 }
161
162 // ------------------------------ LabelStack -----------------------------------
163
164 bool LabelStack::push(const Identifier &id)
165 {
166   if (contains(id))
167     return false;
168
169   StackElem *newtos = new StackElem;
170   newtos->id = id;
171   newtos->prev = tos;
172   tos = newtos;
173   return true;
174 }
175
176 bool LabelStack::contains(const Identifier &id) const
177 {
178   if (id.isEmpty())
179     return true;
180
181   for (StackElem *curr = tos; curr; curr = curr->prev)
182     if (curr->id == id)
183       return true;
184
185   return false;
186 }
187
188 // ------------------------------ ContextImp -----------------------------------
189
190 // ECMA 10.2
191 ContextImp::ContextImp(JSObject *glob, InterpreterImp *interpreter, JSObject *thisV, FunctionBodyNode* currentBody,
192                        
193                        CodeType type, ContextImp *callingCon, FunctionImp *func, const List *args)
194     : _interpreter(interpreter)
195     , m_currentBody(currentBody)
196     , _function(func)
197     , _arguments(args)
198     , m_iterationDepth(0)
199     , m_switchDepth(0) 
200 {
201   m_codeType = type;
202   _callingContext = callingCon;
203
204   // create and initialize activation object (ECMA 10.1.6)
205   if (type == FunctionCode || type == AnonymousCode ) {
206     activation = new ActivationImp(func, *args);
207     variable = activation;
208   } else {
209     activation = NULL;
210     variable = glob;
211   }
212
213   // ECMA 10.2
214   switch(type) {
215     case EvalCode:
216       if (_callingContext) {
217         scope = _callingContext->scopeChain();
218         variable = _callingContext->variableObject();
219         thisVal = _callingContext->thisValue();
220         break;
221       } // else same as GlobalCode
222     case GlobalCode:
223       scope.clear();
224       scope.push(glob);
225       thisVal = static_cast<JSObject*>(glob);
226       break;
227     case FunctionCode:
228     case AnonymousCode:
229       if (type == FunctionCode) {
230         scope = func->scope();
231         scope.push(activation);
232       } else {
233         scope.clear();
234         scope.push(glob);
235         scope.push(activation);
236       }
237       variable = activation; // TODO: DontDelete ? (ECMA 10.2.3)
238       thisVal = thisV;
239       break;
240     }
241
242   _interpreter->setContext(this);
243 }
244
245 ContextImp::~ContextImp()
246 {
247   _interpreter->setContext(_callingContext);
248 }
249
250 void ContextImp::mark()
251 {
252   for (ContextImp *context = this; context; context = context->_callingContext) {
253     context->scope.mark();
254   }
255 }
256
257 // ------------------------------ InterpreterImp -------------------------------
258
259 InterpreterImp* InterpreterImp::s_hook = 0L;
260
261 typedef HashMap<JSObject *, InterpreterImp *> InterpreterMap;
262
263 static inline InterpreterMap &interpreterMap()
264 {
265     static InterpreterMap *map = new InterpreterMap;
266     return *map;
267 }
268
269 InterpreterImp::InterpreterImp(Interpreter *interp, JSObject *glob)
270     : globExec(interp, 0)
271     , _context(0)
272 {
273   // add this interpreter to the global chain
274   // as a root set for garbage collection
275   JSLock lock;
276
277   m_interpreter = interp;
278   if (s_hook) {
279     prev = s_hook;
280     next = s_hook->next;
281     s_hook->next->prev = this;
282     s_hook->next = this;
283   } else {
284     // This is the first interpreter
285     s_hook = next = prev = this;
286   }
287
288   interpreterMap().set(glob, this);
289
290   global = glob;
291   dbg = 0;
292   m_compatMode = Interpreter::NativeMode;
293
294   // initialize properties of the global object
295   initGlobalObject();
296
297   recursion = 0;
298 }
299
300 void InterpreterImp::initGlobalObject()
301 {
302   Identifier::init();
303   
304   // Contructor prototype objects (Object.prototype, Array.prototype etc)
305
306   FunctionPrototype *funcProto = new FunctionPrototype(&globExec);
307   b_FunctionPrototype = funcProto;
308   ObjectPrototype *objProto = new ObjectPrototype(&globExec, funcProto);
309   b_ObjectPrototype = objProto;
310   funcProto->setPrototype(b_ObjectPrototype);
311
312   ArrayPrototype *arrayProto = new ArrayPrototype(&globExec, objProto);
313   b_ArrayPrototype = arrayProto;
314   StringPrototype *stringProto = new StringPrototype(&globExec, objProto);
315   b_StringPrototype = stringProto;
316   BooleanPrototype *booleanProto = new BooleanPrototype(&globExec, objProto, funcProto);
317   b_BooleanPrototype = booleanProto;
318   NumberPrototype *numberProto = new NumberPrototype(&globExec, objProto, funcProto);
319   b_NumberPrototype = numberProto;
320   DatePrototype *dateProto = new DatePrototype(&globExec, objProto);
321   b_DatePrototype = dateProto;
322   RegExpPrototype *regexpProto = new RegExpPrototype(&globExec, objProto, funcProto);
323   b_RegExpPrototype = regexpProto;
324   ErrorPrototype *errorProto = new ErrorPrototype(&globExec, objProto, funcProto);
325   b_ErrorPrototype = errorProto;
326
327   static_cast<JSObject*>(global)->setPrototype(b_ObjectPrototype);
328
329   // Constructors (Object, Array, etc.)
330   b_Object = new ObjectObjectImp(&globExec, objProto, funcProto);
331   b_Function = new FunctionObjectImp(&globExec, funcProto);
332   b_Array = new ArrayObjectImp(&globExec, funcProto, arrayProto);
333   b_String = new StringObjectImp(&globExec, funcProto, stringProto);
334   b_Boolean = new BooleanObjectImp(&globExec, funcProto, booleanProto);
335   b_Number = new NumberObjectImp(&globExec, funcProto, numberProto);
336   b_Date = new DateObjectImp(&globExec, funcProto, dateProto);
337   b_RegExp = new RegExpObjectImp(&globExec, funcProto, regexpProto);
338   b_Error = new ErrorObjectImp(&globExec, funcProto, errorProto);
339
340   // Error object prototypes
341   b_evalErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, EvalError, "EvalError", "EvalError");
342   b_rangeErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, RangeError, "RangeError", "RangeError");
343   b_referenceErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, ReferenceError, "ReferenceError", "ReferenceError");
344   b_syntaxErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, SyntaxError, "SyntaxError", "SyntaxError");
345   b_typeErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, TypeError, "TypeError", "TypeError");
346   b_uriErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, URIError, "URIError", "URIError");
347
348   // Error objects
349   b_evalError = new NativeErrorImp(&globExec, funcProto, b_evalErrorPrototype);
350   b_rangeError = new NativeErrorImp(&globExec, funcProto, b_rangeErrorPrototype);
351   b_referenceError = new NativeErrorImp(&globExec, funcProto, b_referenceErrorPrototype);
352   b_syntaxError = new NativeErrorImp(&globExec, funcProto, b_syntaxErrorPrototype);
353   b_typeError = new NativeErrorImp(&globExec, funcProto, b_typeErrorPrototype);
354   b_uriError = new NativeErrorImp(&globExec, funcProto, b_uriErrorPrototype);
355
356   // ECMA 15.3.4.1
357   funcProto->put(&globExec, constructorPropertyName, b_Function, DontEnum);
358
359   global->put(&globExec, "Object", b_Object, DontEnum);
360   global->put(&globExec, "Function", b_Function, DontEnum);
361   global->put(&globExec, "Array", b_Array, DontEnum);
362   global->put(&globExec, "Boolean", b_Boolean, DontEnum);
363   global->put(&globExec, "String", b_String, DontEnum);
364   global->put(&globExec, "Number", b_Number, DontEnum);
365   global->put(&globExec, "Date", b_Date, DontEnum);
366   global->put(&globExec, "RegExp", b_RegExp, DontEnum);
367   global->put(&globExec, "Error", b_Error, DontEnum);
368   // Using Internal for those to have something != 0
369   // (see kjs_window). Maybe DontEnum would be ok too ?
370   global->put(&globExec, "EvalError",b_evalError, Internal);
371   global->put(&globExec, "RangeError",b_rangeError, Internal);
372   global->put(&globExec, "ReferenceError",b_referenceError, Internal);
373   global->put(&globExec, "SyntaxError",b_syntaxError, Internal);
374   global->put(&globExec, "TypeError",b_typeError, Internal);
375   global->put(&globExec, "URIError",b_uriError, Internal);
376
377   // Set the constructorPropertyName property of all builtin constructors
378   objProto->put(&globExec, constructorPropertyName, b_Object, DontEnum | DontDelete | ReadOnly);
379   funcProto->put(&globExec, constructorPropertyName, b_Function, DontEnum | DontDelete | ReadOnly);
380   arrayProto->put(&globExec, constructorPropertyName, b_Array, DontEnum | DontDelete | ReadOnly);
381   booleanProto->put(&globExec, constructorPropertyName, b_Boolean, DontEnum | DontDelete | ReadOnly);
382   stringProto->put(&globExec, constructorPropertyName, b_String, DontEnum | DontDelete | ReadOnly);
383   numberProto->put(&globExec, constructorPropertyName, b_Number, DontEnum | DontDelete | ReadOnly);
384   dateProto->put(&globExec, constructorPropertyName, b_Date, DontEnum | DontDelete | ReadOnly);
385   regexpProto->put(&globExec, constructorPropertyName, b_RegExp, DontEnum | DontDelete | ReadOnly);
386   errorProto->put(&globExec, constructorPropertyName, b_Error, DontEnum | DontDelete | ReadOnly);
387   b_evalErrorPrototype->put(&globExec, constructorPropertyName, b_evalError, DontEnum | DontDelete | ReadOnly);
388   b_rangeErrorPrototype->put(&globExec, constructorPropertyName, b_rangeError, DontEnum | DontDelete | ReadOnly);
389   b_referenceErrorPrototype->put(&globExec, constructorPropertyName, b_referenceError, DontEnum | DontDelete | ReadOnly);
390   b_syntaxErrorPrototype->put(&globExec, constructorPropertyName, b_syntaxError, DontEnum | DontDelete | ReadOnly);
391   b_typeErrorPrototype->put(&globExec, constructorPropertyName, b_typeError, DontEnum | DontDelete | ReadOnly);
392   b_uriErrorPrototype->put(&globExec, constructorPropertyName, b_uriError, DontEnum | DontDelete | ReadOnly);
393
394   // built-in values
395   global->put(&globExec, "NaN",        jsNaN(), DontEnum|DontDelete);
396   global->put(&globExec, "Infinity",   jsNumber(Inf), DontEnum|DontDelete);
397   global->put(&globExec, "undefined",  jsUndefined(), DontEnum|DontDelete);
398
399   // built-in functions
400   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::Eval, 1, "eval"), DontEnum);
401   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::ParseInt, 2, "parseInt"), DontEnum);
402   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::ParseFloat, 1, "parseFloat"), DontEnum);
403   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::IsNaN, 1, "isNaN"), DontEnum);
404   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::IsFinite, 1, "isFinite"), DontEnum);
405   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::Escape, 1, "escape"), DontEnum);
406   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::UnEscape, 1, "unescape"), DontEnum);
407   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::DecodeURI, 1, "decodeURI"), DontEnum);
408   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::DecodeURIComponent, 1, "decodeURIComponent"), DontEnum);
409   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::EncodeURI, 1, "encodeURI"), DontEnum);
410   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::EncodeURIComponent, 1, "encodeURIComponent"), DontEnum);
411 #ifndef NDEBUG
412   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::KJSPrint, 1, "kjsprint"), DontEnum);
413 #endif
414
415   // built-in objects
416   global->put(&globExec, "Math", new MathObjectImp(&globExec, objProto), DontEnum);
417 }
418
419 InterpreterImp::~InterpreterImp()
420 {
421   if (dbg)
422     dbg->detach(m_interpreter);
423   clear();
424 }
425
426 void InterpreterImp::clear()
427 {
428   //fprintf(stderr,"InterpreterImp::clear\n");
429   // remove from global chain (see init())
430   JSLock lock;
431
432   next->prev = prev;
433   prev->next = next;
434   s_hook = next;
435   if (s_hook == this)
436   {
437     // This was the last interpreter
438     s_hook = 0L;
439   }
440   interpreterMap().remove(global);
441 }
442
443 void InterpreterImp::mark()
444 {
445   if (m_interpreter)
446     m_interpreter->mark();
447   if (_context)
448     _context->mark();
449   if (global)
450       global->mark();
451   if (globExec.exception())
452       globExec.exception()->mark();
453 }
454
455 bool InterpreterImp::checkSyntax(const UString &code)
456 {
457   JSLock lock;
458
459   // Parser::parse() returns 0 in a syntax error occurs, so we just check for that
460   RefPtr<ProgramNode> progNode = Parser::parse(UString(), 0, code.data(), code.size(), 0, 0, 0);
461   return progNode;
462 }
463
464 Completion InterpreterImp::evaluate(const UChar* code, int codeLength, JSValue* thisV, const UString& sourceURL, int startingLineNumber)
465 {
466   JSLock lock;
467
468   // prevent against infinite recursion
469   if (recursion >= 20)
470     return Completion(Throw, Error::create(&globExec, GeneralError, "Recursion too deep"));
471
472   // parse the source code
473   int sid;
474   int errLine;
475   UString errMsg;
476   RefPtr<ProgramNode> progNode = Parser::parse(sourceURL, startingLineNumber, code, codeLength, &sid, &errLine, &errMsg);
477
478   // notify debugger that source has been parsed
479   if (dbg) {
480     bool cont = dbg->sourceParsed(&globExec, sid, sourceURL, UString(code, codeLength), errLine);
481     if (!cont)
482       return Completion(Break);
483   }
484   
485   // no program node means a syntax error occurred
486   if (!progNode)
487     return Completion(Throw, Error::create(&globExec, SyntaxError, errMsg, errLine, sid, &sourceURL));
488
489   globExec.clearException();
490
491   recursion++;
492
493   JSObject* globalObj = globalObject();
494   JSObject* thisObj = globalObj;
495
496   // "this" must be an object... use same rules as Function.prototype.apply()
497   if (thisV && !thisV->isUndefinedOrNull())
498       thisObj = thisV->toObject(&globExec);
499
500   Completion res;
501   if (globExec.hadException())
502     // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it
503     res = Completion(Throw, globExec.exception());
504   else {
505     // execute the code
506     ContextImp ctx(globalObj, this, thisObj, progNode.get());
507     ExecState newExec(m_interpreter, &ctx);
508     progNode->processVarDecls(&newExec);
509     res = progNode->execute(&newExec);
510   }
511
512   recursion--;
513
514   return res;
515 }
516
517 void InterpreterImp::saveBuiltins (SavedBuiltins &builtins) const
518 {
519   if (!builtins._internal) {
520     builtins._internal = new SavedBuiltinsInternal;
521   }
522
523   builtins._internal->b_Object = b_Object;
524   builtins._internal->b_Function = b_Function;
525   builtins._internal->b_Array = b_Array;
526   builtins._internal->b_Boolean = b_Boolean;
527   builtins._internal->b_String = b_String;
528   builtins._internal->b_Number = b_Number;
529   builtins._internal->b_Date = b_Date;
530   builtins._internal->b_RegExp = b_RegExp;
531   builtins._internal->b_Error = b_Error;
532   
533   builtins._internal->b_ObjectPrototype = b_ObjectPrototype;
534   builtins._internal->b_FunctionPrototype = b_FunctionPrototype;
535   builtins._internal->b_ArrayPrototype = b_ArrayPrototype;
536   builtins._internal->b_BooleanPrototype = b_BooleanPrototype;
537   builtins._internal->b_StringPrototype = b_StringPrototype;
538   builtins._internal->b_NumberPrototype = b_NumberPrototype;
539   builtins._internal->b_DatePrototype = b_DatePrototype;
540   builtins._internal->b_RegExpPrototype = b_RegExpPrototype;
541   builtins._internal->b_ErrorPrototype = b_ErrorPrototype;
542   
543   builtins._internal->b_evalError = b_evalError;
544   builtins._internal->b_rangeError = b_rangeError;
545   builtins._internal->b_referenceError = b_referenceError;
546   builtins._internal->b_syntaxError = b_syntaxError;
547   builtins._internal->b_typeError = b_typeError;
548   builtins._internal->b_uriError = b_uriError;
549   
550   builtins._internal->b_evalErrorPrototype = b_evalErrorPrototype;
551   builtins._internal->b_rangeErrorPrototype = b_rangeErrorPrototype;
552   builtins._internal->b_referenceErrorPrototype = b_referenceErrorPrototype;
553   builtins._internal->b_syntaxErrorPrototype = b_syntaxErrorPrototype;
554   builtins._internal->b_typeErrorPrototype = b_typeErrorPrototype;
555   builtins._internal->b_uriErrorPrototype = b_uriErrorPrototype;
556 }
557
558 void InterpreterImp::restoreBuiltins (const SavedBuiltins &builtins)
559 {
560   if (!builtins._internal) {
561     return;
562   }
563
564   b_Object = builtins._internal->b_Object;
565   b_Function = builtins._internal->b_Function;
566   b_Array = builtins._internal->b_Array;
567   b_Boolean = builtins._internal->b_Boolean;
568   b_String = builtins._internal->b_String;
569   b_Number = builtins._internal->b_Number;
570   b_Date = builtins._internal->b_Date;
571   b_RegExp = builtins._internal->b_RegExp;
572   b_Error = builtins._internal->b_Error;
573   
574   b_ObjectPrototype = builtins._internal->b_ObjectPrototype;
575   b_FunctionPrototype = builtins._internal->b_FunctionPrototype;
576   b_ArrayPrototype = builtins._internal->b_ArrayPrototype;
577   b_BooleanPrototype = builtins._internal->b_BooleanPrototype;
578   b_StringPrototype = builtins._internal->b_StringPrototype;
579   b_NumberPrototype = builtins._internal->b_NumberPrototype;
580   b_DatePrototype = builtins._internal->b_DatePrototype;
581   b_RegExpPrototype = builtins._internal->b_RegExpPrototype;
582   b_ErrorPrototype = builtins._internal->b_ErrorPrototype;
583   
584   b_evalError = builtins._internal->b_evalError;
585   b_rangeError = builtins._internal->b_rangeError;
586   b_referenceError = builtins._internal->b_referenceError;
587   b_syntaxError = builtins._internal->b_syntaxError;
588   b_typeError = builtins._internal->b_typeError;
589   b_uriError = builtins._internal->b_uriError;
590   
591   b_evalErrorPrototype = builtins._internal->b_evalErrorPrototype;
592   b_rangeErrorPrototype = builtins._internal->b_rangeErrorPrototype;
593   b_referenceErrorPrototype = builtins._internal->b_referenceErrorPrototype;
594   b_syntaxErrorPrototype = builtins._internal->b_syntaxErrorPrototype;
595   b_typeErrorPrototype = builtins._internal->b_typeErrorPrototype;
596   b_uriErrorPrototype = builtins._internal->b_uriErrorPrototype;
597 }
598
599 InterpreterImp *InterpreterImp::interpreterWithGlobalObject(JSObject *global)
600 {
601     return interpreterMap().get(global);
602 }
603
604
605 // ------------------------------ InternalFunctionImp --------------------------
606
607 const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
608
609 InternalFunctionImp::InternalFunctionImp()
610 {
611 }
612
613 InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto)
614   : JSObject(funcProto)
615 {
616 }
617
618 InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto, const Identifier& name)
619   : JSObject(funcProto)
620   , m_name(name)
621 {
622 }
623
624 bool InternalFunctionImp::implementsCall() const
625 {
626   return true;
627 }
628
629 bool InternalFunctionImp::implementsHasInstance() const
630 {
631   return true;
632 }
633
634 bool InternalFunctionImp::hasInstance(ExecState *exec, JSValue *value)
635 {
636   if (!value->isObject())
637     return false;
638
639   JSValue *prot = get(exec,prototypePropertyName);
640   if (!prot->isObject() && !prot->isNull()) {
641     throwError(exec, TypeError, "Invalid prototype encountered in instanceof operation.");
642     return false;
643   }
644
645   JSObject *v = static_cast<JSObject *>(value);
646   while ((v = v->prototype()->getObject())) {
647     if (v == prot)
648       return true;
649   }
650   return false;
651 }
652
653 // ------------------------------ global functions -----------------------------
654
655 double roundValue(ExecState *exec, JSValue *v)
656 {
657   double d = v->toNumber(exec);
658   double ad = fabs(d);
659   if (ad == 0 || isNaN(d) || isInf(d))
660     return d;
661   return copysign(floor(ad), d);
662 }
663
664 #ifndef NDEBUG
665 #include <stdio.h>
666 void printInfo(ExecState *exec, const char *s, JSValue *o, int lineno)
667 {
668   if (!o)
669     fprintf(stderr, "KJS: %s: (null)", s);
670   else {
671     JSValue *v = o;
672
673     UString name;
674     switch (v->type()) {
675     case UnspecifiedType:
676       name = "Unspecified";
677       break;
678     case UndefinedType:
679       name = "Undefined";
680       break;
681     case NullType:
682       name = "Null";
683       break;
684     case BooleanType:
685       name = "Boolean";
686       break;
687     case StringType:
688       name = "String";
689       break;
690     case NumberType:
691       name = "Number";
692       break;
693     case ObjectType:
694       name = static_cast<JSObject *>(v)->className();
695       if (name.isNull())
696         name = "(unknown class)";
697       break;
698     case GetterSetterType:
699       name = "GetterSetter";
700       break;
701     }
702     UString vString = v->toString(exec);
703     if ( vString.size() > 50 )
704       vString = vString.substr( 0, 50 ) + "...";
705     // Can't use two UString::ascii() in the same fprintf call
706     CString tempString( vString.cstring() );
707
708     fprintf(stderr, "KJS: %s: %s : %s (%p)",
709             s, tempString.c_str(), name.ascii(), (void*)v);
710
711     if (lineno >= 0)
712       fprintf(stderr, ", line %d\n",lineno);
713     else
714       fprintf(stderr, "\n");
715   }
716 }
717 #endif
718
719 }