Snapshot of latest fixes for expression/statement/date/boolean/types ECMA
test suite related bug fixing.
This commit is contained in:
Родитель
2c954b679c
Коммит
f1acd9f856
|
@ -105,6 +105,13 @@ void StaticFieldReference::emitImplicitLoad(ByteCodeGen *bcg)
|
|||
bcg->addPointer(mClass);
|
||||
}
|
||||
|
||||
void StaticFieldReference::emitDelete(ByteCodeGen *bcg)
|
||||
{
|
||||
bcg->addOp(DeleteOp);
|
||||
bcg->addStringRef(mName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void FieldReference::emitImplicitLoad(ByteCodeGen *bcg)
|
||||
{
|
||||
|
@ -323,6 +330,7 @@ ByteCodeData gByteCodeData[OpCodeCount] = {
|
|||
{ -128, "DupN", },
|
||||
{ -128, "DupInsertN", },
|
||||
{ -1, "Pop", },
|
||||
{ -128, "PopN", },
|
||||
{ 0, "GetField", },
|
||||
{ -1, "SetField", },
|
||||
{ 1, "GetMethod", },
|
||||
|
@ -412,7 +420,7 @@ uint32 ByteCodeGen::getLabel(LabelStmtNode *lbl)
|
|||
return result;
|
||||
}
|
||||
|
||||
uint32 ByteCodeGen::getTopLabel(Label::LabelKind kind, const StringAtom *name)
|
||||
uint32 ByteCodeGen::getTopLabel(Label::LabelKind kind, const StringAtom *name, StmtNode *p)
|
||||
{
|
||||
uint32 result = uint32(-1);
|
||||
for (std::vector<uint32>::reverse_iterator i = mLabelStack.rbegin(),
|
||||
|
@ -426,11 +434,11 @@ uint32 ByteCodeGen::getTopLabel(Label::LabelKind kind, const StringAtom *name)
|
|||
if (mLabelList[*i].matches(name))
|
||||
return result;
|
||||
}
|
||||
NOT_REACHED("label not found");
|
||||
m_cx->reportError(Exception::syntaxError, "label not found", p->pos);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 ByteCodeGen::getTopLabel(Label::LabelKind kind)
|
||||
uint32 ByteCodeGen::getTopLabel(Label::LabelKind kind, StmtNode *p)
|
||||
{
|
||||
for (std::vector<uint32>::reverse_iterator i = mLabelStack.rbegin(),
|
||||
end = mLabelStack.rend();
|
||||
|
@ -439,7 +447,7 @@ uint32 ByteCodeGen::getTopLabel(Label::LabelKind kind)
|
|||
if (mLabelList[*i].matches(kind))
|
||||
return *i;
|
||||
}
|
||||
NOT_REACHED("label not found");
|
||||
m_cx->reportError(Exception::syntaxError, "label not found", p->pos);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -615,7 +623,9 @@ void ByteCodeGen::genCodeForFunction(FunctionDefinition &f, size_t pos, JSFuncti
|
|||
}
|
||||
}
|
||||
|
||||
bool hasReturn = genCodeForStatement(f.body, NULL, NotALabel);
|
||||
bool hasReturn = false;
|
||||
if (f.body)
|
||||
hasReturn = genCodeForStatement(f.body, NULL, NotALabel);
|
||||
|
||||
/*
|
||||
// OPT - see above
|
||||
|
@ -702,7 +712,7 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3
|
|||
if (static_cg.hasContent()) {
|
||||
// build a function to be invoked
|
||||
// when the class is loaded
|
||||
f = new JSFunction(Void_Type, mScopeChain);
|
||||
f = new JSFunction(m_cx, Void_Type, mScopeChain);
|
||||
ByteCodeModule *bcm = new ByteCodeModule(&static_cg, NULL);
|
||||
if (m_cx->mReader)
|
||||
bcm->setSource(m_cx->mReader->source, m_cx->mReader->sourceLocation);
|
||||
|
@ -712,7 +722,7 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3
|
|||
f = NULL;
|
||||
if (bcg.hasContent()) {
|
||||
// execute this function now to form the initial instance
|
||||
f = new JSFunction(Void_Type, mScopeChain);
|
||||
f = new JSFunction(m_cx, Void_Type, mScopeChain);
|
||||
ByteCodeModule *bcm = new ByteCodeModule(&bcg, NULL);
|
||||
if (m_cx->mReader)
|
||||
bcm->setSource(m_cx->mReader->source, m_cx->mReader->sourceLocation);
|
||||
|
@ -857,6 +867,11 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3
|
|||
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();
|
||||
uint32 labelAtIncrement = getLabel(Label::ContinueLabel);
|
||||
|
@ -902,6 +917,14 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3
|
|||
addFixup(labelAtTestCondition);
|
||||
|
||||
setLabel(labelAtTopOfBlock);
|
||||
if (valueBaseDepth) {
|
||||
if (valueBaseDepth > 1) {
|
||||
addOpAdjustDepth(DupNOp, valueBaseDepth);
|
||||
addShort(valueBaseDepth);
|
||||
}
|
||||
else
|
||||
addOp(DupOp);
|
||||
}
|
||||
iteratorReadRef->emitCodeSequence(this);
|
||||
addOp(GetPropertyOp);
|
||||
addStringRef(m_cx->Value_StringAtom);
|
||||
|
@ -946,6 +969,14 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3
|
|||
addOp(PopOp);
|
||||
|
||||
setLabel(labelAtEnd);
|
||||
if (valueBaseDepth) {
|
||||
if (valueBaseDepth > 1) {
|
||||
addOpAdjustDepth(PopNOp, valueBaseDepth);
|
||||
addShort(valueBaseDepth);
|
||||
}
|
||||
else
|
||||
addOp(PopOp);
|
||||
}
|
||||
|
||||
delete objectReadRef;
|
||||
delete objectWriteRef;
|
||||
|
@ -987,6 +1018,10 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3
|
|||
addOp(JumpTrueOp);
|
||||
addFixup(labelAtTopOfBlock);
|
||||
}
|
||||
else {
|
||||
addOp(JumpOp);
|
||||
addFixup(labelAtTopOfBlock);
|
||||
}
|
||||
|
||||
setLabel(breakLabel);
|
||||
}
|
||||
|
@ -1009,9 +1044,9 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3
|
|||
GoStmtNode *g = checked_cast<GoStmtNode *>(p);
|
||||
addOp(JumpOp);
|
||||
if (g->name)
|
||||
addFixup(getTopLabel(Label::BreakLabel, g->name));
|
||||
addFixup(getTopLabel(Label::BreakLabel, g->name, p));
|
||||
else
|
||||
addFixup(getTopLabel(Label::BreakLabel));
|
||||
addFixup(getTopLabel(Label::BreakLabel, p));
|
||||
}
|
||||
break;
|
||||
case StmtNode::Continue:
|
||||
|
@ -1019,9 +1054,9 @@ bool ByteCodeGen::genCodeForStatement(StmtNode *p, ByteCodeGen *static_cg, uint3
|
|||
GoStmtNode *g = checked_cast<GoStmtNode *>(p);
|
||||
addOp(JumpOp);
|
||||
if (g->name)
|
||||
addFixup(getTopLabel(Label::ContinueLabel, g->name));
|
||||
addFixup(getTopLabel(Label::ContinueLabel, g->name, p));
|
||||
else
|
||||
addFixup(getTopLabel(Label::ContinueLabel));
|
||||
addFixup(getTopLabel(Label::ContinueLabel, p));
|
||||
}
|
||||
break;
|
||||
case StmtNode::Switch:
|
||||
|
@ -1673,7 +1708,7 @@ PreXcrement:
|
|||
uint16 baseDepth = readRef->baseExpressionDepth();
|
||||
if (baseDepth) { // duplicate the base expression
|
||||
if (baseDepth > 1) {
|
||||
addOpAdjustDepth(DupNOp, -baseDepth);
|
||||
addOpAdjustDepth(DupNOp, baseDepth);
|
||||
addShort(baseDepth);
|
||||
}
|
||||
else
|
||||
|
@ -1785,7 +1820,7 @@ BinaryOpEquals:
|
|||
uint16 baseDepth = readRef->baseExpressionDepth();
|
||||
if (baseDepth) { // duplicate the base expression
|
||||
if (baseDepth > 1) {
|
||||
addOp(DupNOp);
|
||||
addOpAdjustDepth(DupNOp, baseDepth);
|
||||
addShort(baseDepth);
|
||||
}
|
||||
else
|
||||
|
@ -1821,7 +1856,7 @@ BinaryOpEquals:
|
|||
uint16 baseDepth = readRef->baseExpressionDepth();
|
||||
if (baseDepth) { // duplicate the base expression
|
||||
if (baseDepth > 1) {
|
||||
addOpAdjustDepth(DupNOp, -baseDepth);
|
||||
addOpAdjustDepth(DupNOp, baseDepth);
|
||||
addShort(baseDepth);
|
||||
}
|
||||
else
|
||||
|
@ -1862,7 +1897,7 @@ BinaryOpEquals:
|
|||
uint16 baseDepth = readRef->baseExpressionDepth();
|
||||
if (baseDepth) { // duplicate the base expression
|
||||
if (baseDepth > 1) {
|
||||
addOpAdjustDepth(DupNOp, -baseDepth);
|
||||
addOpAdjustDepth(DupNOp, baseDepth);
|
||||
addShort(baseDepth);
|
||||
}
|
||||
else
|
||||
|
@ -1903,7 +1938,7 @@ BinaryOpEquals:
|
|||
uint16 baseDepth = readRef->baseExpressionDepth();
|
||||
if (baseDepth) { // duplicate the base expression
|
||||
if (baseDepth > 1) {
|
||||
addOpAdjustDepth(DupNOp, -baseDepth);
|
||||
addOpAdjustDepth(DupNOp, baseDepth);
|
||||
addShort(baseDepth);
|
||||
}
|
||||
else
|
||||
|
@ -2175,7 +2210,7 @@ BinaryOpEquals:
|
|||
{
|
||||
addOp(LoadTypeOp);
|
||||
addPointer(Array_Type);
|
||||
addOpAdjustDepth(NewInstanceOp, 1);
|
||||
addOpAdjustDepth(NewInstanceOp, 0);
|
||||
addLong(0);
|
||||
PairListExprNode *plen = checked_cast<PairListExprNode *>(p);
|
||||
ExprPairList *e = plen->pairs;
|
||||
|
@ -2243,7 +2278,7 @@ BinaryOpEquals:
|
|||
case ExprNode::functionLiteral:
|
||||
{
|
||||
FunctionExprNode *f = checked_cast<FunctionExprNode *>(p);
|
||||
JSFunction *fnc = new JSFunction(NULL, mScopeChain);
|
||||
JSFunction *fnc = new JSFunction(m_cx, NULL, mScopeChain);
|
||||
|
||||
uint32 reqArgCount = 0;
|
||||
uint32 optArgCount = 0;
|
||||
|
@ -2257,7 +2292,7 @@ BinaryOpEquals:
|
|||
optArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
fnc->setArgCounts(reqArgCount, optArgCount, (f->function.restParameter != NULL));
|
||||
fnc->setArgCounts(m_cx, reqArgCount, optArgCount, (f->function.restParameter != NULL));
|
||||
|
||||
if (mScopeChain->isPossibleUncheckedFunction(&f->function))
|
||||
fnc->setIsPrototype(true);
|
||||
|
@ -2324,6 +2359,7 @@ BinaryOpEquals:
|
|||
{
|
||||
BinaryExprNode *c = checked_cast<BinaryExprNode *>(p);
|
||||
genExpr(c->op1);
|
||||
addOp(PopOp);
|
||||
return genExpr(c->op2);
|
||||
}
|
||||
break;
|
||||
|
@ -2403,6 +2439,7 @@ uint32 printInstruction(Formatter &f, uint32 i, const ByteCodeModule& bcm)
|
|||
break;
|
||||
|
||||
case DupNOp:
|
||||
case PopNOp:
|
||||
case DupInsertNOp:
|
||||
{
|
||||
uint16 u = bcm.getShort(i);
|
||||
|
|
|
@ -117,9 +117,10 @@ typedef enum {
|
|||
SwapOp, // <object1> <object2> --> <object2> <object1>
|
||||
DupOp, // <object> --> <object> <object>
|
||||
DupInsertOp, // <object1> <object2> --> <object2> <object1> <object2>
|
||||
DupNOp, // <N> <object> --> <object> { N times }
|
||||
DupInsertNOp, // <N> <object> {xN} <object2> --> <object2> <object> {xN} <object2>
|
||||
DupNOp, // <N> <N things> --> <N things> <N things>
|
||||
DupInsertNOp, // <N> <N things> <object2> --> <object2> <N things> <object2>
|
||||
PopOp, // <object> -->
|
||||
PopNOp, // <N> <N things> -->
|
||||
// for instance members
|
||||
GetFieldOp, // <slot> <base> --> <object>
|
||||
SetFieldOp, // <slot> <base> <object> --> <object>
|
||||
|
@ -365,9 +366,9 @@ extern ByteCodeData gByteCodeData[OpCodeCount];
|
|||
|
||||
uint32 getLabel(LabelStmtNode *lbl);
|
||||
|
||||
uint32 getTopLabel(Label::LabelKind kind, const StringAtom *name);
|
||||
uint32 getTopLabel(Label::LabelKind kind, const StringAtom *name, StmtNode *p);
|
||||
|
||||
uint32 getTopLabel(Label::LabelKind kind);
|
||||
uint32 getTopLabel(Label::LabelKind kind, StmtNode *p);
|
||||
|
||||
void setLabel(uint32 label)
|
||||
{
|
||||
|
|
|
@ -73,6 +73,7 @@ JSValue Context::readEvalString(const String &str, const String& fileName, Scope
|
|||
|
||||
Arena a;
|
||||
Parser p(mWorld, a, mFlags, str, fileName);
|
||||
Reader *oldReader = mReader;
|
||||
mReader = &p.lexer.reader;
|
||||
StmtNode *parsedStatements = p.parseProgram();
|
||||
ASSERT(p.lexer.peek(true).hasKind(Token::end));
|
||||
|
@ -88,7 +89,6 @@ JSValue Context::readEvalString(const String &str, const String& fileName, Scope
|
|||
f.end();
|
||||
stdOut << '\n';
|
||||
}
|
||||
|
||||
buildRuntime(parsedStatements);
|
||||
JS2Runtime::ByteCodeModule* bcm = genCode(parsedStatements, fileName);
|
||||
if (bcm) {
|
||||
|
@ -97,6 +97,7 @@ JSValue Context::readEvalString(const String &str, const String& fileName, Scope
|
|||
result = interpret(bcm, 0, scopeChain, thisValue, NULL, 0);
|
||||
delete bcm;
|
||||
}
|
||||
setReader(oldReader);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -384,6 +385,13 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
result = popValue(); // XXX debug only? - just decrement top
|
||||
}
|
||||
break;
|
||||
case PopNOp:
|
||||
{
|
||||
uint16 count = *((uint16 *)pc);
|
||||
pc += sizeof(uint16);
|
||||
resizeStack(mStackTop - count);
|
||||
}
|
||||
break;
|
||||
case DupOp:
|
||||
{
|
||||
JSValue v = topValue();
|
||||
|
@ -401,14 +409,14 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
break;
|
||||
case DupNOp:
|
||||
{
|
||||
JSValue v = topValue();
|
||||
uint16 count = *((uint16 *)pc);
|
||||
pc += sizeof(uint16);
|
||||
JSValue *vp = getBase(stackSize() - count);
|
||||
while (count--)
|
||||
pushValue(v);
|
||||
pushValue(*vp++);
|
||||
}
|
||||
break;
|
||||
// <object> {xN} <object2> --> <object2> <object> {xN} <object2>
|
||||
// <N things> <object2> --> <object2> <N things> <object2>
|
||||
case DupInsertNOp:
|
||||
{
|
||||
JSValue v2 = topValue();
|
||||
|
@ -550,16 +558,19 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
|
||||
// XXX Note that this is different behaviour from JS1.5, where
|
||||
// (e.g.) Array(2) is an invocation of the constructor.
|
||||
|
||||
if ((argCount > 1) || ((callFlags & ThisFlags) != NoThis))
|
||||
reportError(Exception::referenceError, "Type cast can only take one argument");
|
||||
JSValue v;
|
||||
if (argCount > 0)
|
||||
v = popValue();
|
||||
popValue(); // don't need the target anymore
|
||||
pushValue(mapValueToType(v, targetValue->type));
|
||||
mThis = oldThis;
|
||||
break; // all done
|
||||
|
||||
target = targetValue->type->getTypeCastFunction();
|
||||
if (target == NULL) {
|
||||
if ((argCount > 1) || ((callFlags & ThisFlags) != NoThis))
|
||||
reportError(Exception::referenceError, "Type cast can only take one argument");
|
||||
JSValue v;
|
||||
if (argCount > 0)
|
||||
v = popValue();
|
||||
popValue(); // don't need the target anymore
|
||||
pushValue(mapValueToType(v, targetValue->type));
|
||||
mThis = oldThis;
|
||||
break; // all done
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -655,6 +666,7 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
mArgumentBase = prev->mArgumentBase;
|
||||
mThis = prev->mThis;
|
||||
mScopeChain = prev->mScopeChain;
|
||||
pushValue(kUndefinedValue);
|
||||
delete prev;
|
||||
}
|
||||
break;
|
||||
|
@ -854,7 +866,17 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
uint32 index = *((uint32 *)pc);
|
||||
pc += sizeof(uint32);
|
||||
const String &name = *mCurModule->getString(index);
|
||||
mScopeChain->getNameValue(this, name, CURRENT_ATTR);
|
||||
JSObject *parent = mScopeChain->getNameValue(this, name, CURRENT_ATTR);
|
||||
JSValue result = topValue();
|
||||
if (result.isFunction() && result.function->isMethod()) {
|
||||
popValue();
|
||||
if (result.function->isConstructor())
|
||||
// A constructor has to be called with a NULL 'this' in order to prompt it
|
||||
// to construct the instance object.
|
||||
pushValue(JSValue((JSFunction *)(new JSBoundFunction(result.function, NULL))));
|
||||
else
|
||||
pushValue(JSValue((JSFunction *)(new JSBoundFunction(result.function, parent))));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GetTypeOfNameOp:
|
||||
|
@ -887,13 +909,13 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
|
||||
// Use the type of the base to dispatch on...
|
||||
JSObject *obj = NULL;
|
||||
if (baseValue->isType())
|
||||
obj = baseValue->type;
|
||||
else
|
||||
if (baseValue->isFunction())
|
||||
obj = baseValue->function;
|
||||
else
|
||||
if (baseValue->isObject())
|
||||
if (baseValue->isType())
|
||||
obj = baseValue->type;
|
||||
else
|
||||
if (baseValue->isFunction())
|
||||
obj = baseValue->function;
|
||||
else
|
||||
if (baseValue->isObject())
|
||||
obj = baseValue->object;
|
||||
else
|
||||
obj = baseValue->toObject(this).object;
|
||||
|
@ -1040,10 +1062,10 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
mPC = pc;
|
||||
const String &name = *mCurModule->getString(index);
|
||||
obj->getProperty(this, name, CURRENT_ATTR);
|
||||
// if the result is a function of some kind, bind
|
||||
// if the result is a method of some kind, bind
|
||||
// the base object to it
|
||||
JSValue result = topValue();
|
||||
if (result.isFunction()) {
|
||||
if (result.isFunction() && result.function->isMethod()) {
|
||||
popValue();
|
||||
if (result.function->isConstructor())
|
||||
// A constructor has to be called with a NULL 'this' in order to prompt it
|
||||
|
@ -1853,16 +1875,22 @@ static JSValue compareEqual(Context *cx, JSValue r1, JSValue r2)
|
|||
else {
|
||||
if (r1.isUndefined())
|
||||
return kTrueValue;
|
||||
if (r1.isNull())
|
||||
if (r1.isNull() || r2.isNull()) // because null->getType() == Object_Type
|
||||
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 (r1.isNaN())
|
||||
if (JSDOUBLE_IS_NaN(f1))
|
||||
return kFalseValue;
|
||||
if (r2.isNaN())
|
||||
if (JSDOUBLE_IS_NaN(f2))
|
||||
return kFalseValue;
|
||||
|
||||
return JSValue(r1.f64 == r2.f64);
|
||||
|
@ -1872,12 +1900,6 @@ static JSValue compareEqual(Context *cx, JSValue r1, JSValue r2)
|
|||
return JSValue(bool(r1.getStringValue()->compare(*r2.getStringValue()) == 0));
|
||||
if (t1 == Boolean_Type)
|
||||
return JSValue(r1.getBoolValue() == r2.getBoolValue());
|
||||
if (r1.isObject())
|
||||
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));
|
||||
NOT_REACHED("unhandled type");
|
||||
return kFalseValue;
|
||||
}
|
||||
|
@ -1944,7 +1966,7 @@ void Context::initOperators()
|
|||
};
|
||||
|
||||
for (uint32 i = 0; i < sizeof(OpTable) / sizeof(OpTableEntry); i++) {
|
||||
JSFunction *f = new JSFunction(OpTable[i].imp, OpTable[i].resType);
|
||||
JSFunction *f = new JSFunction(this, OpTable[i].imp, OpTable[i].resType);
|
||||
OperatorDefinition *op = new OperatorDefinition(OpTable[i].op1, OpTable[i].op2, f);
|
||||
mOperatorTable[OpTable[i].which].push_back(op);
|
||||
}
|
||||
|
@ -2198,7 +2220,7 @@ float64 JSValue::float64ToInteger(float64 d)
|
|||
if (JSDOUBLE_IS_NaN(d))
|
||||
return 0.0;
|
||||
else
|
||||
return (d >= 0.0) ? fd::floor(d) : -fd::floor(d);
|
||||
return (d >= 0.0) ? fd::floor(d) : -fd::floor(-d);
|
||||
}
|
||||
|
||||
JSValue JSValue::valueToInteger(Context *cx, const JSValue& value)
|
||||
|
@ -2382,6 +2404,7 @@ JSType *JSValue::getType() const {
|
|||
case undefined_tag: return Void_Type;
|
||||
case null_tag: return Object_Type;
|
||||
case function_tag: return Function_Type;
|
||||
case type_tag: return Type_Type;
|
||||
default:
|
||||
NOT_REACHED("bad type");
|
||||
return NULL;
|
||||
|
|
|
@ -654,7 +654,7 @@ void ScopeChain::setNameValue(Context *cx, const String& name, AttributeStmtNode
|
|||
|
||||
inline char narrow(char16 ch) { return char(ch); }
|
||||
|
||||
void ScopeChain::getNameValue(Context *cx, const String& name, AttributeStmtNode *attr)
|
||||
JSObject *ScopeChain::getNameValue(Context *cx, const String& name, AttributeStmtNode *attr)
|
||||
{
|
||||
NamespaceList *names = (attr) ? attr->attributeValue->mNamespaceList : NULL;
|
||||
uint32 depth = 0;
|
||||
|
@ -670,10 +670,11 @@ void ScopeChain::getNameValue(Context *cx, const String& name, AttributeStmtNode
|
|||
default:
|
||||
ASSERT(false); // what else needs to be implemented ?
|
||||
}
|
||||
return;
|
||||
return *s;
|
||||
}
|
||||
}
|
||||
m_cx->reportError(Exception::referenceError, "'{0}' not defined", name );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Reference *ScopeChain::getName(const String& name, NamespaceList *names, Access acc)
|
||||
|
@ -745,22 +746,22 @@ Reference *ParameterBarrel::genReference(bool /* hasBase */, const String& name,
|
|||
JSType *ScopeChain::findType(const StringAtom& typeName, size_t pos)
|
||||
{
|
||||
JSValue v = getCompileTimeValue(typeName, NULL);
|
||||
if (!v.isUndefined()) {
|
||||
if (v.isType())
|
||||
return v.type;
|
||||
else {
|
||||
// Allow finding a function that has the same name as it's containing class
|
||||
// i.e. the default constructor.
|
||||
FunctionName *fnName = v.function->getFunctionName();
|
||||
if ((fnName->prefix == FunctionName::normal)
|
||||
&& v.isFunction() && v.function->getClass()
|
||||
&& (v.function->getClass()->mClassName->compare(*fnName->name) == 0))
|
||||
return v.function->getClass();
|
||||
m_cx->reportError(Exception::semanticError, "Unknown type", pos);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
if (!v.isUndefined()) {
|
||||
if (v.isType())
|
||||
return v.type;
|
||||
else {
|
||||
// Allow finding a function that has the same name as it's containing class
|
||||
// i.e. the default constructor.
|
||||
FunctionName *fnName = v.function->getFunctionName();
|
||||
if ((fnName->prefix == FunctionName::normal)
|
||||
&& v.isFunction() && v.function->getClass()
|
||||
&& (v.function->getClass()->mClassName->compare(*fnName->name) == 0))
|
||||
return v.function->getClass();
|
||||
m_cx->reportError(Exception::semanticError, "Unknown type", pos);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Take the specified type in 't' and see if we have a compile-time
|
||||
|
@ -990,7 +991,7 @@ void ScopeChain::collectNames(StmtNode *p)
|
|||
bool isOperator = (f->attributeValue->mTrueFlags & Property::Operator) == Property::Operator;
|
||||
bool isPrototype = (f->attributeValue->mTrueFlags & Property::Prototype) == Property::Prototype;
|
||||
|
||||
JSFunction *fnc = new JSFunction(NULL, this);
|
||||
JSFunction *fnc = new JSFunction(m_cx, NULL, this);
|
||||
|
||||
/* Determine whether a function is unchecked, which is the case if -
|
||||
XXX strict mode is disabled at the point of the function definition;
|
||||
|
@ -1024,7 +1025,7 @@ void ScopeChain::collectNames(StmtNode *p)
|
|||
optArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
fnc->setArgCounts(reqArgCount, optArgCount, (f->function.restParameter != NULL));
|
||||
fnc->setArgCounts(m_cx, reqArgCount, optArgCount, (f->function.restParameter != NULL));
|
||||
|
||||
if (isOperator) {
|
||||
// no need to do anything yet, all operators are 'pre-declared'
|
||||
|
@ -1139,12 +1140,9 @@ void JSType::completeClass(Context *cx, ScopeChain *scopeChain)
|
|||
{
|
||||
// if none exists, build a default constructor that calls 'super()'
|
||||
if (getDefaultConstructor() == NULL) {
|
||||
JSFunction *fnc = new JSFunction(Object_Type, scopeChain);
|
||||
JSFunction *fnc = new JSFunction(cx, Object_Type, scopeChain);
|
||||
fnc->setIsConstructor(true);
|
||||
FunctionName *fnName = new FunctionName();
|
||||
fnName->name = mClassName; //cx->mWorld.identifiers[mClassName];
|
||||
fnName->prefix = FunctionName::normal;
|
||||
fnc->setFunctionName(fnName);
|
||||
fnc->setFunctionName(mClassName);
|
||||
fnc->setClass(this);
|
||||
|
||||
ByteCodeGen bcg(cx, scopeChain);
|
||||
|
@ -1343,6 +1341,7 @@ JSType::JSType(Context *cx, const StringAtom *name, JSType *super, JSObject *pro
|
|||
mVariableCount(0),
|
||||
mInstanceInitializer(NULL),
|
||||
mDefaultConstructor(NULL),
|
||||
mTypeCast(NULL),
|
||||
mClassName(name),
|
||||
mIsDynamic(false),
|
||||
mUninitializedValue(kNullValue),
|
||||
|
@ -1360,12 +1359,20 @@ JSType::JSType(Context *cx, const StringAtom *name, JSType *super, JSObject *pro
|
|||
if (protoObj)
|
||||
mPrototypeObject = protoObj;
|
||||
else
|
||||
mPrototypeObject = new JSObject();
|
||||
mPrototypeObject = new JSObject(this);
|
||||
// and that object is prototype-linked to the super-type's prototype object
|
||||
if (mSuperType)
|
||||
mPrototypeObject->mPrototype = mSuperType->mPrototypeObject;
|
||||
|
||||
// defineVariable(cx, cx->Prototype_StringAtom, NULL, Object_Type, JSValue(mPrototypeObject));
|
||||
if (mSuperType)
|
||||
defineVariable(cx, cx->Prototype_StringAtom, NULL, Object_Type, JSValue(mPrototypeObject));
|
||||
else // must be Object_Type
|
||||
defineVariable(cx, cx->Prototype_StringAtom, NULL, this, JSValue(mPrototypeObject));
|
||||
|
||||
if (mSuperType)
|
||||
mPrototype = mSuperType->mPrototypeObject;
|
||||
else // must be Object_Type
|
||||
mPrototype = mPrototypeObject;
|
||||
}
|
||||
|
||||
JSType::JSType(JSType *xClass) // used for constructing the static component type
|
||||
|
@ -1374,6 +1381,7 @@ JSType::JSType(JSType *xClass) // used for constructing the static component
|
|||
mVariableCount(0),
|
||||
mInstanceInitializer(NULL),
|
||||
mDefaultConstructor(NULL),
|
||||
mTypeCast(NULL),
|
||||
mClassName(NULL),
|
||||
mPrivateNamespace(NULL),
|
||||
mIsDynamic(false),
|
||||
|
@ -1689,14 +1697,17 @@ static JSValue Object_Constructor(Context *cx, const JSValue& thisValue, JSValue
|
|||
static JSValue Object_toString(Context *, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
if (thisValue.isObject())
|
||||
return JSValue(new String(widenCString("[object ") + widenCString("Object") + widenCString("]")));
|
||||
return JSValue(new String(widenCString("[object ") + *thisValue.object->getType()->mClassName + widenCString("]")));
|
||||
else
|
||||
if (thisValue.isType())
|
||||
return JSValue(new String(widenCString("[object ") + widenCString("Type") + widenCString("]")));
|
||||
else {
|
||||
NOT_REACHED("Object.prototype.toString on non-object");
|
||||
return kUndefinedValue;
|
||||
}
|
||||
else
|
||||
if (thisValue.isFunction())
|
||||
return JSValue(new String(widenCString("[object ") + widenCString("Function") + widenCString("]")));
|
||||
else {
|
||||
NOT_REACHED("Object.prototype.toString on non-object");
|
||||
return kUndefinedValue;
|
||||
}
|
||||
}
|
||||
|
||||
struct IteratorDongle {
|
||||
|
@ -1706,12 +1717,24 @@ struct IteratorDongle {
|
|||
|
||||
static JSValue Object_forin(Context *cx, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
JSObject *iteratorObject = Object_Type->newInstance(cx);
|
||||
|
||||
JSObject *obj = NULL;
|
||||
if (thisValue.isType())
|
||||
obj = thisValue.type;
|
||||
else
|
||||
if (thisValue.isFunction())
|
||||
obj = thisValue.function;
|
||||
else
|
||||
if (thisValue.isObject())
|
||||
obj = thisValue.object;
|
||||
else
|
||||
NOT_REACHED("Non object for for..in");
|
||||
|
||||
JSObject *iteratorObject = Object_Type->newInstance(cx);
|
||||
IteratorDongle *itDude = new IteratorDongle();
|
||||
itDude->obj = thisValue.object;
|
||||
itDude->it = thisValue.object->mProperties.begin();
|
||||
itDude->obj = obj;
|
||||
itDude->it = obj->mProperties.begin();
|
||||
if (itDude->it == itDude->obj->mProperties.end())
|
||||
return kNullValue;
|
||||
|
||||
JSValue v(&PROPERTY_NAME(itDude->it));
|
||||
iteratorObject->setProperty(cx, cx->mWorld.identifiers["value"], 0, v);
|
||||
|
@ -1775,13 +1798,14 @@ static JSValue Function_Constructor(Context *cx, const JSValue& thisValue, JSVal
|
|||
{
|
||||
Arena a;
|
||||
Parser p(cx->mWorld, a, cx->mFlags, s, widenCString("function constructor"));
|
||||
Reader *oldReader = cx->mReader;
|
||||
cx->mReader = &p.lexer.reader;
|
||||
|
||||
FunctionExprNode *f = p.parseFunctionExpression(0);
|
||||
if (!p.lexer.peek(true).hasKind(Token::end))
|
||||
cx->reportError(Exception::syntaxError, "Unexpected stuff after the function body");
|
||||
|
||||
fnc = new JSFunction(NULL, cx->mScopeChain);
|
||||
fnc = new JSFunction(cx, NULL, cx->mScopeChain);
|
||||
|
||||
uint32 reqArgCount = 0;
|
||||
uint32 optArgCount = 0;
|
||||
|
@ -1795,7 +1819,7 @@ static JSValue Function_Constructor(Context *cx, const JSValue& thisValue, JSVal
|
|||
optArgCount++;
|
||||
b = b->next;
|
||||
}
|
||||
fnc->setArgCounts(reqArgCount, optArgCount, (f->function.restParameter != NULL));
|
||||
fnc->setArgCounts(cx, reqArgCount, optArgCount, (f->function.restParameter != NULL));
|
||||
|
||||
if (cx->mScopeChain->isPossibleUncheckedFunction(&f->function))
|
||||
fnc->setIsPrototype(true);
|
||||
|
@ -1803,6 +1827,7 @@ static JSValue Function_Constructor(Context *cx, const JSValue& thisValue, JSVal
|
|||
cx->buildRuntimeForFunction(f->function, fnc);
|
||||
ByteCodeGen bcg(cx, cx->mScopeChain);
|
||||
bcg.genCodeForFunction(f->function, f->pos, fnc, false, NULL);
|
||||
cx->setReader(oldReader);
|
||||
}
|
||||
/***************************************************************/
|
||||
|
||||
|
@ -1917,7 +1942,8 @@ static JSValue Boolean_toString(Context *cx, const JSValue& thisValue, JSValue *
|
|||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
JSObject *thisObj = thisValue.object;
|
||||
|
||||
if (thisObj->mType != Boolean_Type)
|
||||
cx->reportError(Exception::typeError, "Boolean.toString can only be applied to Boolean objects");
|
||||
if (thisObj->mPrivate != 0)
|
||||
return JSValue(&cx->True_StringAtom);
|
||||
else
|
||||
|
@ -1928,11 +1954,12 @@ static JSValue Boolean_valueOf(Context *cx, const JSValue& thisValue, JSValue *
|
|||
{
|
||||
ASSERT(thisValue.isObject());
|
||||
JSObject *thisObj = thisValue.object;
|
||||
|
||||
if (thisObj->mType != Boolean_Type)
|
||||
cx->reportError(Exception::typeError, "Boolean.valueOf can only be applied to Boolean objects");
|
||||
if (thisObj->mPrivate != 0)
|
||||
return kTrueValue; //JSValue(1.0);
|
||||
return kTrueValue;
|
||||
else
|
||||
return kFalseValue; //kPositiveZero;
|
||||
return kFalseValue;
|
||||
}
|
||||
|
||||
static JSValue ExtendAttribute_Invoke(Context * /*cx*/, const JSValue& /*thisValue*/, JSValue *argv, uint32 argc)
|
||||
|
@ -1988,7 +2015,77 @@ static JSValue GlobalObject_ParseFloat(Context *cx, const JSValue& /*thisValue*/
|
|||
return JSValue(f);
|
||||
}
|
||||
|
||||
static JSValue GlobalObject_isNaN(Context *cx, const JSValue& /*thisValue*/, JSValue *argv, uint32 argc)
|
||||
{
|
||||
float64 f = argv[0].toNumber(cx).f64;
|
||||
if (JSDOUBLE_IS_NaN(f))
|
||||
return kTrueValue;
|
||||
else
|
||||
return kFalseValue;
|
||||
}
|
||||
|
||||
static JSValue GlobalObject_isFinite(Context *cx, const JSValue& /*thisValue*/, JSValue *argv, uint32 argc)
|
||||
{
|
||||
float64 f = argv[0].toNumber(cx).f64;
|
||||
if (JSDOUBLE_IS_FINITE(f))
|
||||
return kTrueValue;
|
||||
else
|
||||
return kFalseValue;
|
||||
}
|
||||
|
||||
|
||||
JSFunction::JSFunction(Context *cx, JSType *resultType, ScopeChain *scopeChain)
|
||||
: JSObject(Function_Type),
|
||||
mParameterBarrel(NULL),
|
||||
mActivation(),
|
||||
mByteCode(NULL),
|
||||
mCode(NULL),
|
||||
mResultType(resultType),
|
||||
mRequiredArgs(0),
|
||||
mOptionalArgs(0),
|
||||
mArguments(NULL),
|
||||
mScopeChain(NULL),
|
||||
mIsPrototype(false),
|
||||
mIsConstructor(false),
|
||||
mIsChecked(true),
|
||||
mHasRestParameter(false),
|
||||
mRestParameterName(NULL),
|
||||
mClass(NULL),
|
||||
mFunctionName(NULL)
|
||||
{
|
||||
if (scopeChain) {
|
||||
mScopeChain = new 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));
|
||||
}
|
||||
|
||||
JSFunction::JSFunction(Context *cx, NativeCode *code, JSType *resultType)
|
||||
: JSObject(Function_Type),
|
||||
mParameterBarrel(NULL),
|
||||
mActivation(),
|
||||
mByteCode(NULL),
|
||||
mCode(code),
|
||||
mResultType(resultType),
|
||||
mRequiredArgs(0),
|
||||
mOptionalArgs(0),
|
||||
mArguments(NULL),
|
||||
mScopeChain(NULL),
|
||||
mIsPrototype(false),
|
||||
mIsConstructor(false),
|
||||
mIsChecked(false), // native functions aren't checked (?)
|
||||
mHasRestParameter(false),
|
||||
mRestParameterName(NULL),
|
||||
mClass(NULL),
|
||||
mFunctionName(NULL)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
JSValue JSFunction::runArgInitializer(Context *cx, uint32 a, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
|
@ -1996,12 +2093,13 @@ JSValue JSFunction::runArgInitializer(Context *cx, uint32 a, const JSValue& this
|
|||
return cx->interpret(getByteCode(), (int32)mArguments[a].mInitializer, getScopeChain(), thisValue, argv, argc);
|
||||
}
|
||||
|
||||
void JSFunction::setArgCounts(uint32 r, uint32 o, bool hasRest)
|
||||
void JSFunction::setArgCounts(Context *cx, uint32 r, uint32 o, bool hasRest)
|
||||
{
|
||||
mHasRestParameter = hasRest;
|
||||
mRequiredArgs = r;
|
||||
mOptionalArgs = o;
|
||||
mArguments = new ArgumentData[mRequiredArgs + mOptionalArgs + ((hasRest) ? 1 : 0)];
|
||||
setProperty(cx, cx->Length_StringAtom, (NamespaceList *)NULL, JSValue((float64)mRequiredArgs));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2036,22 +2134,19 @@ void Context::assureStackSpace(uint32 s)
|
|||
void Context::initClass(JSType *type, ClassDef *cdef, PrototypeFunctions *pdef)
|
||||
{
|
||||
mScopeChain->addScope(type);
|
||||
JSFunction *constructor = new JSFunction(cdef->defCon, Object_Type);
|
||||
JSFunction *constructor = new JSFunction(this, cdef->defCon, Object_Type);
|
||||
constructor->setClass(type);
|
||||
FunctionName *fnName = new FunctionName();
|
||||
fnName->name = type->mClassName;
|
||||
constructor->setFunctionName(fnName);
|
||||
constructor->setFunctionName(type->mClassName);
|
||||
type->setDefaultConstructor(this, constructor);
|
||||
|
||||
// the prototype functions are defined in the prototype object...
|
||||
if (pdef) {
|
||||
for (uint32 i = 0; i < pdef->mCount; i++) {
|
||||
JSFunction *fun = new JSFunction(pdef->mDef[i].imp, pdef->mDef[i].result);
|
||||
fun->setClass(type);
|
||||
JSFunction *fun = new JSFunction(this, pdef->mDef[i].imp, pdef->mDef[i].result);
|
||||
// fun->setClass(type); don't do this, it makes the function a method
|
||||
StringAtom *name = &mWorld.identifiers[widenCString(pdef->mDef[i].name)];
|
||||
FunctionName *fnName = new FunctionName();
|
||||
fun->setFunctionName(fnName);
|
||||
fun->setArgCounts(pdef->mDef[i].length, 0, false);
|
||||
fun->setFunctionName(name);
|
||||
fun->setArgCounts(this, pdef->mDef[i].length, 0, false);
|
||||
type->mPrototypeObject->defineVariable(this, *name,
|
||||
(NamespaceList *)(NULL),
|
||||
pdef->mDef[i].result,
|
||||
|
@ -2106,6 +2201,7 @@ void Context::initBuiltins()
|
|||
};
|
||||
|
||||
Object_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[0].name)], NULL);
|
||||
Object_Type->mPrototype->mType = Object_Type;
|
||||
Object_Type->mIsDynamic = true;
|
||||
// XXX aren't all the built-ins thus?
|
||||
|
||||
|
@ -2119,34 +2215,26 @@ void Context::initBuiltins()
|
|||
// (which we don't actually have, hmm).
|
||||
// For String, etc. this same issue needs to be finessed
|
||||
|
||||
JSFunction *funProto = new JSFunction(Object_Type, NULL);
|
||||
JSFunction *funProto = new JSFunction(this, Object_Type, NULL);
|
||||
Function_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[2].name)], Object_Type, funProto);
|
||||
Function_Type->defineVariable(this, Prototype_StringAtom, NULL, Object_Type, JSValue(funProto));
|
||||
funProto->mType = Function_Type;
|
||||
|
||||
Number_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[3].name)], Object_Type);
|
||||
Number_Type->defineVariable(this, Prototype_StringAtom, NULL, Object_Type, JSValue(Number_Type->mPrototypeObject));
|
||||
|
||||
Integer_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[4].name)], Object_Type);
|
||||
|
||||
String_Type = new JSStringType(this, &mWorld.identifiers[widenCString(builtInClasses[5].name)], Object_Type);
|
||||
String_Type->defineVariable(this, Prototype_StringAtom, NULL, Object_Type, JSValue(String_Type->mPrototypeObject));
|
||||
|
||||
Array_Type = new JSArrayType(this, Object_Type, &mWorld.identifiers[widenCString(builtInClasses[6].name)], Object_Type);
|
||||
Array_Type->defineVariable(this, Prototype_StringAtom, NULL, Object_Type, JSValue(Array_Type->mPrototypeObject));
|
||||
|
||||
Boolean_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[7].name)], Object_Type);
|
||||
Boolean_Type->defineVariable(this, Prototype_StringAtom, NULL, Object_Type, JSValue(Boolean_Type->mPrototypeObject));
|
||||
|
||||
JSArrayInstance *arrayProto = new JSArrayInstance(this, NULL);
|
||||
Array_Type = new JSArrayType(this, Object_Type, &mWorld.identifiers[widenCString(builtInClasses[6].name)], Object_Type, arrayProto);
|
||||
arrayProto->mType = Array_Type;
|
||||
|
||||
Boolean_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[7].name)], Object_Type);
|
||||
Void_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[8].name)], Object_Type);
|
||||
Unit_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[9].name)], Object_Type);
|
||||
Attribute_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[10].name)], Object_Type);
|
||||
NamedArgument_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[11].name)], Object_Type);
|
||||
|
||||
Date_Type = new JSType(this, &mWorld.identifiers[widenCString(builtInClasses[12].name)], Object_Type);
|
||||
Date_Type->defineVariable(this, Prototype_StringAtom, NULL, Object_Type, JSValue(Date_Type->mPrototypeObject));
|
||||
|
||||
|
||||
String_Type->defineVariable(this, FromCharCode_StringAtom, NULL, String_Type, JSValue(new JSFunction(String_fromCharCode, String_Type)));
|
||||
String_Type->defineVariable(this, FromCharCode_StringAtom, NULL, String_Type, JSValue(new JSFunction(this, String_fromCharCode, String_Type)));
|
||||
|
||||
|
||||
ProtoFunDef objectProtos[] =
|
||||
|
@ -2203,10 +2291,14 @@ void Context::initBuiltins()
|
|||
initClass(NamedArgument_Type, &builtInClasses[11], NULL);
|
||||
initClass(Date_Type, &builtInClasses[12], getDateProtos() );
|
||||
|
||||
Type_Type->defineUnaryOperator(Index, new JSFunction(arrayMaker, Type_Type));
|
||||
Type_Type->defineUnaryOperator(Index, new JSFunction(this, arrayMaker, Type_Type));
|
||||
|
||||
Array_Type->defineUnaryOperator(Index, new JSFunction(Array_GetElement, Object_Type));
|
||||
Array_Type->defineUnaryOperator(IndexEqual, new JSFunction(Array_SetElement, Object_Type));
|
||||
Array_Type->defineUnaryOperator(Index, new JSFunction(this, Array_GetElement, Object_Type));
|
||||
Array_Type->defineUnaryOperator(IndexEqual, new JSFunction(this, Array_SetElement, Object_Type));
|
||||
|
||||
Date_Type->mTypeCast = new JSFunction(this, Date_TypeCast, String_Type);
|
||||
Date_Type->defineStaticMethod(this, widenCString("parse"), NULL, new JSFunction(this, Date_parse, Number_Type));
|
||||
Date_Type->defineStaticMethod(this, widenCString("UTC"), NULL, new JSFunction(this, Date_UTC, Number_Type));
|
||||
|
||||
}
|
||||
|
||||
|
@ -2382,21 +2474,23 @@ Context::Context(JSObject **global, World &world, Arena &a, Pragma::Flags flags)
|
|||
getGlobalObject()->defineVariable(this, widenCString(attribute_init[i].name), (NamespaceList *)(NULL), Attribute_Type, JSValue(attr));
|
||||
}
|
||||
|
||||
JSFunction *x = new JSFunction(ExtendAttribute_Invoke, Attribute_Type);
|
||||
JSFunction *x = new JSFunction(this, ExtendAttribute_Invoke, Attribute_Type);
|
||||
getGlobalObject()->defineVariable(this, Extend_StringAtom, (NamespaceList *)(NULL), Attribute_Type, JSValue(x));
|
||||
|
||||
|
||||
|
||||
|
||||
ProtoFunDef globalObjectFunctions[] = {
|
||||
{ "eval", Object_Type, 1, GlobalObject_Eval },
|
||||
{ "parseInt", Number_Type, 2, GlobalObject_ParseInt },
|
||||
{ "parseFloat", Number_Type, 2, GlobalObject_ParseFloat },
|
||||
{ "eval", Object_Type, 1, GlobalObject_Eval },
|
||||
{ "parseInt", Number_Type, 2, GlobalObject_ParseInt },
|
||||
{ "parseFloat", Number_Type, 2, GlobalObject_ParseFloat },
|
||||
{ "isNaN", Boolean_Type, 2, GlobalObject_isNaN },
|
||||
{ "isFinite", Boolean_Type, 2, GlobalObject_isFinite },
|
||||
};
|
||||
|
||||
for (i = 0; i < (sizeof(globalObjectFunctions) / sizeof(ProtoFunDef)); i++) {
|
||||
x = new JSFunction(globalObjectFunctions[i].imp, globalObjectFunctions[i].result);
|
||||
x->setArgCounts(globalObjectFunctions[i].length, 0, false);
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -385,6 +385,7 @@ XXX ...couldn't get this to work...
|
|||
void emitInvokeSequence(ByteCodeGen *bcg);
|
||||
void emitImplicitLoad(ByteCodeGen *bcg);
|
||||
uint16 baseExpressionDepth() { return 1; }
|
||||
void emitDelete(ByteCodeGen *bcg);
|
||||
};
|
||||
// a member function in a vtable
|
||||
class MethodReference : public Reference {
|
||||
|
@ -482,7 +483,7 @@ XXX ...couldn't get this to work...
|
|||
Access mAccess;
|
||||
uint16 mDepth;
|
||||
void emitCodeSequence(ByteCodeGen *bcg);
|
||||
uint16 baseExpressionDepth() { return mDepth; }
|
||||
uint16 baseExpressionDepth() { return mDepth + 1; }
|
||||
void emitDelete(ByteCodeGen *bcg);
|
||||
};
|
||||
|
||||
|
@ -752,6 +753,7 @@ XXX ...couldn't get this to work...
|
|||
virtual Reference *genReference(bool hasBase, const String& name, NamespaceList *names, Access acc, uint32 depth);
|
||||
|
||||
JSFunction *getDefaultConstructor() { return mDefaultConstructor; }
|
||||
JSFunction *getTypeCastFunction() { return mTypeCast; }
|
||||
|
||||
JSValue getUninitializedValue() { return mUninitializedValue; }
|
||||
|
||||
|
@ -765,6 +767,7 @@ XXX ...couldn't get this to work...
|
|||
uint32 mVariableCount;
|
||||
JSFunction *mInstanceInitializer;
|
||||
JSFunction *mDefaultConstructor;
|
||||
JSFunction *mTypeCast;
|
||||
|
||||
// the 'vtable'
|
||||
MethodList mMethods;
|
||||
|
@ -806,8 +809,8 @@ XXX ...couldn't get this to work...
|
|||
|
||||
class JSArrayType : public JSType {
|
||||
public:
|
||||
JSArrayType(Context *cx, JSType *elementType, const StringAtom *name, JSType *super)
|
||||
: JSType(cx, name, super), mElementType(elementType)
|
||||
JSArrayType(Context *cx, JSType *elementType, const StringAtom *name, JSType *super, JSObject *protoObj = NULL)
|
||||
: JSType(cx, name, super, protoObj), mElementType(elementType)
|
||||
{
|
||||
}
|
||||
virtual ~JSArrayType() { } // keeping gcc happy
|
||||
|
@ -1084,7 +1087,8 @@ XXX ...couldn't get this to work...
|
|||
|
||||
bool hasNameValue(const String& name, NamespaceList *names);
|
||||
|
||||
void getNameValue(Context *cx, const String& name, AttributeStmtNode *attr);
|
||||
// pushes the value of the name and returns it's container object
|
||||
JSObject *getNameValue(Context *cx, const String& name, AttributeStmtNode *attr);
|
||||
|
||||
// return the class on the top of the stack (or NULL if there
|
||||
// isn't one there).
|
||||
|
@ -1180,54 +1184,8 @@ XXX ...couldn't get this to work...
|
|||
|
||||
// XXX these should be Function_Type->newInstance() calls, no?
|
||||
|
||||
JSFunction(JSType *resultType, ScopeChain *scopeChain)
|
||||
: JSObject(Function_Type),
|
||||
mParameterBarrel(NULL),
|
||||
mActivation(),
|
||||
mByteCode(NULL),
|
||||
mCode(NULL),
|
||||
mResultType(resultType),
|
||||
mRequiredArgs(0),
|
||||
mOptionalArgs(0),
|
||||
mArguments(NULL),
|
||||
mScopeChain(NULL),
|
||||
mIsPrototype(false),
|
||||
mIsConstructor(false),
|
||||
mIsChecked(true),
|
||||
mHasRestParameter(false),
|
||||
mRestParameterName(NULL),
|
||||
mClass(NULL)
|
||||
{
|
||||
if (scopeChain) {
|
||||
mScopeChain = new ScopeChain(*scopeChain);
|
||||
}
|
||||
if (Function_Type) // protect against bootstrap
|
||||
mPrototype = Function_Type->mPrototypeObject;
|
||||
mActivation.mContainer = this;
|
||||
}
|
||||
|
||||
JSFunction(NativeCode *code, JSType *resultType)
|
||||
: JSObject(Function_Type),
|
||||
mParameterBarrel(NULL),
|
||||
mActivation(),
|
||||
mByteCode(NULL),
|
||||
mCode(code),
|
||||
mResultType(resultType),
|
||||
mRequiredArgs(0),
|
||||
mOptionalArgs(0),
|
||||
mArguments(NULL),
|
||||
mScopeChain(NULL),
|
||||
mIsPrototype(false),
|
||||
mIsConstructor(false),
|
||||
mIsChecked(false), // native functions aren't checked (?)
|
||||
mHasRestParameter(false),
|
||||
mRestParameterName(NULL),
|
||||
mClass(NULL)
|
||||
{
|
||||
if (Function_Type) // protect against bootstrap
|
||||
mPrototype = Function_Type->mPrototypeObject;
|
||||
mActivation.mContainer = this;
|
||||
}
|
||||
JSFunction(Context *cx, JSType *resultType, ScopeChain *scopeChain);
|
||||
JSFunction(Context *cx, NativeCode *code, JSType *resultType);
|
||||
|
||||
~JSFunction() { } // keeping gcc happy
|
||||
|
||||
|
@ -1238,7 +1196,7 @@ XXX ...couldn't get this to work...
|
|||
|
||||
void setByteCode(ByteCodeModule *b) { ASSERT(!isNative()); mByteCode = b; }
|
||||
void setResultType(JSType *r) { mResultType = r; }
|
||||
void setArgCounts(uint32 r, uint32 o, bool hasRest);
|
||||
void setArgCounts(Context *cx, uint32 r, uint32 o, bool hasRest);
|
||||
void setArgument(uint32 index, const String *n, JSType *t)
|
||||
{ ASSERT(mArguments && (index < (mRequiredArgs + mOptionalArgs + ((mHasRestParameter) ? 1 : 0) ))); mArguments[index].mType = t; mArguments[index].mName = n; }
|
||||
void setArgumentInitializer(uint32 index, uint32 offset)
|
||||
|
@ -1247,13 +1205,16 @@ XXX ...couldn't get this to work...
|
|||
void setIsPrototype(bool i) { mIsPrototype = i; }
|
||||
void setIsConstructor(bool i) { mIsConstructor = i; }
|
||||
void setIsUnchecked() { mIsChecked = false; }
|
||||
void setFunctionName(FunctionName *n) { mFunctionName = n; }
|
||||
void setFunctionName(FunctionName *n) { mFunctionName = new FunctionName(); mFunctionName->prefix = n->prefix; mFunctionName->name = n->name; }
|
||||
void setFunctionName(const StringAtom *n)
|
||||
{ mFunctionName = new FunctionName(); mFunctionName->name = n; }
|
||||
void setClass(JSType *c) { mClass = c; }
|
||||
|
||||
virtual bool hasBoundThis() { return false; }
|
||||
virtual bool isNative() { return (mCode != NULL); }
|
||||
virtual bool isPrototype() { return mIsPrototype; }
|
||||
virtual bool isConstructor() { return mIsConstructor; }
|
||||
bool isMethod() { return (mClass != NULL); }
|
||||
virtual ByteCodeModule *getByteCode() { ASSERT(!isNative()); return mByteCode; }
|
||||
virtual NativeCode *getNativeCode() { ASSERT(isNative()); return mCode; }
|
||||
|
||||
|
|
|
@ -108,6 +108,21 @@ static float64 firstDayOfMonth[2][12] = {
|
|||
#define DayWithinYear(t, year) ((int32)(Day(t) - DayFromYear(year)))
|
||||
|
||||
|
||||
typedef enum formatspec {
|
||||
FORMATSPEC_FULL, FORMATSPEC_DATE, FORMATSPEC_TIME
|
||||
} formatspec;
|
||||
|
||||
|
||||
/* constants for toString, toUTCString */
|
||||
static char js_NaN_date_str[] = "Invalid Date";
|
||||
static const char* days[] =
|
||||
{
|
||||
"Sun","Mon","Tue","Wed","Thu","Fri","Sat"
|
||||
};
|
||||
static const char* months[] =
|
||||
{
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
|
||||
static float64 DaylightSavingTA(float64 t)
|
||||
|
@ -607,133 +622,6 @@ syntax:
|
|||
return nan;
|
||||
}
|
||||
|
||||
#define MAXARGS 7
|
||||
JSValue Date_Constructor(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
JSValue thatValue = thisValue;
|
||||
if (thatValue.isNull())
|
||||
thatValue = Date_Type->newInstance(cx);
|
||||
ASSERT(thatValue.isObject());
|
||||
JSObject *thisObj = thatValue.object;
|
||||
thisObj->mPrivate = new float64;
|
||||
|
||||
#if 0
|
||||
/* Date called as function */
|
||||
if (!cx->fp->constructing) {
|
||||
int64 us, ms, us2ms;
|
||||
jsdouble msec_time;
|
||||
|
||||
/* NSPR 2.0 docs say 'We do not support PRMJ_NowMS and PRMJ_NowS',
|
||||
* so compute ms from PRMJ_Now.
|
||||
*/
|
||||
us = PRMJ_Now();
|
||||
JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC);
|
||||
JSLL_DIV(ms, us, us2ms);
|
||||
JSLL_L2D(msec_time, ms);
|
||||
|
||||
return date_format(cx, msec_time, FORMATSPEC_FULL, rval);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Date called as constructor */
|
||||
if (argc == 0) {
|
||||
int64 us, ms, us2ms;
|
||||
float64 msec_time;
|
||||
|
||||
us = PRMJ_Now();
|
||||
JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC);
|
||||
JSLL_DIV(ms, us, us2ms);
|
||||
JSLL_L2D(msec_time, ms);
|
||||
|
||||
*((float64 *)(thisObj->mPrivate)) = msec_time;
|
||||
}
|
||||
else {
|
||||
if (argc == 1) {
|
||||
if (!argv[0].isString()) {
|
||||
/* the argument is a millisecond number */
|
||||
float64 d = argv[0].toNumber(cx).f64;
|
||||
*((float64 *)(thisObj->mPrivate)) = TIMECLIP(d);
|
||||
} else {
|
||||
/* the argument is a string; parse it. */
|
||||
const String *str = argv[0].toString(cx).string;
|
||||
|
||||
double d = date_parseString(*str);
|
||||
*((float64 *)(thisObj->mPrivate)) = TIMECLIP(d);
|
||||
}
|
||||
}
|
||||
else {
|
||||
float64 array[MAXARGS];
|
||||
uint32 loop;
|
||||
float64 day;
|
||||
float64 msec_time;
|
||||
|
||||
for (loop = 0; loop < MAXARGS; loop++) {
|
||||
if (loop < argc) {
|
||||
float64 double_arg = argv[loop].toNumber(cx).f64;
|
||||
/* if any arg is NaN, make a NaN date object
|
||||
and return */
|
||||
if (!JSDOUBLE_IS_FINITE(double_arg)) {
|
||||
*((float64 *)(thisObj->mPrivate)) = nan;
|
||||
return thatValue;
|
||||
}
|
||||
array[loop] = JSValue::float64ToInteger(double_arg);
|
||||
} else {
|
||||
if (loop == 2) {
|
||||
array[loop] = 1; /* Default the date argument to 1. */
|
||||
} else {
|
||||
array[loop] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* adjust 2-digit years into the 20th century */
|
||||
if (array[0] >= 0 && array[0] <= 99)
|
||||
array[0] += 1900;
|
||||
|
||||
day = MakeDay(array[0], array[1], array[2]);
|
||||
msec_time = MakeTime(array[3], array[4], array[5], array[6]);
|
||||
msec_time = MakeDate(day, msec_time);
|
||||
msec_time = UTC(msec_time);
|
||||
*((float64 *)(thisObj->mPrivate)) = TIMECLIP(msec_time);
|
||||
}
|
||||
}
|
||||
return thatValue;
|
||||
}
|
||||
|
||||
/* constants for toString, toUTCString */
|
||||
static char js_NaN_date_str[] = "Invalid Date";
|
||||
static const char* days[] =
|
||||
{
|
||||
"Sun","Mon","Tue","Wed","Thu","Fri","Sat"
|
||||
};
|
||||
static const char* months[] =
|
||||
{
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
static JSValue Date_toGMTString(Context *cx, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
StringFormatter buf;
|
||||
float64 *date = Date_getProlog(cx, thisValue);
|
||||
|
||||
if (!JSDOUBLE_IS_FINITE(*date)) {
|
||||
buf << js_NaN_date_str;
|
||||
} else {
|
||||
float64 temp = *date;
|
||||
|
||||
/* Avoid dependence on PRMJ_FormatTimeUSEnglish, because it
|
||||
* requires a PRMJTime... which only has 16-bit years. Sub-ECMA.
|
||||
*/
|
||||
printFormat(buf, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
|
||||
days[WeekDay(temp)],
|
||||
DateFromTime(temp),
|
||||
months[MonthFromTime(temp)],
|
||||
YearFromTime(temp),
|
||||
HourFromTime(temp),
|
||||
MinFromTime(temp),
|
||||
SecFromTime(temp));
|
||||
}
|
||||
return JSValue(new String(buf.getString()));
|
||||
}
|
||||
|
||||
/* for Date.toLocaleString; interface to PRMJTime date struct.
|
||||
* If findEquivalent is true, then try to map the year to an equivalent year
|
||||
|
@ -779,11 +667,6 @@ static void new_explode(float64 timeval, PRMJTime *split, bool findEquivalent)
|
|||
split->tm_isdst = (DaylightSavingTA(timeval) != 0);
|
||||
}
|
||||
|
||||
typedef enum formatspec {
|
||||
FORMATSPEC_FULL, FORMATSPEC_DATE, FORMATSPEC_TIME
|
||||
} formatspec;
|
||||
|
||||
|
||||
/* helper function */
|
||||
static JSValue Date_format(Context * /*cx*/, float64 date, formatspec format)
|
||||
{
|
||||
|
@ -887,6 +770,163 @@ static JSValue Date_format(Context * /*cx*/, float64 date, formatspec format)
|
|||
return JSValue(new String(outf.getString()));
|
||||
}
|
||||
|
||||
|
||||
extern JSValue Date_TypeCast(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
int64 us, ms, us2ms;
|
||||
float64 msec_time;
|
||||
|
||||
/* NSPR 2.0 docs say 'We do not support PRMJ_NowMS and PRMJ_NowS',
|
||||
* so compute ms from PRMJ_Now.
|
||||
*/
|
||||
us = PRMJ_Now();
|
||||
JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC);
|
||||
JSLL_DIV(ms, us, us2ms);
|
||||
JSLL_L2D(msec_time, ms);
|
||||
|
||||
return Date_format(cx, msec_time, FORMATSPEC_FULL);
|
||||
}
|
||||
|
||||
#define MAXARGS 7
|
||||
JSValue Date_Constructor(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
JSValue thatValue = thisValue;
|
||||
if (thatValue.isNull())
|
||||
thatValue = Date_Type->newInstance(cx);
|
||||
ASSERT(thatValue.isObject());
|
||||
JSObject *thisObj = thatValue.object;
|
||||
thisObj->mPrivate = new float64;
|
||||
|
||||
/* Date called as constructor */
|
||||
if (argc == 0) {
|
||||
int64 us, ms, us2ms;
|
||||
float64 msec_time;
|
||||
|
||||
us = PRMJ_Now();
|
||||
JSLL_UI2L(us2ms, PRMJ_USEC_PER_MSEC);
|
||||
JSLL_DIV(ms, us, us2ms);
|
||||
JSLL_L2D(msec_time, ms);
|
||||
|
||||
*((float64 *)(thisObj->mPrivate)) = msec_time;
|
||||
}
|
||||
else {
|
||||
if (argc == 1) {
|
||||
if (!argv[0].isString()) {
|
||||
/* the argument is a millisecond number */
|
||||
float64 d = argv[0].toNumber(cx).f64;
|
||||
*((float64 *)(thisObj->mPrivate)) = TIMECLIP(d);
|
||||
} else {
|
||||
/* the argument is a string; parse it. */
|
||||
const String *str = argv[0].toString(cx).string;
|
||||
|
||||
float64 d = date_parseString(*str);
|
||||
*((float64 *)(thisObj->mPrivate)) = TIMECLIP(d);
|
||||
}
|
||||
}
|
||||
else {
|
||||
float64 array[MAXARGS];
|
||||
uint32 loop;
|
||||
float64 day;
|
||||
float64 msec_time;
|
||||
|
||||
for (loop = 0; loop < MAXARGS; loop++) {
|
||||
if (loop < argc) {
|
||||
float64 double_arg = argv[loop].toNumber(cx).f64;
|
||||
/* if any arg is NaN, make a NaN date object
|
||||
and return */
|
||||
if (!JSDOUBLE_IS_FINITE(double_arg)) {
|
||||
*((float64 *)(thisObj->mPrivate)) = nan;
|
||||
return thatValue;
|
||||
}
|
||||
array[loop] = JSValue::float64ToInteger(double_arg);
|
||||
} else {
|
||||
if (loop == 2) {
|
||||
array[loop] = 1; /* Default the date argument to 1. */
|
||||
} else {
|
||||
array[loop] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* adjust 2-digit years into the 20th century */
|
||||
if (array[0] >= 0 && array[0] <= 99)
|
||||
array[0] += 1900;
|
||||
|
||||
day = MakeDay(array[0], array[1], array[2]);
|
||||
msec_time = MakeTime(array[3], array[4], array[5], array[6]);
|
||||
msec_time = MakeDate(day, msec_time);
|
||||
msec_time = UTC(msec_time);
|
||||
*((float64 *)(thisObj->mPrivate)) = TIMECLIP(msec_time);
|
||||
}
|
||||
}
|
||||
return thatValue;
|
||||
}
|
||||
|
||||
JSValue Date_parse(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 /*argc*/)
|
||||
{
|
||||
const String *str = argv[0].toString(cx).string;
|
||||
float64 d = date_parseString(*str);
|
||||
d = TIMECLIP(d);
|
||||
return JSValue(d);
|
||||
}
|
||||
|
||||
JSValue Date_UTC(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||
{
|
||||
float64 array[MAXARGS];
|
||||
uint32 loop;
|
||||
float64 d;
|
||||
|
||||
for (loop = 0; loop < MAXARGS; loop++) {
|
||||
if (loop < argc) {
|
||||
d = argv[loop].toNumber(cx).f64;
|
||||
if (!JSDOUBLE_IS_FINITE(d))
|
||||
return JSValue(d);
|
||||
array[loop] = floor(d);
|
||||
}
|
||||
else
|
||||
array[loop] = 0;
|
||||
}
|
||||
|
||||
/* adjust 2-digit years into the 20th century */
|
||||
if ((array[0] >= 0) && (array[0] <= 99))
|
||||
array[0] += 1900;
|
||||
/* if we got a 0 for 'date' (which is out of range)
|
||||
* pretend it's a 1. (So Date.UTC(1972, 5) works) */
|
||||
if (array[2] < 1)
|
||||
array[2] = 1;
|
||||
|
||||
d = date_msecFromDate(array[0], array[1], array[2],
|
||||
array[3], array[4], array[5], array[6]);
|
||||
d = TIMECLIP(d);
|
||||
return JSValue(d);
|
||||
}
|
||||
|
||||
|
||||
static JSValue Date_toGMTString(Context *cx, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
StringFormatter buf;
|
||||
float64 *date = Date_getProlog(cx, thisValue);
|
||||
|
||||
if (!JSDOUBLE_IS_FINITE(*date)) {
|
||||
buf << js_NaN_date_str;
|
||||
} else {
|
||||
float64 temp = *date;
|
||||
|
||||
/* Avoid dependence on PRMJ_FormatTimeUSEnglish, because it
|
||||
* requires a PRMJTime... which only has 16-bit years. Sub-ECMA.
|
||||
*/
|
||||
printFormat(buf, "%s, %.2d %s %.4d %.2d:%.2d:%.2d GMT",
|
||||
days[WeekDay(temp)],
|
||||
DateFromTime(temp),
|
||||
months[MonthFromTime(temp)],
|
||||
YearFromTime(temp),
|
||||
HourFromTime(temp),
|
||||
MinFromTime(temp),
|
||||
SecFromTime(temp));
|
||||
}
|
||||
return JSValue(new String(buf.getString()));
|
||||
}
|
||||
|
||||
|
||||
static JSValue Date_toLocaleHelper(Context *cx, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/, char *format)
|
||||
{
|
||||
StringFormatter outf;
|
||||
|
@ -1341,6 +1381,7 @@ Context::PrototypeFunctions *getDateProtos()
|
|||
{ "setMilliseconds", Number_Type, 1, Date_setMilliseconds },
|
||||
{ "setUTCMilliseconds", Number_Type, 1, Date_setUTCMilliseconds },
|
||||
{ "toUTCString", String_Type, 0, Date_toGMTString },
|
||||
{ "toGMTString", String_Type, 0, Date_toGMTString }, // XXX this is a SpiderMonkey extension?
|
||||
{ "toLocaleString", String_Type, 0, Date_toLocaleString },
|
||||
{ "toLocaleDateString", String_Type, 0, Date_toLocaleDateString },
|
||||
{ "toLocaleTimeString", String_Type, 0, Date_toLocaleTimeString },
|
||||
|
|
|
@ -37,6 +37,9 @@ namespace JS2Runtime {
|
|||
|
||||
|
||||
extern JSValue Date_Constructor(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc);
|
||||
extern JSValue Date_TypeCast(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc);
|
||||
extern JSValue Date_parse(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc);
|
||||
extern JSValue Date_UTC(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc);
|
||||
|
||||
Context::PrototypeFunctions *getDateProtos();
|
||||
|
||||
|
|
|
@ -249,7 +249,7 @@ void initMathObject(Context *cx, JSObject *mathObj)
|
|||
(NamespaceList *)(NULL), Number_Type, JSValue(MathObjectConstants[i].value));
|
||||
|
||||
for (i = 0; i < sizeof(MathObjectFunctions) / sizeof(MathObjectFunctionDef); i++) {
|
||||
JSFunction *f = new JSFunction(MathObjectFunctions[i].imp, Number_Type);
|
||||
JSFunction *f = new JSFunction(cx, MathObjectFunctions[i].imp, Number_Type);
|
||||
mathObj->defineVariable(cx, widenCString(MathObjectFunctions[i].name),
|
||||
(NamespaceList *)(NULL), Number_Type, JSValue(f));
|
||||
}
|
||||
|
|
|
@ -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(load, NULL)));
|
||||
globalObject->defineVariable(&cx, widenCString("print"), (NamespaceList *)(NULL), NULL, JSValue(new JSFunction(print, NULL)));
|
||||
globalObject->defineVariable(&cx, widenCString("debug"), (NamespaceList *)(NULL), NULL, JSValue(new JSFunction(debug, NULL)));
|
||||
globalObject->defineVariable(&cx, widenCString("trace"), (NamespaceList *)(NULL), NULL, JSValue(new JSFunction(trace, NULL)));
|
||||
globalObject->defineVariable(&cx, widenCString("dikdik"), (NamespaceList *)(NULL), NULL, JSValue(new JSFunction(dikdik, NULL)));
|
||||
globalObject->defineVariable(&cx, widenCString("version"), (NamespaceList *)(NULL), NULL, JSValue(new JSFunction(version, NULL)));
|
||||
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)));
|
||||
|
||||
bool doInteractive = true;
|
||||
int result = 0;
|
||||
|
|
|
@ -41,7 +41,7 @@ RSC=rc.exe
|
|||
# PROP Intermediate_Dir "Release"
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "../../src" /D "_CONSOLE" /D "NDEBUG" /D "WIN32" /D "_MBCS" /YX /FD /c
|
||||
# ADD CPP /nologo /W3 /GX /O2 /I "../../src" /D "_CONSOLE" /D "NDEBUG" /D "WIN32" /D "_MBCS" /D "XP_PC" /YX /FD /c
|
||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||
BSC32=bscmake.exe
|
||||
|
@ -65,7 +65,7 @@ LINK32=link.exe
|
|||
# PROP Ignore_Export_Lib 0
|
||||
# PROP Target_Dir ""
|
||||
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /I "../../src" /D "_CONSOLE" /D "DEBUG" /D "_DEBUG" /D "WIN32" /D "_MBCS" /FR /YX /FD /GZ /c
|
||||
# ADD CPP /nologo /W3 /Gm /GR /GX /ZI /Od /I "../../src" /D "_CONSOLE" /D "DEBUG" /D "_DEBUG" /D "WIN32" /D "_MBCS" /D "XP_PC" /FR /YX /FD /GZ /c
|
||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||
BSC32=bscmake.exe
|
||||
|
|
Загрузка…
Ссылка в новой задаче