diff --git a/mozilla/js2/src/epimetheus.cpp b/mozilla/js2/src/epimetheus.cpp index ac7b4ee370e..e2650a3f632 100644 --- a/mozilla/js2/src/epimetheus.cpp +++ b/mozilla/js2/src/epimetheus.cpp @@ -261,28 +261,30 @@ js2val dump(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint else if (JS2VAL_IS_OBJECT(argv[0])) { JS2Object *fObj = JS2VAL_TO_OBJECT(argv[0]); - if (fObj->kind == SimpleInstanceKind) { - - SimpleInstance *s = checked_cast(fObj); - stdOut << "SimpleInstance\n"; - if (JS2VAL_IS_OBJECT(s->super)) - printFormat(stdOut, "super = 0x%08X\n", s->super); - else - stdOut << "super = " << *metadata->toString(s->super) << '\n'; - stdOut << ((s->sealed) ? "sealed " : "not-sealed ") << '\n'; - stdOut << "type = " << *s->type->getName() << '\n'; - printLocalBindings(&s->localBindings); - if (meta->objectType(argv[0]) == meta->functionClass) { - FunctionWrapper *fWrap; - fWrap = (checked_cast(fObj))->fWrap; - if (fWrap->code) - stdOut << "\n"; + switch (fObj->kind) { + case SimpleInstanceKind: + { + SimpleInstance *s = checked_cast(fObj); + stdOut << "SimpleInstance\n"; + if (JS2VAL_IS_OBJECT(s->super)) + printFormat(stdOut, "super = 0x%08X\n", s->super); else - dumpBytecode(fWrap->bCon); + stdOut << "super = " << *metadata->toString(s->super) << '\n'; + stdOut << ((s->sealed) ? "sealed " : "not-sealed ") << '\n'; + stdOut << "type = " << *s->type->getName() << '\n'; + printLocalBindings(&s->localBindings); + if (meta->objectType(argv[0]) == meta->functionClass) { + FunctionWrapper *fWrap; + fWrap = (checked_cast(fObj))->fWrap; + if (fWrap->code) + stdOut << "\n"; + else + dumpBytecode(fWrap->bCon); + } } - } - else { - if (fObj->kind == ClassKind) { + break; + case ClassKind: + { JS2Class *c = checked_cast(fObj); stdOut << "class " << *c->getName(); if (c->super) @@ -309,6 +311,23 @@ js2val dump(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint } } } + break; + case PackageKind: + { + Package *pkg = checked_cast(fObj); + stdOut << "Package\n"; + if (JS2VAL_IS_OBJECT(pkg->super)) + printFormat(stdOut, "super = 0x%08X\n", pkg->super); + else + stdOut << "super = " << *metadata->toString(pkg->super) << '\n'; + stdOut << ((pkg->sealed) ? "sealed " : "not-sealed ") << '\n'; + printLocalBindings(&pkg->localBindings); + + } + break; + default: + stdOut << "<kind) << ">>\n"; + break; } } } diff --git a/mozilla/js2/src/js2array.cpp b/mozilla/js2/src/js2array.cpp index 6df41199923..f2f987d1ba9 100644 --- a/mozilla/js2/src/js2array.cpp +++ b/mozilla/js2/src/js2array.cpp @@ -258,13 +258,14 @@ static js2val Array_join(JS2Metadata *meta, const js2val thisValue, js2val *argv JS2Object *thisObj = JS2VAL_TO_OBJECT(thatValue); uint32 length = getLength(meta, thisObj); - const String *separator; + const String *separator = NULL; + DEFINE_ROOTKEEPER(rk1, separator); if ((argc == 0) || JS2VAL_IS_UNDEFINED(argv[0])) - separator = new String(widenCString(",")); + separator = meta->engine->allocStringPtr(","); else separator = meta->toString(argv[0]); - String *S = new String(); + String *S = new String(); // not engine allocated, doesn't need rooting JS2Class *c = meta->objectType(thisObj); for (uint32 k = 0; k < length; k++) { @@ -537,7 +538,9 @@ static int32 sort_compare(js2val *a, js2val *b, CompareArgs *arg) } else { const String *astr = meta->toString(av); + DEFINE_ROOTKEEPER(rk1, astr); const String *bstr = meta->toString(bv); + DEFINE_ROOTKEEPER(rk2, bstr); result = astr->compare(*bstr); } return result; diff --git a/mozilla/js2/src/js2engine.cpp b/mozilla/js2/src/js2engine.cpp index d619ededfa6..b944e80214a 100644 --- a/mozilla/js2/src/js2engine.cpp +++ b/mozilla/js2/src/js2engine.cpp @@ -224,6 +224,12 @@ namespace MetaData { return new (p) String(*s); } + String *JS2Engine::allocStringPtr(const String *s, uint32 index, uint32 length) + { + String *p = (String *)(JS2Object::alloc(sizeof(String), false)); + return new (p) String(*s, index, length); + } + String *JS2Engine::concatStrings(const String *s1, const String *s2) { String *p = (String *)(JS2Object::alloc(sizeof(String), false)); @@ -897,8 +903,12 @@ namespace MetaData { // reset to previous env. meta->env = activationStackTop->env; sp = execStack + activationStackTop->execStackBase; - if (!JS2VAL_IS_VOID(activationStackTop->retval)) // XXX might need an actual 'returnValue' flag instead - retval = activationStackTop->retval; + if (!JS2VAL_IS_VOID(activationStackTop->retval)) // XXX might need an actual 'returnValue' flag instead? + // if the value being returned is a non-object, prefer it to the value + // set in the activation frame. [This is the mechanism used to handle + // the automatic return of a new object from an E3 constructor call] + if (!JS2VAL_IS_OBJECT(retval)) + retval = activationStackTop->retval; } // GC-mark any JS2Objects in the activation frame stack, the execution stack @@ -1048,6 +1058,17 @@ namespace MetaData { nameList[length++] = &lbe->name; } } + if (length == 0) { + if (obj->kind == SimpleInstanceKind) { + js2val protoval = (checked_cast(obj))->super; + if (!JS2VAL_IS_NULL(protoval)) { + if (JS2VAL_IS_OBJECT(protoval)) { + obj = JS2VAL_TO_OBJECT(protoval); + return buildNameList(meta); + } + } + } + } it = 0; return (length != 0); } diff --git a/mozilla/js2/src/js2engine.h b/mozilla/js2/src/js2engine.h index 666e0e902e5..9dd6decf7e3 100644 --- a/mozilla/js2/src/js2engine.h +++ b/mozilla/js2/src/js2engine.h @@ -210,8 +210,10 @@ public: js2val allocString(const String *s) { return STRING_TO_JS2VAL(allocStringPtr(s)); } js2val allocString(const String &s) { return allocString(&s); } js2val allocString(const char *s) { return STRING_TO_JS2VAL(allocStringPtr(s)); } + js2val allocString(const String *s, uint32 index, uint32 length) { return STRING_TO_JS2VAL(allocStringPtr(s, index, length)); } String *allocStringPtr(const String *s); String *allocStringPtr(const char *s); + String *allocStringPtr(const String *s, uint32 index, uint32 length); String *concatStrings(const String *s1, const String *s2); String *numberToString(float64 *number); // non-static since they need access to meta diff --git a/mozilla/js2/src/js2eval.cpp b/mozilla/js2/src/js2eval.cpp index 522f09a17a8..24360fab38d 100644 --- a/mozilla/js2/src/js2eval.cpp +++ b/mozilla/js2/src/js2eval.cpp @@ -270,7 +270,7 @@ namespace MetaData { DEFINE_ROOTKEEPER(rk, runtimeFrame); runtimeFrame->instantiate(env); runtimeFrame->thisObject = thisValue; - runtimeFrame->assignArguments(this, fnObj, argv, argc); + runtimeFrame->assignArguments(this, fnObj, argv, argc, argc); Frame *oldTopFrame = env->getTopFrame(); env->addFrame(runtimeFrame); try { @@ -363,7 +363,7 @@ namespace MetaData { // if that's not available or returns a non primitive, throw a TypeError JS2Object *obj = JS2VAL_TO_OBJECT(x); - if (obj->kind != SimpleInstanceKind) // therefore, not an E3 object, so just return + if (obj->kind == ClassKind) // therefore, not an E3 object, so just return return engine->typeofString(x); // the 'typeof' string if (hint == StringHint) { @@ -674,19 +674,24 @@ namespace MetaData { Member *m = meta->findCommonMember(&base, multiname, WriteAccess, true); if (m == NULL) { // XXX E3 compatibility... + JS2Object *baseObj = NULL; + DEFINE_ROOTKEEPER(rk, baseObj); if (JS2VAL_IS_PRIMITIVE(base)) { - base = meta->toObject(base); + if (meta->cxt.E3compatibility) + baseObj = JS2VAL_TO_OBJECT(meta->toObject(base)); } + else + baseObj = JS2VAL_TO_OBJECT(base); if (createIfMissing - && JS2VAL_IS_OBJECT(base) - && ( ((JS2VAL_TO_OBJECT(base)->kind == SimpleInstanceKind) && !checked_cast(JS2VAL_TO_OBJECT(base))->sealed) - || ( (JS2VAL_TO_OBJECT(base)->kind == PackageKind) && !checked_cast(JS2VAL_TO_OBJECT(base))->sealed)) ) { + && baseObj + && ( ((baseObj->kind == SimpleInstanceKind) && !checked_cast(baseObj)->sealed) + || ( (baseObj->kind == PackageKind) && !checked_cast(baseObj)->sealed)) ) { QualifiedName qName = multiname->selectPrimaryName(meta); Multiname *mn = new Multiname(qName); DEFINE_ROOTKEEPER(rk, mn); if ( (meta->findBaseInstanceMember(limit, mn, ReadAccess) == NULL) && (meta->findCommonMember(&base, mn, ReadAccess, true) == NULL) ) { - meta->createDynamicProperty(JS2VAL_TO_OBJECT(base), &qName, newValue, ReadWriteAccess, false, true); + meta->createDynamicProperty(baseObj, &qName, newValue, ReadWriteAccess, false, true); return true; } } diff --git a/mozilla/js2/src/js2math.cpp b/mozilla/js2/src/js2math.cpp index 0f3033bfded..7f91b054be1 100644 --- a/mozilla/js2/src/js2math.cpp +++ b/mozilla/js2/src/js2math.cpp @@ -310,7 +310,7 @@ void initMathObject(JS2Metadata *meta) for (i = 0; i < M_CONSTANTS_COUNT; i++) { Variable *v = new Variable(meta->numberClass, meta->engine->allocNumber(MathObjectConstants[i].value), true); - meta->defineLocalMember(meta->env, &meta->world.identifiers[MathObjectConstants[i].name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + meta->defineLocalMember(meta->env, &meta->world.identifiers[MathObjectConstants[i].name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, false); } meta->env->removeTopFrame(); @@ -343,7 +343,7 @@ void initMathObject(JS2Metadata *meta) SimpleInstance *callInst = new SimpleInstance(meta, meta->functionClass->prototype, meta->functionClass); 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); + meta->defineLocalMember(meta->env, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, false); // XXX add 'length' as a dynamic property of the method meta->createDynamicProperty(callInst, meta->engine->length_StringAtom, INT_TO_JS2VAL(pf->length), ReadAccess, true, false); diff --git a/mozilla/js2/src/js2metadata.cpp b/mozilla/js2/src/js2metadata.cpp index 989c0854c88..ca0cdc5fda9 100644 --- a/mozilla/js2/src/js2metadata.cpp +++ b/mozilla/js2/src/js2metadata.cpp @@ -118,7 +118,7 @@ namespace MetaData { // XXX define a static binding for each parameter Variable *v = new Variable(objectClass, JS2VAL_UNDEFINED, false); compileFrame->positional[pCount++] = v; - pb->mn = defineLocalMember(env, pb->name, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, pb->pos); + pb->mn = defineLocalMember(env, pb->name, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, pb->pos, true); pb = pb->next; } } @@ -372,6 +372,9 @@ namespace MetaData { break; case StmtNode::Return: { + Frame *regionalFrame = *env->getRegionalFrame(); + if (regionalFrame->kind != ParameterKind) + reportError(Exception::syntaxError, "Return statement not in function", p->pos); ExprStmtNode *e = checked_cast(p); if (e->expr) { ValidateExpression(cxt, env, e->expr); @@ -441,7 +444,7 @@ namespace MetaData { } else { Variable *v = new Variable(functionClass, OBJECT_TO_JS2VAL(fObj), true); - defineLocalMember(env, f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos); + defineLocalMember(env, f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos, true); } } } @@ -463,7 +466,7 @@ namespace MetaData { ASSERT(!prototype); // XXX right? FunctionInstance *fObj = validateStaticFunction(&f->function, compileThis, prototype, unchecked, cxt, env); ConstructorMethod *cm = new ConstructorMethod(OBJECT_TO_JS2VAL(fObj)); - defineLocalMember(env, f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, cm, p->pos); + defineLocalMember(env, f->function.name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, cm, p->pos, true); } break; } @@ -517,7 +520,7 @@ namespace MetaData { Variable *v = new Variable(FUTURE_TYPE, immutable ? JS2VAL_FUTUREVALUE : JS2VAL_INACCESSIBLE, immutable); vb->member = v; v->vb = vb; - vb->mn = defineLocalMember(env, name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos); + vb->mn = defineLocalMember(env, name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos, true); bCon->saveMultiname(vb->mn); } break; @@ -560,7 +563,7 @@ namespace MetaData { if ( ! ((a->memberMod == Attribute::NoModifier) || ((a->memberMod == Attribute::Static) && (env->getTopFrame()->kind == ClassKind))) ) reportError(Exception::definitionError, "Illegal attribute", p->pos); Variable *v = new Variable(namespaceClass, OBJECT_TO_JS2VAL(new Namespace(&ns->name)), true); - defineLocalMember(env, &ns->name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos); + defineLocalMember(env, &ns->name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos, true); } break; case StmtNode::Use: @@ -622,7 +625,7 @@ namespace MetaData { JS2Class *c = new JS2Class(superClass, protoVal, new Namespace(engine->private_StringAtom), (a->dynamic || superClass->dynamic), true, final, engine->allocStringPtr(&classStmt->name)); classStmt->c = c; Variable *v = new Variable(classClass, OBJECT_TO_JS2VAL(c), true); - defineLocalMember(env, &classStmt->name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos); + defineLocalMember(env, &classStmt->name, a->namespaces, a->overrideMod, a->xplicit, ReadWriteAccess, v, p->pos, true); if (classStmt->body) { env->addFrame(c); ValidateStmtList(cxt, env, pl, classStmt->body->statements); @@ -2424,7 +2427,7 @@ doUnary: // Attempt the read in each frame in the current environment, stopping at the // first succesful effort. If the property can't be found in any frame, it's // an error. - void Environment::lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase, js2val *rval) + void Environment::lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase, js2val *rval, js2val *base) { LookupKind lookup(true, findThis(meta, false)); FrameListIterator fi = getBegin(); @@ -2455,6 +2458,8 @@ doUnary: js2val withVal = OBJECT_TO_JS2VAL(wf->obj); JS2Class *limit = meta->objectType(withVal); result = limit->read(meta, &withVal, limit, multiname, &lookup, phase, rval); + if (result && base) + *base = withVal; } break; } @@ -2729,7 +2734,7 @@ doUnary: // Multiname *JS2Metadata::defineLocalMember(Environment *env, const String *id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, - LocalMember *m, size_t pos) + LocalMember *m, size_t pos, bool enumerable) { NonWithFrame *innerFrame = checked_cast(*(env->getBegin())); if ((overrideMod != Attribute::NoOverride) || (xplicit && innerFrame->kind != PackageKind)) @@ -2789,7 +2794,7 @@ doUnary: else lbe = *lbeP; for (NamespaceListIterator nli = multiname->nsList->begin(), nlend = multiname->nsList->end(); (nli != nlend); nli++) { - LocalBinding *new_b = new LocalBinding(access, m, true); + LocalBinding *new_b = new LocalBinding(access, m, enumerable); lbe->bindingList.push_back(LocalBindingEntry::NamespaceBinding(*nli, new_b)); } // Mark the bindings of multiname as Forbidden in all non-innermost frames in the current @@ -3034,9 +3039,13 @@ rescan: static js2val GlobalObject_eval(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint32 argc) { - if (!JS2VAL_IS_STRING(argv[0])) - return argv[0]; - return meta->readEvalString(*meta->toString(argv[0]), widenCString("Eval Source")); + if (argc) { + if (!JS2VAL_IS_STRING(argv[0])) + return argv[0]; + return meta->readEvalString(*meta->toString(argv[0]), widenCString("Eval Source")); + } + else + return JS2VAL_UNDEFINED; } #define JS7_ISHEX(c) ((c) < 128 && isxdigit(c)) @@ -3214,6 +3223,18 @@ static const uint8 urlCharType[256] = createDynamicProperty(fInst, engine->length_StringAtom, INT_TO_JS2VAL(length), ReadAccess, true, false); } + static js2val Object_Constructor(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc) + { + if (argc) { + if (JS2VAL_IS_OBJECT(argv[0])) + return argv[0]; // XXX special handling for host objects? + else + return meta->toObject(argv[0]); + } + else + return OBJECT_TO_JS2VAL(new SimpleInstance(meta, meta->objectClass->prototype, meta->objectClass)); + } + static js2val Object_toString(JS2Metadata *meta, const js2val thisValue, js2val /* argv */ [], uint32 /* argc */) { ASSERT(JS2VAL_IS_OBJECT(thisValue)); @@ -3302,19 +3323,20 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... /*** ECMA 3 Object Class ***/ v = new Variable(classClass, OBJECT_TO_JS2VAL(objectClass), true); - defineLocalMember(env, &world.identifiers["Object"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["Object"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); // Function properties of the Object prototype object objectClass->prototype = OBJECT_TO_JS2VAL(new SimpleInstance(this, NULL, objectClass)); + objectClass->construct = Object_Constructor; // Adding "prototype" as a static member of the class - not a dynamic property env->addFrame(objectClass); v = new Variable(objectClass, OBJECT_TO_JS2VAL(objectClass->prototype), true); - defineLocalMember(env, engine->prototype_StringAtom, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, engine->prototype_StringAtom, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, false); env->removeTopFrame(); /*** ECMA 3 Function Class ***/ // Need this initialized early, as subsequent FunctionInstances need the Function.prototype value v = new Variable(classClass, OBJECT_TO_JS2VAL(functionClass), true); - defineLocalMember(env, &world.identifiers["Function"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["Function"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); initFunctionObject(this); // Adding 'toString' to the Object.prototype XXX Or make this a static class member? @@ -3326,34 +3348,34 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... /*** ECMA 3 Date Class ***/ MAKEBUILTINCLASS(dateClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Date"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(dateClass), true); - defineLocalMember(env, &world.identifiers["Date"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["Date"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); initDateObject(this); /*** ECMA 3 RegExp Class ***/ MAKEBUILTINCLASS(regexpClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["RegExp"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(regexpClass), true); - defineLocalMember(env, &world.identifiers["RegExp"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["RegExp"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); initRegExpObject(this); /*** ECMA 3 String Class ***/ v = new Variable(classClass, OBJECT_TO_JS2VAL(stringClass), true); - defineLocalMember(env, &world.identifiers["String"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["String"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); initStringObject(this); /*** ECMA 3 Number Class ***/ v = new Variable(classClass, OBJECT_TO_JS2VAL(numberClass), true); - defineLocalMember(env, &world.identifiers["Number"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["Number"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); initNumberObject(this); /*** ECMA 3 Boolean Class ***/ v = new Variable(classClass, OBJECT_TO_JS2VAL(booleanClass), true); - defineLocalMember(env, &world.identifiers["Boolean"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["Boolean"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); initBooleanObject(this); /*** ECMA 3 Math Class ***/ MAKEBUILTINCLASS(mathClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Math"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(mathClass), true); - defineLocalMember(env, &world.identifiers["Math"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["Math"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); initMathObject(this); /*** ECMA 3 Array Class ***/ @@ -3361,31 +3383,31 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... arrayClass->write = arrayWriteProperty; arrayClass->writePublic = arrayWritePublic; v = new Variable(classClass, OBJECT_TO_JS2VAL(arrayClass), true); - defineLocalMember(env, &world.identifiers["Array"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["Array"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); initArrayObject(this); /*** ECMA 3 Error Classes ***/ MAKEBUILTINCLASS(errorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["Error"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(errorClass), true); - defineLocalMember(env, &world.identifiers["Error"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["Error"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); MAKEBUILTINCLASS(evalErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["EvalError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(evalErrorClass), true); - defineLocalMember(env, &world.identifiers["EvalError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["EvalError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); MAKEBUILTINCLASS(rangeErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["RangeError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(rangeErrorClass), true); - defineLocalMember(env, &world.identifiers["RangeError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["RangeError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); MAKEBUILTINCLASS(referenceErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["ReferenceError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(referenceErrorClass), true); - defineLocalMember(env, &world.identifiers["ReferenceError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["ReferenceError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); MAKEBUILTINCLASS(syntaxErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["SyntaxError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(syntaxErrorClass), true); - defineLocalMember(env, &world.identifiers["SyntaxError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["SyntaxError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); MAKEBUILTINCLASS(typeErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["TypeError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(typeErrorClass), true); - defineLocalMember(env, &world.identifiers["TypeError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["TypeError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); MAKEBUILTINCLASS(uriErrorClass, objectClass, true, true, true, engine->allocStringPtr(&world.identifiers["UriError"]), JS2VAL_NULL); v = new Variable(classClass, OBJECT_TO_JS2VAL(uriErrorClass), true); - defineLocalMember(env, &world.identifiers["UriError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, &world.identifiers["UriError"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, true); initErrorObject(this); } @@ -3449,37 +3471,6 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... return c->isAncestor(objectType(objVal)); } - - -/* - void ArrayInstance::writeProperty(JS2Metadata *meta, const String *name, js2val newValue, uint32 flags) - { - // An index has to pass the test that : - // ToString(ToUint32(ToString(index))) == ToString(index) - // (we already have done the 'ToString(index)' part, so require - // - // ToString(ToUint32(name)) == name - // - - // XXX things would go faster if the index made it here as an int - // (which it more typically is) rather than converted to string - // and back. - - const char16 *numEnd; - float64 f = stringToDouble(name->data(), name->data() + name->length(), numEnd); - uint32 index = JS2Engine::float64toUInt32(f); - - char buf[dtosStandardBufferSize]; - const char *chrp = doubleToStr(buf, dtosStandardBufferSize, index, dtosStandard, 0); - - if (widenCString(chrp) == *name) { - uint32 length = getLength(meta, this); - if (index >= length) - setLength(meta, this, index + 1); - } - } -*/ - InstanceMember *JS2Metadata::findLocalInstanceMember(JS2Class *limit, Multiname *multiname, Access access) { InstanceMember *result = NULL; @@ -3714,6 +3705,13 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... return (findCommonMember(&val, mn, ReadWriteAccess, true) != NULL); } + void JS2Metadata::createDynamicProperty(JS2Object *obj, const String *name, js2val initVal, Access access, bool sealed, bool enumerable) + { + DEFINE_ROOTKEEPER(rk, name); + QualifiedName qName(publicNamespace, name); + createDynamicProperty(obj, &qName, initVal, access, sealed, enumerable); + } + // The caller must make sure that the created property does not already exist and does not conflict with any other property. void JS2Metadata::createDynamicProperty(JS2Object *obj, QualifiedName *qName, js2val initVal, Access access, bool sealed, bool enumerable) { @@ -3851,9 +3849,9 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... env->addFrame(builtinClass); { Variable *v = new Variable(builtinClass, OBJECT_TO_JS2VAL(builtinClass->prototype), true); - defineLocalMember(env, engine->prototype_StringAtom, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, engine->prototype_StringAtom, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, false); v = new Variable(builtinClass, INT_TO_JS2VAL(1), true); - defineLocalMember(env, engine->length_StringAtom, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + defineLocalMember(env, engine->length_StringAtom, &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, false); pf = staticFunctions; if (pf) { @@ -3861,7 +3859,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... SimpleInstance *callInst = new SimpleInstance(this, functionClass->prototype, functionClass); 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); + defineLocalMember(env, &world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, false); createDynamicProperty(callInst, engine->length_StringAtom, INT_TO_JS2VAL(pf->length), ReadAccess, true, false); pf++; } @@ -3874,7 +3872,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... createDynamicProperty(fInst, engine->length_StringAtom, INT_TO_JS2VAL(1), ReadAccess, true, false); fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), construct, env); ASSERT(JS2VAL_IS_OBJECT(builtinClass->prototype)); - createDynamicProperty(JS2VAL_TO_OBJECT(builtinClass->prototype), &world.identifiers["constructor"], OBJECT_TO_JS2VAL(fInst), ReadWriteAccess, false, true); + createDynamicProperty(JS2VAL_TO_OBJECT(builtinClass->prototype), &world.identifiers["constructor"], OBJECT_TO_JS2VAL(fInst), ReadWriteAccess, false, false); pf = protoFunctions; if (pf) { @@ -3882,12 +3880,12 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... SimpleInstance *callInst = new SimpleInstance(this, functionClass->prototype, functionClass); callInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code, env); Multiname *mn = new Multiname(&world.identifiers[pf->name], &publicNamespaceList); - InstanceMember *m = new InstanceMethod(mn, callInst, true, true); + InstanceMember *m = new InstanceMethod(mn, callInst, true, false); defineInstanceMember(builtinClass, &cxt, mn->name, mn->nsList, Attribute::NoOverride, false, m, 0); FunctionInstance *fInst = new FunctionInstance(this, functionClass->prototype, functionClass); fInst->fWrap = callInst->fWrap; - createDynamicProperty(JS2VAL_TO_OBJECT(builtinClass->prototype), &world.identifiers[pf->name], OBJECT_TO_JS2VAL(fInst), ReadWriteAccess, false, true); + createDynamicProperty(JS2VAL_TO_OBJECT(builtinClass->prototype), &world.identifiers[pf->name], OBJECT_TO_JS2VAL(fInst), ReadWriteAccess, false, false); createDynamicProperty(fInst, engine->length_StringAtom, INT_TO_JS2VAL(pf->length), ReadAccess, true, false); pf++; } @@ -4106,6 +4104,20 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... GCMARKOBJECT(type); } + /************************************************************************************ + * + * ArrayInstance + * + ************************************************************************************/ + + ArrayInstance::ArrayInstance(JS2Metadata *meta, js2val parent, JS2Class *type) + : SimpleInstance(meta, parent, type) + { + JS2Object *result = this; + DEFINE_ROOTKEEPER(rk1, result); + + meta->createDynamicProperty(this, meta->engine->length_StringAtom, INT_TO_JS2VAL(0), ReadWriteAccess, true, false); + } /************************************************************************************ * @@ -4117,7 +4129,13 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... : SimpleInstance(meta, parent, type) { // Add prototype property - meta->createDynamicProperty(this, meta->engine->prototype_StringAtom, OBJECT_TO_JS2VAL(parent), ReadWriteAccess, false, true); + JS2Object *result = this; + DEFINE_ROOTKEEPER(rk1, result); + + JS2Object *obj = new SimpleInstance(meta, meta->objectClass->prototype, meta->objectClass); + DEFINE_ROOTKEEPER(rk2, obj); + + meta->createDynamicProperty(this, meta->engine->prototype_StringAtom, OBJECT_TO_JS2VAL(obj), ReadWriteAccess, false, true); } @@ -4219,7 +4237,8 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... // Assume that instantiate has been called, the plural frame will contain // the cloned Variables assigned into this (singular) frame. Use the // incoming values to initialize the positionals. - void ParameterFrame::assignArguments(JS2Metadata *meta, JS2Object *fnObj, js2val *argBase, uint32 argCount) + // Pad out to 'length' args with undefined values if argCount is insufficient + void ParameterFrame::assignArguments(JS2Metadata *meta, JS2Object *fnObj, js2val *argBase, uint32 argCount, uint32 length) { Multiname *mn = new Multiname(NULL, meta->publicNamespace); DEFINE_ROOTKEEPER(rk1, mn); @@ -4228,7 +4247,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... ParameterFrame *plural = checked_cast(pluralFrame); ASSERT((plural->positionalCount == 0) || (plural->positional != NULL)); - SimpleInstance *argsObj = new SimpleInstance(meta, meta->objectClass->prototype, meta->objectClass);; + SimpleInstance *argsObj = new SimpleInstance(meta, meta->objectClass->prototype, meta->objectClass); DEFINE_ROOTKEEPER(rk2, argsObj); // Add the 'arguments' property @@ -4245,11 +4264,17 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now... ASSERT(plural->positional[i]->cloneContent->kind == Member::Variable); (checked_cast(plural->positional[i]->cloneContent))->value = argBase[i]; } -// mn->name = meta->engine->numberToString(i); meta->arrayClass->writePublic(meta, OBJECT_TO_JS2VAL(argsObj), meta->arrayClass, meta->engine->numberToString(i), true, argBase[i]); } - setLength(meta, argsObj, i); -// mn->name = meta->engine->allocStringPtr(&meta->world.identifiers["callee"]); + while (i++ < length) { + if (i < plural->positionalCount) { + ASSERT(plural->positional[i]->cloneContent); + ASSERT(plural->positional[i]->cloneContent->kind == Member::Variable); + (checked_cast(plural->positional[i]->cloneContent))->value = JS2VAL_UNDEFINED; + } + meta->arrayClass->writePublic(meta, OBJECT_TO_JS2VAL(argsObj), meta->arrayClass, meta->engine->numberToString(i), true, JS2VAL_UNDEFINED); + } + setLength(meta, argsObj, argCount); meta->arrayClass->writePublic(meta, OBJECT_TO_JS2VAL(argsObj), meta->arrayClass, meta->engine->allocStringPtr("callee"), true, OBJECT_TO_JS2VAL(fnObj)); } diff --git a/mozilla/js2/src/js2metadata.h b/mozilla/js2/src/js2metadata.h index 1f9d48ab62c..3eb086728f1 100644 --- a/mozilla/js2/src/js2metadata.h +++ b/mozilla/js2/src/js2metadata.h @@ -648,7 +648,7 @@ public: void removeTopFrame() { frameList.pop_front(); } js2val findThis(JS2Metadata *meta, bool allowPrototypeThis); - void lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase, js2val *rval); + void lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase, js2val *rval, js2val *base); void lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing); void lexicalInit(JS2Metadata *meta, Multiname *multiname, js2val newValue); bool lexicalDelete(JS2Metadata *meta, Multiname *multiname, Phase phase); @@ -821,8 +821,7 @@ public: // are added. class ArrayInstance : public SimpleInstance { public: - ArrayInstance(JS2Metadata *meta, js2val parent, JS2Class *type) : SimpleInstance(meta, parent, type) { } - + ArrayInstance(JS2Metadata *meta, js2val parent, JS2Class *type); virtual ~ArrayInstance() { } }; @@ -1067,7 +1066,7 @@ public: uint32 positionalCount; virtual void instantiate(Environment *env); - void assignArguments(JS2Metadata *meta, JS2Object *fnObj, js2val *argBase, uint32 argCount); + void assignArguments(JS2Metadata *meta, JS2Object *fnObj, js2val *argBase, uint32 argCount, uint32 length); virtual void markChildren(); virtual ~ParameterFrame() { } }; @@ -1201,7 +1200,7 @@ public: InstanceBinding *resolveInstanceMemberName(JS2Class *js2class, Multiname *multiname, Access access, Phase phase, QualifiedName *qname); DynamicVariable *defineHoistedVar(Environment *env, const String *id, StmtNode *p, bool isVar); - Multiname *defineLocalMember(Environment *env, const String *id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, LocalMember *m, size_t pos); + Multiname *defineLocalMember(Environment *env, const String *id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, Access access, LocalMember *m, size_t pos, bool enumerable); InstanceMember *defineInstanceMember(JS2Class *c, Context *cxt, const String *id, NamespaceList *namespaces, Attribute::OverrideModifier overrideMod, bool xplicit, InstanceMember *m, size_t pos); @@ -1221,8 +1220,7 @@ public: js2val invokeFunction(JS2Object *fnObj, js2val thisValue, js2val *argv, uint32 argc); void createDynamicProperty(JS2Object *obj, QualifiedName *qName, js2val initVal, Access access, bool sealed, bool enumerable); - void createDynamicProperty(JS2Object *obj, const String *name, js2val initVal, Access access, bool sealed, bool enumerable) - { QualifiedName qName(publicNamespace, name); createDynamicProperty(obj, &qName, initVal, access, sealed, enumerable); } + void createDynamicProperty(JS2Object *obj, const String *name, js2val initVal, Access access, bool sealed, bool enumerable); diff --git a/mozilla/js2/src/js2number.cpp b/mozilla/js2/src/js2number.cpp index a3a282cbb28..8c2f31fcf82 100644 --- a/mozilla/js2/src/js2number.cpp +++ b/mozilla/js2/src/js2number.cpp @@ -121,7 +121,7 @@ namespace MetaData { for (i = 0; i < N_CONSTANTS_COUNT; i++) { Variable *v = new Variable(meta->numberClass, meta->engine->allocNumber(NumberObjectConstants[i].value), true); - meta->defineLocalMember(meta->env, &meta->world.identifiers[NumberObjectConstants[i].name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0); + meta->defineLocalMember(meta->env, &meta->world.identifiers[NumberObjectConstants[i].name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0, false); } meta->env->removeTopFrame(); diff --git a/mozilla/js2/src/js2op_access.cpp b/mozilla/js2/src/js2op_access.cpp index f7c4b168deb..ead642609a3 100644 --- a/mozilla/js2/src/js2op_access.cpp +++ b/mozilla/js2/src/js2op_access.cpp @@ -99,7 +99,7 @@ { Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; pc += sizeof(short); - meta->env->lexicalRead(meta, mn, phase, &a); + meta->env->lexicalRead(meta, mn, phase, &a, NULL); push(a); } break; @@ -142,8 +142,9 @@ { Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; pc += sizeof(short); - meta->env->lexicalRead(meta, mn, phase, &a); - push(JS2VAL_NULL); + b = JS2VAL_NULL; + meta->env->lexicalRead(meta, mn, phase, &a, &b); + push(b); push(a); } break; diff --git a/mozilla/js2/src/js2op_arithmetic.cpp b/mozilla/js2/src/js2op_arithmetic.cpp index 42e8262afcd..7cfca0a533a 100644 --- a/mozilla/js2/src/js2op_arithmetic.cpp +++ b/mozilla/js2/src/js2op_arithmetic.cpp @@ -892,7 +892,7 @@ { Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; pc += sizeof(short); - meta->env->lexicalRead(meta, mn, phase, &a); + meta->env->lexicalRead(meta, mn, phase, &a, NULL); if (JS2VAL_IS_LONG(a)) { int64 i = *JS2VAL_TO_LONG(a); JSLL_ADD(i, i, 1); @@ -918,7 +918,7 @@ { Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; pc += sizeof(short); - meta->env->lexicalRead(meta, mn, phase, &a); + meta->env->lexicalRead(meta, mn, phase, &a, NULL); float64 num = meta->toFloat64(a); meta->env->lexicalWrite(meta, mn, allocNumber(num - 1.0), true); pushNumber(num); @@ -928,7 +928,7 @@ { Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; pc += sizeof(short); - meta->env->lexicalRead(meta, mn, phase, &a); + meta->env->lexicalRead(meta, mn, phase, &a, NULL); float64 num = meta->toFloat64(a); a = pushNumber(num + 1.0); meta->env->lexicalWrite(meta, mn, a, true); @@ -938,7 +938,7 @@ { Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)]; pc += sizeof(short); - meta->env->lexicalRead(meta, mn, phase, &a); + meta->env->lexicalRead(meta, mn, phase, &a, NULL); float64 num = meta->toFloat64(a); a = pushNumber(num - 1.0); meta->env->lexicalWrite(meta, mn, a, true); diff --git a/mozilla/js2/src/js2op_invocation.cpp b/mozilla/js2/src/js2op_invocation.cpp index e96d04d8be1..91a03a1123a 100644 --- a/mozilla/js2/src/js2op_invocation.cpp +++ b/mozilla/js2/src/js2op_invocation.cpp @@ -74,7 +74,12 @@ meta->reportError(Exception::badValueError, "Non-object prototype value", errorPos()); } + uint32 length = getLength(meta, obj); if (fWrap->code) { // native code, pass pointer to argument base + while (argCount < length) { + push(JS2VAL_UNDEFINED); + argCount++; + } a = fWrap->code(meta, a, base(argCount), argCount); pop(argCount + 1); push(a); @@ -84,7 +89,7 @@ pFrame->instantiate(meta->env); baseVal = OBJECT_TO_JS2VAL(new SimpleInstance(meta, protoVal, meta->objectType(protoVal))); pFrame->thisObject = baseVal; - pFrame->assignArguments(meta, obj, base(argCount), argCount); + pFrame->assignArguments(meta, obj, base(argCount), argCount, length); 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; @@ -119,18 +124,26 @@ a = OBJECT_TO_JS2VAL(g); } } + uint32 length = getLength(meta, fObj); if (fWrap->code) { // native code + Environment *oldEnv = meta->env; + meta->env = fWrap->env; + while (argCount < length) { + push(JS2VAL_UNDEFINED); + argCount++; + } a = fWrap->code(meta, a, base(argCount), argCount); pop(argCount + 2); push(a); + meta->env = oldEnv; } else { pFrame = new ParameterFrame(fWrap->compileFrame); pFrame->instantiate(meta->env); pFrame->thisObject = a; - // assignArguments(runtimeFrame, fWrap->compileFrame->signature); - // XXX - pFrame->assignArguments(meta, fObj, base(argCount), argCount); + // XXX (use fWrap->compileFrame->signature) + uint32 i = length; + pFrame->assignArguments(meta, fObj, base(argCount), argCount, length); 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; @@ -141,18 +154,25 @@ MethodClosure *mc = checked_cast(fObj); SimpleInstance *fInst = mc->method->fInst; FunctionWrapper *fWrap = fInst->fWrap; - + uint32 length = getLength(meta, fObj); if (fWrap->code) { + Environment *oldEnv = meta->env; + meta->env = fWrap->env; + while (argCount < length) { + push(JS2VAL_UNDEFINED); + argCount++; + } a = fWrap->code(meta, mc->thisObject, base(argCount), argCount); pop(argCount + 2); push(a); + meta->env = oldEnv; } else { pFrame = new ParameterFrame(fWrap->compileFrame); pFrame->instantiate(meta->env); pFrame->thisObject = mc->thisObject; // assignArguments(runtimeFrame, fWrap->compileFrame->signature); - pFrame->assignArguments(meta, fObj, base(argCount), argCount); + pFrame->assignArguments(meta, fObj, base(argCount), argCount, length); 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); diff --git a/mozilla/js2/src/js2string.cpp b/mozilla/js2/src/js2string.cpp index cfe5f05c9a1..2241c8c40fe 100644 --- a/mozilla/js2/src/js2string.cpp +++ b/mozilla/js2/src/js2string.cpp @@ -119,7 +119,11 @@ static js2val String_valueOf(JS2Metadata *meta, const js2val thisValue, js2val * */ static js2val String_search(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { - js2val S = STRING_TO_JS2VAL(meta->toString(thisValue)); + const String *str = NULL; + DEFINE_ROOTKEEPER(rk, str); + str = meta->toString(thisValue); + + js2val S = STRING_TO_JS2VAL(str); js2val regexp = argv[0]; @@ -129,7 +133,6 @@ static js2val String_search(JS2Metadata *meta, const js2val thisValue, js2val *a } REState *pState = (checked_cast(JS2VAL_TO_OBJECT(regexp)))->mRegExp; - const String *str = JS2VAL_TO_STRING(S); REMatchState *match = REExecute(pState, str->begin(), 0, (int32)str->length(), false); if (match) return meta->engine->allocNumber((float64)(match->startIndex)); @@ -265,6 +268,7 @@ static const String interpretDollar(JS2Metadata *meta, const String *replaceStr, static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { const String *S = meta->toString(thisValue); + DEFINE_ROOTKEEPER(rk1, S); js2val searchValue = JS2VAL_UNDEFINED; js2val replaceValue = JS2VAL_UNDEFINED; @@ -272,6 +276,7 @@ static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val * if (argc > 0) searchValue = argv[0]; if (argc > 1) replaceValue = argv[1]; const String *replaceStr = meta->toString(replaceValue); + DEFINE_ROOTKEEPER(rk2, replaceStr); if (meta->objectType(searchValue) != meta->regexpClass) { RegExpInstance *reInst = checked_cast(JS2VAL_TO_OBJECT(searchValue)); @@ -280,13 +285,13 @@ static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val * String newString; int32 lastIndex = 0; - while (true) { + while (true) { match = REExecute(pState, S->begin(), lastIndex, toInt32(S->length()), false); if (match) { String insertString; uint32 start = 0; while (true) { - // look for '$' in the replacement string and interpret it as necessary + // look for '$' in the replacement string and interpret it as necessary uint32 dollarPos = replaceStr->find('$', start); if ((dollarPos != String::npos) && (dollarPos < (replaceStr->length() - 1))) { uint32 skip; @@ -295,7 +300,7 @@ static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val * start = dollarPos + skip; } else { - // otherwise, absorb the entire replacement string + // otherwise, absorb the entire replacement string insertString += replaceStr->substr(start, replaceStr->length() - start); break; } @@ -318,6 +323,7 @@ static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val * } else { const String *searchStr = meta->toString(searchValue); + DEFINE_ROOTKEEPER(rk3, searchStr); REMatchState match; uint32 pos = S->find(*searchStr, 0); if (pos == String::npos) @@ -402,10 +408,12 @@ static void regexpSplitMatch(JS2Metadata *meta, const String *S, uint32 q, RESta static js2val String_split(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { const String *S = meta->toString(thisValue); + DEFINE_ROOTKEEPER(rk0, S); js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta, meta->arrayClass->prototype, meta->arrayClass)); ArrayInstance *A = checked_cast(JS2VAL_TO_OBJECT(result)); - DEFINE_ROOTKEEPER(rk, A); + DEFINE_ROOTKEEPER(rk1, A); + setLength(meta, A, 0); uint32 lim; js2val separatorV = (argc > 0) ? argv[0] : JS2VAL_UNDEFINED; @@ -448,11 +456,14 @@ static js2val String_split(JS2Metadata *meta, const js2val thisValue, js2val *ar return result; } + String *T = NULL; + DEFINE_ROOTKEEPER(rk2, T); + while (true) { uint32 q = p; step11: if (q == s) { - js2val v = meta->engine->allocString(new String(*S, p, (s - p))); + js2val v = meta->engine->allocString(S, p, (s - p)); meta->arrayClass->writePublic(meta, OBJECT_TO_JS2VAL(A), meta->arrayClass, meta->engine->numberToString(getLength(meta, A)), true, v); return result; } @@ -470,7 +481,7 @@ step11: q = q + 1; goto step11; } - String *T = meta->engine->allocStringPtr(new String(*S, p, (q - p))); // XXX + T = meta->engine->allocStringPtr(S, p, (q - p)); // XXX js2val v = STRING_TO_JS2VAL(T); meta->arrayClass->writePublic(meta, OBJECT_TO_JS2VAL(A), meta->arrayClass, meta->engine->numberToString(getLength(meta, A)), true, v); if (getLength(meta, A) == lim) @@ -488,6 +499,7 @@ step11: static js2val String_charAt(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { const String *str = meta->toString(thisValue); + DEFINE_ROOTKEEPER(rk, str); uint32 pos = 0; if (argc > 0) @@ -503,6 +515,7 @@ static js2val String_charAt(JS2Metadata *meta, const js2val thisValue, js2val *a static js2val String_charCodeAt(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { const String *str = meta->toString(thisValue); + DEFINE_ROOTKEEPER(rk, str); uint32 pos = 0; if (argc > 0) @@ -517,7 +530,9 @@ static js2val String_charCodeAt(JS2Metadata *meta, const js2val thisValue, js2va static js2val String_concat(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { const String *str = meta->toString(thisValue); + DEFINE_ROOTKEEPER(rk1, str); String *result = meta->engine->allocStringPtr(str); + DEFINE_ROOTKEEPER(rk2, result); for (uint32 i = 0; i < argc; i++) { *result += *meta->toString(argv[i]); @@ -532,7 +547,9 @@ static js2val String_indexOf(JS2Metadata *meta, const js2val thisValue, js2val * return meta->engine->allocNumber(-1.0); const String *str = meta->toString(thisValue); + DEFINE_ROOTKEEPER(rk1, str); const String *searchStr = meta->toString(argv[0]); + DEFINE_ROOTKEEPER(rk2, searchStr); uint32 pos = 0; if (argc > 1) { @@ -559,7 +576,9 @@ static js2val String_lastIndexOf(JS2Metadata *meta, const js2val thisValue, js2v return meta->engine->allocNumber(-1.0); const String *str = meta->toString(thisValue); + DEFINE_ROOTKEEPER(rk1, str); const String *searchStr = meta->toString(argv[0]); + DEFINE_ROOTKEEPER(rk2, searchStr); uint32 pos = str->size(); if (argc > 1) { @@ -589,9 +608,12 @@ static js2val String_localeCompare(JS2Metadata * /* meta */, const js2val /*this static js2val String_toLowerCase(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/) { - js2val S = STRING_TO_JS2VAL(meta->toString(thisValue)); + const String *str = meta->toString(thisValue); + DEFINE_ROOTKEEPER(rk1, str); + js2val S = STRING_TO_JS2VAL(str); - String *result = meta->engine->allocStringPtr(JS2VAL_TO_STRING(S)); + String *result = meta->engine->allocStringPtr(str); + DEFINE_ROOTKEEPER(rk2, result); for (String::iterator i = result->begin(), end = result->end(); i != end; i++) *i = toLower(*i); @@ -600,9 +622,12 @@ static js2val String_toLowerCase(JS2Metadata *meta, const js2val thisValue, js2v static js2val String_toUpperCase(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/) { - js2val S = STRING_TO_JS2VAL(meta->toString(thisValue)); + const String *str = meta->toString(thisValue); + DEFINE_ROOTKEEPER(rk1, str); + js2val S = STRING_TO_JS2VAL(str); String *result = meta->engine->allocStringPtr(JS2VAL_TO_STRING(S)); + DEFINE_ROOTKEEPER(rk2, result); for (String::iterator i = result->begin(), end = result->end(); i != end; i++) *i = toUpper(*i); @@ -633,6 +658,7 @@ static js2val String_toUpperCase(JS2Metadata *meta, const js2val thisValue, js2v static js2val String_slice(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { const String *sourceString = meta->toString(thisValue); + DEFINE_ROOTKEEPER(rk1, sourceString); uint32 sourceLength = sourceString->size(); uint32 start, end; @@ -705,6 +731,7 @@ static js2val String_slice(JS2Metadata *meta, const js2val thisValue, js2val *ar static js2val String_substring(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc) { const String *sourceString = meta->toString(thisValue); + DEFINE_ROOTKEEPER(rk1, sourceString); uint32 sourceLength = sourceString->size(); uint32 start, end; @@ -785,6 +812,7 @@ void initStringObject(JS2Metadata *meta) }; StringInstance *strInst = new StringInstance(meta, meta->objectClass->prototype, meta->stringClass); + DEFINE_ROOTKEEPER(rk1, strInst); meta->stringClass->prototype = OBJECT_TO_JS2VAL(strInst); strInst->mValue = meta->engine->allocStringPtr("");