diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index a684eddd484f..c24427ba491e 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -5854,7 +5854,7 @@ CloneSimpleValues(JSContext* cx, } // Security wrapped objects are not allowed either. - if (obj->getClass()->ext.wrappedObject) + if (obj->isWrapper() && !obj->getClass()->ext.innerObject) return NS_ERROR_DOM_NOT_SUPPORTED_ERR; // See if this JSObject is backed by some C++ object. If it is then we assume diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 5f1d6098ef5f..de8bcc0d1f0f 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4085,7 +4085,8 @@ JS_PUBLIC_API(JSBool) JS_IsArrayObject(JSContext *cx, JSObject *obj) { assertSameCompartment(cx, obj); - return obj->wrappedObject(cx)->isArray(); + return obj->isArray() || + (obj->isWrapper() && JSWrapper::wrappedObject(obj)->isArray()); } JS_PUBLIC_API(JSBool) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index 7a8bb0791ed2..5c933537e05b 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -101,6 +101,7 @@ #include "jsstr.h" #include "jsstaticcheck.h" #include "jsvector.h" +#include "jswrapper.h" #include "jsatominlines.h" #include "jscntxtinlines.h" @@ -2394,11 +2395,9 @@ array_concat(JSContext *cx, uintN argc, Value *vp) return false; const Value &v = p[i]; if (v.isObject()) { - JSObject *wobj; - aobj = &v.toObject(); - wobj = aobj->wrappedObject(cx); - if (wobj->isArray()) { + if (aobj->isArray() || + (aobj->isWrapper() && JSWrapper::wrappedObject(aobj)->isArray())) { jsid id = ATOM_TO_JSID(cx->runtime->atomState.lengthAtom); if (!aobj->getProperty(cx, id, tvr.addr())) return false; @@ -2827,10 +2826,12 @@ array_every(JSContext *cx, uintN argc, Value *vp) static JSBool array_isArray(JSContext *cx, uintN argc, Value *vp) { + JSObject *obj; vp->setBoolean(argc > 0 && vp[2].isObject() && - vp[2].toObject().wrappedObject(cx)->isArray()); - return JS_TRUE; + ((obj = &vp[2].toObject())->isArray() || + (obj->isWrapper() && JSWrapper::wrappedObject(obj)->isArray()))); + return true; } static JSFunctionSpec array_methods[] = { diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index f13eb457ac55..b50de625c925 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -786,7 +786,6 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsid id, PropertyOp watcher; origobj = obj; - obj = obj->wrappedObject(cx); OBJ_TO_INNER_OBJECT(cx, obj); if (!obj) return JS_FALSE; diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index b40cd6b00674..e80b4ac73d56 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -2304,7 +2304,7 @@ js_fun_apply(JSContext *cx, uintN argc, Value *vp) * Steps 4-5 (note erratum removing steps originally numbered 5 and 7 in * original version of ES5). */ - JSObject *aobj = vp[3].toObject().wrappedObject(cx); + JSObject *aobj = &vp[3].toObject(); jsuint length; if (aobj->isArray()) { length = aobj->getArrayLength(); @@ -2496,7 +2496,7 @@ fun_bind(JSContext *cx, uintN argc, Value *vp) return false; /* Step 2. */ - if (!target->wrappedObject(cx)->isCallable()) { + if (!target->isCallable()) { if (JSString *str = js_ValueToString(cx, vp[1])) { if (const char *bytes = js_GetStringBytes(cx, str)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 920f9a4c104e..5363af249bb4 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -2637,7 +2637,6 @@ SetProtoCheckingForCycles(JSContext *cx, JSObject *obj, JSObject *proto) bool cycle = false; for (JSObject *obj2 = proto; obj2;) { - obj2 = obj2->wrappedObject(cx); if (obj2 == obj) { cycle = true; break; diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 4033af8fb9c3..08daa2d38eed 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -1124,8 +1124,7 @@ HasInstance(JSContext *cx, JSObject *obj, const Value *v, JSBool *bp) static JS_ALWAYS_INLINE bool EqualObjects(JSContext *cx, JSObject *lobj, JSObject *robj) { - return lobj == robj || - lobj->wrappedObject(cx) == robj->wrappedObject(cx); + return lobj == robj; } bool diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 39c90471ecda..6315b6c52b65 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -111,7 +111,7 @@ Class js_IteratorClass = { NULL, /* outerObject */ NULL, /* innerObject */ iterator_iterator, - NULL /* wrappedObject */ + NULL /* unused */ } }; @@ -1170,7 +1170,7 @@ Class js_GeneratorClass = { NULL, /* outerObject */ NULL, /* innerObject */ iterator_iterator, - NULL, /* wrappedObject */ + NULL /* unused */ } }; diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index 9ae94756d112..c5de941fbc5a 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -812,7 +812,7 @@ obj_toStringHelper(JSContext *cx, JSObject *obj) if (obj->isProxy()) return JSProxy::obj_toString(cx, obj); - const char *clazz = obj->wrappedObject(cx)->getClass()->name; + const char *clazz = obj->getClass()->name; size_t nchars = 9 + strlen(clazz); /* 9 for "[object ]" */ jschar *chars = (jschar *) cx->malloc((nchars + 1) * sizeof(jschar)); if (!chars) @@ -5859,13 +5859,6 @@ CheckAccess(JSContext *cx, JSObject *obj, jsid id, JSAccessMode mode, JSType js_TypeOf(JSContext *cx, JSObject *obj) { - /* - * Unfortunately we have wrappers that are native objects and thus don't - * overwrite js_TypeOf (i.e. XPCCrossOriginWrapper), so we have to - * unwrap here. - */ - obj = obj->wrappedObject(cx); - /* * ECMA 262, 11.4.3 says that any native object that implements * [[Call]] should be of type "function". However, RegExp is of @@ -5893,7 +5886,7 @@ js_IsDelegate(JSContext *cx, JSObject *obj, const Value &v) { if (v.isPrimitive()) return false; - JSObject *obj2 = v.toObject().wrappedObject(cx); + JSObject *obj2 = &v.toObject(); while ((obj2 = obj2->getProto()) != NULL) { if (obj2 == obj) return true; @@ -6388,16 +6381,6 @@ js_SetReservedSlot(JSContext *cx, JSObject *obj, uint32 slot, const Value &v) return true; } -JSObject * -JSObject::wrappedObject(JSContext *cx) const -{ - if (JSObjectOp op = getClass()->ext.wrappedObject) { - if (JSObject *obj = op(cx, const_cast(this))) - return obj; - } - return const_cast(this); -} - JSObject * JSObject::getGlobal() const { diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 2fb936fe0e4a..2429e29ea7ac 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -1097,8 +1097,6 @@ struct JSObject : js::gc::Cell { return (op ? op : js_TypeOf)(cx, this); } - JSObject *wrappedObject(JSContext *cx) const; - /* These four are time-optimized to avoid stub calls. */ JSObject *thisObject(JSContext *cx) { JSObjectOp op = getOps()->thisObject; diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 121ab7259af6..ac1bacf1763f 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -1000,7 +1000,7 @@ JS_FRIEND_API(Class) OuterWindowProxyClass = { NULL, /* equality */ NULL, /* outerObject */ proxy_innerObject, - NULL, /* wrappedObject */ + NULL /* unused */ }, { proxy_LookupProperty, diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index a786e15e4935..d08ba4f9698f 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -10211,14 +10211,9 @@ TraceRecorder::getThis(LIns*& this_ins) /* thisv is a reference, so it'll see the newly computed |this|. */ #ifdef DEBUG - /* - * Check that thisv is our global. It could be a XPCCrossOriginWrapper around an outer - * window object whose inner object is our global, so follow all the links as needed. - */ JS_ASSERT(thisv.isObject()); - JSObject *thisObj = thisv.toObject().wrappedObject(cx); - OBJ_TO_INNER_OBJECT(cx, thisObj); - JS_ASSERT(thisObj == globalObj); + JSObject *thisObj = &thisv.toObject(); + JS_ASSERT(thisObj->getClass()->ext.innerObject); #endif this_ins = INS_CONSTOBJ(globalObj); set(&thisv, this_ins); diff --git a/js/src/jstypedarray.cpp b/js/src/jstypedarray.cpp index b2d8b84c923b..db37811214e2 100644 --- a/js/src/jstypedarray.cpp +++ b/js/src/jstypedarray.cpp @@ -929,7 +929,7 @@ class TypedArrayTemplate if (!tarray->copyFrom(cx, src, offset)) return false; - } else if (arg0->wrappedObject(cx)->isArray()) { + } else { jsuint len; if (!js_GetLengthProperty(cx, arg0, &len)) return false; @@ -943,10 +943,6 @@ class TypedArrayTemplate if (!tarray->copyFrom(cx, arg0, len, offset)) return false; - } else { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TYPED_ARRAY_BAD_ARGS); - return false; } vp->setUndefined(); @@ -989,37 +985,18 @@ class TypedArrayTemplate init(JSContext *cx, JSObject *other, int32 byteOffsetInt = -1, int32 lengthInt = -1) { type = ArrayTypeID(); + ArrayBuffer *abuf; - //printf ("Constructing with type %d other %p offset %d length %d\n", type, other, byteOffset, length); - - if (other->wrappedObject(cx)->isArray()) { - jsuint len; - if (!js_GetLengthProperty(cx, other, &len)) - return false; - if (!createBufferWithSizeAndCount(cx, sizeof(NativeType), len)) - return false; - if (!copyFrom(cx, other, len)) - return false; - } else if (js_IsTypedArray(other)) { + if (js_IsTypedArray(other)) { TypedArray *tarray = TypedArray::fromJSObject(other); JS_ASSERT(tarray); - //printf ("SizeAndCount: %d %d\n", sizeof(NativeType), tarray->length); - if (!createBufferWithSizeAndCount(cx, sizeof(NativeType), tarray->length)) return false; if (!copyFrom(cx, tarray)) return false; - } else if (other->getClass() == &ArrayBuffer::jsclass) { - ArrayBuffer *abuf = ArrayBuffer::fromJSObject(other); - - if (!abuf) { - // the arg isn't a real arraybuffer - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TYPED_ARRAY_BAD_ARGS); - return false; - } - + } else if (other->getClass() == &ArrayBuffer::jsclass && + ((abuf = ArrayBuffer::fromJSObject(other)) != NULL)) { uint32 boffset = (byteOffsetInt < 0) ? 0 : uint32(byteOffsetInt); if (boffset > abuf->byteLength || boffset % sizeof(NativeType) != 0) { @@ -1063,9 +1040,13 @@ class TypedArrayTemplate length = len; data = abuf->offsetData(boffset); } else { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_TYPED_ARRAY_BAD_ARGS); - return false; + jsuint len; + if (!js_GetLengthProperty(cx, other, &len)) + return false; + if (!createBufferWithSizeAndCount(cx, sizeof(NativeType), len)) + return false; + if (!copyFrom(cx, other, len)) + return false; } return true; diff --git a/js/src/jsvalue.h b/js/src/jsvalue.h index d99e187f71e4..a1fad41ab0dc 100644 --- a/js/src/jsvalue.h +++ b/js/src/jsvalue.h @@ -987,8 +987,7 @@ struct ClassExtension { JSObjectOp outerObject; JSObjectOp innerObject; JSIteratorOp iteratorObject; - JSObjectOp wrappedObject; /* NB: infallible, null returns are - treated as the original object */ + void *unused; }; #define JS_NULL_CLASS_EXT {NULL,NULL,NULL,NULL,NULL} diff --git a/js/src/jswrapper.h b/js/src/jswrapper.h index 7840be30ab3b..0b30bf9164ae 100644 --- a/js/src/jswrapper.h +++ b/js/src/jswrapper.h @@ -99,7 +99,7 @@ class JS_FRIEND_API(JSWrapper) : public js::JSProxyHandler { static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, JSWrapper *handler); - static inline JSObject *wrappedObject(JSObject *wrapper) { + static inline JSObject *wrappedObject(const JSObject *wrapper) { return wrapper->getProxyPrivate().toObjectOrNull(); } diff --git a/js/src/methodjit/Compiler.cpp b/js/src/methodjit/Compiler.cpp index 8b900c84b4e7..86e100fcace0 100644 --- a/js/src/methodjit/Compiler.cpp +++ b/js/src/methodjit/Compiler.cpp @@ -4259,13 +4259,6 @@ mjit::Compiler::jsop_instanceof() if (!lhs->isTypeKnown()) isFalse = frame.testPrimitive(Assembler::Equal, lhs); - /* Quick test to avoid wrapped objects. */ - masm.loadPtr(Address(obj, offsetof(JSObject, clasp)), temp); - masm.loadPtr(Address(temp, offsetof(Class, ext) + - offsetof(ClassExtension, wrappedObject)), temp); - j = masm.branchTestPtr(Assembler::NonZero, temp, temp); - stubcc.linkExit(j, Uses(3)); - Address protoAddr(obj, offsetof(JSObject, proto)); Label loop = masm.label(); diff --git a/js/src/tests/js1_8_5/extensions/typedarray.js b/js/src/tests/js1_8_5/extensions/typedarray.js index 0bcdf943108a..b211da15e7bf 100644 --- a/js/src/tests/js1_8_5/extensions/typedarray.js +++ b/js/src/tests/js1_8_5/extensions/typedarray.js @@ -260,9 +260,9 @@ function test() checkThrows(function() a.set(new Array(0x7fffffff))); checkThrows(function() a.set([1,2,3], 2147483647)); - checkThrows(function() a.set(ArrayBuffer.prototype)); - checkThrows(function() a.set(UInt16Array.prototype)); - checkThrows(function() a.set(Int32Array.prototype)); + a.set(ArrayBuffer.prototype); + a.set(Int16Array.prototype); + a.set(Int32Array.prototype); a.set([1,2,3]); a.set([4,5,6], 3); @@ -305,12 +305,16 @@ function test() a = new Uint8Array(0x100); checkThrows(function() Uint32Array.prototype.slice.apply(a, [0, 0x100])); - checkThrows(function() new Int32Array(ArrayBuffer.prototype)); - checkThrows(function() new Int32Array(Int32Array.prototype)); - checkThrows(function() new Int32Array(Float64Array.prototype)); - checkThrows(function() new Int32Array(ArrayBuffer)); - checkThrows(function() new Int32Array(Int32Array)); - checkThrows(function() new Int32Array(Float64Array)); + // The prototypes are objects that don't have a length property, so they act + // like empty arrays. + check(function() new Int32Array(ArrayBuffer.prototype).length == 0); + check(function() new Int32Array(Int32Array.prototype).length == 0); + check(function() new Int32Array(Float64Array.prototype).length == 0); + + // ArrayBuffer, Int32Array and Float64Array are native functions and have a .length + // checkThrows(function() new Int32Array(ArrayBuffer)); + // checkThrows(function() new Int32Array(Int32Array)); + // checkThrows(function() new Int32Array(Float64Array)); check(function() Int32Array.BYTES_PER_ELEMENT == 4); check(function() (new Int32Array(4)).BYTES_PER_ELEMENT == 4);