Fixed passing wrong environment to function call.

git-svn-id: svn://10.0.0.236/trunk@139296 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rogerl%netscape.com 2003-03-11 23:46:09 +00:00
parent 7307191534
commit d9a6dcdb17
10 changed files with 169 additions and 148 deletions

View File

@ -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<PrototypeInstance *>(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<SimpleInstance *>(obj)->type->getName());
break;
default:
ASSERT(false);
break;
}
}
}
return a;
}
//
// XXX Only scanning dynamic properties

View File

@ -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.

View File

@ -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);

View File

@ -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;

View File

@ -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<FunctionInstance *>(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;

View File

@ -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);

View File

@ -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<InvokeExprNode *>(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();

View File

@ -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<Frame *> 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<SystemFrame *>(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<Frame *> 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<SystemFrame *>(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<Namespace *> NamespaceList;
typedef NamespaceList::iterator NamespaceListIterator;

View File

@ -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);

View File

@ -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<PrototypeInstance *>(fObj))->type == meta->functionClass)) {
fWrap = (checked_cast<FunctionInstance *>(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<PrototypeInstance *>(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<SimpleInstance *>(obj)->type->getName());
break;
}
}
}
push(a);
push(typeofString(a));
}
break;