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

Last change on this file since 13211 was 13153, checked in by darin, 19 years ago

Reviewed by Maciej.

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