2006-03-31 Anders Carlsson <andersca@mac.com>
[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     JSCell::mark();
127     
128     if (getter && !getter->marked())
129         getter->mark();
130     if (setter && !setter->marked())
131         setter->mark();
132 }
133
134 JSValue *GetterSetterImp::toPrimitive(ExecState*, JSType) const
135 {
136     assert(false);
137     return jsNull();
138 }
139
140 bool GetterSetterImp::toBoolean(ExecState*) const
141 {
142     assert(false);
143     return false;
144 }
145
146 double GetterSetterImp::toNumber(ExecState *) const
147 {
148     assert(false);
149     return 0.0;
150 }
151
152 UString GetterSetterImp::toString(ExecState *) const
153 {
154     assert(false);
155     return UString::null();
156 }
157
158 JSObject *GetterSetterImp::toObject(ExecState *exec) const
159 {
160     assert(false);
161     return jsNull()->toObject(exec);
162 }
163
164 // ------------------------------ LabelStack -----------------------------------
165
166 bool LabelStack::push(const Identifier &id)
167 {
168   if (contains(id))
169     return false;
170
171   StackElem *newtos = new StackElem;
172   newtos->id = id;
173   newtos->prev = tos;
174   tos = newtos;
175   return true;
176 }
177
178 bool LabelStack::contains(const Identifier &id) const
179 {
180   if (id.isEmpty())
181     return true;
182
183   for (StackElem *curr = tos; curr; curr = curr->prev)
184     if (curr->id == id)
185       return true;
186
187   return false;
188 }
189
190 // ------------------------------ ContextImp -----------------------------------
191
192 // ECMA 10.2
193 ContextImp::ContextImp(JSObject *glob, InterpreterImp *interpreter, JSObject *thisV, FunctionBodyNode* currentBody,
194                        
195                        CodeType type, ContextImp *callingCon, FunctionImp *func, const List *args)
196     : _interpreter(interpreter)
197     , m_currentBody(currentBody)
198     , _function(func)
199     , _arguments(args)
200     , m_iterationDepth(0)
201     , m_switchDepth(0) 
202 {
203   m_codeType = type;
204   _callingContext = callingCon;
205
206   // create and initialize activation object (ECMA 10.1.6)
207   if (type == FunctionCode || type == AnonymousCode ) {
208     activation = new ActivationImp(func, *args);
209     variable = activation;
210   } else {
211     activation = NULL;
212     variable = glob;
213   }
214
215   // ECMA 10.2
216   switch(type) {
217     case EvalCode:
218       if (_callingContext) {
219         scope = _callingContext->scopeChain();
220         variable = _callingContext->variableObject();
221         thisVal = _callingContext->thisValue();
222         break;
223       } // else same as GlobalCode
224     case GlobalCode:
225       scope.clear();
226       scope.push(glob);
227       thisVal = static_cast<JSObject*>(glob);
228       break;
229     case FunctionCode:
230     case AnonymousCode:
231       if (type == FunctionCode) {
232         scope = func->scope();
233         scope.push(activation);
234       } else {
235         scope.clear();
236         scope.push(glob);
237         scope.push(activation);
238       }
239       variable = activation; // TODO: DontDelete ? (ECMA 10.2.3)
240       thisVal = thisV;
241       break;
242     }
243
244   _interpreter->setContext(this);
245 }
246
247 ContextImp::~ContextImp()
248 {
249   _interpreter->setContext(_callingContext);
250 }
251
252 void ContextImp::mark()
253 {
254   for (ContextImp *context = this; context; context = context->_callingContext) {
255     context->scope.mark();
256   }
257 }
258
259 // ------------------------------ InterpreterImp -------------------------------
260
261 InterpreterImp* InterpreterImp::s_hook = 0L;
262
263 typedef HashMap<JSObject *, InterpreterImp *> InterpreterMap;
264
265 static inline InterpreterMap &interpreterMap()
266 {
267     static InterpreterMap *map = new InterpreterMap;
268     return *map;
269 }
270
271 InterpreterImp::InterpreterImp(Interpreter *interp, JSObject *glob)
272     : globExec(interp, 0)
273     , _context(0)
274 {
275   // add this interpreter to the global chain
276   // as a root set for garbage collection
277   JSLock lock;
278
279   m_interpreter = interp;
280   if (s_hook) {
281     prev = s_hook;
282     next = s_hook->next;
283     s_hook->next->prev = this;
284     s_hook->next = this;
285   } else {
286     // This is the first interpreter
287     s_hook = next = prev = this;
288   }
289
290   interpreterMap().set(glob, this);
291
292   global = glob;
293   dbg = 0;
294   m_compatMode = Interpreter::NativeMode;
295
296   // initialize properties of the global object
297   initGlobalObject();
298
299   recursion = 0;
300 }
301
302 void InterpreterImp::initGlobalObject()
303 {
304   Identifier::init();
305   
306   // Contructor prototype objects (Object.prototype, Array.prototype etc)
307
308   FunctionPrototype *funcProto = new FunctionPrototype(&globExec);
309   b_FunctionPrototype = funcProto;
310   ObjectPrototype *objProto = new ObjectPrototype(&globExec, funcProto);
311   b_ObjectPrototype = objProto;
312   funcProto->setPrototype(b_ObjectPrototype);
313
314   ArrayPrototype *arrayProto = new ArrayPrototype(&globExec, objProto);
315   b_ArrayPrototype = arrayProto;
316   StringPrototype *stringProto = new StringPrototype(&globExec, objProto);
317   b_StringPrototype = stringProto;
318   BooleanPrototype *booleanProto = new BooleanPrototype(&globExec, objProto, funcProto);
319   b_BooleanPrototype = booleanProto;
320   NumberPrototype *numberProto = new NumberPrototype(&globExec, objProto, funcProto);
321   b_NumberPrototype = numberProto;
322   DatePrototype *dateProto = new DatePrototype(&globExec, objProto);
323   b_DatePrototype = dateProto;
324   RegExpPrototype *regexpProto = new RegExpPrototype(&globExec, objProto, funcProto);
325   b_RegExpPrototype = regexpProto;
326   ErrorPrototype *errorProto = new ErrorPrototype(&globExec, objProto, funcProto);
327   b_ErrorPrototype = errorProto;
328
329   static_cast<JSObject*>(global)->setPrototype(b_ObjectPrototype);
330
331   // Constructors (Object, Array, etc.)
332   b_Object = new ObjectObjectImp(&globExec, objProto, funcProto);
333   b_Function = new FunctionObjectImp(&globExec, funcProto);
334   b_Array = new ArrayObjectImp(&globExec, funcProto, arrayProto);
335   b_String = new StringObjectImp(&globExec, funcProto, stringProto);
336   b_Boolean = new BooleanObjectImp(&globExec, funcProto, booleanProto);
337   b_Number = new NumberObjectImp(&globExec, funcProto, numberProto);
338   b_Date = new DateObjectImp(&globExec, funcProto, dateProto);
339   b_RegExp = new RegExpObjectImp(&globExec, funcProto, regexpProto);
340   b_Error = new ErrorObjectImp(&globExec, funcProto, errorProto);
341
342   // Error object prototypes
343   b_evalErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, EvalError, "EvalError", "EvalError");
344   b_rangeErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, RangeError, "RangeError", "RangeError");
345   b_referenceErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, ReferenceError, "ReferenceError", "ReferenceError");
346   b_syntaxErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, SyntaxError, "SyntaxError", "SyntaxError");
347   b_typeErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, TypeError, "TypeError", "TypeError");
348   b_uriErrorPrototype = new NativeErrorPrototype(&globExec, errorProto, URIError, "URIError", "URIError");
349
350   // Error objects
351   b_evalError = new NativeErrorImp(&globExec, funcProto, b_evalErrorPrototype);
352   b_rangeError = new NativeErrorImp(&globExec, funcProto, b_rangeErrorPrototype);
353   b_referenceError = new NativeErrorImp(&globExec, funcProto, b_referenceErrorPrototype);
354   b_syntaxError = new NativeErrorImp(&globExec, funcProto, b_syntaxErrorPrototype);
355   b_typeError = new NativeErrorImp(&globExec, funcProto, b_typeErrorPrototype);
356   b_uriError = new NativeErrorImp(&globExec, funcProto, b_uriErrorPrototype);
357
358   // ECMA 15.3.4.1
359   funcProto->put(&globExec, constructorPropertyName, b_Function, DontEnum);
360
361   global->put(&globExec, "Object", b_Object, DontEnum);
362   global->put(&globExec, "Function", b_Function, DontEnum);
363   global->put(&globExec, "Array", b_Array, DontEnum);
364   global->put(&globExec, "Boolean", b_Boolean, DontEnum);
365   global->put(&globExec, "String", b_String, DontEnum);
366   global->put(&globExec, "Number", b_Number, DontEnum);
367   global->put(&globExec, "Date", b_Date, DontEnum);
368   global->put(&globExec, "RegExp", b_RegExp, DontEnum);
369   global->put(&globExec, "Error", b_Error, DontEnum);
370   // Using Internal for those to have something != 0
371   // (see kjs_window). Maybe DontEnum would be ok too ?
372   global->put(&globExec, "EvalError",b_evalError, Internal);
373   global->put(&globExec, "RangeError",b_rangeError, Internal);
374   global->put(&globExec, "ReferenceError",b_referenceError, Internal);
375   global->put(&globExec, "SyntaxError",b_syntaxError, Internal);
376   global->put(&globExec, "TypeError",b_typeError, Internal);
377   global->put(&globExec, "URIError",b_uriError, Internal);
378
379   // Set the constructorPropertyName property of all builtin constructors
380   objProto->put(&globExec, constructorPropertyName, b_Object, DontEnum | DontDelete | ReadOnly);
381   funcProto->put(&globExec, constructorPropertyName, b_Function, DontEnum | DontDelete | ReadOnly);
382   arrayProto->put(&globExec, constructorPropertyName, b_Array, DontEnum | DontDelete | ReadOnly);
383   booleanProto->put(&globExec, constructorPropertyName, b_Boolean, DontEnum | DontDelete | ReadOnly);
384   stringProto->put(&globExec, constructorPropertyName, b_String, DontEnum | DontDelete | ReadOnly);
385   numberProto->put(&globExec, constructorPropertyName, b_Number, DontEnum | DontDelete | ReadOnly);
386   dateProto->put(&globExec, constructorPropertyName, b_Date, DontEnum | DontDelete | ReadOnly);
387   regexpProto->put(&globExec, constructorPropertyName, b_RegExp, DontEnum | DontDelete | ReadOnly);
388   errorProto->put(&globExec, constructorPropertyName, b_Error, DontEnum | DontDelete | ReadOnly);
389   b_evalErrorPrototype->put(&globExec, constructorPropertyName, b_evalError, DontEnum | DontDelete | ReadOnly);
390   b_rangeErrorPrototype->put(&globExec, constructorPropertyName, b_rangeError, DontEnum | DontDelete | ReadOnly);
391   b_referenceErrorPrototype->put(&globExec, constructorPropertyName, b_referenceError, DontEnum | DontDelete | ReadOnly);
392   b_syntaxErrorPrototype->put(&globExec, constructorPropertyName, b_syntaxError, DontEnum | DontDelete | ReadOnly);
393   b_typeErrorPrototype->put(&globExec, constructorPropertyName, b_typeError, DontEnum | DontDelete | ReadOnly);
394   b_uriErrorPrototype->put(&globExec, constructorPropertyName, b_uriError, DontEnum | DontDelete | ReadOnly);
395
396   // built-in values
397   global->put(&globExec, "NaN",        jsNaN(), DontEnum|DontDelete);
398   global->put(&globExec, "Infinity",   jsNumber(Inf), DontEnum|DontDelete);
399   global->put(&globExec, "undefined",  jsUndefined(), DontEnum|DontDelete);
400
401   // built-in functions
402   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::Eval, 1, "eval"), DontEnum);
403   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::ParseInt, 2, "parseInt"), DontEnum);
404   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::ParseFloat, 1, "parseFloat"), DontEnum);
405   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::IsNaN, 1, "isNaN"), DontEnum);
406   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::IsFinite, 1, "isFinite"), DontEnum);
407   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::Escape, 1, "escape"), DontEnum);
408   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::UnEscape, 1, "unescape"), DontEnum);
409   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::DecodeURI, 1, "decodeURI"), DontEnum);
410   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::DecodeURIComponent, 1, "decodeURIComponent"), DontEnum);
411   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::EncodeURI, 1, "encodeURI"), DontEnum);
412   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::EncodeURIComponent, 1, "encodeURIComponent"), DontEnum);
413 #ifndef NDEBUG
414   global->putDirectFunction(new GlobalFuncImp(&globExec, funcProto, GlobalFuncImp::KJSPrint, 1, "kjsprint"), DontEnum);
415 #endif
416
417   // built-in objects
418   global->put(&globExec, "Math", new MathObjectImp(&globExec, objProto), DontEnum);
419 }
420
421 InterpreterImp::~InterpreterImp()
422 {
423   if (dbg)
424     dbg->detach(m_interpreter);
425   clear();
426 }
427
428 void InterpreterImp::clear()
429 {
430   //fprintf(stderr,"InterpreterImp::clear\n");
431   // remove from global chain (see init())
432   JSLock lock;
433
434   next->prev = prev;
435   prev->next = next;
436   s_hook = next;
437   if (s_hook == this)
438   {
439     // This was the last interpreter
440     s_hook = 0L;
441   }
442   interpreterMap().remove(global);
443 }
444
445 void InterpreterImp::mark()
446 {
447   if (m_interpreter)
448     m_interpreter->mark();
449   if (_context)
450     _context->mark();
451   if (global)
452       global->mark();
453   if (globExec.exception())
454       globExec.exception()->mark();
455 }
456
457 bool InterpreterImp::checkSyntax(const UString &code)
458 {
459   JSLock lock;
460
461   // Parser::parse() returns 0 in a syntax error occurs, so we just check for that
462   RefPtr<ProgramNode> progNode = Parser::parse(UString(), 0, code.data(), code.size(), 0, 0, 0);
463   return progNode;
464 }
465
466 Completion InterpreterImp::evaluate(const UChar* code, int codeLength, JSValue* thisV, const UString& sourceURL, int startingLineNumber)
467 {
468   JSLock lock;
469
470   // prevent against infinite recursion
471   if (recursion >= 20)
472     return Completion(Throw, Error::create(&globExec, GeneralError, "Recursion too deep"));
473
474   // parse the source code
475   int sid;
476   int errLine;
477   UString errMsg;
478   RefPtr<ProgramNode> progNode = Parser::parse(sourceURL, startingLineNumber, code, codeLength, &sid, &errLine, &errMsg);
479
480   // notify debugger that source has been parsed
481   if (dbg) {
482     bool cont = dbg->sourceParsed(&globExec, sid, sourceURL, UString(code, codeLength), errLine);
483     if (!cont)
484       return Completion(Break);
485   }
486   
487   // no program node means a syntax error occurred
488   if (!progNode)
489     return Completion(Throw, Error::create(&globExec, SyntaxError, errMsg, errLine, sid, &sourceURL));
490
491   globExec.clearException();
492
493   recursion++;
494
495   JSObject* globalObj = globalObject();
496   JSObject* thisObj = globalObj;
497
498   // "this" must be an object... use same rules as Function.prototype.apply()
499   if (thisV && !thisV->isUndefinedOrNull())
500       thisObj = thisV->toObject(&globExec);
501
502   Completion res;
503   if (globExec.hadException())
504     // the thisV->toObject() conversion above might have thrown an exception - if so, propagate it
505     res = Completion(Throw, globExec.exception());
506   else {
507     // execute the code
508     ContextImp ctx(globalObj, this, thisObj, progNode.get());
509     ExecState newExec(m_interpreter, &ctx);
510     progNode->processVarDecls(&newExec);
511     res = progNode->execute(&newExec);
512   }
513
514   recursion--;
515
516   return res;
517 }
518
519 void InterpreterImp::saveBuiltins (SavedBuiltins &builtins) const
520 {
521   if (!builtins._internal) {
522     builtins._internal = new SavedBuiltinsInternal;
523   }
524
525   builtins._internal->b_Object = b_Object;
526   builtins._internal->b_Function = b_Function;
527   builtins._internal->b_Array = b_Array;
528   builtins._internal->b_Boolean = b_Boolean;
529   builtins._internal->b_String = b_String;
530   builtins._internal->b_Number = b_Number;
531   builtins._internal->b_Date = b_Date;
532   builtins._internal->b_RegExp = b_RegExp;
533   builtins._internal->b_Error = b_Error;
534   
535   builtins._internal->b_ObjectPrototype = b_ObjectPrototype;
536   builtins._internal->b_FunctionPrototype = b_FunctionPrototype;
537   builtins._internal->b_ArrayPrototype = b_ArrayPrototype;
538   builtins._internal->b_BooleanPrototype = b_BooleanPrototype;
539   builtins._internal->b_StringPrototype = b_StringPrototype;
540   builtins._internal->b_NumberPrototype = b_NumberPrototype;
541   builtins._internal->b_DatePrototype = b_DatePrototype;
542   builtins._internal->b_RegExpPrototype = b_RegExpPrototype;
543   builtins._internal->b_ErrorPrototype = b_ErrorPrototype;
544   
545   builtins._internal->b_evalError = b_evalError;
546   builtins._internal->b_rangeError = b_rangeError;
547   builtins._internal->b_referenceError = b_referenceError;
548   builtins._internal->b_syntaxError = b_syntaxError;
549   builtins._internal->b_typeError = b_typeError;
550   builtins._internal->b_uriError = b_uriError;
551   
552   builtins._internal->b_evalErrorPrototype = b_evalErrorPrototype;
553   builtins._internal->b_rangeErrorPrototype = b_rangeErrorPrototype;
554   builtins._internal->b_referenceErrorPrototype = b_referenceErrorPrototype;
555   builtins._internal->b_syntaxErrorPrototype = b_syntaxErrorPrototype;
556   builtins._internal->b_typeErrorPrototype = b_typeErrorPrototype;
557   builtins._internal->b_uriErrorPrototype = b_uriErrorPrototype;
558 }
559
560 void InterpreterImp::restoreBuiltins (const SavedBuiltins &builtins)
561 {
562   if (!builtins._internal) {
563     return;
564   }
565
566   b_Object = builtins._internal->b_Object;
567   b_Function = builtins._internal->b_Function;
568   b_Array = builtins._internal->b_Array;
569   b_Boolean = builtins._internal->b_Boolean;
570   b_String = builtins._internal->b_String;
571   b_Number = builtins._internal->b_Number;
572   b_Date = builtins._internal->b_Date;
573   b_RegExp = builtins._internal->b_RegExp;
574   b_Error = builtins._internal->b_Error;
575   
576   b_ObjectPrototype = builtins._internal->b_ObjectPrototype;
577   b_FunctionPrototype = builtins._internal->b_FunctionPrototype;
578   b_ArrayPrototype = builtins._internal->b_ArrayPrototype;
579   b_BooleanPrototype = builtins._internal->b_BooleanPrototype;
580   b_StringPrototype = builtins._internal->b_StringPrototype;
581   b_NumberPrototype = builtins._internal->b_NumberPrototype;
582   b_DatePrototype = builtins._internal->b_DatePrototype;
583   b_RegExpPrototype = builtins._internal->b_RegExpPrototype;
584   b_ErrorPrototype = builtins._internal->b_ErrorPrototype;
585   
586   b_evalError = builtins._internal->b_evalError;
587   b_rangeError = builtins._internal->b_rangeError;
588   b_referenceError = builtins._internal->b_referenceError;
589   b_syntaxError = builtins._internal->b_syntaxError;
590   b_typeError = builtins._internal->b_typeError;
591   b_uriError = builtins._internal->b_uriError;
592   
593   b_evalErrorPrototype = builtins._internal->b_evalErrorPrototype;
594   b_rangeErrorPrototype = builtins._internal->b_rangeErrorPrototype;
595   b_referenceErrorPrototype = builtins._internal->b_referenceErrorPrototype;
596   b_syntaxErrorPrototype = builtins._internal->b_syntaxErrorPrototype;
597   b_typeErrorPrototype = builtins._internal->b_typeErrorPrototype;
598   b_uriErrorPrototype = builtins._internal->b_uriErrorPrototype;
599 }
600
601 InterpreterImp *InterpreterImp::interpreterWithGlobalObject(JSObject *global)
602 {
603     return interpreterMap().get(global);
604 }
605
606
607 // ------------------------------ InternalFunctionImp --------------------------
608
609 const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
610
611 InternalFunctionImp::InternalFunctionImp()
612 {
613 }
614
615 InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto)
616   : JSObject(funcProto)
617 {
618 }
619
620 InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto, const Identifier& name)
621   : JSObject(funcProto)
622   , m_name(name)
623 {
624 }
625
626 bool InternalFunctionImp::implementsCall() const
627 {
628   return true;
629 }
630
631 bool InternalFunctionImp::implementsHasInstance() const
632 {
633   return true;
634 }
635
636 bool InternalFunctionImp::hasInstance(ExecState *exec, JSValue *value)
637 {
638   if (!value->isObject())
639     return false;
640
641   JSValue *prot = get(exec,prototypePropertyName);
642   if (!prot->isObject() && !prot->isNull()) {
643     throwError(exec, TypeError, "Invalid prototype encountered in instanceof operation.");
644     return false;
645   }
646
647   JSObject *v = static_cast<JSObject *>(value);
648   while ((v = v->prototype()->getObject())) {
649     if (v == prot)
650       return true;
651   }
652   return false;
653 }
654
655 // ------------------------------ global functions -----------------------------
656
657 double roundValue(ExecState *exec, JSValue *v)
658 {
659   double d = v->toNumber(exec);
660   double ad = fabs(d);
661   if (ad == 0 || isNaN(d) || isInf(d))
662     return d;
663   return copysign(floor(ad), d);
664 }
665
666 #ifndef NDEBUG
667 #include <stdio.h>
668 void printInfo(ExecState *exec, const char *s, JSValue *o, int lineno)
669 {
670   if (!o)
671     fprintf(stderr, "KJS: %s: (null)", s);
672   else {
673     JSValue *v = o;
674
675     UString name;
676     switch (v->type()) {
677     case UnspecifiedType:
678       name = "Unspecified";
679       break;
680     case UndefinedType:
681       name = "Undefined";
682       break;
683     case NullType:
684       name = "Null";
685       break;
686     case BooleanType:
687       name = "Boolean";
688       break;
689     case StringType:
690       name = "String";
691       break;
692     case NumberType:
693       name = "Number";
694       break;
695     case ObjectType:
696       name = static_cast<JSObject *>(v)->className();
697       if (name.isNull())
698         name = "(unknown class)";
699       break;
700     case GetterSetterType:
701       name = "GetterSetter";
702       break;
703     }
704     UString vString = v->toString(exec);
705     if ( vString.size() > 50 )
706       vString = vString.substr( 0, 50 ) + "...";
707     // Can't use two UString::ascii() in the same fprintf call
708     CString tempString( vString.cstring() );
709
710     fprintf(stderr, "KJS: %s: %s : %s (%p)",
711             s, tempString.c_str(), name.ascii(), (void*)v);
712
713     if (lineno >= 0)
714       fprintf(stderr, ", line %d\n",lineno);
715     else
716       fprintf(stderr, "\n");
717   }
718 }
719 #endif
720
721 }