diff --git a/js/src/jit-test/tests/basic/testAssigningWatchedDeletedProperty.js b/js/src/jit-test/tests/basic/testAssigningWatchedDeletedProperty.js new file mode 100644 index 000000000000..62fa710f5a98 --- /dev/null +++ b/js/src/jit-test/tests/basic/testAssigningWatchedDeletedProperty.js @@ -0,0 +1,7 @@ +var o = {}; +o.watch("p", function() { }); + +for (var i = 0; i < HOTLOOP + 2; i++) { + o.p = 123; + delete o.p; +} diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index de6b58526be3..f40244d144dd 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -576,9 +576,6 @@ struct JSWatchPoint { #define JSWP_LIVE 0x1 /* live because set and not cleared */ #define JSWP_HELD 0x2 /* held while running handler/setter */ -static bool -IsWatchedProperty(JSContext *cx, const Shape *shape); - /* * NB: DropWatchPointAndUnlock releases cx->runtime->debuggerLock in all cases. */ @@ -770,7 +767,9 @@ js_watch_set_wrapper(JSContext *cx, uintN argc, Value *vp) return js_watch_set(cx, obj, userid, vp); } -static bool +namespace js { + +bool IsWatchedProperty(JSContext *cx, const Shape *shape) { if (shape->hasSetterValue()) { @@ -778,12 +777,14 @@ IsWatchedProperty(JSContext *cx, const Shape *shape) if (!funobj || !funobj->isFunction()) return false; - JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj); + JSFunction *fun = funobj->getFunctionPrivate(); return fun->maybeNative() == js_watch_set_wrapper; } return shape->setterOp() == js_watch_set; } +} + /* * Return an appropriate setter to substitute for |setter| on a property * with attributes |attrs|, to implement a watchpoint on the property named diff --git a/js/src/jsdbgapi.h b/js/src/jsdbgapi.h index fc476fac3f01..494d0eaf51d5 100644 --- a/js/src/jsdbgapi.h +++ b/js/src/jsdbgapi.h @@ -159,6 +159,13 @@ js_SweepWatchPoints(JSContext *cx); extern JSBool js_watch_set(JSContext *cx, JSObject *obj, jsid id, js::Value *vp); +namespace js { + +bool +IsWatchedProperty(JSContext *cx, const Shape *shape); + +} + #endif #endif /* JS_HAS_OBJ_WATCHPOINT */ diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 08fc958596fb..6a40dbc465de 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -12241,6 +12241,11 @@ TraceRecorder::record_AddProperty(JSObject *obj) LIns* v_ins = get(&v); const Shape* shape = obj->lastProperty(); + if (!shape->hasDefaultSetter()) { + JS_ASSERT(IsWatchedProperty(cx, shape)); + RETURN_STOP_A("assignment adds property with watchpoint"); + } + #ifdef DEBUG JS_ASSERT(addPropShapeBefore); if (obj->inDictionaryMode())