diff --git a/mozilla/js2/src/bytecodegen.cpp b/mozilla/js2/src/bytecodegen.cpp index 4342beccb4a..725f176e7fb 100644 --- a/mozilla/js2/src/bytecodegen.cpp +++ b/mozilla/js2/src/bytecodegen.cpp @@ -423,16 +423,22 @@ uint32 ByteCodeGen::getLabel(LabelStmtNode *lbl) uint32 ByteCodeGen::getTopLabel(Label::LabelKind kind, const StringAtom *name, StmtNode *p) { uint32 result = uint32(-1); + bool foundName = false; + bool foundLabel = false; for (std::vector::reverse_iterator i = mLabelStack.rbegin(), end = mLabelStack.rend(); (i != end); i++) { - // find the closest kind of label - if (mLabelList[*i].matches(kind)) + // find the appropriate kind of label + if (mLabelList[*i].matches(kind)) { result = *i; + foundLabel = true; + } else // and return it when we get the name - if (mLabelList[*i].matches(name)) - return result; + if (mLabelList[*i].matches(name)) { + if (foundLabel) + return result; + } } m_cx->reportError(Exception::syntaxError, "label not found", p->pos); return false; @@ -852,25 +858,6 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3 case StmtNode::ForIn: { ForStmtNode *f = checked_cast(p); - Reference *value = NULL; - - if (f->initializer->getKind() == StmtNode::Var) { - VariableStmtNode *vs = checked_cast(f->initializer); - VariableBinding *v = vs->bindings; - value = mScopeChain->getName(*v->name, CURRENT_ATTR, Write); - } - else { - if (f->initializer->getKind() == StmtNode::expression) { - ExprStmtNode *e = checked_cast(f->initializer); - value = genReference(e->expr, Write); - } - else - NOT_REACHED("what else??"); - } - if (value == NULL) - m_cx->reportError(Exception::referenceError, "Invalid for..in target"); - - uint16 valueBaseDepth = value->baseExpressionDepth(); uint32 breakLabel = getLabel(Label::BreakLabel); uint32 labelAtTopOfBlock = getLabel(); @@ -917,14 +904,23 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3 addFixup(labelAtTestCondition); setLabel(labelAtTopOfBlock); - if (valueBaseDepth) { - if (valueBaseDepth > 1) { - addOpAdjustDepth(DupNOp, valueBaseDepth); - addShort(valueBaseDepth); + + Reference *value = NULL; + if (f->initializer->getKind() == StmtNode::Var) { + VariableStmtNode *vs = checked_cast(f->initializer); + VariableBinding *v = vs->bindings; + value = mScopeChain->getName(*v->name, CURRENT_ATTR, Write); + } + else { + if (f->initializer->getKind() == StmtNode::expression) { + ExprStmtNode *e = checked_cast(f->initializer); + value = genReference(e->expr, Write); } else - addOp(DupOp); - } + NOT_REACHED("what else??"); + } + if (value == NULL) + m_cx->reportError(Exception::referenceError, "Invalid for..in target"); iteratorReadRef->emitCodeSequence(this); addOp(GetPropertyOp); addStringRef(m_cx->Value_StringAtom); @@ -969,15 +965,16 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3 addOp(PopOp); setLabel(labelAtEnd); +/* if (valueBaseDepth) { if (valueBaseDepth > 1) { - addOpAdjustDepth(PopNOp, valueBaseDepth); + addOpAdjustDepth(PopNOp, -valueBaseDepth); addShort(valueBaseDepth); } else addOp(PopOp); } - +*/ delete objectReadRef; delete objectWriteRef; delete iteratorReadRef; @@ -1030,7 +1027,11 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3 { LabelStmtNode *l = checked_cast(p); mLabelStack.push_back(getLabel(l)); + uint32 breakLabel = getLabel(Label::BreakLabel); + mLabelStack.push_back(breakLabel); genCodeForStatement(l->stmt, static_cg, finallyLabel); + setLabel(breakLabel); + mLabelStack.pop_back(); mLabelStack.pop_back(); } break; @@ -1111,7 +1112,7 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3 switchTempReadRef->emitCodeSequence(this); genExpr(c->expr); addOp(DoOperatorOp); - addByte(Equal); + addByte(SpittingImage); addOp(JumpTrueOp); addFixup(c->label); } @@ -1185,19 +1186,17 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3 break; case StmtNode::Return: { + JSFunction *container = mScopeChain->getContainerFunction(); + if (!container) + m_cx->reportError(Exception::syntaxError, "return statement outside of function", p->pos); ExprStmtNode *e = checked_cast(p); if (e->expr) { genExpr(e->expr); - - JSFunction *container = mScopeChain->getContainerFunction(); - if (container) { - if (container->getResultType() != Object_Type) { - addOp(LoadTypeOp); - addPointer(container->getResultType()); - addOp(CastOp); - } + if (container->getResultType() != Object_Type) { + addOp(LoadTypeOp); + addPointer(container->getResultType()); + addOp(CastOp); } - ASSERT(mStackTop == 1); addOpSetDepth(ReturnOp, 0); } @@ -2195,11 +2194,23 @@ BinaryOpEquals: PairListExprNode *plen = checked_cast(p); ExprPairList *e = plen->pairs; while (e) { - if (e->field && e->value && (e->field->getKind() == ExprNode::identifier)) { + if (e->field && e->value) { addOp(DupOp); genExpr(e->value); addOp(SetPropertyOp); - addStringRef(checked_cast(e->field)->name); + switch (e->field->getKind()) { + case ExprNode::identifier: + addStringRef(checked_cast(e->field)->name); + break; + case ExprNode::string: + addStringRef(checked_cast(e->field)->str); + break; + case ExprNode::number: + addStringRef(*numberToString(checked_cast(e->field)->value)); + break; + default: + NOT_REACHED("bad field name"); + } addOp(PopOp); } e = e->next; diff --git a/mozilla/js2/src/js2execution.cpp b/mozilla/js2/src/js2execution.cpp index 6f81b23c316..0304197f523 100644 --- a/mozilla/js2/src/js2execution.cpp +++ b/mozilla/js2/src/js2execution.cpp @@ -63,6 +63,10 @@ namespace JavaScript { namespace JS2Runtime { +class JSException { +public: +}; + inline char narrow(char16 ch) { return char(ch); } @@ -91,13 +95,18 @@ JSValue Context::readEvalString(const String &str, const String& fileName, Scope } buildRuntime(parsedStatements); JS2Runtime::ByteCodeModule* bcm = genCode(parsedStatements, fileName); - if (bcm) { - setReader(NULL); - bcm->setSource(str, fileName); - result = interpret(bcm, 0, scopeChain, thisValue, NULL, 0); - delete bcm; + try { + if (bcm) { + setReader(NULL); + bcm->setSource(str, fileName); + result = interpret(bcm, 0, scopeChain, thisValue, NULL, 0); + delete bcm; + } + } + catch (JSException *x) { + setReader(oldReader); + throw x; } - setReader(oldReader); return result; } @@ -206,8 +215,35 @@ JSValue Context::interpret(JS2Runtime::ByteCodeModule *bcm, int offset, ScopeCha mStackMax = mCurModule->mStackDepth; mStackTop = 0; - JSValue result = interpret(pc, endPC); + JSValue result; + try { + result = interpret(pc, endPC); + } + catch (JSException *x) { + Activation *prev = mActivationStack.top(); + mActivationStack.pop(); + // the following (delete's) are a bit iffy - depends on whether + // a closure capturing the contents has come along... + if (mThis.isObject()) + mScopeChain->popScope(); + delete[] mStack; + delete[] mLocals; + if (scopeChain == NULL) + delete mScopeChain; + + mCurModule = prev->mModule; + mStack = prev->mStack; + mStackTop = prev->mStackTop; + if (mCurModule) + mStackMax = mCurModule->mStackDepth; + mLocals = prev->mLocals; + mArgumentBase = prev->mArgumentBase; + mThis = prev->mThis; + mScopeChain = prev->mScopeChain; + delete prev; + throw x; + } Activation *prev = mActivationStack.top(); mActivationStack.pop(); @@ -364,8 +400,8 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) mPC = pc; try { if (mDebugFlag) { - if (mCurModule->mFunction) { - FunctionName *fnName = mCurModule->mFunction->getFunctionName(); + FunctionName *fnName; + if (mCurModule->mFunction && (fnName = mCurModule->mFunction->getFunctionName())) { StringFormatter s; PrettyPrinter pp(s); fnName->print(pp); @@ -613,7 +649,7 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) mScopeChain->defineVariable(this, Arguments_StringAtom, NULL, Array_Type, JSValue(args)); } -// mScopeChain->addScope(mActivationStack.top()); + mScopeChain->addScope(target->getParameterBarrel()); mCurModule = target->getByteCode(); pc = mCurModule->mCodeBase; endPC = mCurModule->mCodeBase + mCurModule->mLength; @@ -884,11 +920,11 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) uint32 index = *((uint32 *)pc); pc += sizeof(uint32); const String &name = *mCurModule->getString(index); - JSValue v = topValue(); - if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { - popValue(); - pushValue(JSValue(v.function->getFunction())); - } + JSValue v = topValue(); + if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { + popValue(); + pushValue(JSValue(v.function->getFunction())); + } mScopeChain->setNameValue(this, name, CURRENT_ATTR); } break; @@ -941,8 +977,13 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) uint32 argCount = dimCount + 1; JSValue *argBase = buildArgumentBlock(target, argCount); resizeStack(stackSize() - (dimCount + 1)); - result = interpret(target->getByteCode(), 0, target->getScopeChain(), argBase[0], argBase, argCount); - delete[] argBase; + try { + result = interpret(target->getByteCode(), 0, target->getScopeChain(), argBase[0], argBase, argCount); + } + catch (JSException *x) { + delete[] argBase; + throw x; + } } pushValue(result); } @@ -974,9 +1015,9 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) if (target) { JSValue v = popValue(); // need to have this sitting right above the base value - if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { - v = JSValue(v.function->getFunction()); - } + if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { + v = JSValue(v.function->getFunction()); + } insertValue(v, mStackTop - dimCount); JSValue result; @@ -992,8 +1033,13 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) uint32 argCount = dimCount + 2; JSValue *argBase = buildArgumentBlock(target, argCount); resizeStack(stackSize() - (dimCount + 2)); - result = interpret(target->getByteCode(), 0, target->getScopeChain(), *baseValue, argBase, argCount); - delete[] argBase; + try { + result = interpret(target->getByteCode(), 0, target->getScopeChain(), *baseValue, argBase, argCount); + } + catch (JSException *x) { + delete[] argBase; + throw x; + } } pushValue(result); } @@ -1001,9 +1047,9 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) if (dimCount != 1) reportError(Exception::typeError, "too many indices"); JSValue v = popValue(); - if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { - v = JSValue(v.function->getFunction()); - } + if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { + v = JSValue(v.function->getFunction()); + } JSValue index = popValue(); popValue(); // discard base const String *name = index.toString(this).string; @@ -1042,8 +1088,13 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) uint32 argCount = dimCount + 1; JSValue *argBase = buildArgumentBlock(target, argCount); resizeStack(stackSize() - (dimCount + 1)); - result = interpret(target->getByteCode(), 0, target->getScopeChain(), kNullValue, argBase, argCount); - delete[] argBase; + try { + result = interpret(target->getByteCode(), 0, target->getScopeChain(), kNullValue, argBase, argCount); + } + catch (JSException *x) { + delete[] argBase; + throw x; + } } pushValue(result); } @@ -1115,9 +1166,9 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) case SetPropertyOp: { JSValue v = popValue(); - if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { - v = JSValue(v.function->getFunction()); - } + if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { + v = JSValue(v.function->getFunction()); + } JSValue base = popValue(); JSObject *obj = NULL; if (!base.isObject() && !base.isType()) @@ -1278,7 +1329,13 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) args->setProperty(this, *numberToString(i), NULL, argBase[i]); mScopeChain->defineVariable(this, Arguments_StringAtom, NULL, Array_Type, JSValue(args)); } - result = interpret(target->getByteCode(), 0, target->getScopeChain(), newThis, argBase, argCount); + try { + result = interpret(target->getByteCode(), 0, target->getScopeChain(), newThis, argBase, argCount); + } + catch (JSException *x) { + delete[] argBase; + throw x; + } } if (isPrototypeFunctionCall) { @@ -1321,10 +1378,10 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) { uint32 index = *((uint32 *)pc); pc += sizeof(uint32); - JSValue v = topValue(); - if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { - v = JSValue(v.function->getFunction()); - } + JSValue v = topValue(); + if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { + v = JSValue(v.function->getFunction()); + } mLocals[index] = v; } break; @@ -1339,10 +1396,10 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) break; case SetClosureVarOp: { - JSValue v = topValue(); - if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { - v = JSValue(v.function->getFunction()); - } + JSValue v = topValue(); + if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { + v = JSValue(v.function->getFunction()); + } uint32 depth = *((uint32 *)pc); pc += sizeof(uint32); uint32 index = *((uint32 *)pc); @@ -1368,10 +1425,10 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) break; case SetArgOp: { - JSValue v = topValue(); - if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { - v = JSValue(v.function->getFunction()); - } + JSValue v = topValue(); + if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { + v = JSValue(v.function->getFunction()); + } uint32 index = *((uint32 *)pc); pc += sizeof(uint32); mArgumentBase[index] = v; @@ -1407,9 +1464,9 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) case SetFieldOp: { JSValue v = popValue(); - if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { - v = JSValue(v.function->getFunction()); - } + if (v.isFunction() && v.function->hasBoundThis() && !v.function->isMethod()) { + v = JSValue(v.function->getFunction()); + } JSValue base = popValue(); ASSERT(dynamic_cast(base.object)); uint32 index = *((uint32 *)pc); @@ -1482,13 +1539,21 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) break; case ThrowOp: { - JSValue x = topValue(); + throw new JSException(); +/* if (mTryStack.size() > 0) { HandlerData *hndlr = (HandlerData *)mTryStack.top(); Activation *curAct = (mActivationStack.size() > 0) ? mActivationStack.top() : NULL; if (curAct != hndlr->mActivation) { - Activation *prev = mActivationStack.top(); + ASSERT(mActivationStack.size() > 0); + Activation *prev;// = mActivationStack.top(); do { + prev = curAct; + if (prev->mPC == NULL) { + // Yikes! the exception is getting thrown across a re-invocation + // of the interpreter loop. + ASSERT(false); + } mActivationStack.pop(); curAct = mActivationStack.top(); } while (hndlr->mActivation != curAct); @@ -1508,6 +1573,7 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) } else reportError(Exception::uncaughtError, "No handler for throw"); +*/ } break; case ClassOp: @@ -1571,6 +1637,41 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC) reportError(Exception::internalError, "Bad Opcode"); } } + catch (JSException *jsx) { + JSValue x = topValue(); + if (mTryStack.size() > 0) { + HandlerData *hndlr = (HandlerData *)mTryStack.top(); + Activation *curAct = (mActivationStack.size() > 0) ? mActivationStack.top() : NULL; + if (curAct != hndlr->mActivation) { + ASSERT(mActivationStack.size() > 0); + Activation *prev;// = mActivationStack.top(); + do { + prev = curAct; + if (prev->mPC == NULL) { + // Yikes! the exception is getting thrown across a re-invocation + // of the interpreter loop. + throw jsx; + } + mActivationStack.pop(); + curAct = mActivationStack.top(); + } while (hndlr->mActivation != curAct); + mCurModule = prev->mModule; + endPC = mCurModule->mCodeBase + mCurModule->mLength; + mLocals = prev->mLocals; + mStack = prev->mStack; + mStackTop = 1; // just the exception object remains + mStackMax = mCurModule->mStackDepth; + mArgumentBase = prev->mArgumentBase; + mThis = prev->mThis; + } + + resizeStack(hndlr->mStackSize); + pc = hndlr->mPC; + pushValue(x); + } + else + reportError(Exception::uncaughtError, "No handler for throw"); + } catch (Exception x) { throw x; } @@ -1943,6 +2044,52 @@ static JSValue objectEqual(Context *cx, const JSValue& /*thisValue*/, JSValue *a return compareEqual(cx, r1, r2); } +static JSValue objectSpittingImage(Context *cx, const JSValue& /*thisValue*/, JSValue *argv, uint32 /*argc*/) +{ + JSValue r1 = argv[0]; + JSValue r2 = argv[1]; + + JSType *t1 = r1.getType(); + JSType *t2 = r2.getType(); + + if (t1 != t2) { + return kFalseValue; + } + else { + if (r1.isUndefined()) + return kTrueValue; + if (r1.isNull()) + return kTrueValue; + if (r1.isObject() && r2.isObject()) // because new Boolean()->getType() == Boolean_Type + return JSValue(r1.object == r2.object); + if (r1.isType()) + return JSValue(r1.type == r2.type); + if (r1.isFunction()) + return JSValue(r1.function->isEqual(r2.function)); + if (t1 == Number_Type) { + + float64 f1 = r1.getNumberValue(); + float64 f2 = r2.getNumberValue(); + + if (JSDOUBLE_IS_NaN(f1)) + return kFalseValue; + if (JSDOUBLE_IS_NaN(f2)) + return kFalseValue; + + return JSValue(r1.f64 == r2.f64); + } + else { + if (t1 == String_Type) + return JSValue(bool(r1.getStringValue()->compare(*r2.getStringValue()) == 0)); + if (r1.isBool() && r2.isBool()) + return JSValue(r1.getBoolValue() == r2.getBoolValue()); + return kFalseValue; + } + } +} + + + void Context::initOperators() { struct OpTableEntry { @@ -1990,7 +2137,9 @@ void Context::initOperators() { Less, Object_Type, Object_Type, objectLess, Boolean_Type }, { LessEqual, Object_Type, Object_Type, objectLessEqual, Boolean_Type }, - { Equal, Object_Type, Object_Type, objectEqual, Boolean_Type } + { Equal, Object_Type, Object_Type, objectEqual, Boolean_Type }, + + { SpittingImage, Object_Type, Object_Type, objectSpittingImage, Boolean_Type } }; diff --git a/mozilla/js2/src/js2runtime.cpp b/mozilla/js2/src/js2runtime.cpp index de1dee078e1..d8fb6d9ca3d 100644 --- a/mozilla/js2/src/js2runtime.cpp +++ b/mozilla/js2/src/js2runtime.cpp @@ -227,7 +227,7 @@ void JSObject::defineTempVariable(Context *cx, Reference *&readRef, Reference *& char buf[32]; sprintf(buf, "%%tempvar%%_%d", tempVarCount++); const String &name = cx->mWorld.identifiers[buf]; - /* Property *prop = */defineVariable(cx, name, (NamespaceList *)NULL, type); + /* Property *prop = */defineVariable(cx, name, (NamespaceList *)NULL, Property::NoAttribute, type); readRef = new NameReference(name, Read, Object_Type, 0); writeRef = new NameReference(name, Write, Object_Type, 0); } @@ -255,7 +255,7 @@ Property *JSObject::defineVariable(Context *cx, const String &name, AttributeStm mProperties.insert(e); return prop; } -Property *JSObject::defineVariable(Context *cx, const String &name, NamespaceList *names, JSType *type) +Property *JSObject::defineVariable(Context *cx, const String &name, NamespaceList *names, PropertyAttribute attrFlags, JSType *type) { PropertyIterator it; if (hasOwnProperty(name, names, Read, &it)) { @@ -265,7 +265,7 @@ Property *JSObject::defineVariable(Context *cx, const String &name, NamespaceLis } } - Property *prop = new Property(new JSValue(), type, 0); + Property *prop = new Property(new JSValue(), type, attrFlags); const PropertyMap::value_type e(name, new NamespacedProperty(prop, names)); mProperties.insert(e); return prop; @@ -298,7 +298,7 @@ Property *JSObject::defineVariable(Context *cx, const String &name, AttributeStm mProperties.insert(e); return prop; } -Property *JSObject::defineVariable(Context *cx, const String &name, NamespaceList *names, JSType *type, const JSValue v) +Property *JSObject::defineVariable(Context *cx, const String &name, NamespaceList *names, PropertyAttribute attrFlags, JSType *type, const JSValue v) { PropertyIterator it; if (hasOwnProperty(name, names, Read, &it)) { @@ -307,7 +307,7 @@ Property *JSObject::defineVariable(Context *cx, const String &name, NamespaceLis } } - Property *prop = new Property(new JSValue(v), type, 0); + Property *prop = new Property(new JSValue(v), type, attrFlags); const PropertyMap::value_type e(name, new NamespacedProperty(prop, names)); mProperties.insert(e); return prop; @@ -440,7 +440,7 @@ void JSObject::setProperty(Context *cx, const String &name, NamespaceList *names } } else - defineVariable(cx, name, names, Object_Type, v); + defineVariable(cx, name, names, Property::Enumerable, Object_Type, v); } void JSType::setProperty(Context *cx, const String &name, NamespaceList *names, const JSValue &v) @@ -490,7 +490,7 @@ void JSInstance::setProperty(Context *cx, const String &name, NamespaceList *nam if (mType->hasOwnProperty(name, names, Write, &i)) mType->setProperty(cx, name, names, v); else - defineVariable(cx, name, names, Object_Type, v); + defineVariable(cx, name, names, Property::Enumerable, Object_Type, v); } } @@ -644,13 +644,8 @@ void ScopeChain::setNameValue(Context *cx, const String& name, AttributeStmtNode else ASSERT(false); // what else needs to be implemented ? } - else { - if ((*s)->mType == Object_Type) { - (*s)->defineVariable(cx, name, attr, Object_Type, v); - break; - } - } } + cx->getGlobalObject()->defineVariable(cx, name, attr, Object_Type, v); } inline char narrow(char16 ch) { return char(ch); } @@ -668,6 +663,9 @@ JSObject *ScopeChain::getNameValue(Context *cx, const String& name, AttributeStm case ValuePointer: cx->pushValue(*PROPERTY_VALUEPOINTER(i)); break; + case Slot: + cx->pushValue((*s)->getSlotValue(cx, PROPERTY_INDEX(i))); + break; default: ASSERT(false); // what else needs to be implemented ? } @@ -734,7 +732,11 @@ Reference *ParameterBarrel::genReference(bool /* hasBase */, const String& name, return NULL; } - +JSValue ParameterBarrel::getSlotValue(Context *cx, uint32 slotIndex) +{ + // Assume that the appropriate argument chunk is the topmost one + return cx->mArgumentBase[slotIndex]; +} @@ -910,6 +912,12 @@ void ScopeChain::collectNames(StmtNode *p) classStmt->mType = thisClass; } break; + case StmtNode::label: + { + LabelStmtNode *l = checked_cast(p); + collectNames(l->stmt); + } + break; case StmtNode::block: { // should push a new Activation scope here? @@ -1128,7 +1136,7 @@ void ScopeChain::collectNames(StmtNode *p) NamespaceStmtNode *n = checked_cast(p); Attribute *x = new Attribute(0, 0); x->mNamespaceList = new NamespaceList(&n->name, x->mNamespaceList); - m_cx->getGlobalObject()->defineVariable(m_cx, n->name, (NamespaceList *)(NULL), Attribute_Type, JSValue(x)); + m_cx->getGlobalObject()->defineVariable(m_cx, n->name, (NamespaceList *)(NULL), Property::NoAttribute, Attribute_Type, JSValue(x)); } break; default: @@ -1519,14 +1527,19 @@ void Context::buildRuntimeForStmt(StmtNode *p) } } break; + case StmtNode::label: + { + LabelStmtNode *l = checked_cast(p); + buildRuntimeForStmt(l->stmt); + } + break; case StmtNode::Try: { TryStmtNode *t = checked_cast(p); if (t->catches) { CatchClause *c = t->catches; while (c) { - if (c->type) - c->prop->mType = mScopeChain->extractType(c->type); + c->prop->mType = mScopeChain->extractType(c->type); c = c->next; } } @@ -1734,12 +1747,17 @@ static JSValue Object_forin(Context *cx, const JSValue& thisValue, JSValue * /*a IteratorDongle *itDude = new IteratorDongle(); itDude->obj = obj; itDude->it = obj->mProperties.begin(); - while (itDude->it == itDude->obj->mProperties.end()) { - itDude->obj = itDude->obj->mPrototype; - if (itDude->obj == NULL) - return kNullValue; - itDude->it = itDude->obj->mProperties.begin(); - } + while (true) { + while (itDude->it == itDude->obj->mProperties.end()) { + itDude->obj = itDude->obj->mPrototype; + if (itDude->obj == NULL) + return kNullValue; + itDude->it = itDude->obj->mProperties.begin(); + } + if (PROPERTY_ATTR(itDude->it) & Property::Enumerable) + break; + itDude->it++; + } JSValue v(&PROPERTY_NAME(itDude->it)); iteratorObject->setProperty(cx, cx->mWorld.identifiers["value"], 0, v); @@ -1755,13 +1773,17 @@ static JSValue Object_next(Context *cx, const JSValue& /*thisValue*/, JSValue *a IteratorDongle *itDude = (IteratorDongle *)(iteratorObject->mPrivate); itDude->it++; - - while (itDude->it == itDude->obj->mProperties.end()) { - itDude->obj = itDude->obj->mPrototype; - if (itDude->obj == NULL) - return kNullValue; - itDude->it = itDude->obj->mProperties.begin(); - } + while (true) { + while (itDude->it == itDude->obj->mProperties.end()) { + itDude->obj = itDude->obj->mPrototype; + if (itDude->obj == NULL) + return kNullValue; + itDude->it = itDude->obj->mProperties.begin(); + } + if (PROPERTY_ATTR(itDude->it) & Property::Enumerable) + break; + itDude->it++; + } JSValue v(&PROPERTY_NAME(itDude->it)); iteratorObject->setProperty(cx, cx->mWorld.identifiers["value"], 0, v); return iteratorValue; @@ -2063,7 +2085,7 @@ JSFunction::JSFunction(Context *cx, JSType *resultType, ScopeChain *scopeChain) if (Function_Type) // protect against bootstrap mPrototype = Function_Type->mPrototypeObject; mActivation.mContainer = this; - defineVariable(cx, cx->Length_StringAtom, (NamespaceList *)NULL, Number_Type, JSValue((float64)0)); + defineVariable(cx, cx->Length_StringAtom, (NamespaceList *)NULL, Property::NoAttribute, Number_Type, JSValue((float64)0)); } JSFunction::JSFunction(Context *cx, NativeCode *code, JSType *resultType) @@ -2088,7 +2110,7 @@ JSFunction::JSFunction(Context *cx, NativeCode *code, JSType *resultType) if (Function_Type) // protect against bootstrap mPrototype = Function_Type->mPrototypeObject; mActivation.mContainer = this; - defineVariable(cx, cx->Length_StringAtom, (NamespaceList *)NULL, Number_Type, JSValue((float64)0)); + defineVariable(cx, cx->Length_StringAtom, (NamespaceList *)NULL, Property::NoAttribute, Number_Type, JSValue((float64)0)); } JSValue JSFunction::runArgInitializer(Context *cx, uint32 a, const JSValue& thisValue, JSValue *argv, uint32 argc) @@ -2153,6 +2175,7 @@ void Context::initClass(JSType *type, ClassDef *cdef, PrototypeFunctions *pdef) fun->setArgCounts(this, pdef->mDef[i].length, 0, false); type->mPrototypeObject->defineVariable(this, *name, (NamespaceList *)(NULL), + Property::NoAttribute, pdef->mDef[i].result, JSValue(fun)); } @@ -2160,7 +2183,7 @@ void Context::initClass(JSType *type, ClassDef *cdef, PrototypeFunctions *pdef) type->completeClass(this, mScopeChain); type->setStaticInitializer(this, NULL); type->mUninitializedValue = *cdef->uninit; - getGlobalObject()->defineVariable(this, widenCString(cdef->name), (NamespaceList *)(NULL), Type_Type, JSValue(type)); + getGlobalObject()->defineVariable(this, widenCString(cdef->name), (NamespaceList *)(NULL), Property::NoAttribute, Type_Type, JSValue(type)); mScopeChain->popScope(); if (pdef) delete pdef; } @@ -2436,7 +2459,7 @@ Context::Context(JSObject **global, World &world, Arena &a, Pragma::Flags flags) JSObject *mathObj = Object_Type->newInstance(this); - getGlobalObject()->defineVariable(this, Math_StringAtom, (NamespaceList *)(NULL), Object_Type, JSValue(mathObj)); + getGlobalObject()->defineVariable(this, Math_StringAtom, (NamespaceList *)(NULL), Property::NoAttribute, Object_Type, JSValue(mathObj)); initMathObject(this, mathObj); initDateObject(this); @@ -2478,11 +2501,11 @@ Context::Context(JSObject **global, World &world, Arena &a, Pragma::Flags flags) for (i = 0; i < (sizeof(attribute_init) / sizeof(Attribute_Init)); i++) { Attribute *attr = new Attribute(attribute_init[i].trueFlags, attribute_init[i].falseFlags); - getGlobalObject()->defineVariable(this, widenCString(attribute_init[i].name), (NamespaceList *)(NULL), Attribute_Type, JSValue(attr)); + getGlobalObject()->defineVariable(this, widenCString(attribute_init[i].name), (NamespaceList *)(NULL), Property::NoAttribute, Attribute_Type, JSValue(attr)); } JSFunction *x = new JSFunction(this, ExtendAttribute_Invoke, Attribute_Type); - getGlobalObject()->defineVariable(this, Extend_StringAtom, (NamespaceList *)(NULL), Attribute_Type, JSValue(x)); + getGlobalObject()->defineVariable(this, Extend_StringAtom, (NamespaceList *)(NULL), Property::NoAttribute, Attribute_Type, JSValue(x)); @@ -2499,7 +2522,7 @@ Context::Context(JSObject **global, World &world, Arena &a, Pragma::Flags flags) x = new JSFunction(this, globalObjectFunctions[i].imp, globalObjectFunctions[i].result); x->setArgCounts(this, globalObjectFunctions[i].length, 0, false); x->setIsPrototype(true); - getGlobalObject()->defineVariable(this, widenCString(globalObjectFunctions[i].name), (NamespaceList *)(NULL), globalObjectFunctions[i].result, JSValue(x)); + getGlobalObject()->defineVariable(this, widenCString(globalObjectFunctions[i].name), (NamespaceList *)(NULL), Property::NoAttribute, globalObjectFunctions[i].result, JSValue(x)); } /* @@ -2514,9 +2537,9 @@ Context::Context(JSObject **global, World &world, Arena &a, Pragma::Flags flags) getGlobalObject()->defineVariable(this, widenCString("parseInt"), (NamespaceList *)(NULL), Object_Type, JSValue(x)); */ - getGlobalObject()->defineVariable(this, Undefined_StringAtom, (NamespaceList *)(NULL), Void_Type, kUndefinedValue); - getGlobalObject()->defineVariable(this, NaN_StringAtom, (NamespaceList *)(NULL), Void_Type, kNaNValue); - getGlobalObject()->defineVariable(this, Infinity_StringAtom, (NamespaceList *)(NULL), Void_Type, kPositiveInfinity); + getGlobalObject()->defineVariable(this, Undefined_StringAtom, (NamespaceList *)(NULL), Property::NoAttribute, Void_Type, kUndefinedValue); + getGlobalObject()->defineVariable(this, NaN_StringAtom, (NamespaceList *)(NULL), Property::NoAttribute, Void_Type, kNaNValue); + getGlobalObject()->defineVariable(this, Infinity_StringAtom, (NamespaceList *)(NULL), Property::NoAttribute, Void_Type, kPositiveInfinity); } diff --git a/mozilla/js2/src/js2runtime.h b/mozilla/js2/src/js2runtime.h index 2a87802abdc..f4ad88807ba 100644 --- a/mozilla/js2/src/js2runtime.h +++ b/mozilla/js2/src/js2runtime.h @@ -551,7 +551,7 @@ XXX ...couldn't get this to work... // add a property virtual Property *defineVariable(Context *cx, const String &name, AttributeStmtNode *attr, JSType *type); - virtual Property *defineVariable(Context *cx, const String &name, NamespaceList *names, JSType *type); + virtual Property *defineVariable(Context *cx, const String &name, NamespaceList *names, PropertyAttribute attrFlags, JSType *type); // add a property/value into the map // - assumes the map doesn't already have this property @@ -588,7 +588,7 @@ XXX ...couldn't get this to work... virtual void defineSetterMethod(Context *cx, const String &name, AttributeStmtNode *attr, JSFunction *f); virtual Property *defineVariable(Context *cx, const String &name, AttributeStmtNode *attr, JSType *type, const JSValue v); - virtual Property *defineVariable(Context *cx, const String &name, NamespaceList *names, JSType *type, const JSValue v); + virtual Property *defineVariable(Context *cx, const String &name, NamespaceList *names, PropertyAttribute attrFlags, JSType *type, const JSValue v); virtual Reference *genReference(bool hasBase, const String& name, NamespaceList *names, Access acc, uint32 depth); @@ -601,6 +601,8 @@ XXX ...couldn't get this to work... virtual void defineTempVariable(Context *cx, Reference *&readRef, Reference *&writeRef, JSType *type); + virtual JSValue getSlotValue(Context *cx, uint32 slotIndex) { ASSERT(false); return kUndefinedValue; } + // debug only void printProperties(Formatter &f) const { @@ -866,6 +868,8 @@ XXX ...couldn't get this to work... // captures the Parameter names scope + // it's a JSType simply because it's also a thing that + // maps from names to slots. class ParameterBarrel : public JSType { public: @@ -881,6 +885,8 @@ XXX ...couldn't get this to work... Reference *genReference(bool hasBase, const String& name, NamespaceList *names, Access acc, uint32 depth); + JSValue getSlotValue(Context *cx, uint32 slotIndex); + }; @@ -1218,6 +1224,8 @@ XXX ...couldn't get this to work... bool isMethod() { return (mClass != NULL); } virtual ByteCodeModule *getByteCode() { ASSERT(!isNative()); return mByteCode; } virtual NativeCode *getNativeCode() { ASSERT(isNative()); return mCode; } + virtual ParameterBarrel *getParameterBarrel() + { return mParameterBarrel; } virtual JSType *getResultType() { return mResultType; } virtual JSType *getArgType(uint32 a) { ASSERT(mArguments && (a < (mRequiredArgs + mOptionalArgs))); return mArguments[a].mType; } @@ -1268,7 +1276,7 @@ XXX ...couldn't get this to work... JSObject *mThis; public: JSBoundFunction(JSFunction *f, JSObject *thisObj) - : mFunction(f), mThis(thisObj) { } + : mFunction(NULL), mThis(thisObj) { if (f->hasBoundThis()) mFunction = f->getFunction(); else mFunction = f; } ~JSBoundFunction() { } // keeping gcc happy @@ -1278,7 +1286,8 @@ XXX ...couldn't get this to work... bool isConstructor() { return mFunction->isConstructor(); } ByteCodeModule *getByteCode() { return mFunction->getByteCode(); } NativeCode *getNativeCode() { return mFunction->getNativeCode(); } - + ParameterBarrel *getParameterBarrel() + { return mFunction->mParameterBarrel; } JSType *getResultType() { return mFunction->getResultType(); } JSType *getArgType(uint32 a) { return mFunction->getArgType(a); } bool argHasInitializer(uint32 a){ return mFunction->argHasInitializer(a); } diff --git a/mozilla/js2/src/jsarray.cpp b/mozilla/js2/src/jsarray.cpp index 54f7bb37b57..9c6e7ae6623 100644 --- a/mozilla/js2/src/jsarray.cpp +++ b/mozilla/js2/src/jsarray.cpp @@ -68,7 +68,7 @@ JSValue Array_Constructor(Context *cx, const JSValue& thisValue, JSValue *argv, arrInst->mLength = argc; for (uint32 i = 0; i < argc; i++) { const String *id = numberToString(i); - arrInst->defineVariable(cx, *id, (NamespaceList *)(NULL), Object_Type, argv[i]); + arrInst->defineVariable(cx, *id, (NamespaceList *)(NULL), Property::Enumerable, Object_Type, argv[i]); delete id; } } @@ -137,7 +137,7 @@ static JSValue Array_push(Context *cx, const JSValue& thisValue, JSValue *argv, for (uint32 i = 0; i < argc; i++) { const String *id = numberToString(i + arrInst->mLength); - arrInst->defineVariable(cx, *id, (NamespaceList *)(NULL), Object_Type, argv[i]); + arrInst->defineVariable(cx, *id, (NamespaceList *)(NULL), Property::NoAttribute, Object_Type, argv[i]); delete id; } arrInst->mLength += argc; @@ -573,7 +573,7 @@ JSValue Array_SetElement(Context *cx, const JSValue& thisValue, JSValue *argv, u if (isArrayIndex(cx, index, intIndex)) { PropertyIterator it = thisObj->findNamespacedProperty(*name, NULL); if (it == thisObj->mProperties.end()) - thisObj->insertNewProperty(*name, NULL, 0, Object_Type, argv[1]); + thisObj->insertNewProperty(*name, NULL, Property::Enumerable, Object_Type, argv[1]); else { Property *prop = PROPERTY(it); ASSERT(prop->mFlag == ValuePointer); diff --git a/mozilla/js2/src/jsdate.cpp b/mozilla/js2/src/jsdate.cpp index b4f67fb9873..c62651a0d01 100644 --- a/mozilla/js2/src/jsdate.cpp +++ b/mozilla/js2/src/jsdate.cpp @@ -673,34 +673,34 @@ static JSValue Date_format(Context * /*cx*/, float64 date, formatspec format) StringFormatter outf; char tzbuf[100]; bool usetz; - size_t i, tzlen; + size_t i, tzlen, bytesStored; PRMJTime split; if (!JSDOUBLE_IS_FINITE(date)) { - outf << js_NaN_date_str; + outf << js_NaN_date_str; } else { - float64 local = LocalTime(date); + float64 local = LocalTime(date); - /* offset from GMT in minutes. The offset includes daylight savings, - if it applies. */ + /* offset from GMT in minutes. The offset includes daylight savings, + if it applies. */ int32 minutes = (int32)fd::floor((LocalTZA + DaylightSavingTA(date)) / msPerMinute); - /* map 510 minutes to 0830 hours */ - int32 offset = (minutes / 60) * 100 + minutes % 60; + /* map 510 minutes to 0830 hours */ + int32 offset = (minutes / 60) * 100 + minutes % 60; - /* print as "Wed Nov 05 19:38:03 GMT-0800 (PST) 1997" The TZA is - * printed as 'GMT-0800' rather than as 'PST' to avoid - * operating-system dependence on strftime (which - * PRMJ_FormatTimeUSEnglish calls, for %Z only.) win32 prints - * PST as 'Pacific Standard Time.' This way we always know - * what we're getting, and can parse it if we produce it. - * The OS TZA string is included as a comment. - */ + /* print as "Wed Nov 05 19:38:03 GMT-0800 (PST) 1997" The TZA is + * printed as 'GMT-0800' rather than as 'PST' to avoid + * operating-system dependence on strftime (which + * PRMJ_FormatTimeUSEnglish calls, for %Z only.) win32 prints + * PST as 'Pacific Standard Time.' This way we always know + * what we're getting, and can parse it if we produce it. + * The OS TZA string is included as a comment. + */ - /* get a timezone string from the OS to include as a - comment. */ - new_explode(date, &split, true); - PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &split); + /* get a timezone string from the OS to include as a + comment. */ + new_explode(date, &split, true); + bytesStored = PRMJ_FormatTime(tzbuf, sizeof tzbuf, "(%Z)", &split); /* Decide whether to use the resulting timezone string. * @@ -708,23 +708,27 @@ static JSValue Date_format(Context * /*cx*/, float64 date, formatspec format) * It's then likely in some other character encoding, and we probably * won't display it correctly. */ - usetz = true; - tzlen = strlen(tzbuf); - if (tzlen > 100) { - usetz = false; - } else { - for (i = 0; i < tzlen; i++) { - int16 c = tzbuf[i]; - if (c > 127 || - !(isalpha(c) || isdigit(c) || - c == ' ' || c == '(' || c == ')')) { - usetz = false; + if (bytesStored > 0) { + usetz = true; + tzlen = strlen(tzbuf); + if (tzlen > 100) { + usetz = false; + } else { + for (i = 0; i < tzlen; i++) { + int16 c = tzbuf[i]; + if (c > 127 || + !(isalpha(c) || isdigit(c) || + c == ' ' || c == '(' || c == ')')) { + usetz = false; + } } } - } - /* Also reject it if it's not parenthesized or if it's '()'. */ - if (tzbuf[0] != '(' || tzbuf[1] == ')') + /* Also reject it if it's not parenthesized or if it's '()'. */ + if (tzbuf[0] != '(' || tzbuf[1] == ')') + usetz = false; + } + else usetz = false; switch (format) { diff --git a/mozilla/js2/src/jsmath.cpp b/mozilla/js2/src/jsmath.cpp index c1062b68671..56b1a6e1765 100644 --- a/mozilla/js2/src/jsmath.cpp +++ b/mozilla/js2/src/jsmath.cpp @@ -246,12 +246,13 @@ void initMathObject(Context *cx, JSObject *mathObj) uint32 i; for (i = 0; i < M_CONSTANTS_COUNT; i++) mathObj->defineVariable(cx, widenCString(MathObjectConstants[i].name), - (NamespaceList *)(NULL), Number_Type, JSValue(MathObjectConstants[i].value)); + (NamespaceList *)(NULL), Property::NoAttribute, + Number_Type, JSValue(MathObjectConstants[i].value)); for (i = 0; i < sizeof(MathObjectFunctions) / sizeof(MathObjectFunctionDef); i++) { JSFunction *f = new JSFunction(cx, MathObjectFunctions[i].imp, Number_Type); mathObj->defineVariable(cx, widenCString(MathObjectFunctions[i].name), - (NamespaceList *)(NULL), Number_Type, JSValue(f)); + (NamespaceList *)(NULL), Property::NoAttribute, Number_Type, JSValue(f)); } } diff --git a/mozilla/js2/tests/cpp/DikDik_Shell.cpp b/mozilla/js2/tests/cpp/DikDik_Shell.cpp index 691284541e9..f9deaf27486 100644 --- a/mozilla/js2/tests/cpp/DikDik_Shell.cpp +++ b/mozilla/js2/tests/cpp/DikDik_Shell.cpp @@ -257,12 +257,12 @@ int main(int argc, char **argv) JSObject *globalObject; Context cx(&globalObject, world, a, Pragma::js2); - globalObject->defineVariable(&cx, widenCString("load"), (NamespaceList *)(NULL), NULL, JSValue(new JSFunction(&cx, load, NULL))); - globalObject->defineVariable(&cx, widenCString("print"), (NamespaceList *)(NULL), NULL, JSValue(new JSFunction(&cx, print, NULL))); - globalObject->defineVariable(&cx, widenCString("debug"), (NamespaceList *)(NULL), NULL, JSValue(new JSFunction(&cx, debug, NULL))); - globalObject->defineVariable(&cx, widenCString("trace"), (NamespaceList *)(NULL), NULL, JSValue(new JSFunction(&cx, trace, NULL))); - globalObject->defineVariable(&cx, widenCString("dikdik"), (NamespaceList *)(NULL), NULL, JSValue(new JSFunction(&cx, dikdik, NULL))); - globalObject->defineVariable(&cx, widenCString("version"), (NamespaceList *)(NULL), NULL, JSValue(new JSFunction(&cx, version, NULL))); + globalObject->defineVariable(&cx, widenCString("load"), (NamespaceList *)(NULL), Property::NoAttribute, NULL, JSValue(new JSFunction(&cx, load, NULL))); + globalObject->defineVariable(&cx, widenCString("print"), (NamespaceList *)(NULL), Property::NoAttribute, NULL, JSValue(new JSFunction(&cx, print, NULL))); + globalObject->defineVariable(&cx, widenCString("debug"), (NamespaceList *)(NULL), Property::NoAttribute, NULL, JSValue(new JSFunction(&cx, debug, NULL))); + globalObject->defineVariable(&cx, widenCString("trace"), (NamespaceList *)(NULL), Property::NoAttribute, NULL, JSValue(new JSFunction(&cx, trace, NULL))); + globalObject->defineVariable(&cx, widenCString("dikdik"), (NamespaceList *)(NULL), Property::NoAttribute, NULL, JSValue(new JSFunction(&cx, dikdik, NULL))); + globalObject->defineVariable(&cx, widenCString("version"), (NamespaceList *)(NULL), Property::NoAttribute, NULL, JSValue(new JSFunction(&cx, version, NULL))); bool doInteractive = true; int result = 0;