mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 903332 - Make watch/unwatch into proxy hooks and such, and make watching/unwatching work on DOM proxies and windows (or at least work as much as it ever did, which is to say kinda-sorta-ish). r=bhackett, r=efaust
--HG-- extra : rebase_source : b5bae3832b7718b579abb7c09f36c9c46907d7cc
This commit is contained in:
parent
9fa1166172
commit
39bee2a91f
@ -35,6 +35,7 @@ MOCHITEST_FILES = test_bug1682.html \
|
||||
test_viewport.html \
|
||||
test_documentAll.html \
|
||||
test_document-element-inserted.html \
|
||||
test_document.watch.html \
|
||||
$(filter disabled-temporarily--bug-559932, test_bug445004.html) \
|
||||
bug445004-inner.js \
|
||||
bug445004-outer-rel.html \
|
||||
|
129
content/html/document/test/test_document.watch.html
Normal file
129
content/html/document/test/test_document.watch.html
Normal file
@ -0,0 +1,129 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=903332
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 903332</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 903332 **/
|
||||
|
||||
var watch1Called;
|
||||
function watch1(prop, oldValue, newValue)
|
||||
{
|
||||
is(watch1Called, false, "watch1Called not reset properly?");
|
||||
watch1Called = true;
|
||||
|
||||
is(prop, "cookie", "wrong property name passed to watch1");
|
||||
return newValue;
|
||||
}
|
||||
|
||||
var watch2Called;
|
||||
function watch2(prop, oldValue, newValue)
|
||||
{
|
||||
is(watch2Called, false, "watch2Called not reset properly?");
|
||||
watch2Called = true;
|
||||
|
||||
is(prop, "cookie", "wrong property name passed to watch2");
|
||||
return newValue;
|
||||
}
|
||||
|
||||
// Just in case subsequent tests depend on a particular value...
|
||||
var originalValue = document.cookie;
|
||||
ok(true, "originalValue: " + originalValue);
|
||||
|
||||
var originalPrefix = originalValue.length > 0 ? originalValue + "; " : "";
|
||||
|
||||
try
|
||||
{
|
||||
// trial set (no watch) to verify things work
|
||||
document.cookie = "first=set";
|
||||
is(document.cookie, originalPrefix + "first=set",
|
||||
"first value correct");
|
||||
|
||||
// add a watch
|
||||
document.watch("cookie", watch1);
|
||||
|
||||
// set, check for watch invoked
|
||||
watch1Called = false;
|
||||
document.cookie = "second=set";
|
||||
is(watch1Called, true, "watch1 function should be called");
|
||||
is(document.cookie, originalPrefix + "first=set; second=set",
|
||||
"second value correct");
|
||||
|
||||
// and a second time, just in case
|
||||
watch1Called = false;
|
||||
document.cookie = "third=set";
|
||||
is(watch1Called, true, "watch1 function should be called");
|
||||
is(document.cookie, originalPrefix + "first=set; second=set; third=set",
|
||||
"third value correct");
|
||||
|
||||
// overwrite the current watch with a new one
|
||||
document.watch("cookie", watch2);
|
||||
|
||||
// set, check for watch invoked
|
||||
watch1Called = false;
|
||||
watch2Called = false;
|
||||
document.cookie = "fourth=set";
|
||||
is(watch1Called, false, "watch1 invoked erroneously");
|
||||
is(watch2Called, true, "watch2 function should be called");
|
||||
is(document.cookie, originalPrefix + "first=set; second=set; third=set; fourth=set",
|
||||
"fourth value correct");
|
||||
|
||||
// and a second time, just in case
|
||||
watch1Called = false;
|
||||
watch2Called = false;
|
||||
document.cookie = "fifth=set";
|
||||
is(watch1Called, false, "watch1 invoked erroneously");
|
||||
is(watch2Called, true, "watch2 function should be called");
|
||||
is(document.cookie, originalPrefix + "first=set; second=set; third=set; fourth=set; fifth=set",
|
||||
"fifth value correct");
|
||||
|
||||
// remove the watch
|
||||
document.unwatch("cookie");
|
||||
|
||||
// check for non-invocation now
|
||||
watch1Called = false;
|
||||
watch2Called = false;
|
||||
document.cookie = "sixth=set";
|
||||
is(watch1Called, false, "watch1 shouldn't be called");
|
||||
is(watch2Called, false, "watch2 shouldn't be called");
|
||||
is(document.cookie, originalPrefix + "first=set; second=set; third=set; fourth=set; fifth=set; sixth=set",
|
||||
"sixth value correct");
|
||||
}
|
||||
finally
|
||||
{
|
||||
// reset
|
||||
document.unwatch("cookie"); // harmless, should be no-op except if bugs
|
||||
|
||||
var d = new Date();
|
||||
d.setTime(0);
|
||||
var suffix = "=; expires=" + d.toGMTString();
|
||||
|
||||
document.cookie = "first" + suffix;
|
||||
document.cookie = "second" + suffix;
|
||||
document.cookie = "third" + suffix;
|
||||
document.cookie = "fourth" + suffix;
|
||||
document.cookie = "fifth" + suffix;
|
||||
document.cookie = "sixth" + suffix;
|
||||
}
|
||||
|
||||
is(document.cookie, originalValue,
|
||||
"document.cookie isn't what it was initially! expect bustage further " +
|
||||
"down the line");
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=903332">Mozilla Bug 903332</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -604,6 +604,11 @@ public:
|
||||
virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::AutoIdVector &props) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool watch(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id, JS::Handle<JSObject*> callable) MOZ_OVERRIDE;
|
||||
virtual bool unwatch(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id) MOZ_OVERRIDE;
|
||||
|
||||
// Derived traps
|
||||
virtual bool has(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id, bool *bp) MOZ_OVERRIDE;
|
||||
@ -953,6 +958,20 @@ nsOuterWindowProxy::AppendIndexedPropertyNames(JSContext *cx, JSObject *proxy,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsOuterWindowProxy::watch(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id, JS::Handle<JSObject*> callable)
|
||||
{
|
||||
return js::WatchGuts(cx, proxy, id, callable);
|
||||
}
|
||||
|
||||
bool
|
||||
nsOuterWindowProxy::unwatch(JSContext *cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id)
|
||||
{
|
||||
return js::UnwatchGuts(cx, proxy, id);
|
||||
}
|
||||
|
||||
nsOuterWindowProxy
|
||||
nsOuterWindowProxy::singleton;
|
||||
|
||||
|
@ -235,6 +235,19 @@ BaseDOMProxyHandler::enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
(!proto || js::GetPropertyNames(cx, proto, 0, &props));
|
||||
}
|
||||
|
||||
bool
|
||||
BaseDOMProxyHandler::watch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||
JS::Handle<JSObject*> callable)
|
||||
{
|
||||
return js::WatchGuts(cx, proxy, id, callable);
|
||||
}
|
||||
|
||||
bool
|
||||
BaseDOMProxyHandler::unwatch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id)
|
||||
{
|
||||
return js::UnwatchGuts(cx, proxy, id);
|
||||
}
|
||||
|
||||
bool
|
||||
DOMProxyHandler::has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp)
|
||||
{
|
||||
|
@ -58,6 +58,11 @@ public:
|
||||
JS::Handle<jsid> id,
|
||||
JS::MutableHandle<JSPropertyDescriptor> desc,
|
||||
unsigned flags) MOZ_OVERRIDE;
|
||||
|
||||
bool watch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
|
||||
JS::Handle<JSObject*> callable) MOZ_OVERRIDE;
|
||||
bool unwatch(JSContext* cx, JS::Handle<JSObject*> proxy,
|
||||
JS::Handle<jsid> id) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
class DOMProxyHandler : public BaseDOMProxyHandler
|
||||
|
@ -377,6 +377,11 @@ typedef bool
|
||||
typedef bool
|
||||
(* DeleteSpecialOp)(JSContext *cx, JS::HandleObject obj, HandleSpecialId sid, bool *succeeded);
|
||||
|
||||
typedef bool
|
||||
(* WatchOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
|
||||
|
||||
typedef bool
|
||||
(* UnwatchOp)(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
|
||||
|
||||
typedef JSObject *
|
||||
(* ObjectOp)(JSContext *cx, JS::HandleObject obj);
|
||||
@ -465,6 +470,8 @@ struct ObjectOps
|
||||
DeletePropertyOp deleteProperty;
|
||||
DeleteElementOp deleteElement;
|
||||
DeleteSpecialOp deleteSpecial;
|
||||
WatchOp watch;
|
||||
UnwatchOp unwatch;
|
||||
|
||||
JSNewEnumerateOp enumerate;
|
||||
ObjectOp thisObject;
|
||||
@ -473,7 +480,7 @@ struct ObjectOps
|
||||
#define JS_NULL_OBJECT_OPS \
|
||||
{nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \
|
||||
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr, \
|
||||
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}
|
||||
nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr}
|
||||
|
||||
} // namespace js
|
||||
|
||||
@ -502,7 +509,7 @@ struct JSClass {
|
||||
JSNative construct;
|
||||
JSTraceOp trace;
|
||||
|
||||
void *reserved[40];
|
||||
void *reserved[42];
|
||||
};
|
||||
|
||||
#define JSCLASS_HAS_PRIVATE (1<<0) // objects have private slot
|
||||
|
@ -525,9 +525,9 @@ obj_getPrototypeOf(JSContext *cx, unsigned argc, Value *vp)
|
||||
|
||||
#if JS_HAS_OBJ_WATCHPOINT
|
||||
|
||||
static bool
|
||||
obj_watch_handler(JSContext *cx, JSObject *obj_, jsid id_, jsval old,
|
||||
jsval *nvp, void *closure)
|
||||
bool
|
||||
js::WatchHandler(JSContext *cx, JSObject *obj_, jsid id_, JS::Value old,
|
||||
JS::Value *nvp, void *closure)
|
||||
{
|
||||
RootedObject obj(cx, obj_);
|
||||
RootedId id(cx, id_);
|
||||
@ -577,9 +577,11 @@ obj_watch(JSContext *cx, unsigned argc, Value *vp)
|
||||
if (!CheckAccess(cx, obj, propid, JSACC_WATCH, &tmp, &attrs))
|
||||
return false;
|
||||
|
||||
args.rval().setUndefined();
|
||||
if (!JSObject::watch(cx, obj, propid, callable))
|
||||
return false;
|
||||
|
||||
return JS_SetWatchPoint(cx, obj, propid, obj_watch_handler, callable);
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -602,7 +604,7 @@ obj_unwatch(JSContext *cx, unsigned argc, Value *vp)
|
||||
id = JSID_VOID;
|
||||
}
|
||||
|
||||
if (!JS_ClearWatchPoint(cx, obj, id, nullptr, nullptr))
|
||||
if (!JSObject::unwatch(cx, obj, id))
|
||||
return false;
|
||||
|
||||
args.rval().setUndefined();
|
||||
|
@ -8,7 +8,8 @@
|
||||
#define builtin_Object_h
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "js/Value.h"
|
||||
|
||||
namespace JS { class Value; }
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -25,6 +26,10 @@ JSString *
|
||||
ObjectToSource(JSContext *cx, JS::HandleObject obj);
|
||||
#endif // JS_HAS_TOSOURCE
|
||||
|
||||
extern bool
|
||||
WatchHandler(JSContext *cx, JSObject *obj, jsid id, JS::Value old,
|
||||
JS::Value *nvp, void *closure);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#endif /* builtin_Object_h */
|
||||
|
@ -2169,6 +2169,7 @@ const Class TypedObject::class_ = {
|
||||
TypedDatum::obj_deleteProperty,
|
||||
TypedDatum::obj_deleteElement,
|
||||
TypedDatum::obj_deleteSpecial,
|
||||
nullptr, nullptr, // watch/unwatch
|
||||
TypedDatum::obj_enumerate,
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
@ -2259,6 +2260,7 @@ const Class TypedHandle::class_ = {
|
||||
TypedDatum::obj_deleteProperty,
|
||||
TypedDatum::obj_deleteElement,
|
||||
TypedDatum::obj_deleteSpecial,
|
||||
nullptr, nullptr, // watch/unwatch
|
||||
TypedDatum::obj_enumerate,
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
|
@ -1298,6 +1298,33 @@ JS_GetDataViewByteLength(JSObject *obj);
|
||||
JS_FRIEND_API(void *)
|
||||
JS_GetDataViewData(JSObject *obj);
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* Add a watchpoint -- in the Object.prototype.watch sense -- to |obj| for the
|
||||
* property |id|, using the callable object |callable| as the function to be
|
||||
* called for notifications.
|
||||
*
|
||||
* This is an internal function exposed -- temporarily -- only so that DOM
|
||||
* proxies can be watchable. Don't use it! We'll soon kill off the
|
||||
* Object.prototype.{,un}watch functions, at which point this will go too.
|
||||
*/
|
||||
extern JS_FRIEND_API(bool)
|
||||
WatchGuts(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
|
||||
|
||||
/*
|
||||
* Remove a watchpoint -- in the Object.prototype.watch sense -- from |obj| for
|
||||
* the property |id|.
|
||||
*
|
||||
* This is an internal function exposed -- temporarily -- only so that DOM
|
||||
* proxies can be watchable. Don't use it! We'll soon kill off the
|
||||
* Object.prototype.{,un}watch functions, at which point this will go too.
|
||||
*/
|
||||
extern JS_FRIEND_API(bool)
|
||||
UnwatchGuts(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
|
||||
|
||||
} // namespace js
|
||||
|
||||
/*
|
||||
* A class, expected to be passed by value, which represents the CallArgs for a
|
||||
* JSJitGetterOp.
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "jsarray.h"
|
||||
#include "jsatom.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsfun.h"
|
||||
#include "jsgc.h"
|
||||
#include "jsiter.h"
|
||||
@ -35,6 +36,7 @@
|
||||
#include "jswatchpoint.h"
|
||||
#include "jswrapper.h"
|
||||
|
||||
#include "builtin/Object.h"
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "jit/AsmJSModule.h"
|
||||
@ -5010,6 +5012,70 @@ baseops::DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, boo
|
||||
return baseops::DeleteGeneric(cx, obj, id, succeeded);
|
||||
}
|
||||
|
||||
bool
|
||||
js::WatchGuts(JSContext *cx, JS::HandleObject origObj, JS::HandleId id, JS::HandleObject callable)
|
||||
{
|
||||
RootedObject obj(cx, GetInnerObject(cx, origObj));
|
||||
if (origObj != obj) {
|
||||
// If by unwrapping and innerizing, we changed the object, check again
|
||||
// to make sure that we're allowed to set a watch point.
|
||||
RootedValue v(cx);
|
||||
unsigned attrs;
|
||||
if (!CheckAccess(cx, obj, id, JSACC_WATCH, &v, &attrs))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obj->isNative()) {
|
||||
// Use sparse indexes for watched objects, as dense elements can be
|
||||
// written to without checking the watchpoint map.
|
||||
if (!JSObject::sparsifyDenseElements(cx, obj))
|
||||
return false;
|
||||
|
||||
types::MarkTypePropertyConfigured(cx, obj, id);
|
||||
}
|
||||
|
||||
WatchpointMap *wpmap = cx->compartment()->watchpointMap;
|
||||
if (!wpmap) {
|
||||
wpmap = cx->runtime()->new_<WatchpointMap>();
|
||||
if (!wpmap || !wpmap->init()) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
cx->compartment()->watchpointMap = wpmap;
|
||||
}
|
||||
|
||||
return wpmap->watch(cx, obj, id, js::WatchHandler, callable);
|
||||
}
|
||||
|
||||
bool
|
||||
baseops::Watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable)
|
||||
{
|
||||
if (!obj->isNative()) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_WATCH,
|
||||
obj->getClass()->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
return WatchGuts(cx, obj, id, callable);
|
||||
}
|
||||
|
||||
bool
|
||||
js::UnwatchGuts(JSContext *cx, JS::HandleObject origObj, JS::HandleId id)
|
||||
{
|
||||
// Looking in the map for an unsupported object will never hit, so we don't
|
||||
// need to check for nativeness or watchable-ness here.
|
||||
RootedObject obj(cx, GetInnerObject(cx, origObj));
|
||||
if (WatchpointMap *wpmap = cx->compartment()->watchpointMap)
|
||||
wpmap->unwatch(obj, id, nullptr, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
baseops::Unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id)
|
||||
{
|
||||
return UnwatchGuts(cx, obj, id);
|
||||
}
|
||||
|
||||
bool
|
||||
js::HasDataProperty(JSContext *cx, JSObject *obj, jsid id, Value *vp)
|
||||
{
|
||||
|
@ -155,6 +155,12 @@ DeleteSpecial(JSContext *cx, HandleObject obj, HandleSpecialId sid, bool *succee
|
||||
extern bool
|
||||
DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succeeded);
|
||||
|
||||
extern bool
|
||||
Watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable);
|
||||
|
||||
extern bool
|
||||
Unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
|
||||
|
||||
} /* namespace js::baseops */
|
||||
|
||||
extern const Class IntlClass;
|
||||
@ -1093,6 +1099,10 @@ class JSObject : public js::ObjectImpl
|
||||
static bool deleteByValue(JSContext *cx, js::HandleObject obj,
|
||||
const js::Value &property, bool *succeeded);
|
||||
|
||||
static inline bool watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::HandleObject callable);
|
||||
static inline bool unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id);
|
||||
|
||||
static bool enumerate(JSContext *cx, JS::HandleObject obj, JSIterateOp iterop,
|
||||
JS::MutableHandleValue statep, JS::MutableHandleId idp)
|
||||
{
|
||||
|
@ -72,6 +72,21 @@ JSObject::deleteSpecial(JSContext *cx, js::HandleObject obj, js::HandleSpecialId
|
||||
return (op ? op : js::baseops::DeleteSpecial)(cx, obj, sid, succeeded);
|
||||
}
|
||||
|
||||
/* static */ inline bool
|
||||
JSObject::watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id,
|
||||
JS::HandleObject callable)
|
||||
{
|
||||
js::WatchOp op = obj->getOps()->watch;
|
||||
return (op ? op : js::baseops::Watch)(cx, obj, id, callable);
|
||||
}
|
||||
|
||||
/* static */ inline bool
|
||||
JSObject::unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id)
|
||||
{
|
||||
js::UnwatchOp op = obj->getOps()->unwatch;
|
||||
return (op ? op : js::baseops::Unwatch)(cx, obj, id);
|
||||
}
|
||||
|
||||
inline void
|
||||
JSObject::finalize(js::FreeOp *fop)
|
||||
{
|
||||
|
@ -371,6 +371,19 @@ BaseProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandl
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
BaseProxyHandler::watch(JSContext *cx, HandleObject proxy, HandleId id, HandleObject callable)
|
||||
{
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_CANT_WATCH,
|
||||
proxy->getClass()->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
BaseProxyHandler::unwatch(JSContext *cx, HandleObject proxy, HandleId id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
DirectProxyHandler::getPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
|
||||
@ -2747,6 +2760,20 @@ Proxy::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject pro
|
||||
|
||||
JSObject * const Proxy::LazyProto = reinterpret_cast<JSObject *>(0x1);
|
||||
|
||||
/* static */ bool
|
||||
Proxy::watch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id, JS::HandleObject callable)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
return proxy->as<ProxyObject>().handler()->watch(cx, proxy, id, callable);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Proxy::unwatch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id)
|
||||
{
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
return proxy->as<ProxyObject>().handler()->unwatch(cx, proxy, id);
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
proxy_innerObject(JSContext *cx, HandleObject obj)
|
||||
{
|
||||
@ -3046,6 +3073,18 @@ proxy_Construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
return Proxy::construct(cx, proxy, args);
|
||||
}
|
||||
|
||||
static bool
|
||||
proxy_Watch(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::HandleObject callable)
|
||||
{
|
||||
return Proxy::watch(cx, obj, id, callable);
|
||||
}
|
||||
|
||||
static bool
|
||||
proxy_Unwatch(JSContext *cx, JS::HandleObject obj, JS::HandleId id)
|
||||
{
|
||||
return Proxy::unwatch(cx, obj, id);
|
||||
}
|
||||
|
||||
#define PROXY_CLASS_EXT \
|
||||
{ \
|
||||
nullptr, /* outerObject */ \
|
||||
@ -3098,6 +3137,7 @@ proxy_Construct(JSContext *cx, unsigned argc, Value *vp)
|
||||
proxy_DeleteProperty, \
|
||||
proxy_DeleteElement, \
|
||||
proxy_DeleteSpecial, \
|
||||
proxy_Watch, proxy_Unwatch, \
|
||||
nullptr, /* enumerate */ \
|
||||
nullptr, /* thisObject */ \
|
||||
} \
|
||||
@ -3155,6 +3195,7 @@ const Class js::OuterWindowProxyObject::class_ = {
|
||||
proxy_DeleteProperty,
|
||||
proxy_DeleteElement,
|
||||
proxy_DeleteSpecial,
|
||||
proxy_Watch, proxy_Unwatch,
|
||||
nullptr, /* enumerate */
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
|
@ -166,6 +166,12 @@ class JS_FRIEND_API(BaseProxyHandler)
|
||||
uint32_t index, MutableHandleValue vp, bool *present);
|
||||
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
|
||||
|
||||
// These two hooks must be overridden, or not overridden, in tandem -- no
|
||||
// overriding just one!
|
||||
virtual bool watch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
||||
JS::HandleObject callable);
|
||||
virtual bool unwatch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id);
|
||||
|
||||
/* See comment for weakmapKeyDelegateOp in js/Class.h. */
|
||||
virtual JSObject *weakmapKeyDelegate(JSObject *proxy);
|
||||
};
|
||||
@ -275,6 +281,10 @@ class Proxy
|
||||
static bool defaultValue(JSContext *cx, HandleObject obj, JSType hint, MutableHandleValue vp);
|
||||
static bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop);
|
||||
|
||||
static bool watch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id,
|
||||
JS::HandleObject callable);
|
||||
static bool unwatch(JSContext *cx, JS::HandleObject proxy, JS::HandleId id);
|
||||
|
||||
/* IC entry path for handling __noSuchMethod__ on access. */
|
||||
static bool callProp(JSContext *cx, HandleObject proxy, HandleObject reveiver, HandleId id,
|
||||
MutableHandleValue vp);
|
||||
|
@ -536,6 +536,7 @@ const Class WithObject::class_ = {
|
||||
with_DeleteProperty,
|
||||
with_DeleteElement,
|
||||
with_DeleteSpecial,
|
||||
nullptr, nullptr, /* watch/unwatch */
|
||||
with_Enumerate,
|
||||
with_ThisObject,
|
||||
}
|
||||
|
@ -3470,6 +3470,7 @@ const Class ArrayBufferObject::class_ = {
|
||||
ArrayBufferObject::obj_deleteProperty,
|
||||
ArrayBufferObject::obj_deleteElement,
|
||||
ArrayBufferObject::obj_deleteSpecial,
|
||||
nullptr, nullptr, /* watch/unwatch */
|
||||
ArrayBufferObject::obj_enumerate,
|
||||
nullptr, /* thisObject */
|
||||
}
|
||||
@ -3632,6 +3633,7 @@ IMPL_TYPED_ARRAY_COMBINED_UNWRAPPERS(Float64, double, double)
|
||||
_typedArray##Object::obj_deleteProperty, \
|
||||
_typedArray##Object::obj_deleteElement, \
|
||||
_typedArray##Object::obj_deleteSpecial, \
|
||||
nullptr, nullptr, /* watch/unwatch */ \
|
||||
_typedArray##Object::obj_enumerate, \
|
||||
nullptr, /* thisObject */ \
|
||||
} \
|
||||
|
@ -739,6 +739,7 @@ const XPCWrappedNativeJSClass XPC_WN_NoHelper_JSClass = {
|
||||
nullptr, // deleteProperty
|
||||
nullptr, // deleteElement
|
||||
nullptr, // deleteSpecial
|
||||
nullptr, nullptr, // watch/unwatch
|
||||
XPC_WN_JSOp_Enumerate,
|
||||
XPC_WN_JSOp_ThisObject,
|
||||
}
|
||||
|
@ -1172,6 +1172,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
|
||||
nullptr, /* deleteProperty */ \
|
||||
nullptr, /* deleteElement */ \
|
||||
nullptr, /* deleteSpecial */ \
|
||||
nullptr, nullptr, /* watch/unwatch */ \
|
||||
XPC_WN_JSOp_Enumerate, \
|
||||
XPC_WN_JSOp_ThisObject, \
|
||||
}
|
||||
@ -1200,6 +1201,7 @@ XPC_WN_JSOp_ThisObject(JSContext *cx, JS::HandleObject obj);
|
||||
nullptr, /* deleteProperty */ \
|
||||
nullptr, /* deleteElement */ \
|
||||
nullptr, /* deleteSpecial */ \
|
||||
nullptr, nullptr, /* watch/unwatch */ \
|
||||
XPC_WN_JSOp_Enumerate, \
|
||||
XPC_WN_JSOp_ThisObject, \
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user