Fixing for..in, runaway string allocation, array.length initialization.

This commit is contained in:
rogerl%netscape.com 2003-04-04 23:24:57 +00:00
Родитель cb6b7d86a9
Коммит 93fb6ad7bd
9 изменённых файлов: 89 добавлений и 68 удалений

Просмотреть файл

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