зеркало из https://github.com/mozilla/gecko-dev.git
Added Array class. Moved conversions to MetaData.
This commit is contained in:
Родитель
2751ea016b
Коммит
7965c7bfe2
|
@ -155,6 +155,9 @@ namespace MetaData {
|
|||
for (std::vector<Frame *>::iterator fi = mFrameList.begin(), fend = mFrameList.end(); (fi != fend); fi++) {
|
||||
GCMARKOBJECT(*fi);
|
||||
}
|
||||
for (std::vector<RegExpInstance *>::iterator ri = mRegExpList.begin(), rend = mRegExpList.end(); (ri != rend); ri++) {
|
||||
GCMARKOBJECT(*ri);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -148,12 +148,13 @@ public:
|
|||
// XXX We lose StringAtom here (and is it safe to stash the address of a StringAtom?)
|
||||
// - is there any way of keeping StringAtoms themselves in a bytecodeContainer?
|
||||
|
||||
void addRegExp(RegExpInstance *x, size_t pos) { emitOp(eRegExp, pos); addPointer(x); }
|
||||
void addRegExp(RegExpInstance *x, size_t pos) { emitOp(eRegExp, pos); mRegExpList.push_back(x); addShort(mRegExpList.size() - 1); }
|
||||
|
||||
|
||||
typedef std::vector<uint8> CodeBuffer;
|
||||
|
||||
CodeBuffer mBuffer;
|
||||
std::vector<RegExpInstance *> mRegExpList; // gc tracking
|
||||
std::vector<Multiname *> mMultinameList; // gc tracking
|
||||
std::vector<Frame *> mFrameList; // gc tracking
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ static int readEvalPrint(FILE *in)
|
|||
metadata->ValidateStmtList(parsedStatements);
|
||||
js2val rval = metadata->ExecuteStmtList(RunPhase, parsedStatements);
|
||||
if (!JS2VAL_IS_VOID(rval))
|
||||
stdOut << *metadata->engine->toString(rval) << '\n';
|
||||
stdOut << *metadata->toString(rval) << '\n';
|
||||
}
|
||||
}
|
||||
clear(buffer);
|
||||
|
@ -204,7 +204,7 @@ using namespace MetaData;
|
|||
js2val print(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc)
|
||||
{
|
||||
for (uint32 i = 0; i < argc; i++) {
|
||||
stdOut << *metadata->engine->toString(argv[i]) << '\n';
|
||||
stdOut << *metadata->toString(argv[i]) << '\n';
|
||||
}
|
||||
return JS2VAL_UNDEFINED;
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ js2val print(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 ar
|
|||
js2val load(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 argc)
|
||||
{
|
||||
if (argc)
|
||||
return meta->readEvalFile(*meta->engine->toString(argv[0]));
|
||||
return meta->readEvalFile(*meta->toString(argv[0]));
|
||||
else
|
||||
return JS2VAL_UNDEFINED;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,852 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public
|
||||
* License Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License. You may obtain a copy of
|
||||
* the License at http://www.mozilla.org/NPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS
|
||||
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
||||
* implied. See the License for the specific language governing
|
||||
* rights and limitations under the License.
|
||||
*
|
||||
* The Original Code is the JavaScript 2 Prototype.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Netscape
|
||||
* Communications Corporation. Portions created by Netscape are
|
||||
* Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the
|
||||
* terms of the GNU Public License (the "GPL"), in which case the
|
||||
* provisions of the GPL are applicable instead of those above.
|
||||
* If you wish to allow use of your version of this file only
|
||||
* under the terms of the GPL and not to allow others to use your
|
||||
* version of this file under the NPL, indicate your decision by
|
||||
* deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this
|
||||
* file under either the NPL or the GPL.
|
||||
*/
|
||||
|
||||
#ifdef _WIN32
|
||||
// Turn off warnings about identifiers too long in browser information
|
||||
#pragma warning(disable: 4786)
|
||||
#pragma warning(disable: 4711)
|
||||
#pragma warning(disable: 4710)
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
#include "js2value.h"
|
||||
#include "numerics.h"
|
||||
#include "reader.h"
|
||||
#include "parser.h"
|
||||
#include "regexp.h"
|
||||
#include "js2engine.h"
|
||||
#include "bytecodecontainer.h"
|
||||
#include "js2metadata.h"
|
||||
|
||||
namespace JavaScript {
|
||||
namespace MetaData {
|
||||
|
||||
uint32 getLength(JS2Metadata *meta, JS2Object *obj)
|
||||
{
|
||||
Multiname mn(meta->engine->length_StringAtom, meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
uint32 length = 0;
|
||||
js2val result;
|
||||
if (meta->readDynamicProperty(obj, &mn, &lookup, RunPhase, &result))
|
||||
length = toUInt32(meta->toInteger(result));
|
||||
return length;
|
||||
}
|
||||
|
||||
js2val setLength(JS2Metadata *meta, JS2Object *obj, uint32 length)
|
||||
{
|
||||
Multiname mn(meta->engine->length_StringAtom, meta->publicNamespace);
|
||||
js2val result = meta->engine->allocNumber(length);
|
||||
meta->writeDynamicProperty(obj, &mn, true, result, RunPhase);
|
||||
return result;
|
||||
}
|
||||
|
||||
js2val Array_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
js2val thatValue = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass));
|
||||
ArrayInstance *arrInst = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(thatValue));
|
||||
if (argc > 0) {
|
||||
if (argc == 1) {
|
||||
if (JS2VAL_IS_NUMBER(argv[0])) {
|
||||
uint32 i = (uint32)(meta->toFloat64(argv[0]));
|
||||
if (i == meta->toFloat64(argv[0]))
|
||||
setLength(meta, arrInst, i);
|
||||
else
|
||||
meta->reportError(Exception::rangeError, "Array length too large", meta->engine->errorPos());
|
||||
}
|
||||
else {
|
||||
setLength(meta, arrInst, 1);
|
||||
Multiname mn(meta->toString((int32)0), meta->publicNamespace);
|
||||
meta->writeDynamicProperty(arrInst, &mn, true, argv[0], RunPhase);
|
||||
delete mn.name;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Multiname mn(NULL, meta->publicNamespace);
|
||||
setLength(meta, arrInst, argc);
|
||||
for (uint32 i = 0; i < argc; i++) {
|
||||
mn.name = meta->toString(i);
|
||||
meta->writeDynamicProperty(arrInst, &mn, true, argv[i], RunPhase);
|
||||
delete mn.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return thatValue;
|
||||
}
|
||||
|
||||
static js2val Array_toString(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
if (meta->objectType(thisValue) != meta->arrayClass)
|
||||
meta->reportError(Exception::typeError, "Array.prototype.toString called on a non Array", meta->engine->errorPos());
|
||||
|
||||
ArrayInstance *arrInst = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(thisValue));
|
||||
uint32 length = getLength(meta, arrInst);
|
||||
|
||||
if (length == 0)
|
||||
return STRING_TO_JS2VAL(meta->engine->allocString(meta->engine->Empty_StringAtom));
|
||||
else {
|
||||
Multiname mn(NULL, meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
js2val result;
|
||||
String *s = new String();
|
||||
for (uint32 i = 0; i < length; i++) {
|
||||
mn.name = meta->toString(i);
|
||||
if (meta->readDynamicProperty(arrInst, &mn, &lookup, RunPhase, &result)
|
||||
&& !JS2VAL_IS_UNDEFINED(result))
|
||||
s->append(*meta->toString(result));
|
||||
if (i < (length - 1))
|
||||
s->append(widenCString(","));
|
||||
delete mn.name;
|
||||
}
|
||||
result = meta->engine->allocString(s);
|
||||
delete s;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static js2val Array_toSource(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
if (meta->objectType(thisValue) != meta->arrayClass)
|
||||
meta->reportError(Exception::typeError, "Array.prototype.toString called on a non Array", meta->engine->errorPos());
|
||||
|
||||
ArrayInstance *arrInst = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(thisValue));
|
||||
uint32 length = getLength(meta, arrInst);
|
||||
|
||||
if (length == 0)
|
||||
return meta->engine->allocString("[]");
|
||||
else {
|
||||
Multiname mn(NULL, meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
js2val result;
|
||||
String *s = new String();
|
||||
for (uint32 i = 0; i < length; i++) {
|
||||
mn.name = meta->toString(i);
|
||||
if (meta->readDynamicProperty(arrInst, &mn, &lookup, RunPhase, &result)
|
||||
&& !JS2VAL_IS_UNDEFINED(result))
|
||||
s->append(*meta->toString(result));
|
||||
if (i < (length - 1))
|
||||
s->append(widenCString(","));
|
||||
delete mn.name;
|
||||
}
|
||||
s->append(widenCString("]"));
|
||||
result = meta->engine->allocString(s);
|
||||
delete s;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static js2val Array_push(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue);
|
||||
uint32 length = getLength(meta, thisObj);
|
||||
|
||||
Multiname mn(NULL, meta->publicNamespace);
|
||||
for (uint32 i = 0; i < argc; i++) {
|
||||
mn.name = meta->toString(i);
|
||||
meta->writeDynamicProperty(thisObj, &mn, true, argv[i], RunPhase);
|
||||
delete mn.name;
|
||||
}
|
||||
return setLength(meta, thisObj, length + argc);
|
||||
}
|
||||
|
||||
static js2val Array_pop(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue);
|
||||
uint32 length = getLength(meta, thisObj);
|
||||
|
||||
if (length > 0) {
|
||||
Multiname mn(meta->toString(length - 1), meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
const String *id = meta->toString(length - 1);
|
||||
js2val result = JS2VAL_UNDEFINED;
|
||||
bool deleteResult;
|
||||
meta->readDynamicProperty(thisObj, &mn, &lookup, RunPhase, &result);
|
||||
meta->deleteProperty(thisValue, &mn, &lookup, RunPhase, &deleteResult);
|
||||
setLength(meta, thisObj, length - 1);
|
||||
delete mn.name;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return JS2VAL_UNDEFINED;
|
||||
}
|
||||
|
||||
js2val Array_concat(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
js2val E = thisValue;
|
||||
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass));
|
||||
ArrayInstance *A = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(result));
|
||||
uint32 n = 0;
|
||||
uint32 i = 0;
|
||||
Multiname mn(NULL, meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
|
||||
do {
|
||||
if (meta->objectType(E) != meta->arrayClass) {
|
||||
mn.name = meta->toString(n++);
|
||||
meta->writeDynamicProperty(A, &mn, true, E, RunPhase);
|
||||
delete mn.name;
|
||||
}
|
||||
else {
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *arrObj = JS2VAL_TO_OBJECT(E);
|
||||
uint32 length = getLength(meta, arrObj);
|
||||
for (uint32 k = 0; k < length; k++) {
|
||||
mn.name = meta->toString(k);
|
||||
js2val rval = JS2VAL_UNDEFINED;
|
||||
meta->readDynamicProperty(arrObj, &mn, &lookup, RunPhase, &rval);
|
||||
delete mn.name;
|
||||
mn.name = meta->toString(n++);
|
||||
meta->writeDynamicProperty(A, &mn, true, rval, RunPhase);
|
||||
delete mn.name;
|
||||
}
|
||||
}
|
||||
E = argv[i++];
|
||||
} while (i <= argc);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static js2val Array_join(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue);
|
||||
uint32 length = getLength(meta, thisObj);
|
||||
|
||||
const String *separator;
|
||||
if ((argc == 0) || JS2VAL_IS_UNDEFINED(argv[0]))
|
||||
separator = new String(widenCString(","));
|
||||
else
|
||||
separator = meta->toString(argv[0]);
|
||||
|
||||
String *S = new String();
|
||||
Multiname mn(NULL, meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
|
||||
for (uint32 k = 0; k < length; k++) {
|
||||
js2val result = JS2VAL_UNDEFINED;
|
||||
mn.name = meta->toString(k);
|
||||
meta->readDynamicProperty(thisObj, &mn, &lookup, RunPhase, &result);
|
||||
if (!JS2VAL_IS_UNDEFINED(result) && !JS2VAL_IS_NULL(result))
|
||||
*S += *meta->toString(result);
|
||||
|
||||
if (k < (length - 1))
|
||||
*S += *separator;
|
||||
delete mn.name;
|
||||
}
|
||||
|
||||
return meta->engine->allocString(S);
|
||||
}
|
||||
|
||||
static js2val Array_reverse(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue);
|
||||
uint32 length = getLength(meta, thisObj);
|
||||
|
||||
Multiname mn1(NULL, meta->publicNamespace);
|
||||
Multiname mn2(NULL, meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
|
||||
uint32 halfway = length / 2;
|
||||
|
||||
for (uint32 k = 0; k < halfway; k++) {
|
||||
bool deleteResult;
|
||||
js2val result1 = JS2VAL_UNDEFINED;
|
||||
js2val result2 = JS2VAL_UNDEFINED;
|
||||
mn1.name = meta->toString(k);
|
||||
mn2.name = meta->toString(length - k - 1);
|
||||
|
||||
if (meta->hasOwnProperty(thisObj, mn1.name)) {
|
||||
if (meta->hasOwnProperty(thisObj, mn2.name)) {
|
||||
meta->readDynamicProperty(thisObj, &mn1, &lookup, RunPhase, &result1);
|
||||
meta->readDynamicProperty(thisObj, &mn2, &lookup, RunPhase, &result2);
|
||||
meta->writeDynamicProperty(thisObj, &mn1, true, result2, RunPhase);
|
||||
meta->writeDynamicProperty(thisObj, &mn2, true, result1, RunPhase);
|
||||
}
|
||||
else {
|
||||
meta->readDynamicProperty(thisObj, &mn1, &lookup, RunPhase, &result1);
|
||||
meta->writeDynamicProperty(thisObj, &mn2, true, result1, RunPhase);
|
||||
meta->deleteProperty(thisValue, &mn1, &lookup, RunPhase, &deleteResult);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (meta->hasOwnProperty(thisObj, mn2.name)) {
|
||||
meta->readDynamicProperty(thisObj, &mn2, &lookup, RunPhase, &result2);
|
||||
meta->writeDynamicProperty(thisObj, &mn1, true, result2, RunPhase);
|
||||
meta->deleteProperty(thisValue, &mn2, &lookup, RunPhase, &deleteResult);
|
||||
}
|
||||
else {
|
||||
meta->deleteProperty(thisValue, &mn1, &lookup, RunPhase, &deleteResult);
|
||||
meta->deleteProperty(thisValue, &mn2, &lookup, RunPhase, &deleteResult);
|
||||
}
|
||||
}
|
||||
delete mn1.name;
|
||||
delete mn2.name;
|
||||
}
|
||||
|
||||
return thisValue;
|
||||
}
|
||||
|
||||
static js2val Array_shift(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue);
|
||||
uint32 length = getLength(meta, thisObj);
|
||||
|
||||
if (length == 0) {
|
||||
setLength(meta, thisObj, 0);
|
||||
return JS2VAL_UNDEFINED;
|
||||
}
|
||||
|
||||
Multiname mn1(NULL, meta->publicNamespace);
|
||||
Multiname mn2(NULL, meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
js2val result;
|
||||
bool deleteResult;
|
||||
mn1.name = meta->toString((int32)0);
|
||||
meta->readDynamicProperty(thisObj, &mn1, &lookup, RunPhase, &result);
|
||||
delete mn1.name;
|
||||
|
||||
for (uint32 k = 1; k < length; k++) {
|
||||
mn1.name = meta->toString(k);
|
||||
mn2.name = meta->toString(k - 1);
|
||||
|
||||
if (meta->hasOwnProperty(thisObj, mn1.name)) {
|
||||
meta->readDynamicProperty(thisObj, &mn1, &lookup, RunPhase, &result);
|
||||
meta->writeDynamicProperty(thisObj, &mn2, true, result, RunPhase);
|
||||
}
|
||||
else
|
||||
meta->deleteProperty(thisValue, &mn2, &lookup, RunPhase, &deleteResult);
|
||||
delete mn1.name;
|
||||
delete mn2.name;
|
||||
}
|
||||
|
||||
mn1.name = meta->toString(length - 1);
|
||||
meta->deleteProperty(thisValue, &mn2, &lookup, RunPhase, &deleteResult);
|
||||
delete mn1.name;
|
||||
setLength(meta, thisObj, length - 1);
|
||||
return result;
|
||||
}
|
||||
|
||||
static js2val Array_slice(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue);
|
||||
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass));
|
||||
ArrayInstance *A = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(result));
|
||||
|
||||
uint32 length = getLength(meta, thisObj);
|
||||
|
||||
uint32 start, end;
|
||||
if (argc < 1)
|
||||
start = 0;
|
||||
else {
|
||||
int32 arg0 = meta->toInteger(argv[0]);
|
||||
if (arg0 < 0) {
|
||||
arg0 += length;
|
||||
if (arg0 < 0)
|
||||
start = 0;
|
||||
else
|
||||
start = toUInt32(arg0);
|
||||
}
|
||||
else {
|
||||
if (toUInt32(arg0) >= length) // cast ok since > 0
|
||||
start = length;
|
||||
else
|
||||
start = toUInt32(arg0);
|
||||
}
|
||||
}
|
||||
|
||||
if (argc < 2)
|
||||
end = length;
|
||||
else {
|
||||
int32 arg1 = meta->toInteger(argv[1]);
|
||||
if (arg1 < 0) {
|
||||
arg1 += length;
|
||||
if (arg1 < 0)
|
||||
end = 0;
|
||||
else
|
||||
end = toUInt32(arg1);
|
||||
}
|
||||
else {
|
||||
if (toUInt32(arg1) >= length)
|
||||
end = length;
|
||||
else
|
||||
end = toUInt32(arg1);
|
||||
}
|
||||
}
|
||||
|
||||
Multiname mn1(NULL, meta->publicNamespace);
|
||||
Multiname mn2(NULL, meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
uint32 n = 0;
|
||||
while (start < end) {
|
||||
mn1.name = meta->toString(start);
|
||||
if (meta->hasOwnProperty(thisObj, mn1.name)) {
|
||||
js2val rval;
|
||||
mn2.name = meta->toString(n);
|
||||
meta->readDynamicProperty(thisObj, &mn1, &lookup, RunPhase, &rval);
|
||||
meta->writeDynamicProperty(A, &mn2, true, rval, RunPhase);
|
||||
delete mn2.name;
|
||||
}
|
||||
n++;
|
||||
start++;
|
||||
delete mn1.name;
|
||||
}
|
||||
setLength(meta, A, n);
|
||||
return result;
|
||||
}
|
||||
|
||||
typedef struct CompareArgs {
|
||||
JS2Metadata *meta;
|
||||
JS2Object *target;
|
||||
} CompareArgs;
|
||||
|
||||
typedef struct QSortArgs {
|
||||
js2val *vec;
|
||||
js2val *pivot;
|
||||
CompareArgs *arg;
|
||||
} QSortArgs;
|
||||
|
||||
static int32 sort_compare(js2val *a, js2val *b, CompareArgs *arg);
|
||||
|
||||
static void
|
||||
js_qsort_r(QSortArgs *qa, int lo, int hi)
|
||||
{
|
||||
js2val *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(js2val *vec, size_t nel, CompareArgs *arg)
|
||||
{
|
||||
js2val *pivot;
|
||||
QSortArgs qa;
|
||||
|
||||
pivot = (js2val *)STD::malloc(nel);
|
||||
qa.vec = vec;
|
||||
qa.pivot = pivot;
|
||||
qa.arg = arg;
|
||||
js_qsort_r(&qa, 0, (int)(nel - 1));
|
||||
STD::free(pivot);
|
||||
}
|
||||
|
||||
static int32 sort_compare(js2val *a, js2val *b, CompareArgs *arg)
|
||||
{
|
||||
js2val av = *(const js2val *)a;
|
||||
js2val bv = *(const js2val *)b;
|
||||
CompareArgs *ca = (CompareArgs *) arg;
|
||||
JS2Metadata *meta = ca->meta;
|
||||
int32 result;
|
||||
|
||||
if (ca->target == NULL) {
|
||||
if (JS2VAL_IS_UNDEFINED(av) || JS2VAL_IS_UNDEFINED(bv)) {
|
||||
/* Put undefined properties at the end. */
|
||||
result = (JS2VAL_IS_UNDEFINED(av)) ? 1 : -1;
|
||||
}
|
||||
else {
|
||||
const String *astr = meta->toString(av);
|
||||
const String *bstr = meta->toString(bv);
|
||||
result = astr->compare(*bstr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
js2val argv[2];
|
||||
argv[0] = av;
|
||||
argv[1] = bv;
|
||||
js2val v = JS2VAL_UNDEFINED;// XXX = cx->invokeFunction(ca->target, kNullValue, argv, 2);
|
||||
float64 f = meta->toFloat64(v);
|
||||
if (JSDOUBLE_IS_NaN(f) || (f == 0))
|
||||
result = 0;
|
||||
else
|
||||
if (f > 0)
|
||||
result = 1;
|
||||
else
|
||||
result = -1;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static js2val Array_sort(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
CompareArgs ca;
|
||||
ca.meta = meta;
|
||||
ca.target = NULL;
|
||||
|
||||
if (argc > 0) {
|
||||
if (!JS2VAL_IS_UNDEFINED(argv[0])) {
|
||||
if (meta->objectType(argv[0]) != meta->functionClass)
|
||||
meta->reportError(Exception::typeError, "sort needs a compare function", meta->engine->errorPos());
|
||||
ca.target = JS2VAL_TO_OBJECT(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue);
|
||||
uint32 length = getLength(meta, thisObj);
|
||||
|
||||
if (length > 0) {
|
||||
uint32 i;
|
||||
js2val *vec = new js2val[length];
|
||||
|
||||
Multiname mn(NULL, meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
for (i = 0; i < length; i++) {
|
||||
mn.name = meta->toString(i);
|
||||
meta->readDynamicProperty(thisObj, &mn, &lookup, RunPhase, &vec[i]);
|
||||
delete mn.name;
|
||||
}
|
||||
|
||||
js_qsort(vec, length, &ca);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
mn.name = meta->toString(i);
|
||||
meta->writeDynamicProperty(thisObj, &mn, true, vec[i], RunPhase);
|
||||
delete mn.name;
|
||||
}
|
||||
delete[] mn.name;
|
||||
}
|
||||
return thisValue;
|
||||
}
|
||||
|
||||
static js2val Array_splice(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc > 1) {
|
||||
uint32 k;
|
||||
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue);
|
||||
uint32 length = getLength(meta, thisObj);
|
||||
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass));
|
||||
ArrayInstance *A = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(result));
|
||||
|
||||
int32 arg0 = meta->toInteger(argv[0]);
|
||||
uint32 start;
|
||||
if (arg0 < 0) {
|
||||
arg0 += length;
|
||||
if (arg0 < 0)
|
||||
start = 0;
|
||||
else
|
||||
start = toUInt32(arg0);
|
||||
}
|
||||
else {
|
||||
if (toUInt32(arg0) >= length)
|
||||
start = length;
|
||||
else
|
||||
start = toUInt32(arg0);
|
||||
}
|
||||
|
||||
uint32 deleteCount;
|
||||
int32 arg1 = meta->toInteger(argv[1]);
|
||||
if (arg1 < 0)
|
||||
deleteCount = 0;
|
||||
else
|
||||
if (toUInt32(arg1) >= (length - start))
|
||||
deleteCount = length - start;
|
||||
else
|
||||
deleteCount = toUInt32(arg1);
|
||||
|
||||
Multiname mn1(NULL, meta->publicNamespace);
|
||||
Multiname mn2(NULL, meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
for (k = 0; k < deleteCount; k++) {
|
||||
mn1.name = meta->toString(start + k);
|
||||
if (meta->hasOwnProperty(thisObj, mn1.name)) {
|
||||
js2val rval;
|
||||
mn2.name = meta->toString(k);
|
||||
meta->readDynamicProperty(thisObj, &mn1, &lookup, RunPhase, &rval);
|
||||
meta->writeDynamicProperty(A, &mn2, true, rval, RunPhase);
|
||||
delete mn2.name;
|
||||
}
|
||||
delete mn1.name;
|
||||
}
|
||||
setLength(meta, A, deleteCount);
|
||||
|
||||
uint32 newItemCount = argc - 2;
|
||||
if (newItemCount < deleteCount) {
|
||||
bool deleteResult;
|
||||
for (k = start; k < (length - deleteCount); k++) {
|
||||
mn1.name = meta->toString(k + deleteCount);
|
||||
mn2.name = meta->toString(k + newItemCount);
|
||||
if (meta->hasOwnProperty(thisObj, mn1.name)) {
|
||||
js2val rval;
|
||||
meta->readDynamicProperty(thisObj, &mn1, &lookup, RunPhase, &rval);
|
||||
meta->writeDynamicProperty(A, &mn2, true, rval, RunPhase);
|
||||
}
|
||||
else
|
||||
meta->deleteProperty(thisValue, &mn2, &lookup, RunPhase, &deleteResult);
|
||||
delete mn1.name;
|
||||
delete mn2.name;
|
||||
}
|
||||
for (k = length; k > (length - deleteCount + newItemCount); k--) {
|
||||
mn1.name = meta->toString(k - 1);
|
||||
meta->deleteProperty(thisValue, &mn1, &lookup, RunPhase, &deleteResult);
|
||||
delete mn1.name;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (newItemCount > deleteCount) {
|
||||
for (k = length - deleteCount; k > start; k--) {
|
||||
bool deleteResult;
|
||||
mn1.name = meta->toString(k + deleteCount - 1);
|
||||
mn1.name = meta->toString(k + newItemCount - 1);
|
||||
if (meta->hasOwnProperty(thisObj, mn1.name)) {
|
||||
js2val rval;
|
||||
meta->readDynamicProperty(thisObj, &mn1, &lookup, RunPhase, &rval);
|
||||
meta->writeDynamicProperty(A, &mn2, true, rval, RunPhase);
|
||||
}
|
||||
else
|
||||
meta->deleteProperty(thisValue, &mn2, &lookup, RunPhase, &deleteResult);
|
||||
delete mn1.name;
|
||||
delete mn2.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
k = start;
|
||||
for (uint32 i = 2; i < argc; i++) {
|
||||
mn1.name = meta->toString(k++);
|
||||
meta->writeDynamicProperty(A, &mn2, true, argv[i], RunPhase);
|
||||
delete mn1.name;
|
||||
}
|
||||
setLength(meta, thisObj, (length - deleteCount + newItemCount));
|
||||
|
||||
return result;
|
||||
}
|
||||
return JS2VAL_UNDEFINED;
|
||||
}
|
||||
|
||||
static js2val Array_unshift(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
ASSERT(JS2VAL_IS_OBJECT(thisValue));
|
||||
JS2Object *thisObj = JS2VAL_TO_OBJECT(thisValue);
|
||||
|
||||
uint32 length = getLength(meta, thisObj);
|
||||
uint32 k;
|
||||
|
||||
Multiname mn1(NULL, meta->publicNamespace);
|
||||
Multiname mn2(NULL, meta->publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
|
||||
for (k = length; k > 0; k--) {
|
||||
bool deleteResult;
|
||||
mn1.name = meta->toString(k - 1);
|
||||
mn2.name = meta->toString(k + argc - 1);
|
||||
if (meta->hasOwnProperty(thisObj, mn1.name)) {
|
||||
js2val rval;
|
||||
meta->readDynamicProperty(thisObj, &mn1, &lookup, RunPhase, &rval);
|
||||
meta->writeDynamicProperty(thisObj, &mn2, true, rval, RunPhase);
|
||||
}
|
||||
else
|
||||
meta->deleteProperty(thisValue, &mn2, &lookup, RunPhase, &deleteResult);
|
||||
delete mn1.name;
|
||||
delete mn2.name;
|
||||
}
|
||||
|
||||
for (k = 0; k < argc; k++) {
|
||||
mn1.name = meta->toString(k);
|
||||
meta->writeDynamicProperty(thisObj, &mn1, true, argv[k], RunPhase);
|
||||
delete mn1.name;
|
||||
}
|
||||
setLength(meta, thisObj, (length + argc));
|
||||
|
||||
return thisValue;
|
||||
}
|
||||
|
||||
#if 0
|
||||
// An index has to pass the test that :
|
||||
// meta->toString(ToUint32(meta->toString(index))) == meta->toString(index)
|
||||
//
|
||||
// the 'meta->toString(index)' operation is the default behaviour of '[]'
|
||||
//
|
||||
// isArrayIndex() is called when we know that index is a Number
|
||||
//
|
||||
static bool isArrayIndex(JS2Metadata *meta, js2val index, uint32 &intIndex)
|
||||
{
|
||||
ASSERT(JS2VAL_IS_NUMBER(index));
|
||||
js2val v = JSValue::toUInt32(cx, index);
|
||||
if ((JSValue::f64(v) == JSValue::f64(index)) && (JSValue::f64(v) < two32minus1)) {
|
||||
intIndex = (uint32)JSValue::f64(v);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
js2val Array_GetElement(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
// the 'this' value is the first argument, then the index
|
||||
if (argc != 2)
|
||||
cx->reportError(Exception::referenceError, "[] only supports single dimension");
|
||||
|
||||
JSArrayInstance *arrInst = checked_cast<JSArrayInstance *>(JSValue::instance(thisValue));
|
||||
|
||||
js2val index = argv[1];
|
||||
const String *name = JSValue::string(JSValue::meta->toString(cx, index));
|
||||
|
||||
arrInst->getProperty(cx, *name, NULL);
|
||||
return cx->popValue();
|
||||
}
|
||||
|
||||
js2val Array_SetElement(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
// the 'this' value is the first argument, then the rValue, and finally the index
|
||||
if (argc != 3)
|
||||
cx->reportError(Exception::referenceError, "[]= only supports single dimension");
|
||||
|
||||
JSArrayInstance *arrInst = checked_cast<JSArrayInstance *>(JSValue::instance(thisValue));
|
||||
|
||||
js2val index = argv[2];
|
||||
const String *name = JSValue::string(JSValue::meta->toString(cx, index));
|
||||
|
||||
if (JS2VAL_IS_NUMBER(index)) {
|
||||
uint32 intIndex;
|
||||
if (isArrayIndex(cx, index, intIndex)) {
|
||||
PropertyIterator it = arrInst->findNamespacedProperty(*name, NULL);
|
||||
if (it == arrInst->mProperties.end())
|
||||
arrInst->insertNewProperty(*name, NULL, Property::Enumerable, Object_Type, argv[1]);
|
||||
else {
|
||||
Property *prop = PROPERTY(it);
|
||||
ASSERT(prop->mFlag == ValuePointer);
|
||||
prop->mData.vp = argv[1];
|
||||
}
|
||||
if (intIndex >= arrInst->mLength)
|
||||
arrInst->mLength = intIndex + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
arrInst->setProperty(cx, *name, NULL, argv[1]);
|
||||
}
|
||||
return argv[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void initArrayObject(JS2Metadata *meta)
|
||||
{
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
uint16 length;
|
||||
NativeCode *code;
|
||||
} PrototypeFunction;
|
||||
|
||||
PrototypeFunction arrayProtos[] =
|
||||
{
|
||||
{ "toString", 0, Array_toString },
|
||||
{ "toLocaleString", 0, Array_toString }, // XXX
|
||||
{ "toSource", 0, Array_toSource },
|
||||
{ "push", 1, Array_push },
|
||||
{ "pop", 0, Array_pop },
|
||||
{ "concat", 1, Array_concat },
|
||||
{ "join", 1, Array_join },
|
||||
{ "reverse", 0, Array_reverse },
|
||||
{ "shift", 0, Array_shift },
|
||||
{ "slice", 2, Array_slice },
|
||||
{ "sort", 1, Array_sort },
|
||||
{ "splice", 2, Array_splice },
|
||||
{ "unshift", 1, Array_unshift },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
NamespaceList publicNamespaceList;
|
||||
publicNamespaceList.push_back(meta->publicNamespace);
|
||||
|
||||
meta->arrayClass->construct = Array_Constructor;
|
||||
|
||||
PrototypeFunction *pf = &arrayProtos[0];
|
||||
while (pf->name) {
|
||||
FixedInstance *fInst = new FixedInstance(meta->functionClass);
|
||||
fInst->fWrap = new FunctionWrapper(true, new ParameterFrame(JS2VAL_INACCESSIBLE, true), pf->code);
|
||||
|
||||
InstanceMember *m = new InstanceMethod(fInst);
|
||||
meta->defineInstanceMember(meta->arrayClass, &meta->cxt, &meta->world.identifiers[pf->name], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0);
|
||||
pf++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -298,7 +298,6 @@ static int32 WeekDay(float64 t)
|
|||
static float64 *Date_getProlog(JS2Metadata *meta, const js2val thisValue)
|
||||
{
|
||||
if (meta->objectType(thisValue) != meta->dateClass)
|
||||
//|| ((checked_cast<PrototypeInstance *>(JS2VAL_TO_OBJECT(thisValue))->type != meta->dateClass)) )
|
||||
meta->reportError(Exception::typeError, "You really need a date", meta->engine->errorPos());
|
||||
DateInstance *dateInst = checked_cast<DateInstance *>(JS2VAL_TO_OBJECT(thisValue));
|
||||
return &dateInst->ms;
|
||||
|
@ -388,7 +387,7 @@ static js2val Date_makeTime(JS2Metadata *meta, const js2val thisValue, js2val *a
|
|||
argc = maxargs; /* clamp argc */
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
float64 f = meta->engine->toFloat64(argv[i]);
|
||||
float64 f = meta->toFloat64(argv[i]);
|
||||
if (JSDOUBLE_IS_NaN(f)) {
|
||||
*date = nan;
|
||||
return meta->engine->nanValue;
|
||||
|
@ -454,7 +453,7 @@ static js2val Date_makeDate(JS2Metadata *meta, const js2val thisValue, js2val *a
|
|||
argc = maxargs; /* clamp argc */
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
float64 f = meta->engine->toFloat64(argv[i]);
|
||||
float64 f = meta->toFloat64(argv[i]);
|
||||
if (JSDOUBLE_IS_NaN(f)) {
|
||||
*date = nan;
|
||||
return meta->engine->nanValue;
|
||||
|
@ -874,11 +873,11 @@ js2val Date_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv,
|
|||
if (argc == 1) {
|
||||
if (!JS2VAL_IS_STRING(argv[0])) {
|
||||
/* the argument is a millisecond number */
|
||||
float64 d = meta->engine->toFloat64(argv[0]);
|
||||
float64 d = meta->toFloat64(argv[0]);
|
||||
thisInst->ms = TIMECLIP(d);
|
||||
} else {
|
||||
/* the argument is a string; parse it. */
|
||||
const String *str = meta->engine->toString(argv[0]);
|
||||
const String *str = meta->toString(argv[0]);
|
||||
float64 d = date_parseString(*str);
|
||||
thisInst->ms = TIMECLIP(d);
|
||||
}
|
||||
|
@ -891,7 +890,7 @@ js2val Date_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv,
|
|||
|
||||
for (loop = 0; loop < MAXARGS; loop++) {
|
||||
if (loop < argc) {
|
||||
float64 double_arg = meta->engine->toFloat64(argv[loop]);
|
||||
float64 double_arg = meta->toFloat64(argv[loop]);
|
||||
/* if any arg is NaN, make a NaN date object
|
||||
and return */
|
||||
if (!JSDOUBLE_IS_FINITE(double_arg)) {
|
||||
|
@ -924,7 +923,7 @@ js2val Date_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv,
|
|||
|
||||
js2val Date_parse(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 /*argc*/)
|
||||
{
|
||||
const String *str = meta->engine->toString(argv[0]);
|
||||
const String *str = meta->toString(argv[0]);
|
||||
float64 d = date_parseString(*str);
|
||||
d = TIMECLIP(d);
|
||||
return meta->engine->allocNumber(d);
|
||||
|
@ -938,7 +937,7 @@ js2val Date_UTC(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uin
|
|||
|
||||
for (loop = 0; loop < MAXARGS; loop++) {
|
||||
if (loop < argc) {
|
||||
d = meta->engine->toFloat64(argv[loop]);
|
||||
d = meta->toFloat64(argv[loop]);
|
||||
if (!JSDOUBLE_IS_FINITE(d))
|
||||
return meta->engine->allocNumber(d);
|
||||
array[loop] = floor(d);
|
||||
|
@ -1272,7 +1271,7 @@ static js2val Date_getUTCMilliseconds(JS2Metadata *meta, const js2val thisValue,
|
|||
static js2val Date_setTime(JS2Metadata *meta, const js2val thisValue, js2val argv[], uint32 /*argc*/)
|
||||
{
|
||||
float64 *date = Date_getProlog(meta, thisValue);
|
||||
float64 result = meta->engine->toFloat64(argv[0]);
|
||||
float64 result = meta->toFloat64(argv[0]);
|
||||
*date = TIMECLIP(result);
|
||||
return meta->engine->allocNumber(*date);
|
||||
}
|
||||
|
@ -1286,7 +1285,7 @@ static js2val Date_setYear(JS2Metadata *meta, const js2val thisValue, js2val arg
|
|||
|
||||
float64 *date = Date_getProlog(meta, thisValue);
|
||||
result = *date;
|
||||
year = meta->engine->toFloat64(argv[0]);
|
||||
year = meta->toFloat64(argv[0]);
|
||||
if (!JSDOUBLE_IS_FINITE(year)) {
|
||||
*date = nan;
|
||||
return meta->engine->allocNumber(*date);
|
||||
|
|
|
@ -188,84 +188,6 @@ namespace MetaData {
|
|||
return new JavaScript::String(widenCString(chrp));
|
||||
}
|
||||
|
||||
// x is not a String
|
||||
const String *JS2Engine::convertValueToString(js2val x)
|
||||
{
|
||||
if (JS2VAL_IS_UNDEFINED(x))
|
||||
return undefined_StringAtom;
|
||||
if (JS2VAL_IS_NULL(x))
|
||||
return null_StringAtom;
|
||||
if (JS2VAL_IS_BOOLEAN(x))
|
||||
return (JS2VAL_TO_BOOLEAN(x)) ? true_StringAtom : false_StringAtom;
|
||||
if (JS2VAL_IS_INT(x))
|
||||
return numberToString(JS2VAL_TO_INT(x));
|
||||
if (JS2VAL_IS_LONG(x)) {
|
||||
float64 d;
|
||||
JSLL_L2D(d, *JS2VAL_TO_LONG(x));
|
||||
return numberToString(&d);
|
||||
}
|
||||
if (JS2VAL_IS_ULONG(x)) {
|
||||
float64 d;
|
||||
JSLL_UL2D(d, *JS2VAL_TO_ULONG(x));
|
||||
return numberToString(&d);
|
||||
}
|
||||
if (JS2VAL_IS_FLOAT(x)) {
|
||||
float64 d = *JS2VAL_TO_FLOAT(x);
|
||||
return numberToString(&d);
|
||||
}
|
||||
if (JS2VAL_IS_DOUBLE(x))
|
||||
return numberToString(JS2VAL_TO_DOUBLE(x));
|
||||
return toString(toPrimitive(x));
|
||||
}
|
||||
|
||||
// x is not a primitive (it is an object and not null)
|
||||
js2val JS2Engine::convertValueToPrimitive(js2val x)
|
||||
{
|
||||
// return [[DefaultValue]] --> get property 'toString' and invoke it,
|
||||
// if not available or result is not primitive then try property 'valueOf'
|
||||
// if that's not available or returns a non primitive, throw a TypeError
|
||||
|
||||
return STRING_TO_JS2VAL(object_StringAtom);
|
||||
|
||||
ASSERT(false);
|
||||
return JS2VAL_VOID;
|
||||
}
|
||||
|
||||
// x is not a number
|
||||
float64 JS2Engine::convertValueToDouble(js2val x)
|
||||
{
|
||||
if (JS2VAL_IS_UNDEFINED(x))
|
||||
return nan;
|
||||
if (JS2VAL_IS_NULL(x))
|
||||
return 0;
|
||||
if (JS2VAL_IS_BOOLEAN(x))
|
||||
return (JS2VAL_TO_BOOLEAN(x)) ? 1.0 : 0.0;
|
||||
if (JS2VAL_IS_STRING(x)) {
|
||||
String *str = JS2VAL_TO_STRING(x);
|
||||
char16 *numEnd;
|
||||
return stringToDouble(str->data(), str->data() + str->length(), numEnd);
|
||||
}
|
||||
return toFloat64(toPrimitive(x));
|
||||
}
|
||||
|
||||
// x is not a number, convert it to one
|
||||
js2val JS2Engine::convertValueToGeneralNumber(js2val x)
|
||||
{
|
||||
// XXX Assuming convert to float64, rather than long/ulong
|
||||
return allocNumber(toFloat64(x));
|
||||
}
|
||||
|
||||
// x is not an Object, it needs to be wrapped in one
|
||||
js2val JS2Engine::convertValueToObject(js2val x)
|
||||
{
|
||||
if (JS2VAL_IS_UNDEFINED(x) || JS2VAL_IS_NULL(x) || JS2VAL_IS_SPECIALREF(x))
|
||||
meta->reportError(Exception::typeError, "Can't convert to Object", errorPos());
|
||||
if (JS2VAL_IS_STRING(x))
|
||||
return String_Constructor(meta, JS2VAL_NULL, &x, 1);
|
||||
// XXX need more
|
||||
return OBJECT_TO_JS2VAL(new PrototypeInstance(meta->objectClass->prototype, meta->objectClass));
|
||||
}
|
||||
|
||||
// x is a Number, validate that it has no fractional component
|
||||
int64 JS2Engine::checkInteger(js2val x)
|
||||
{
|
||||
|
@ -301,83 +223,6 @@ namespace MetaData {
|
|||
return i;
|
||||
}
|
||||
|
||||
// x is any js2val
|
||||
float64 JS2Engine::toFloat64(js2val x)
|
||||
{
|
||||
if (JS2VAL_IS_INT(x))
|
||||
return JS2VAL_TO_INT(x);
|
||||
else
|
||||
if (JS2VAL_IS_DOUBLE(x))
|
||||
return *JS2VAL_TO_DOUBLE(x);
|
||||
else
|
||||
if (JS2VAL_IS_LONG(x)) {
|
||||
float64 d;
|
||||
JSLL_L2D(d, *JS2VAL_TO_LONG(x));
|
||||
return d;
|
||||
}
|
||||
else
|
||||
if (JS2VAL_IS_ULONG(x)) {
|
||||
float64 d;
|
||||
JSLL_UL2D(d, *JS2VAL_TO_ULONG(x));
|
||||
return d;
|
||||
}
|
||||
else
|
||||
if (JS2VAL_IS_FLOAT(x))
|
||||
return *JS2VAL_TO_FLOAT(x);
|
||||
else
|
||||
return convertValueToDouble(x);
|
||||
}
|
||||
|
||||
// x is not a bool
|
||||
bool JS2Engine::convertValueToBoolean(js2val x)
|
||||
{
|
||||
if (JS2VAL_IS_UNDEFINED(x))
|
||||
return false;
|
||||
if (JS2VAL_IS_NULL(x))
|
||||
return false;
|
||||
if (JS2VAL_IS_INT(x))
|
||||
return (JS2VAL_TO_INT(x) != 0);
|
||||
if (JS2VAL_IS_LONG(x) || JS2VAL_IS_ULONG(x))
|
||||
return (!JSLL_IS_ZERO(x));
|
||||
if (JS2VAL_IS_FLOAT(x)) {
|
||||
float64 xd = *JS2VAL_TO_FLOAT(x);
|
||||
return ! (JSDOUBLE_IS_POSZERO(xd) || JSDOUBLE_IS_NEGZERO(xd) || JSDOUBLE_IS_NaN(xd));
|
||||
}
|
||||
if (JS2VAL_IS_DOUBLE(x)) {
|
||||
float64 xd = *JS2VAL_TO_DOUBLE(x);
|
||||
return ! (JSDOUBLE_IS_POSZERO(xd) || JSDOUBLE_IS_NEGZERO(xd) || JSDOUBLE_IS_NaN(xd));
|
||||
}
|
||||
if (JS2VAL_IS_STRING(x)) {
|
||||
String *str = JS2VAL_TO_STRING(x);
|
||||
return (str->length() != 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// x is not an int
|
||||
int32 JS2Engine::convertValueToInteger(js2val x)
|
||||
{
|
||||
int32 i;
|
||||
if (JS2VAL_IS_LONG(x)) {
|
||||
JSLL_L2I(i, *JS2VAL_TO_LONG(x));
|
||||
return i;
|
||||
}
|
||||
if (JS2VAL_IS_ULONG(x)) {
|
||||
JSLL_UL2I(i, *JS2VAL_TO_ULONG(x));
|
||||
return i;
|
||||
}
|
||||
if (JS2VAL_IS_FLOAT(x)) {
|
||||
float64 f = *JS2VAL_TO_FLOAT(x);
|
||||
return toInt32(f);
|
||||
}
|
||||
if (JS2VAL_IS_DOUBLE(x)) {
|
||||
float64 d = *JS2VAL_TO_DOUBLE(x);
|
||||
return toInt32(d);
|
||||
}
|
||||
float64 d = convertValueToDouble(x);
|
||||
return toInt32(d);
|
||||
}
|
||||
|
||||
int32 JS2Engine::toInt32(float64 d)
|
||||
{
|
||||
if ((d == 0.0) || !JSDOUBLE_IS_FINITE(d) )
|
||||
|
@ -444,7 +289,8 @@ namespace MetaData {
|
|||
INIT_STRINGATOM(object),
|
||||
Empty_StringAtom(&world.identifiers[""]),
|
||||
Dollar_StringAtom(&world.identifiers["$"]),
|
||||
prototype_StringAtom(&world.identifiers["prototype"])
|
||||
INIT_STRINGATOM(prototype),
|
||||
INIT_STRINGATOM(length)
|
||||
{
|
||||
for (int i = 0; i < 256; i++)
|
||||
float64Table[i] = NULL;
|
||||
|
|
|
@ -156,27 +156,11 @@ public:
|
|||
// Use the pc map in the current bytecode container to get a source offset
|
||||
size_t errorPos();
|
||||
|
||||
int32 toInt32(float64 f);
|
||||
uint32 toUInt32(float64 f);
|
||||
uint16 toUInt16(float64 f);
|
||||
static int32 toInt32(float64 f);
|
||||
static uint32 toUInt32(float64 f);
|
||||
static uint16 toUInt16(float64 f);
|
||||
|
||||
|
||||
const String *convertValueToString(js2val x);
|
||||
js2val convertValueToPrimitive(js2val x);
|
||||
float64 convertValueToDouble(js2val x);
|
||||
bool convertValueToBoolean(js2val x);
|
||||
int32 convertValueToInteger(js2val x);
|
||||
js2val convertValueToGeneralNumber(js2val x);
|
||||
js2val convertValueToObject(js2val x);
|
||||
|
||||
const String *toString(js2val x){ if (JS2VAL_IS_STRING(x)) return JS2VAL_TO_STRING(x); else return convertValueToString(x); }
|
||||
js2val toPrimitive(js2val x) { if (JS2VAL_IS_PRIMITIVE(x)) return x; else return convertValueToPrimitive(x); }
|
||||
float64 toFloat64(js2val x);
|
||||
js2val toGeneralNumber(js2val x){ if (JS2VAL_IS_NUMBER(x)) return x; else return convertValueToGeneralNumber(x); }
|
||||
bool toBoolean(js2val x) { if (JS2VAL_IS_BOOLEAN(x)) return JS2VAL_TO_BOOLEAN(x); else return convertValueToBoolean(x); }
|
||||
int32 toInteger(js2val x) { if (JS2VAL_IS_INT(x)) return JS2VAL_TO_INT(x); else return convertValueToInteger(x); }
|
||||
js2val toObject(js2val x) { if (JS2VAL_IS_OBJECT(x)) return x; else return convertValueToObject(x); }
|
||||
|
||||
js2val assignmentConversion(js2val val, JS2Class *type) { return val; } // XXX s'more code, please
|
||||
|
||||
int64 checkInteger(js2val x);
|
||||
|
@ -236,6 +220,7 @@ public:
|
|||
const String *Empty_StringAtom;
|
||||
const String *Dollar_StringAtom;
|
||||
const String *prototype_StringAtom;
|
||||
const String *length_StringAtom;
|
||||
|
||||
// The activation stack, when it's empty and a return is executed, the
|
||||
// interpreter quits
|
||||
|
|
|
@ -92,73 +92,73 @@ static js2val Math_abs(JS2Metadata *meta, const js2val /*thisValue*/, js2val *ar
|
|||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
else
|
||||
return meta->engine->allocNumber(fd::fabs(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::fabs(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
static js2val Math_acos(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
return meta->engine->allocNumber(fd::acos(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::acos(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
static js2val Math_asin(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
return meta->engine->allocNumber(fd::asin(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::asin(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
static js2val Math_atan(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
return meta->engine->allocNumber(fd::atan(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::atan(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
static js2val Math_atan2(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc <= 1)
|
||||
return meta->engine->nanValue;
|
||||
float64 y = meta->engine->toFloat64(argv[0]);
|
||||
float64 x = meta->engine->toFloat64(argv[1]);
|
||||
float64 y = meta->engine->meta->toFloat64(argv[0]);
|
||||
float64 x = meta->engine->meta->toFloat64(argv[1]);
|
||||
return meta->engine->allocNumber(fd::atan2(y, x));
|
||||
}
|
||||
static js2val Math_ceil(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
return meta->engine->allocNumber(fd::ceil(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::ceil(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
static js2val Math_cos(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
return meta->engine->allocNumber(fd::cos(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::cos(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
static js2val Math_exp(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
return meta->engine->allocNumber(fd::exp(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::exp(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
static js2val Math_floor(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
else
|
||||
return meta->engine->allocNumber(fd::floor(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::floor(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
static js2val Math_log(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
return meta->engine->allocNumber(fd::log(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::log(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
static js2val Math_max(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->negInfValue;
|
||||
float64 result = meta->engine->toFloat64(argv[0]);
|
||||
float64 result = meta->engine->meta->toFloat64(argv[0]);
|
||||
if (JSDOUBLE_IS_NaN(result)) return meta->engine->nanValue;
|
||||
for (uint32 i = 1; i < argc; ++i) {
|
||||
float64 arg = meta->engine->toFloat64(argv[i]);
|
||||
float64 arg = meta->engine->meta->toFloat64(argv[i]);
|
||||
if (JSDOUBLE_IS_NaN(arg)) return meta->engine->nanValue;
|
||||
if (arg > result)
|
||||
result = arg;
|
||||
|
@ -169,10 +169,10 @@ static js2val Math_min(JS2Metadata *meta, const js2val /*thisValue*/, js2val *ar
|
|||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->posInfValue;
|
||||
float64 result = meta->engine->toFloat64(argv[0]);
|
||||
float64 result = meta->engine->meta->toFloat64(argv[0]);
|
||||
if (JSDOUBLE_IS_NaN(result)) return meta->engine->nanValue;
|
||||
for (uint32 i = 1; i < argc; ++i) {
|
||||
float64 arg = meta->engine->toFloat64(argv[i]);
|
||||
float64 arg = meta->engine->meta->toFloat64(argv[i]);
|
||||
if (JSDOUBLE_IS_NaN(arg)) return meta->engine->nanValue;
|
||||
if ((arg < result) || (JSDOUBLE_IS_POSZERO(result) && JSDOUBLE_IS_NEGZERO(arg)))
|
||||
result = arg;
|
||||
|
@ -183,7 +183,7 @@ static js2val Math_pow(JS2Metadata *meta, const js2val /*thisValue*/, js2val *ar
|
|||
{
|
||||
if (argc < 1)
|
||||
return meta->engine->nanValue;
|
||||
return meta->engine->allocNumber(fd::pow(meta->engine->toFloat64(argv[0]), meta->engine->toFloat64(argv[1])));
|
||||
return meta->engine->allocNumber(fd::pow(meta->engine->meta->toFloat64(argv[0]), meta->engine->meta->toFloat64(argv[1])));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -265,26 +265,26 @@ static js2val Math_round(JS2Metadata *meta, const js2val /*thisValue*/, js2val *
|
|||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
float64 x = meta->engine->toFloat64(argv[0]);
|
||||
float64 x = meta->engine->meta->toFloat64(argv[0]);
|
||||
return meta->engine->allocNumber( fd::copysign( fd::floor(x + 0.5), x ) );
|
||||
}
|
||||
static js2val Math_sin(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
return meta->engine->allocNumber(fd::sin(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::sin(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
static js2val Math_sqrt(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
return meta->engine->allocNumber(fd::sqrt(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::sqrt(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
static js2val Math_tan(JS2Metadata *meta, const js2val /*thisValue*/, js2val *argv, uint32 argc)
|
||||
{
|
||||
if (argc == 0)
|
||||
return meta->engine->nanValue;
|
||||
return meta->engine->allocNumber(fd::tan(meta->engine->toFloat64(argv[0])));
|
||||
return meta->engine->allocNumber(fd::tan(meta->engine->meta->toFloat64(argv[0])));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include "world.h"
|
||||
#include "utilities.h"
|
||||
#include "js2value.h"
|
||||
#include "jslong.h"
|
||||
#include "numerics.h"
|
||||
#include "reader.h"
|
||||
#include "parser.h"
|
||||
|
@ -985,7 +986,7 @@ namespace MetaData {
|
|||
VariableStmtNode *vs = checked_cast<VariableStmtNode *>(p);
|
||||
VariableBinding *vb = vs->bindings;
|
||||
while (vb) {
|
||||
if (vb->member) {
|
||||
if (vb->member) { // static or instance variable
|
||||
if (vb->member->kind == Member::Variable) {
|
||||
Variable *v = checked_cast<Variable *>(vb->member);
|
||||
JS2Class *type = getVariableType(v, CompilePhase, p->pos);
|
||||
|
@ -2497,53 +2498,6 @@ doUnary:
|
|||
return STRING_TO_JS2VAL(meta->engine->object_StringAtom);
|
||||
}
|
||||
|
||||
js2val RegExp_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
// XXX Change constructors to take js2val pointer for the result (which would be an already
|
||||
// rooted pointer).
|
||||
RegExpInstance *thisInst = new RegExpInstance(meta->regexpClass);
|
||||
JS2Object::RootIterator ri = JS2Object::addRoot(&thisInst);
|
||||
js2val thatValue = OBJECT_TO_JS2VAL(thisInst);
|
||||
REuint32 flags = 0;
|
||||
|
||||
const String *regexpStr = meta->engine->Empty_StringAtom;
|
||||
const String *flagStr = meta->engine->Empty_StringAtom;
|
||||
if (argc > 0) {
|
||||
if (meta->objectType(argv[0]) == meta->regexpClass) {
|
||||
if ((argc == 1) || JS2VAL_IS_UNDEFINED(argv[1])) {
|
||||
RegExpInstance *otherInst = checked_cast<RegExpInstance *>(JS2VAL_TO_OBJECT(argv[0]));
|
||||
js2val src = otherInst->getSource(meta);
|
||||
ASSERT(JS2VAL_IS_STRING(src));
|
||||
regexpStr = JS2VAL_TO_STRING(src);
|
||||
flags = otherInst->mRegExp->flags;
|
||||
}
|
||||
else
|
||||
meta->reportError(Exception::typeError, "Illegal RegExp constructor args", meta->engine->errorPos());
|
||||
}
|
||||
else
|
||||
regexpStr = meta->engine->toString(argv[0]);
|
||||
if ((argc > 1) && !JS2VAL_IS_UNDEFINED(argv[1])) {
|
||||
flagStr = meta->engine->toString(argv[1]);
|
||||
if (parseFlags(flagStr->begin(), (int32)flagStr->length(), &flags) != RE_NO_ERROR)
|
||||
meta->reportError(Exception::syntaxError, "Failed to parse RegExp : '{0}'", meta->engine->errorPos(), *regexpStr + "/" + *flagStr); // XXX error message?
|
||||
}
|
||||
}
|
||||
REState *pState = REParse(regexpStr->begin(), (int32)regexpStr->length(), flags, RE_VERSION_1);
|
||||
if (pState) {
|
||||
thisInst->mRegExp = pState;
|
||||
// XXX ECMA spec says these are DONTENUM
|
||||
thisInst->setSource(meta, STRING_TO_JS2VAL(regexpStr));
|
||||
thisInst->setGlobal(meta, BOOLEAN_TO_JS2VAL((pState->flags & RE_GLOBAL) == RE_GLOBAL));
|
||||
thisInst->setIgnoreCase(meta, BOOLEAN_TO_JS2VAL((pState->flags & RE_IGNORECASE) == RE_IGNORECASE));
|
||||
thisInst->setLastIndex(meta, INT_TO_JS2VAL(0));
|
||||
thisInst->setMultiline(meta, BOOLEAN_TO_JS2VAL((pState->flags & RE_MULTILINE) == RE_MULTILINE));
|
||||
}
|
||||
else
|
||||
meta->reportError(Exception::syntaxError, "Failed to parse RegExp : '{0}'", meta->engine->errorPos(), "/" + *regexpStr + "/" + *flagStr); // XXX what about the RE parser error message?
|
||||
JS2Object::removeRoot(ri);
|
||||
return thatValue;
|
||||
}
|
||||
|
||||
void JS2Metadata::addGlobalObjectFunction(char *name, NativeCode *code)
|
||||
{
|
||||
FixedInstance *fInst = new FixedInstance(functionClass);
|
||||
|
@ -2600,6 +2554,7 @@ doUnary:
|
|||
NamespaceList publicNamespaceList;
|
||||
publicNamespaceList.push_back(publicNamespace);
|
||||
Variable *v;
|
||||
InstanceMember *m;
|
||||
|
||||
MAKEBUILTINCLASS(dateClass, objectClass, true, true, true, &world.identifiers["Date"]);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(dateClass), true);
|
||||
|
@ -2611,6 +2566,16 @@ doUnary:
|
|||
v = new Variable(classClass, OBJECT_TO_JS2VAL(regexpClass), true);
|
||||
defineStaticMember(&env, &world.identifiers["RegExp"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
regexpClass->construct = RegExp_Constructor;
|
||||
m = new InstanceVariable(objectClass, false, false, regexpClass->slotCount++);
|
||||
defineInstanceMember(regexpClass, &cxt, &world.identifiers["source"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0);
|
||||
m = new InstanceVariable(objectClass, false, false, regexpClass->slotCount++);
|
||||
defineInstanceMember(regexpClass, &cxt, &world.identifiers["global"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0);
|
||||
m = new InstanceVariable(objectClass, false, false, regexpClass->slotCount++);
|
||||
defineInstanceMember(regexpClass, &cxt, &world.identifiers["lastIndex"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0);
|
||||
m = new InstanceVariable(objectClass, false, false, regexpClass->slotCount++);
|
||||
defineInstanceMember(regexpClass, &cxt, &world.identifiers["ignoreCase"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0);
|
||||
m = new InstanceVariable(objectClass, false, false, regexpClass->slotCount++);
|
||||
defineInstanceMember(regexpClass, &cxt, &world.identifiers["multiline"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, m, 0);
|
||||
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(stringClass), true);
|
||||
defineStaticMember(&env, &world.identifiers["String"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
|
@ -2622,6 +2587,12 @@ doUnary:
|
|||
defineStaticMember(&env, &world.identifiers["Math"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
initMathObject(this);
|
||||
|
||||
MAKEBUILTINCLASS(arrayClass, objectClass, true, true, true, &world.identifiers["Array"]);
|
||||
v = new Variable(classClass, OBJECT_TO_JS2VAL(arrayClass), true);
|
||||
defineStaticMember(&env, &world.identifiers["Array"], &publicNamespaceList, Attribute::NoOverride, false, ReadWriteAccess, v, 0);
|
||||
// dateClass->prototype = new PrototypeInstance(NULL, dateClass);
|
||||
initArrayObject(this);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -2638,7 +2609,9 @@ doUnary:
|
|||
return numberClass;
|
||||
if (JS2VAL_IS_STRING(objVal)) {
|
||||
if (JS2VAL_TO_STRING(objVal)->length() == 1)
|
||||
return characterClass;
|
||||
return stringClass; // XXX characterClass; Need the connection from class Character to
|
||||
// class String - i.e. access to all the functions in 'String.prototype' -
|
||||
// but (some of) those routines depened on being called on a StringInstance...
|
||||
else
|
||||
return stringClass;
|
||||
}
|
||||
|
@ -2705,6 +2678,31 @@ doUnary:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
// Return true if the object contains the property, but don't
|
||||
// scan the prototype chain. Only scan dynamic properties. XXX
|
||||
bool JS2Metadata::hasOwnProperty(JS2Object *obj, const String *name)
|
||||
{
|
||||
ASSERT(obj);
|
||||
DynamicPropertyMap *dMap = NULL;
|
||||
bool isPrototypeInstance = false;
|
||||
if (obj->kind == DynamicInstanceKind)
|
||||
dMap = &(checked_cast<DynamicInstance *>(obj))->dynamicProperties;
|
||||
else
|
||||
if (obj->kind == GlobalObjectKind)
|
||||
dMap = &(checked_cast<GlobalObject *>(obj))->dynamicProperties;
|
||||
else {
|
||||
ASSERT(obj->kind == PrototypeInstanceKind);
|
||||
isPrototypeInstance = true;
|
||||
dMap = &(checked_cast<PrototypeInstance *>(obj))->dynamicProperties;
|
||||
}
|
||||
for (DynamicPropertyIterator i = dMap->begin(), end = dMap->end(); (i != end); i++) {
|
||||
if (i->first == *name) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Read the property from the container given by the public id in multiname - if that exists
|
||||
//
|
||||
bool JS2Metadata::readDynamicProperty(JS2Object *container, Multiname *multiname, LookupKind *lookupKind, Phase phase, js2val *rval)
|
||||
|
@ -2746,6 +2744,34 @@ doUnary:
|
|||
return false; // 'None'
|
||||
}
|
||||
|
||||
void DynamicInstance::writeProperty(JS2Metadata *meta, const String *name, js2val newValue)
|
||||
{
|
||||
const DynamicPropertyMap::value_type e(*name, newValue);
|
||||
dynamicProperties.insert(e);
|
||||
}
|
||||
|
||||
void ArrayInstance::writeProperty(JS2Metadata *meta, const String *name, js2val newValue)
|
||||
{
|
||||
// An index has to pass the test that :
|
||||
// ToString(ToUint32(ToString(index))) == ToString(index)
|
||||
// (we already have done the 'ToString(index)' part, so require
|
||||
//
|
||||
// ToString(ToUint32(name)) == name
|
||||
//
|
||||
const DynamicPropertyMap::value_type e(*name, newValue);
|
||||
dynamicProperties.insert(e);
|
||||
|
||||
char16 *numEnd;
|
||||
float64 f = stringToDouble(name->data(), name->data() + name->length(), numEnd);
|
||||
uint32 index = JS2Engine::toUInt32(f);
|
||||
|
||||
if (index == f) {
|
||||
uint32 length = getLength(meta, this);
|
||||
if (index >= length)
|
||||
setLength(meta, this, index + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Write a value to a dynamic container - inserting into the map if not already there (if createIfMissing)
|
||||
bool JS2Metadata::writeDynamicProperty(JS2Object *container, Multiname *multiname, bool createIfMissing, js2val newValue, Phase phase)
|
||||
{
|
||||
|
@ -2775,8 +2801,7 @@ doUnary:
|
|||
DynamicInstance *dynInst = checked_cast<DynamicInstance *>(container);
|
||||
InstanceBinding *ib = resolveInstanceMemberName(dynInst->type, multiname, ReadAccess, phase);
|
||||
if (ib == NULL) {
|
||||
const DynamicPropertyMap::value_type e(*name, newValue);
|
||||
dynInst->dynamicProperties.insert(e);
|
||||
dynInst->writeProperty(this, name, newValue);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2858,9 +2883,10 @@ readClassProperty:
|
|||
InstanceBinding *ib = resolveInstanceMemberName(c, multiname, ReadAccess, phase);
|
||||
if ((ib == NULL) && isDynamicInstance)
|
||||
return readDynamicProperty(JS2VAL_TO_OBJECT(containerVal), multiname, lookupKind, phase, rval);
|
||||
else
|
||||
// XXX passing a primitive here ???
|
||||
return readInstanceMember(containerVal, c, (ib) ? &ib->qname : NULL, phase, rval);
|
||||
else {
|
||||
// XXX Spec. would have us passing a primitive here ???
|
||||
return readInstanceMember(toObject(containerVal), c, (ib) ? &ib->qname : NULL, phase, rval);
|
||||
}
|
||||
}
|
||||
JS2Object *container = JS2VAL_TO_OBJECT(containerVal);
|
||||
switch (container->kind) {
|
||||
|
@ -3388,6 +3414,184 @@ deleteClassProperty:
|
|||
|
||||
}
|
||||
|
||||
// x is not a String
|
||||
const String *JS2Metadata::convertValueToString(js2val x)
|
||||
{
|
||||
if (JS2VAL_IS_UNDEFINED(x))
|
||||
return engine->undefined_StringAtom;
|
||||
if (JS2VAL_IS_NULL(x))
|
||||
return engine->null_StringAtom;
|
||||
if (JS2VAL_IS_BOOLEAN(x))
|
||||
return (JS2VAL_TO_BOOLEAN(x)) ? engine->true_StringAtom : engine->false_StringAtom;
|
||||
if (JS2VAL_IS_INT(x))
|
||||
return numberToString(JS2VAL_TO_INT(x));
|
||||
if (JS2VAL_IS_LONG(x)) {
|
||||
float64 d;
|
||||
JSLL_L2D(d, *JS2VAL_TO_LONG(x));
|
||||
return numberToString(&d);
|
||||
}
|
||||
if (JS2VAL_IS_ULONG(x)) {
|
||||
float64 d;
|
||||
JSLL_UL2D(d, *JS2VAL_TO_ULONG(x));
|
||||
return numberToString(&d);
|
||||
}
|
||||
if (JS2VAL_IS_FLOAT(x)) {
|
||||
float64 d = *JS2VAL_TO_FLOAT(x);
|
||||
return numberToString(&d);
|
||||
}
|
||||
if (JS2VAL_IS_DOUBLE(x))
|
||||
return numberToString(JS2VAL_TO_DOUBLE(x));
|
||||
return toString(toPrimitive(x));
|
||||
}
|
||||
|
||||
// x is not a primitive (it is an object and not null)
|
||||
js2val JS2Metadata::convertValueToPrimitive(js2val x)
|
||||
{
|
||||
// return [[DefaultValue]] --> get property 'toString' and invoke it,
|
||||
// if not available or result is not primitive then try property 'valueOf'
|
||||
// if that's not available or returns a non primitive, throw a TypeError
|
||||
|
||||
Multiname mn(&world.identifiers["toString"], publicNamespace);
|
||||
LookupKind lookup(false, NULL);
|
||||
js2val result;
|
||||
if (readProperty(x, &mn, &lookup, RunPhase, &result)) {
|
||||
if (JS2VAL_IS_OBJECT(result)) {
|
||||
JS2Object *obj = JS2VAL_TO_OBJECT(result);
|
||||
if ((obj->kind == FixedInstanceKind) && (objectType(result) == functionClass)) {
|
||||
FunctionWrapper *fWrap = (checked_cast<FixedInstance *>(obj))->fWrap;
|
||||
if (fWrap->code) {
|
||||
result = (fWrap->code)(this, result, NULL, 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (obj->kind == MethodClosureKind) {
|
||||
MethodClosure *mc = checked_cast<MethodClosure *>(obj);
|
||||
FixedInstance *fInst = mc->method->fInst;
|
||||
FunctionWrapper *fWrap = fInst->fWrap;
|
||||
if (fWrap->code) {
|
||||
result = (fWrap->code)(this, mc->thisObject, NULL, 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return STRING_TO_JS2VAL(engine->object_StringAtom);
|
||||
}
|
||||
|
||||
// x is not a number
|
||||
float64 JS2Metadata::convertValueToDouble(js2val x)
|
||||
{
|
||||
if (JS2VAL_IS_UNDEFINED(x))
|
||||
return nan;
|
||||
if (JS2VAL_IS_NULL(x))
|
||||
return 0;
|
||||
if (JS2VAL_IS_BOOLEAN(x))
|
||||
return (JS2VAL_TO_BOOLEAN(x)) ? 1.0 : 0.0;
|
||||
if (JS2VAL_IS_STRING(x)) {
|
||||
String *str = JS2VAL_TO_STRING(x);
|
||||
char16 *numEnd;
|
||||
return stringToDouble(str->data(), str->data() + str->length(), numEnd);
|
||||
}
|
||||
return toFloat64(toPrimitive(x));
|
||||
}
|
||||
|
||||
// x is not a number, convert it to one
|
||||
js2val JS2Metadata::convertValueToGeneralNumber(js2val x)
|
||||
{
|
||||
// XXX Assuming convert to float64, rather than long/ulong
|
||||
return engine->allocNumber(toFloat64(x));
|
||||
}
|
||||
|
||||
// x is not an Object, it needs to be wrapped in one
|
||||
js2val JS2Metadata::convertValueToObject(js2val x)
|
||||
{
|
||||
if (JS2VAL_IS_UNDEFINED(x) || JS2VAL_IS_NULL(x) || JS2VAL_IS_SPECIALREF(x))
|
||||
reportError(Exception::typeError, "Can't convert to Object", engine->errorPos());
|
||||
if (JS2VAL_IS_STRING(x))
|
||||
return String_Constructor(this, JS2VAL_NULL, &x, 1);
|
||||
// XXX need more
|
||||
return OBJECT_TO_JS2VAL(new PrototypeInstance(objectClass->prototype, objectClass));
|
||||
}
|
||||
|
||||
// x is any js2val
|
||||
float64 JS2Metadata::toFloat64(js2val x)
|
||||
{
|
||||
if (JS2VAL_IS_INT(x))
|
||||
return JS2VAL_TO_INT(x);
|
||||
else
|
||||
if (JS2VAL_IS_DOUBLE(x))
|
||||
return *JS2VAL_TO_DOUBLE(x);
|
||||
else
|
||||
if (JS2VAL_IS_LONG(x)) {
|
||||
float64 d;
|
||||
JSLL_L2D(d, *JS2VAL_TO_LONG(x));
|
||||
return d;
|
||||
}
|
||||
else
|
||||
if (JS2VAL_IS_ULONG(x)) {
|
||||
float64 d;
|
||||
JSLL_UL2D(d, *JS2VAL_TO_ULONG(x));
|
||||
return d;
|
||||
}
|
||||
else
|
||||
if (JS2VAL_IS_FLOAT(x))
|
||||
return *JS2VAL_TO_FLOAT(x);
|
||||
else
|
||||
return convertValueToDouble(x);
|
||||
}
|
||||
|
||||
// x is not a bool
|
||||
bool JS2Metadata::convertValueToBoolean(js2val x)
|
||||
{
|
||||
if (JS2VAL_IS_UNDEFINED(x))
|
||||
return false;
|
||||
if (JS2VAL_IS_NULL(x))
|
||||
return false;
|
||||
if (JS2VAL_IS_INT(x))
|
||||
return (JS2VAL_TO_INT(x) != 0);
|
||||
if (JS2VAL_IS_LONG(x) || JS2VAL_IS_ULONG(x))
|
||||
return (!JSLL_IS_ZERO(x));
|
||||
if (JS2VAL_IS_FLOAT(x)) {
|
||||
float64 xd = *JS2VAL_TO_FLOAT(x);
|
||||
return ! (JSDOUBLE_IS_POSZERO(xd) || JSDOUBLE_IS_NEGZERO(xd) || JSDOUBLE_IS_NaN(xd));
|
||||
}
|
||||
if (JS2VAL_IS_DOUBLE(x)) {
|
||||
float64 xd = *JS2VAL_TO_DOUBLE(x);
|
||||
return ! (JSDOUBLE_IS_POSZERO(xd) || JSDOUBLE_IS_NEGZERO(xd) || JSDOUBLE_IS_NaN(xd));
|
||||
}
|
||||
if (JS2VAL_IS_STRING(x)) {
|
||||
String *str = JS2VAL_TO_STRING(x);
|
||||
return (str->length() != 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// x is not an int
|
||||
int32 JS2Metadata::convertValueToInteger(js2val x)
|
||||
{
|
||||
int32 i;
|
||||
if (JS2VAL_IS_LONG(x)) {
|
||||
JSLL_L2I(i, *JS2VAL_TO_LONG(x));
|
||||
return i;
|
||||
}
|
||||
if (JS2VAL_IS_ULONG(x)) {
|
||||
JSLL_UL2I(i, *JS2VAL_TO_ULONG(x));
|
||||
return i;
|
||||
}
|
||||
if (JS2VAL_IS_FLOAT(x)) {
|
||||
float64 f = *JS2VAL_TO_FLOAT(x);
|
||||
return toInt32(f);
|
||||
}
|
||||
if (JS2VAL_IS_DOUBLE(x)) {
|
||||
float64 d = *JS2VAL_TO_DOUBLE(x);
|
||||
return toInt32(d);
|
||||
}
|
||||
float64 d = convertValueToDouble(x);
|
||||
return toInt32(d);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Throw an exception of the specified kind, indicating the position 'pos' and
|
||||
|
|
|
@ -60,10 +60,14 @@ typedef js2val (Constructor)(JS2Metadata *meta, const js2val thisValue, js2val *
|
|||
extern void initDateObject(JS2Metadata *meta);
|
||||
extern void initStringObject(JS2Metadata *meta);
|
||||
extern void initMathObject(JS2Metadata *meta);
|
||||
extern void initArrayObject(JS2Metadata *meta);
|
||||
|
||||
extern js2val String_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);
|
||||
extern js2val RegExp_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);
|
||||
extern js2val RegExp_exec(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc);
|
||||
|
||||
extern uint32 getLength(JS2Metadata *meta, JS2Object *obj);
|
||||
extern js2val setLength(JS2Metadata *meta, JS2Object *obj, uint32 length);
|
||||
|
||||
// OBJECT is the semantic domain of all possible objects and is defined as:
|
||||
// OBJECT = UNDEFINED | NULL | BOOLEAN | FLOAT64 | LONG | ULONG | CHARACTER | STRING | NAMESPACE |
|
||||
|
@ -514,6 +518,8 @@ public:
|
|||
Slot *slots; // A set of slots that hold this instance's fixed property values
|
||||
DynamicPropertyMap dynamicProperties; // A set of this instance's dynamic properties
|
||||
virtual void markChildren();
|
||||
|
||||
virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue);
|
||||
};
|
||||
|
||||
// Prototype instances are represented as PROTOTYPE records. Prototype instances
|
||||
|
@ -545,16 +551,28 @@ public:
|
|||
// that contains the string data
|
||||
class StringInstance : public FixedInstance {
|
||||
public:
|
||||
StringInstance(JS2Class *type) : FixedInstance(type) { }
|
||||
StringInstance(JS2Class *type) : FixedInstance(type), mValue(NULL) { }
|
||||
|
||||
String *mValue;
|
||||
String *mValue; // has been allocated by engine in the GC'able Pond
|
||||
|
||||
virtual void markChildren() { if (mValue) JS2Object::mark(mValue); }
|
||||
};
|
||||
|
||||
// RegExp instances are fixed (not dynamic? XXX) instances created by the RegExp class, they have an extra field
|
||||
// that contains the RegExp object
|
||||
class RegExpInstance : public FixedInstance {
|
||||
// Array instances are dynamic instances created by the Array class, they
|
||||
// maintain the value of the 'length' property when 'indexable' elements
|
||||
// are added.
|
||||
class ArrayInstance : public DynamicInstance {
|
||||
public:
|
||||
RegExpInstance(JS2Class *type) : FixedInstance(type) { }
|
||||
ArrayInstance(JS2Class *type) : DynamicInstance(type) { }
|
||||
|
||||
virtual void writeProperty(JS2Metadata *meta, const String *name, js2val newValue);
|
||||
};
|
||||
|
||||
// RegExp instances are dynamic instances created by the RegExp class, they have an extra field
|
||||
// that contains the RegExp object
|
||||
class RegExpInstance : public DynamicInstance {
|
||||
public:
|
||||
RegExpInstance(JS2Class *type) : DynamicInstance(type) { }
|
||||
|
||||
void setLastIndex(JS2Metadata *meta, js2val a);
|
||||
void setGlobal(JS2Metadata *meta, js2val a);
|
||||
|
@ -922,6 +940,7 @@ public:
|
|||
bool readStaticMember(StaticMember *m, Phase phase, js2val *rval);
|
||||
bool readInstanceMember(js2val containerVal, JS2Class *c, QualifiedName *qname, Phase phase, js2val *rval);
|
||||
JS2Object *lookupDynamicProperty(JS2Object *obj, const String *name);
|
||||
bool JS2Metadata::hasOwnProperty(JS2Object *obj, const String *name);
|
||||
|
||||
bool writeProperty(js2val container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase);
|
||||
bool writeProperty(Frame *container, Multiname *multiname, LookupKind *lookupKind, bool createIfMissing, js2val newValue, Phase phase);
|
||||
|
@ -941,6 +960,21 @@ public:
|
|||
void reportError(Exception::Kind kind, const char *message, size_t pos, const String &name);
|
||||
void reportError(Exception::Kind kind, const char *message, size_t pos, const String *name);
|
||||
|
||||
const String *convertValueToString(js2val x);
|
||||
js2val convertValueToPrimitive(js2val x);
|
||||
float64 convertValueToDouble(js2val x);
|
||||
bool convertValueToBoolean(js2val x);
|
||||
int32 convertValueToInteger(js2val x);
|
||||
js2val convertValueToGeneralNumber(js2val x);
|
||||
js2val convertValueToObject(js2val x);
|
||||
|
||||
const String *toString(js2val x) { if (JS2VAL_IS_STRING(x)) return JS2VAL_TO_STRING(x); else return convertValueToString(x); }
|
||||
js2val toPrimitive(js2val x) { if (JS2VAL_IS_PRIMITIVE(x)) return x; else return convertValueToPrimitive(x); }
|
||||
float64 toFloat64(js2val x);
|
||||
js2val toGeneralNumber(js2val x) { if (JS2VAL_IS_NUMBER(x)) return x; else return convertValueToGeneralNumber(x); }
|
||||
bool toBoolean(js2val x) { if (JS2VAL_IS_BOOLEAN(x)) return JS2VAL_TO_BOOLEAN(x); else return convertValueToBoolean(x); }
|
||||
int32 toInteger(js2val x) { if (JS2VAL_IS_INT(x)) return JS2VAL_TO_INT(x); else return convertValueToInteger(x); }
|
||||
js2val toObject(js2val x) { if (JS2VAL_IS_OBJECT(x)) return x; else return convertValueToObject(x); }
|
||||
|
||||
// Used for interning strings
|
||||
World &world;
|
||||
|
@ -980,6 +1014,7 @@ public:
|
|||
JS2Class *dateClass;
|
||||
JS2Class *regexpClass;
|
||||
JS2Class *mathClass;
|
||||
JS2Class *arrayClass;
|
||||
|
||||
Parser *mParser; // used for error reporting
|
||||
|
||||
|
|
|
@ -130,7 +130,7 @@
|
|||
LookupKind lookup(false, NULL);
|
||||
indexVal = pop();
|
||||
b = pop();
|
||||
const String *indexStr = toString(indexVal);
|
||||
const String *indexStr = meta->toString(indexVal);
|
||||
Multiname mn(&meta->world.identifiers[*indexStr], meta->publicNamespace);
|
||||
if (!meta->readProperty(b, &mn, &lookup, RunPhase, &a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
|
||||
|
@ -144,7 +144,7 @@
|
|||
LookupKind lookup(false, NULL);
|
||||
indexVal = pop();
|
||||
b = pop();
|
||||
const String *indexStr = toString(indexVal);
|
||||
const String *indexStr = meta->toString(indexVal);
|
||||
Multiname mn(&meta->world.identifiers[*indexStr], meta->publicNamespace);
|
||||
bool result;
|
||||
if (!meta->deleteProperty(b, &mn, &lookup, RunPhase, &result))
|
||||
|
@ -163,7 +163,7 @@
|
|||
a = pop();
|
||||
indexVal = pop();
|
||||
b = pop();
|
||||
const String *indexStr = toString(indexVal);
|
||||
const String *indexStr = meta->toString(indexVal);
|
||||
Multiname mn(&meta->world.identifiers[*indexStr], meta->publicNamespace);
|
||||
meta->writeProperty(b, &mn, &lookup, true, a, RunPhase);
|
||||
push(a);
|
||||
|
@ -177,7 +177,7 @@
|
|||
LookupKind lookup(false, NULL);
|
||||
indexVal = pop();
|
||||
b = top();
|
||||
const String *indexStr = toString(indexVal);
|
||||
const String *indexStr = meta->toString(indexVal);
|
||||
Multiname mn(&meta->world.identifiers[*indexStr], meta->publicNamespace);
|
||||
if (!meta->readProperty(b, &mn, &lookup, RunPhase, &a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
|
||||
|
@ -192,7 +192,7 @@
|
|||
LookupKind lookup(false, NULL);
|
||||
indexVal = pop();
|
||||
b = top();
|
||||
const String *indexStr = toString(indexVal);
|
||||
const String *indexStr = meta->toString(indexVal);
|
||||
push(STRING_TO_JS2VAL(indexStr));
|
||||
Multiname mn(&meta->world.identifiers[*indexStr], meta->publicNamespace);
|
||||
if (!meta->readProperty(b, &mn, &lookup, RunPhase, &a))
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
case eMinus:
|
||||
{
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
a = meta->toGeneralNumber(a);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 v = *JS2VAL_TO_LONG(a);
|
||||
if (JSLL_EQ(v, JSLL_MININT))
|
||||
|
@ -55,22 +55,21 @@
|
|||
pushLong(v);
|
||||
}
|
||||
else
|
||||
pushNumber(-toFloat64(a));
|
||||
pushNumber(-meta->toFloat64(a));
|
||||
}
|
||||
break;
|
||||
|
||||
case ePlus:
|
||||
{
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
push(toGeneralNumber(a));
|
||||
push(meta->toGeneralNumber(a));
|
||||
}
|
||||
break;
|
||||
|
||||
case eComplement:
|
||||
{
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
a = meta->toGeneralNumber(a);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 i = *JS2VAL_TO_LONG(a);
|
||||
JSLL_NOT(i, i);
|
||||
|
@ -83,7 +82,7 @@
|
|||
pushULong(i);
|
||||
}
|
||||
else {
|
||||
pushNumber(~toInteger(a));
|
||||
pushNumber(~meta->toInteger(a));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -92,8 +91,8 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
int32 count = toInteger(b);
|
||||
a = meta->toGeneralNumber(a);
|
||||
int32 count = meta->toInteger(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 r;
|
||||
JSLL_SHL(r, *JS2VAL_TO_LONG(a), count & 0x3F);
|
||||
|
@ -106,15 +105,15 @@
|
|||
pushULong(r);
|
||||
}
|
||||
else
|
||||
pushNumber(toInteger(a) << (count & 0x1F));
|
||||
pushNumber(meta->toInteger(a) << (count & 0x1F));
|
||||
}
|
||||
break;
|
||||
case eRightShift:
|
||||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
int32 count = toInteger(b);
|
||||
a = meta->toGeneralNumber(a);
|
||||
int32 count = meta->toInteger(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 r;
|
||||
JSLL_SHR(r, *JS2VAL_TO_LONG(a), count & 0x3F);
|
||||
|
@ -127,15 +126,15 @@
|
|||
pushULong(r);
|
||||
}
|
||||
else
|
||||
pushNumber(toInteger(a) >> (count & 0x1F));
|
||||
pushNumber(meta->toInteger(a) >> (count & 0x1F));
|
||||
}
|
||||
break;
|
||||
case eLogicalRightShift:
|
||||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
int32 count = toInteger(b);
|
||||
a = meta->toGeneralNumber(a);
|
||||
int32 count = meta->toInteger(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 r;
|
||||
JSLL_SHR(r, *JS2VAL_TO_LONG(a), count & 0x3F);
|
||||
|
@ -148,15 +147,15 @@
|
|||
pushULong(r);
|
||||
}
|
||||
else
|
||||
pushNumber(toUInt32(toInteger(a)) >> (count & 0x1F));
|
||||
pushNumber(toUInt32(meta->toInteger(a)) >> (count & 0x1F));
|
||||
}
|
||||
break;
|
||||
case eBitwiseAnd:
|
||||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
b = toGeneralNumber(b);
|
||||
a = meta->toGeneralNumber(a);
|
||||
b = meta->toGeneralNumber(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 x = *JS2VAL_TO_LONG(a);
|
||||
if (JS2VAL_IS_LONG(b)) {
|
||||
|
@ -205,7 +204,7 @@
|
|||
}
|
||||
}
|
||||
else
|
||||
pushNumber(toInteger(a) & toInteger(b));
|
||||
pushNumber(meta->toInteger(a) & meta->toInteger(b));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -213,8 +212,8 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
b = toGeneralNumber(b);
|
||||
a = meta->toGeneralNumber(a);
|
||||
b = meta->toGeneralNumber(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 x = *JS2VAL_TO_LONG(a);
|
||||
if (JS2VAL_IS_LONG(b)) {
|
||||
|
@ -263,7 +262,7 @@
|
|||
}
|
||||
}
|
||||
else
|
||||
pushNumber(toInteger(a) ^ toInteger(b));
|
||||
pushNumber(meta->toInteger(a) ^ meta->toInteger(b));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -271,8 +270,8 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
b = toGeneralNumber(b);
|
||||
a = meta->toGeneralNumber(a);
|
||||
b = meta->toGeneralNumber(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 x = *JS2VAL_TO_LONG(a);
|
||||
if (JS2VAL_IS_LONG(b)) {
|
||||
|
@ -321,7 +320,7 @@
|
|||
}
|
||||
}
|
||||
else
|
||||
pushNumber(toInteger(a) | toInteger(b));
|
||||
pushNumber(meta->toInteger(a) | meta->toInteger(b));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -330,18 +329,18 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toPrimitive(a);
|
||||
b = toPrimitive(b);
|
||||
a = meta->toPrimitive(a);
|
||||
b = meta->toPrimitive(b);
|
||||
if (JS2VAL_IS_STRING(a) || JS2VAL_IS_STRING(b)) {
|
||||
const String *astr = toString(a);
|
||||
const String *bstr = toString(b);
|
||||
const String *astr = meta->toString(a);
|
||||
const String *bstr = meta->toString(b);
|
||||
String *c = allocStringPtr(astr);
|
||||
*c += *bstr;
|
||||
push(STRING_TO_JS2VAL(c));
|
||||
}
|
||||
else {
|
||||
a = toGeneralNumber(a);
|
||||
b = toGeneralNumber(b);
|
||||
a = meta->toGeneralNumber(a);
|
||||
b = meta->toGeneralNumber(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 x = *JS2VAL_TO_LONG(a);
|
||||
if (JS2VAL_IS_LONG(b)) {
|
||||
|
@ -390,8 +389,8 @@
|
|||
}
|
||||
}
|
||||
else {
|
||||
float64 x = toFloat64(a);
|
||||
float64 y = toFloat64(b);
|
||||
float64 x = meta->toFloat64(a);
|
||||
float64 y = meta->toFloat64(b);
|
||||
float64 z = x + y;
|
||||
if (JS2VAL_IS_FLOAT(a) || JS2VAL_IS_FLOAT(b))
|
||||
pushFloat(z);
|
||||
|
@ -407,8 +406,8 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
b = toGeneralNumber(b);
|
||||
a = meta->toGeneralNumber(a);
|
||||
b = meta->toGeneralNumber(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 x = *JS2VAL_TO_LONG(a);
|
||||
if (JS2VAL_IS_LONG(b)) {
|
||||
|
@ -457,8 +456,8 @@
|
|||
}
|
||||
}
|
||||
else {
|
||||
float64 x = toFloat64(a);
|
||||
float64 y = toFloat64(b);
|
||||
float64 x = meta->toFloat64(a);
|
||||
float64 y = meta->toFloat64(b);
|
||||
float64 z = x - y;
|
||||
if (JS2VAL_IS_FLOAT(a) || JS2VAL_IS_FLOAT(b))
|
||||
pushFloat(z);
|
||||
|
@ -473,8 +472,8 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
b = toGeneralNumber(b);
|
||||
a = meta->toGeneralNumber(a);
|
||||
b = meta->toGeneralNumber(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 x = *JS2VAL_TO_LONG(a);
|
||||
if (JS2VAL_IS_LONG(b)) {
|
||||
|
@ -523,8 +522,8 @@
|
|||
}
|
||||
}
|
||||
else {
|
||||
float64 x = toFloat64(a);
|
||||
float64 y = toFloat64(b);
|
||||
float64 x = meta->toFloat64(a);
|
||||
float64 y = meta->toFloat64(b);
|
||||
float64 z = x * y;
|
||||
if (JS2VAL_IS_FLOAT(a) || JS2VAL_IS_FLOAT(b))
|
||||
pushFloat(z);
|
||||
|
@ -539,8 +538,8 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
b = toGeneralNumber(b);
|
||||
a = meta->toGeneralNumber(a);
|
||||
b = meta->toGeneralNumber(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 x = *JS2VAL_TO_LONG(a);
|
||||
if (JS2VAL_IS_LONG(b)) {
|
||||
|
@ -589,8 +588,8 @@
|
|||
}
|
||||
}
|
||||
else {
|
||||
float64 x = toFloat64(a);
|
||||
float64 y = toFloat64(b);
|
||||
float64 x = meta->toFloat64(a);
|
||||
float64 y = meta->toFloat64(b);
|
||||
float64 z = x / y;
|
||||
if (JS2VAL_IS_FLOAT(a) || JS2VAL_IS_FLOAT(b))
|
||||
pushFloat(z);
|
||||
|
@ -605,8 +604,8 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toGeneralNumber(a);
|
||||
b = toGeneralNumber(b);
|
||||
a = meta->toGeneralNumber(a);
|
||||
b = meta->toGeneralNumber(b);
|
||||
if (JS2VAL_IS_LONG(a)) {
|
||||
int64 x = *JS2VAL_TO_LONG(a);
|
||||
if (JS2VAL_IS_LONG(b)) {
|
||||
|
@ -655,8 +654,8 @@
|
|||
}
|
||||
}
|
||||
else {
|
||||
float64 x = toFloat64(a);
|
||||
float64 y = toFloat64(b);
|
||||
float64 x = meta->toFloat64(a);
|
||||
float64 y = meta->toFloat64(b);
|
||||
float64 z;
|
||||
#ifdef XP_PC
|
||||
/* Workaround MS fmod bug where 42 % (1/0) => NaN, not 42. */
|
||||
|
@ -678,14 +677,14 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
push(BOOLEAN_TO_JS2VAL(toBoolean(a) ^ toBoolean(b)));
|
||||
push(BOOLEAN_TO_JS2VAL(meta->toBoolean(a) ^ meta->toBoolean(b)));
|
||||
}
|
||||
break;
|
||||
|
||||
case eLogicalNot:
|
||||
{
|
||||
a = pop();
|
||||
push(BOOLEAN_TO_JS2VAL(!toBoolean(a)));
|
||||
push(BOOLEAN_TO_JS2VAL(!meta->toBoolean(a)));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -693,13 +692,13 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toPrimitive(a);
|
||||
b = toPrimitive(b);
|
||||
a = meta->toPrimitive(a);
|
||||
b = meta->toPrimitive(b);
|
||||
bool rval;
|
||||
if (JS2VAL_IS_STRING(a) && JS2VAL_IS_STRING(b))
|
||||
rval = (*JS2VAL_TO_STRING(a) < *JS2VAL_TO_STRING(b));
|
||||
else
|
||||
rval = toFloat64(a) < toFloat64(b);
|
||||
rval = meta->toFloat64(a) < meta->toFloat64(b);
|
||||
push(BOOLEAN_TO_JS2VAL(rval));
|
||||
}
|
||||
break;
|
||||
|
@ -708,13 +707,13 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toPrimitive(a);
|
||||
b = toPrimitive(b);
|
||||
a = meta->toPrimitive(a);
|
||||
b = meta->toPrimitive(b);
|
||||
bool rval;
|
||||
if (JS2VAL_IS_STRING(a) && JS2VAL_IS_STRING(b))
|
||||
rval = (*JS2VAL_TO_STRING(a) <= *JS2VAL_TO_STRING(b));
|
||||
else
|
||||
rval = toFloat64(a) <= toFloat64(b);
|
||||
rval = meta->toFloat64(a) <= meta->toFloat64(b);
|
||||
push(BOOLEAN_TO_JS2VAL(rval));
|
||||
}
|
||||
break;
|
||||
|
@ -723,13 +722,13 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toPrimitive(a);
|
||||
b = toPrimitive(b);
|
||||
a = meta->toPrimitive(a);
|
||||
b = meta->toPrimitive(b);
|
||||
bool rval;
|
||||
if (JS2VAL_IS_STRING(a) && JS2VAL_IS_STRING(b))
|
||||
rval = (*JS2VAL_TO_STRING(a) > *JS2VAL_TO_STRING(b));
|
||||
else
|
||||
rval = toFloat64(a) > toFloat64(b);
|
||||
rval = meta->toFloat64(a) > meta->toFloat64(b);
|
||||
push(BOOLEAN_TO_JS2VAL(rval));
|
||||
}
|
||||
break;
|
||||
|
@ -738,13 +737,13 @@
|
|||
{
|
||||
b = pop();
|
||||
a = pop();
|
||||
a = toPrimitive(a);
|
||||
b = toPrimitive(b);
|
||||
a = meta->toPrimitive(a);
|
||||
b = meta->toPrimitive(b);
|
||||
bool rval;
|
||||
if (JS2VAL_IS_STRING(a) && JS2VAL_IS_STRING(b))
|
||||
rval = (*JS2VAL_TO_STRING(a) >= *JS2VAL_TO_STRING(b));
|
||||
else
|
||||
rval = toFloat64(a) >= toFloat64(b);
|
||||
rval = meta->toFloat64(a) >= meta->toFloat64(b);
|
||||
push(BOOLEAN_TO_JS2VAL(rval));
|
||||
}
|
||||
break;
|
||||
|
@ -762,29 +761,29 @@
|
|||
if (JS2VAL_IS_BOOLEAN(b))
|
||||
rval = (JS2VAL_TO_BOOLEAN(a) == JS2VAL_TO_BOOLEAN(b));
|
||||
else {
|
||||
b = toPrimitive(b);
|
||||
b = meta->toPrimitive(b);
|
||||
if (JS2VAL_IS_NULL(b) || JS2VAL_IS_UNDEFINED(b))
|
||||
rval = false;
|
||||
else
|
||||
rval = (toFloat64(a) == toFloat64(b));
|
||||
rval = (meta->toFloat64(a) == meta->toFloat64(b));
|
||||
}
|
||||
}
|
||||
else
|
||||
if (JS2VAL_IS_NUMBER(a)) {
|
||||
b = toPrimitive(b);
|
||||
b = meta->toPrimitive(b);
|
||||
if (JS2VAL_IS_NULL(b) || JS2VAL_IS_UNDEFINED(b))
|
||||
rval = false;
|
||||
else
|
||||
rval = (toFloat64(a) == toFloat64(b));
|
||||
rval = (meta->toFloat64(a) == meta->toFloat64(b));
|
||||
}
|
||||
else
|
||||
if (JS2VAL_IS_STRING(a)) {
|
||||
b = toPrimitive(b);
|
||||
b = meta->toPrimitive(b);
|
||||
if (JS2VAL_IS_NULL(b) || JS2VAL_IS_UNDEFINED(b))
|
||||
rval = false;
|
||||
else
|
||||
if (JS2VAL_IS_BOOLEAN(b) || JS2VAL_IS_NUMBER(b))
|
||||
rval = (toFloat64(a) == toFloat64(b));
|
||||
rval = (meta->toFloat64(a) == meta->toFloat64(b));
|
||||
else
|
||||
rval = (*JS2VAL_TO_STRING(a) == *JS2VAL_TO_STRING(b));
|
||||
}
|
||||
|
@ -793,31 +792,31 @@
|
|||
rval = false;
|
||||
else
|
||||
if (JS2VAL_IS_BOOLEAN(b)) {
|
||||
a = toPrimitive(a);
|
||||
a = meta->toPrimitive(a);
|
||||
if (JS2VAL_IS_NULL(a) || JS2VAL_IS_UNDEFINED(a))
|
||||
rval = false;
|
||||
else
|
||||
if (JS2VAL_IS_BOOLEAN(a))
|
||||
rval = (JS2VAL_TO_BOOLEAN(a) == JS2VAL_TO_BOOLEAN(b));
|
||||
else
|
||||
rval = (toFloat64(a) == toFloat64(b));
|
||||
rval = (meta->toFloat64(a) == meta->toFloat64(b));
|
||||
}
|
||||
else
|
||||
if (JS2VAL_IS_NUMBER(b)) {
|
||||
a = toPrimitive(a);
|
||||
a = meta->toPrimitive(a);
|
||||
if (JS2VAL_IS_NULL(a) || JS2VAL_IS_UNDEFINED(a))
|
||||
rval = false;
|
||||
else
|
||||
rval = (toFloat64(a) == toFloat64(b));
|
||||
rval = (meta->toFloat64(a) == meta->toFloat64(b));
|
||||
}
|
||||
else
|
||||
if (JS2VAL_IS_STRING(b)) {
|
||||
a = toPrimitive(a);
|
||||
a = meta->toPrimitive(a);
|
||||
if (JS2VAL_IS_NULL(a) || JS2VAL_IS_UNDEFINED(a))
|
||||
rval = false;
|
||||
else
|
||||
if (JS2VAL_IS_BOOLEAN(a) || JS2VAL_IS_NUMBER(a))
|
||||
rval = (toFloat64(a) == toFloat64(b));
|
||||
rval = (meta->toFloat64(a) == meta->toFloat64(b));
|
||||
else
|
||||
rval = (*JS2VAL_TO_STRING(a) == *JS2VAL_TO_STRING(b));
|
||||
}
|
||||
|
@ -850,7 +849,7 @@
|
|||
push(a);
|
||||
}
|
||||
else {
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
meta->env.lexicalWrite(meta, mn, allocNumber(num + 1.0), true, phase);
|
||||
pushNumber(num);
|
||||
}
|
||||
|
@ -862,7 +861,7 @@
|
|||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
a = meta->env.lexicalRead(meta, mn, phase);
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
meta->env.lexicalWrite(meta, mn, allocNumber(num - 1.0), true, phase);
|
||||
pushNumber(num);
|
||||
}
|
||||
|
@ -872,7 +871,7 @@
|
|||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
a = meta->env.lexicalRead(meta, mn, phase);
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
a = pushNumber(num + 1.0);
|
||||
meta->env.lexicalWrite(meta, mn, a, true, phase);
|
||||
}
|
||||
|
@ -882,7 +881,7 @@
|
|||
Multiname *mn = bCon->mMultinameList[BytecodeContainer::getShort(pc)];
|
||||
pc += sizeof(short);
|
||||
a = meta->env.lexicalRead(meta, mn, phase);
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
a = pushNumber(num - 1.0);
|
||||
meta->env.lexicalWrite(meta, mn, a, true, phase);
|
||||
}
|
||||
|
@ -896,7 +895,7 @@
|
|||
baseVal = pop();
|
||||
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
meta->writeProperty(baseVal, mn, &lookup, true, allocNumber(num + 1.0), RunPhase);
|
||||
pushNumber(num);
|
||||
baseVal = JS2VAL_VOID;
|
||||
|
@ -910,7 +909,7 @@
|
|||
baseVal = pop();
|
||||
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
meta->writeProperty(baseVal, mn, &lookup, true, allocNumber(num - 1.0), RunPhase);
|
||||
pushNumber(num);
|
||||
baseVal = JS2VAL_VOID;
|
||||
|
@ -924,7 +923,7 @@
|
|||
baseVal = pop();
|
||||
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
a = pushNumber(num + 1.0);
|
||||
meta->writeProperty(baseVal, mn, &lookup, true, a, RunPhase);
|
||||
baseVal = JS2VAL_VOID;
|
||||
|
@ -938,7 +937,7 @@
|
|||
baseVal = pop();
|
||||
if (!meta->readProperty(baseVal, mn, &lookup, RunPhase, &a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn->name);
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
a = pushNumber(num - 1.0);
|
||||
meta->writeProperty(baseVal, mn, &lookup, true, a, RunPhase);
|
||||
baseVal = JS2VAL_VOID;
|
||||
|
@ -950,11 +949,11 @@
|
|||
LookupKind lookup(false, NULL);
|
||||
indexVal = pop();
|
||||
baseVal = pop();
|
||||
const String *indexStr = toString(indexVal);
|
||||
const String *indexStr = meta->toString(indexVal);
|
||||
Multiname mn(&meta->world.identifiers[*indexStr], meta->publicNamespace);
|
||||
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
meta->writeProperty(baseVal, &mn, &lookup, true, allocNumber(num + 1.0), RunPhase);
|
||||
pushNumber(num);
|
||||
baseVal = JS2VAL_VOID;
|
||||
|
@ -966,11 +965,11 @@
|
|||
LookupKind lookup(false, NULL);
|
||||
indexVal = pop();
|
||||
baseVal = pop();
|
||||
const String *indexStr = toString(indexVal);
|
||||
const String *indexStr = meta->toString(indexVal);
|
||||
Multiname mn(&meta->world.identifiers[*indexStr], meta->publicNamespace);
|
||||
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
meta->writeProperty(baseVal, &mn, &lookup, true, allocNumber(num - 1.0), RunPhase);
|
||||
pushNumber(num);
|
||||
baseVal = JS2VAL_VOID;
|
||||
|
@ -982,11 +981,11 @@
|
|||
LookupKind lookup(false, NULL);
|
||||
indexVal = pop();
|
||||
baseVal = pop();
|
||||
const String *indexStr = toString(indexVal);
|
||||
const String *indexStr = meta->toString(indexVal);
|
||||
Multiname mn(&meta->world.identifiers[*indexStr], meta->publicNamespace);
|
||||
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
a = pushNumber(num + 1.0);
|
||||
meta->writeProperty(baseVal, &mn, &lookup, true, a, RunPhase);
|
||||
baseVal = JS2VAL_VOID;
|
||||
|
@ -998,11 +997,11 @@
|
|||
LookupKind lookup(false, NULL);
|
||||
indexVal = pop();
|
||||
baseVal = pop();
|
||||
const String *indexStr = toString(indexVal);
|
||||
const String *indexStr = meta->toString(indexVal);
|
||||
Multiname mn(&meta->world.identifiers[*indexStr], meta->publicNamespace);
|
||||
if (!meta->readProperty(baseVal, &mn, &lookup, RunPhase, &a))
|
||||
meta->reportError(Exception::propertyAccessError, "No property named {0}", errorPos(), mn.name);
|
||||
float64 num = toFloat64(a);
|
||||
float64 num = meta->toFloat64(a);
|
||||
a = pushNumber(num - 1.0);
|
||||
meta->writeProperty(baseVal, &mn, &lookup, true, a, RunPhase);
|
||||
baseVal = JS2VAL_VOID;
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
case eBranchTrue:
|
||||
{
|
||||
a = pop();
|
||||
bool c = toBoolean(a);
|
||||
bool c = meta->toBoolean(a);
|
||||
if (c) {
|
||||
int32 offset = BytecodeContainer::getOffset(pc);
|
||||
pc += offset;
|
||||
|
@ -47,7 +47,7 @@
|
|||
case eBranchFalse:
|
||||
{
|
||||
a = pop();
|
||||
bool c = toBoolean(a);
|
||||
bool c = meta->toBoolean(a);
|
||||
if (!c) {
|
||||
int32 offset = BytecodeContainer::getOffset(pc);
|
||||
pc += offset;
|
||||
|
@ -82,7 +82,7 @@
|
|||
case eFirst:
|
||||
{
|
||||
a = pop();
|
||||
b = toObject(a);
|
||||
b = meta->toObject(a);
|
||||
ForIteratorObject *fi = new ForIteratorObject(JS2VAL_TO_OBJECT(b));
|
||||
push(OBJECT_TO_JS2VAL(fi));
|
||||
push(BOOLEAN_TO_JS2VAL(fi->first()));
|
||||
|
|
|
@ -37,12 +37,12 @@
|
|||
{
|
||||
uint16 argCount = BytecodeContainer::getShort(pc);
|
||||
pc += sizeof(uint16);
|
||||
a = top();
|
||||
a = top(argCount + 1);
|
||||
ASSERT(JS2VAL_IS_OBJECT(a) && !JS2VAL_IS_NULL(a));
|
||||
JS2Object *obj = JS2VAL_TO_OBJECT(a);
|
||||
if (obj->kind == ClassKind) {
|
||||
JS2Class *c = checked_cast<JS2Class *>(obj);
|
||||
a = c->construct(meta, JS2VAL_NULL, NULL, argCount);
|
||||
a = c->construct(meta, JS2VAL_NULL, base(argCount), argCount);
|
||||
pop(argCount + 1);
|
||||
push(a);
|
||||
}
|
||||
|
@ -94,11 +94,11 @@
|
|||
uint16 argCount = BytecodeContainer::getShort(pc);
|
||||
pc += sizeof(uint16);
|
||||
a = top(argCount + 2); // 'this'
|
||||
b = top(argCount + 1); // target function
|
||||
b = top(argCount + 1); // target function
|
||||
if (JS2VAL_IS_PRIMITIVE(b))
|
||||
meta->reportError(Exception::badValueError, "Can't call on primitive value", errorPos());
|
||||
JS2Object *fObj = JS2VAL_TO_OBJECT(b);
|
||||
if (fObj->kind == FixedInstanceKind) {
|
||||
if ((fObj->kind == FixedInstanceKind) && (meta->objectType(b) == meta->functionClass)) {
|
||||
FixedInstance *fInst = checked_cast<FixedInstance *>(fObj);
|
||||
FunctionWrapper *fWrap = fInst->fWrap;
|
||||
js2val compileThis = fWrap->compileFrame->thisObject;
|
||||
|
|
|
@ -73,6 +73,14 @@
|
|||
}
|
||||
break;
|
||||
|
||||
case eRegExp:
|
||||
{
|
||||
RegExpInstance *x = bCon->mRegExpList[BytecodeContainer::getShort(pc)];
|
||||
push(OBJECT_TO_JS2VAL(x));
|
||||
pc += sizeof(short);
|
||||
}
|
||||
break;
|
||||
|
||||
case eNull:
|
||||
{
|
||||
push(JS2VAL_NULL);
|
||||
|
|
|
@ -134,23 +134,23 @@ namespace MetaData {
|
|||
if (argc > 0) {
|
||||
int32 index = 0;
|
||||
|
||||
const String *str = meta->engine->toString(argv[0]);
|
||||
const String *str = meta->engine->meta->toString(argv[0]);
|
||||
js2val globalMultiline = thisInst->getMultiline(meta);
|
||||
|
||||
if (thisInst->getGlobal(meta)) {
|
||||
js2val lastIndex = thisInst->getLastIndex(meta);
|
||||
index = meta->engine->toInteger(lastIndex);
|
||||
index = meta->engine->meta->toInteger(lastIndex);
|
||||
}
|
||||
|
||||
REMatchState *match = REExecute(thisInst->mRegExp, str->begin(), index, toInt32(str->length()), meta->engine->toBoolean(globalMultiline));
|
||||
REMatchState *match = REExecute(thisInst->mRegExp, str->begin(), index, toInt32(str->length()), meta->toBoolean(globalMultiline));
|
||||
if (match) {
|
||||
PrototypeInstance *A = new PrototypeInstance(meta->objectClass->prototype, meta->objectClass);
|
||||
result = OBJECT_TO_JS2VAL(A);
|
||||
js2val matchStr = meta->engine->allocString(str->substr((uint32)match->startIndex, (uint32)match->endIndex - match->startIndex));
|
||||
Multiname mname(&meta->world.identifiers[*numberToString((long)0)], meta->publicNamespace);
|
||||
Multiname mname(&meta->world.identifiers[*meta->toString((long)0)], meta->publicNamespace);
|
||||
meta->writeDynamicProperty(A, &mname, true, matchStr, RunPhase);
|
||||
for (int32 i = 0; i < match->parenCount; i++) {
|
||||
Multiname mname(&meta->world.identifiers[*numberToString(i + 1)], meta->publicNamespace);
|
||||
Multiname mname(&meta->world.identifiers[*meta->toString(i + 1)], meta->publicNamespace);
|
||||
if (match->parens[i].index != -1) {
|
||||
js2val parenStr = meta->engine->allocString(str->substr((uint32)(match->parens[i].index), (uint32)(match->parens[i].length)));
|
||||
meta->writeDynamicProperty(A, &mname, true, parenStr, RunPhase);
|
||||
|
@ -182,5 +182,52 @@ namespace MetaData {
|
|||
return result;
|
||||
}
|
||||
|
||||
js2val RegExp_Constructor(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
// XXX Change constructors to take js2val pointer for the result (which would be an already
|
||||
// rooted pointer).
|
||||
RegExpInstance *thisInst = new RegExpInstance(meta->regexpClass);
|
||||
JS2Object::RootIterator ri = JS2Object::addRoot(&thisInst);
|
||||
js2val thatValue = OBJECT_TO_JS2VAL(thisInst);
|
||||
REuint32 flags = 0;
|
||||
|
||||
const String *regexpStr = meta->engine->Empty_StringAtom;
|
||||
const String *flagStr = meta->engine->Empty_StringAtom;
|
||||
if (argc > 0) {
|
||||
if (meta->objectType(argv[0]) == meta->regexpClass) {
|
||||
if ((argc == 1) || JS2VAL_IS_UNDEFINED(argv[1])) {
|
||||
RegExpInstance *otherInst = checked_cast<RegExpInstance *>(JS2VAL_TO_OBJECT(argv[0]));
|
||||
js2val src = otherInst->getSource(meta);
|
||||
ASSERT(JS2VAL_IS_STRING(src));
|
||||
regexpStr = JS2VAL_TO_STRING(src);
|
||||
flags = otherInst->mRegExp->flags;
|
||||
}
|
||||
else
|
||||
meta->reportError(Exception::typeError, "Illegal RegExp constructor args", meta->engine->errorPos());
|
||||
}
|
||||
else
|
||||
regexpStr = meta->toString(argv[0]);
|
||||
if ((argc > 1) && !JS2VAL_IS_UNDEFINED(argv[1])) {
|
||||
flagStr = meta->toString(argv[1]);
|
||||
if (parseFlags(flagStr->begin(), (int32)flagStr->length(), &flags) != RE_NO_ERROR)
|
||||
meta->reportError(Exception::syntaxError, "Failed to parse RegExp : '{0}'", meta->engine->errorPos(), *regexpStr + "/" + *flagStr); // XXX error message?
|
||||
}
|
||||
}
|
||||
REState *pState = REParse(regexpStr->begin(), (int32)regexpStr->length(), flags, RE_VERSION_1);
|
||||
if (pState) {
|
||||
thisInst->mRegExp = pState;
|
||||
// XXX ECMA spec says these are DONTENUM
|
||||
thisInst->setSource(meta, STRING_TO_JS2VAL(regexpStr));
|
||||
thisInst->setGlobal(meta, BOOLEAN_TO_JS2VAL((pState->flags & RE_GLOBAL) == RE_GLOBAL));
|
||||
thisInst->setIgnoreCase(meta, BOOLEAN_TO_JS2VAL((pState->flags & RE_IGNORECASE) == RE_IGNORECASE));
|
||||
thisInst->setLastIndex(meta, INT_TO_JS2VAL(0));
|
||||
thisInst->setMultiline(meta, BOOLEAN_TO_JS2VAL((pState->flags & RE_MULTILINE) == RE_MULTILINE));
|
||||
}
|
||||
else
|
||||
meta->reportError(Exception::syntaxError, "Failed to parse RegExp : '{0}'", meta->engine->errorPos(), "/" + *regexpStr + "/" + *flagStr); // XXX what about the RE parser error message?
|
||||
JS2Object::removeRoot(ri);
|
||||
return thatValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,9 +65,9 @@ js2val String_Constructor(JS2Metadata *meta, const js2val /*thisValue*/, js2val
|
|||
StringInstance *strInst = checked_cast<StringInstance *>(JS2VAL_TO_OBJECT(thatValue));
|
||||
|
||||
if (argc > 0)
|
||||
strInst->mValue = meta->engine->allocStringPtr(meta->engine->toString(argv[0]));
|
||||
strInst->mValue = meta->engine->allocStringPtr(meta->engine->meta->toString(argv[0]));
|
||||
else
|
||||
strInst->mValue = meta->engine->allocStringPtr((String *)NULL);
|
||||
strInst->mValue = meta->engine->allocStringPtr("");
|
||||
return thatValue;
|
||||
}
|
||||
|
||||
|
@ -109,7 +109,7 @@ static js2val String_valueOf(JS2Metadata *meta, const js2val thisValue, js2val *
|
|||
*/
|
||||
static js2val String_search(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
js2val S = STRING_TO_JS2VAL(meta->engine->toString(thisValue));
|
||||
js2val S = STRING_TO_JS2VAL(meta->engine->meta->toString(thisValue));
|
||||
|
||||
js2val regexp = argv[0];
|
||||
|
||||
|
@ -144,7 +144,7 @@ static js2val String_search(JS2Metadata *meta, const js2val thisValue, js2val *a
|
|||
|
||||
static js2val String_match(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
js2val S = STRING_TO_JS2VAL(meta->engine->toString(thisValue));
|
||||
js2val S = STRING_TO_JS2VAL(meta->engine->meta->toString(thisValue));
|
||||
|
||||
js2val regexp = argv[0];
|
||||
if ((argc == 0) || (meta->objectType(thisValue) != meta->regexpClass)) {
|
||||
|
@ -170,7 +170,7 @@ static js2val String_match(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
|||
else
|
||||
lastIndex = match->endIndex;
|
||||
js2val matchStr = meta->engine->allocString(JS2VAL_TO_STRING(S)->substr(toUInt32(match->startIndex), toUInt32(match->endIndex) - match->startIndex));
|
||||
Multiname mname(&meta->world.identifiers[*numberToString(index)], meta->publicNamespace);
|
||||
Multiname mname(&meta->world.identifiers[*meta->toString(index)], meta->publicNamespace);
|
||||
index++;
|
||||
meta->writeDynamicProperty(A, &mname, true, matchStr, RunPhase);
|
||||
}
|
||||
|
@ -179,14 +179,13 @@ static js2val String_match(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
|||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static const String interpretDollar(JS2Metadata *meta, const String *replaceStr, uint32 dollarPos, const String *searchStr, REMatchState *match, uint32 &skip)
|
||||
{
|
||||
skip = 2;
|
||||
const char16 *dollarValue = replaceStr->begin() + dollarPos + 1;
|
||||
switch (*dollarValue) {
|
||||
case '$':
|
||||
return meta->engine->Dollar_StringAtom;
|
||||
return *meta->engine->Dollar_StringAtom;
|
||||
case '&':
|
||||
return searchStr->substr((uint32)match->startIndex, (uint32)match->endIndex - match->startIndex);
|
||||
case '`':
|
||||
|
@ -220,7 +219,7 @@ static const String interpretDollar(JS2Metadata *meta, const String *replaceStr,
|
|||
// fall thru
|
||||
default:
|
||||
skip = 1;
|
||||
return meta->engine->Dollar_StringAtom;
|
||||
return *meta->engine->Dollar_StringAtom;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -235,7 +234,7 @@ static const String interpretDollar(JS2Metadata *meta, const String *replaceStr,
|
|||
* in the same manner as in String.prototype.match, including the update of searchValue.lastIndex. Let m
|
||||
* be the number of left capturing parentheses in searchValue (NCapturingParens as specified in section 15.10.2.1).
|
||||
*
|
||||
* If searchValue is not a regular expression, let searchString be ToString(searchValue) and search string for the first
|
||||
* If searchValue is not a regular expression, let searchString be meta->toString(searchValue) and search string for the first
|
||||
* occurrence of searchString. Let m be 0.
|
||||
*
|
||||
* If replaceValue is a function, then for each matched substring, call the function with the following m + 3 arguments.
|
||||
|
@ -255,19 +254,19 @@ static const String interpretDollar(JS2Metadata *meta, const String *replaceStr,
|
|||
|
||||
static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
const String *S = meta->engine->toString(thisValue);
|
||||
const String *S = meta->engine->meta->toString(thisValue);
|
||||
|
||||
js2val searchValue;
|
||||
js2val replaceValue;
|
||||
|
||||
if (argc > 0) searchValue = argv[0];
|
||||
if (argc > 1) replaceValue = argv[1];
|
||||
const String *replaceStr = meta->engine->toString(replaceValue);
|
||||
const String *replaceStr = meta->engine->meta->toString(replaceValue);
|
||||
|
||||
if (meta->objectType(searchValue) != meta->regexpClass) {
|
||||
REState *pState = (checked_cast<RegExpInstance *>(JS2VAL_TO_OBJECT(searchValue)))->mRegExp;
|
||||
RegExpInstance *reInst = checked_cast<RegExpInstance *>(JS2VAL_TO_OBJECT(searchValue));
|
||||
REState *pState = reInst->mRegExp;
|
||||
REMatchState *match;
|
||||
// uint32 m = pState->parenCount;
|
||||
String newString;
|
||||
int32 lastIndex = 0;
|
||||
|
||||
|
@ -282,7 +281,7 @@ static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val *
|
|||
if ((dollarPos != String::npos) && (dollarPos < (replaceStr->length() - 1))) {
|
||||
uint32 skip;
|
||||
insertString += replaceStr->substr(start, dollarPos - start);
|
||||
insertString += interpretDollar(cx, replaceStr, dollarPos, S, match, skip);
|
||||
insertString += interpretDollar(meta, replaceStr, dollarPos, S, match, skip);
|
||||
start = dollarPos + skip;
|
||||
}
|
||||
else {
|
||||
|
@ -304,11 +303,11 @@ static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val *
|
|||
}
|
||||
newString += S->substr(toUInt32(lastIndex), toUInt32(S->length()) - lastIndex);
|
||||
if ((pState->flags & RE_GLOBAL) == 0)
|
||||
JS2VAL_TO_OBJECT(searchValue)->setProperty(cx, cx->LastIndex_StringAtom, NULL, JSValue::newNumber((float64)lastIndex));
|
||||
reInst->setLastIndex(meta, meta->engine->allocNumber((float64)lastIndex));
|
||||
return meta->engine->allocString(newString);
|
||||
}
|
||||
else {
|
||||
const String *searchStr = JSValue::string(JSValue::toString(cx, searchValue));
|
||||
const String *searchStr = meta->engine->meta->toString(searchValue);
|
||||
REMatchState match;
|
||||
uint32 pos = S->find(*searchStr, 0);
|
||||
if (pos == String::npos)
|
||||
|
@ -324,7 +323,7 @@ static js2val String_replace(JS2Metadata *meta, const js2val thisValue, js2val *
|
|||
if ((dollarPos != String::npos) && (dollarPos < (replaceStr->length() - 1))) {
|
||||
uint32 skip;
|
||||
insertString += replaceStr->substr(start, dollarPos - start);
|
||||
insertString += interpretDollar(cx, replaceStr, dollarPos, S, &match, skip);
|
||||
insertString += interpretDollar(meta, replaceStr, dollarPos, S, &match, skip);
|
||||
start = dollarPos + skip;
|
||||
}
|
||||
else {
|
||||
|
@ -365,7 +364,7 @@ static void strSplitMatch(const String *S, uint32 q, const String *R, MatchResul
|
|||
result.failure = false;
|
||||
}
|
||||
|
||||
static void regexpSplitMatch(const String *S, uint32 q, REState *RE, MatchResult &result)
|
||||
static void regexpSplitMatch(JS2Metadata *meta, const String *S, uint32 q, REState *RE, MatchResult &result)
|
||||
{
|
||||
result.failure = true;
|
||||
result.captures = NULL;
|
||||
|
@ -392,10 +391,11 @@ static void regexpSplitMatch(const String *S, uint32 q, REState *RE, MatchResult
|
|||
|
||||
static js2val String_split(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
const String *S = meta->engine->toString(thisValue);
|
||||
const String *S = meta->engine->meta->toString(thisValue);
|
||||
|
||||
js2val result = OBJECT_TO_JS2VAL(new ArrayInstance(meta->arrayClass));
|
||||
ArrayInstance *A = checked_cast<ArrayInstance *>(JS2VAL_TO_OBJECT(result));
|
||||
|
||||
js2val result = Array_Type->newInstance(cx);
|
||||
JSArrayInstance *A = checked_cast<JSArrayInstance *>(JSValue::instance(result));
|
||||
uint32 lim;
|
||||
js2val separatorV = (argc > 0) ? argv[0] : JS2VAL_UNDEFINED;
|
||||
js2val limitV = (argc > 1) ? argv[1] : JS2VAL_UNDEFINED;
|
||||
|
@ -413,7 +413,7 @@ static js2val String_split(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
|||
if (meta->objectType(separatorV) == meta->regexpClass)
|
||||
RE = (checked_cast<RegExpInstance *>(JS2VAL_TO_OBJECT(separatorV)))->mRegExp;
|
||||
else
|
||||
R = meta->engine->toString(separatorV);
|
||||
R = meta->engine->meta->toString(separatorV);
|
||||
|
||||
if (lim == 0)
|
||||
return result;
|
||||
|
@ -425,15 +425,18 @@ static js2val String_split(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
|||
return JSValue(A);
|
||||
}
|
||||
*/
|
||||
Multiname mn(NULL, meta->publicNamespace);
|
||||
if (s == 0) {
|
||||
MatchResult z;
|
||||
if (RE)
|
||||
regexpSplitMatch(S, 0, RE, z);
|
||||
regexpSplitMatch(meta, S, 0, RE, z);
|
||||
else
|
||||
strSplitMatch(S, 0, R, z);
|
||||
if (!z.failure)
|
||||
return result;
|
||||
A->setProperty(cx, widenCString("0"), NULL, STRING_TO_JS2VAL(S));
|
||||
mn.name = meta->toString((int32)0);
|
||||
meta->writeDynamicProperty(A, &mn, true, STRING_TO_JS2VAL(S), RunPhase);
|
||||
delete mn.name;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -441,14 +444,15 @@ static js2val String_split(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
|||
uint32 q = p;
|
||||
step11:
|
||||
if (q == s) {
|
||||
String *T = meta->engine->allocString(*S, p, (s - p));
|
||||
js2val v = STRING_TO_JS2VAL(T);
|
||||
A->setProperty(cx, *numberToString(A->mLength), NULL, v);
|
||||
js2val v = meta->engine->allocString(new String(*S, p, (s - p)));
|
||||
mn.name = meta->toString(getLength(meta, A));
|
||||
meta->writeDynamicProperty(A, &mn, true, v, RunPhase);
|
||||
delete mn.name;
|
||||
return result;
|
||||
}
|
||||
MatchResult z;
|
||||
if (RE)
|
||||
regexpSplitMatch(S, q, RE, z);
|
||||
regexpSplitMatch(meta, S, q, RE, z);
|
||||
else
|
||||
strSplitMatch(S, q, R, z);
|
||||
if (z.failure) {
|
||||
|
@ -462,27 +466,30 @@ step11:
|
|||
}
|
||||
String *T = meta->engine->allocStringPtr(new String(*S, p, (q - p))); // XXX
|
||||
js2val v = STRING_TO_JS2VAL(T);
|
||||
A->setProperty(cx, *numberToString(A->mLength), NULL, v);
|
||||
if (A->mLength == lim)
|
||||
mn.name = meta->toString(getLength(meta, A));
|
||||
meta->writeDynamicProperty(A, &mn, true, v, RunPhase);
|
||||
delete mn.name;
|
||||
if (getLength(meta, A) == lim)
|
||||
return result;
|
||||
p = e;
|
||||
|
||||
for (uint32 i = 0; i < z.capturesCount; i++) {
|
||||
A->setProperty(cx, *numberToString(A->mLength), NULL, z.captures[i]);
|
||||
if (A->mLength == lim)
|
||||
mn.name = meta->toString(getLength(meta, A));
|
||||
meta->writeDynamicProperty(A, &mn, true, z.captures[i], RunPhase);
|
||||
delete mn.name;
|
||||
if (getLength(meta, A) == lim)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static js2val String_charAt(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
const String *str = meta->engine->toString(thisValue);
|
||||
const String *str = meta->engine->meta->toString(thisValue);
|
||||
|
||||
uint32 pos = 0;
|
||||
if (argc > 0)
|
||||
pos = toUInt32(meta->engine->toInteger(argv[0]));
|
||||
pos = toUInt32(meta->toInteger(argv[0]));
|
||||
|
||||
if ((pos < 0) || (pos >= str->size()))
|
||||
return STRING_TO_JS2VAL(meta->engine->Empty_StringAtom);
|
||||
|
@ -493,11 +500,11 @@ static js2val String_charAt(JS2Metadata *meta, const js2val thisValue, js2val *a
|
|||
|
||||
static js2val String_charCodeAt(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
const String *str = meta->engine->toString(thisValue);
|
||||
const String *str = meta->toString(thisValue);
|
||||
|
||||
uint32 pos = 0;
|
||||
if (argc > 0)
|
||||
pos = toUInt32(meta->engine->toInteger(argv[0]));
|
||||
pos = toUInt32(meta->toInteger(argv[0]));
|
||||
|
||||
if ((pos < 0) || (pos >= str->size()))
|
||||
return meta->engine->nanValue;
|
||||
|
@ -507,11 +514,11 @@ static js2val String_charCodeAt(JS2Metadata *meta, const js2val thisValue, js2va
|
|||
|
||||
static js2val String_concat(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
const String *str = meta->engine->toString(thisValue);
|
||||
const String *str = meta->toString(thisValue);
|
||||
String *result = meta->engine->allocStringPtr(str);
|
||||
|
||||
for (uint32 i = 0; i < argc; i++) {
|
||||
*result += *meta->engine->toString(argv[i]);
|
||||
*result += *meta->toString(argv[i]);
|
||||
}
|
||||
|
||||
return STRING_TO_JS2VAL(result);
|
||||
|
@ -522,12 +529,12 @@ static js2val String_indexOf(JS2Metadata *meta, const js2val thisValue, js2val *
|
|||
if (argc == 0)
|
||||
return meta->engine->allocNumber(-1.0);
|
||||
|
||||
const String *str = meta->engine->toString(thisValue);
|
||||
const String *searchStr = meta->engine->toString(argv[0]);
|
||||
const String *str = meta->toString(thisValue);
|
||||
const String *searchStr = meta->toString(argv[0]);
|
||||
uint32 pos = 0;
|
||||
|
||||
if (argc > 1) {
|
||||
float64 fpos = meta->engine->toFloat64(argv[1]);
|
||||
float64 fpos = meta->toFloat64(argv[1]);
|
||||
if (JSDOUBLE_IS_NaN(fpos))
|
||||
pos = 0;
|
||||
if (fpos < 0)
|
||||
|
@ -549,12 +556,12 @@ static js2val String_lastIndexOf(JS2Metadata *meta, const js2val thisValue, js2v
|
|||
if (argc == 0)
|
||||
return meta->engine->allocNumber(-1.0);
|
||||
|
||||
const String *str = meta->engine->toString(thisValue);
|
||||
const String *searchStr = meta->engine->toString(argv[0]);
|
||||
const String *str = meta->toString(thisValue);
|
||||
const String *searchStr = meta->toString(argv[0]);
|
||||
uint32 pos = str->size();
|
||||
|
||||
if (argc > 1) {
|
||||
float64 fpos = meta->engine->toFloat64(argv[1]);
|
||||
float64 fpos = meta->toFloat64(argv[1]);
|
||||
if (JSDOUBLE_IS_NaN(fpos))
|
||||
pos = str->size();
|
||||
else {
|
||||
|
@ -580,7 +587,7 @@ static js2val String_localeCompare(JS2Metadata *meta, const js2val /*thisValue*/
|
|||
|
||||
static js2val String_toLowerCase(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
js2val S = STRING_TO_JS2VAL(meta->engine->toString(thisValue));
|
||||
js2val S = STRING_TO_JS2VAL(meta->toString(thisValue));
|
||||
|
||||
String *result = meta->engine->allocStringPtr(JS2VAL_TO_STRING(S));
|
||||
for (String::iterator i = result->begin(), end = result->end(); i != end; i++)
|
||||
|
@ -591,7 +598,7 @@ static js2val String_toLowerCase(JS2Metadata *meta, const js2val thisValue, js2v
|
|||
|
||||
static js2val String_toUpperCase(JS2Metadata *meta, const js2val thisValue, js2val * /*argv*/, uint32 /*argc*/)
|
||||
{
|
||||
js2val S = STRING_TO_JS2VAL(meta->engine->toString(thisValue));
|
||||
js2val S = STRING_TO_JS2VAL(meta->toString(thisValue));
|
||||
|
||||
String *result = meta->engine->allocStringPtr(JS2VAL_TO_STRING(S));
|
||||
for (String::iterator i = result->begin(), end = result->end(); i != end; i++)
|
||||
|
@ -623,13 +630,13 @@ static js2val String_toUpperCase(JS2Metadata *meta, const js2val thisValue, js2v
|
|||
|
||||
static js2val String_slice(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
const String *sourceString = meta->engine->toString(thisValue);
|
||||
const String *sourceString = meta->toString(thisValue);
|
||||
|
||||
uint32 sourceLength = sourceString->size();
|
||||
uint32 start, end;
|
||||
|
||||
if (argc > 0) {
|
||||
int32 arg0 = meta->engine->toInteger(argv[0]);
|
||||
int32 arg0 = meta->toInteger(argv[0]);
|
||||
if (arg0 < 0) {
|
||||
arg0 += sourceLength;
|
||||
if (arg0 < 0)
|
||||
|
@ -648,7 +655,7 @@ static js2val String_slice(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
|||
start = 0; // XXX argc must be > 1 since the length of the function is 1
|
||||
|
||||
if (argc > 1) {
|
||||
int32 arg1 = meta->engine->toInteger(argv[1]);
|
||||
int32 arg1 = meta->toInteger(argv[1]);
|
||||
if (arg1 < 0) {
|
||||
arg1 += sourceLength;
|
||||
if (arg1 < 0)
|
||||
|
@ -695,20 +702,20 @@ static js2val String_slice(JS2Metadata *meta, const js2val thisValue, js2val *ar
|
|||
|
||||
static js2val String_substring(JS2Metadata *meta, const js2val thisValue, js2val *argv, uint32 argc)
|
||||
{
|
||||
const String *sourceString = meta->engine->toString(thisValue);
|
||||
const String *sourceString = meta->toString(thisValue);
|
||||
|
||||
uint32 sourceLength = sourceString->size();
|
||||
uint32 start, end;
|
||||
|
||||
if (argc > 0) {
|
||||
float64 farg0 = meta->engine->toFloat64(argv[0]);
|
||||
float64 farg0 = meta->toFloat64(argv[0]);
|
||||
if (JSDOUBLE_IS_NaN(farg0) || (farg0 < 0))
|
||||
start = 0;
|
||||
else {
|
||||
if (!JSDOUBLE_IS_FINITE(farg0))
|
||||
start = sourceLength;
|
||||
else {
|
||||
start = meta->engine->toUInt32(farg0);
|
||||
start = JS2Engine::toUInt32(farg0);
|
||||
if (start > sourceLength)
|
||||
start = sourceLength;
|
||||
}
|
||||
|
@ -718,14 +725,14 @@ static js2val String_substring(JS2Metadata *meta, const js2val thisValue, js2val
|
|||
start = 0;
|
||||
|
||||
if (argc > 1) {
|
||||
float64 farg1 = meta->engine->toFloat64(argv[1]);
|
||||
float64 farg1 = meta->toFloat64(argv[1]);
|
||||
if (JSDOUBLE_IS_NaN(farg1) || (farg1 < 0))
|
||||
end = 0;
|
||||
else {
|
||||
if (!JSDOUBLE_IS_FINITE(farg1))
|
||||
end = sourceLength;
|
||||
else {
|
||||
end = meta->engine->toUInt32(farg1);
|
||||
end = JS2Engine::toUInt32(farg1);
|
||||
if (end > sourceLength)
|
||||
end = sourceLength;
|
||||
}
|
||||
|
@ -762,13 +769,11 @@ void initStringObject(JS2Metadata *meta)
|
|||
{ "indexOf", 2, String_indexOf }, // XXX ECMA spec says 1, but tests want 2 XXX
|
||||
{ "lastIndexOf", 2, String_lastIndexOf }, // XXX ECMA spec says 1, but tests want 2 XXX
|
||||
{ "localeCompare", 1, String_localeCompare },
|
||||
#if 0
|
||||
{ "match", 1, String_match },
|
||||
{ "replace", 2, String_replace },
|
||||
{ "search", 1, String_search },
|
||||
{ "slice", 2, String_slice },
|
||||
{ "split", 1, String_split }, // XXX ECMA spec says 2, but tests want 1 XXX
|
||||
#endif
|
||||
{ "substring", 2, String_substring },
|
||||
{ "toSource", 0, String_toString },
|
||||
{ "toLocaleUpperCase", 0, String_toUpperCase }, // (sic)
|
||||
|
|
Загрузка…
Ссылка в новой задаче