Fixes all over for E3 test results - gc + ECMA edge cases.
git-svn-id: svn://10.0.0.236/trunk@140790 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -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<SimpleInstance *>(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<SimpleInstance *>(fObj))->fWrap;
|
||||
if (fWrap->code)
|
||||
stdOut << "<native code>\n";
|
||||
switch (fObj->kind) {
|
||||
case SimpleInstanceKind:
|
||||
{
|
||||
SimpleInstance *s = checked_cast<SimpleInstance *>(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<SimpleInstance *>(fObj))->fWrap;
|
||||
if (fWrap->code)
|
||||
stdOut << "<native code>\n";
|
||||
else
|
||||
dumpBytecode(fWrap->bCon);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fObj->kind == ClassKind) {
|
||||
break;
|
||||
case ClassKind:
|
||||
{
|
||||
JS2Class *c = checked_cast<JS2Class *>(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<Package *>(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 << "<<unimplemented kind " << (int32)(fObj->kind) << ">>\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<SimpleInstance *>(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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<SimpleInstance *>(JS2VAL_TO_OBJECT(base))->sealed)
|
||||
|| ( (JS2VAL_TO_OBJECT(base)->kind == PackageKind) && !checked_cast<Package *>(JS2VAL_TO_OBJECT(base))->sealed)) ) {
|
||||
&& baseObj
|
||||
&& ( ((baseObj->kind == SimpleInstanceKind) && !checked_cast<SimpleInstance *>(baseObj)->sealed)
|
||||
|| ( (baseObj->kind == PackageKind) && !checked_cast<Package *>(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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<ExprStmtNode *>(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<NonWithFrame *>(*(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<ParameterFrame *>(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<Variable *>(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<Variable *>(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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<MethodClosure *>(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);
|
||||
|
||||
@@ -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<RegExpInstance *>(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<RegExpInstance *>(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<ArrayInstance *>(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("");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user