Ben Murdoch | c561043 | 2016-08-08 18:44:38 +0100 | [diff] [blame] | 1 | // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | // Flags: --expose-debug-as debug --no-always-opt |
| 6 | |
| 7 | // Test that the (strict) eval scope is visible to the debugger. |
| 8 | |
| 9 | var Debug = debug.Debug; |
| 10 | var exception = null; |
| 11 | var delegate = null; |
| 12 | |
| 13 | function listener(event, exec_state, event_data, data) { |
| 14 | if (event != Debug.DebugEvent.Break) return; |
| 15 | try { |
| 16 | delegate(exec_state); |
| 17 | } catch (e) { |
| 18 | exception = e; |
| 19 | } |
| 20 | } |
| 21 | |
| 22 | Debug.setListener(listener); |
| 23 | |
| 24 | // Current function is the top-level eval. |
| 25 | // We can access stack- and context-allocated values in the eval-scope. |
| 26 | delegate = function(exec_state) { |
| 27 | assertEquals([ debug.ScopeType.Eval, |
| 28 | debug.ScopeType.Script, |
| 29 | debug.ScopeType.Global ], |
| 30 | exec_state.frame(0).allScopes().map(s => s.scopeType())); |
| 31 | var scope = exec_state.frame(0).scope(0); |
| 32 | assertEquals(1, scope.scopeObject().property("a").value().value()); |
| 33 | assertEquals(1, exec_state.frame(0).evaluate("a").value()); |
| 34 | scope.setVariableValue("a", 2); |
| 35 | assertEquals(2, exec_state.frame(0).evaluate("a++").value()); |
| 36 | } |
| 37 | |
| 38 | eval("'use strict'; \n" + |
| 39 | "var a = 1; \n" + |
| 40 | "debugger; \n" + |
| 41 | "assertEquals(3, a);\n"); |
| 42 | |
| 43 | eval("'use strict'; \n" + |
| 44 | "var a = 1; \n" + |
| 45 | "(x=>a); \n" + // Force context-allocation. |
| 46 | "debugger; \n" + |
| 47 | "assertEquals(3, a);\n"); |
| 48 | |
| 49 | // Current function is an inner function. |
| 50 | // We cannot access stack-allocated values in the eval-scope. |
| 51 | delegate = function(exec_state) { |
| 52 | assertEquals([ debug.ScopeType.Local, |
| 53 | debug.ScopeType.Script, |
| 54 | debug.ScopeType.Global ], |
| 55 | exec_state.frame(0).allScopes().map(s => s.scopeType())); |
| 56 | assertEquals([ debug.ScopeType.Eval, |
| 57 | debug.ScopeType.Script, |
| 58 | debug.ScopeType.Global ], |
| 59 | exec_state.frame(1).allScopes().map(s => s.scopeType())); |
| 60 | var scope = exec_state.frame(0).scope(0); |
| 61 | assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError); |
| 62 | assertTrue(scope.scopeObject().property("a").isUndefined()); |
| 63 | } |
| 64 | |
| 65 | eval("'use strict'; \n" + |
| 66 | "var a = 1; \n" + |
| 67 | "(() => {debugger})()\n"); |
| 68 | |
| 69 | // Current function is an escaped inner function. |
| 70 | delegate = function(exec_state) { |
| 71 | assertEquals([ debug.ScopeType.Local, |
| 72 | debug.ScopeType.Script, |
| 73 | debug.ScopeType.Global ], |
| 74 | exec_state.frame(0).allScopes().map(s => s.scopeType())); |
| 75 | assertEquals([ debug.ScopeType.Script, |
| 76 | debug.ScopeType.Global ], |
| 77 | exec_state.frame(1).allScopes().map(s => s.scopeType())); |
| 78 | var scope = exec_state.frame(0).scope(0); |
| 79 | assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError); |
| 80 | assertTrue(scope.scopeObject().property("a").isUndefined()); |
| 81 | } |
| 82 | |
| 83 | var f = eval("'use strict'; \n" + |
| 84 | "var a = 1; \n" + |
| 85 | "() => {debugger}\n"); |
| 86 | f(); |
| 87 | |
| 88 | // Current function is an inner function. |
| 89 | // We can access context-allocated values in the eval-scope. |
| 90 | delegate = function(exec_state) { |
| 91 | assertEquals([ debug.ScopeType.Local, |
| 92 | debug.ScopeType.Closure, |
| 93 | debug.ScopeType.Script, |
| 94 | debug.ScopeType.Global ], |
| 95 | exec_state.frame(0).allScopes().map(s => s.scopeType())); |
| 96 | assertEquals([ debug.ScopeType.Eval, |
| 97 | debug.ScopeType.Script, |
| 98 | debug.ScopeType.Global ], |
| 99 | exec_state.frame(1).allScopes().map(s => s.scopeType())); |
| 100 | var scope = exec_state.frame(1).scope(0); |
| 101 | assertEquals(1, scope.scopeObject().property("a").value().value()); |
| 102 | assertEquals(1, exec_state.frame(1).evaluate("a").value()); |
| 103 | assertEquals(1, exec_state.frame(0).evaluate("a").value()); |
| 104 | scope.setVariableValue("a", 2); |
| 105 | assertEquals(2, exec_state.frame(0).evaluate("a++").value()); |
| 106 | assertEquals(3, exec_state.frame(1).evaluate("a++").value()); |
| 107 | } |
| 108 | |
| 109 | eval("'use strict'; \n" + |
| 110 | "var a = 1; \n" + |
| 111 | "(() => { a; \n" + // Force context-allocation. |
| 112 | " debugger; \n" + |
| 113 | " assertEquals(4, a);\n" + |
| 114 | " })(); \n" |
| 115 | ); |
| 116 | |
| 117 | // Current function is an escaped inner function. |
| 118 | // We can access context-allocated values in the eval-scope. |
| 119 | delegate = function(exec_state) { |
| 120 | assertEquals([ debug.ScopeType.Local, |
| 121 | debug.ScopeType.Closure, |
| 122 | debug.ScopeType.Script, |
| 123 | debug.ScopeType.Global ], |
| 124 | exec_state.frame(0).allScopes().map(s => s.scopeType())); |
| 125 | assertEquals([ debug.ScopeType.Script, |
| 126 | debug.ScopeType.Global ], |
| 127 | exec_state.frame(1).allScopes().map(s => s.scopeType())); |
| 128 | var scope = exec_state.frame(0).scope(1); |
| 129 | assertEquals(1, scope.scopeObject().property("a").value().value()); |
| 130 | assertEquals(1, exec_state.frame(0).evaluate("a").value()); |
| 131 | scope.setVariableValue("a", 2); |
| 132 | assertEquals(2, exec_state.frame(0).evaluate("a++").value()); |
| 133 | } |
| 134 | |
| 135 | var g = eval("'use strict'; \n" + |
| 136 | "var a = 1; \n" + |
| 137 | "() => { a; \n" + |
| 138 | " debugger; \n" + |
| 139 | " assertEquals(3, a);\n" + |
| 140 | " } \n"); |
| 141 | g(); |
| 142 | |
| 143 | Debug.setListener(null); |
| 144 | assertNull(exception); |