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

Last change on this file since 13597 was 13597, checked in by andersca, 19 years ago

2006-03-31 Anders Carlsson <[email protected]>

Reviewed by Maciej.

Make sure the GetterSetterImp objects are marked as well.


  • kjs/internal.cpp: (KJS::GetterSetterImp::mark): Call JSCell::mark().


  • Property svn:eol-style set to native
File size: 23.3 KB
Line 
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 1999-2002 Harri Porten ([email protected])
4 * Copyright (C) 2001 Peter Kelly ([email protected])
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
51namespace KJS {
52
53#if PLATFORM(WIN_OS)
54#define copysign _copysign
55#endif
56
57// ------------------------------ StringImp ------------------------------------
58
59JSValue *StringImp::toPrimitive(ExecState *, JSType) const
60{
61 return const_cast<StringImp *>(this);
62}
63
64bool StringImp::toBoolean(ExecState *) const
65{
66 return (val.size() > 0);
67}
68
69double StringImp::toNumber(ExecState *) const
70{
71 return val.toDouble();
72}
73
74UString StringImp::toString(ExecState *) const
75{
76 return val;
77}
78
79JSObject *StringImp::toObject(ExecState *exec) const
80{
81 return new StringInstance(exec->lexicalInterpreter()->builtinStringPrototype(), val);
82}
83
84// ------------------------------ NumberImp ------------------------------------
85
86JSValue *NumberImp::toPrimitive(ExecState *, JSType) const
87{
88 return const_cast<NumberImp *>(this);
89}
90
91bool NumberImp::toBoolean(ExecState *) const
92{
93 return val < 0.0 || val > 0.0; // false for NaN
94}
95
96double NumberImp::toNumber(ExecState *) const
97{
98 return val;
99}
100
101UString 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
108JSObject *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.
117bool NumberImp::getUInt32(uint32_t& uint32) const
118{
119 uint32 = (uint32_t)val;
120 return (double)uint32 == val;
121}
122
123// --------------------------- GetterSetterImp ---------------------------------
124void 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
134JSValue *GetterSetterImp::toPrimitive(ExecState*, JSType) const
135{
136 assert(false);
137 return jsNull();
138}
139
140bool GetterSetterImp::toBoolean(ExecState*) const
141{
142 assert(false);
143 return false;
144}
145
146double GetterSetterImp::toNumber(ExecState *) const
147{
148 assert(false);
149 return 0.0;
150}
151
152UString GetterSetterImp::toString(ExecState *) const
153{
154 assert(false);
155 return UString::null();
156}
157
158JSObject *GetterSetterImp::toObject(ExecState *exec) const
159{
160 assert(false);
161 return jsNull()->toObject(exec);
162}
163
164// ------------------------------ LabelStack -----------------------------------
165
166bool 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
178bool 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
193ContextImp::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
247ContextImp::~ContextImp()
248{
249 _interpreter->setContext(_callingContext);
250}
251
252void ContextImp::mark()
253{
254 for (ContextImp *context = this; context; context = context->_callingContext) {
255 context->scope.mark();
256 }
257}
258
259// ------------------------------ InterpreterImp -------------------------------
260
261InterpreterImp* InterpreterImp::s_hook = 0L;
262
263typedef HashMap<JSObject *, InterpreterImp *> InterpreterMap;
264
265static inline InterpreterMap &interpreterMap()
266{
267 static InterpreterMap *map = new InterpreterMap;
268 return *map;
269}
270
271InterpreterImp::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
302void 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
421InterpreterImp::~InterpreterImp()
422{
423 if (dbg)
424 dbg->detach(m_interpreter);
425 clear();
426}
427
428void 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
445void 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
457bool 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
466Completion 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
519void 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
560void 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
601InterpreterImp *InterpreterImp::interpreterWithGlobalObject(JSObject *global)
602{
603 return interpreterMap().get(global);
604}
605
606
607// ------------------------------ InternalFunctionImp --------------------------
608
609const ClassInfo InternalFunctionImp::info = {"Function", 0, 0, 0};
610
611InternalFunctionImp::InternalFunctionImp()
612{
613}
614
615InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto)
616 : JSObject(funcProto)
617{
618}
619
620InternalFunctionImp::InternalFunctionImp(FunctionPrototype* funcProto, const Identifier& name)
621 : JSObject(funcProto)
622 , m_name(name)
623{
624}
625
626bool InternalFunctionImp::implementsCall() const
627{
628 return true;
629}
630
631bool InternalFunctionImp::implementsHasInstance() const
632{
633 return true;
634}
635
636bool 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
657double 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>
668void 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}
Note: See TracBrowser for help on using the repository browser.