mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 1270746 part 3 - Replace hasInstance JSClass hook on wrapped natives with a Symbol.hasInstance native. r=peterv
Resolve a `Symbol.hasInstance` native function that works like the class hook. Differential Revision: https://phabricator.services.mozilla.com/D141344
This commit is contained in:
parent
b2ea1ec05f
commit
07e7d34e88
@ -40,63 +40,59 @@ void XPC_WN_NoHelper_Finalize(JS::GCContext* gcx, JSObject* obj);
|
||||
|
||||
bool XPC_WN_Helper_Call(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
bool XPC_WN_Helper_HasInstance(JSContext* cx, JS::HandleObject obj,
|
||||
JS::MutableHandleValue valp, bool* bp);
|
||||
|
||||
bool XPC_WN_Helper_Construct(JSContext* cx, unsigned argc, JS::Value* vp);
|
||||
|
||||
void XPCWrappedNative_Trace(JSTracer* trc, JSObject* obj);
|
||||
|
||||
extern const js::ClassExtension XPC_WN_JSClassExtension;
|
||||
|
||||
#define XPC_MAKE_CLASS_OPS(_flags) \
|
||||
{ \
|
||||
/* addProperty */ \
|
||||
((_flags)&XPC_SCRIPTABLE_USE_JSSTUB_FOR_ADDPROPERTY) ? nullptr \
|
||||
: ((_flags)&XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE) \
|
||||
? XPC_WN_MaybeResolvingPropertyStub \
|
||||
: XPC_WN_CannotModifyPropertyStub, \
|
||||
\
|
||||
/* delProperty */ \
|
||||
((_flags)&XPC_SCRIPTABLE_USE_JSSTUB_FOR_DELPROPERTY) ? nullptr \
|
||||
: ((_flags)&XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE) \
|
||||
? XPC_WN_MaybeResolvingDeletePropertyStub \
|
||||
: XPC_WN_CannotDeletePropertyStub, \
|
||||
\
|
||||
/* enumerate */ \
|
||||
((_flags)&XPC_SCRIPTABLE_WANT_NEWENUMERATE) \
|
||||
? nullptr /* We will use newEnumerate set below in this case */ \
|
||||
: XPC_WN_Shared_Enumerate, \
|
||||
\
|
||||
/* newEnumerate */ \
|
||||
((_flags)&XPC_SCRIPTABLE_WANT_NEWENUMERATE) ? XPC_WN_NewEnumerate \
|
||||
: nullptr, \
|
||||
\
|
||||
/* resolve */ /* We have to figure out resolve strategy at call time \
|
||||
*/ \
|
||||
XPC_WN_Helper_Resolve, \
|
||||
\
|
||||
/* mayResolve */ \
|
||||
nullptr, \
|
||||
\
|
||||
/* finalize */ \
|
||||
((_flags)&XPC_SCRIPTABLE_WANT_FINALIZE) ? XPC_WN_Helper_Finalize \
|
||||
: XPC_WN_NoHelper_Finalize, \
|
||||
\
|
||||
/* call */ \
|
||||
((_flags)&XPC_SCRIPTABLE_WANT_CALL) ? XPC_WN_Helper_Call : nullptr, \
|
||||
\
|
||||
/* hasInstance */ \
|
||||
((_flags)&XPC_SCRIPTABLE_WANT_HASINSTANCE) ? XPC_WN_Helper_HasInstance \
|
||||
: nullptr, \
|
||||
\
|
||||
/* construct */ \
|
||||
((_flags)&XPC_SCRIPTABLE_WANT_CONSTRUCT) ? XPC_WN_Helper_Construct \
|
||||
: nullptr, \
|
||||
\
|
||||
/* trace */ \
|
||||
((_flags)&XPC_SCRIPTABLE_IS_GLOBAL_OBJECT) ? JS_GlobalObjectTraceHook \
|
||||
: XPCWrappedNative_Trace, \
|
||||
#define XPC_MAKE_CLASS_OPS(_flags) \
|
||||
{ \
|
||||
/* addProperty */ \
|
||||
((_flags)&XPC_SCRIPTABLE_USE_JSSTUB_FOR_ADDPROPERTY) ? nullptr \
|
||||
: ((_flags)&XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE) \
|
||||
? XPC_WN_MaybeResolvingPropertyStub \
|
||||
: XPC_WN_CannotModifyPropertyStub, \
|
||||
\
|
||||
/* delProperty */ \
|
||||
((_flags)&XPC_SCRIPTABLE_USE_JSSTUB_FOR_DELPROPERTY) ? nullptr \
|
||||
: ((_flags)&XPC_SCRIPTABLE_ALLOW_PROP_MODS_DURING_RESOLVE) \
|
||||
? XPC_WN_MaybeResolvingDeletePropertyStub \
|
||||
: XPC_WN_CannotDeletePropertyStub, \
|
||||
\
|
||||
/* enumerate */ \
|
||||
((_flags)&XPC_SCRIPTABLE_WANT_NEWENUMERATE) \
|
||||
? nullptr /* We will use newEnumerate set below in this case */ \
|
||||
: XPC_WN_Shared_Enumerate, \
|
||||
\
|
||||
/* newEnumerate */ \
|
||||
((_flags)&XPC_SCRIPTABLE_WANT_NEWENUMERATE) ? XPC_WN_NewEnumerate \
|
||||
: nullptr, \
|
||||
\
|
||||
/* resolve */ /* We have to figure out resolve strategy at call time \
|
||||
*/ \
|
||||
XPC_WN_Helper_Resolve, \
|
||||
\
|
||||
/* mayResolve */ \
|
||||
nullptr, \
|
||||
\
|
||||
/* finalize */ \
|
||||
((_flags)&XPC_SCRIPTABLE_WANT_FINALIZE) ? XPC_WN_Helper_Finalize \
|
||||
: XPC_WN_NoHelper_Finalize, \
|
||||
\
|
||||
/* call */ \
|
||||
((_flags)&XPC_SCRIPTABLE_WANT_CALL) ? XPC_WN_Helper_Call : nullptr, \
|
||||
\
|
||||
/* hasInstance */ \
|
||||
nullptr, \
|
||||
\
|
||||
/* construct */ \
|
||||
((_flags)&XPC_SCRIPTABLE_WANT_CONSTRUCT) ? XPC_WN_Helper_Construct \
|
||||
: nullptr, \
|
||||
\
|
||||
/* trace */ \
|
||||
((_flags)&XPC_SCRIPTABLE_IS_GLOBAL_OBJECT) ? JS_GlobalObjectTraceHook \
|
||||
: XPCWrappedNative_Trace, \
|
||||
}
|
||||
|
||||
#define XPC_MAKE_CLASS(_name, _flags, _classOps) \
|
||||
|
@ -753,12 +753,25 @@ bool XPC_WN_Helper_Construct(JSContext* cx, unsigned argc, Value* vp) {
|
||||
POST_HELPER_STUB
|
||||
}
|
||||
|
||||
bool XPC_WN_Helper_HasInstance(JSContext* cx, HandleObject obj,
|
||||
MutableHandleValue valp, bool* bp) {
|
||||
static bool XPC_WN_Helper_HasInstance(JSContext* cx, unsigned argc, Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (!args.requireAtLeast(cx, "WrappedNative[Symbol.hasInstance]", 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!args.thisv().isObject()) {
|
||||
JS_ReportErrorASCII(
|
||||
cx, "WrappedNative[Symbol.hasInstance]: unexpected this value");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject obj(cx, &args.thisv().toObject());
|
||||
RootedValue val(cx, args.get(0));
|
||||
|
||||
bool retval2;
|
||||
PRE_HELPER_STUB
|
||||
HasInstance(wrapper, cx, obj, valp, &retval2, &retval);
|
||||
*bp = retval2;
|
||||
HasInstance(wrapper, cx, obj, val, &retval2, &retval);
|
||||
args.rval().setBoolean(retval2);
|
||||
POST_HELPER_STUB
|
||||
}
|
||||
|
||||
@ -795,6 +808,24 @@ bool XPC_WN_Helper_Resolve(JSContext* cx, HandleObject obj, HandleId id,
|
||||
RootedId old(cx, ccx.SetResolveName(id));
|
||||
|
||||
nsCOMPtr<nsIXPCScriptable> scr = wrapper->GetScriptable();
|
||||
|
||||
// Resolve a Symbol.hasInstance property if we want custom `instanceof`
|
||||
// behavior.
|
||||
if (scr && scr->WantHasInstance() &&
|
||||
id.isWellKnownSymbol(SymbolCode::hasInstance)) {
|
||||
mozilla::Maybe<AutoSetResolvingWrapper> asrw;
|
||||
if (scr->AllowPropModsDuringResolve()) {
|
||||
asrw.emplace(ccx, wrapper);
|
||||
}
|
||||
if (!JS_DefineFunctionById(
|
||||
cx, obj, id, XPC_WN_Helper_HasInstance, 1,
|
||||
JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_RESOLVING)) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
} else {
|
||||
resolved = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (scr && scr->WantResolve()) {
|
||||
mozilla::Maybe<AutoSetResolvingWrapper> asrw;
|
||||
if (scr->AllowPropModsDuringResolve()) {
|
||||
|
23
js/xpconnect/tests/unit/test_xpcwn_instanceof.js
Normal file
23
js/xpconnect/tests/unit/test_xpcwn_instanceof.js
Normal file
@ -0,0 +1,23 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Tests for custom `instanceof` behavior via XPC_SCRIPTABLE_WANT_HASINSTANCE.
|
||||
|
||||
add_task(function id_instanceof() {
|
||||
// ID objects are instances of Components.ID.
|
||||
let id = Components.ID("{f2f5c784-7f6c-43f5-81b0-45ff32c312b1}");
|
||||
Assert.equal(id instanceof Components.ID, true);
|
||||
Assert.equal({} instanceof Components.ID, false);
|
||||
Assert.equal(null instanceof Components.ID, false);
|
||||
|
||||
// Components.ID has a Symbol.hasInstance function.
|
||||
let desc = Object.getOwnPropertyDescriptor(Components.ID, Symbol.hasInstance);
|
||||
Assert.equal(typeof desc, "object");
|
||||
Assert.equal(typeof desc.value, "function");
|
||||
|
||||
// Test error handling when calling this function with unexpected values.
|
||||
Assert.throws(() => desc.value.call(null), /At least 1 argument required/);
|
||||
Assert.throws(() => desc.value.call(null, 1), /unexpected this value/);
|
||||
Assert.throws(() => desc.value.call({}, {}), /NS_ERROR_XPC_BAD_OP_ON_WN_PROTO/);
|
||||
});
|
@ -142,6 +142,7 @@ head = head_watchdog.js
|
||||
[test_watchdog_hibernate.js]
|
||||
head = head_watchdog.js
|
||||
[test_weak_keys.js]
|
||||
[test_xpcwn_instanceof.js]
|
||||
[test_xpcwn_tamperproof.js]
|
||||
[test_xrayed_arguments.js]
|
||||
[test_xrayed_iterator.js]
|
||||
|
Loading…
Reference in New Issue
Block a user