|
1 // Test that the watch handler is not called recursively for the same object |
|
2 // and property. |
|
3 (function() { |
|
4 var obj1 = {}, obj2 = {}; |
|
5 var handler_entry_count = 0; |
|
6 var handler_exit_count = 0; |
|
7 |
|
8 obj1.watch('x', handler); |
|
9 obj1.watch('y', handler); |
|
10 obj2.watch('x', handler); |
|
11 obj1.x = 1; |
|
12 assertEq(handler_entry_count, 3); |
|
13 assertEq(handler_exit_count, 3); |
|
14 |
|
15 function handler(id) { |
|
16 handler_entry_count++; |
|
17 assertEq(handler_exit_count, 0); |
|
18 switch (true) { |
|
19 case this === obj1 && id === "x": |
|
20 assertEq(handler_entry_count, 1); |
|
21 obj2.x = 3; |
|
22 assertEq(handler_exit_count, 2); |
|
23 break; |
|
24 case this === obj2 && id === "x": |
|
25 assertEq(handler_entry_count, 2); |
|
26 obj1.y = 4; |
|
27 assertEq(handler_exit_count, 1); |
|
28 break; |
|
29 default: |
|
30 assertEq(this, obj1); |
|
31 assertEq(id, "y"); |
|
32 assertEq(handler_entry_count, 3); |
|
33 |
|
34 // We expect no more watch handler invocations |
|
35 obj1.x = 5; |
|
36 obj1.y = 6; |
|
37 obj2.x = 7; |
|
38 assertEq(handler_exit_count, 0); |
|
39 break; |
|
40 } |
|
41 ++handler_exit_count; |
|
42 assertEq(handler_entry_count, 3); |
|
43 } |
|
44 })(); |
|
45 |
|
46 |
|
47 // Test that run-away recursion in watch handlers is properly handled. |
|
48 (function() { |
|
49 var obj = {}; |
|
50 var i = 0; |
|
51 try { |
|
52 handler(); |
|
53 throw new Error("Unreachable"); |
|
54 } catch(e) { |
|
55 assertEq(e instanceof InternalError, true); |
|
56 } |
|
57 |
|
58 function handler() { |
|
59 var prop = "a" + ++i; |
|
60 obj.watch(prop, handler); |
|
61 obj[prop] = 2; |
|
62 } |
|
63 })(); |