SuperConstructor call sequence.

git-svn-id: svn://10.0.0.236/trunk@142196 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rogerl%netscape.com 2003-05-08 07:07:55 +00:00
parent 832cb868ca
commit 8db2da07db
8 changed files with 54 additions and 27 deletions

View File

@ -58,6 +58,9 @@ static const char *const kindStrings[] = {
"Property access error", // you're at the wrong house
"Uninitialized error", // read before write
"Argument mismatch error", // bad argument type/number
"Attribute error", // illegal attribute error
"Constant error", // it just won't go away
"Arguments error" // an error in the arguments
};
// Return a null-terminated string describing the exception's kind.

View File

@ -65,7 +65,9 @@ namespace JavaScript
propertyAccessError,
uninitializedError,
argumentMismatchError,
attributeError
attributeError,
constantError,
argumentsError
};
Kind kind; // The exception's kind

View File

@ -549,7 +549,7 @@ static int32 sort_compare(js2val *a, js2val *b, CompareArgs *arg)
js2val argv[2];
argv[0] = av;
argv[1] = bv;
js2val v = meta->invokeFunction(ca->target, JS2VAL_NULL, argv, 2);
js2val v = meta->invokeFunction(ca->target, JS2VAL_NULL, argv, 2, NULL);
float64 f = meta->toFloat64(v);
if (JSDOUBLE_IS_NaN(f) || (f == 0))
result = 0;

View File

@ -961,15 +961,17 @@ namespace MetaData {
// XXX Default construction of an instance of the class
// that is the value of the passed in 'this'
js2val JS2Engine::defaultConstructor(JS2Metadata *meta, const js2val thisValue, js2val /* argv */ [], uint32 /* argc */)
js2val JS2Engine::defaultConstructor(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
{
ASSERT(JS2VAL_IS_OBJECT(thisValue) && !JS2VAL_IS_NULL(thisValue));
JS2Object *obj = JS2VAL_TO_OBJECT(thisValue);
ASSERT(obj->kind == ClassKind);
JS2Class *c = checked_cast<JS2Class *>(obj);
if (!c->complete)
meta->reportError(Exception::constantError, "Cannot construct an instance of a class before its definition has been compiled", meta->engine->errorPos());
SimpleInstance *result = new SimpleInstance(meta, c->prototype, c);
DEFINE_ROOTKEEPER(rk, result);
meta->invokeInit(c, OBJECT_TO_JS2VAL(result), NULL, 0);
meta->invokeInit(c, OBJECT_TO_JS2VAL(result), argv, argc);
return OBJECT_TO_JS2VAL(result);
}

View File

@ -231,7 +231,7 @@ namespace MetaData {
JS2Object *fnObj = JS2VAL_TO_OBJECT(fnVal);
if ((fnObj->kind == SimpleInstanceKind)
&& ((checked_cast<SimpleInstance *>(fnObj))->type == functionClass)) {
result = invokeFunction(fnObj, thisValue, NULL, 0);
result = invokeFunction(fnObj, thisValue, NULL, 0, NULL);
return true;
}
}
@ -268,16 +268,29 @@ namespace MetaData {
return retval;
}
// Invoke the constructor function for a class, calling the super constructor as necessary
// Invoke the constructor function for a class
void JS2Metadata::invokeInit(JS2Class *c, js2val thisValue, js2val *argv, uint32 argc)
{
if (c->init) {
invokeFunction(c->init, thisValue, argv, argc);
FunctionInstance *init = NULL;
if (c) init = c->init;
if (init) {
ParameterFrame *runtimeFrame;
DEFINE_ROOTKEEPER(rk, runtimeFrame);
runtimeFrame = new ParameterFrame(init->fWrap->compileFrame);
if (!init->fWrap->compileFrame->callsSuperConstructor) {
invokeInit(c->super, thisValue, NULL, 0);
runtimeFrame->superConstructorCalled = true;
}
invokeFunction(init, thisValue, argv, argc, runtimeFrame);
if (!runtimeFrame->superConstructorCalled)
reportError(Exception::uninitializedError, "The superconstuctor must be called before returning normally from a constructor", engine->errorPos());
}
else
if (argc)
reportError(Exception::argumentsError, "The default constructor does not take any arguments", engine->errorPos());
}
js2val JS2Metadata::invokeFunction(JS2Object *fnObj, js2val thisValue, js2val *argv, uint32 argc)
js2val JS2Metadata::invokeFunction(JS2Object *fnObj, js2val thisValue, js2val *argv, uint32 argc, ParameterFrame *runtimeFrame)
{
js2val result = JS2VAL_UNDEFINED;
@ -297,8 +310,9 @@ namespace MetaData {
BytecodeContainer *bCon = fWrap->bCon;
CompilationData *oldData = startCompilationUnit(bCon, bCon->mSource, bCon->mSourceLocation);
ParameterFrame *runtimeFrame = new ParameterFrame(fWrap->compileFrame);
DEFINE_ROOTKEEPER(rk, runtimeFrame);
if (runtimeFrame == NULL)
runtimeFrame = new ParameterFrame(fWrap->compileFrame);
runtimeFrame->instantiate(fWrap->env);
runtimeFrame->thisObject = thisValue;
runtimeFrame->assignArguments(this, fnObj, argv, argc, argc);

View File

@ -85,7 +85,7 @@ namespace MetaData {
}
}
FunctionInstance *JS2Metadata::validateStaticFunction(Context *cxt, Environment *env, FunctionDefinition *fnDef, bool prototype, bool unchecked, size_t pos)
FunctionInstance *JS2Metadata::validateStaticFunction(Context *cxt, Environment *env, FunctionDefinition *fnDef, bool prototype, bool unchecked, bool isConstructor, size_t pos)
{
js2val compileThis = JS2VAL_VOID;
ParameterFrame *compileFrame = new ParameterFrame(compileThis, prototype);
@ -116,6 +116,7 @@ namespace MetaData {
}
createDynamicProperty(result, engine->length_StringAtom, INT_TO_JS2VAL(pCount), ReadAccess, true, false);
result->fWrap->length = pCount;
compileFrame->isConstructor = isConstructor;
ValidateStmt(cxt, env, Plural, fnDef->body);
env->removeTopFrame();
}
@ -134,7 +135,7 @@ namespace MetaData {
DEFINE_ROOTKEEPER(rk1, fnInst);
switch (fnDef->prefix) {
case FunctionName::normal:
fnInst = validateStaticFunction(cxt, env, fnDef, a->prototype, unchecked, pos);
fnInst = validateStaticFunction(cxt, env, fnDef, a->prototype, unchecked, false, pos);
if (hoisted)
defineHoistedVar(env, fnDef->name, OBJECT_TO_JS2VAL(fnInst), false, pos);
else {
@ -148,7 +149,7 @@ namespace MetaData {
reportError(Exception::attributeError, "A getter cannot have the prototype attribute", pos);
ASSERT(!(unchecked || hoisted));
// XXX shouldn't be using validateStaticFunction
fnInst = validateStaticFunction(cxt, env, fnDef, false, false, pos);
fnInst = validateStaticFunction(cxt, env, fnDef, false, false, false, pos);
Getter *g = new Getter(fnInst);
defineLocalMember(env, fnDef->name, &a->namespaces, a->overrideMod, a->xplicit, ReadAccess, g, pos, true);
}
@ -159,7 +160,7 @@ namespace MetaData {
reportError(Exception::attributeError, "A setter cannot have the prototype attribute", pos);
ASSERT(!(unchecked || hoisted));
// XXX shouldn't be using validateStaticFunction
fnInst = validateStaticFunction(cxt, env, fnDef, false, false, pos);
fnInst = validateStaticFunction(cxt, env, fnDef, false, false, false, pos);
Setter *s = new Setter(fnInst);
defineLocalMember(env, fnDef->name, &a->namespaces, a->overrideMod, a->xplicit, WriteAccess, s, pos, true);
}
@ -174,8 +175,7 @@ namespace MetaData {
if (fnDef->prefix != FunctionName::normal)
reportError(Exception::syntaxError, "A class constructor cannot be a getter or a setter", pos);
// XXX shouldn't be using validateStaticFunction
c->init = validateStaticFunction(cxt, env, fnDef, false, false, pos);
c->init->fWrap->compileFrame->isConstructor = true;
c->init = validateStaticFunction(cxt, env, fnDef, false, false, true, pos);
}
void JS2Metadata::validateInstance(Context *cxt, Environment *env, FunctionDefinition *fnDef, JS2Class *c, CompoundAttribute *a, bool final, size_t pos)
@ -185,7 +185,7 @@ namespace MetaData {
// XXX shouldn't be using validateStaticFunction
FunctionInstance *fnInst = NULL;
DEFINE_ROOTKEEPER(rk1, fnInst);
fnInst = validateStaticFunction(cxt, env, fnDef, false, false, pos);
fnInst = validateStaticFunction(cxt, env, fnDef, false, false, false, pos);
Multiname *mn = new Multiname(fnDef->name, a->namespaces);
InstanceMember *m;
switch (fnDef->prefix) {
@ -695,6 +695,8 @@ namespace MetaData {
ASSERT(env->getTopFrame() == c);
env->removeTopFrame();
}
if (c->init == NULL)
c->init = superClass->init;
c->complete = true;
}
break;
@ -1421,7 +1423,9 @@ namespace MetaData {
ExprStmtNode *e = checked_cast<ExprStmtNode *>(p);
Reference *r = SetupExprNode(env, phase, e->expr, &exprType);
if (r) r->emitReadBytecode(bCon, p->pos);
bCon->emitOp(ePopv, p->pos);
// superStmt expressions don't produce any result value
if (e->expr->getKind() != ExprNode::superStmt)
bCon->emitOp(ePopv, p->pos);
}
break;
case StmtNode::Namespace:
@ -1912,7 +1916,7 @@ namespace MetaData {
case ExprNode::functionLiteral:
{
FunctionExprNode *f = checked_cast<FunctionExprNode *>(p);
f->obj = validateStaticFunction(cxt, env, &f->function, true, true, p->pos);
f->obj = validateStaticFunction(cxt, env, &f->function, true, true, false, p->pos);
}
break;
case ExprNode::superStmt:
@ -1922,7 +1926,6 @@ namespace MetaData {
reportError(Exception::syntaxError, "A super statement is meaningful only inside a constructor", p->pos);
InvokeExprNode *i = checked_cast<InvokeExprNode *>(p);
ValidateExpression(cxt, env, i->op);
ExprPairList *args = i->pairs;
while (args) {
ValidateExpression(cxt, env, args->value);
@ -4161,7 +4164,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
case Member::InstanceGetterMember:
{
InstanceGetter *ig = checked_cast<InstanceGetter *>(m);
*rval = invokeFunction(ig->fInst, containerVal, NULL, 0);
*rval = invokeFunction(ig->fInst, containerVal, NULL, 0, NULL);
return true;
}
default:
@ -4186,7 +4189,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
case Member::InstanceSetterMember:
{
InstanceSetter *is = checked_cast<InstanceSetter *>(m);
invokeFunction(is->fInst, containerVal, &newValue, 1);
invokeFunction(is->fInst, containerVal, &newValue, 1, NULL);
return true;
}
default:
@ -4248,7 +4251,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
case LocalMember::GetterMember:
{
Getter *g = checked_cast<Getter *>(m);
*rval = invokeFunction(g->code, JS2VAL_VOID, NULL, 0);
*rval = invokeFunction(g->code, JS2VAL_VOID, NULL, 0, NULL);
}
return true;
case LocalMember::SetterMember:
@ -4313,7 +4316,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
case LocalMember::SetterMember:
{
Setter *s = checked_cast<Setter *>(m);
invokeFunction(s->code, JS2VAL_VOID, &newValue, 1);
invokeFunction(s->code, JS2VAL_VOID, &newValue, 1, NULL);
}
return true;
}
@ -4585,7 +4588,9 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
GCMARKOBJECT(super)
GCMARKVALUE(prototype);
GCMARKOBJECT(privateNamespace)
GCMARKOBJECT(init)
if (typeofString) JS2Object::mark(typeofString);
if (name) JS2Object::mark(name);
GCMARKVALUE(defaultValue);
for (InstanceBindingIterator rib = instanceBindings.begin(), riend = instanceBindings.end(); (rib != riend); rib++) {
InstanceBindingEntry *ibe = *rib;

View File

@ -1360,7 +1360,7 @@ public:
void ValidateStmt(Context *cxt, Environment *env, Plurality pl, StmtNode *p);
void ValidateExpression(Context *cxt, Environment *env, ExprNode *p);
void ValidateAttributeExpression(Context *cxt, Environment *env, ExprNode *p);
FunctionInstance *validateStaticFunction(Context *cxt, Environment *env, FunctionDefinition *fnDef, bool prototype, bool unchecked, size_t pos);
FunctionInstance *validateStaticFunction(Context *cxt, Environment *env, FunctionDefinition *fnDef, bool prototype, bool unchecked, bool isConstructor, size_t pos);
void validateStatic(Context *cxt, Environment *env, FunctionDefinition *fnDef, CompoundAttribute *a, bool unchecked, bool hoisted, size_t pos);
void validateConstructor(Context *cxt, Environment *env, FunctionDefinition *fnDef, JS2Class *c, CompoundAttribute *a, size_t pos);
@ -1400,7 +1400,7 @@ public:
js2val invokeFunction(const char *fname);
bool invokeFunctionOnObject(js2val thisValue, const String *fnName, js2val &result);
js2val invokeFunction(JS2Object *fnObj, js2val thisValue, js2val *argv, uint32 argc);
js2val invokeFunction(JS2Object *fnObj, js2val thisValue, js2val *argv, uint32 argc, ParameterFrame *runtimeFrame);
void invokeInit(JS2Class *c, js2val thisValue, js2val* argv, uint32 argc);
void createDynamicProperty(JS2Object *obj, QualifiedName *qName, js2val initVal, Access access, bool sealed, bool enumerable);

View File

@ -189,6 +189,7 @@
ASSERT(c);
ASSERT(!JS2VAL_IS_VOID(pFrame->thisObject));
meta->invokeInit(c->super, pFrame->thisObject, base(argCount), argCount);
pFrame->superConstructorCalled = true;
}
break;