1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/tests/ecma_5/extensions/watchpoint-deletes-JSPropertyOp-setter.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,56 @@ 1.4 +/* 1.5 + * Any copyright is dedicated to the Public Domain. 1.6 + * http://creativecommons.org/licenses/publicdomain/ 1.7 + */ 1.8 + 1.9 +function make_watcher(name) { 1.10 + return function (id, oldv, newv) { 1.11 + print("watched " + name + "[0]"); 1.12 + }; 1.13 +} 1.14 + 1.15 +var o, p; 1.16 +function f(flag) { 1.17 + if (flag) { 1.18 + o = arguments; 1.19 + } else { 1.20 + p = arguments; 1.21 + o.watch(0, make_watcher('o')); 1.22 + p.watch(0, make_watcher('p')); 1.23 + 1.24 + /* 1.25 + * Previously, the watchpoint implementation actually substituted its magic setter 1.26 + * functions for the setters of shared shapes, and then 1) carefully ignored calls 1.27 + * to its magic setter from unrelated objects, and 2) avoided restoring the 1.28 + * original setter until all watchpoints on that shape had been removed. 1.29 + * 1.30 + * However, when the watchpoint code began using JSObject::changeProperty and 1.31 + * js_ChangeNativePropertyAttrs to change shapes' setters, the shape tree code 1.32 + * became conscious of the presence of watchpoints, and shared shapes between 1.33 + * objects only when their watchpoint nature coincided. Clearing the magic setter 1.34 + * from one object's shape would not affect other objects, because the 1.35 + * watchpointed and non-watchpointed shapes were distinct if they were shared. 1.36 + * 1.37 + * Thus, the first unwatch call must go ahead and fix p's shape, even though a 1.38 + * watchpoint exists on the same shape in o. o's watchpoint's presence shouldn't 1.39 + * cause 'unwatch' to leave p's magic setter in place. 1.40 + */ 1.41 + 1.42 + /* DropWatchPointAndUnlock would see o's watchpoint, and not change p's property. */ 1.43 + p.unwatch(0); 1.44 + 1.45 + /* DropWatchPointAndUnlock would fix o's property, but not p's; p's setter would be gone. */ 1.46 + o.unwatch(0); 1.47 + 1.48 + /* This would fail to invoke the arguments object's setter. */ 1.49 + p[0] = 4; 1.50 + 1.51 + /* And the formal parameter would not get updated. */ 1.52 + assertEq(flag, 4); 1.53 + } 1.54 +} 1.55 + 1.56 +f(true); 1.57 +f(false); 1.58 + 1.59 +reportCompare(true, true);