michael@0: // Test that the watch handler is not called recursively for the same object michael@0: // and property. michael@0: (function() { michael@0: var obj1 = {}, obj2 = {}; michael@0: var handler_entry_count = 0; michael@0: var handler_exit_count = 0; michael@0: michael@0: obj1.watch('x', handler); michael@0: obj1.watch('y', handler); michael@0: obj2.watch('x', handler); michael@0: obj1.x = 1; michael@0: assertEq(handler_entry_count, 3); michael@0: assertEq(handler_exit_count, 3); michael@0: michael@0: function handler(id) { michael@0: handler_entry_count++; michael@0: assertEq(handler_exit_count, 0); michael@0: switch (true) { michael@0: case this === obj1 && id === "x": michael@0: assertEq(handler_entry_count, 1); michael@0: obj2.x = 3; michael@0: assertEq(handler_exit_count, 2); michael@0: break; michael@0: case this === obj2 && id === "x": michael@0: assertEq(handler_entry_count, 2); michael@0: obj1.y = 4; michael@0: assertEq(handler_exit_count, 1); michael@0: break; michael@0: default: michael@0: assertEq(this, obj1); michael@0: assertEq(id, "y"); michael@0: assertEq(handler_entry_count, 3); michael@0: michael@0: // We expect no more watch handler invocations michael@0: obj1.x = 5; michael@0: obj1.y = 6; michael@0: obj2.x = 7; michael@0: assertEq(handler_exit_count, 0); michael@0: break; michael@0: } michael@0: ++handler_exit_count; michael@0: assertEq(handler_entry_count, 3); michael@0: } michael@0: })(); michael@0: michael@0: michael@0: // Test that run-away recursion in watch handlers is properly handled. michael@0: (function() { michael@0: var obj = {}; michael@0: var i = 0; michael@0: try { michael@0: handler(); michael@0: throw new Error("Unreachable"); michael@0: } catch(e) { michael@0: assertEq(e instanceof InternalError, true); michael@0: } michael@0: michael@0: function handler() { michael@0: var prop = "a" + ++i; michael@0: obj.watch(prop, handler); michael@0: obj[prop] = 2; michael@0: } michael@0: })();