diff options
Diffstat (limited to 'js/src/jit-test/tests/modules/debugger-frames.js')
-rw-r--r-- | js/src/jit-test/tests/modules/debugger-frames.js | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/modules/debugger-frames.js b/js/src/jit-test/tests/modules/debugger-frames.js new file mode 100644 index 000000000..ba7a1471c --- /dev/null +++ b/js/src/jit-test/tests/modules/debugger-frames.js @@ -0,0 +1,89 @@ +// Test debugger access to frames and environments work as expected inside a module. + +load(libdir + "asserts.js"); + +function assertArrayEq(actual, expected) +{ + var eq = actual.length == expected.length; + if (eq) { + for (var i = 0; i < actual.length; i++) { + if (actual[i] !== expected[i]) { + eq = false; + break; + } + } + } + if (!eq) { + print("Assertion failed: got " + JSON.stringify(actual) + + ", expected " + JSON.stringify(expected)); + quit(3); + } +} + +var g2 = newGlobal(); + +var dbg = Debugger(g2); +dbg.onDebuggerStatement = function (frame) { + // The current frame is a module frame. + assertEq(frame.type, 'module'); + assertEq(frame.this, undefined); + + // The frame's environement is a module environment. + let env = frame.environment; + assertEq(env.type, 'declarative'); + assertEq(env.callee, null); + + // Top level module definitions and imports are visible. + assertArrayEq(env.names().sort(), ['a', 'b', 'c', 'x', 'y', 'z']); + assertArrayEq(['a', 'b', 'c'].map(env.getVariable, env), [1, 2, 3]); + assertArrayEq(['x', 'y', 'z'].map(env.getVariable, env), [4, 5, 6]); + + // Cannot set imports or const bindings. + assertThrowsInstanceOf(() => env.setVariable('a', 10), TypeError); + assertThrowsInstanceOf(() => env.setVariable('b', 11), TypeError); + assertThrowsInstanceOf(() => env.setVariable('c', 12), TypeError); + env.setVariable('x', 7); + env.setVariable('y', 8); + assertThrowsInstanceOf(() => env.setVariable('z', 9), TypeError); + assertArrayEq(['a', 'b', 'c'].map(env.getVariable, env), [1, 2, 3]); + assertArrayEq(['x', 'y', 'z'].map(env.getVariable, env), [7, 8, 6]); + + // The global lexical is the next thing after the module on the scope chain, + // followed by the global. + assertEq(env.parent.type, 'declarative'); + assertEq(env.parent.parent.type, 'object'); + assertEq(env.parent.parent.parent, null); +}; + +f = g2.eval( +` + let moduleRepo = {}; + setModuleResolveHook(function(module, specifier) { + if (specifier in moduleRepo) + return moduleRepo[specifier]; + throw "Module '" + specifier + "' not found"; + }); + + // Set up a module to import from. + a = moduleRepo['a'] = parseModule( + \` + export var a = 1; + export let b = 2; + export const c = 3; + export function f(x) { return x + 1; } + \`); + a.declarationInstantiation(); + a.evaluation(); + + let m = parseModule( + \` + import { a, b, c } from 'a'; + var x = 4; + let y = 5; + const z = 6; + + debugger; + \`); + m.declarationInstantiation(); + m.evaluation(); +`); |