зеркало из https://github.com/mozilla/pjs.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:
Родитель
fcfa1d2581
Коммит
9f287653da
|
@ -533,17 +533,6 @@ void ByteCodeGen::genCodeForFunction(FunctionDefinition &f, size_t pos, JSFuncti
|
|||
{
|
||||
mScopeChain->addScope(fnc->mParameterBarrel);
|
||||
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
|
||||
if (f.name) {
|
||||
|
@ -632,13 +621,8 @@ void ByteCodeGen::genCodeForFunction(FunctionDefinition &f, size_t pos, JSFuncti
|
|||
if (f.body)
|
||||
hasReturn = genCodeForStatement(f.body, NULL, NotALabel);
|
||||
|
||||
/*
|
||||
// OPT - see above
|
||||
addByte(PopScopeOp);
|
||||
addByte(PopScopeOp);
|
||||
*/
|
||||
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);
|
||||
ASSERT(mStackTop == 1);
|
||||
addOpSetDepth(ReturnOp, 0);
|
||||
|
|
|
@ -202,8 +202,9 @@ JSValue Context::interpret(JS2Runtime::ByteCodeModule *bcm, int offset, ScopeCha
|
|||
mScopeChain = new ScopeChain(this, mWorld);
|
||||
mScopeChain->addScope(getGlobalObject());
|
||||
}
|
||||
if (mThis.isObject())
|
||||
mScopeChain->addScope(mThis.object);
|
||||
|
||||
// if (mThis.isObject())
|
||||
// mScopeChain->addScope(mThis.object);
|
||||
// mScopeChain->addScope(mActivationStack.top());
|
||||
|
||||
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
|
||||
// a closure capturing the contents has come along...
|
||||
if (mThis.isObject())
|
||||
mScopeChain->popScope();
|
||||
// if (mThis.isObject())
|
||||
// mScopeChain->popScope();
|
||||
delete[] mStack;
|
||||
delete[] mLocals;
|
||||
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
|
||||
// a closure capturing the contents has come along...
|
||||
if (mThis.isObject())
|
||||
mScopeChain->popScope();
|
||||
// if (mThis.isObject())
|
||||
// mScopeChain->popScope();
|
||||
delete[] mStack;
|
||||
delete[] mLocals;
|
||||
if (scopeChain == NULL)
|
||||
|
@ -401,6 +402,7 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
try {
|
||||
if (mDebugFlag) {
|
||||
FunctionName *fnName;
|
||||
uint32 x = mScopeChain->mScopeStack.size();
|
||||
if (mCurModule->mFunction && (fnName = mCurModule->mFunction->getFunctionName())) {
|
||||
StringFormatter s;
|
||||
PrettyPrinter pp(s);
|
||||
|
@ -409,10 +411,10 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
std::string str(fnStr.length(), char());
|
||||
std::transform(fnStr.begin(), fnStr.end(), str.begin(), narrow);
|
||||
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
|
||||
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);
|
||||
}
|
||||
switch ((ByteCodeOp)(*pc++)) {
|
||||
|
@ -639,8 +641,8 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
mArgumentBase, oldThis,
|
||||
pc, mCurModule));
|
||||
mScopeChain = target->getScopeChain();
|
||||
if (mThis.isObject())
|
||||
mScopeChain->addScope(mThis.object);
|
||||
// if (mThis.isObject())
|
||||
// mScopeChain->addScope(mThis.object);
|
||||
|
||||
if (!target->isChecked()) {
|
||||
JSArrayInstance *args = (JSArrayInstance *)Array_Type->newInstance(this);
|
||||
|
@ -692,7 +694,10 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
}
|
||||
mActivationStack.pop();
|
||||
delete[] mLocals;
|
||||
delete[] mStack;
|
||||
delete[] mStack;
|
||||
|
||||
mScopeChain->popScope();
|
||||
mScopeChain->popScope();
|
||||
|
||||
mCurModule = prev->mModule;
|
||||
pc = prev->mPC;
|
||||
|
@ -721,6 +726,9 @@ JSValue Context::interpret(uint8 *pc, uint8 *endPC)
|
|||
delete[] mLocals;
|
||||
delete[] mStack;
|
||||
|
||||
mScopeChain->popScope();
|
||||
mScopeChain->popScope();
|
||||
|
||||
mCurModule = prev->mModule;
|
||||
pc = prev->mPC;
|
||||
endPC = mCurModule->mCodeBase + mCurModule->mLength;
|
||||
|
@ -2225,8 +2233,19 @@ float64 stringToNumber(const String *string)
|
|||
if (sBegin)
|
||||
if ((sBegin[0] == '0') && ((sBegin[1] & ~0x20) == 'X'))
|
||||
return stringToInteger(sBegin, string->end(), numEnd, 16);
|
||||
else
|
||||
return stringToDouble(sBegin, string->end(), numEnd);
|
||||
else {
|
||||
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
|
||||
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)
|
||||
{
|
||||
PropertyIterator i = findNamespacedProperty(name, names);
|
||||
if ((PROPERTY_ATTR(i) & Property::DontDelete) == 0) {
|
||||
mProperties.erase(i);
|
||||
return true;
|
||||
if (i != mProperties.end()) {
|
||||
if ((PROPERTY_ATTR(i) & Property::DontDelete) == 0) {
|
||||
mProperties.erase(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1962,6 +1964,14 @@ static JSValue Number_Constructor(Context *cx, const JSValue& thisValue, JSValue
|
|||
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*/)
|
||||
{
|
||||
if (!thisValue.isObject() || (thisValue.getType() != Number_Type))
|
||||
|
@ -2387,14 +2397,17 @@ void Context::initBuiltins()
|
|||
|
||||
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(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->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));
|
||||
|
||||
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)
|
||||
{
|
||||
ASSERT(n < mStackMax);
|
||||
ASSERT(n <= mStackMax);
|
||||
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 {
|
||||
public:
|
||||
enum { ReplacementStackSize = 4 };
|
||||
|
|
|
@ -62,7 +62,17 @@ JSValue Array_Constructor(Context *cx, const JSValue& thisValue, JSValue *argv,
|
|||
JSArrayInstance *arrInst = checked_cast<JSArrayInstance *>(thisObj);
|
||||
if (argc > 0) {
|
||||
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 {
|
||||
arrInst->mLength = argc;
|
||||
|
@ -93,7 +103,8 @@ static JSValue Array_toString(Context *cx, const JSValue& thisValue, JSValue * /
|
|||
const String *id = numberToString(i);
|
||||
arrInst->getProperty(cx, *id, NULL);
|
||||
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))
|
||||
s->append(widenCString(","));
|
||||
}
|
||||
|
@ -385,9 +396,154 @@ static JSValue Array_slice(Context *cx, const JSValue& thisValue, JSValue *argv,
|
|||
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)
|
||||
|
|
|
@ -426,6 +426,74 @@ static JSValue Date_makeTime(Context *cx, const JSValue& thisValue, JSValue *arg
|
|||
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! */
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
|
|
@ -67,9 +67,18 @@ JSValue String_Constructor(Context *cx, const JSValue& thisValue, JSValue *argv,
|
|||
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)
|
||||
{
|
||||
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);
|
||||
for (uint32 i = 0; i < argc; i++)
|
||||
*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_TypeCast(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();
|
||||
|
|
|
@ -1683,8 +1683,6 @@ double JS::stringToDouble(const char16 *str, const char16 *strEnd, const char16
|
|||
double value = strToDouble(cstr.get(), estr);
|
||||
ptrdiff_t i = estr - cstr.get();
|
||||
numEnd = i ? str1 + i : str;
|
||||
if ((value == 0.0) && (i == 0))
|
||||
return nan;
|
||||
return value;
|
||||
}
|
||||
|
||||
|
|
|
@ -221,6 +221,10 @@ static bool processArgs(Context *cx, int argc, char **argv, int *result)
|
|||
for (int i = 0; i < argc; i++) {
|
||||
if (argv[i][0] == '-') {
|
||||
switch (argv[i][1]) {
|
||||
default:
|
||||
stdOut << "unrecognized command line switch\n";
|
||||
i = argc;
|
||||
break;
|
||||
case 'f':
|
||||
{
|
||||
try {
|
||||
|
@ -235,7 +239,12 @@ static bool processArgs(Context *cx, int argc, char **argv, int *result)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
if ((argv[i][0] == '/') && (argv[i][1] == '/')) {
|
||||
// skip rest of command line
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return doInteractive;
|
||||
}
|
||||
|
@ -246,13 +255,15 @@ static bool processArgs(Context *cx, int argc, char **argv, int *result)
|
|||
|
||||
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 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 {
|
||||
JSObject *globalObject;
|
||||
Context cx(&globalObject, world, a, Pragma::js2);
|
||||
|
|
Загрузка…
Ссылка в новой задаче