Bug 619283 - Built-in JS methods must not box undefined or null into the global object when called, both to comply with ES5 and to prevent inadvertent global object exposure to secure JS variants. r=dmandelin, a=blocking

This commit is contained in:
Jeff Walden 2011-01-26 13:37:45 -08:00
Родитель d19fc49cf0
Коммит 6eedfa38e8
61 изменённых файлов: 1358 добавлений и 616 удалений

Просмотреть файл

@ -6,7 +6,7 @@ function f() {
(eval("\
(function(){\
with(\
__defineGetter__(\"x\", function(){for(a = 0; a < 3; a++){c=a}})\
this.__defineGetter__(\"x\", function(){for(a = 0; a < 3; a++){c=a}})\
){}\
})\
"))()

Просмотреть файл

@ -1,5 +1,5 @@
a = b = c = d = 0;
__defineGetter__("e", function () { throw StopIteration; })
this.__defineGetter__("e", function () { throw StopIteration; })
try {
for each(f in this) {}
} catch (exc) {

Просмотреть файл

@ -1,3 +1,3 @@
__defineGetter__('x', Float32Array);
this.__defineGetter__('x', Float32Array);
with(this)
x;

Просмотреть файл

@ -1,7 +1,7 @@
this.watch("x", Object.create)
try {
(function() {
__defineGetter__("x",
this.__defineGetter__("x",
function() {
return this
})

Просмотреть файл

@ -1,3 +1,3 @@
__defineSetter__("x", function(){});
this.__defineSetter__("x", function(){});
this.watch("x", eval);
x = 0;

Просмотреть файл

@ -10,7 +10,7 @@ function f() {
})\
"))();
}
__defineSetter__("x", eval)
this.__defineSetter__("x", eval)
f()
appendToActual(x);

Просмотреть файл

@ -1 +1 @@
x = __defineSetter__("x", function(z) function() { z })
x = this.__defineSetter__("x", function(z) function() { z })

Просмотреть файл

@ -3,6 +3,6 @@
eval("for(w in ((function(x,y){b:0})())) ;");
})();
__defineSetter__("l", function() { gc() });
this.__defineSetter__("l", function() { gc() });
this.watch("l", function(x) { yield #1={} });
l = true;

Просмотреть файл

@ -2,7 +2,7 @@
Function("\n\
for (a = 0; a < 3; a++) {\n\
if (a == 0) {} else {\n\
__defineSetter__(\"\",1)\n\
this.__defineSetter__(\"\",1)\n\
}\n\
}\n\
")()

Просмотреть файл

@ -1,7 +1,7 @@
// |jit-test| error: InternalError
(function() {
try {
(Function("__defineGetter__(\"x\",(Function(\"for(z=0;z<6;z++)(x)\")))"))()
(Function("this.__defineGetter__(\"x\",(Function(\"for(z=0;z<6;z++)(x)\")))"))()
} catch(e) {}
})()
((function f(d, aaaaaa) {

Просмотреть файл

@ -1,6 +1,6 @@
setDebug(true);
__defineGetter__("someProperty", function () { evalInFrame(1, "var x = 'success'"); });
this.__defineGetter__("someProperty", function () { evalInFrame(1, "var x = 'success'"); });
function caller(obj) {
assertJit();
obj.someProperty;

Просмотреть файл

@ -1,6 +1,6 @@
setDebug(true);
__defineGetter__("someProperty", function () { evalInFrame(1, "var x = 'success'"); });
this.__defineGetter__("someProperty", function () { evalInFrame(1, "var x = 'success'"); });
function caller(obj) {
assertJit();
var x = ({ dana : 'zuul' });

Просмотреть файл

@ -1,6 +1,6 @@
setDebug(true);
__defineGetter__("someProperty", function () { evalInFrame(1, "x = 'success'"); });
this.__defineGetter__("someProperty", function () { evalInFrame(1, "x = 'success'"); });
function caller(obj) {
assertJit();
var x = "failure";

Просмотреть файл

@ -1,7 +1,7 @@
// |jit-test| error: ReferenceError
__defineSetter__("x", function () {})
this.__defineSetter__("x", function () {})
try {
__defineGetter__("d", (Function("x")))
this.__defineGetter__("d", (Function("x")))
} catch (e) {}
d
print(delete x)

Просмотреть файл

@ -1,4 +1,4 @@
__defineSetter__("x",/a/)
this.__defineSetter__("x",/a/)
Function("\
for each(w in[0,0,0]) {\
for each(y in[0,0,0,0,0,0,0,0,x,0,0,0,0,0,0,0,0,0,x,0,0,0,0,0,0,0,x]) {}\

Просмотреть файл

@ -1,4 +1,4 @@
__defineGetter__("x", Float64Array)
this.__defineGetter__("x", Float64Array)
Function("\
with(this) {\
eval(\"x\")\

Просмотреть файл

@ -1,7 +1,7 @@
// vim: set ts=4 sw=4 tw=99 et:
var count = 0;
watch("x", function() {
this.watch("x", function() {
count++;
});
for(var i=0; i<10; i++) {

Просмотреть файл

@ -1955,9 +1955,7 @@ JS_PUBLIC_API(jsval)
JS_ComputeThis(JSContext *cx, jsval *vp)
{
assertSameCompartment(cx, JSValueArray(vp, 2));
if (!ComputeThisFromVp(cx, Valueify(vp)))
return JSVAL_NULL;
return vp[1];
return BoxThisForVp(cx, Valueify(vp)) ? vp[1] : JSVAL_NULL;
}
JS_PUBLIC_API(void *)
@ -4260,11 +4258,7 @@ JS_ObjectIsCallable(JSContext *cx, JSObject *obj)
static JSBool
js_generic_native_method_dispatcher(JSContext *cx, uintN argc, Value *vp)
{
JSFunctionSpec *fs;
JSObject *tmp;
Native native;
fs = (JSFunctionSpec *) vp->toObject().getReservedSlot(0).toPrivate();
JSFunctionSpec *fs = (JSFunctionSpec *) vp->toObject().getReservedSlot(0).toPrivate();
JS_ASSERT((fs->flags & JSFUN_GENERIC_NATIVE) != 0);
if (argc < 1) {
@ -4272,16 +4266,6 @@ js_generic_native_method_dispatcher(JSContext *cx, uintN argc, Value *vp)
return JS_FALSE;
}
if (vp[2].isPrimitive()) {
/*
* Make sure that this is an object or null, as required by the generic
* functions.
*/
if (!js_ValueToObjectOrNull(cx, vp[2], &tmp))
return JS_FALSE;
vp[2].setObjectOrNull(tmp);
}
/*
* Copy all actual (argc) arguments down over our |this| parameter, vp[1],
* which is almost always the class constructor object, e.g. Array. Then
@ -4290,23 +4274,16 @@ js_generic_native_method_dispatcher(JSContext *cx, uintN argc, Value *vp)
*/
memmove(vp + 1, vp + 2, argc * sizeof(jsval));
/*
* Follow Function.prototype.apply and .call by using the global object as
* the 'this' param if no args.
*/
if (!ComputeThisFromArgv(cx, vp + 2))
return JS_FALSE;
/* Clear the last parameter in case too few arguments were passed. */
vp[2 + --argc].setUndefined();
native =
Native native =
#ifdef JS_TRACER
(fs->flags & JSFUN_TRCINFO)
? JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo *, fs->call)->native
:
(fs->flags & JSFUN_TRCINFO)
? JS_FUNC_TO_DATA_PTR(JSNativeTraceInfo *, fs->call)->native
:
#endif
Valueify(fs->call);
Valueify(fs->call);
return native(cx, argc, vp);
}
@ -5037,11 +5014,10 @@ JS_CallFunction(JSContext *cx, JSObject *obj, JSFunction *fun, uintN argc, jsval
jsval *rval)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
JSBool ok;
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, fun, JSValueArray(argv, argc));
ok = ExternalInvoke(cx, obj, ObjectValue(*fun), argc, Valueify(argv), Valueify(rval));
JSBool ok = ExternalInvoke(cx, ObjectOrNullValue(obj), ObjectValue(*fun), argc,
Valueify(argv), Valueify(rval));
LAST_FRAME_CHECKS(cx, ok);
return ok;
}
@ -5056,9 +5032,11 @@ JS_CallFunctionName(JSContext *cx, JSObject *obj, const char *name, uintN argc,
AutoValueRooter tvr(cx);
JSAtom *atom = js_Atomize(cx, name, strlen(name), 0);
JSBool ok = atom &&
js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, tvr.addr()) &&
ExternalInvoke(cx, obj, tvr.value(), argc, Valueify(argv), Valueify(rval));
JSBool ok =
atom &&
js_GetMethod(cx, obj, ATOM_TO_JSID(atom), JSGET_NO_METHOD_BARRIER, tvr.addr()) &&
ExternalInvoke(cx, ObjectOrNullValue(obj), tvr.value(), argc, Valueify(argv),
Valueify(rval));
LAST_FRAME_CHECKS(cx, ok);
return ok;
}
@ -5068,11 +5046,11 @@ JS_CallFunctionValue(JSContext *cx, JSObject *obj, jsval fval, uintN argc, jsval
jsval *rval)
{
JS_THREADSAFE_ASSERT(cx->compartment != cx->runtime->atomsCompartment);
JSBool ok;
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj, fval, JSValueArray(argv, argc));
ok = ExternalInvoke(cx, obj, Valueify(fval), argc, Valueify(argv), Valueify(rval));
JSBool ok = ExternalInvoke(cx, ObjectOrNullValue(obj), Valueify(fval), argc, Valueify(argv),
Valueify(rval));
LAST_FRAME_CHECKS(cx, ok);
return ok;
}

Просмотреть файл

@ -1181,6 +1181,20 @@ JS_THIS(JSContext *cx, jsval *vp)
}
#endif
/*
* |this| is passed to functions in ES5 without change. Functions themselves
* do any post-processing they desire to box |this|, compute the global object,
* &c. Use this macro to retrieve a function's unboxed |this| value.
*
* This macro must not be used in conjunction with JS_THIS or JS_THIS_OBJECT,
* or vice versa. Either use the provided this value with this macro, or
* compute the boxed this value using those.
*
* N.B. constructors must not use JS_THIS_VALUE, as no 'this' object has been
* created.
*/
#define JS_THIS_VALUE(cx,vp) ((vp)[1])
extern JS_PUBLIC_API(void *)
JS_malloc(JSContext *cx, size_t nbytes);

Просмотреть файл

@ -1095,12 +1095,11 @@ array_toSource(JSContext *cx, uintN argc, Value *vp)
{
JS_CHECK_RECURSION(cx, return false);
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj ||
(obj->getClass() != &js_SlowArrayClass &&
!InstanceOf(cx, obj, &js_ArrayClass, vp + 2))) {
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!obj->isSlowArray() && !InstanceOf(cx, obj, &js_ArrayClass, vp + 2))
return false;
}
/* Find joins or cycles in the reachable object graph. */
jschar *sharpchars;
@ -1301,7 +1300,7 @@ array_toString_sub(JSContext *cx, JSObject *obj, JSBool locale,
static JSBool
array_toString(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
@ -1335,7 +1334,7 @@ array_toString(JSContext *cx, uintN argc, Value *vp)
static JSBool
array_toLocaleString(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
@ -1441,17 +1440,22 @@ array_join(JSContext *cx, uintN argc, Value *vp)
return JS_FALSE;
vp[2].setString(str);
}
JSObject *obj = ComputeThisFromVp(cx, vp);
return obj && array_toString_sub(cx, obj, JS_FALSE, str, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
return array_toString_sub(cx, obj, JS_FALSE, str, vp);
}
static JSBool
array_reverse(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
jsuint len;
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj || !js_GetLengthProperty(cx, obj, &len))
return JS_FALSE;
if (!js_GetLengthProperty(cx, obj, &len))
return false;
vp->setObject(*obj);
do {
@ -1462,7 +1466,7 @@ array_reverse(JSContext *cx, uintN argc, Value *vp)
/* An empty array or an array with no elements is already reversed. */
if (len == 0 || obj->getDenseArrayCapacity() == 0)
return JS_TRUE;
return true;
/*
* It's actually surprisingly complicated to reverse an array due to the
@ -1759,8 +1763,10 @@ js::array_sort(JSContext *cx, uintN argc, Value *vp)
fval.setNull();
}
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj || !js_GetLengthProperty(cx, obj, &len))
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!js_GetLengthProperty(cx, obj, &len))
return false;
if (len == 0) {
vp->setObject(*obj);
@ -2077,10 +2083,11 @@ JS_DEFINE_CALLINFO_3(extern, BOOL_FAIL, js_ArrayCompPush_tn, CONTEXT, OBJECT,
static JSBool
array_push(JSContext *cx, uintN argc, Value *vp)
{
/* Insist on one argument and obj of the expected class. */
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return JS_FALSE;
return false;
/* Insist on one argument and obj of the expected class. */
if (argc != 1 || !obj->isDenseArray())
return array_push_slowly(cx, obj, argc, vp + 2, vp);
@ -2132,9 +2139,9 @@ array_pop_dense(JSContext *cx, JSObject* obj, Value *vp)
static JSBool
array_pop(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return JS_FALSE;
return false;
if (obj->isDenseArray())
return array_pop_dense(cx, obj, vp);
return array_pop_slowly(cx, obj, vp);
@ -2143,11 +2150,12 @@ array_pop(JSContext *cx, uintN argc, Value *vp)
static JSBool
array_shift(JSContext *cx, uintN argc, Value *vp)
{
jsuint length, i;
JSBool hole;
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return JS_FALSE;
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj || !js_GetLengthProperty(cx, obj, &length))
jsuint length;
if (!js_GetLengthProperty(cx, obj, &length))
return JS_FALSE;
if (length == 0) {
@ -2170,12 +2178,13 @@ array_shift(JSContext *cx, uintN argc, Value *vp)
}
/* Get the to-be-deleted property's value into vp ASAP. */
JSBool hole;
if (!GetElement(cx, obj, 0, &hole, vp))
return JS_FALSE;
/* Slide down the array above the first element. */
AutoValueRooter tvr(cx);
for (i = 0; i != length; i++) {
for (jsuint i = 0; i < length; i++) {
if (!JS_CHECK_OPERATION_LIMIT(cx) ||
!GetElement(cx, obj, i + 1, &hole, tvr.addr()) ||
!SetOrDeleteArrayElement(cx, obj, i, hole, tvr.value())) {
@ -2194,12 +2203,15 @@ static JSBool
array_unshift(JSContext *cx, uintN argc, Value *vp)
{
Value *argv;
jsuint length;
JSBool hole;
jsdouble last, newlen;
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj || !js_GetLengthProperty(cx, obj, &length))
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
jsuint length;
if (!js_GetLengthProperty(cx, obj, &length))
return JS_FALSE;
newlen = length;
if (argc > 0) {
@ -2258,15 +2270,14 @@ array_unshift(JSContext *cx, uintN argc, Value *vp)
static JSBool
array_splice(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
jsuint length, begin, end, count, delta, last;
JSBool hole;
/*
* Create a new array value to return. Our ECMA v2 proposal specs
* that splice always returns an array value, even when given no
* arguments. We think this is best because it eliminates the need
* for callers to do an extra test to handle the empty splice case.
*/
/* Create a new array value to return. */
JSObject *obj2 = NewDenseEmptyArray(cx);
if (!obj2)
return JS_FALSE;
@ -2276,8 +2287,7 @@ array_splice(JSContext *cx, uintN argc, Value *vp)
if (argc == 0)
return JS_TRUE;
Value *argv = JS_ARGV(cx, vp);
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj || !js_GetLengthProperty(cx, obj, &length))
if (!js_GetLengthProperty(cx, obj, &length))
return JS_FALSE;
jsuint origlength = length;
@ -2428,7 +2438,10 @@ array_concat(JSContext *cx, uintN argc, Value *vp)
Value *p = JS_ARGV(cx, vp) - 1;
/* Create a new Array object and root it using *vp. */
JSObject *aobj = ComputeThisFromVp(cx, vp);
JSObject *aobj = ToObject(cx, &vp[1]);
if (!aobj)
return false;
JSObject *nobj;
jsuint length;
if (aobj->isDenseArray()) {
@ -2513,8 +2526,11 @@ array_slice(JSContext *cx, uintN argc, Value *vp)
argv = JS_ARGV(cx, vp);
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj || !js_GetLengthProperty(cx, obj, &length))
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!js_GetLengthProperty(cx, obj, &length))
return JS_FALSE;
begin = 0;
end = length;
@ -2589,8 +2605,10 @@ array_indexOfHelper(JSContext *cx, JSBool isLast, uintN argc, Value *vp)
jsint direction;
JSBool hole;
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj || !js_GetLengthProperty(cx, obj, &length))
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!js_GetLengthProperty(cx, obj, &length))
return JS_FALSE;
if (length == 0)
goto not_found;
@ -2683,9 +2701,12 @@ typedef enum ArrayExtraMode {
static JSBool
array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
jsuint length;
if (!obj || !js_GetLengthProperty(cx, obj, &length))
if (!js_GetLengthProperty(cx, obj, &length))
return JS_FALSE;
/*

Просмотреть файл

@ -1403,6 +1403,15 @@ GetAndCacheLocalTime(JSContext *cx, JSObject *obj, Value *vp, jsdouble *time = N
return true;
}
static inline bool
GetThisUTCTime(JSContext *cx, Value *vp, jsdouble *dp)
{
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
return GetUTCTime(cx, obj, vp, dp);
}
/*
* See ECMA 15.9.5.4 thru 15.9.5.23
*/
@ -1410,19 +1419,21 @@ static JSBool
date_getTime(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getYear(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
Value yearVal = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_YEAR);
if (yearVal.isInt32()) {
@ -1433,13 +1444,16 @@ date_getYear(JSContext *cx, uintN argc, Value *vp)
*vp = yearVal;
}
return JS_TRUE;
return true;
}
static JSBool
date_getFullYear(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
@ -1451,113 +1465,120 @@ static JSBool
date_getUTCFullYear(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = YearFromTime(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getMonth(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MONTH);
return JS_TRUE;
return true;
}
static JSBool
date_getUTCMonth(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = MonthFromTime(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getDate(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DATE);
return JS_TRUE;
return true;
}
static JSBool
date_getUTCDate(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = DateFromTime(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getDay(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_DAY);
return JS_TRUE;
return true;
}
static JSBool
date_getUTCDay(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = WeekDay(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getHours(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_HOURS);
return JS_TRUE;
return true;
}
static JSBool
date_getUTCHours(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = HourFromTime(result);
@ -1569,27 +1590,29 @@ date_getUTCHours(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_getMinutes(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_MINUTES);
return JS_TRUE;
return true;
}
static JSBool
date_getUTCMinutes(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = MinFromTime(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
/* Date.getSeconds is mapped to getUTCSeconds */
@ -1597,12 +1620,15 @@ date_getUTCMinutes(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_getUTCSeconds(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetAndCacheLocalTime(cx, obj, vp))
return JS_FALSE;
return false;
*vp = obj->getSlot(JSObject::JSSLOT_DATE_LOCAL_SECONDS);
return JS_TRUE;
return true;
}
/* Date.getMilliseconds is mapped to getUTCMilliseconds */
@ -1611,43 +1637,48 @@ static JSBool
date_getUTCMilliseconds(JSContext *cx, uintN argc, Value *vp)
{
jsdouble result;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &result))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &result))
return false;
if (JSDOUBLE_IS_FINITE(result))
result = msFromTime(result);
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_getTimezoneOffset(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj;
jsdouble utctime, localtime, result;
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
obj = ComputeThisFromVp(cx, vp);
jsdouble utctime;
if (!GetUTCTime(cx, obj, vp, &utctime))
return JS_FALSE;
return false;
jsdouble localtime;
if (!GetAndCacheLocalTime(cx, obj, NULL, &localtime))
return JS_FALSE;
return false;
/*
* Return the time zone offset in minutes for the current locale that is
* appropriate for this time. This value would be a constant except for
* daylight savings time.
*/
result = (utctime - localtime) / msPerMinute;
jsdouble result = (utctime - localtime) / msPerMinute;
vp->setNumber(result);
return JS_TRUE;
return true;
}
static JSBool
date_setTime(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!InstanceOf(cx, obj, &js_DateClass, vp + 2))
return false;
@ -1666,7 +1697,6 @@ date_setTime(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
{
JSObject *obj;
Value *argv;
uintN i;
jsdouble args[4], *argp, *stop;
@ -1676,7 +1706,10 @@ date_makeTime(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
jsdouble msec_time;
jsdouble result;
obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetUTCTime(cx, obj, vp, &result))
return false;
@ -1805,7 +1838,6 @@ date_setUTCHours(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
{
JSObject *obj;
Value *argv;
uintN i;
jsdouble lorutime; /* local or UTC version of *date */
@ -1813,7 +1845,10 @@ date_makeDate(JSContext *cx, uintN maxargs, JSBool local, uintN argc, Value *vp)
jsdouble year, month, day;
jsdouble result;
obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!GetUTCTime(cx, obj, vp, &result))
return false;
@ -1914,7 +1949,9 @@ date_setUTCFullYear(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_setYear(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
jsdouble result;
if (!GetUTCTime(cx, obj, vp, &result))
@ -1989,23 +2026,21 @@ static JSBool
date_utc_format(JSContext *cx, Value *vp,
void (*printFunc)(char*, size_t, jsdouble))
{
char buf[100];
JSString *str;
jsdouble utctime;
if (!GetThisUTCTime(cx, vp, &utctime))
return false;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(utctime)) {
char buf[100];
if (!JSDOUBLE_IS_FINITE(utctime))
JS_snprintf(buf, sizeof buf, js_NaN_date_str);
} else {
else
(*printFunc)(buf, sizeof buf, utctime);
}
str = JS_NewStringCopyZ(cx, buf);
JSString *str = JS_NewStringCopyZ(cx, buf);
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
return JS_TRUE;
return true;
}
static JSBool
@ -2025,7 +2060,7 @@ static JSBool
date_toJSON(JSContext *cx, uintN argc, Value *vp)
{
/* Step 1. */
JSObject *obj = js_ValueToNonNullObject(cx, vp[1]);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
@ -2208,17 +2243,15 @@ date_format(JSContext *cx, jsdouble date, formatspec format, Value *rval)
}
static JSBool
date_toLocaleHelper(JSContext *cx, const char *format, Value *vp)
date_toLocaleHelper(JSContext *cx, JSObject *obj, const char *format, Value *vp)
{
JSObject *obj;
char buf[100];
JSString *str;
PRMJTime split;
jsdouble utctime;
obj = ComputeThisFromVp(cx, vp);
if (!GetUTCTime(cx, obj, vp, &utctime))
return JS_FALSE;
return false;
if (!JSDOUBLE_IS_FINITE(utctime)) {
JS_snprintf(buf, sizeof buf, js_NaN_date_str);
@ -2254,19 +2287,23 @@ date_toLocaleHelper(JSContext *cx, const char *format, Value *vp)
str = JS_NewStringCopyZ(cx, buf);
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
return JS_TRUE;
return true;
}
static JSBool
date_toLocaleString(JSContext *cx, uintN argc, Value *vp)
{
/* Use '%#c' for windows, because '%c' is
* backward-compatible and non-y2k with msvc; '%#c' requests that a
* full year be used in the result string.
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
/*
* Use '%#c' for windows, because '%c' is backward-compatible and non-y2k
* with msvc; '%#c' requests that a full year be used in the result string.
*/
return date_toLocaleHelper(cx,
return date_toLocaleHelper(cx, obj,
#if defined(_WIN32) && !defined(__MWERKS__)
"%#c"
#else
@ -2278,11 +2315,15 @@ date_toLocaleString(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_toLocaleDateString(JSContext *cx, uintN argc, Value *vp)
{
/* Use '%#x' for windows, because '%x' is
* backward-compatible and non-y2k with msvc; '%#x' requests that a
* full year be used in the result string.
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
/*
* Use '%#x' for windows, because '%x' is backward-compatible and non-y2k
* with msvc; '%#x' requests that a full year be used in the result string.
*/
return date_toLocaleHelper(cx,
return date_toLocaleHelper(cx, obj,
#if defined(_WIN32) && !defined(__MWERKS__)
"%#x"
#else
@ -2294,7 +2335,11 @@ date_toLocaleDateString(JSContext *cx, uintN argc, Value *vp)
static JSBool
date_toLocaleTimeString(JSContext *cx, uintN argc, Value *vp)
{
return date_toLocaleHelper(cx, "%X", vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
return date_toLocaleHelper(cx, obj, "%X", vp);
}
static JSBool
@ -2303,24 +2348,27 @@ date_toLocaleFormat(JSContext *cx, uintN argc, Value *vp)
if (argc == 0)
return date_toLocaleString(cx, argc, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
JSString *fmt = js_ValueToString(cx, vp[2]);
if (!fmt)
return JS_FALSE;
return false;
vp[2].setString(fmt);
JSAutoByteString fmtbytes(cx, fmt);
if (!fmtbytes)
return JS_FALSE;
return false;
return date_toLocaleHelper(cx, fmtbytes.ptr(), vp);
return date_toLocaleHelper(cx, obj, fmtbytes.ptr(), vp);
}
static JSBool
date_toTimeString(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &utctime))
return false;
return date_format(cx, utctime, FORMATSPEC_TIME, vp);
}
@ -2328,9 +2376,8 @@ static JSBool
date_toDateString(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &utctime))
return false;
return date_format(cx, utctime, FORMATSPEC_DATE, vp);
}
@ -2342,31 +2389,28 @@ static JSBool
date_toSource(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
char *numStr, *bytes;
JSString *str;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
if (!GetThisUTCTime(cx, vp, &utctime))
return false;
ToCStringBuf cbuf;
numStr = NumberToCString(cx, &cbuf, utctime);
char *numStr = NumberToCString(cx, &cbuf, utctime);
if (!numStr) {
JS_ReportOutOfMemory(cx);
return JS_FALSE;
return false;
}
bytes = JS_smprintf("(new %s(%s))", js_Date_str, numStr);
char *bytes = JS_smprintf("(new %s(%s))", js_Date_str, numStr);
if (!bytes) {
JS_ReportOutOfMemory(cx);
return JS_FALSE;
return false;
}
str = JS_NewStringCopyZ(cx, bytes);
JSString *str = JS_NewStringCopyZ(cx, bytes);
js_free(bytes);
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
return JS_TRUE;
return true;
}
#endif
@ -2374,16 +2418,17 @@ static JSBool
date_toString(JSContext *cx, uintN argc, Value *vp)
{
jsdouble utctime;
if (!GetThisUTCTime(cx, vp, &utctime))
return false;
if (!GetUTCTime(cx, ComputeThisFromVp(cx, vp), vp, &utctime))
return JS_FALSE;
return date_format(cx, utctime, FORMATSPEC_FULL, vp);
}
static JSBool
date_valueOf(JSContext *cx, uintN argc, Value *vp)
{
/* It is an error to call date_valueOf on a non-date object, but we don't
/*
* It is an error to call date_valueOf on a non-date object, but we don't
* need to check for that explicitly here because every path calls
* GetUTCTime, which does the check.
*/
@ -2392,13 +2437,18 @@ date_valueOf(JSContext *cx, uintN argc, Value *vp)
if (argc == 0)
return date_getTime(cx, argc, vp);
/* Verify this before extracting a string from the first argument. */
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
/* Convert to number only if the hint was given, otherwise favor string. */
JSString *str = js_ValueToString(cx, vp[2]);
if (!str)
return JS_FALSE;
return false;
JSLinearString *linear_str = str->ensureLinear(cx);
if (!linear_str)
return JS_FALSE;
return false;
JSAtom *number_str = cx->runtime->atomState.typeAtoms[JSTYPE_NUMBER];
if (EqualStrings(linear_str, number_str))
return date_getTime(cx, argc, vp);

Просмотреть файл

@ -737,7 +737,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsid id, Value *vp)
*/
JSBool ok = !wp->setter ||
(shape->hasSetterValue()
? ExternalInvoke(cx, obj,
? ExternalInvoke(cx, ObjectValue(*obj),
ObjectValue(*CastAsObject(wp->setter)),
1, vp, vp)
: CallJSPropertyOpSetter(cx, wp->setter, obj, userid, vp));
@ -753,7 +753,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsid id, Value *vp)
static JSBool
js_watch_set_wrapper(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;

Просмотреть файл

@ -788,14 +788,15 @@ Exception(JSContext *cx, uintN argc, Value *vp)
static JSBool
exn_toString(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj;
jsval v;
JSString *name, *message, *result;
jschar *chars, *cp;
size_t name_length, message_length, length;
obj = ComputeThisFromVp(cx, vp);
if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), Valueify(&v)))
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return JS_FALSE;
if (!obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), Valueify(&v)))
return JS_FALSE;
name = JSVAL_IS_STRING(v) ? JSVAL_TO_STRING(v) : cx->runtime->emptyString;
vp->setString(name);
@ -848,14 +849,15 @@ exn_toString(JSContext *cx, uintN argc, Value *vp)
static JSBool
exn_toSource(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj;
JSString *name, *message, *filename, *lineno_as_str, *result;
jsval localroots[3] = {JSVAL_NULL, JSVAL_NULL, JSVAL_NULL};
size_t lineno_length, name_length, message_length, filename_length, length;
jschar *chars, *cp;
obj = ComputeThisFromVp(cx, vp);
if (!obj || !obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), vp))
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!obj->getProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.nameAtom), vp))
return false;
name = js_ValueToString(cx, *vp);
if (!name)

Просмотреть файл

@ -2051,7 +2051,7 @@ fun_toString(JSContext *cx, uintN argc, Value *vp)
if (argc != 0 && !ValueToECMAUint32(cx, vp[2], &indent))
return false;
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
@ -2069,7 +2069,7 @@ fun_toSource(JSContext *cx, uintN argc, Value *vp)
{
JS_ASSERT(IsFunctionObject(vp[0]));
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
@ -2086,15 +2086,10 @@ JSBool
js_fun_call(JSContext *cx, uintN argc, Value *vp)
{
LeaveTrace(cx);
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj)
return JS_FALSE;
Value fval = vp[1];
if (!js_IsCallable(fval)) {
JSString *str = js_ValueToString(cx, fval);
if (str) {
if (JSString *str = js_ValueToString(cx, fval)) {
JSAutoByteString bytes(cx, str);
if (!!bytes) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
@ -2103,7 +2098,7 @@ js_fun_call(JSContext *cx, uintN argc, Value *vp)
bytes.ptr());
}
}
return JS_FALSE;
return false;
}
Value *argv = vp + 2;
@ -2136,10 +2131,6 @@ js_fun_call(JSContext *cx, uintN argc, Value *vp)
JSBool
js_fun_apply(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj)
return false;
/* Step 1. */
Value fval = vp[1];
if (!js_IsCallable(fval)) {
@ -2314,13 +2305,11 @@ static JSBool
fun_bind(JSContext *cx, uintN argc, Value *vp)
{
/* Step 1. */
JSObject *target = ComputeThisFromVp(cx, vp);
if (!target)
return false;
Value &thisv = vp[1];
/* Step 2. */
if (!target->isCallable()) {
if (JSString *str = js_ValueToString(cx, vp[1])) {
if (!js_IsCallable(thisv)) {
if (JSString *str = js_ValueToString(cx, thisv)) {
JSAutoByteString bytes(cx, str);
if (!!bytes) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
@ -2331,6 +2320,8 @@ fun_bind(JSContext *cx, uintN argc, Value *vp)
return false;
}
JSObject *target = &thisv.toObject();
/* Step 3. */
Value *args = NULL;
uintN argslen = 0;

Просмотреть файл

@ -455,12 +455,12 @@ CallThisObjectHook(JSContext *cx, JSObject *obj, Value *argv)
* The alert should display "true".
*/
JS_STATIC_INTERPRET bool
ComputeGlobalThis(JSContext *cx, Value *argv)
ComputeGlobalThis(JSContext *cx, Value *vp)
{
JSObject *thisp = argv[-2].toObject().getGlobal()->thisObject(cx);
JSObject *thisp = vp[0].toObject().getGlobal()->thisObject(cx);
if (!thisp)
return false;
argv[-1].setObject(*thisp);
vp[1].setObject(*thisp);
return true;
}
@ -508,21 +508,25 @@ ReportIncompatibleMethod(JSContext *cx, Value *vp, Class *clasp)
}
bool
ComputeThisFromArgv(JSContext *cx, Value *argv)
BoxThisForVp(JSContext *cx, Value *vp)
{
/*
* Check for SynthesizeFrame poisoning and fast constructors which
* didn't check their vp properly.
*/
JS_ASSERT(!argv[-1].isMagic());
JS_ASSERT(!vp[1].isMagic());
#ifdef DEBUG
JSFunction *fun = vp[0].toObject().isFunction() ? vp[0].toObject().getFunctionPrivate() : NULL;
JS_ASSERT_IF(fun && fun->isInterpreted(), !fun->inStrictMode());
#endif
if (argv[-1].isNullOrUndefined())
return ComputeGlobalThis(cx, argv);
if (vp[1].isNullOrUndefined())
return ComputeGlobalThis(cx, vp);
if (!argv[-1].isObject())
return !!js_PrimitiveToObject(cx, &argv[-1]);
if (!vp[1].isObject())
return !!js_PrimitiveToObject(cx, &vp[1]);
JS_ASSERT(IsSaneThisObject(argv[-1].toObject()));
JS_ASSERT(IsSaneThisObject(vp[1].toObject()));
return true;
}
@ -895,7 +899,7 @@ ExternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, const Value &fval,
*/
JS_CHECK_RECURSION(cx, return JS_FALSE);
return ExternalInvoke(cx, obj, fval, argc, argv, rval);
return ExternalInvoke(cx, ObjectValue(*obj), fval, argc, argv, rval);
}
bool

Просмотреть файл

@ -841,27 +841,13 @@ inline void
PutActivationObjects(JSContext *cx, JSStackFrame *fp);
/*
* For a call with arguments argv including argv[-1] (nominal |this|) and
* argv[-2] (callee) replace null |this| with callee's parent and replace
* primitive values with the equivalent wrapper objects. argv[-1] must
* not be JSVAL_VOID or an activation object.
* For a call's vp (which necessarily includes callee at vp[0] and the original
* specified |this| at vp[1]), convert null/undefined |this| into the global
* object for the callee and replace other primitives with boxed versions. The
* callee must not be strict mode code.
*/
extern bool
ComputeThisFromArgv(JSContext *cx, js::Value *argv);
JS_ALWAYS_INLINE JSObject *
ComputeThisFromVp(JSContext *cx, js::Value *vp)
{
extern bool ComputeThisFromArgv(JSContext *, js::Value *);
return ComputeThisFromArgv(cx, vp + 2) ? &vp[1].toObject() : NULL;
}
JS_ALWAYS_INLINE bool
ComputeThisFromVpInPlace(JSContext *cx, js::Value *vp)
{
extern bool ComputeThisFromArgv(JSContext *, js::Value *);
return ComputeThisFromArgv(cx, vp + 2);
}
BoxThisForVp(JSContext *cx, js::Value *vp);
/*
* Abstracts the layout of the stack passed to natives from the engine and from
@ -882,10 +868,6 @@ struct CallArgs
Value *argv() const { return argv_; }
uintN argc() const { return argc_; }
Value &rval() const { return argv_[-2]; }
bool computeThis(JSContext *cx) const {
return ComputeThisFromArgv(cx, argv_);
}
};
/*
@ -954,13 +936,6 @@ extern bool
ExternalInvoke(JSContext *cx, const Value &thisv, const Value &fval,
uintN argc, Value *argv, Value *rval);
static JS_ALWAYS_INLINE bool
ExternalInvoke(JSContext *cx, JSObject *obj, const Value &fval,
uintN argc, Value *argv, Value *rval)
{
return ExternalInvoke(cx, ObjectOrNullValue(obj), fval, argc, argv, rval);
}
extern bool
ExternalGetOrSet(JSContext *cx, JSObject *obj, jsid id, const Value &fval,
JSAccessMode mode, uintN argc, Value *argv, Value *rval);

Просмотреть файл

@ -372,7 +372,7 @@ JSStackFrame::computeThis(JSContext *cx)
*/
JS_ASSERT(!isEvalFrame());
}
if (!js::ComputeThisFromArgv(cx, &thisv + 1))
if (!js::BoxThisForVp(cx, &thisv - 1))
return NULL;
JS_ASSERT(IsSaneThisObject(thisv.toObject()));
return &thisv.toObject();
@ -662,13 +662,7 @@ GetPrimitiveThis(JSContext *cx, Value *vp, T *v)
return true;
}
if (thisv.isObjectOrNull()) {
JSObject *obj = thisv.toObjectOrNull();
if (!obj || obj->getClass() != Behavior::getClass()) {
obj = ComputeThisFromVp(cx, vp);
if (!InstanceOf(cx, obj, Behavior::getClass(), vp + 2))
return false;
}
if (thisv.isObject() && thisv.toObject().getClass() == Behavior::getClass()) {
*v = Behavior::extract(thisv.toObject().getPrimitiveThis());
return true;
}

Просмотреть файл

@ -375,7 +375,7 @@ GetCustomIterator(JSContext *cx, JSObject *obj, uintN flags, Value *vp)
/* Otherwise call it and return that object. */
LeaveTrace(cx);
Value arg = BooleanValue((flags & JSITER_FOREACH) == 0);
if (!ExternalInvoke(cx, obj, *vp, 1, &arg, vp))
if (!ExternalInvoke(cx, ObjectValue(*obj), *vp, 1, &arg, vp))
return false;
if (vp->isPrimitive()) {
/*
@ -710,10 +710,8 @@ js_ThrowStopIteration(JSContext *cx)
static JSBool
iterator_next(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj;
obj = ComputeThisFromVp(cx, vp);
if (!InstanceOf(cx, obj, &js_IteratorClass, vp + 2))
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj || !InstanceOf(cx, obj, &js_IteratorClass, vp + 2))
return false;
if (!js_IteratorMore(cx, obj, vp))
@ -953,7 +951,7 @@ js_IteratorMore(JSContext *cx, JSObject *iterobj, Value *rval)
jsid id = ATOM_TO_JSID(cx->runtime->atomState.nextAtom);
if (!js_GetMethod(cx, iterobj, id, JSGET_METHOD_BARRIER, rval))
return false;
if (!ExternalInvoke(cx, iterobj, *rval, 0, NULL, rval)) {
if (!ExternalInvoke(cx, ObjectValue(*iterobj), *rval, 0, NULL, rval)) {
/* Check for StopIteration. */
if (!cx->isExceptionPending() || !js_ValueIsStopIteration(cx->getPendingException()))
return false;
@ -1339,11 +1337,10 @@ CloseGenerator(JSContext *cx, JSObject *obj)
static JSBool
generator_op(JSContext *cx, JSGeneratorOp op, Value *vp, uintN argc)
{
JSObject *obj;
LeaveTrace(cx);
obj = ComputeThisFromVp(cx, vp);
if (!InstanceOf(cx, obj, &js_GeneratorClass, vp + 2))
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj || !InstanceOf(cx, obj, &js_GeneratorClass, vp + 2))
return JS_FALSE;
JSGenerator *gen = (JSGenerator *) obj->getPrivate();

Просмотреть файл

@ -472,8 +472,7 @@ js_TraceSharpMap(JSTracer *trc, JSSharpObjectMap *map)
static JSBool
obj_toSource(JSContext *cx, uintN argc, Value *vp)
{
JSBool ok, outermost;
JSObject *obj;
JSBool ok;
JSHashEntry *he;
JSIdArray *ida;
jschar *chars, *ochars, *vsharp;
@ -494,9 +493,13 @@ obj_toSource(JSContext *cx, uintN argc, Value *vp)
AutoArrayRooter tvr(cx, JS_ARRAY_LENGTH(localroot), localroot);
/* If outermost, we need parentheses to be an expression, not a block. */
outermost = (cx->sharpObjectMap.depth == 0);
obj = ComputeThisFromVp(cx, vp);
if (!obj || !(he = js_EnterSharpObject(cx, obj, &ida, &chars))) {
JSBool outermost = (cx->sharpObjectMap.depth == 0);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!(he = js_EnterSharpObject(cx, obj, &ida, &chars))) {
ok = JS_FALSE;
goto out;
}
@ -850,24 +853,25 @@ obj_toString(JSContext *cx, uintN argc, Value *vp)
{
Value &thisv = vp[1];
/* ES5 15.2.4.2 step 1. */
/* Step 1. */
if (thisv.isUndefined()) {
vp->setString(ATOM_TO_STRING(cx->runtime->atomState.objectUndefinedAtom));
return true;
}
/* ES5 15.2.4.2 step 2. */
/* Step 2. */
if (thisv.isNull()) {
vp->setString(ATOM_TO_STRING(cx->runtime->atomState.objectNullAtom));
return true;
}
/* ES5 15.2.4.2 step 3. */
if (!thisv.isObject() && !js_PrimitiveToObject(cx, &thisv))
/* Step 3. */
JSObject *obj = ToObject(cx, &thisv);
if (!obj)
return false;
/* ES5 15.2.4.2 steps 4-5. */
JSString *str = js::obj_toStringHelper(cx, &thisv.toObject());
/* Steps 4-5. */
JSString *str = js::obj_toStringHelper(cx, obj);
if (!str)
return false;
vp->setString(str);
@ -877,10 +881,11 @@ obj_toString(JSContext *cx, uintN argc, Value *vp)
static JSBool
obj_toLocaleString(JSContext *cx, uintN argc, Value *vp)
{
if (!ComputeThisFromVp(cx, vp))
return JS_FALSE;
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
JSString *str = js_ValueToString(cx, vp[1]);
JSString *str = js_ValueToString(cx, ObjectValue(*obj));
if (!str)
return JS_FALSE;
@ -891,10 +896,11 @@ obj_toLocaleString(JSContext *cx, uintN argc, Value *vp)
static JSBool
obj_valueOf(JSContext *cx, uintN argc, Value *vp)
{
if (!ComputeThisFromVp(cx, vp))
return JS_FALSE;
*vp = vp[1];
return JS_TRUE;
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
vp->setObject(*obj);
return true;
}
/*
@ -1340,7 +1346,8 @@ obj_watch_handler(JSContext *cx, JSObject *obj, jsid id, jsval old,
argv[0] = IdToValue(id);
argv[1] = Valueify(old);
argv[2] = Valueify(*nvp);
ok = ExternalInvoke(cx, obj, ObjectOrNullValue(callable), 3, argv, Valueify(nvp));
ok = ExternalInvoke(cx, ObjectValue(*obj), ObjectOrNullValue(callable), 3, argv,
Valueify(nvp));
js_StopResolving(cx, &key, JSRESFLAG_WATCH, entry, generation);
return ok;
}
@ -1362,10 +1369,13 @@ obj_watch(JSContext *cx, uintN argc, Value *vp)
if (!ValueToId(cx, vp[2], &propid))
return JS_FALSE;
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
Value tmp;
uintN attrs;
if (!obj || !CheckAccess(cx, obj, propid, JSACC_WATCH, &tmp, &attrs))
if (!CheckAccess(cx, obj, propid, JSACC_WATCH, &tmp, &attrs))
return JS_FALSE;
vp->setUndefined();
@ -1380,9 +1390,9 @@ obj_watch(JSContext *cx, uintN argc, Value *vp)
static JSBool
obj_unwatch(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return JS_FALSE;
return false;
vp->setUndefined();
jsid id;
if (argc != 0) {
@ -1405,9 +1415,10 @@ obj_unwatch(JSContext *cx, uintN argc, Value *vp)
static JSBool
obj_hasOwnProperty(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
return obj &&
js_HasOwnPropertyHelper(cx, obj->getOps()->lookupProperty, argc, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
return js_HasOwnPropertyHelper(cx, obj->getOps()->lookupProperty, argc, vp);
}
JSBool
@ -1418,11 +1429,11 @@ js_HasOwnPropertyHelper(JSContext *cx, LookupPropOp lookup, uintN argc,
if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), &id))
return JS_FALSE;
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj2;
JSProperty *prop;
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
JSObject *obj2;
JSProperty *prop;
if (obj->isProxy()) {
bool has;
if (!JSProxy::hasOwn(cx, obj, id, &has))
@ -1484,28 +1495,42 @@ js_HasOwnProperty(JSContext *cx, LookupPropOp lookup, JSObject *obj, jsid id,
return true;
}
/* Proposed ECMA 15.2.4.6. */
/* ES5 15.2.4.6. */
static JSBool
obj_isPrototypeOf(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
/* Step 1. */
if (argc < 1 || !vp[2].isObject()) {
vp->setBoolean(false);
return true;
}
/* Step 2. */
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return JS_FALSE;
const Value &v = argc != 0 ? vp[2] : UndefinedValue();
vp->setBoolean(js_IsDelegate(cx, obj, v));
return JS_TRUE;
return false;
/* Step 3. */
vp->setBoolean(js_IsDelegate(cx, obj, vp[2]));
return true;
}
/* Proposed ECMA 15.2.4.7. */
/* ES5 15.2.4.7. */
static JSBool
obj_propertyIsEnumerable(JSContext *cx, uintN argc, Value *vp)
{
/* Step 1. */
jsid id;
if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), &id))
return JS_FALSE;
return false;
JSObject *obj = ComputeThisFromVp(cx, vp);
return obj && js_PropertyIsEnumerable(cx, obj, id, vp);
/* Step 2. */
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
/* Steps 3-5. */
return js_PropertyIsEnumerable(cx, obj, id, vp);
}
JSBool
@ -1561,6 +1586,10 @@ const char js_lookupSetter_str[] = "__lookupSetter__";
JS_FRIEND_API(JSBool)
js_obj_defineGetter(JSContext *cx, uintN argc, Value *vp)
{
if (!BoxThisForVp(cx, vp))
return false;
JSObject *obj = &vp[1].toObject();
if (argc <= 1 || !js_IsCallable(vp[3])) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_GETTER_OR_SETTER,
@ -1572,8 +1601,7 @@ js_obj_defineGetter(JSContext *cx, uintN argc, Value *vp)
jsid id;
if (!ValueToId(cx, vp[2], &id))
return JS_FALSE;
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj || !CheckRedeclaration(cx, obj, id, JSPROP_GETTER, NULL, NULL))
if (!CheckRedeclaration(cx, obj, id, JSPROP_GETTER, NULL, NULL))
return JS_FALSE;
/*
* Getters and setters are just like watchpoints from an access
@ -1591,6 +1619,10 @@ js_obj_defineGetter(JSContext *cx, uintN argc, Value *vp)
JS_FRIEND_API(JSBool)
js_obj_defineSetter(JSContext *cx, uintN argc, Value *vp)
{
if (!BoxThisForVp(cx, vp))
return false;
JSObject *obj = &vp[1].toObject();
if (argc <= 1 || !js_IsCallable(vp[3])) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BAD_GETTER_OR_SETTER,
@ -1602,8 +1634,7 @@ js_obj_defineSetter(JSContext *cx, uintN argc, Value *vp)
jsid id;
if (!ValueToId(cx, vp[2], &id))
return JS_FALSE;
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj || !CheckRedeclaration(cx, obj, id, JSPROP_SETTER, NULL, NULL))
if (!CheckRedeclaration(cx, obj, id, JSPROP_SETTER, NULL, NULL))
return JS_FALSE;
/*
* Getters and setters are just like watchpoints from an access
@ -1624,10 +1655,12 @@ obj_lookupGetter(JSContext *cx, uintN argc, Value *vp)
jsid id;
if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), &id))
return JS_FALSE;
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return JS_FALSE;
JSObject *pobj;
JSProperty *prop;
if (!obj || !obj->lookupProperty(cx, id, &pobj, &prop))
if (!obj->lookupProperty(cx, id, &pobj, &prop))
return JS_FALSE;
vp->setUndefined();
if (prop) {
@ -1646,10 +1679,12 @@ obj_lookupSetter(JSContext *cx, uintN argc, Value *vp)
jsid id;
if (!ValueToId(cx, argc != 0 ? vp[2] : UndefinedValue(), &id))
return JS_FALSE;
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return JS_FALSE;
JSObject *pobj;
JSProperty *prop;
if (!obj || !obj->lookupProperty(cx, id, &pobj, &prop))
if (!obj->lookupProperty(cx, id, &pobj, &prop))
return JS_FALSE;
vp->setUndefined();
if (prop) {
@ -5863,28 +5898,6 @@ HasNativeMethod(JSObject *obj, jsid methodid, Native native)
return funobj;
}
/*
* When we have an object of a builtin class, we don't quite know what its
* valueOf/toString methods are, since these methods may have been overwritten
* or shadowed. However, we can still do better than js_TryMethod by
* hard-coding the necessary properties for us to find the native we expect.
*
* TODO: a per-thread shape-based cache would be faster and simpler.
*/
static JS_ALWAYS_INLINE bool
ClassMethodIsNative(JSContext *cx, JSObject *obj, Class *clasp, jsid methodid,
Native native)
{
JS_ASSERT(obj->getClass() == clasp);
if (HasNativeMethod(obj, methodid, native))
return true;
JSObject *pobj = obj->getProto();
return pobj && pobj->getClass() == clasp &&
HasNativeMethod(pobj, methodid, native);
}
bool
DefaultValue(JSContext *cx, JSObject *obj, JSType hint, Value *vp)
{
@ -6167,10 +6180,9 @@ js_SetClassPrototype(JSContext *cx, JSObject *ctor, JSObject *proto, uintN attrs
ObjectOrNullValue(ctor), PropertyStub, PropertyStub, 0);
}
JSBool
js_PrimitiveToObject(JSContext *cx, Value *vp)
JSObject *
PrimitiveToObject(JSContext *cx, const Value &v)
{
Value v = *vp;
JS_ASSERT(v.isPrimitive());
Class *clasp;
@ -6185,11 +6197,21 @@ js_PrimitiveToObject(JSContext *cx, Value *vp)
JSObject *obj = NewBuiltinClassInstance(cx, clasp);
if (!obj)
return JS_FALSE;
return NULL;
obj->setPrimitiveThis(v);
return obj;
}
JSBool
js_PrimitiveToObject(JSContext *cx, Value *vp)
{
JSObject *obj = PrimitiveToObject(cx, *vp);
if (!obj)
return false;
vp->setObject(*obj);
return JS_TRUE;
return true;
}
JSBool
@ -6202,13 +6224,35 @@ js_ValueToObjectOrNull(JSContext *cx, const Value &v, JSObject **objp)
} else if (v.isUndefined()) {
obj = NULL;
} else {
Value tmp = v;
if (!js_PrimitiveToObject(cx, &tmp))
return JS_FALSE;
obj = &tmp.toObject();
obj = PrimitiveToObject(cx, v);
if (!obj)
return false;
}
*objp = obj;
return JS_TRUE;
return true;
}
namespace js {
/* Callers must handle the already-object case . */
JSObject *
ToObjectSlow(JSContext *cx, Value *vp)
{
JS_ASSERT(!vp->isMagic());
JS_ASSERT(!vp->isObject());
if (vp->isNullOrUndefined()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO,
vp->isNull() ? "null" : "undefined", "object");
return NULL;
}
JSObject *obj = PrimitiveToObject(cx, *vp);
if (obj)
vp->setObject(*obj);
return obj;
}
}
JSObject *
@ -6254,7 +6298,7 @@ js_TryMethod(JSContext *cx, JSObject *obj, JSAtom *atom,
if (fval.isPrimitive())
return JS_TRUE;
return ExternalInvoke(cx, obj, fval, argc, argv, rval);
return ExternalInvoke(cx, ObjectValue(*obj), fval, argc, argv, rval);
}
#if JS_HAS_XDR

Просмотреть файл

@ -1787,6 +1787,25 @@ js_PrimitiveToObject(JSContext *cx, js::Value *vp);
extern JSBool
js_ValueToObjectOrNull(JSContext *cx, const js::Value &v, JSObject **objp);
namespace js {
/*
* Invokes the ES5 ToObject algorithm on *vp, writing back the object to vp.
* If *vp might already be an object, use ToObject.
*/
extern JSObject *
ToObjectSlow(JSContext *cx, js::Value *vp);
JS_ALWAYS_INLINE JSObject *
ToObject(JSContext *cx, js::Value *vp)
{
if (vp->isObject())
return &vp->toObject();
return ToObjectSlow(cx, vp);
}
}
/*
* v and vp may alias. On successful return, vp->isObject(). If vp is not
* rooted, the caller must root vp before the next possible GC.

Просмотреть файл

@ -1178,6 +1178,28 @@ CopyInitializerObject(JSContext *cx, JSObject *baseobj)
return obj;
}
/*
* When we have an object of a builtin class, we don't quite know what its
* valueOf/toString methods are, since these methods may have been overwritten
* or shadowed. However, we can still do better than js_TryMethod by
* hard-coding the necessary properties for us to find the native we expect.
*
* TODO: a per-thread shape-based cache would be faster and simpler.
*/
static JS_ALWAYS_INLINE bool
ClassMethodIsNative(JSContext *cx, JSObject *obj, Class *clasp, jsid methodid,
Native native)
{
JS_ASSERT(obj->getClass() == clasp);
if (HasNativeMethod(obj, methodid, native))
return true;
JSObject *pobj = obj->getProto();
return pobj && pobj->getClass() == clasp &&
HasNativeMethod(pobj, methodid, native);
}
} /* namespace js */
#endif /* jsobjinlines_h___ */

Просмотреть файл

@ -259,14 +259,7 @@ JSProxyHandler::construct(JSContext *cx, JSObject *proxy,
Value fval = GetConstruct(proxy);
if (fval.isUndefined())
return ExternalInvokeConstructor(cx, GetCall(proxy), argc, argv, rval);
/*
* FIXME: The Proxy proposal says to pass undefined as the this argument,
* but primitive this is not supported yet. See bug 576644.
*/
JS_ASSERT(fval.isObject());
JSObject *thisobj = fval.toObject().getGlobal();
return ExternalInvoke(cx, thisobj, fval, argc, argv, rval);
return ExternalInvoke(cx, UndefinedValue(), fval, argc, argv, rval);
}
bool
@ -335,7 +328,7 @@ GetDerivedTrap(JSContext *cx, JSObject *handler, JSAtom *atom, Value *fvalp)
static bool
Trap(JSContext *cx, JSObject *handler, Value fval, uintN argc, Value* argv, Value *rval)
{
return ExternalInvoke(cx, handler, fval, argc, argv, rval);
return ExternalInvoke(cx, ObjectValue(*handler), fval, argc, argv, rval);
}
static bool
@ -1279,15 +1272,12 @@ static const uint32 JSSLOT_CALLABLE_CONSTRUCT = 1;
static JSBool
callable_Call(JSContext *cx, uintN argc, Value *vp)
{
JSObject *thisobj = ComputeThisFromVp(cx, vp);
if (!thisobj)
return false;
JSObject *callable = &JS_CALLEE(cx, vp).toObject();
JS_ASSERT(callable->getClass() == &CallableObjectClass);
const Value &fval = callable->getSlot(JSSLOT_CALLABLE_CALL);
const Value &thisval = vp[1];
Value rval;
bool ok = ExternalInvoke(cx, thisobj, fval, argc, JS_ARGV(cx, vp), &rval);
bool ok = ExternalInvoke(cx, thisval, fval, argc, JS_ARGV(cx, vp), &rval);
*vp = rval;
return ok;
}
@ -1326,7 +1316,7 @@ callable_Construct(JSContext *cx, uintN argc, Value *vp)
/* If the call returns an object, return that, otherwise the original newobj. */
Value rval;
if (!ExternalInvoke(cx, newobj, callable->getSlot(JSSLOT_CALLABLE_CALL),
if (!ExternalInvoke(cx, ObjectValue(*newobj), callable->getSlot(JSSLOT_CALLABLE_CALL),
argc, vp + 2, &rval)) {
return false;
}
@ -1338,7 +1328,7 @@ callable_Construct(JSContext *cx, uintN argc, Value *vp)
}
Value rval;
bool ok = ExternalInvoke(cx, thisobj, fval, argc, vp + 2, &rval);
bool ok = ExternalInvoke(cx, ObjectValue(*thisobj), fval, argc, vp + 2, &rval);
*vp = rval;
return ok;
}

Просмотреть файл

@ -619,8 +619,10 @@ js_regexp_toString(JSContext *cx, JSObject *obj, Value *vp)
static JSBool
regexp_toString(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = JS_THIS_OBJECT(cx, Jsvalify(vp));
return obj && js_regexp_toString(cx, obj, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
return js_regexp_toString(cx, obj, vp);
}
/*
@ -758,13 +760,19 @@ regexp_exec_sub(JSContext *cx, JSObject *obj, uintN argc, Value *argv, JSBool te
JSBool
js_regexp_exec(JSContext *cx, uintN argc, Value *vp)
{
return regexp_exec_sub(cx, JS_THIS_OBJECT(cx, Jsvalify(vp)), argc, vp + 2, JS_FALSE, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
return regexp_exec_sub(cx, obj, argc, vp + 2, JS_FALSE, vp);
}
JSBool
js_regexp_test(JSContext *cx, uintN argc, Value *vp)
{
if (!regexp_exec_sub(cx, JS_THIS_OBJECT(cx, Jsvalify(vp)), argc, vp + 2, JS_TRUE, vp))
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!regexp_exec_sub(cx, obj, argc, vp + 2, JS_TRUE, vp))
return false;
if (!vp->isTrue())
vp->setBoolean(false);

Просмотреть файл

@ -436,7 +436,7 @@ static const uint8 urlCharType[256] =
/* See ECMA-262 Edition 3 B.2.1 */
JSBool
js_str_escape(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval)
js_str_escape(JSContext *cx, uintN argc, Value *vp, Value *rval)
{
const char digits[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
@ -444,7 +444,7 @@ js_str_escape(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval
jsint mask = URL_XALPHAS | URL_XPALPHAS | URL_PATH;
if (argc > 1) {
double d;
if (!ValueToNumber(cx, argv[1], &d))
if (!ValueToNumber(cx, vp[3], &d))
return JS_FALSE;
if (!JSDOUBLE_IS_FINITE(d) ||
(mask = (jsint)d) != d ||
@ -458,7 +458,7 @@ js_str_escape(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval
}
}
JSLinearString *str = ArgToRootedString(cx, argc, argv - 2, 0);
JSLinearString *str = ArgToRootedString(cx, argc, vp, 0);
if (!str)
return JS_FALSE;
@ -535,8 +535,7 @@ js_str_escape(JSContext *cx, JSObject *obj, uintN argc, Value *argv, Value *rval
static JSBool
str_escape(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
return obj && js_str_escape(cx, obj, argc, vp + 2, vp);
return js_str_escape(cx, argc, vp, vp);
}
/* See ECMA-262 Edition 3 B.2.2 */
@ -713,38 +712,33 @@ Class js_StringClass = {
ConvertStub
};
#define NORMALIZE_THIS(cx,vp,str) \
JS_BEGIN_MACRO \
if (vp[1].isString()) { \
str = vp[1].toString(); \
} else { \
str = NormalizeThis(cx, vp); \
if (!str) \
return JS_FALSE; \
} \
JS_END_MACRO
static JSString *
NormalizeThis(JSContext *cx, Value *vp)
/*
* Returns a JSString * for the |this| value associated with vp, or throws a
* TypeError if |this| is null or undefined. This algorithm is the same as
* calling CheckObjectCoercible(this), then returning ToString(this), as all
* String.prototype.* methods do.
*/
static JS_ALWAYS_INLINE JSString *
ThisToStringForStringProto(JSContext *cx, Value *vp)
{
if (vp[1].isNullOrUndefined() && !ComputeThisFromVp(cx, vp))
return NULL;
if (vp[1].isString())
return vp[1].toString();
/*
* String.prototype.{toString,toSource,valueOf} throw a TypeError if the
* this-argument is not a string or a String object. So those methods use
* js::GetPrimitiveThis which provides that behavior.
*
* By standard, the rest of the String methods must ToString the
* this-argument rather than throw a TypeError. So those methods use
* NORMALIZE_THIS (and thus NormalizeThis) instead.
*/
if (vp[1].isObject()) {
JSObject *obj = &vp[1].toObject();
if (obj->getClass() == &js_StringClass) {
if (obj->getClass() == &js_StringClass &&
ClassMethodIsNative(cx, obj,
&js_StringClass,
ATOM_TO_JSID(cx->runtime->atomState.toStringAtom),
js_str_toString))
{
vp[1] = obj->getPrimitiveThis();
return vp[1].toString();
}
} else if (vp[1].isNullOrUndefined()) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_CONVERT_TO,
vp[1].isNull() ? "null" : "undefined", "object");
return NULL;
}
JSString *str = js_ValueToString(cx, vp[1]);
@ -763,14 +757,14 @@ NormalizeThis(JSContext *cx, Value *vp)
static JSBool
str_quote(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
str = js_QuoteString(cx, str, '"');
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
return JS_TRUE;
return true;
}
static JSBool
@ -857,11 +851,11 @@ ValueToIntegerRange(JSContext *cx, const Value &v, int32 *out)
static JSBool
str_substring(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
int32 length, begin, end;
NORMALIZE_THIS(cx, vp, str);
if (argc > 0) {
end = length = int32(str->length());
@ -924,29 +918,30 @@ js_toLowerCase(JSContext *cx, JSString *str)
static JSBool
str_toLowerCase(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
str = js_toLowerCase(cx, str);
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
return JS_TRUE;
return true;
}
static JSBool
str_toLocaleLowerCase(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
/*
* Forcefully ignore the first (or any) argument and return toLowerCase(),
* ECMA has reserved that argument, presumably for defining the locale.
*/
if (cx->localeCallbacks && cx->localeCallbacks->localeToLowerCase) {
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
return cx->localeCallbacks->localeToLowerCase(cx, str, Jsvalify(vp));
}
return str_toLowerCase(cx, 0, vp);
}
@ -974,54 +969,56 @@ js_toUpperCase(JSContext *cx, JSString *str)
static JSBool
str_toUpperCase(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
str = js_toUpperCase(cx, str);
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
return JS_TRUE;
return true;
}
static JSBool
str_toLocaleUpperCase(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
/*
* Forcefully ignore the first (or any) argument and return toUpperCase(),
* ECMA has reserved that argument, presumably for defining the locale.
*/
if (cx->localeCallbacks && cx->localeCallbacks->localeToUpperCase) {
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
return cx->localeCallbacks->localeToUpperCase(cx, str, Jsvalify(vp));
}
return str_toUpperCase(cx, 0, vp);
}
static JSBool
str_localeCompare(JSContext *cx, uintN argc, Value *vp)
{
JSString *str, *thatStr;
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
NORMALIZE_THIS(cx, vp, str);
if (argc == 0) {
vp->setInt32(0);
} else {
thatStr = js_ValueToString(cx, vp[2]);
JSString *thatStr = js_ValueToString(cx, vp[2]);
if (!thatStr)
return JS_FALSE;
return false;
if (cx->localeCallbacks && cx->localeCallbacks->localeCompare) {
vp[2].setString(thatStr);
return cx->localeCallbacks->localeCompare(cx, str, thatStr, Jsvalify(vp));
}
int32 result;
if (!CompareStrings(cx, str, thatStr, &result))
return JS_FALSE;
return false;
vp->setInt32(result);
}
return JS_TRUE;
return true;
}
JSBool
@ -1037,13 +1034,15 @@ js_str_charAt(JSContext *cx, uintN argc, Value *vp)
if ((size_t)i >= str->length())
goto out_of_range;
} else {
NORMALIZE_THIS(cx, vp, str);
str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
if (argc == 0) {
d = 0.0;
} else {
if (!ValueToNumber(cx, vp[2], &d))
return JS_FALSE;
return false;
d = js_DoubleToInteger(d);
}
@ -1054,13 +1053,13 @@ js_str_charAt(JSContext *cx, uintN argc, Value *vp)
str = JSString::getUnitString(cx, str, size_t(i));
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
return JS_TRUE;
return true;
out_of_range:
out_of_range:
vp->setString(cx->runtime->emptyString);
return JS_TRUE;
return true;
}
JSBool
@ -1074,7 +1073,9 @@ js_str_charCodeAt(JSContext *cx, uintN argc, Value *vp)
if ((size_t)i >= str->length())
goto out_of_range;
} else {
NORMALIZE_THIS(cx, vp, str);
str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
double d;
if (argc == 0) {
@ -1376,9 +1377,9 @@ RopeMatch(JSContext *cx, JSString *textstr, const jschar *pat, jsuint patlen, js
static JSBool
str_indexOf(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
JSLinearString *patstr = ArgToRootedString(cx, argc, vp, 0);
if (!patstr)
@ -1434,8 +1435,9 @@ str_indexOf(JSContext *cx, uintN argc, Value *vp)
static JSBool
str_lastIndexOf(JSContext *cx, uintN argc, Value *vp)
{
JSString *textstr;
NORMALIZE_THIS(cx, vp, textstr);
JSString *textstr = ThisToStringForStringProto(cx, vp);
if (!textstr)
return false;
size_t textlen = textstr->length();
const jschar *text = textstr->getChars(cx);
if (!text)
@ -1506,8 +1508,9 @@ str_lastIndexOf(JSContext *cx, uintN argc, Value *vp)
static JSBool
js_TrimString(JSContext *cx, Value *vp, JSBool trimLeft, JSBool trimRight)
{
JSString *str;
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
size_t length = str->length();
const jschar *chars = str->getChars(cx);
if (!chars)
@ -1855,8 +1858,9 @@ MatchCallback(JSContext *cx, RegExpStatics *res, size_t count, void *p)
static JSBool
str_match(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
RegExpGuard g(cx);
if (!g.init(argc, vp))
@ -1885,8 +1889,9 @@ str_match(JSContext *cx, uintN argc, Value *vp)
static JSBool
str_search(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
RegExpGuard g(cx);
if (!g.init(argc, vp))
@ -2432,7 +2437,9 @@ JSBool
js::str_replace(JSContext *cx, uintN argc, Value *vp)
{
ReplaceData rdata(cx);
NORMALIZE_THIS(cx, vp, rdata.str);
rdata.str = ThisToStringForStringProto(cx, vp);
if (!rdata.str)
return false;
static const uint32 optarg = 2;
/* Extract replacement string/function. */
@ -2634,8 +2641,9 @@ find_split(JSContext *cx, RegExpStatics *res, JSString *str, js::RegExp *re, jsi
static JSBool
str_split(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
if (argc == 0) {
Value v = StringValue(str);
@ -2736,11 +2744,11 @@ str_split(JSContext *cx, uintN argc, Value *vp)
static JSBool
str_substr(JSContext *cx, uintN argc, Value *vp)
{
JSString *str;
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
int32 length, len, begin;
NORMALIZE_THIS(cx, vp, str);
if (argc > 0) {
length = int32(str->length());
if (!ValueToIntegerRange(cx, vp[2], &begin))
@ -2788,28 +2796,28 @@ out:
static JSBool
str_concat(JSContext *cx, uintN argc, Value *vp)
{
JSString *str, *str2;
Value *argv;
uintN i;
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
/* Set vp (aka rval) early to handle the argc == 0 case. */
vp->setString(str);
Value *argv;
uintN i;
for (i = 0, argv = vp + 2; i < argc; i++) {
str2 = js_ValueToString(cx, argv[i]);
JSString *str2 = js_ValueToString(cx, argv[i]);
if (!str2)
return JS_FALSE;
return false;
argv[i].setString(str2);
str = js_ConcatStrings(cx, str, str2);
if (!str)
return JS_FALSE;
return false;
vp->setString(str);
}
return JS_TRUE;
return true;
}
static JSBool
@ -2837,8 +2845,9 @@ str_slice(JSContext *cx, uintN argc, Value *vp)
}
}
JSString *str;
NORMALIZE_THIS(cx, vp, str);
JSString *str = ThisToStringForStringProto(cx, vp);
if (!str)
return false;
if (argc != 0) {
double begin, end, length;
@ -2890,8 +2899,9 @@ static bool
tagify(JSContext *cx, const char *begin, JSLinearString *param, const char *end,
Value *vp)
{
JSString *thisstr;
NORMALIZE_THIS(cx, vp, thisstr);
JSString *thisstr = ThisToStringForStringProto(cx, vp);
if (!thisstr)
return false;
JSLinearString *str = thisstr->ensureLinear(cx);
if (!str)
return false;

Просмотреть файл

@ -1007,8 +1007,7 @@ js_DeflateStringToUTF8Buffer(JSContext *cx, const jschar *chars,
/* Export a few natives and a helper to other files in SpiderMonkey. */
extern JSBool
js_str_escape(JSContext *cx, JSObject *obj, uintN argc, js::Value *argv,
js::Value *rval);
js_str_escape(JSContext *cx, uintN argc, js::Value *argv, js::Value *rval);
/*
* The String.prototype.replace fast-native entry point is exported for joined

Просмотреть файл

@ -824,10 +824,11 @@ class TypedArrayTemplate
static JSBool
fun_slice(JSContext *cx, uintN argc, Value *vp)
{
Value *argv = JS_ARGV(cx, vp);
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!InstanceOf(cx, obj, ThisTypeArray::fastClass(), vp+2))
if (!InstanceOf(cx, obj, ThisTypeArray::fastClass(), vp + 2))
return false;
if (obj->getClass() != fastClass()) {
@ -847,6 +848,7 @@ class TypedArrayTemplate
int32_t length = int32(tarray->length);
if (argc > 0) {
Value *argv = JS_ARGV(cx, vp);
if (!ValueToInt32(cx, argv[0], &begin))
return false;
if (begin < 0) {
@ -898,10 +900,11 @@ class TypedArrayTemplate
static JSBool
fun_set(JSContext *cx, uintN argc, Value *vp)
{
Value *argv = JS_ARGV(cx, vp);
JSObject *obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!InstanceOf(cx, obj, ThisTypeArray::fastClass(), vp+2))
if (!InstanceOf(cx, obj, ThisTypeArray::fastClass(), vp + 2))
return false;
if (obj->getClass() != fastClass()) {
@ -919,6 +922,7 @@ class TypedArrayTemplate
// these are the default values
int32_t offset = 0;
Value *argv = JS_ARGV(cx, vp);
if (argc > 1) {
if (!ValueToInt32(cx, argv[1], &offset))
return false;

Просмотреть файл

@ -261,9 +261,9 @@ static JSPropertySpec namespace_props[] = {
static JSBool
namespace_toString(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj;
obj = ComputeThisFromVp(cx, vp);
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return JS_FALSE;
if (!JS_InstanceOf(cx, obj, Jsvalify(&js_NamespaceClass), Jsvalify(vp + 2)))
return JS_FALSE;
*vp = Valueify(obj->getNameURIVal());
@ -451,8 +451,11 @@ ConvertQNameToString(JSContext *cx, JSObject *obj)
static JSBool
qname_toString(JSContext *cx, uintN argc, Value *vp)
{
JSObject *obj = ComputeThisFromVp(cx, vp);
if (!obj || !InstanceOf(cx, obj, &js_QNameClass, vp + 2))
JSObject *obj = ToObject(cx, &vp[1]);
if (!obj)
return false;
if (!InstanceOf(cx, obj, &js_QNameClass, vp + 2))
return false;
JSString *str = ConvertQNameToString(cx, obj);
@ -5155,7 +5158,9 @@ StartNonListXMLMethod(JSContext *cx, jsval *vp, JSObject **objp)
JS_ASSERT(VALUE_IS_FUNCTION(cx, *vp));
*objp = JS_THIS_OBJECT(cx, vp);
*objp = ToObject(cx, Valueify(&vp[1]));
if (!*objp)
return NULL;
xml = (JSXML *) GetInstancePrivate(cx, *objp, &js_XMLClass, Valueify(vp + 2));
if (!xml || xml->xml_class != JSXML_CLASS_LIST)
return xml;
@ -5183,7 +5188,9 @@ StartNonListXMLMethod(JSContext *cx, jsval *vp, JSObject **objp)
/* Beware: these two are not bracketed by JS_BEGIN/END_MACRO. */
#define XML_METHOD_PROLOG \
JSObject *obj = JS_THIS_OBJECT(cx, vp); \
JSObject *obj = ToObject(cx, Valueify(&vp[1])); \
if (!obj) \
return JS_FALSE; \
JSXML *xml = (JSXML *)GetInstancePrivate(cx, obj, &js_XMLClass, Valueify(vp+2)); \
if (!xml) \
return JS_FALSE
@ -5274,7 +5281,10 @@ xml_attribute(JSContext *cx, uintN argc, jsval *vp)
vp[2] = OBJECT_TO_JSVAL(qn); /* local root */
jsid id = OBJECT_TO_JSID(qn);
return GetProperty(cx, JS_THIS_OBJECT(cx, vp), id, vp);
JSObject *obj = ToObject(cx, Valueify(&vp[1]));
if (!obj)
return JS_FALSE;
return GetProperty(cx, obj, id, vp);
}
/* XML and XMLList */
@ -5288,7 +5298,10 @@ xml_attributes(JSContext *cx, uintN argc, jsval *vp)
AutoObjectRooter tvr(cx, qn);
jsid id = OBJECT_TO_JSID(qn);
return GetProperty(cx, JS_THIS_OBJECT(cx, vp), id, vp);
JSObject *obj = ToObject(cx, Valueify(&vp[1]));
if (!obj)
return JS_FALSE;
return GetProperty(cx, obj, id, vp);
}
static JSXML *
@ -5443,8 +5456,11 @@ xml_childIndex(JSContext *cx, uintN argc, jsval *vp)
static JSBool
xml_children(JSContext *cx, uintN argc, jsval *vp)
{
JSObject *obj = ToObject(cx, Valueify(&vp[1]));
if (!obj)
return false;
jsid name = ATOM_TO_JSID(cx->runtime->atomState.starAtom);
return GetProperty(cx, JS_THIS_OBJECT(cx, vp), name, vp);
return GetProperty(cx, obj, name, vp);
}
/* XML and XMLList */
@ -5653,11 +5669,12 @@ xml_elements(JSContext *cx, uintN argc, jsval *vp)
static JSBool
xml_hasOwnProperty(JSContext *cx, uintN argc, jsval *vp)
{
JSObject *obj;
jsval name;
JSBool found;
obj = JS_THIS_OBJECT(cx, vp);
JSObject *obj = ToObject(cx, Valueify(&vp[1]));
if (!obj)
return JS_FALSE;
if (!InstanceOf(cx, obj, &js_XMLClass, Valueify(vp + 2)))
return JS_FALSE;
@ -6691,13 +6708,10 @@ xml_toString_helper(JSContext *cx, JSXML *xml)
static JSBool
xml_toSource(JSContext *cx, uintN argc, jsval *vp)
{
jsval thisv;
JSString *str;
thisv = JS_THIS(cx, vp);
if (JSVAL_IS_NULL(thisv))
JSObject *obj = ToObject(cx, Valueify(&vp[1]));
if (!obj)
return JS_FALSE;
str = ToXMLString(cx, thisv, TO_SOURCE_FLAG);
JSString *str = ToXMLString(cx, OBJECT_TO_JSVAL(obj), TO_SOURCE_FLAG);
if (!str)
return JS_FALSE;
*vp = STRING_TO_JSVAL(str);
@ -6721,13 +6735,10 @@ xml_toString(JSContext *cx, uintN argc, jsval *vp)
static JSBool
xml_toXMLString(JSContext *cx, uintN argc, jsval *vp)
{
jsval thisv;
JSString *str;
thisv = JS_THIS(cx, vp);
if (JSVAL_IS_NULL(thisv))
JSObject *obj = ToObject(cx, Valueify(&vp[1]));
if (!obj)
return JS_FALSE;
str = ToXMLString(cx, thisv, 0);
JSString *str = ToXMLString(cx, OBJECT_TO_JSVAL(obj), 0);
if (!str)
return JS_FALSE;
*vp = STRING_TO_JSVAL(str);
@ -6738,8 +6749,11 @@ xml_toXMLString(JSContext *cx, uintN argc, jsval *vp)
static JSBool
xml_valueOf(JSContext *cx, uintN argc, jsval *vp)
{
*vp = JS_THIS(cx, vp);
return !JSVAL_IS_NULL(*vp);
JSObject *obj = ToObject(cx, Valueify(&vp[1]));
if (!obj)
return false;
*vp = OBJECT_TO_JSVAL(obj);
return true;
}
static JSFunctionSpec xml_methods[] = {
@ -6831,25 +6845,24 @@ SetDefaultXMLSettings(JSContext *cx, JSObject *obj)
static JSBool
xml_settings(JSContext *cx, uintN argc, jsval *vp)
{
JSObject *settings;
JSObject *obj;
settings = JS_NewObject(cx, NULL, NULL, NULL);
JSObject *settings = JS_NewObject(cx, NULL, NULL, NULL);
if (!settings)
return JS_FALSE;
return false;
*vp = OBJECT_TO_JSVAL(settings);
obj = JS_THIS_OBJECT(cx, vp);
return obj && CopyXMLSettings(cx, obj, settings);
JSObject *obj = ToObject(cx, Valueify(&vp[1]));
if (!obj)
return false;
return CopyXMLSettings(cx, obj, settings);
}
static JSBool
xml_setSettings(JSContext *cx, uintN argc, jsval *vp)
{
JSObject *obj, *settings;
JSObject *settings;
jsval v;
JSBool ok;
obj = JS_THIS_OBJECT(cx, vp);
JSObject *obj = ToObject(cx, Valueify(&vp[1]));
if (!obj)
return JS_FALSE;
v = (argc == 0) ? JSVAL_VOID : vp[2];

Просмотреть файл

@ -189,11 +189,6 @@ new TestCase( SECTION,
2,
eval("var obj = new Object(); obj.indexOf = String.prototype.indexOf; obj.indexOf('bject')") );
new TestCase( SECTION,
"var f = new Object( String.prototype.indexOf ); f('"+GLOBAL+"')",
0,
eval("var f = new Object( String.prototype.indexOf ); f('"+GLOBAL+"')") );
new TestCase( SECTION,
"var f = new Function(); f.toString = Object.prototype.toString; f.indexOf = String.prototype.indexOf; f.indexOf('[object Function]')",
0,

Просмотреть файл

@ -0,0 +1,86 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var gTestfile = 'isPrototypeOf.js';
var BUGNUMBER = 619283;
var summary = "Object.prototype.isPrototypeOf";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function expectThrowTypeError(fun)
{
try
{
var r = fun();
throw new Error("didn't throw TypeError, returned " + r);
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"didn't throw TypeError, got: " + e);
}
}
var isPrototypeOf = Object.prototype.isPrototypeOf;
/*
* 1. If V is not an Object, return false.
*/
assertEq(isPrototypeOf(), false);
assertEq(isPrototypeOf(1), false);
assertEq(isPrototypeOf(Number.MAX_VALUE), false);
assertEq(isPrototypeOf(NaN), false);
assertEq(isPrototypeOf(""), false);
assertEq(isPrototypeOf("sesquicentennial"), false);
assertEq(isPrototypeOf(true), false);
assertEq(isPrototypeOf(false), false);
assertEq(isPrototypeOf(0.72), false);
assertEq(isPrototypeOf(undefined), false);
assertEq(isPrototypeOf(null), false);
/*
* 2. Let O be the result of calling ToObject passing the this value as the
* argument.
*/
var protoGlobal = Object.create(this);
expectThrowTypeError(function() { isPrototypeOf.call(null, {}); });
expectThrowTypeError(function() { isPrototypeOf.call(undefined, {}); });
expectThrowTypeError(function() { isPrototypeOf({}); });
expectThrowTypeError(function() { isPrototypeOf.call(null, protoGlobal); });
expectThrowTypeError(function() { isPrototypeOf.call(undefined, protoGlobal); });
expectThrowTypeError(function() { isPrototypeOf(protoGlobal); });
/*
* 3. Repeat
*/
/*
* 3a. Let V be the value of the [[Prototype]] internal property of V.
* 3b. If V is null, return false.
*/
assertEq(Object.prototype.isPrototypeOf(Object.prototype), false);
assertEq(String.prototype.isPrototypeOf({}), false);
assertEq(Object.prototype.isPrototypeOf(Object.create(null)), false);
/* 3c. If O and V refer to the same object, return true. */
assertEq(Object.prototype.isPrototypeOf({}), true);
assertEq(this.isPrototypeOf(protoGlobal), true);
assertEq(Object.prototype.isPrototypeOf({}), true);
assertEq(Object.prototype.isPrototypeOf(new Number(17)), true);
assertEq(Object.prototype.isPrototypeOf(function(){}), true);
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");

Просмотреть файл

@ -42,3 +42,5 @@ script vacuous-accessor-unqualified-name.js
script add-property-non-extensible.js
skip-if(!xulRuntime.shell) script freeze-global-eval-const.js # uses evalcx
script preventExtensions-idempotent.js
script isPrototypeOf.js
script propertyIsEnumerable.js

Просмотреть файл

@ -0,0 +1,199 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var gTestfile = 'propertyIsEnumerable.js';
var BUGNUMBER = 619283;
var summary = "Object.prototype.propertyIsEnumerable";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
function expectThrowError(errorCtor, fun)
{
try
{
var r = fun();
throw "didn't throw TypeError, returned " + r;
}
catch (e)
{
assertEq(e instanceof errorCtor, true,
"didn't throw " + errorCtor.prototype.name + ", got: " + e);
}
}
function expectThrowTypeError(fun)
{
expectThrowError(TypeError, fun);
}
function withToString(fun)
{
return { toString: fun };
}
function withValueOf(fun)
{
return { toString: null, valueOf: fun };
}
var propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
/*
* 1. Let P be ToString(V).
*/
expectThrowError(ReferenceError, function()
{
propertyIsEnumerable(withToString(function() { fahslkjdfhlkjdsl; }));
});
expectThrowError(ReferenceError, function()
{
propertyIsEnumerable.call(null, withToString(function() { fahslkjdfhlkjdsl; }));
});
expectThrowError(ReferenceError, function()
{
propertyIsEnumerable.call(undefined, withToString(function() { fahslkjdfhlkjdsl; }));
});
expectThrowError(ReferenceError, function()
{
propertyIsEnumerable(withValueOf(function() { fahslkjdfhlkjdsl; }));
});
expectThrowError(ReferenceError, function()
{
propertyIsEnumerable.call(null, withValueOf(function() { fahslkjdfhlkjdsl; }));
});
expectThrowError(ReferenceError, function()
{
propertyIsEnumerable.call(undefined, withValueOf(function() { fahslkjdfhlkjdsl; }));
});
expectThrowError(SyntaxError, function()
{
propertyIsEnumerable(withToString(function() { eval("}"); }));
});
expectThrowError(SyntaxError, function()
{
propertyIsEnumerable.call(null, withToString(function() { eval("}"); }));
});
expectThrowError(SyntaxError, function()
{
propertyIsEnumerable.call(undefined, withToString(function() { eval("}"); }));
});
expectThrowError(SyntaxError, function()
{
propertyIsEnumerable(withValueOf(function() { eval("}"); }));
});
expectThrowError(SyntaxError, function()
{
propertyIsEnumerable.call(null, withValueOf(function() { eval("}"); }));
});
expectThrowError(SyntaxError, function()
{
propertyIsEnumerable.call(undefined, withValueOf(function() { eval("}"); }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable(withToString(function() { [].length = -1; }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable.call(null, withToString(function() { [].length = -1; }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable.call(undefined, withToString(function() { [].length = -1; }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable(withValueOf(function() { [].length = -1; }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable.call(null, withValueOf(function() { [].length = -1; }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable.call(undefined, withValueOf(function() { [].length = -1; }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable(withToString(function() { [].length = 0.7; }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable.call(null, withToString(function() { [].length = 0.7; }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable.call(undefined, withToString(function() { [].length = 0.7; }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable(withValueOf(function() { [].length = 0.7; }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable.call(null, withValueOf(function() { [].length = 0.7; }));
});
expectThrowError(RangeError, function()
{
propertyIsEnumerable.call(undefined, withValueOf(function() { [].length = 0.7; }));
});
/*
* 2. Let O be the result of calling ToObject passing the this value as the
* argument.
*/
expectThrowTypeError(function() { propertyIsEnumerable("s"); });
expectThrowTypeError(function() { propertyIsEnumerable.call(null, "s"); });
expectThrowTypeError(function() { propertyIsEnumerable.call(undefined, "s"); });
expectThrowTypeError(function() { propertyIsEnumerable(true); });
expectThrowTypeError(function() { propertyIsEnumerable.call(null, true); });
expectThrowTypeError(function() { propertyIsEnumerable.call(undefined, true); });
expectThrowTypeError(function() { propertyIsEnumerable(NaN); });
expectThrowTypeError(function() { propertyIsEnumerable.call(null, NaN); });
expectThrowTypeError(function() { propertyIsEnumerable.call(undefined, NaN); });
expectThrowTypeError(function() { propertyIsEnumerable({}); });
expectThrowTypeError(function() { propertyIsEnumerable.call(null, {}); });
expectThrowTypeError(function() { propertyIsEnumerable.call(undefined, {}); });
/*
* 3. Let desc be the result of calling the [[GetOwnProperty]] internal method
* of O passing P as the argument.
* 4. If desc is undefined, return false.
*/
assertEq(propertyIsEnumerable.call({}, "valueOf"), false);
assertEq(propertyIsEnumerable.call({}, "toString"), false);
assertEq(propertyIsEnumerable.call("s", 1), false);
assertEq(propertyIsEnumerable.call({}, "dsfiodjfs"), false);
assertEq(propertyIsEnumerable.call(true, "toString"), false);
assertEq(propertyIsEnumerable.call({}, "__proto__"), false);
assertEq(propertyIsEnumerable.call(Object, "getOwnPropertyDescriptor"), false);
assertEq(propertyIsEnumerable.call(this, "expectThrowTypeError"), true);
assertEq(propertyIsEnumerable.call("s", "length"), false);
assertEq(propertyIsEnumerable.call("s", 0), true);
assertEq(propertyIsEnumerable.call(Number, "MAX_VALUE"), false);
assertEq(propertyIsEnumerable.call({ x: 9 }, "x"), true);
assertEq(propertyIsEnumerable.call(function() { }, "prototype"), false);
assertEq(propertyIsEnumerable.call(function() { }, "length"), false);
assertEq(propertyIsEnumerable.call(function() { "use strict"; }, "caller"), false);
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");

Просмотреть файл

@ -0,0 +1,112 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 619283;
var summary =
"ECMAScript built-in methods that immediately throw when |this| is " +
"|undefined| or |null| (due to CheckObjectCoercible, ToObject, or ToString)";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
// This test fills out for the non-standard methods which
// ecma_5/misc/builtin-methods-reject-null-undefined-this.js declines to test.
var ClassToMethodMap =
{
Object: [/*
* Don't box this just yet for these methods -- they're used too
* much without qualification to do that. :-(
*/
/* "__defineGetter__", "__defineSetter__", */
"__lookupGetter__", "__lookupSetter__", "watch", "unwatch",
"toSource"],
Function: ["toSource"],
Array: ["toSource"],
String: ["toSource", "quote", "bold", "italics", "fixed", "fontsize",
"fontcolor", "link", "anchor", "strike", "small", "big", "blink",
"sup", "sub", "substr", "trimLeft", "trimRight", "toJSON"],
Boolean: ["toSource", "toJSON"],
Number: ["toSource", "toJSON"],
Date: ["toSource", "toLocaleFormat", "getYear", "setYear",
"toGMTString"],
RegExp: ["toSource"],
Error: ["toSource"],
};
var badThisValues = [null, undefined];
function testMethod(Class, className, method)
{
var expr;
// Try out explicit this values
for (var i = 0, sz = badThisValues.length; i < sz; i++)
{
var badThis = badThisValues[i];
expr = className + ".prototype." + method + ".call(" + badThis + ")";
try
{
Class.prototype[method].call(badThis);
throw new Error(expr + " didn't throw a TypeError");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"wrong error for " + expr + ", instead threw " + e);
}
expr = className + ".prototype." + method + ".apply(" + badThis + ")";
try
{
Class.prototype[method].apply(badThis);
throw new Error(expr + " didn't throw a TypeError");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"wrong error for " + expr + ", instead threw " + e);
}
}
// ..and for good measure..
expr = "(0, " + className + ".prototype." + method + ")()"
try
{
// comma operator to call GetValue() on the method and de-Reference it
(0, Class.prototype[method])();
throw new Error(expr + " didn't throw a TypeError");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"wrong error for " + expr + ", instead threw " + e);
}
}
for (var className in ClassToMethodMap)
{
var Class = this[className];
var methodNames = ClassToMethodMap[className];
for (var i = 0, sz = methodNames.length; i < sz; i++)
{
var method = methodNames[i];
testMethod(Class, className, method);
}
}
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");

Просмотреть файл

@ -24,3 +24,4 @@ script bug566661.js
script iterator-in-catch.js
script strict-function-statements.js
skip-if(!xulRuntime.shell) script function-definition-with.js # needs evaluate()
script extension-methods-reject-null-undefined-this.js

Просмотреть файл

@ -1,11 +1,13 @@
// Any copyright is dedicated to the Public Domain.
// http://creativecommons.org/licenses/publicdomain/
var global = this;
(function() {
function f() {
this.b = function() {};
Object.defineProperty(this, "b", ({
configurable: __defineSetter__("", function() {})
configurable: global.__defineSetter__("", function() {})
}));
}
for each(y in [0]) {

Просмотреть файл

@ -0,0 +1,153 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
//-----------------------------------------------------------------------------
var BUGNUMBER = 619283;
var summary =
"ECMAScript built-in methods that immediately throw when |this| is " +
"|undefined| or |null| (due to CheckObjectCoercible, ToObject, or ToString)";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
// We can't just exhaustively loop over everything because 1) method properties
// might be extensions with special |this| handling, and 2) some methods don't
// *quite* immediately throw a TypeError, first thing, if |this| is |undefined|
// or |null|, or their algorithms are very slightly ambiguous about whether they
// do. Why? Ipse-dixitism. *shrug*
var ClassToMethodMap =
{
Object: [/* "toString" has special |this| handling */
"toLocaleString", "valueOf", "hasOwnProperty",
/*
* "isPrototypeOf" has special |this| handling already tested in
* ecma_5/Object/isPrototypeOf.js.
*/
/*
* "isPrototypeOf" has special |this| handling already tested in
* ecma_5/Object/propertyIsEnumerable.js.
*/],
// Function methods often don't ToObject(this) as their very first step,
// and they're already stepwise well-tested such that manual tests here
// would be redundant.
Array: ["toString", "toLocaleString", "concat", "join", "pop", "push",
"reverse", "shift", "slice", "sort", "splice", "unshift",
"indexOf", "lastIndexOf", "every", "some", "forEach", "map",
"filter", "reduce", "reduceRight"],
String: ["toString", "valueOf", "charAt", "charCodeAt", "concat",
"indexOf", "lastIndexOf", "localeCompare", "match", "replace",
"search", "slice", "split", "substring", "toLowerCase",
"toLocaleLowerCase", "toUpperCase", "toLocaleUpperCase", "trim",
/*
* "trimLeft" and "trimRight" are non-standard and thus are tested
* in ecma_5/extensions/trim-extensions.js.
*/
],
Boolean: ["toString", "valueOf"],
Number: ["toString", "toLocaleString", "valueOf",
/*
* toFixed doesn't *immediately* test |this| for number or
* Number-ness, but because the ToInteger(void 0) which arguably
* precedes it in the toFixed algorithm won't throw in this test,
* we don't need to specially test it.
*/
"toFixed",
"toExponential", "toPrecision"],
Date: ["toString", "toDateString", "toTimeString", "toLocaleString",
"toLocaleDateString", "toLocaleTimeString", "valueOf", "getTime",
"getFullYear", "getUTCFullYear", "getMonth", "getUTCMonth",
"getDate", "getUTCDate", "getDay", "getUTCDay", "getHours",
"getUTCHours", "getMinutes", "getUTCMinutes", "getSeconds",
"getUTCSeconds", "getMilliseconds", "getUTCMilliseconds",
/*
* toFixed doesn't *immediately* test |this| for number or
* Number-ness, but because the TimeClip(ToNumber(void 0)) which
* arguably precedes it in the setTime algorithm won't throw in
* this test, we don't need to specially test it.
*/
"setTime",
"getTimezoneOffset", "setMilliseconds", "setUTCMilliseconds",
"setSeconds", "setUTCSeconds", "setMinutes", "setUTCMinutes",
"setHours", "setUTCHours", "setDate", "setUTCDate", "setMonth",
"setUTCMonth", "setFullYear", "setUTCFullYear", "toUTCString",
"toISOString", "toJSON"],
RegExp: ["exec", "test", "toString"],
Error: ["toString"],
};
var badThisValues = [null, undefined];
function testMethod(Class, className, method)
{
var expr;
// Try out explicit this values
for (var i = 0, sz = badThisValues.length; i < sz; i++)
{
var badThis = badThisValues[i];
expr = className + ".prototype." + method + ".call(" + badThis + ")";
try
{
Class.prototype[method].call(badThis);
throw new Error(expr + " didn't throw a TypeError");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"wrong error for " + expr + ", instead threw " + e);
}
expr = className + ".prototype." + method + ".apply(" + badThis + ")";
try
{
Class.prototype[method].apply(badThis);
throw new Error(expr + " didn't throw a TypeError");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"wrong error for " + expr + ", instead threw " + e);
}
}
// ..and for good measure..
expr = "(0, " + className + ".prototype." + method + ")()"
try
{
// comma operator to call GetValue() on the method and de-Reference it
(0, Class.prototype[method])();
throw new Error(expr + " didn't throw a TypeError");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"wrong error for " + expr + ", instead threw " + e);
}
}
for (var className in ClassToMethodMap)
{
var Class = this[className];
var methodNames = ClassToMethodMap[className];
for (var i = 0, sz = methodNames.length; i < sz; i++)
{
var method = methodNames[i];
testMethod(Class, className, method);
}
}
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("All tests passed!");

Просмотреть файл

@ -7,3 +7,4 @@ script explicit-undefined-optional-argument.js
script function-definition-eval.js
skip-if(!xulRuntime.shell) script function-definition-evaluate.js # needs evaluate()
script future-reserved-words.js
script builtin-methods-reject-null-undefined-this.js

Просмотреть файл

@ -44,6 +44,15 @@ var expect = 'No Crash';
printBugNumber(BUGNUMBER);
printStatus (summary);
"".match.apply();
try
{
"".match.apply();
throw new Error("should have thrown for undefined this");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"No TypeError for String.prototype.match");
}
reportCompare(expect, actual, summary);

Просмотреть файл

@ -51,8 +51,16 @@ function test()
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
(function() { var s = function(){}.prototype.toSource; s(); })();
try
{
(function() { var s = function(){}.prototype.toSource; s(); })();
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"No TypeError for Object.prototype.toSource");
}
reportCompare(expect, actual, summary);

Просмотреть файл

@ -57,13 +57,30 @@ function test()
n.__defineGetter__("prototype", n.toSource);
p = n.__lookupGetter__("prototype");
n = p;
assertEq(n, Object.prototype.toSource);
assertEq(p, Object.prototype.toSource);
n["prototype"] = [n];
n = p;
assertEq(n, Object.prototype.toSource);
assertEq(p, Object.prototype.toSource);
p2 = n["prototype"];
assertEq(Array.isArray(p2), true);
assertEq(p2[0], Object.prototype.toSource);
n = p2;
assertEq(n.toString, Array.prototype.toString);
n.__defineGetter__("0", n.toString);
n = p;
n();
assertEq(n, Object.prototype.toSource);
n.call(this);
reportCompare(expect, actual, summary);

Просмотреть файл

@ -60,11 +60,16 @@ actual = String.toUpperCase(new Boolean(true));
reportCompare(expect, actual, summary +
" String.toUpperCase(new Boolean(true))");
// null means the global object is passed
expect = (typeof window == 'undefined') ? 9 : -1;
actual = String.indexOf(null, 'l');
reportCompare(expect, actual, summary +
" String.indexOf(null, 'l')");
try
{
String.indexOf(null, 'l');
throw new Error("should have thrown a TypeError");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"String.indexOf(null [, ...]) didn't work correctly");
}
expect = 2;
actual = String.indexOf(String(null), 'l');
@ -86,11 +91,16 @@ actual = String.toUpperCase(true);
reportCompare(expect, actual, summary +
" String.toUpperCase(true)");
// null means the global object is passed
expect = (typeof window == 'undefined') ? -1 : 11;
actual = String.indexOf(undefined, 'd');
reportCompare(expect, actual, summary +
" String.indexOf(undefined, 'd')");
try
{
String.indexOf(undefined, 'd');
throw new Error("should have thrown a TypeError");
}
catch (e)
{
assertEq(e instanceof TypeError, true,
"String.indexOf(undefined [, ...]) didn't work correctly");
}
expect = 2;
actual = String.indexOf(String(undefined), 'd');

Просмотреть файл

@ -58,15 +58,17 @@ function test()
actual = f + '';
compareSource(expect, actual, summary);
expect = 'TypeError: "a" is not a function';
try
{
f();
throw new Error("no TypeError thrown calling map with undefined this");
}
catch(ex)
{
actual = ex + '';
assertEq(ex instanceof TypeError, true,
"No TypeError for Array.prototype.map with undefined this");
}
reportCompare(expect, actual, summary);
reportCompare(true, true, summary);
exitFunc ('test');
}

Просмотреть файл

@ -58,15 +58,17 @@ function test()
actual = f + '';
compareSource(expect, actual, summary);
expect = 'TypeError: "a" is not a function';
try
{
f();
throw new Error("no TypeError thrown calling map with undefined this");
}
catch(ex)
{
actual = ex + '';
assertEq(ex instanceof TypeError, true,
"No TypeError for Array.prototype.map with undefined this");
}
reportCompare(expect, actual, summary);
reportCompare(true, true, summary);
exitFunc ('test');
}

Просмотреть файл

@ -42,6 +42,9 @@ var actual = '';
var expect = true;
var voids = [null, undefined];
function noop() { }
var generics = {
String: [{ quote: [] },
{ substring: [] },
@ -85,6 +88,8 @@ var generics = {
printBugNumber(BUGNUMBER);
printStatus (summary);
var global = this;
for (var c in generics)
{
var methods = generics[c];
@ -96,59 +101,62 @@ for (var c in generics)
{
for (var v = 0; v < voids.length; v++)
{
var lhs = c + '.' + methodname +
'(' + voids[v] + (method[methodname].length ?(', ' + method[methodname].toString()):'') + ')';
var Constructor = global[c]
var rhs = c + '.prototype.' + methodname +
'.apply(' + voids[v] + ', ' + method[methodname].toSource() + ')';
var argsLen = method[methodname].length;
assertEq(argsLen === 0 || argsLen === 1, true, "not all arities handled");
var expr = lhs + ' == ' + rhs;
printStatus('Testing ' + expr);
var generic = Constructor[methodname];
var prototypy = Constructor.prototype[methodname];
assertEq(typeof generic, "function");
assertEq(typeof prototypy, "function");
// GENERIC METHOD TESTING
try
{
printStatus('lhs ' + lhs + ': ' + eval(lhs));
switch (method[methodname].length)
{
case 0:
generic(voids[v]);
break;
case 1:
generic(voids[v], method[methodname][0]);
break;
}
throw new Error(c + "." + methodname + " must throw for null or " +
"undefined first argument");
}
catch(ex)
catch (e)
{
printStatus(ex + '');
assertEq(e instanceof TypeError, true,
"Didn't get a TypeError for " + c + "." + methodname +
" called with null or undefined first argument");
}
// PROTOTYPE METHOD TESTING
try
{
printStatus('rhs ' + rhs + ': ' + eval(rhs));
prototypy.apply(voids[v], method[methodname][0]);
throw new Error(c + ".prototype." + methodname + " must throw " +
"for null or undefined this");
}
catch(ex)
catch (e)
{
printStatus(ex + '');
assertEq(e instanceof TypeError, true,
c + ".prototype." + methodname + "didn't throw a " +
"TypeError when called with null or undefined this");
}
try
{
actual = comparelr(eval(lhs), eval(rhs));
}
catch(ex)
{
actual = ex + '';
}
reportCompare(expect, actual, expr);
printStatus('');
}
}
}
}
function comparelr(lhs, rhs)
{
if (lhs.constructor.name != 'Array')
{
return (lhs == rhs);
}
if (typeof reportCompare === "function")
reportCompare(true, true);
return (lhs.toSource() == rhs.toSource());
}
function noop()
{
}
print("Tests finished.");

Просмотреть файл

@ -46,7 +46,7 @@ printBugNumber(BUGNUMBER);
printStatus (summary);
this.watch("b", "".substring);
__defineGetter__("a", gc);
this.__defineGetter__("a", gc);
for each (b in [this, null, null]);
a;

Просмотреть файл

@ -51,7 +51,7 @@ for (var j = 0; j < 10; j++)
for (var i = 0; i < j; ++i)
this["n" + i] = 1;
__defineGetter__('w', (function(){}));
this.__defineGetter__('w', (function(){}));
[1 for each (g in this) for each (t in /x/g)];
}

Просмотреть файл

@ -49,7 +49,7 @@ printStatus (summary);
// Assertion failure: !OBJ_GET_CLASS(cx, proto)->getObjectOps, at ../jsobj.cpp:2030
jit(true);
__defineGetter__("x3", Function);
this.__defineGetter__("x3", Function);
parseInt = x3;
parseInt.prototype = [];
for (var z = 0; z < 4; ++z) { new parseInt() }

Просмотреть файл

@ -55,7 +55,7 @@ function test()
// Assertion failure: afunbox->parent, at ../jsparse.cpp:1912
watch("x", Function);
this.watch("x", Function);
NaN = uneval({ get \u3056 (){ return undefined } });
x+=NaN;

Просмотреть файл

@ -55,7 +55,7 @@ function test()
// Assertion failure: localKind == JSLOCAL_VAR || localKind == JSLOCAL_CONST, at ../jsfun.cpp:916
watch("x", Function);
this.watch("x", Function);
NaN = uneval({ get \u3056 (){ return undefined } });
x+=NaN;

Просмотреть файл

@ -59,7 +59,7 @@ function test()
reportCompare(expect, actual, summary + ': 1');
// crash [@ js_Interpret]
(eval("(function(){ watch(\"x\", function () { new function ()y } ); const y });"))();
(eval("(function(){ this.watch(\"x\", function () { new function ()y } ); const y });"))();
x = NaN;
reportCompare(expect, actual, summary + ': 2');

Просмотреть файл

@ -2,7 +2,7 @@ function f(code) {
code.replace(/s/, "")
eval(code)
}
__defineGetter__("x", /x/)
this.__defineGetter__("x", /x/)
f("function a() {\
x = Proxy.createFunction((function () {\
return {\

Просмотреть файл

@ -6,14 +6,14 @@
eval("\
(function(){for(d in[0,Number]) {\
__defineGetter__(\"\",function(){}),\
[(__defineGetter__(\"x\",Math.pow))]\
this.__defineGetter__(\"\",function(){}),\
[(this.__defineGetter__(\"x\",Math.pow))]\
}})\
")()
delete gc
eval("\
(function() {\
for(e in __defineSetter__(\"x\",function(){})){}\
for(e in this.__defineSetter__(\"x\",function(){})){}\
})\
")()
delete gc