author | Bobby Holley <bobbyholley@gmail.com> |
Thu, 19 Jun 2014 09:57:06 -0700 | |
changeset 189623 | a471415834ae635da94c5e8a2344bf31c44118ed |
parent 189622 | fa086a70cfbfc508f298fdbfeeb5066ca801c5d3 |
child 189624 | 206d7f502e142587002b10f96f49e76f0cacf594 |
push id | 26992 |
push user | kwierso@gmail.com |
push date | Fri, 20 Jun 2014 01:07:53 +0000 |
treeherder | mozilla-central@bdac18bd6c74 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | gabor |
bugs | 976148 |
milestone | 33.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/xpconnect/tests/chrome/test_xrayToJS.xul | file | annotate | diff | comparison | revisions | |
js/xpconnect/wrappers/XrayWrapper.cpp | file | annotate | diff | comparison | revisions |
--- a/js/xpconnect/tests/chrome/test_xrayToJS.xul +++ b/js/xpconnect/tests/chrome/test_xrayToJS.xul @@ -48,18 +48,17 @@ https://bugzilla.mozilla.org/show_bug.cg // Test constructors that can be instantiated with zero arguments. for (var c of simpleConstructors) { ok(iwin[c], "Constructors appear: " + c); is(iwin[c], Cu.unwaiveXrays(iwin.wrappedJSObject[c]), "we end up with the appropriate constructor: " + c); is(Cu.unwaiveXrays(Cu.waiveXrays(new iwin[c]).constructor), iwin[c], "constructor property is set up right: " + c); - is(Object.getPrototypeOf(new iwin[c]), - Cu.unwaiveXrays(Cu.waiveXrays(iwin[c]).prototype), + is(Object.getPrototypeOf(new iwin[c]), iwin[c].prototype, "prototype is correct: " + c); is(global(new iwin[c]), iwin, "Got the right global: " + c); } // Test Object in more detail. var num = new iwin.Object(4); is(num.valueOf(), 4, "primitive object construction works"); is(global(num), iwin, "correct global for num");
--- a/js/xpconnect/wrappers/XrayWrapper.cpp +++ b/js/xpconnect/wrappers/XrayWrapper.cpp @@ -412,29 +412,35 @@ public: // the target is the canonical representation of state. If it gets // collected, then expandos and such should be collected too. So there's // nothing to do here. } enum { SLOT_PROTOKEY = 0, SLOT_ISPROTOTYPE, + SLOT_CONSTRUCTOR_FOR, SLOT_COUNT }; virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE; static JSProtoKey getProtoKey(JSObject *holder) { int32_t key = js::GetReservedSlot(holder, SLOT_PROTOKEY).toInt32(); return static_cast<JSProtoKey>(key); } static bool isPrototype(JSObject *holder) { return js::GetReservedSlot(holder, SLOT_ISPROTOTYPE).toBoolean(); } + static JSProtoKey constructorFor(JSObject *holder) { + int32_t key = js::GetReservedSlot(holder, SLOT_CONSTRUCTOR_FOR).toInt32(); + return static_cast<JSProtoKey>(key); + } + static bool getOwnPropertyFromTargetIfSafe(JSContext *cx, HandleObject target, HandleObject wrapper, HandleId id, MutableHandle<JSPropertyDescriptor> desc); static const JSClass HolderClass; static JSXrayTraits singleton; @@ -561,16 +567,35 @@ JSXrayTraits::resolveOwnProperty(JSConte return JS_WrapPropertyDescriptor(cx, desc); } else if (IsTypedArrayKey(key)) { if (IsArrayIndex(GetArrayIndexFromId(cx, id))) { JS_ReportError(cx, "Accessing TypedArray data over Xrays is slow, and forbidden " "in order to encourage performant code. To copy TypedArrays " "across origin boundaries, consider using Components.utils.cloneInto()."); return false; } + } else if (key == JSProto_Function) { + // Handle the 'prototype' property to make xrayedGlobal.StandardClass.prototype work. + if (id == GetRTIdByIndex(cx, XPCJSRuntime::IDX_PROTOTYPE)) { + JSProtoKey standardConstructor = constructorFor(holder); + if (standardConstructor != JSProto_Null) { + RootedObject standardProto(cx); + { + JSAutoCompartment ac(cx, target); + if (!JS_GetClassPrototype(cx, standardConstructor, &standardProto)) + return false; + MOZ_ASSERT(standardProto); + } + if (!JS_WrapObject(cx, &standardProto)) + return false; + FillPropertyDescriptor(desc, wrapper, JSPROP_PERMANENT | JSPROP_READONLY, + ObjectValue(*standardProto)); + return true; + } + } } // The rest of this function applies only to prototypes. return true; } // The non-HasPrototypes semantics implemented by traditional Xrays are kind // of broken with respect to |own|-ness and the holder. The common code @@ -814,16 +839,22 @@ JSXrayTraits::enumerateNames(JSContext * } else if (IsTypedArrayKey(key)) { uint32_t length = JS_GetTypedArrayLength(target); // TypedArrays enumerate every indexed property in range, but // |length| is a getter that lives on the proto, like it should be. if (!props.reserve(length)) return false; for (int32_t i = 0; i <= int32_t(length - 1); ++i) props.infallibleAppend(INT_TO_JSID(i)); + } else if (key == JSProto_Function) { + // Handle the .prototype property on standard constructors. + if (constructorFor(holder) != JSProto_Null) { + if (!props.append(GetRTIdByIndex(cx, XPCJSRuntime::IDX_PROTOTYPE))) + return false; + } } // The rest of this function applies only to prototypes. return true; } // Grab the JSClass. We require all Xrayable classes to have a ClassSpec. const js::Class *clasp = js::GetObjectClass(target); @@ -878,16 +909,23 @@ JSXrayTraits::createHolder(JSContext *cx // Store it on the holder. RootedValue v(cx); v.setNumber(static_cast<uint32_t>(key)); js::SetReservedSlot(holder, SLOT_PROTOKEY, v); v.setBoolean(isPrototype); js::SetReservedSlot(holder, SLOT_ISPROTOTYPE, v); + // If this is a function, also compute whether it serves as a constructor + // for a standard class. + if (key == JSProto_Function) { + v.setNumber(static_cast<uint32_t>(IdentifyStandardConstructor(target))); + js::SetReservedSlot(holder, SLOT_CONSTRUCTOR_FOR, v); + } + return holder; } XPCWrappedNativeXrayTraits XPCWrappedNativeXrayTraits::singleton; DOMXrayTraits DOMXrayTraits::singleton; JSXrayTraits JSXrayTraits::singleton; XrayTraits*