зеркало из https://github.com/mozilla/pjs.git
Fixing for..in, runaway string allocation, array.length initialization.
This commit is contained in:
Родитель
cb6b7d86a9
Коммит
93fb6ad7bd
|
@ -233,11 +233,11 @@ js2val trace(JS2Metadata *meta, const js2val /* thisValue */, js2val /* argv */
|
|||
return JS2VAL_UNDEFINED;
|
||||
}
|
||||
|
||||
void printFrameBindings(NonWithFrame *f)
|
||||
void printLocalBindings(LocalBindingMap *lMap)
|
||||
{
|
||||
stdOut << " Local Bindings:\n";
|
||||
|
||||
for (LocalBindingIterator bi = f->localBindings.begin(), bend = f->localBindings.end(); (bi != bend); bi++) {
|
||||
for (LocalBindingIterator bi = lMap->begin(), bend = lMap->end(); (bi != bend); bi++) {
|
||||
LocalBindingEntry *lbe = *bi;
|
||||
for (LocalBindingEntry::NS_Iterator i = lbe->begin(), end = lbe->end(); (i != end); i++) {
|
||||
LocalBindingEntry::NamespaceBinding ns = *i;
|
||||
|
@ -261,14 +261,25 @@ 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)
|
||||
&& (meta->objectType(argv[0]) == meta->functionClass))) {
|
||||
FunctionWrapper *fWrap;
|
||||
fWrap = (checked_cast<SimpleInstance *>(fObj))->fWrap;
|
||||
if (fWrap->code)
|
||||
stdOut << "<native code>\n";
|
||||
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
|
||||
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) {
|
||||
|
@ -280,7 +291,7 @@ js2val dump(JS2Metadata *meta, const js2val /* thisValue */, js2val argv[], uint
|
|||
stdOut << ((c->dynamic) ? " dynamic, " : " non-dynamic, ") << ((c->final) ? "final" : "non-final") << "\n";
|
||||
stdOut << " slotCount = " << c->slotCount << "\n";
|
||||
|
||||
printFrameBindings(c);
|
||||
printLocalBindings(&c->localBindings);
|
||||
|
||||
stdOut << " Instance Bindings:\n";
|
||||
for (InstanceBindingIterator rib = c->instanceBindings.begin(), riend = c->instanceBindings.end(); (rib != riend); rib++) {
|
||||
|
|
|
@ -121,6 +121,8 @@ js2val Array_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val *
|
|||
setLength(meta, arrInst, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
setLength(meta, arrInst, 0);
|
||||
return thatValue;
|
||||
}
|
||||
|
||||
|
|
|
@ -211,7 +211,11 @@ namespace MetaData {
|
|||
|
||||
String *JS2Engine::allocStringPtr(const char *s)
|
||||
{
|
||||
return allocStringPtr(&meta->world.identifiers[widenCString(s)]);
|
||||
String *p = (String *)(JS2Object::alloc(sizeof(String), false));
|
||||
size_t len = strlen(s);
|
||||
String *result = new (p) String(len, uni::null);
|
||||
std::transform(s, s+len, result->begin(), widen);
|
||||
return result;
|
||||
}
|
||||
|
||||
String *JS2Engine::allocStringPtr(const String *s)
|
||||
|
@ -274,7 +278,7 @@ namespace MetaData {
|
|||
{
|
||||
char buf[dtosStandardBufferSize];
|
||||
const char *chrp = doubleToStr(buf, dtosStandardBufferSize, i, dtosStandard, 0);
|
||||
return allocStringPtr(&meta->world.identifiers[chrp]);
|
||||
return allocStringPtr(chrp);
|
||||
}
|
||||
|
||||
// Convert a double to a string
|
||||
|
@ -282,7 +286,7 @@ namespace MetaData {
|
|||
{
|
||||
char buf[dtosStandardBufferSize];
|
||||
const char *chrp = doubleToStr(buf, dtosStandardBufferSize, *number, dtosStandard, 0);
|
||||
return allocStringPtr(&meta->world.identifiers[chrp]);
|
||||
return allocStringPtr(chrp);
|
||||
}
|
||||
|
||||
// x is a Number, validate that it has no fractional component
|
||||
|
@ -1012,47 +1016,40 @@ namespace MetaData {
|
|||
//
|
||||
// Initialize and build a list of names of properties in the object.
|
||||
//
|
||||
bool ForIteratorObject::first()
|
||||
bool ForIteratorObject::first(JS2Engine *engine)
|
||||
{
|
||||
if (obj == NULL)
|
||||
return false;
|
||||
originalObj = obj;
|
||||
return buildNameList();
|
||||
return buildNameList(engine->meta);
|
||||
}
|
||||
|
||||
// Iterate over LocalBindings
|
||||
bool ForIteratorObject::buildNameList()
|
||||
bool ForIteratorObject::buildNameList(JS2Metadata *meta)
|
||||
{
|
||||
if (obj->kind == ClassKind) {
|
||||
JS2Class *c = checked_cast<JS2Class *>(obj);
|
||||
nameList = new const String *[c->localBindings.size()];
|
||||
length = 0;
|
||||
for (LocalBindingIterator bi = c->localBindings.begin(), bend = c->localBindings.end(); (bi != bend); bi++) {
|
||||
LocalBindingEntry *lbe = *bi;
|
||||
nameList[length++] = &lbe->name;
|
||||
}
|
||||
}
|
||||
else {
|
||||
LocalBindingMap *lMap = NULL;
|
||||
if (obj->kind == SimpleInstanceKind)
|
||||
lMap = &(checked_cast<SimpleInstance *>(obj))->localBindings;
|
||||
else
|
||||
if (obj->kind == PackageKind)
|
||||
lMap = &(checked_cast<Package *>(obj))->localBindings;
|
||||
else
|
||||
if (obj->kind == ClassKind)
|
||||
lMap = &(checked_cast<JS2Class *>(obj))->localBindings;
|
||||
LocalBindingMap *lMap = NULL;
|
||||
if (obj->kind == SimpleInstanceKind)
|
||||
lMap = &(checked_cast<SimpleInstance *>(obj))->localBindings;
|
||||
else
|
||||
if (obj->kind == PackageKind)
|
||||
lMap = &(checked_cast<Package *>(obj))->localBindings;
|
||||
else
|
||||
if (obj->kind == ClassKind)
|
||||
lMap = &(checked_cast<JS2Class *>(obj))->localBindings;
|
||||
|
||||
if (lMap) {
|
||||
nameList = new const String *[lMap->size()];
|
||||
length = 0;
|
||||
for (LocalBindingIterator bi = lMap->begin(), bend = lMap->end(); (bi != bend); bi++) {
|
||||
LocalBindingEntry *lbe = *bi;
|
||||
nameList[length++] = &lbe->name;
|
||||
if (lMap) {
|
||||
nameList = new const String *[lMap->size()];
|
||||
length = 0;
|
||||
for (LocalBindingIterator bi = lMap->begin(), bend = lMap->end(); (bi != bend); bi++) {
|
||||
LocalBindingEntry *lbe = *bi;
|
||||
for (LocalBindingEntry::NS_Iterator i = lbe->begin(), end = lbe->end(); (i != end); i++) {
|
||||
LocalBindingEntry::NamespaceBinding ns = *i;
|
||||
if ((ns.first == meta->publicNamespace) && ns.second->enumerable)
|
||||
nameList[length++] = &lbe->name;
|
||||
}
|
||||
it = 0;
|
||||
return (length != 0);
|
||||
}
|
||||
it = 0;
|
||||
return (length != 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1086,7 +1083,7 @@ namespace MetaData {
|
|||
if (!JS2VAL_IS_NULL(protoval)) {
|
||||
if (JS2VAL_IS_OBJECT(protoval)) {
|
||||
obj = JS2VAL_TO_OBJECT(protoval);
|
||||
return buildNameList();
|
||||
return buildNameList(engine->meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -362,6 +362,10 @@ namespace MetaData {
|
|||
// if not available or result is not primitive then try property 'valueOf'
|
||||
// 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
|
||||
return engine->typeofString(x); // the 'typeof' string
|
||||
|
||||
if (hint == StringHint) {
|
||||
js2val result;
|
||||
if (invokeFunctionOnObject(x, engine->toString_StringAtom, result)) {
|
||||
|
|
|
@ -1544,7 +1544,7 @@ namespace MetaData {
|
|||
break;
|
||||
case ExprNode::This:
|
||||
{
|
||||
if (env->findThis(true) == JS2VAL_VOID)
|
||||
if (env->findThis(this, true) == JS2VAL_VOID)
|
||||
reportError(Exception::syntaxError, "No 'this' available", p->pos);
|
||||
}
|
||||
break;
|
||||
|
@ -2402,7 +2402,7 @@ doUnary:
|
|||
// findThis returns the value of this. If allowPrototypeThis is true, allow this to be defined
|
||||
// by either an instance member of a class or a prototype function. If allowPrototypeThis is
|
||||
// false, allow this to be defined only by an instance member of a class.
|
||||
js2val Environment::findThis(bool allowPrototypeThis)
|
||||
js2val Environment::findThis(JS2Metadata *meta, bool allowPrototypeThis)
|
||||
{
|
||||
FrameListIterator fi = getBegin();
|
||||
while (fi != getEnd()) {
|
||||
|
@ -2412,8 +2412,7 @@ doUnary:
|
|||
if (allowPrototypeThis || !checked_cast<ParameterFrame *>(pf)->prototype)
|
||||
return checked_cast<ParameterFrame *>(pf)->thisObject;
|
||||
// XXX for ECMA3, when we hit a package (read GlobalObject) return that as the 'this'
|
||||
// XXX should have 'ECMA3' compatibility flag in Environment?
|
||||
if (pf->kind == PackageKind)
|
||||
if ((pf->kind == PackageKind) && meta->cxt.E3compatibility)
|
||||
return OBJECT_TO_JS2VAL(pf);
|
||||
fi++;
|
||||
}
|
||||
|
@ -2427,7 +2426,7 @@ doUnary:
|
|||
// an error.
|
||||
void Environment::lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase, js2val *rval)
|
||||
{
|
||||
LookupKind lookup(true, findThis(false));
|
||||
LookupKind lookup(true, findThis(meta, false));
|
||||
FrameListIterator fi = getBegin();
|
||||
bool result = false;
|
||||
while (fi != getEnd()) {
|
||||
|
@ -2470,7 +2469,7 @@ doUnary:
|
|||
// exists, then fine. Otherwise create the property there.
|
||||
void Environment::lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing)
|
||||
{
|
||||
LookupKind lookup(true, findThis(false));
|
||||
LookupKind lookup(true, findThis(meta, false));
|
||||
FrameListIterator fi = getBegin();
|
||||
bool result = false;
|
||||
while (fi != getEnd()) {
|
||||
|
@ -2513,7 +2512,8 @@ doUnary:
|
|||
if (result)
|
||||
return;
|
||||
}
|
||||
meta->reportError(Exception::referenceError, "{0} is undefined", meta->engine->errorPos(), multiname->name);
|
||||
if (!meta->cxt.E3compatibility)
|
||||
meta->reportError(Exception::referenceError, "{0} is undefined", meta->engine->errorPos(), multiname->name);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2521,7 +2521,7 @@ doUnary:
|
|||
// but it had darn well better be in the environment somewhere.
|
||||
void Environment::lexicalInit(JS2Metadata *meta, Multiname *multiname, js2val newValue)
|
||||
{
|
||||
LookupKind lookup(true, findThis(false));
|
||||
LookupKind lookup(true, findThis(meta, false));
|
||||
FrameListIterator fi = getBegin();
|
||||
bool result = false;
|
||||
while (fi != getEnd()) {
|
||||
|
@ -2570,7 +2570,7 @@ doUnary:
|
|||
// can't be found, or the result of the deleteProperty call if it was found.
|
||||
bool Environment::lexicalDelete(JS2Metadata *meta, Multiname *multiname, Phase phase)
|
||||
{
|
||||
LookupKind lookup(true, findThis(false));
|
||||
LookupKind lookup(true, findThis(meta, false));
|
||||
FrameListIterator fi = getBegin();
|
||||
bool result = false;
|
||||
while (fi != getEnd()) {
|
||||
|
@ -2643,7 +2643,7 @@ doUnary:
|
|||
************************************************************************************/
|
||||
|
||||
// clone a context
|
||||
Context::Context(Context *cxt) : strict(cxt->strict), openNamespaces(cxt->openNamespaces)
|
||||
Context::Context(Context *cxt) : strict(cxt->strict), E3compatibility(cxt->E3compatibility), openNamespaces(cxt->openNamespaces)
|
||||
{
|
||||
ASSERT(false); // ?? used ??
|
||||
}
|
||||
|
@ -3218,7 +3218,7 @@ static const uint8 urlCharType[256] =
|
|||
{
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *obj = JS2VAL_TO_OBJECT(thisValue);
|
||||
if (obj->kind == PackageKind) {
|
||||
if ((obj->kind == PackageKind) && meta->cxt.E3compatibility) {
|
||||
// special case this for now, ECMA3 test sanity...
|
||||
return GlobalObject_toString(meta, thisValue, NULL, 0);
|
||||
}
|
||||
|
@ -3570,7 +3570,7 @@ XXX see EvalAttributeExpression, where identifiers are being handled for now...
|
|||
Member *JS2Metadata::findCommonMember(js2val *base, Multiname *multiname, Access access, bool flat)
|
||||
{
|
||||
Member *m = NULL;
|
||||
if (JS2VAL_IS_PRIMITIVE(*base)) {
|
||||
if (JS2VAL_IS_PRIMITIVE(*base) && cxt.E3compatibility) {
|
||||
*base = toObject(*base); // XXX E3 compatibility...
|
||||
}
|
||||
JS2Object *baseObj = JS2VAL_TO_OBJECT(*base);
|
||||
|
|
|
@ -647,7 +647,7 @@ public:
|
|||
void addFrame(Frame *f) { frameList.push_front(f); }
|
||||
void removeTopFrame() { frameList.pop_front(); }
|
||||
|
||||
js2val findThis(bool allowPrototypeThis);
|
||||
js2val findThis(JS2Metadata *meta, bool allowPrototypeThis);
|
||||
void lexicalRead(JS2Metadata *meta, Multiname *multiname, Phase phase, js2val *rval);
|
||||
void lexicalWrite(JS2Metadata *meta, Multiname *multiname, js2val newValue, bool createIfMissing);
|
||||
void lexicalInit(JS2Metadata *meta, Multiname *multiname, js2val newValue);
|
||||
|
@ -867,7 +867,7 @@ class ForIteratorObject : public JS2Object {
|
|||
public:
|
||||
ForIteratorObject(JS2Object *obj) : JS2Object(ForIteratorKind), obj(obj), nameList(NULL) { }
|
||||
|
||||
bool first();
|
||||
bool first(JS2Engine *engine);
|
||||
bool next(JS2Engine *engine);
|
||||
|
||||
js2val value(JS2Engine *engine);
|
||||
|
@ -880,7 +880,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
bool buildNameList();
|
||||
bool buildNameList(JS2Metadata *meta);
|
||||
|
||||
const String **nameList;
|
||||
uint32 it;
|
||||
|
@ -1101,9 +1101,10 @@ typedef NamespaceList::iterator NamespaceListIterator;
|
|||
// A CONTEXT carries static information about a particular point in the source program.
|
||||
class Context {
|
||||
public:
|
||||
Context() : strict(false) { }
|
||||
Context() : strict(false), E3compatibility(true) { }
|
||||
Context(Context *cxt);
|
||||
bool strict; // true if strict mode is in effect
|
||||
bool E3compatibility;
|
||||
NamespaceList openNamespaces; // The set of namespaces that are open at this point.
|
||||
// The public namespace is always a member of this set.
|
||||
};
|
||||
|
|
|
@ -71,8 +71,10 @@
|
|||
pc += sizeof(short);
|
||||
b = pop();
|
||||
JS2Class *limit = meta->objectType(b);
|
||||
if (!limit->write(meta, b, limit, mn, &lookup, true, a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
|
||||
if (!limit->write(meta, b, limit, mn, &lookup, true, a)) {
|
||||
if (!meta->cxt.E3compatibility)
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
|
||||
}
|
||||
push(a);
|
||||
}
|
||||
break;
|
||||
|
@ -190,8 +192,10 @@
|
|||
astr = meta->toString(indexVal);
|
||||
Multiname mn(&meta->world.identifiers[*astr], meta->publicNamespace);
|
||||
JS2Class *limit = meta->objectType(b);
|
||||
if (!limit->bracketWrite(meta, b, limit, &mn, a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
|
||||
if (!limit->bracketWrite(meta, b, limit, &mn, a)) {
|
||||
if (!meta->cxt.E3compatibility)
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
|
||||
}
|
||||
push(a);
|
||||
indexVal = JS2VAL_VOID;
|
||||
astr = NULL;
|
||||
|
@ -243,8 +247,10 @@
|
|||
b = pop();
|
||||
Multiname mn(&meta->world.identifiers[*JS2VAL_TO_STRING(indexVal)], meta->publicNamespace);
|
||||
JS2Class *limit = meta->objectType(b);
|
||||
if (!limit->bracketWrite(meta, b, limit, &mn, a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
|
||||
if (!limit->bracketWrite(meta, b, limit, &mn, a)) {
|
||||
if (!meta->cxt.E3compatibility)
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
|
||||
}
|
||||
push(a);
|
||||
indexVal = JS2VAL_VOID;
|
||||
}
|
||||
|
|
|
@ -116,7 +116,7 @@
|
|||
b = meta->toObject(a);
|
||||
ForIteratorObject *fi = new ForIteratorObject(JS2VAL_TO_OBJECT(b));
|
||||
push(OBJECT_TO_JS2VAL(fi));
|
||||
push(BOOLEAN_TO_JS2VAL(fi->first()));
|
||||
push(BOOLEAN_TO_JS2VAL(fi->first(this)));
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
|
||||
case eThis: // XXX literal?
|
||||
{
|
||||
a = meta->env->findThis(true);
|
||||
a = meta->env->findThis(meta, true);
|
||||
if (JS2VAL_IS_INACCESSIBLE(a))
|
||||
meta->reportError(Exception::compileExpressionError, "'this' not available", errorPos());
|
||||
push(a);
|
||||
|
|
Загрузка…
Ссылка в новой задаче