diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index 55ac87def94..2153317c260 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -64,9 +64,9 @@ namespace JavaScript { namespace MetaData { // Begin execution of a bytecodeContainer - js2val JS2Engine::interpret(Phase execPhase, BytecodeContainer *targetbCon) + js2val JS2Engine::interpret(Phase execPhase, BytecodeContainer *targetbCon, Environment *env) { - jsr(execPhase, targetbCon, sp - execStack, JS2VAL_VOID); + jsr(execPhase, targetbCon, sp - execStack, JS2VAL_VOID, env); ActivationFrame *f = activationStackTop; js2val result; try { @@ -218,6 +218,14 @@ namespace MetaData { return new (p) String(*s); } + String *JS2Engine::concatStrings(const String *s1, const String *s2) + { + String *p = (String *)(JS2Object::alloc(sizeof(String))); + String *result = new (p) String(*s1); + result->append(*s2); + return result; + } + // if the argument can be stored as an integer value, do so // otherwise get a double value js2val JS2Engine::allocNumber(float64 x) @@ -830,15 +838,16 @@ namespace MetaData { // Save current engine state (pc, environment top) and // jump to start of new bytecodeContainer - void JS2Engine::jsr(Phase execPhase, BytecodeContainer *new_bCon, uint32 stackBase, js2val returnVal) + void JS2Engine::jsr(Phase execPhase, BytecodeContainer *new_bCon, uint32 stackBase, js2val returnVal, Environment *env) { ASSERT(activationStackTop < (activationStack + MAX_ACTIVATION_STACK)); activationStackTop->bCon = bCon; activationStackTop->pc = pc; activationStackTop->phase = phase; - activationStackTop->topFrame = meta->env->getTopFrame(); +// activationStackTop->topFrame = meta->env->getTopFrame(); activationStackTop->execStackBase = stackBase; activationStackTop->retval = returnVal; + activationStackTop->env = meta->env; activationStackTop++; bCon = new_bCon; if ((int32)bCon->getMaxStack() >= (execStackLimit - sp)) { @@ -852,7 +861,7 @@ namespace MetaData { } pc = new_bCon->getCodeStart(); phase = execPhase; - + meta->env = env; } // Return to previously saved execution state @@ -864,8 +873,9 @@ namespace MetaData { bCon = activationStackTop->bCon; pc = activationStackTop->pc; phase = activationStackTop->phase; - while (meta->env->getTopFrame() != activationStackTop->topFrame) - meta->env->removeTopFrame(); + meta->env = activationStackTop->env; +// while (meta->env->getTopFrame() != activationStackTop->topFrame) +// meta->env->removeTopFrame(); sp = execStack + activationStackTop->execStackBase; if (!JS2VAL_IS_VOID(activationStackTop->retval)) // XXX might need an actual 'returnValue' flag instead retval = activationStackTop->retval; @@ -878,7 +888,7 @@ namespace MetaData { if (bCon) bCon->mark(); for (ActivationFrame *f = activationStack; (f < activationStackTop); f++) { - GCMARKOBJECT(f->topFrame); + GCMARKOBJECT(f->env); if (f->bCon) f->bCon->mark(); } @@ -929,6 +939,57 @@ namespace MetaData { delete hndlr; } + js2val JS2Engine::typeofString(js2val a) + { + if (JS2VAL_IS_UNDEFINED(a)) + a = STRING_TO_JS2VAL(undefined_StringAtom); + else + if (JS2VAL_IS_BOOLEAN(a)) + a = allocString("boolean"); + else + if (JS2VAL_IS_NUMBER(a)) + a = allocString("number"); + else + if (JS2VAL_IS_STRING(a)) + a = allocString("string"); + else { + ASSERT(JS2VAL_IS_OBJECT(a)); + if (JS2VAL_IS_NULL(a)) + a = STRING_TO_JS2VAL(object_StringAtom); + else { + JS2Object *obj = JS2VAL_TO_OBJECT(a); + switch (obj->kind) { + case MultinameKind: + a = allocString("namespace"); + break; + case AttributeObjectKind: + a = allocString("attribute"); + break; + case ClassKind: + case MethodClosureKind: + a = STRING_TO_JS2VAL(Function_StringAtom); + break; + case PrototypeInstanceKind: + if (checked_cast(obj)->type == meta->functionClass) + a = STRING_TO_JS2VAL(Function_StringAtom); + else + a = STRING_TO_JS2VAL(object_StringAtom); + break; + case PackageKind: + case GlobalObjectKind: + a = STRING_TO_JS2VAL(object_StringAtom); + break; + case SimpleInstanceKind: + a = STRING_TO_JS2VAL(checked_cast(obj)->type->getName()); + break; + default: + ASSERT(false); + break; + } + } + } + return a; + } // // XXX Only scanning dynamic properties diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index 504eb873fdb..5fb6bce4f90 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -163,8 +163,8 @@ enum JS2Op { class Frame; - class ParameterFrame; +class Environment; class JS2Object; class JS2Metadata; @@ -179,7 +179,7 @@ public: JS2Engine(World &world); - js2val interpret(Phase execPhase, BytecodeContainer *targetbCon); + js2val interpret(Phase execPhase, BytecodeContainer *targetbCon, Environment *env); js2val interpreterLoop(); // Use the pc map in the current bytecode container to get a source offset @@ -211,6 +211,7 @@ public: js2val allocString(const char *s) { return STRING_TO_JS2VAL(allocStringPtr(s)); } String *allocStringPtr(const String *s); String *allocStringPtr(const char *s); + String *concatStrings(const String *s1, const String *s2); String *numberToString(float64 *number); // non-static since they need access to meta String *numberToString(int32 i); @@ -266,17 +267,18 @@ public: struct ActivationFrame { uint8 *pc; BytecodeContainer *bCon; - Frame *topFrame; Phase phase; js2val retval; uint32 execStackBase; + Environment *env; }; - void jsr(Phase execPhase, BytecodeContainer *bCon, uint32 stackBase, js2val returnVal); + void jsr(Phase execPhase, BytecodeContainer *bCon, uint32 stackBase, js2val returnVal, Environment *env); bool activationStackEmpty() { return (activationStackTop == activationStack); } void rts(); ActivationFrame *activationStack; ActivationFrame *activationStackTop; + js2val typeofString(js2val a); // The execution stack for expression evaluation, should be empty // between statements. diff --git a/mozilla/js2/src/js2error.cpp b/mozilla/js2/src/js2error.cpp index c545d5459b4..90d09306261 100644 --- a/mozilla/js2/src/js2error.cpp +++ b/mozilla/js2/src/js2error.cpp @@ -153,7 +153,7 @@ void initErrorObject(JS2Metadata *meta) PrototypeFunction *pf = &errorProtos[0]; while (pf->name) { SimpleInstance *fInst = new SimpleInstance(meta->functionClass); - fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code); + fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code, meta->env); InstanceMember *m = new InstanceMethod(fInst); meta->defineInstanceMember(meta->errorClass, &meta->cxt, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0); diff --git a/mozilla/js2/src/js2eval.cpp b/mozilla/js2/src/js2eval.cpp index 6b01520d5d3..b10dd6f7cf2 100644 --- a/mozilla/js2/src/js2eval.cpp +++ b/mozilla/js2/src/js2eval.cpp @@ -149,7 +149,7 @@ namespace MetaData { bCon->emitOp(eReturnVoid, lastPos); uint8 *savePC = engine->pc; engine->pc = NULL; - js2val retval = engine->interpret(phase, bCon); + js2val retval = engine->interpret(phase, bCon, env); engine->pc = savePC; return retval; } @@ -170,7 +170,7 @@ namespace MetaData { bCon->emitOp(eReturn, p->pos); savePC = engine->pc; engine->pc = NULL; - retval = engine->interpret(phase, bCon); + retval = engine->interpret(phase, bCon, env); } catch (Exception &x) { engine->pc = savePC; @@ -282,7 +282,7 @@ namespace MetaData { bCon->emitOp(eReturn, 0); savePC = engine->pc; engine->pc = NULL; - retval = engine->interpret(RunPhase, bCon); + retval = engine->interpret(RunPhase, bCon, env); } catch (Exception &x) { engine->pc = savePC; @@ -333,7 +333,7 @@ namespace MetaData { try { savePC = engine->pc; engine->pc = NULL; - result = engine->interpret(RunPhase, bCon); + result = engine->interpret(RunPhase, bCon, env); } catch (Exception &x) { engine->pc = savePC; diff --git a/mozilla/js2/src/js2function.cpp b/mozilla/js2/src/js2function.cpp index 923f62f1404..f16aa1d0556 100644 --- a/mozilla/js2/src/js2function.cpp +++ b/mozilla/js2/src/js2function.cpp @@ -85,7 +85,7 @@ namespace MetaData { else { // construct an empty function wrapper js2val thatValue = OBJECT_TO_JS2VAL(new FunctionInstance(meta, meta->functionClass->prototype, meta->functionClass)); FunctionInstance *fnInst = checked_cast(JS2VAL_TO_OBJECT(thatValue)); - fnInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true)); + fnInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), meta->env); fnInst->fWrap->bCon->emitOp(eReturnVoid, meta->engine->errorPos()); fnInst->writeProperty(meta, meta->engine->length_StringAtom, INT_TO_JS2VAL(0), DynamicPropertyValue::READONLY); return thatValue; diff --git a/mozilla/js2/src/js2math.cpp b/mozilla/js2/src/js2math.cpp index 359b54768ab..c5640ac0903 100644 --- a/mozilla/js2/src/js2math.cpp +++ b/mozilla/js2/src/js2math.cpp @@ -341,7 +341,7 @@ void initMathObject(JS2Metadata *meta) FunctionData *pf = &prototypeFunctions[0]; while (pf->name) { SimpleInstance *callInst = new SimpleInstance(meta->functionClass); - callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code); + callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code, meta->env); Variable *v = new Variable(meta->functionClass, OBJECT_TO_JS2VAL(callInst), true); meta->defineLocalMember(meta->env, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index c0fe2dcd326..37b6dcc69f9 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -92,13 +92,13 @@ namespace MetaData { if (prototype) { FunctionInstance *fInst = new FunctionInstance(this, functionClass->prototype, functionClass); - fInst->fWrap = new FunctionWrapper(unchecked, compileFrame); + fInst->fWrap = new FunctionWrapper(unchecked, compileFrame, env); fnDef->fWrap = fInst->fWrap; result = fInst; } else { SimpleInstance *sInst = new SimpleInstance(functionClass); - sInst->fWrap = new FunctionWrapper(unchecked, compileFrame); + sInst->fWrap = new FunctionWrapper(unchecked, compileFrame, env); fnDef->fWrap = sInst->fWrap; result = sInst; } @@ -2272,7 +2272,12 @@ doUnary: { InvokeExprNode *i = checked_cast(p); Reference *rVal = SetupExprNode(env, phase, i->op, exprType); - if (rVal) rVal->emitReadForInvokeBytecode(bCon, p->pos); + if (rVal) + rVal->emitReadForInvokeBytecode(bCon, p->pos); + else /* a call doesn't have to have an lValue to execute on, + * but we use the value as it's own 'this' in that case. + */ + bCon->emitOp(eDup, p->pos); ExprPairList *args = i->pairs; uint16 argCount = 0; while (args) { @@ -3162,7 +3167,7 @@ static const uint8 urlCharType[256] = void JS2Metadata::addGlobalObjectFunction(char *name, NativeCode *code, uint32 length) { SimpleInstance *fInst = new SimpleInstance(functionClass); - fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), code); + fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), code, env); writeDynamicProperty(glob, new Multiname(&world.identifiers[name], publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase); fInst->writeProperty(this, engine->length_StringAtom, INT_TO_JS2VAL(length), DynamicPropertyValue::READONLY); } @@ -3284,7 +3289,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... // Adding 'toString' to the Object.prototype XXX Or make this a static class member? FunctionInstance *fInst = new FunctionInstance(this, functionClass->prototype, functionClass); - fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Object_toString); + fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_VOID, true), Object_toString, env); objectClass->prototype->writeProperty(this, engine->toString_StringAtom, OBJECT_TO_JS2VAL(fInst), 0); fInst->writeProperty(this, engine->length_StringAtom, INT_TO_JS2VAL(0), DynamicPropertyValue::READONLY); @@ -4331,7 +4336,7 @@ deleteClassProperty: if (pf) { while (pf->name) { SimpleInstance *callInst = new SimpleInstance(functionClass); - callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code); + callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code, env); v = new Variable(functionClass, OBJECT_TO_JS2VAL(callInst), true); defineLocalMember(env, &world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); writeDynamicProperty(callInst, new Multiname(engine->length_StringAtom, publicNamespace), true, INT_TO_JS2VAL(pf->length), RunPhase); @@ -4344,14 +4349,14 @@ deleteClassProperty: // Add "constructor" as a dynamic property of the prototype FunctionInstance *fInst = new FunctionInstance(this, functionClass->prototype, functionClass); writeDynamicProperty(fInst, new Multiname(engine->length_StringAtom, publicNamespace), true, INT_TO_JS2VAL(1), RunPhase); - fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), construct); + fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), construct, env); writeDynamicProperty(builtinClass->prototype, new Multiname(&world.identifiers["constructor"], publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase); pf = protoFunctions; if (pf) { while (pf->name) { SimpleInstance *callInst = new SimpleInstance(functionClass); - callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code); + callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code, env); /* XXX not prototype object function properties, like ECMA3 writeDynamicProperty(dateClass->prototype, new Multiname(world.identifiers[pf->name], publicNamespace), true, OBJECT_TO_JS2VAL(fInst), RunPhase); @@ -4486,6 +4491,7 @@ deleteClassProperty: GCMARKOBJECT(type) if (fWrap) { GCMARKOBJECT(fWrap->compileFrame); + GCMARKOBJECT(fWrap->env); if (fWrap->bCon) fWrap->bCon->mark(); } @@ -4580,6 +4586,7 @@ deleteClassProperty: { PrototypeInstance::markChildren(); if (fWrap) { + GCMARKOBJECT(fWrap->env); GCMARKOBJECT(fWrap->compileFrame); if (fWrap->bCon) fWrap->bCon->mark(); diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index 834e2733fbb..f722c15e4bd 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -163,7 +163,7 @@ public: Pond *nextPond; }; -#define GCMARKOBJECT(n) if ((n) && !(n)->isMarked()) { (n)->mark(); (n)->markChildren(); } +#define GCMARKOBJECT(n) if ((n) && !(n)->isMarked()) { (n)->markObject(); (n)->markChildren(); } #define GCMARKVALUE(v) JS2Object::markJS2Value(v) class JS2Object { @@ -193,7 +193,7 @@ public: virtual void markChildren() { } bool isMarked() { return ((PondScum *)this)[-1].isMarked(); } - void mark() { ((PondScum *)this)[-1].mark(); } + void markObject() { ((PondScum *)this)[-1].mark(); } static void mark(const void *p) { ((PondScum *)p)[-1].mark(); } static void markJS2Value(js2val v); @@ -496,6 +496,16 @@ public: }; +class WithFrame : public Frame { +public: + WithFrame(JS2Object *b) : Frame(WithFrameKind), obj(b) { } + virtual ~WithFrame() { } + + virtual void markChildren() { GCMARKOBJECT(obj); } + + JS2Object *obj; +}; + class NonWithFrame : public Frame { public: @@ -516,16 +526,57 @@ public: virtual ~NonWithFrame() { } }; -class WithFrame : public Frame { +// The top-level frame containing predefined constants, functions, and classes. +class SystemFrame : public NonWithFrame { public: - WithFrame(JS2Object *b) : Frame(WithFrameKind), obj(b) { } - virtual ~WithFrame() { } - - virtual void markChildren() { GCMARKOBJECT(obj); } - - JS2Object *obj; + SystemFrame() : NonWithFrame(SystemKind) { } + virtual ~SystemFrame() { } }; + +// Environments contain the bindings that are visible from a given point in the source code. An ENVIRONMENT is +// a list of two or more frames. Each frame corresponds to a scope. More specific frames are listed first +// -each frame's scope is directly contained in the following frame's scope. The last frame is always the +// SYSTEMFRAME. The next-to-last frame is always a PACKAGE or GLOBAL frame. +typedef std::deque FrameList; +typedef FrameList::iterator FrameListIterator; + +// Deriving from JS2Object for gc sake only +class Environment : public JS2Object { +public: + Environment(SystemFrame *systemFrame, Frame *nextToLast) : JS2Object(EnvironmentKind) { frameList.push_back(nextToLast); frameList.push_back(systemFrame); } + virtual ~Environment() { } + + Environment(Environment *e) : JS2Object(EnvironmentKind), frameList(e->frameList) { } + + JS2Class *getEnclosingClass(); + FrameListIterator getRegionalFrame(); + Frame *getTopFrame() { return frameList.front(); } + FrameListIterator getBegin() { return frameList.begin(); } + FrameListIterator getEnd() { return frameList.end(); } + Frame *getPackageOrGlobalFrame(); + SystemFrame *getSystemFrame() { return checked_cast(frameList.back()); } + + void setTopFrame(Frame *f) { while (frameList.front() != f) frameList.pop_front(); } + + void addFrame(Frame *f) { frameList.push_front(f); } + void removeTopFrame() { frameList.pop_front(); } + + js2val findThis(bool allowPrototypeThis); + js2val lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase); + void lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing, Phase phase); + void lexicalInit(JS2Metadata *meta, Multiname *multiname, js2val newValue); + bool lexicalDelete(JS2Metadata *meta, Multiname *multiname, Phase phase); + + void instantiateFrame(NonWithFrame *pluralFrame, NonWithFrame *singularFrame); + + void markChildren(); + +private: + FrameList frameList; +}; + + class JS2Class : public NonWithFrame { public: JS2Class(JS2Class *super, JS2Object *proto, Namespace *privateNamespace, bool dynamic, bool allowNull, bool final, const String *name); @@ -591,15 +642,16 @@ class ParameterFrame; class FunctionWrapper { public: - FunctionWrapper(bool unchecked, ParameterFrame *compileFrame) - : bCon(new BytecodeContainer()), code(NULL), unchecked(unchecked), compileFrame(compileFrame) { } - FunctionWrapper(bool unchecked, ParameterFrame *compileFrame, NativeCode *code) - : bCon(NULL), code(code), unchecked(unchecked), compileFrame(compileFrame) { } + FunctionWrapper(bool unchecked, ParameterFrame *compileFrame, Environment *env) + : bCon(new BytecodeContainer()), code(NULL), unchecked(unchecked), compileFrame(compileFrame), env(new Environment(env)) { } + FunctionWrapper(bool unchecked, ParameterFrame *compileFrame, NativeCode *code, Environment *env) + : bCon(NULL), code(code), unchecked(unchecked), compileFrame(compileFrame), env(new Environment(env)) { } BytecodeContainer *bCon; NativeCode *code; bool unchecked; // true if the function is untyped, non-method, normal ParameterFrame *compileFrame; + Environment *env; }; @@ -930,13 +982,6 @@ public: }; -// The top-level frame containing predefined constants, functions, and classes. -class SystemFrame : public NonWithFrame { -public: - SystemFrame() : NonWithFrame(SystemKind) { } - virtual ~SystemFrame() { } -}; - // Frames holding bindings for invoked functions class ParameterFrame : public NonWithFrame { public: @@ -981,46 +1026,6 @@ public: js2val thisObject; }; -// Environments contain the bindings that are visible from a given point in the source code. An ENVIRONMENT is -// a list of two or more frames. Each frame corresponds to a scope. More specific frames are listed first -// -each frame's scope is directly contained in the following frame's scope. The last frame is always the -// SYSTEMFRAME. The next-to-last frame is always a PACKAGE or GLOBAL frame. -typedef std::deque FrameList; -typedef FrameList::iterator FrameListIterator; - -// Deriving from JS2Object for gc sake only, these are supposed to be found as JS2 values -class Environment : public JS2Object { -public: - Environment(SystemFrame *systemFrame, Frame *nextToLast) : JS2Object(EnvironmentKind) { frameList.push_back(nextToLast); frameList.push_back(systemFrame); } - virtual ~Environment() { } - - JS2Class *getEnclosingClass(); - FrameListIterator getRegionalFrame(); - Frame *getTopFrame() { return frameList.front(); } - FrameListIterator getBegin() { return frameList.begin(); } - FrameListIterator getEnd() { return frameList.end(); } - Frame *getPackageOrGlobalFrame(); - SystemFrame *getSystemFrame() { return checked_cast(frameList.back()); } - - void setTopFrame(Frame *f) { while (frameList.front() != f) frameList.pop_front(); } - - void addFrame(Frame *f) { frameList.push_front(f); } - void removeTopFrame() { frameList.pop_front(); } - - js2val findThis(bool allowPrototypeThis); - js2val lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase); - void lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing, Phase phase); - void lexicalInit(JS2Metadata *meta, Multiname *multiname, js2val newValue); - bool lexicalDelete(JS2Metadata *meta, Multiname *multiname, Phase phase); - - void instantiateFrame(NonWithFrame *pluralFrame, NonWithFrame *singularFrame); - - void markChildren(); - -private: - FrameList frameList; -}; - typedef std::vector NamespaceList; typedef NamespaceList::iterator NamespaceListIterator; diff --git a/mozilla/js2/src/js2op_arithmetic.cpp b/mozilla/js2/src/js2op_arithmetic.cpp index bcd23418c6a..13f9a47fadf 100644 --- a/mozilla/js2/src/js2op_arithmetic.cpp +++ b/mozilla/js2/src/js2op_arithmetic.cpp @@ -334,11 +334,7 @@ if (JS2VAL_IS_STRING(a) || JS2VAL_IS_STRING(b)) { const String *astr = meta->toString(a); const String *bstr = meta->toString(b); - - String c = *astr; - - c += *bstr; - push(STRING_TO_JS2VAL(allocStringPtr(&c))); + push(STRING_TO_JS2VAL(concatStrings(astr, bstr))); } else { a = meta->toGeneralNumber(a); diff --git a/mozilla/js2/src/js2op_invocation.cpp b/mozilla/js2/src/js2op_invocation.cpp index 82e69c6014d..628a4f13bb4 100644 --- a/mozilla/js2/src/js2op_invocation.cpp +++ b/mozilla/js2/src/js2op_invocation.cpp @@ -92,7 +92,7 @@ baseVal = OBJECT_TO_JS2VAL(pInst); pFrame->thisObject = baseVal; pFrame->assignArguments(meta, obj, base(argCount), argCount); - jsr(phase, fWrap->bCon, base(argCount + 1) - execStack, baseVal); // seems out of order, but we need to catch the current top frame + jsr(phase, fWrap->bCon, base(argCount + 1) - execStack, baseVal, fWrap->env); // seems out of order, but we need to catch the current top frame meta->env->addFrame(pFrame); pFrame = NULL; } @@ -114,9 +114,8 @@ pc += sizeof(uint16); a = top(argCount + 2); // 'this' b = top(argCount + 1); // target function -// uint32 length = 0; if (JS2VAL_IS_PRIMITIVE(b)) - meta->reportError(Exception::badValueError, "Can't call on primitive value", errorPos()); + meta->reportError(Exception::badValueError, "{0} is not a function", errorPos(), JS2VAL_TO_STRING(typeofString(b))); JS2Object *fObj = JS2VAL_TO_OBJECT(b); FunctionWrapper *fWrap = NULL; if ((fObj->kind == SimpleInstanceKind) @@ -127,7 +126,6 @@ if ((fObj->kind == PrototypeInstanceKind) && ((checked_cast(fObj))->type == meta->functionClass)) { fWrap = (checked_cast(fObj))->fWrap; -// length = getLength(meta, fObj); } if (fWrap) { if (fWrap->compileFrame->prototype) { @@ -138,10 +136,6 @@ } } if (fWrap->code) { // native code -// while (length > argCount) { -// push(JS2VAL_UNDEFINED); -// argCount++; -// } a = fWrap->code(meta, a, base(argCount), argCount); pop(argCount + 2); push(a); @@ -153,7 +147,7 @@ // assignArguments(runtimeFrame, fWrap->compileFrame->signature); // XXX pFrame->assignArguments(meta, fObj, base(argCount), argCount); - jsr(phase, fWrap->bCon, base(argCount + 2) - execStack, JS2VAL_VOID); // seems out of order, but we need to catch the current top frame + jsr(phase, fWrap->bCon, base(argCount + 2) - execStack, JS2VAL_VOID, fWrap->env); // seems out of order, but we need to catch the current top frame meta->env->addFrame(pFrame); pFrame = NULL; } @@ -175,7 +169,7 @@ pFrame->thisObject = mc->thisObject; // assignArguments(runtimeFrame, fWrap->compileFrame->signature); pFrame->assignArguments(meta, fObj, base(argCount), argCount); - jsr(phase, fWrap->bCon, base(argCount + 2) - execStack, JS2VAL_VOID); // seems out of order, but we need to catch the current top frame + jsr(phase, fWrap->bCon, base(argCount + 2) - execStack, JS2VAL_VOID, fWrap->env); // seems out of order, but we need to catch the current top frame meta->env->addFrame(meta->objectType(mc->thisObject)); meta->env->addFrame(pFrame); pFrame = NULL; @@ -192,7 +186,7 @@ push(a); } else - meta->reportError(Exception::badValueError, "Un-callable object", errorPos()); + meta->reportError(Exception::badValueError, "{0} is not a function", errorPos(), JS2VAL_TO_STRING(typeofString(b))); } break; @@ -340,51 +334,7 @@ case eTypeof: { a = pop(); - if (JS2VAL_IS_UNDEFINED(a)) - a = STRING_TO_JS2VAL(undefined_StringAtom); - else - if (JS2VAL_IS_BOOLEAN(a)) - a = allocString("boolean"); - else - if (JS2VAL_IS_NUMBER(a)) - a = allocString("number"); - else - if (JS2VAL_IS_STRING(a)) - a = allocString("string"); - else { - ASSERT(JS2VAL_IS_OBJECT(a)); - if (JS2VAL_IS_NULL(a)) - a = STRING_TO_JS2VAL(object_StringAtom); - else { - JS2Object *obj = JS2VAL_TO_OBJECT(a); - switch (obj->kind) { - case MultinameKind: - a = allocString("namespace"); - break; - case AttributeObjectKind: - a = allocString("attribute"); - break; - case ClassKind: - case MethodClosureKind: - a = STRING_TO_JS2VAL(Function_StringAtom); - break; - case PrototypeInstanceKind: - if (checked_cast(obj)->type == meta->functionClass) - a = STRING_TO_JS2VAL(Function_StringAtom); - else - a = STRING_TO_JS2VAL(object_StringAtom); - break; - case PackageKind: - case GlobalObjectKind: - a = STRING_TO_JS2VAL(object_StringAtom); - break; - case SimpleInstanceKind: - a = STRING_TO_JS2VAL(checked_cast(obj)->type->getName()); - break; - } - } - } - push(a); + push(typeofString(a)); } break;