зеркало из https://github.com/mozilla/gecko-dev.git
Added Array.sort. Fixed toNumber(String) for trailing whitespace. Fixed
Date.SetXXX for date values. Fixed scopechain growth bug. Fixed empty array literals. Fixed empty type casts for built-ins.
This commit is contained in:
Родитель
4ca6952df1
Коммит
52e1b91b23
|
@ -533,17 +533,6 @@ void ByteCodeGen::genCodeForFunction(FunctionDefinition &f, size_t pos, JSFuncti
|
||||||
{
|
{
|
||||||
mScopeChain->addScope(fnc->mParameterBarrel);
|
mScopeChain->addScope(fnc->mParameterBarrel);
|
||||||
mScopeChain->addScope(&fnc->mActivation);
|
mScopeChain->addScope(&fnc->mActivation);
|
||||||
// OPT - no need to push the parameter and function
|
|
||||||
// scopes if the function doesn't contain any 'eval'
|
|
||||||
// calls, all other references to the variables mapped
|
|
||||||
// inside these scopes will have been turned into
|
|
||||||
// localVar references.
|
|
||||||
/*
|
|
||||||
addByte(PushScopeOp);
|
|
||||||
addPointer(fnc->mParameterBarrel);
|
|
||||||
addByte(PushScopeOp);
|
|
||||||
addPointer(&fnc->mActivation);
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (f.name) {
|
if (f.name) {
|
||||||
|
@ -632,13 +621,8 @@ void ByteCodeGen::genCodeForFunction(FunctionDefinition &f, size_t pos, JSFuncti
|
||||||
if (f.body)
|
if (f.body)
|
||||||
hasReturn = genCodeForStatement(f.body, NULL, NotALabel);
|
hasReturn = genCodeForStatement(f.body, NULL, NotALabel);
|
||||||
|
|
||||||
/*
|
|
||||||
// OPT - see above
|
|
||||||
addByte(PopScopeOp);
|
|
||||||
addByte(PopScopeOp);
|
|
||||||
*/
|
|
||||||
if (isConstructor) {
|
if (isConstructor) {
|
||||||
ASSERT(!hasReturn); // is this useful? Won't the semantics have done it?
|
ASSERT(!hasReturn); // XXX is this useful? Won't the semantics have done it?
|
||||||
addOp(LoadThisOp);
|
addOp(LoadThisOp);
|
||||||
ASSERT(mStackTop == 1);
|
ASSERT(mStackTop == 1);
|
||||||
addOpSetDepth(ReturnOp, 0);
|
addOpSetDepth(ReturnOp, 0);
|
||||||
|
|
|
@ -202,8 +202,9 @@ JSValue Context::interpret(JS2Runtime::ByteCodeModule *bcm, int offset, ScopeCha
|
||||||
mScopeChain = new ScopeChain(this, mWorld);
|
mScopeChain = new ScopeChain(this, mWorld);
|
||||||
mScopeChain->addScope(getGlobalObject());
|
mScopeChain->addScope(getGlobalObject());
|
||||||
}
|
}
|
||||||
if (mThis.isObject())
|
|
||||||
mScopeChain->addScope(mThis.object);
|
// if (mThis.isObject())
|
||||||
|
// mScopeChain->addScope(mThis.object);
|
||||||
// mScopeChain->addScope(mActivationStack.top());
|
// mScopeChain->addScope(mActivationStack.top());
|
||||||
|
|
||||||
mCurModule = bcm;
|
mCurModule = bcm;
|
||||||
|
@ -225,8 +226,8 @@ JSValue Context::interpret(JS2Runtime::ByteCodeModule *bcm, int offset, ScopeCha
|
||||||
|
|
||||||
// the following (delete's) are a bit iffy - depends on whether
|
// the following (delete's) are a bit iffy - depends on whether
|
||||||
// a closure capturing the contents has come along...
|
// a closure capturing the contents has come along...
|
||||||
if (mThis.isObject())
|
// if (mThis.isObject())
|
||||||
mScopeChain->popScope();
|
// mScopeChain->popScope();
|
||||||
delete[] mStack;
|
delete[] mStack;
|
||||||
delete[] mLocals;
|
delete[] mLocals;
|
||||||
if (scopeChain == NULL)
|
if (scopeChain == NULL)
|
||||||
|
@ -249,8 +250,8 @@ JSValue Context::interpret(JS2Runtime::ByteCodeModule *bcm, int offset, ScopeCha
|
||||||
|
|
||||||
// the following (delete's) are a bit iffy - depends on whether
|
// the following (delete's) are a bit iffy - depends on whether
|
||||||
// a closure capturing the contents has come along...
|
// a closure capturing the contents has come along...
|
||||||
if (mThis.isObject())
|
// if (mThis.isObject())
|
||||||
mScopeChain->popScope();
|
// mScopeChain->popScope();
|
||||||
delete[] mStack;
|
delete[] mStack;
|
||||||
delete[] mLocals;
|
delete[] mLocals;
|
||||||
if (scopeChain == NULL)
|
if (scopeChain == NULL)
|
||||||
|
@ -401,6 +402,7 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
||||||
try {
|
try {
|
||||||
if (mDebugFlag) {
|
if (mDebugFlag) {
|
||||||
FunctionName *fnName;
|
FunctionName *fnName;
|
||||||
|
uint32 x = mScopeChain->mScopeStack.size();
|
||||||
if (mCurModule->mFunction && (fnName = mCurModule->mFunction->getFunctionName())) {
|
if (mCurModule->mFunction && (fnName = mCurModule->mFunction->getFunctionName())) {
|
||||||
StringFormatter s;
|
StringFormatter s;
|
||||||
PrettyPrinter pp(s);
|
PrettyPrinter pp(s);
|
||||||
|
@ -409,10 +411,10 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
||||||
std::string str(fnStr.length(), char());
|
std::string str(fnStr.length(), char());
|
||||||
std::transform(fnStr.begin(), fnStr.end(), str.begin(), narrow);
|
std::transform(fnStr.begin(), fnStr.end(), str.begin(), narrow);
|
||||||
uint32 len = strlen(str.c_str());
|
uint32 len = strlen(str.c_str());
|
||||||
printFormat(stdOut, "%.30s+%.4d%*c%d ", str.c_str(), (pc - mCurModule->mCodeBase), (len > 30) ? 0 : (len - 30), ' ', stackSize());
|
printFormat(stdOut, "%.30s+%.4d%*c%d %d ", str.c_str(), (pc - mCurModule->mCodeBase), (len > 30) ? 0 : (len - 30), ' ', stackSize(), x);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printFormat(stdOut, "+%.4d%*c%d ", (pc - mCurModule->mCodeBase), 30, ' ', stackSize());
|
printFormat(stdOut, "+%.4d%*c%d %d ", (pc - mCurModule->mCodeBase), 30, ' ', stackSize(), x);
|
||||||
printInstruction(stdOut, toUInt32(pc - mCurModule->mCodeBase), *mCurModule);
|
printInstruction(stdOut, toUInt32(pc - mCurModule->mCodeBase), *mCurModule);
|
||||||
}
|
}
|
||||||
switch ((ByteCodeOp)(*pc++)) {
|
switch ((ByteCodeOp)(*pc++)) {
|
||||||
|
@ -639,8 +641,8 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
||||||
mArgumentBase, oldThis,
|
mArgumentBase, oldThis,
|
||||||
pc, mCurModule));
|
pc, mCurModule));
|
||||||
mScopeChain = target->getScopeChain();
|
mScopeChain = target->getScopeChain();
|
||||||
if (mThis.isObject())
|
// if (mThis.isObject())
|
||||||
mScopeChain->addScope(mThis.object);
|
// mScopeChain->addScope(mThis.object);
|
||||||
|
|
||||||
if (!target->isChecked()) {
|
if (!target->isChecked()) {
|
||||||
JSArrayInstance *args = (JSArrayInstance *)Array_Type->newInstance(this);
|
JSArrayInstance *args = (JSArrayInstance *)Array_Type->newInstance(this);
|
||||||
|
@ -692,7 +694,10 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
||||||
}
|
}
|
||||||
mActivationStack.pop();
|
mActivationStack.pop();
|
||||||
delete[] mLocals;
|
delete[] mLocals;
|
||||||
delete[] mStack;
|
delete[] mStack;
|
||||||
|
|
||||||
|
mScopeChain->popScope();
|
||||||
|
mScopeChain->popScope();
|
||||||
|
|
||||||
mCurModule = prev->mModule;
|
mCurModule = prev->mModule;
|
||||||
pc = prev->mPC;
|
pc = prev->mPC;
|
||||||
|
@ -721,6 +726,9 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
||||||
delete[] mLocals;
|
delete[] mLocals;
|
||||||
delete[] mStack;
|
delete[] mStack;
|
||||||
|
|
||||||
|
mScopeChain->popScope();
|
||||||
|
mScopeChain->popScope();
|
||||||
|
|
||||||
mCurModule = prev->mModule;
|
mCurModule = prev->mModule;
|
||||||
pc = prev->mPC;
|
pc = prev->mPC;
|
||||||
endPC = mCurModule->mCodeBase + mCurModule->mLength;
|
endPC = mCurModule->mCodeBase + mCurModule->mLength;
|
||||||
|
@ -2225,8 +2233,19 @@ float64 stringToNumber(const String *string)
|
||||||
if (sBegin)
|
if (sBegin)
|
||||||
if ((sBegin[0] == '0') && ((sBegin[1] & ~0x20) == 'X'))
|
if ((sBegin[0] == '0') && ((sBegin[1] & ~0x20) == 'X'))
|
||||||
return stringToInteger(sBegin, string->end(), numEnd, 16);
|
return stringToInteger(sBegin, string->end(), numEnd, 16);
|
||||||
else
|
else {
|
||||||
return stringToDouble(sBegin, string->end(), numEnd);
|
float64 result = stringToDouble(sBegin, string->end(), numEnd);
|
||||||
|
if (numEnd != string->end()) {
|
||||||
|
const char16 *sEnd = string->end();
|
||||||
|
while (numEnd != sEnd) {
|
||||||
|
if (!isSpace(*numEnd++))
|
||||||
|
return nan;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return result;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -175,9 +175,11 @@ bool JSObject::hasProperty(const String &name, NamespaceList *names, Access acc,
|
||||||
bool JSObject::deleteProperty(const String &name, NamespaceList *names)
|
bool JSObject::deleteProperty(const String &name, NamespaceList *names)
|
||||||
{
|
{
|
||||||
PropertyIterator i = findNamespacedProperty(name, names);
|
PropertyIterator i = findNamespacedProperty(name, names);
|
||||||
if ((PROPERTY_ATTR(i) & Property::DontDelete) == 0) {
|
if (i != mProperties.end()) {
|
||||||
mProperties.erase(i);
|
if ((PROPERTY_ATTR(i) & Property::DontDelete) == 0) {
|
||||||
return true;
|
mProperties.erase(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1962,6 +1964,14 @@ static JSValue Number_Constructor(Context *cx, const JSValue& thisValue, JSValue
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSValue Number_TypeCast(Context *cx, const JSValue& /*thisValue*/, JSValue *argv, uint32 argc)
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
return kPositiveZero;
|
||||||
|
else
|
||||||
|
return argv[0].toNumber(cx);
|
||||||
|
}
|
||||||
|
|
||||||
static JSValue Number_toString(Context *cx, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/)
|
static JSValue Number_toString(Context *cx, const JSValue& thisValue, JSValue * /*argv*/, uint32 /*argc*/)
|
||||||
{
|
{
|
||||||
if (!thisValue.isObject() || (thisValue.getType() != Number_Type))
|
if (!thisValue.isObject() || (thisValue.getType() != Number_Type))
|
||||||
|
@ -2387,14 +2397,17 @@ void Context::initBuiltins()
|
||||||
|
|
||||||
Function_Type->mTypeCast = new JSFunction(this, Function_Constructor, Object_Type);
|
Function_Type->mTypeCast = new JSFunction(this, Function_Constructor, Object_Type);
|
||||||
|
|
||||||
|
Number_Type->mTypeCast = new JSFunction(this, Number_TypeCast, Number_Type);
|
||||||
|
|
||||||
Array_Type->defineUnaryOperator(Index, new JSFunction(this, Array_GetElement, Object_Type));
|
Array_Type->defineUnaryOperator(Index, new JSFunction(this, Array_GetElement, Object_Type));
|
||||||
Array_Type->defineUnaryOperator(IndexEqual, new JSFunction(this, Array_SetElement, Object_Type));
|
Array_Type->defineUnaryOperator(IndexEqual, new JSFunction(this, Array_SetElement, Object_Type));
|
||||||
|
Array_Type->mTypeCast = new JSFunction(this, Array_Constructor, Array_Type);
|
||||||
|
|
||||||
Date_Type->mTypeCast = new JSFunction(this, Date_TypeCast, String_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("parse"), NULL, new JSFunction(this, Date_parse, Number_Type));
|
||||||
Date_Type->defineStaticMethod(this, widenCString("UTC"), NULL, new JSFunction(this, Date_UTC, Number_Type));
|
Date_Type->defineStaticMethod(this, widenCString("UTC"), NULL, new JSFunction(this, Date_UTC, Number_Type));
|
||||||
|
|
||||||
String_Type->mTypeCast = new JSFunction(this, String_Constructor, String_Type);
|
String_Type->mTypeCast = new JSFunction(this, String_TypeCast, String_Type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1515,7 +1515,7 @@ XXX ...couldn't get this to work...
|
||||||
|
|
||||||
void resizeStack(uint32 n)
|
void resizeStack(uint32 n)
|
||||||
{
|
{
|
||||||
ASSERT(n < mStackMax);
|
ASSERT(n <= mStackMax);
|
||||||
mStackTop = n;
|
mStackTop = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1619,6 +1619,13 @@ XXX ...couldn't get this to work...
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
(a local instance of) This class is used when a function in the
|
||||||
|
interpreter execution codepath may need to re-invoke the interpreter
|
||||||
|
(by calling an internal method that MAY have an override). The stack
|
||||||
|
replacement simply inserts a stack big enough for whatever action is
|
||||||
|
about to occur.
|
||||||
|
*/
|
||||||
class ContextStackReplacement {
|
class ContextStackReplacement {
|
||||||
public:
|
public:
|
||||||
enum { ReplacementStackSize = 4 };
|
enum { ReplacementStackSize = 4 };
|
||||||
|
|
|
@ -62,7 +62,17 @@ JSValue Array_Constructor(Context *cx, const JSValue& thisValue, JSValue *argv,
|
||||||
JSArrayInstance *arrInst = checked_cast<JSArrayInstance *>(thisObj);
|
JSArrayInstance *arrInst = checked_cast<JSArrayInstance *>(thisObj);
|
||||||
if (argc > 0) {
|
if (argc > 0) {
|
||||||
if (argc == 1) {
|
if (argc == 1) {
|
||||||
arrInst->mLength = (uint32)(argv[0].toNumber(cx).f64);
|
if (argv[0].isNumber()) {
|
||||||
|
uint32 i = (uint32)(argv[0].f64);
|
||||||
|
if (i == argv[0].f64)
|
||||||
|
arrInst->mLength = i;
|
||||||
|
else
|
||||||
|
cx->reportError(Exception::rangeError, "Array length too large");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
arrInst->mLength = 1;
|
||||||
|
arrInst->defineVariable(cx, widenCString("0"), (NamespaceList *)(NULL), Property::Enumerable, Object_Type, argv[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
arrInst->mLength = argc;
|
arrInst->mLength = argc;
|
||||||
|
@ -93,7 +103,8 @@ static JSValue Array_toString(Context *cx, const JSValue& thisValue, JSValue * /
|
||||||
const String *id = numberToString(i);
|
const String *id = numberToString(i);
|
||||||
arrInst->getProperty(cx, *id, NULL);
|
arrInst->getProperty(cx, *id, NULL);
|
||||||
JSValue result = cx->popValue();
|
JSValue result = cx->popValue();
|
||||||
s->append(*result.toString(cx).string);
|
if (!result.isUndefined() && !result.isNull())
|
||||||
|
s->append(*result.toString(cx).string);
|
||||||
if (i < (arrInst->mLength - 1))
|
if (i < (arrInst->mLength - 1))
|
||||||
s->append(widenCString(","));
|
s->append(widenCString(","));
|
||||||
}
|
}
|
||||||
|
@ -385,9 +396,154 @@ static JSValue Array_slice(Context *cx, const JSValue& thisValue, JSValue *argv,
|
||||||
return JSValue(A);
|
return JSValue(A);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue Array_sort(Context * /*cx*/, const JSValue& /*thisValue*/, JSValue * /*argv*/, uint32 /*argc*/)
|
typedef struct CompareArgs {
|
||||||
|
Context *context;
|
||||||
|
JSFunction *target;
|
||||||
|
} CompareArgs;
|
||||||
|
|
||||||
|
typedef struct QSortArgs {
|
||||||
|
JSValue *vec;
|
||||||
|
JSValue *pivot;
|
||||||
|
CompareArgs *arg;
|
||||||
|
} QSortArgs;
|
||||||
|
|
||||||
|
static int sort_compare(JSValue *a, JSValue *b, CompareArgs *arg);
|
||||||
|
|
||||||
|
static void
|
||||||
|
js_qsort_r(QSortArgs *qa, int lo, int hi)
|
||||||
{
|
{
|
||||||
return kUndefinedValue;
|
JSValue *pivot, *vec, *a, *b;
|
||||||
|
int i, j, lohi, hilo;
|
||||||
|
|
||||||
|
CompareArgs *arg;
|
||||||
|
|
||||||
|
pivot = qa->pivot;
|
||||||
|
vec = qa->vec;
|
||||||
|
arg = qa->arg;
|
||||||
|
|
||||||
|
while (lo < hi) {
|
||||||
|
i = lo;
|
||||||
|
j = hi;
|
||||||
|
a = vec + i;
|
||||||
|
*pivot = *a;
|
||||||
|
while (i < j) {
|
||||||
|
b = vec + j;
|
||||||
|
if (sort_compare(b, pivot, arg) >= 0) {
|
||||||
|
j--;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
*a = *b;
|
||||||
|
while (sort_compare(a, pivot, arg) <= 0) {
|
||||||
|
i++;
|
||||||
|
a = vec + i;
|
||||||
|
if (i == j)
|
||||||
|
goto store_pivot;
|
||||||
|
}
|
||||||
|
*b = *a;
|
||||||
|
}
|
||||||
|
if (i > lo) {
|
||||||
|
store_pivot:
|
||||||
|
*a = *pivot;
|
||||||
|
}
|
||||||
|
if (i - lo < hi - i) {
|
||||||
|
lohi = i - 1;
|
||||||
|
if (lo < lohi)
|
||||||
|
js_qsort_r(qa, lo, lohi);
|
||||||
|
lo = i + 1;
|
||||||
|
} else {
|
||||||
|
hilo = i + 1;
|
||||||
|
if (hilo < hi)
|
||||||
|
js_qsort_r(qa, hilo, hi);
|
||||||
|
hi = i - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void js_qsort(JSValue *vec, size_t nel, CompareArgs *arg)
|
||||||
|
{
|
||||||
|
JSValue *pivot;
|
||||||
|
QSortArgs qa;
|
||||||
|
|
||||||
|
pivot = new JSValue();
|
||||||
|
qa.vec = vec;
|
||||||
|
qa.pivot = pivot;
|
||||||
|
qa.arg = arg;
|
||||||
|
js_qsort_r(&qa, 0, (int)(nel - 1));
|
||||||
|
delete(pivot);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sort_compare(JSValue *a, JSValue *b, CompareArgs *arg)
|
||||||
|
{
|
||||||
|
JSValue av = *(const JSValue *)a;
|
||||||
|
JSValue bv = *(const JSValue *)b;
|
||||||
|
CompareArgs *ca = (CompareArgs *) arg;
|
||||||
|
Context *cx = ca->context;
|
||||||
|
|
||||||
|
if (ca->target == NULL) {
|
||||||
|
int32 result;
|
||||||
|
if (av.isUndefined() || bv.isUndefined()) {
|
||||||
|
/* Put undefined properties at the end. */
|
||||||
|
result = (av.isUndefined()) ? 1 : -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const String *astr = av.toString(cx).string;
|
||||||
|
const String *bstr = bv.toString(cx).string;
|
||||||
|
result = astr->compare(*bstr);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
JSValue argv[2];
|
||||||
|
argv[0] = av;
|
||||||
|
argv[1] = bv;
|
||||||
|
JSValue result = cx->invokeFunction(ca->target, kNullValue, argv, 2);
|
||||||
|
return (int32)(result.toInt32(cx).f64);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static JSValue Array_sort(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||||
|
{
|
||||||
|
ASSERT(thisValue.isObject());
|
||||||
|
ContextStackReplacement csr(cx);
|
||||||
|
|
||||||
|
CompareArgs ca;
|
||||||
|
ca.context = cx;
|
||||||
|
|
||||||
|
if (argc > 0) {
|
||||||
|
if (!argv[0].isFunction())
|
||||||
|
cx->reportError(Exception::typeError, "sort needs a compare function");
|
||||||
|
ca.target = argv[0].function;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ca.target = NULL;
|
||||||
|
|
||||||
|
JSObject *thisObj = thisValue.object;
|
||||||
|
thisObj->getProperty(cx, cx->Length_StringAtom, CURRENT_ATTR);
|
||||||
|
JSValue result = cx->popValue();
|
||||||
|
uint32 length = (uint32)(result.toUInt32(cx).f64);
|
||||||
|
|
||||||
|
if (length > 0) {
|
||||||
|
uint32 i;
|
||||||
|
JSValue *vec = new JSValue[length];
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
const String *id = numberToString(i);
|
||||||
|
thisObj->getProperty(cx, *id, CURRENT_ATTR);
|
||||||
|
vec[i] = cx->popValue();
|
||||||
|
delete id;
|
||||||
|
}
|
||||||
|
|
||||||
|
js_qsort(vec, length, &ca);
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++) {
|
||||||
|
const String *id = numberToString(i);
|
||||||
|
thisObj->setProperty(cx, *id, CURRENT_ATTR, vec[i]);
|
||||||
|
delete id;
|
||||||
|
}
|
||||||
|
delete[] vec;
|
||||||
|
}
|
||||||
|
return thisValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue Array_splice(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
static JSValue Array_splice(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||||
|
|
|
@ -426,6 +426,74 @@ static JSValue Date_makeTime(Context *cx, const JSValue& thisValue, JSValue *arg
|
||||||
return JSValue(*date);
|
return JSValue(*date);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static JSValue Date_makeDate(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc, uint32 maxargs, bool local)
|
||||||
|
{
|
||||||
|
uint32 i;
|
||||||
|
float64 lorutime; /* local or UTC version of *date */
|
||||||
|
float64 args[3], *argp, *stop;
|
||||||
|
float64 year, month, day;
|
||||||
|
float64 result;
|
||||||
|
|
||||||
|
float64 *date = Date_getProlog(cx, thisValue);
|
||||||
|
|
||||||
|
result = *date;
|
||||||
|
|
||||||
|
/* see complaint about ECMA in date_MakeTime */
|
||||||
|
if (argc == 0)
|
||||||
|
argc = 1; /* should be safe, because length of all settors is 1 */
|
||||||
|
else if (argc > maxargs)
|
||||||
|
argc = maxargs; /* clamp argc */
|
||||||
|
|
||||||
|
for (i = 0; i < argc; i++) {
|
||||||
|
argv[i] = argv[i].toNumber(cx);
|
||||||
|
if (JSDOUBLE_IS_NaN(argv[i])) {
|
||||||
|
*date = nan;
|
||||||
|
return kNaNValue;
|
||||||
|
}
|
||||||
|
args[i] = argv[i].toInteger(cx).f64;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return NaN if date is NaN and we're not setting the year,
|
||||||
|
* If we are, use 0 as the time. */
|
||||||
|
if (!(JSDOUBLE_IS_FINITE(result))) {
|
||||||
|
if (argc < 3)
|
||||||
|
return kNaNValue;
|
||||||
|
else
|
||||||
|
lorutime = +0.;
|
||||||
|
} else {
|
||||||
|
if (local)
|
||||||
|
lorutime = LocalTime(result);
|
||||||
|
else
|
||||||
|
lorutime = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
argp = args;
|
||||||
|
stop = argp + argc;
|
||||||
|
if (maxargs >= 3 && argp < stop)
|
||||||
|
year = *argp++;
|
||||||
|
else
|
||||||
|
year = YearFromTime(lorutime);
|
||||||
|
|
||||||
|
if (maxargs >= 2 && argp < stop)
|
||||||
|
month = *argp++;
|
||||||
|
else
|
||||||
|
month = MonthFromTime(lorutime);
|
||||||
|
|
||||||
|
if (maxargs >= 1 && argp < stop)
|
||||||
|
day = *argp++;
|
||||||
|
else
|
||||||
|
day = DateFromTime(lorutime);
|
||||||
|
|
||||||
|
day = MakeDay(year, month, day); /* day within year */
|
||||||
|
result = MakeDate(day, TimeWithinDay(lorutime));
|
||||||
|
|
||||||
|
if (local)
|
||||||
|
result = UTC(result);
|
||||||
|
|
||||||
|
*date = TIMECLIP(result);
|
||||||
|
return JSValue(*date);
|
||||||
|
}
|
||||||
|
|
||||||
/* find UTC time from given date... no 1900 correction! */
|
/* find UTC time from given date... no 1900 correction! */
|
||||||
static float64 date_msecFromDate(float64 year, float64 mon, float64 mday, float64 hour, float64 min, float64 sec, float64 msec)
|
static float64 date_msecFromDate(float64 year, float64 mon, float64 mday, float64 hour, float64 min, float64 sec, float64 msec)
|
||||||
{
|
{
|
||||||
|
@ -1258,32 +1326,32 @@ static JSValue Date_setYear(Context *cx, const JSValue& thisValue, JSValue *argv
|
||||||
|
|
||||||
static JSValue Date_setFullYear(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
static JSValue Date_setFullYear(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||||
{
|
{
|
||||||
return Date_makeTime(cx, thisValue, argv, argc, 3, true);
|
return Date_makeDate(cx, thisValue, argv, argc, 3, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue Date_setUTCFullYear(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
static JSValue Date_setUTCFullYear(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||||
{
|
{
|
||||||
return Date_makeTime(cx, thisValue, argv, argc, 3, false);
|
return Date_makeDate(cx, thisValue, argv, argc, 3, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue Date_setMonth(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
static JSValue Date_setMonth(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||||
{
|
{
|
||||||
return Date_makeTime(cx, thisValue, argv, argc, 2, true);
|
return Date_makeDate(cx, thisValue, argv, argc, 2, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue Date_setUTCMonth(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
static JSValue Date_setUTCMonth(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||||
{
|
{
|
||||||
return Date_makeTime(cx, thisValue, argv, argc, 2, false);
|
return Date_makeDate(cx, thisValue, argv, argc, 2, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue Date_setDate(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
static JSValue Date_setDate(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||||
{
|
{
|
||||||
return Date_makeTime(cx, thisValue, argv, argc, 1, true);
|
return Date_makeDate(cx, thisValue, argv, argc, 1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue Date_setUTCDate(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
static JSValue Date_setUTCDate(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||||
{
|
{
|
||||||
return Date_makeTime(cx, thisValue, argv, argc, 1, false);
|
return Date_makeDate(cx, thisValue, argv, argc, 1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static JSValue Date_setHours(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
static JSValue Date_setHours(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc)
|
||||||
|
|
|
@ -67,9 +67,18 @@ JSValue String_Constructor(Context *cx, const JSValue& thisValue, JSValue *argv,
|
||||||
return thatValue;
|
return thatValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSValue String_TypeCast(Context *cx, const JSValue& /*thisValue*/, JSValue *argv, uint32 argc)
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
return JSValue(&cx->Empty_StringAtom);
|
||||||
|
else
|
||||||
|
return argv[0].toString(cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
JSValue String_fromCharCode(Context *cx, const JSValue& /*thisValue*/, JSValue *argv, uint32 argc)
|
JSValue String_fromCharCode(Context *cx, const JSValue& /*thisValue*/, JSValue *argv, uint32 argc)
|
||||||
{
|
{
|
||||||
String *resultStr = new String(); // can't use cx->mEmptyString because we're modifying this below
|
String *resultStr = new String(); // can't use cx->Empty_StringAtom; because we're modifying this below
|
||||||
resultStr->reserve(argc);
|
resultStr->reserve(argc);
|
||||||
for (uint32 i = 0; i < argc; i++)
|
for (uint32 i = 0; i < argc; i++)
|
||||||
*resultStr += (char16)(argv[i].toUInt16(cx).f64);
|
*resultStr += (char16)(argv[i].toUInt16(cx).f64);
|
||||||
|
|
|
@ -36,6 +36,7 @@ namespace JS2Runtime {
|
||||||
|
|
||||||
|
|
||||||
extern JSValue String_Constructor(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc);
|
extern JSValue String_Constructor(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc);
|
||||||
|
extern JSValue String_TypeCast(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc);
|
||||||
extern JSValue String_fromCharCode(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc);
|
extern JSValue String_fromCharCode(Context *cx, const JSValue& thisValue, JSValue *argv, uint32 argc);
|
||||||
|
|
||||||
Context::PrototypeFunctions *getStringProtos();
|
Context::PrototypeFunctions *getStringProtos();
|
||||||
|
|
|
@ -1683,8 +1683,6 @@ double JS::stringToDouble(const char16 *str, const char16 *strEnd, const char16
|
||||||
double value = strToDouble(cstr.get(), estr);
|
double value = strToDouble(cstr.get(), estr);
|
||||||
ptrdiff_t i = estr - cstr.get();
|
ptrdiff_t i = estr - cstr.get();
|
||||||
numEnd = i ? str1 + i : str;
|
numEnd = i ? str1 + i : str;
|
||||||
if ((value == 0.0) && (i == 0))
|
|
||||||
return nan;
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,6 +221,10 @@ static bool processArgs(Context *cx, int argc, char **argv, int *result)
|
||||||
for (int i = 0; i < argc; i++) {
|
for (int i = 0; i < argc; i++) {
|
||||||
if (argv[i][0] == '-') {
|
if (argv[i][0] == '-') {
|
||||||
switch (argv[i][1]) {
|
switch (argv[i][1]) {
|
||||||
|
default:
|
||||||
|
stdOut << "unrecognized command line switch\n";
|
||||||
|
i = argc;
|
||||||
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
@ -235,7 +239,12 @@ static bool processArgs(Context *cx, int argc, char **argv, int *result)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if ((argv[i][0] == '/') && (argv[i][1] == '/')) {
|
||||||
|
// skip rest of command line
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return doInteractive;
|
return doInteractive;
|
||||||
}
|
}
|
||||||
|
@ -246,13 +255,15 @@ static bool processArgs(Context *cx, int argc, char **argv, int *result)
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
#if defined(XP_MAC) && !defined(XP_MAC_MPW)
|
|
||||||
initConsole("\pJavaScript Shell", "Welcome to the js2 shell.\n", argc, argv);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace JavaScript;
|
using namespace JavaScript;
|
||||||
using namespace Shell;
|
using namespace Shell;
|
||||||
|
|
||||||
|
#if defined(XP_MAC) && !defined(XP_MAC_MPW)
|
||||||
|
initConsole("\pJavaScript Shell", "Welcome to DikDik.\n", argc, argv);
|
||||||
|
#else
|
||||||
|
stdOut << "Welcome to DikDik.\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
try {
|
try {
|
||||||
JSObject *globalObject;
|
JSObject *globalObject;
|
||||||
Context cx(&globalObject, world, a, Pragma::js2);
|
Context cx(&globalObject, world, a, Pragma::js2);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче