| /* |
| * Any copyright is dedicated to the Public Domain. |
| * http://creativecommons.org/licenses/publicdomain/ |
| */ |
| |
| function make_watcher(name) { |
| return function (id, oldv, newv) { |
| print("watched " + name + "[0]"); |
| }; |
| } |
| |
| var o, p; |
| function f(flag) { |
| if (flag) { |
| o = arguments; |
| } else { |
| p = arguments; |
| o.watch(0, make_watcher('o')); |
| p.watch(0, make_watcher('p')); |
| |
| /* |
| * Previously, the watchpoint implementation actually substituted its magic setter |
| * functions for the setters of shared shapes, and then 1) carefully ignored calls |
| * to its magic setter from unrelated objects, and 2) avoided restoring the |
| * original setter until all watchpoints on that shape had been removed. |
| * |
| * However, when the watchpoint code began using JSObject::changeProperty and |
| * js_ChangeNativePropertyAttrs to change shapes' setters, the shape tree code |
| * became conscious of the presence of watchpoints, and shared shapes between |
| * objects only when their watchpoint nature coincided. Clearing the magic setter |
| * from one object's shape would not affect other objects, because the |
| * watchpointed and non-watchpointed shapes were distinct if they were shared. |
| * |
| * Thus, the first unwatch call must go ahead and fix p's shape, even though a |
| * watchpoint exists on the same shape in o. o's watchpoint's presence shouldn't |
| * cause 'unwatch' to leave p's magic setter in place. |
| */ |
| |
| /* DropWatchPointAndUnlock would see o's watchpoint, and not change p's property. */ |
| p.unwatch(0); |
| |
| /* DropWatchPointAndUnlock would fix o's property, but not p's; p's setter would be gone. */ |
| o.unwatch(0); |
| |
| /* This would fail to invoke the arguments object's setter. */ |
| p[0] = 4; |
| |
| /* And the formal parameter would not get updated. */ |
| assertEq(flag, 4); |
| } |
| } |
| |
| f(true); |
| f(false); |
| |
| reportCompare(true, true); |