diff options
Diffstat (limited to 'deps/v8/test/debugger/debug')
156 files changed, 13744 insertions, 268 deletions
diff --git a/deps/v8/test/debugger/debug/compiler/debug-catch-prediction.js b/deps/v8/test/debugger/debug/compiler/debug-catch-prediction.js new file mode 100644 index 0000000000..50fbf58222 --- /dev/null +++ b/deps/v8/test/debugger/debug/compiler/debug-catch-prediction.js @@ -0,0 +1,142 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug event catch prediction for thrown exceptions. We distinguish +// between "caught" and "uncaught" based on the following assumptions: +// 1) try-catch : Will always catch the exception. +// 2) try-finally : Will always re-throw the exception. + +Debug = debug.Debug; + +var log = []; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + log.push([event_data.exception(), event_data.uncaught()]); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnException(); +Debug.setListener(listener); + +(function TryCatch() { + log = []; // Clear log. + function f(a) { + try { + throw "boom" + a; + } catch(e) { + return e; + } + } + assertEquals("boom1", f(1)); + assertEquals("boom2", f(2)); + %OptimizeFunctionOnNextCall(f); + assertEquals("boom3", f(3)); + print("Collect log:", log); + assertEquals([["boom1",false], ["boom2",false], ["boom3",false]], log); +})(); + +(function TryFinally() { + log = []; // Clear log. + function f(a) { + try { + throw "baem" + a; + } finally { + return a + 10; + } + } + assertEquals(11, f(1)); + assertEquals(12, f(2)); + %OptimizeFunctionOnNextCall(f); + assertEquals(13, f(3)); + print("Collect log:", log); + assertEquals([["baem1",true], ["baem2",true], ["baem3",true]], log); +})(); + +(function TryCatchFinally() { + log = []; // Clear log. + function f(a) { + try { + throw "wosh" + a; + } catch(e) { + return e + a; + } finally { + // Nothing. + } + } + assertEquals("wosh11", f(1)); + assertEquals("wosh22", f(2)); + %OptimizeFunctionOnNextCall(f); + assertEquals("wosh33", f(3)); + print("Collect log:", log); + assertEquals([["wosh1",false], ["wosh2",false], ["wosh3",false]], log); +})(); + +(function TryCatchNestedFinally() { + log = []; // Clear log. + function f(a) { + try { + try { + throw "bang" + a; + } finally { + // Nothing. + } + } catch(e) { + return e + a; + } + } + assertEquals("bang11", f(1)); + assertEquals("bang22", f(2)); + %OptimizeFunctionOnNextCall(f); + assertEquals("bang33", f(3)); + print("Collect log:", log); + assertEquals([["bang1",false], ["bang2",false], ["bang3",false]], log); +})(); + +(function TryFinallyNestedCatch() { + log = []; // Clear log. + function f(a) { + try { + try { + throw "peng" + a; + } catch(e) { + return e + } + } finally { + return a + 10; + } + } + assertEquals(11, f(1)); + assertEquals(12, f(2)); + %OptimizeFunctionOnNextCall(f); + assertEquals(13, f(3)); + print("Collect log:", log); + assertEquals([["peng1",false], ["peng2",false], ["peng3",false]], log); +})(); + +(function TryFinallyNestedFinally() { + log = []; // Clear log. + function f(a) { + try { + try { + throw "oops" + a; + } finally { + // Nothing. + } + } finally { + return a + 10; + } + } + assertEquals(11, f(1)); + assertEquals(12, f(2)); + %OptimizeFunctionOnNextCall(f); + assertEquals(13, f(3)); + print("Collect log:", log); + assertEquals([["oops1",true], ["oops2",true], ["oops3",true]], log); +})(); diff --git a/deps/v8/test/debugger/debug/compiler/osr-typing-debug-change.js b/deps/v8/test/debugger/debug/compiler/osr-typing-debug-change.js index 1a7e85cb5a..92eb899036 100644 --- a/deps/v8/test/debugger/debug/compiler/osr-typing-debug-change.js +++ b/deps/v8/test/debugger/debug/compiler/osr-typing-debug-change.js @@ -79,15 +79,12 @@ if (changed) { assertEquals(0.5, r3); } -var counter = 0; -var o = { toString : function() { counter++; return 100; } }; - function listenerSetJToObject( event, exec_state, event_data, data) { if (event == Debug.DebugEvent.Break) { var scope = exec_state.frame(1).scope(0); try { - scope.setVariableValue("j", o); + scope.setVariableValue("j", 100); changed = true; } catch(e) { changed = false; @@ -112,7 +109,6 @@ function ChangeIntVarAndOsr() { var r4 = ChangeIntVarAndOsr(); if (changed) { assertEquals(101, r4); - assertEquals(1, counter); } else { assertEquals(5, r4); } diff --git a/deps/v8/test/debugger/debug/debug-backtrace.js b/deps/v8/test/debugger/debug/debug-backtrace.js new file mode 100644 index 0000000000..63bbe1065a --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-backtrace.js @@ -0,0 +1,98 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// The functions used for testing backtraces. They are at the top to make the +// testing of source line/column easier. +function f(x, y) { + a=1; +}; + +var m = (0, function() { + new f(1); +}); + +function g() { + m(); +}; + + +Debug = debug.Debug + +listenerCalled = false; +exception = false; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + // The expected backtrace is + // 0: f + // 1: m + // 2: g + // 3: [anonymous] + assertEquals(4, exec_state.frameCount()); + + var frame0 = exec_state.frame(0); + assertEquals("f", frame0.func().name()); + assertEquals(0, frame0.index()); + assertEquals(31, frame0.sourceLine()); + assertEquals(2, frame0.sourceColumn()); + assertEquals(2, frame0.localCount()); + assertEquals("x", frame0.localName(0)); + assertEquals(1, frame0.localValue(0).value()); + assertEquals("y", frame0.localName(1)); + assertEquals(undefined, frame0.localValue(1).value()); + + var frame1 = exec_state.frame(1); + assertEquals("m", frame1.func().name()); + assertEquals(1, frame1.index()); + assertEquals(35, frame1.sourceLine()); + assertEquals(2, frame1.sourceColumn()); + assertEquals(0, frame1.localCount()); + + var frame2 = exec_state.frame(2); + assertEquals("g", frame2.func().name()); + + var frame3 = exec_state.frame(3); + assertEquals("", frame3.func().name()); + + listenerCalled = true; + } + } catch (e) { + exception = e; + }; +}; + +// Add the debug event listener. +Debug.setListener(listener); + +// Set a break point and call to invoke the debug event listener. +Debug.setBreakPoint(f, 0, 0); +g(); + +// Make sure that the debug event listener vas invoked. +assertFalse(exception, "exception in listener"); +assertTrue(listenerCalled); diff --git a/deps/v8/test/debugger/debug/debug-break-native.js b/deps/v8/test/debugger/debug/debug-break-native.js new file mode 100644 index 0000000000..10ed405670 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-break-native.js @@ -0,0 +1,40 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +Debug = debug.Debug +var exception = null; + +function breakListener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + exec_state.prepareStep(Debug.StepAction.StepIn); + // Assert that the break happens at an intended location. + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// break") > 0); + } catch (e) { + exception = e; + } +} + +Debug.setListener(breakListener); + +debugger; // break + +function f(x) { + return x; // break +} // break + +Debug.setBreakPoint(f, 0, 0); // break +Debug.scripts(); // break + +new Error("123").stack; // break +Math.sin(0); // break + +f("this should break"); // break + +Debug.setListener(null); // break + +f("this should not break"); + +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/debug-breakpoints.js b/deps/v8/test/debugger/debug/debug-breakpoints.js new file mode 100644 index 0000000000..4240e8f762 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-breakpoints.js @@ -0,0 +1,120 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +Debug.setListener(function() {}); + +function f() {a=1;b=2} +function g() { + a=1; + b=2; +} + +bp = Debug.setBreakPoint(f, 0, 0); +assertEquals("() {[B0]a=1;b=2}", Debug.showBreakPoints(f)); +Debug.clearBreakPoint(bp); +assertEquals("() {a=1;b=2}", Debug.showBreakPoints(f)); +bp1 = Debug.setBreakPoint(f, 0, 8); +assertEquals("() {a=1;[B0]b=2}", Debug.showBreakPoints(f)); +bp2 = Debug.setBreakPoint(f, 0, 4); +assertEquals("() {[B0]a=1;[B1]b=2}", Debug.showBreakPoints(f)); +bp3 = Debug.setBreakPoint(f, 0, 11); +assertEquals("() {[B0]a=1;[B1]b=2[B2]}", Debug.showBreakPoints(f)); +Debug.clearBreakPoint(bp1); +assertEquals("() {[B0]a=1;b=2[B1]}", Debug.showBreakPoints(f)); +Debug.clearBreakPoint(bp2); +assertEquals("() {a=1;b=2[B0]}", Debug.showBreakPoints(f)); +Debug.clearBreakPoint(bp3); +assertEquals("() {a=1;b=2}", Debug.showBreakPoints(f)); + +// The following test checks that the Debug.showBreakPoints(g) produces output +// like follows when changein breakpoints. +// +// function g() { +// [BX]a=1; +// [BX]b=2; +// }[BX] + +// Test set and clear breakpoint at the first possible location (line 0, +// position 0). +bp = Debug.setBreakPoint(g, 0, 0); +// function g() { +// [B0]a=1; +// b=2; +// } +assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0); +Debug.clearBreakPoint(bp); +// function g() { +// a=1; +// b=2; +// } +assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0); + +// Second test set and clear breakpoints on lines 1, 2 and 3 (position = 0). +bp1 = Debug.setBreakPoint(g, 2, 0); +// function g() { +// a=1; +// [B0]b=2; +// } +assertTrue(Debug.showBreakPoints(g).indexOf("[B0]b=2;") > 0); +bp2 = Debug.setBreakPoint(g, 1, 0); +// function g() { +// [B0]a=1; +// [B1]b=2; +// } +assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0); +assertTrue(Debug.showBreakPoints(g).indexOf("[B1]b=2;") > 0); +bp3 = Debug.setBreakPoint(g, 3, 0); +// function g() { +// [B0]a=1; +// [B1]b=2; +// }[B2] +assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0); +assertTrue(Debug.showBreakPoints(g).indexOf("[B1]b=2;") > 0); +assertTrue(Debug.showBreakPoints(g).indexOf("[B2]}") > 0); +Debug.clearBreakPoint(bp1); +// function g() { +// [B0]a=1; +// b=2; +// }[B1] +assertTrue(Debug.showBreakPoints(g).indexOf("[B0]a=1;") > 0); +assertTrue(Debug.showBreakPoints(g).indexOf("[B1]}") > 0); +assertTrue(Debug.showBreakPoints(g).indexOf("[B2]") < 0); +Debug.clearBreakPoint(bp2); +// function g() { +// a=1; +// b=2; +// }[B0] +assertTrue(Debug.showBreakPoints(g).indexOf("[B0]}") > 0); +assertTrue(Debug.showBreakPoints(g).indexOf("[B1]") < 0); +Debug.clearBreakPoint(bp3); +// function g() { +// a=1; +// b=2; +// } +assertTrue(Debug.showBreakPoints(g).indexOf("[B0]") < 0); diff --git a/deps/v8/test/debugger/debug/debug-clearbreakpoint.js b/deps/v8/test/debugger/debug/debug-clearbreakpoint.js new file mode 100644 index 0000000000..0c8267c711 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-clearbreakpoint.js @@ -0,0 +1,60 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +// Simple function which stores the last debug event. +listenerComplete = false; +exception = false; + +var breakpoint = -1; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + // Clear once. + Debug.clearBreakPoint(breakpoint); + // Indicate that all was processed. + listenerComplete = true; + } + } catch (e) { + exception = e + }; +}; + +// Add the debug event listener. +Debug.setListener(listener); + +function g() {}; + +// Set a break point and call to invoke the debug event listener. +breakpoint = Debug.setBreakPoint(g, 0, 0); +g(); + +// Make sure that the debug event listener vas invoked. +assertTrue(listenerComplete, "listener did not run to completion"); +assertFalse(exception, "exception in listener") diff --git a/deps/v8/test/debugger/debug/debug-compile-event.js b/deps/v8/test/debugger/debug/debug-compile-event.js new file mode 100644 index 0000000000..2e52609591 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-compile-event.js @@ -0,0 +1,122 @@ +// Copyright 2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +var exception = false; // Exception in debug event listener. +var after_compile_count = 0; +var compile_error_count = 0; +var current_source = ''; // Current source being compiled. +var source_count = 0; // Total number of scources compiled. +var mute_listener = false; + +function compileSource(source) { + current_source = source; + eval(current_source); + source_count++; +} + +function safeEval(code) { + try { + mute_listener = true; + return eval('(' + code + ')'); + } catch (e) { + assertEquals(void 0, e); + return undefined; + } finally { + mute_listener = false; + } +} + +function listener(event, exec_state, event_data, data) { + if (mute_listener) return; + try { + if (event == Debug.DebugEvent.BeforeCompile || + event == Debug.DebugEvent.AfterCompile || + event == Debug.DebugEvent.CompileError) { + // Count the events. + if (event == Debug.DebugEvent.AfterCompile) { + after_compile_count++; + } else if (event == Debug.DebugEvent.CompileError) { + compile_error_count++; + } + + // If the compiled source contains 'eval' there will be additional compile + // events for the source inside eval. + if (current_source.indexOf('eval') == 0) { + // For source with 'eval' there will be compile events with substrings + // as well as with with the exact source. + assertTrue(current_source.indexOf(event_data.script().source()) >= 0); + } else { + // For source without 'eval' there will be a compile events with the + // exact source. + assertEquals(current_source, event_data.script().source()); + } + + // Check that we pick script name from //# sourceURL, iff present + if (event == Debug.DebugEvent.AfterCompile) { + assertEquals(current_source.indexOf('sourceURL') >= 0 ? + 'myscript.js' : undefined, + event_data.script().name()); + } + } + } catch (e) { + exception = e + } +}; + + +// Add the debug event listener. +Debug.setListener(listener); + +// Compile different sources. +compileSource('a=1'); +compileSource('(function(){})'); +compileSource('eval("a=2")'); +source_count++; // Using eval causes additional compilation event. +compileSource('eval("eval(\'(function(){return a;})\')")'); +source_count += 2; // Using eval causes additional compilation event. +compileSource('JSON.parse(\'{"a":1,"b":2}\')'); +// Using JSON.parse does not causes additional compilation events. +compileSource('x=1; //# sourceURL=myscript.js'); + +try { + compileSource('}'); +} catch(e) { +} + +// Make sure that the debug event listener was invoked. +assertFalse(exception, "exception in listener") + +// Number of before and after + error events should be the same. +assertEquals(compile_error_count, 1); + +// Check the actual number of events (no compilation through the API as all +// source compiled through eval). +assertEquals(source_count, after_compile_count); + +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/debug-conditional-breakpoints.js b/deps/v8/test/debugger/debug/debug-conditional-breakpoints.js new file mode 100644 index 0000000000..b4b73140ba --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-conditional-breakpoints.js @@ -0,0 +1,137 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +// Simple debug event handler which just counts the number of break points hit. +var break_point_hit_count; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + break_point_hit_count++; + } +}; + +// Add the debug event listener. +Debug.setListener(listener); + +// Test functions. +count = 0; +function f() {}; +function g() {h(count++)}; +function h(x) {var a=x; return a}; + + +// Conditional breakpoint which syntax error. +break_point_hit_count = 0; +bp = Debug.setBreakPoint(f, 0, 0, '{{{'); +f(); +assertEquals(0, break_point_hit_count); +Debug.clearBreakPoint(bp); + +// Conditional breakpoint which evaluates to false. +break_point_hit_count = 0; +bp = Debug.setBreakPoint(f, 0, 0, 'false'); +f(); +assertEquals(0, break_point_hit_count); +Debug.clearBreakPoint(bp); + +// Conditional breakpoint which evaluates to true. +break_point_hit_count = 0; +bp = Debug.setBreakPoint(f, 0, 0, 'true'); +f(); +assertEquals(1, break_point_hit_count); +Debug.clearBreakPoint(bp); + +// Conditional breakpoint which different types of quotes. +break_point_hit_count = 0; +bp = Debug.setBreakPoint(f, 0, 0, '"a" == "a"'); +f(); +assertEquals(1, break_point_hit_count); +Debug.clearBreakPoint(bp); +break_point_hit_count = 0; +bp = Debug.setBreakPoint(f, 0, 0, "'a' == 'a'"); +f(); +assertEquals(1, break_point_hit_count); +Debug.clearBreakPoint(bp); + +// Conditional breakpoint which checks global variable. +break_point_hit_count = 0; +bp = Debug.setBreakPoint(f, 0, 0, 'x==1'); +f(); +assertEquals(0, break_point_hit_count); +x=1; +f(); +assertEquals(1, break_point_hit_count); +Debug.clearBreakPoint(bp); + +// Conditional breakpoint which checks global variable. +break_point_hit_count = 0; +bp = Debug.setBreakPoint(g, 0, 0, 'count % 2 == 0'); +for (var i = 0; i < 10; i++) { + g(); +} +assertEquals(5, break_point_hit_count); +Debug.clearBreakPoint(bp); + +// Conditional breakpoint which checks a parameter. +break_point_hit_count = 0; +bp = Debug.setBreakPoint(h, 0, 0, 'x % 2 == 0'); +for (var i = 0; i < 10; i++) { + g(); +} +assertEquals(5, break_point_hit_count); +Debug.clearBreakPoint(bp); + +// Conditional breakpoint which checks a local variable. +break_point_hit_count = 0; +bp = Debug.setBreakPoint(h, 0, 22, 'a % 2 == 0'); +for (var i = 0; i < 10; i++) { + g(); +} +assertEquals(5, break_point_hit_count); +Debug.clearBreakPoint(bp); + +// Multiple conditional breakpoint which the same condition. +break_point_hit_count = 0; +bp1 = Debug.setBreakPoint(h, 0, 22, 'a % 2 == 0'); +assertThrows(() => Debug.setBreakPoint(h, 0, 22, 'a % 2 == 0')); +for (var i = 0; i < 10; i++) { + g(); +} +assertEquals(5, break_point_hit_count); +Debug.clearBreakPoint(bp1); + +// Multiple conditional breakpoint which different conditions. +break_point_hit_count = 0; +bp1 = Debug.setBreakPoint(h, 0, 22, 'a % 2 == 0'); +assertThrows(() => Debug.setBreakPoint(h, 0, 22, '(a + 1) % 2 == 0')); +for (var i = 0; i < 10; i++) { + g(); +} +assertEquals(5, break_point_hit_count); +Debug.clearBreakPoint(bp1); diff --git a/deps/v8/test/debugger/debug/debug-enable-disable-breakpoints.js b/deps/v8/test/debugger/debug/debug-enable-disable-breakpoints.js new file mode 100644 index 0000000000..25db3eafe3 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-enable-disable-breakpoints.js @@ -0,0 +1,62 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +// Simple debug event handler which just counts the number of break points hit. +var break_point_hit_count; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + break_point_hit_count++; + } +}; + +// Add the debug event listener. +Debug.setListener(listener); + +// Test function. +function f() {a=1;b=2;}; + +// This tests enabeling and disabling of break points including the case +// with several break points in the same location. +break_point_hit_count = 0; + +// Set a breakpoint in f. +bp1 = Debug.setBreakPoint(f); +f(); +assertEquals(1, break_point_hit_count); + +// Deactivate all breakpoints. +Debug.debuggerFlags().breakPointsActive.setValue(false); +f(); +assertEquals(1, break_point_hit_count); + +// Activate all breakpoints. +Debug.debuggerFlags().breakPointsActive.setValue(true); +f(); +assertEquals(2, break_point_hit_count); diff --git a/deps/v8/test/debugger/debug/debug-eval-scope.js b/deps/v8/test/debugger/debug/debug-eval-scope.js new file mode 100644 index 0000000000..093c4df722 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-eval-scope.js @@ -0,0 +1,144 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --no-always-opt + +// Test that the (strict) eval scope is visible to the debugger. + +var Debug = debug.Debug; +var exception = null; +var delegate = null; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + delegate(exec_state); + } catch (e) { + exception = e; + } +} + +Debug.setListener(listener); + +// Current function is the top-level eval. +// We can access stack- and context-allocated values in the eval-scope. +delegate = function(exec_state) { + assertEquals([ debug.ScopeType.Eval, + debug.ScopeType.Script, + debug.ScopeType.Global ], + exec_state.frame(0).allScopes().map(s => s.scopeType())); + var scope = exec_state.frame(0).scope(0); + assertEquals(1, scope.scopeObject().property("a").value().value()); + assertEquals(1, exec_state.frame(0).evaluate("a").value()); + scope.setVariableValue("a", 2); + assertEquals(2, exec_state.frame(0).evaluate("a++").value()); +} + +eval("'use strict'; \n" + + "var a = 1; \n" + + "debugger; \n" + + "assertEquals(3, a);\n"); + +eval("'use strict'; \n" + + "var a = 1; \n" + + "(x=>a); \n" + // Force context-allocation. + "debugger; \n" + + "assertEquals(3, a);\n"); + +// Current function is an inner function. +// We cannot access stack-allocated values in the eval-scope. +delegate = function(exec_state) { + assertEquals([ debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global ], + exec_state.frame(0).allScopes().map(s => s.scopeType())); + assertEquals([ debug.ScopeType.Eval, + debug.ScopeType.Script, + debug.ScopeType.Global ], + exec_state.frame(1).allScopes().map(s => s.scopeType())); + var scope = exec_state.frame(0).scope(0); + assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError); + assertTrue(scope.scopeObject().property("a").isUndefined()); +} + +eval("'use strict'; \n" + + "var a = 1; \n" + + "(() => {debugger})()\n"); + +// Current function is an escaped inner function. +delegate = function(exec_state) { + assertEquals([ debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global ], + exec_state.frame(0).allScopes().map(s => s.scopeType())); + assertEquals([ debug.ScopeType.Script, + debug.ScopeType.Global ], + exec_state.frame(1).allScopes().map(s => s.scopeType())); + var scope = exec_state.frame(0).scope(0); + assertThrows(() => exec_state.frame(0).evaluate("a"), ReferenceError); + assertTrue(scope.scopeObject().property("a").isUndefined()); +} + +var f = eval("'use strict'; \n" + + "var a = 1; \n" + + "() => {debugger}\n"); +f(); + +// Current function is an inner function. +// We can access context-allocated values in the eval-scope. +delegate = function(exec_state) { + assertEquals([ debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global ], + exec_state.frame(0).allScopes().map(s => s.scopeType())); + assertEquals([ debug.ScopeType.Eval, + debug.ScopeType.Script, + debug.ScopeType.Global ], + exec_state.frame(1).allScopes().map(s => s.scopeType())); + var scope = exec_state.frame(1).scope(0); + assertEquals(1, scope.scopeObject().property("a").value().value()); + assertEquals(1, exec_state.frame(1).evaluate("a").value()); + assertEquals(1, exec_state.frame(0).evaluate("a").value()); + scope.setVariableValue("a", 2); + assertEquals(2, exec_state.frame(0).evaluate("a++").value()); + assertEquals(3, exec_state.frame(1).evaluate("a++").value()); +} + +eval("'use strict'; \n" + + "var a = 1; \n" + + "(() => { a; \n" + // Force context-allocation. + " debugger; \n" + + " assertEquals(4, a);\n" + + " })(); \n" + ); + +// Current function is an escaped inner function. +// We can access context-allocated values in the eval-scope. +delegate = function(exec_state) { + assertEquals([ debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global ], + exec_state.frame(0).allScopes().map(s => s.scopeType())); + assertEquals([ debug.ScopeType.Script, + debug.ScopeType.Global ], + exec_state.frame(1).allScopes().map(s => s.scopeType())); + var scope = exec_state.frame(0).scope(1); + assertEquals(1, scope.scopeObject().property("a").value().value()); + assertEquals(1, exec_state.frame(0).evaluate("a").value()); + scope.setVariableValue("a", 2); + assertEquals(2, exec_state.frame(0).evaluate("a++").value()); +} + +var g = eval("'use strict'; \n" + + "var a = 1; \n" + + "() => { a; \n" + + " debugger; \n" + + " assertEquals(3, a);\n" + + " } \n"); +g(); + +Debug.setListener(null); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/debug-evaluate-bool-constructor.js b/deps/v8/test/debugger/debug/debug-evaluate-bool-constructor.js new file mode 100644 index 0000000000..83a0f06391 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-evaluate-bool-constructor.js @@ -0,0 +1,64 @@ +// Copyright 2009 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --noanalyze-environment-liveness +Debug = debug.Debug + +var listenerComplete = false; +var exception = false; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + var a = exec_state.frame(0).evaluate("a"); + assertEquals('object', a.type()); + assertEquals('Object', a.className()); + + // Indicate that all was processed. + listenerComplete = true; + } + } catch (e) { + print(e); + exception = e + }; +}; + +// Add the debug event listener. +Debug.setListener(listener); + +function callDebugger() { + // Add set constructor field to a non-function value. + var a = {constructor:true}; + debugger; +} + +callDebugger(); + + +// Make sure that the debug event listener vas invoked. +assertFalse(exception, "exception in listener") +assertTrue(listenerComplete, "listener did not run to completion"); diff --git a/deps/v8/test/debugger/debug/debug-evaluate-locals-optimized-double.js b/deps/v8/test/debugger/debug/debug-evaluate-locals-optimized-double.js new file mode 100644 index 0000000000..79abb00c07 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-evaluate-locals-optimized-double.js @@ -0,0 +1,201 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --expose-gc +// Flags: --inline-construct + +Debug = debug.Debug + +var listenerComplete = false; +var exception = false; + +var testingConstructCall = false; + +var input = [ + {a: 1, b: 2}, + {a: 3, b: 4}, + {a: 5, b: 6}, + {a: 7, b: 8}, + {a: 9, b: 10} +]; + +var expected = [ + { locals: {i: 0, x0: 3.03, y0: 4.04, a0: 1.01, b0: 2.02}, + args: { names: ["i", "x0", "y0"], values: [0, 3.03, 4.04] } }, + { locals: {i: 1, x1: 5.05, y1: 6.06, a1: 3.03, b1: 4.04}, + args: { names: ["i", "x1", "y1"], values: [1, 5.05, 6.06] } }, + { locals: {i: 2, a2: 5.05, b2: 6.06}, + args: { names: ["i"], values: [2] } }, + { locals: {i: 3, x3: 9.09, y3: 10.10, z3: undefined, a3: 7.07, b3: 8.08}, + args: { names: ["i", "x3", "y3", "z3"], + values: [3, 9.09, 10.10, undefined] } }, + { locals: {i: 4, x4: 11.11, y4: 12.12, a4: 9.09, b4: 10.10}, + args: { names: ["i", "x4", "y4"], values: [4, 11.11, 12.12] } } +]; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) + { + assertEquals(6, exec_state.frameCount()); + + for (var i = 0; i < exec_state.frameCount(); i++) { + var frame = exec_state.frame(i); + if (i < exec_state.frameCount() - 1) { + var expected_args = expected[i].args; + var expected_locals = expected[i].locals; + + // All frames except the bottom one have expected locals. + var locals = {}; + for (var j = 0; j < frame.localCount(); j++) { + locals[frame.localName(j)] = frame.localValue(j).value(); + } + assertPropertiesEqual(expected_locals, locals); + + // All frames except the bottom one have two scopes. + assertEquals(3, frame.scopeCount()); + assertEquals(debug.ScopeType.Local, frame.scope(0).scopeType()); + assertEquals(debug.ScopeType.Script, frame.scope(1).scopeType()); + assertEquals(debug.ScopeType.Global, frame.scope(2).scopeType()); + + Object.keys(expected_locals).forEach(function (name) { + assertEquals(expected_locals[name], + frame.scope(0).scopeObject().value()[name]); + }); + + for (var j = 0; j < expected_args.names.length; j++) { + var arg_name = expected_args.names[j]; + var arg_value = expected_args.values[j]; + assertEquals(arg_value, + frame.scope(0).scopeObject().value()[arg_name]); + } + + // Evaluate in the inlined frame. + Object.keys(expected_locals).forEach(function (name) { + assertEquals(expected_locals[name], frame.evaluate(name).value()); + }); + + for (var j = 0; j < expected_args.names.length; j++) { + var arg_name = expected_args.names[j]; + var arg_value = expected_args.values[j]; + assertEquals(arg_value, frame.evaluate(arg_name).value()); + assertEquals(arg_value, frame.evaluate('arguments['+j+']').value()); + } + } else { + // The bottom frame only have the global scope. + assertEquals(2, frame.scopeCount()); + assertEquals(debug.ScopeType.Script, frame.scope(0).scopeType()); + assertEquals(debug.ScopeType.Global, frame.scope(1).scopeType()); + } + + // Check the frame function. + switch (i) { + case 0: assertEquals("h", frame.func().name()); break; + case 1: assertEquals("g3", frame.func().name()); break; + case 2: assertEquals("g2", frame.func().name()); break; + case 3: assertEquals("g1", frame.func().name()); break; + case 4: assertEquals("f", frame.func().name()); break; + case 5: break; + default: assertUnreachable(); + } + } + + // Indicate that all was processed. + listenerComplete = true; + } + } catch (e) { + exception = e.toString() + e.stack; + }; +}; + +for (var i = 0; i < 4; i++) f(input.length - 1, 11.11, 12.12); +%OptimizeFunctionOnNextCall(f); +f(input.length - 1, 11.11, 12.12); + +// Add the debug event listener. +Debug.setListener(listener); + +function h(i, x0, y0) { + var a0 = input[i].a; + var b0 = input[i].b; + a0 = a0 + a0 / 100; + b0 = b0 + b0 / 100; + debugger; // Breakpoint. + return a0 + b0; +}; + +function g3(i, x1, y1) { + var a1 = input[i].a; + var b1 = input[i].b; + a1 = a1 + a1 / 100; + b1 = b1 + b1 / 100; + h(i - 1, a1, b1); + return a1 + b1; +}; + +function g2(i) { + var a2 = input[i].a; + var b2 = input[i].b; + a2 = a2 + a2 / 100; + b2 = b2 + b2 / 100; + g3(i - 1, a2, b2); + return a2 + b2; +}; + +function g1(i, x3, y3, z3) { + var a3 = input[i].a; + var b3 = input[i].b; + a3 = a3 + a3 / 100; + b3 = b3 + b3 / 100; + new g2(i - 1, a3, b3); + return a3 + b3; +}; + +function f(i, x4, y4) { + var a4 = input[i].a; + var b4 = input[i].b; + a4 = a4 + a4 / 100; + b4 = b4 + b4 / 100; + g1(i - 1, a4, b4); + return a4 + b4; +}; + +// Test calling f normally and as a constructor. +f(input.length - 1, 11.11, 12.12); +f(input.length - 1, 11.11, 12.12, ""); +testingConstructCall = true; +new f(input.length - 1, 11.11, 12.12); +new f(input.length - 1, 11.11, 12.12, ""); + +// Make sure that the debug event listener was invoked. +assertFalse(exception, "exception in listener " + exception) +assertTrue(listenerComplete); + +//Throw away type information for next run. +gc(); + +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/debug-evaluate-locals.js b/deps/v8/test/debugger/debug/debug-evaluate-locals.js new file mode 100644 index 0000000000..0108acf2ff --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-evaluate-locals.js @@ -0,0 +1,149 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +listenerComplete = false; +exception = false; + + +function h() { + var a = 1; + var b = 2; + var eval = 5; // Overriding eval should not break anything. + debugger; // Breakpoint. + return a; +} + +function checkFrame0(frame) { + // Frame 0 (h) has normal variables a and b. + var count = frame.localCount(); + assertEquals(3, count); + for (var i = 0; i < count; ++i) { + var name = frame.localName(i); + var value = frame.localValue(i).value(); + if (name == 'a') { + assertEquals(1, value); + } else if (name !='eval') { + assertEquals('b', name); + assertEquals(2, value); + } + } +} + + +function g() { + var a = 3; + eval("var b = 4;"); + return h() + a; +} + +function checkFrame1(frame) { + // Frame 1 (g) has normal variable a, b (and arguments). + var count = frame.localCount(); + assertEquals(3, count); + for (var i = 0; i < count; ++i) { + var name = frame.localName(i); + var value = frame.localValue(i).value(); + if (name == 'a') { + assertEquals(3, value); + } else if (name == 'b') { + assertEquals(4, value); + } else { + assertEquals('arguments', name); + } + } +} + + +function f() { + var a = 5; + var b = 0; + with ({b:6}) { + return g(); + } +} + +function checkFrame2(frame) { + // Frame 2 (f) has normal variables a and b. + var count = frame.localCount(); + assertEquals(2, count); + for (var i = 0; i < count; ++i) { + var name = frame.localName(i); + var value = frame.localValue(i).value(); + if (name == 'a') { + assertEquals(5, value); + } else { + assertEquals('b', name); + assertEquals(0, value); + } + } +} + + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) + { + checkFrame0(exec_state.frame(0)); + checkFrame1(exec_state.frame(1)); + checkFrame2(exec_state.frame(2)); + + assertEquals(1, exec_state.frame(0).evaluate('a').value()); + assertEquals(2, exec_state.frame(0).evaluate('b').value()); + assertEquals(5, exec_state.frame(0).evaluate('eval').value()); + assertEquals(3, exec_state.frame(1).evaluate('a').value()); + assertEquals(4, exec_state.frame(1).evaluate('b').value()); + assertEquals("function", + exec_state.frame(1).evaluate('typeof eval').value()); + assertEquals(5, exec_state.frame(2).evaluate('a').value()); + assertEquals(6, exec_state.frame(2).evaluate('b').value()); + assertEquals("function", + exec_state.frame(2).evaluate('typeof eval').value()); + assertEquals("foo", + exec_state.frame(0).evaluate('a = "foo"').value()); + assertEquals("bar", + exec_state.frame(1).evaluate('a = "bar"').value()); + // Indicate that all was processed. + listenerComplete = true; + } + } catch (e) { + exception = e; + print("Caught something. " + e + " " + e.stack); + }; +}; + +// Add the debug event listener. +Debug.setListener(listener); + +var f_result = f(); + +assertEquals("foobar", f_result); + +// Make sure that the debug event listener was invoked. +assertFalse(exception, "exception in listener") +assertTrue(listenerComplete); diff --git a/deps/v8/test/debugger/debug/debug-evaluate-no-side-effect-builtins.js b/deps/v8/test/debugger/debug/debug-evaluate-no-side-effect-builtins.js new file mode 100644 index 0000000000..154498c911 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-evaluate-no-side-effect-builtins.js @@ -0,0 +1,79 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --ignition --side-effect-free-debug-evaluate + +Debug = debug.Debug + +var exception = null; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + function success(expectation, source) { + assertEquals(expectation, exec_state.frame(0).evaluate(source).value()); + } + function fail(source) { + assertThrows(() => exec_state.frame(0).evaluate(source), EvalError); + } + + // Test Math functions. + for (f of Object.getOwnPropertyNames(Math)) { + if (typeof Math[f] === "function") { + var result = exec_state.frame(0).evaluate( + `Math.${f}(0.5, -0.5);`).value(); + if (f != "random") assertEquals(Math[f](0.5, -0.5), result); + } + } + + // Test Number functions. + for (f of Object.getOwnPropertyNames(Number)) { + if (typeof Number[f] === "function") { + success(Number[f](0.5), `Number.${f}(0.5);`); + } + } + for (f of Object.getOwnPropertyNames(Number.prototype)) { + if (typeof Number.prototype[f] === "function") { + if (f == "toLocaleString") continue; + success(Number(0.5)[f](5), `Number(0.5).${f}(5);`); + } + } + + // Test String functions. + success(" ", "String.fromCodePoint(0x20)"); + success(" ", "String.fromCharCode(0x20)"); + for (f of Object.getOwnPropertyNames(String.prototype)) { + if (typeof String.prototype[f] === "function") { + // Do not expect locale-specific or regexp-related functions to work. + if (f.indexOf("locale") >= 0) continue; + if (f == "normalize") continue; + if (f == "match") continue; + if (f == "search") continue; + if (f == "split") continue; + success("abcd"[f](2), `"abcd".${f}(2);`); + } + } + fail("'abcd'.match(/a/)"); + fail("'abcd'.replace(/a/)"); + fail("'abcd'.search(/a/)"); + fail("'abcd'.split(/a/)"); + + // Test JSON functions. + success('{"abc":[1,2]}', "JSON.stringify(JSON.parse('{\"abc\":[1,2]}'))"); + } catch (e) { + exception = e; + print(e, e.stack); + }; +}; + +// Add the debug event listener. +Debug.setListener(listener); + +function f() { + debugger; +}; + +f(); + +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/debug-evaluate-no-side-effect.js b/deps/v8/test/debugger/debug/debug-evaluate-no-side-effect.js new file mode 100644 index 0000000000..113ca3d16a --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-evaluate-no-side-effect.js @@ -0,0 +1,83 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --ignition --side-effect-free-debug-evaluate + +Debug = debug.Debug + +var exception = null; +let a = 1; +var object = { property : 2, + get getter() { return 3; } + }; +var string1 = { toString() { return "x"; } }; +var string2 = { toString() { print("x"); return "x"; } }; +var array = [4, 5]; +var error = new Error(); + +function set_a() { a = 2; } + +function get_a() { return a; } + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + function success(expectation, source) { + assertEquals(expectation, exec_state.frame(0).evaluate(source).value()); + } + function fail(source) { + assertThrows(() => exec_state.frame(0).evaluate(source), EvalError); + } + // Simple test. + success(3, "1 + 2"); + // Dymanic load. + success(array, "array"); + // Context load. + success(1, "a"); + // Global and named property load. + success(2, "object.property"); + // Load via read-only getter. + success(3, "object.getter"); + // Implicit call to read-only toString. + success("xy", "string1 + 'y'"); + // Keyed property load. + success(5, "array[1]"); + // Call to read-only function. + success(1, "get_a()"); + // Call to read-only function within try-catch. + success(1, "try { get_a() } catch (e) {}"); + // Call to C++ built-in. + success(Math.sin(2), "Math.sin(2)"); + // Call to whitelisted get accessors. + success(3, "'abc'.length"); + success(2, "array.length"); + // Test that non-read-only code fails. + fail("exception = 1"); + // Test that calling a non-read-only function fails. + fail("set_a()"); + // Test that implicit call to a non-read-only function fails. + fail("string2 + 'y'"); + // Test that try-catch does not catch the EvalError. + fail("try { set_a() } catch (e) {}"); + // Test that call to set accessor fails. + fail("array.length = 4"); + // Test that call to non-whitelisted get accessor fails. + fail("error.stack"); + } catch (e) { + exception = e; + print(e, e.stack); + }; +}; + +// Add the debug event listener. +Debug.setListener(listener); + +function f() { + debugger; +}; + +f(); + +assertNull(exception); +assertEquals(1, a); diff --git a/deps/v8/test/debugger/debug/debug-evaluate-shadowed-context.js b/deps/v8/test/debugger/debug/debug-evaluate-shadowed-context.js new file mode 100644 index 0000000000..564bdc6fc3 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-evaluate-shadowed-context.js @@ -0,0 +1,83 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --no-analyze-environment-liveness + +// Test that debug-evaluate only resolves variables that are used by +// the function inside which we debug-evaluate. This is to avoid +// incorrect variable resolution when a context-allocated variable is +// shadowed by a stack-allocated variable. + +Debug = debug.Debug + +var exception = null; +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + for (var i = 0; i < exec_state.frameCount() - 1; i++) { + var frame = exec_state.frame(i); + var value; + try { + value = frame.evaluate("x").value(); + } catch (e) { + value = e.name; + } + print(frame.sourceLineText()); + var expected = frame.sourceLineText().match(/\/\/ (.*$)/)[1]; + assertEquals(String(expected), String(value)); + } + assertEquals("[object global]", + String(exec_state.frame(0).evaluate("this").value())); + assertEquals("y", exec_state.frame(0).evaluate("y").value()); + assertEquals("a", exec_state.frame(0).evaluate("a").value()); + exec_state.frame(0).evaluate("a = 'A'"); + assertThrows(() => exec_state.frame(0).evaluate("z"), ReferenceError); + } catch (e) { + exception = e; + print(e + e.stack); + } +} + +Debug.setListener(listener); + +var a = "a"; +(function() { + var x = 1; // context allocate x + (() => x); + var y = "y"; + var z = "z"; + (function() { + var x = 2; // stack allocate shadowing x + (function() { + y; // access y + debugger; // ReferenceError + })(); // 2 + })(); // 1 + return y; +})(); + +assertEquals("A", a); +a = "a"; + +(function() { + var x = 1; // context allocate x + (() => x); + var y = "y"; + var z = "z"; + (function() { + var x = 2; // stack allocate shadowing x + (() => { + y; + a; + this; // context allocate receiver + debugger; // ReferenceError + })(); // 2 + })(); // 1 + return y; +})(); + +assertEquals("A", a); + +Debug.setListener(null); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/debug-evaluate-with.js b/deps/v8/test/debugger/debug/debug-evaluate-with.js index 06b627c517..260114d94d 100644 --- a/deps/v8/test/debugger/debug/debug-evaluate-with.js +++ b/deps/v8/test/debugger/debug/debug-evaluate-with.js @@ -24,6 +24,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Flags: --noanalyze-environment-liveness Debug = debug.Debug diff --git a/deps/v8/test/debugger/debug/debug-evaluate.js b/deps/v8/test/debugger/debug/debug-evaluate.js new file mode 100644 index 0000000000..9328c323fa --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-evaluate.js @@ -0,0 +1,85 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +listenerComplete = false; +exception = false; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + assertEquals(3, exec_state.frame(0).evaluate("1+2").value()); + assertEquals(5, exec_state.frame(0).evaluate("a+2").value()); + assertEquals(4, exec_state.frame(0).evaluate("({a:1,b:2}).b+2").value()); + + assertEquals(3, exec_state.frame(0).evaluate("a").value()); + assertEquals(2, exec_state.frame(1).evaluate("a").value()); + assertEquals(1, exec_state.frame(2).evaluate("a").value()); + + assertEquals(1, exec_state.evaluateGlobal("a").value()); + assertEquals(1, exec_state.evaluateGlobal("this.a").value()); + + assertEquals(longString, + exec_state.evaluateGlobal("this.longString").value()); + + // Indicate that all was processed. + listenerComplete = true; + } + } catch (e) { + exception = e + }; +}; + +// Add the debug event listener. +Debug.setListener(listener); + +function f() { + var a = 3; +}; + +function g() { + var a = 2; + f(); + return a; // Use the value to prevent it being removed by DCE. +}; + +a = 1; + +// String which is longer than 80 chars. +var longString = "1234567890_"; +for (var i = 0; i < 4; i++) { + longString += longString; +} + +// Set a break point at return in f and invoke g to hit the breakpoint. +Debug.setBreakPoint(f, 2, 0); +g(); + +assertFalse(exception, "exception in listener") +// Make sure that the debug event listener vas invoked. +assertTrue(listenerComplete, "listener did not run to completion"); diff --git a/deps/v8/test/debugger/debug/debug-function-scopes.js b/deps/v8/test/debugger/debug/debug-function-scopes.js new file mode 100644 index 0000000000..caca2114fd --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-function-scopes.js @@ -0,0 +1,191 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +var Debug = debug.Debug; + +const ScopeType = debug.ScopeType; + +let exception = null; +let listenerDelegate = null; + +const expected_break_count = 5; +let break_count = 0; + +Debug.setListener(function(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + break_count++; + listenerDelegate(exec_state); + } catch (e) { + exception = e; + print(e, e.stack); + } +}); + +function CheckScope(scope_frame, scope_expectations, expected_scope_type) { + assertEquals(expected_scope_type, scope_frame.scopeType()); + + var scope_object = scope_frame.scopeObject().value(); + + for (var name in scope_expectations) { + var actual = scope_object[name]; + var expected = scope_expectations[name]; + assertEquals(expected, actual); + } +} + +// --- + +listenerDelegate = function(exec_state) { + const frame = exec_state.frame(0); + + assertEquals(7, frame.scopeCount()); + + CheckScope(frame.scope(0), {}, ScopeType.Local); + CheckScope(frame.scope(1), { a: 4, b: 5 }, ScopeType.Closure); + CheckScope(frame.scope(2), { w: 5, v: "Capybara" }, ScopeType.With); + CheckScope(frame.scope(3), { z: 22 }, ScopeType.Closure); + CheckScope(frame.scope(4), { x: 5 }, ScopeType.Closure); + CheckScope(frame.scope(5), {}, ScopeType.Script); + CheckScope(frame.scope(6), {}, ScopeType.Global); +}; + +(function F1(x) { + function F2(y) { + var z = x + y; + with ({w: 5, v: "Capybara"}) { + var F3 = function(a, b) { + function F4(p) { + debugger; + return p + a + b + z + w + v.length; + } + return F4; + } + return F3(4, 5); + } + } + return F2(17); +})(5)(); + +// --- + +listenerDelegate = function(exec_state) { + const frame = exec_state.frame(0); + + assertEquals(3, frame.scopeCount()); + + CheckScope(frame.scope(0), {}, ScopeType.Local); + CheckScope(frame.scope(1), {}, ScopeType.Script); + CheckScope(frame.scope(2), {}, ScopeType.Global); +}; + +(function() { debugger; return 5; })(); + +// --- + +listenerDelegate = function(exec_state) { + const frame = exec_state.frame(0); + + assertEquals(5, frame.scopeCount()); + + CheckScope(frame.scope(0), {}, ScopeType.Local); + CheckScope(frame.scope(1), { visible2: 20 }, ScopeType.Closure); + CheckScope(frame.scope(2), { visible1: 10 }, ScopeType.Closure); + CheckScope(frame.scope(3), {}, ScopeType.Script); + CheckScope(frame.scope(4), {}, ScopeType.Global); +}; + +(function F1(invisible_parameter) { + var invisible1 = 1; + var visible1 = 10; + return (function F2() { + var invisible2 = 2; + return (function F3() { + var visible2 = 20; + return (function () { debugger; return visible1 + visible2; }); + })(); + })(); +})(5)(); + +// --- + +listenerDelegate = function(exec_state) { + const frame = exec_state.frame(0); + + assertEquals(5, frame.scopeCount()); + + CheckScope(frame.scope(0), {}, ScopeType.Local); + CheckScope(frame.scope(1), { e2: "I'm error 2" }, ScopeType.Catch); + CheckScope(frame.scope(2), { e1: "I'm error 1" }, ScopeType.Catch); + CheckScope(frame.scope(3), {}, ScopeType.Script); + CheckScope(frame.scope(4), {}, ScopeType.Global); +}; + +(function One() { + try { + throw "I'm error 1"; + } catch (e1) { + try { + throw "I'm error 2"; + } catch (e2) { + return function GetError() { + debugger; + return e1 + e2; + }; + } + } +})()(); + +// --- + +listenerDelegate = function(exec_state) { + const frame = exec_state.frame(0); + + assertEquals(5, frame.scopeCount()); + + CheckScope(frame.scope(0), {}, ScopeType.Local); + CheckScope(frame.scope(1), { p4: 20, p6: 22 }, ScopeType.Closure); + CheckScope(frame.scope(2), { p1: 1 }, ScopeType.Closure); + CheckScope(frame.scope(3), {}, ScopeType.Script); + CheckScope(frame.scope(4), {}, ScopeType.Global); +}; + +(function Raz(p1, p2) { + var p3 = p1 + p2; + return (function() { + var p4 = 20; + var p5 = 21; + var p6 = 22; + return eval("(function(p7){ debugger; return p1 + p4 + p6 + p7})"); + })(); +})(1,2)(); + +// --- + +assertNull(exception); +assertEquals(expected_break_count, break_count); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-1.js b/deps/v8/test/debugger/debug/debug-liveedit-1.js new file mode 100644 index 0000000000..950a2faea6 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-1.js @@ -0,0 +1,46 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug + +eval("var something1 = 25; " + + " function ChooseAnimal() { return 'Cat'; } " + + " ChooseAnimal.Helper = function() { return 'Help!'; }"); + +assertEquals("Cat", ChooseAnimal()); + +var script = Debug.findScript(ChooseAnimal); + +var orig_animal = "Cat"; +var patch_pos = script.source.indexOf(orig_animal); +var new_animal_patch = "Cap' + 'y' + 'bara"; + +var change_log = new Array(); +Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_animal.length, new_animal_patch, change_log); + +assertEquals("Capybara", ChooseAnimal()); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-2.js b/deps/v8/test/debugger/debug/debug-liveedit-2.js new file mode 100644 index 0000000000..408ee5a08b --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-2.js @@ -0,0 +1,65 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --noalways-opt + + +Debug = debug.Debug + +eval("function ChooseAnimal(p) {\n " + + " if (p == 7) {\n" + // Use p + " return;\n" + + " }\n" + + " return function Chooser() {\n" + + " return 'Cat';\n" + + " };\n" + + "}\n"); + +var old_closure = ChooseAnimal(19); + +assertEquals("Cat", old_closure()); + +var script = Debug.findScript(ChooseAnimal); + +var orig_animal = "'Cat'"; +var patch_pos = script.source.indexOf(orig_animal); +var new_animal_patch = "'Capybara' + p"; + +// We patch innermost function "Chooser". +// However, this does not actually patch existing "Chooser" instances, +// because old value of parameter "p" was not saved. +// Instead it patches ChooseAnimal. +var change_log = new Array(); +Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_animal.length, new_animal_patch, change_log); +print("Change log: " + JSON.stringify(change_log) + "\n"); + +var new_closure = ChooseAnimal(19); +// New instance of closure is patched. +assertEquals("Capybara19", new_closure()); + +// Old instance of closure is not patched. +assertEquals("Cat", old_closure()); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-3.js b/deps/v8/test/debugger/debug/debug-liveedit-3.js new file mode 100644 index 0000000000..c075453ff1 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-3.js @@ -0,0 +1,66 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// In this test case we edit a script so that techincally function text +// hasen't been changed. However actually function became one level more nested +// and must be recompiled because it uses variable from outer scope. + + +Debug = debug.Debug + +var function_z_text = +" function Z() {\n" ++ " return 2 + p;\n" ++ " }\n"; + +eval( +"function Factory(p) {\n" ++ "return (\n" ++ function_z_text ++ ");\n" ++ "}\n" +); + +var z6 = Factory(6); +assertEquals(8, z6()); + +var script = Debug.findScript(Factory); + +var new_source = script.source.replace(function_z_text, "function Intermediate() {\nreturn (\n" + function_z_text + ")\n;\n}\n"); +print("new source: " + new_source); + +var change_log = new Array(); +var result = Debug.LiveEdit.SetScriptSource(script, new_source, false, change_log); +print("Result: " + JSON.stringify(result) + "\n"); +print("Change log: " + JSON.stringify(change_log) + "\n"); + +assertEquals(8, z6()); + +var z100 = Factory(100)(); + +assertEquals(102, z100()); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-4.js b/deps/v8/test/debugger/debug/debug-liveedit-4.js new file mode 100644 index 0000000000..0b94ece542 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-4.js @@ -0,0 +1,68 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --noalways-opt + +// In this test case we edit a script so that techincally function text +// hasen't been changed. However actually function became one level more nested +// and must be recompiled because it uses variable from outer scope. + + +Debug = debug.Debug + +eval( +"function TestFunction() {\n" ++ " var a = 'a';\n" ++ " var b = 'b';\n" ++ " var c = 'c';\n" ++ " function A() {\n" ++ " return 2013;\n" ++ " }\n" ++ " function B() {\n" ++ " return String([a, c]);\n" ++ " }\n" ++ " return B();\n" ++ "}\n" +); + +var res = TestFunction(); +print(res); +assertEquals('a,c', res); + +var script = Debug.findScript(TestFunction); +var new_source = script.source.replace("2013", "b"); +print("new source: " + new_source); +var change_log = new Array(); +var result = Debug.LiveEdit.SetScriptSource(script, new_source, false, change_log); + +print("Result: " + JSON.stringify(result) + "\n"); +print("Change log: " + JSON.stringify(change_log) + "\n"); + +var res = TestFunction(); +print(res); +// This might be 'a,b' without a bug fixed. +assertEquals('a,c', res); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-check-stack.js b/deps/v8/test/debugger/debug/debug-liveedit-check-stack.js new file mode 100644 index 0000000000..bba7acafec --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-check-stack.js @@ -0,0 +1,138 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug + +unique_id = 1; + +function TestBase(name) { + print("TestBase constructor: " + name); + + this.ChooseAnimal = eval( + "/* " + unique_id + "*/\n" + + "(function ChooseAnimal(callback) {\n " + + " callback();\n" + + " return 'Cat';\n" + + "})\n" + ); + // Prevents eval script caching. + unique_id++; + + var script = Debug.findScript(this.ChooseAnimal); + + var orig_animal = "'Cat'"; + var patch_pos = script.source.indexOf(orig_animal); + var new_animal_patch = "'Capybara'"; + + var got_exception = false; + var successfully_changed = false; + + // Should be called from Debug context. + this.ScriptChanger = function() { + assertEquals(false, successfully_changed, "applying patch second time"); + // Runs in debugger context. + var change_log = new Array(); + try { + Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_animal.length, new_animal_patch, change_log); + } finally { + print("Change log: " + JSON.stringify(change_log) + "\n"); + } + successfully_changed = true; + }; +} + +function Noop() {} + +function WrapInCatcher(f, holder) { + return function() { + delete holder[0]; + try { + f(); + } catch (e) { + if (e instanceof Debug.LiveEdit.Failure) { + holder[0] = e; + } else { + throw e; + } + } + }; +} + +function WrapInNativeCall(f) { + return function() { + return %Call(f, undefined); + }; +} + +function WrapInDebuggerCall(f) { + return function() { + return %ExecuteInDebugContext(f); + }; +} + +function WrapInRestartProof(f) { + var already_called = false; + return function() { + if (already_called) { + return; + } + already_called = true; + f(); + } +} + +function WrapInConstructor(f) { + return function() { + return new function() { + f(); + }; + } +} + + +// A series of tests. In each test we call ChooseAnimal function that calls +// a callback that attempts to modify the function on the fly. + +test = new TestBase("First test ChooseAnimal without edit"); +assertEquals("Cat", test.ChooseAnimal(Noop)); + +test = new TestBase("Test without function on stack"); +test.ScriptChanger(); +assertEquals("Capybara", test.ChooseAnimal(Noop)); + +test = new TestBase("Test with function on stack"); +assertEquals("Capybara", test.ChooseAnimal(WrapInDebuggerCall(WrapInRestartProof(test.ScriptChanger)))); + + +test = new TestBase("Test with function on stack and with constructor frame"); +assertEquals("Capybara", test.ChooseAnimal(WrapInConstructor(WrapInDebuggerCall(WrapInRestartProof(test.ScriptChanger))))); + +test = new TestBase("Test with C++ frame above ChooseAnimal frame"); +exception_holder = {}; +assertEquals("Cat", test.ChooseAnimal(WrapInNativeCall(WrapInDebuggerCall(WrapInCatcher(test.ScriptChanger, exception_holder))))); +assertTrue(!!exception_holder[0]); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-compile-error.js b/deps/v8/test/debugger/debug/debug-liveedit-compile-error.js new file mode 100644 index 0000000000..24068eb1b3 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-compile-error.js @@ -0,0 +1,56 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug + +eval("var something1 = 25; \n" + + " function ChooseAnimal() { return 'Cat'; } \n" + + " ChooseAnimal.Helper = function() { return 'Help!'; }\n"); + +assertEquals("Cat", ChooseAnimal()); + +var script = Debug.findScript(ChooseAnimal); + +var orig_animal = "Cat"; +var patch_pos = script.source.indexOf(orig_animal); +var new_animal_patch = "Cap' + ) + 'bara"; + +var change_log = new Array(); +var caught_exception = null; +try { + Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, + orig_animal.length, new_animal_patch, change_log); +} catch (e) { + caught_exception = e; +} + +assertNotNull(caught_exception); +assertEquals("Unexpected token )", + caught_exception.details.syntaxErrorMessage); + +assertEquals(2, caught_exception.details.position.start.line); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-diff.js b/deps/v8/test/debugger/debug/debug-liveedit-diff.js new file mode 100644 index 0000000000..d049cb022d --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-diff.js @@ -0,0 +1,110 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug + +function CheckCompareOneWay(s1, s2) { + var diff_array = Debug.LiveEdit.TestApi.CompareStrings(s1, s2); + + var pos1 = 0; + var pos2 = 0; + print("Compare:"); + print("s1='" + s1 + "'"); + print("s2='" + s2 + "'"); + print("Diff:"); + print("" + diff_array); + for (var i = 0; i < diff_array.length; i += 3) { + var similar_length = diff_array[i] - pos1; + assertEquals(s1.substring(pos1, pos1 + similar_length), + s2.substring(pos2, pos2 + similar_length)); + + print(s1.substring(pos1, pos1 + similar_length)); + pos1 += similar_length; + pos2 += similar_length; + print("<<< " + pos1 + " " + diff_array[i + 1]); + print(s1.substring(pos1, diff_array[i + 1])); + print("==="); + print(s2.substring(pos2, diff_array[i + 2])); + print(">>> " + pos2 + " " + diff_array[i + 2]); + pos1 = diff_array[i + 1]; + pos2 = diff_array[i + 2]; + } + { + // After last change + var similar_length = s1.length - pos1; + assertEquals(similar_length, s2.length - pos2); + assertEquals(s1.substring(pos1, pos1 + similar_length), + s2.substring(pos2, pos2 + similar_length)); + + print(s1.substring(pos1, pos1 + similar_length)); + } + print(""); +} + +function CheckCompareOneWayPlayWithLF(s1, s2) { + var s1Oneliner = s1.replace(/\n/g, ' '); + var s2Oneliner = s2.replace(/\n/g, ' '); + CheckCompareOneWay(s1, s2); + CheckCompareOneWay(s1Oneliner, s2); + CheckCompareOneWay(s1, s2Oneliner); + CheckCompareOneWay(s1Oneliner, s2Oneliner); +} + +function CheckCompare(s1, s2) { + CheckCompareOneWayPlayWithLF(s1, s2); + CheckCompareOneWayPlayWithLF(s2, s1); +} + +CheckCompare("", ""); + +CheckCompare("a", "b"); + +CheckCompare( + "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway", + "yesterday\nall\nmy\ntroubles\nseem\nso\nfar\naway" +); + +CheckCompare( + "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway", + "\nall\nmy\ntroubles\nseemed\nso\nfar\naway" +); + +CheckCompare( + "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway", + "all\nmy\ntroubles\nseemed\nso\nfar\naway" +); + +CheckCompare( + "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway", + "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway\n" +); + +CheckCompare( + "yesterday\nall\nmy\ntroubles\nseemed\nso\nfar\naway", + "yesterday\nall\nmy\ntroubles\nseemed\nso\n" +); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-double-call.js b/deps/v8/test/debugger/debug/debug-liveedit-double-call.js new file mode 100644 index 0000000000..927efddf62 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-double-call.js @@ -0,0 +1,140 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug + + +function TestCase(test_scenario, expected_output) { + // Global variable, accessed from eval'd script. + test_output = ""; + + var script_text_generator = (function() { + var variables = { a: 1, b: 1, c: 1, d: 1, e: 1, f: 1 }; + + return { + get: function() { + return "(function() {\n " + + " function A() {\n " + + " test_output += 'a' + " + variables.a + ";\n " + + " test_output += '=';\n " + + " debugger;\n " + + " return 'Capybara';\n " + + " }\n " + + " function B(p1, p2) {\n " + + " test_output += 'b' + " + variables.b + ";\n " + + " return A();\n " + + " }\n " + + " function C() {\n " + + " test_output += 'c' + " + variables.c + ";\n " + + " // Function call with argument adaptor is intentional.\n " + + " return B();\n " + + " }\n " + + " function D() {\n " + + " test_output += 'd' + " + variables.d + ";\n " + + " // Function call with argument adaptor is intentional.\n " + + " return C(1, 2);\n " + + " }\n " + + " function E() {\n " + + " test_output += 'e' + " + variables.e + ";\n " + + " return D();\n " + + " }\n " + + " function F() {\n " + + " test_output += 'f' + " + variables.f + ";\n " + + " return E();\n " + + " }\n " + + " return F();\n " + + "})\n"; + }, + change: function(var_name) { + variables[var_name]++; + } + }; + })(); + + var test_fun = eval(script_text_generator.get()); + + var script = Debug.findScript(test_fun); + + var scenario_pos = 0; + + function DebuggerStatementHandler() { + while (true) { + assertTrue(scenario_pos < test_scenario.length); + var change_var = test_scenario[scenario_pos++]; + if (change_var == '=') { + // Continue. + return; + } + script_text_generator.change(change_var); + try { + Debug.LiveEdit.SetScriptSource(script, script_text_generator.get(), + false, []); + } catch (e) { + print("LiveEdit exception: " + e); + throw e; + } + } + } + + var saved_exception = null; + + function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + try { + DebuggerStatementHandler(); + } catch (e) { + saved_exception = e; + } + } else { + print("Other: " + event); + } + } + + Debug.setListener(listener); + assertEquals("Capybara", test_fun()); + Debug.setListener(null); + + if (saved_exception) { + print("Exception: " + saved_exception); + assertUnreachable(); + } + + print(test_output); + + assertEquals(expected_output, test_output); +} + +TestCase(['='], "f1e1d1c1b1a1="); + +TestCase(['c', '=', '='], "f1e1d1c1b1a1=c2b1a1="); + +TestCase(['b', 'c', 'd', 'e', '=', '='], "f1e1d1c1b1a1=e2d2c2b2a1="); + +TestCase(['b', 'c', '=', 'b', 'c', 'd', 'e', '=', '='], "f1e1d1c1b1a1=c2b2a1=e2d2c3b3a1="); + +TestCase(['e', 'f', '=', '='], "f1e1d1c1b1a1=f2e2d1c1b1a1="); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-exceptions.js b/deps/v8/test/debugger/debug/debug-liveedit-exceptions.js new file mode 100644 index 0000000000..36463b3dca --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-exceptions.js @@ -0,0 +1,66 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +Debug = debug.Debug + +function BestEditor() { + throw 'Emacs'; +} + +var exception = null; +var results = []; +var log = [] + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Exception) return; + try { + var source_line = event_data.sourceLineText(); + print(source_line); + log.push(source_line); + switch (results.length) { + case 0: + Replace(BestEditor, "Emacs", "Eclipse"); + break; + case 1: + Replace(BestEditor, "Eclipse", "Vim"); + break; + case 2: + break; + default: + assertUnreachable(); + } + } catch (e) { + exception = e; + } +}; + +function Replace(fun, original, patch) { + var script = Debug.findScript(fun); + if (fun.toString().indexOf(original) < 0) return; + var patch_pos = script.source.indexOf(original); + var change_log = []; + Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, original.length, patch, change_log); +} + +Debug.setListener(listener); +Debug.setBreakOnException(); + +for (var i = 0; i < 3; i++) { + try { + BestEditor(); + } catch (e) { + results.push(e); + } +} +Debug.setListener(null); + +assertNull(exception); +assertEquals(["Emacs", "Eclipse", "Vim"], results); +print(JSON.stringify(log, 1)); +assertEquals([ + " throw 'Emacs';", + " throw 'Eclipse';", + " throw 'Vim';", +], log); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-literals.js b/deps/v8/test/debugger/debug/debug-liveedit-literals.js new file mode 100644 index 0000000000..08edec3fbd --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-literals.js @@ -0,0 +1,92 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug + +function Test(old_expression, new_expression) { + // Generate several instances of function to test that we correctly fix + // all functions in memory. + var function_instance_number = 11; + eval("var t1 =1;\n" + + "ChooseAnimalArray = [];\n" + + "for (var i = 0; i < function_instance_number; i++) {\n" + + " ChooseAnimalArray.push(\n" + + " function ChooseAnimal() {\n" + + " return " + old_expression + ";\n" + + " });\n" + + "}\n" + + "var t2 =1;\n"); + + for (var i = 0; i < ChooseAnimalArray.length; i++) { + assertEquals("Cat", ChooseAnimalArray[i]()); + } + + var script = Debug.findScript(ChooseAnimalArray[0]); + + var patch_pos = script.source.indexOf(old_expression); + var new_animal_patch = new_expression; + + var change_log = new Array(); + Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, + old_expression.length, new_expression, change_log); + + for (var i = 0; i < ChooseAnimalArray.length; i++) { + assertEquals("Capybara", ChooseAnimalArray[i]()); + } +} + +// Check that old literal boilerplate was reset. +Test("['Cat'][0]", "['Capybara'][0]"); +Test("['Cat'][0]", "{a:'Capybara'}.a"); + +// No literals -> 1 literal. +Test("'Cat'", "['Capybara'][0]"); + +// No literals -> 2 literals. +Test("'Cat'", "['Capy'][0] + {a:'bara'}.a"); + +// 1 literal -> no literals. +Test("['Cat'][0]", "'Capybara'"); + +// 2 literals -> no literals. +Test("['Ca'][0] + {a:'t'}.a", "'Capybara'"); + +// No literals -> regexp. +Test("'Cat'", "(/.A.Y.A.A/i).exec('Capybara')[0]"); + +// Array literal -> regexp. +Test("['Cat'][0]", "(/.A.Y.A.A/i).exec('Capybara')[0]"); + +// Regexp -> object literal. +Test("(/.A./i).exec('Cat')[0]", "{c:'Capybara'}.c"); + +// No literals -> regexp. +Test("'Cat'", "(/.A.Y.A.A/i).exec('Capybara')[0]"); + +// Regexp -> no literals. +Test("(/.A./i).exec('Cat')[0]", "'Capybara'"); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-newsource.js b/deps/v8/test/debugger/debug/debug-liveedit-newsource.js new file mode 100644 index 0000000000..e6f55bbe09 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-newsource.js @@ -0,0 +1,75 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug + +eval("var something1 = 25; \n" + + "var something2 = 2010; \n" + + "// Array(); \n" + + "function ChooseAnimal() {\n" + + " return 'Cat';\n" + + "} \n" + + "function ChooseFurniture() {\n" + + " return 'Table';\n" + + "} \n" + + "function ChooseNumber() { return 17; } \n" + + "ChooseAnimal.Factory = function Factory() {\n" + + " return function FactoryImpl(name) {\n" + + " return 'Help ' + name;\n" + + " }\n" + + "}\n"); + +assertEquals("Cat", ChooseAnimal()); +assertEquals(25, something1); + +var script = Debug.findScript(ChooseAnimal); + +var new_source = script.source.replace("Cat", "Cap' + 'yb' + 'ara"); +var new_source = new_source.replace("25", "26"); +var new_source = new_source.replace("Help", "Hello"); +var new_source = new_source.replace("17", "18"); +// The call to array causes a change in the number of type feedback slots for +// the script. +// +// TODO(mvstanton): For now, the inclusion of the Array() call at the top level +// of the script causes us to visit a corner case, but I'd like to validate +// correctness more explicitly. +var new_source = new_source.replace("// Array", "Array"); +print("new source: " + new_source); + +var change_log = new Array(); +var result = Debug.LiveEdit.SetScriptSource(script, new_source, false, change_log); +print("Result: " + JSON.stringify(result) + "\n"); +print("Change log: " + JSON.stringify(change_log) + "\n"); + +assertEquals("Capybara", ChooseAnimal()); +// Global variable do not get changed (without restarting script). +assertEquals(25, something1); +// We should support changes in oneliners. +assertEquals(18, ChooseNumber()); +assertEquals("Hello Peter", ChooseAnimal.Factory()("Peter")); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-patch-positions-replace.js b/deps/v8/test/debugger/debug/debug-liveedit-patch-positions-replace.js new file mode 100644 index 0000000000..374ffde643 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-patch-positions-replace.js @@ -0,0 +1,81 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Scenario: a function is being changed, which causes enclosing function to +// have its positions patched; position changing requires new instance of Code +// object to be introduced; the function happens to be on stack at this moment; +// later it will resume over new instance of Code. +// Before the change 2 rinfo are 22 characters away from each other. After the +// change they are 114 characters away from each other. New instance of Code is +// required when those numbers cross the border value of 64 (in any direction). + +Debug = debug.Debug + +eval( + "function BeingReplaced(changer, opt_x, opt_y) {\n" + + " changer();\n" + + " var res = new Object();\n" + + " if (opt_x) { res.y = opt_y; }\n" + + " res.a = (function() {})();\n" + + " return res.a;\n" + + "}" +); + +var script = Debug.findScript(BeingReplaced); + +var orig_body = "{}"; +var patch_pos = script.source.indexOf(orig_body); +// Line long enough to change rinfo encoding. +var new_body_patch = "{return 'Capybara';" + + " " + + "}"; + +var change_log = new Array(); +function Changer() { + Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, orig_body.length, new_body_patch, change_log); + print("Change log: " + JSON.stringify(change_log) + "\n"); +} + +function NoOp() { +} + +function CallM(changer) { + // We expect call IC here after several function runs. + return BeingReplaced(changer); +} + +// This several iterations should cause call IC for BeingReplaced call. This IC +// will keep reference to code object of BeingRepalced function. This reference +// should also be patched. Unfortunately, this is a manually checked fact (from +// debugger or debug print) and doesn't work as an automatic test. +CallM(NoOp); +CallM(NoOp); +CallM(NoOp); + +var res = CallM(Changer); +assertEquals("Capybara", res); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-restart-frame.js b/deps/v8/test/debugger/debug/debug-liveedit-restart-frame.js new file mode 100644 index 0000000000..659e3c74e6 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-restart-frame.js @@ -0,0 +1,154 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Flags: --noanalyze-environment-liveness + + +Debug = debug.Debug + +function FindCallFrame(exec_state, frame_code) { + var number = Number(frame_code); + if (number >= 0) { + return exec_state.frame(number); + } else { + for (var i = 0; i < exec_state.frameCount(); i++) { + var frame = exec_state.frame(i); + var func_mirror = frame.func(); + if (frame_code == func_mirror.name()) { + return frame; + } + } + } + throw new Error("Failed to find function name " + function_name); +} + +function TestCase(test_scenario, expected_output) { + // Global variable, accessed from eval'd script. + test_output = ""; + + function TestCode() { + function A() { + // Extra stack variable. To make function not slim. + // Restarter doesn't work on slim function when stopped on 'debugger' + // statement. (There is no padding for 'debugger' statement). + var o = {}; + test_output += 'A'; + test_output += '='; + debugger; + return 'Capybara'; + } + function B(p1, p2) { + test_output += 'B'; + return A(); + } + function C() { + test_output += 'C'; + // Function call with argument adaptor is intentional. + return B(); + } + function D() { + test_output += 'D'; + // Function call with argument adaptor is intentional. + return C(1, 2); + } + function E() { + test_output += 'E'; + return D(); + } + function F() { + test_output += 'F'; + return E(); + } + return F(); + } + + var scenario_pos = 0; + + function DebuggerStatementHandler(exec_state) { + while (true) { + assertTrue(scenario_pos < test_scenario.length); + var change_code = test_scenario[scenario_pos++]; + if (change_code == '=') { + // Continue. + return; + } + var frame = FindCallFrame(exec_state, change_code); + var error = frame.restart(); + if (typeof error === 'string') + throw new Error(error); + } + } + + var saved_exception = null; + + function listener(event, exec_state, event_data, data) { + if (saved_exception != null) { + return; + } + if (event == Debug.DebugEvent.Break) { + try { + DebuggerStatementHandler(exec_state); + } catch (e) { + saved_exception = e; + } + } else { + print("Other: " + event); + } + } + + Debug.setListener(listener); + assertEquals("Capybara", TestCode()); + Debug.setListener(null); + + if (saved_exception) { + print("Exception: " + saved_exception); + print("Stack: " + saved_exception.stack); + assertUnreachable(); + } + + print(test_output); + + assertEquals(expected_output, test_output); +} + +TestCase('0==', "FEDCBA=A="); +TestCase('1==', "FEDCBA=BA="); +TestCase('2==', "FEDCBA=CBA="); +TestCase('3==', "FEDCBA=DCBA="); +TestCase('4==', "FEDCBA=EDCBA="); +TestCase('5==', "FEDCBA=FEDCBA="); + +TestCase('=', "FEDCBA="); + +TestCase('C==', "FEDCBA=CBA="); + +TestCase('B=C=A=D==', "FEDCBA=BA=CBA=A=DCBA="); + +// Successive restarts don't work now and require additional fix. +//TestCase('BCDE==', "FEDCBA=EDCBA="); +//TestCase('BC=BCDE==', "FEDCBA=CBA=EDCBA="); +//TestCase('EF==', "FEDCBA=FEDCBA="); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-stack-padding.js b/deps/v8/test/debugger/debug/debug-liveedit-stack-padding.js new file mode 100644 index 0000000000..d0cc77ac7a --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-stack-padding.js @@ -0,0 +1,88 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug; +Debug.setListener(listener); + +SlimFunction = eval( + "(function() {\n " + + " return 'Cat';\n" + + "})\n" +); + +var script = Debug.findScript(SlimFunction); + +Debug.setScriptBreakPointById(script.id, 1, 0); + +var orig_animal = "'Cat'"; +var patch_pos = script.source.indexOf(orig_animal); +var new_animal_patch = "'Capybara'"; + +debugger_handler = (function() { + var already_called = false; + return function() { + if (already_called) { + return; + } + already_called = true; + + var change_log = new Array(); + try { + Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, + orig_animal.length, new_animal_patch, change_log); + } finally { + print("Change log: " + JSON.stringify(change_log) + "\n"); + } + }; +})(); + +var saved_exception = null; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + try { + debugger_handler(); + } catch (e) { + saved_exception = e; + } + } else { + print("Other: " + event); + } +} + + +var animal = SlimFunction(); + +if (saved_exception) { + print("Exception: " + saved_exception); + assertUnreachable(); +} + +assertEquals("Capybara", animal); + +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-stepin.js b/deps/v8/test/debugger/debug/debug-liveedit-stepin.js new file mode 100644 index 0000000000..a453525bc9 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-stepin.js @@ -0,0 +1,74 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +Debug = debug.Debug + +function BestEditor() { + return 'Emacs'; +} + +var exception = null; +var results = []; +var log = [] + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var source_line = event_data.sourceLineText(); + log.push(source_line); + if (source_line.indexOf("return") >= 0) { + switch (results.length) { + case 0: + break; + case 1: + Replace(BestEditor, "Emacs", "Eclipse"); + break; + case 2: + Replace(BestEditor, "Eclipse", "Vim"); + break; + default: + assertUnreachable(); + } + } + exec_state.prepareStep(Debug.StepAction.StepIn); + } catch (e) { + exception = e; + } +}; + +function Replace(fun, original, patch) { + var script = Debug.findScript(fun); + if (fun.toString().indexOf(original) < 0) return; + var patch_pos = script.source.indexOf(original); + var change_log = []; + Debug.LiveEdit.TestApi.ApplySingleChunkPatch(script, patch_pos, original.length, patch, change_log); +} + +Debug.setListener(listener); + +debugger; +results.push(BestEditor()); +results.push(BestEditor()); +results.push(BestEditor()); +Debug.setListener(null); + +assertNull(exception); +assertEquals(["Emacs", "Eclipse", "Vim"], results); +print(JSON.stringify(log, 1)); +assertEquals([ + "debugger;", + "results.push(BestEditor());", + " return 'Emacs';","}", + "results.push(BestEditor());", + "results.push(BestEditor());", + " return 'Emacs';", + " return 'Eclipse';","}", + "results.push(BestEditor());", + "results.push(BestEditor());", + " return 'Eclipse';", + " return 'Vim';", + "}","results.push(BestEditor());", + "Debug.setListener(null);" +], log); diff --git a/deps/v8/test/debugger/debug/debug-liveedit-utils.js b/deps/v8/test/debugger/debug/debug-liveedit-utils.js new file mode 100644 index 0000000000..df631817f5 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-liveedit-utils.js @@ -0,0 +1,93 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug + +function Return2010() { + return 2010; +} + + +// Diff it trivial: zero chunks +var NoChunkTranslator = new Debug.LiveEdit.TestApi.PosTranslator([]); + +assertEquals(0, NoChunkTranslator.Translate(0)); +assertEquals(10, NoChunkTranslator.Translate(10)); + + +// Diff has one chunk +var SingleChunkTranslator = new Debug.LiveEdit.TestApi.PosTranslator([20, 30, 25]); + +assertEquals(0, SingleChunkTranslator.Translate(0)); +assertEquals(5, SingleChunkTranslator.Translate(5)); +assertEquals(10, SingleChunkTranslator.Translate(10)); +assertEquals(19, SingleChunkTranslator.Translate(19)); +assertEquals(2010, SingleChunkTranslator.Translate(20, Return2010)); +assertEquals(25, SingleChunkTranslator.Translate(30)); +assertEquals(26, SingleChunkTranslator.Translate(31)); +assertEquals(2010, SingleChunkTranslator.Translate(26, Return2010)); + +try { + SingleChunkTranslator.Translate(21); + assertTrue(false); +} catch (ignore) { +} +try { + SingleChunkTranslator.Translate(24); + assertTrue(false); +} catch (ignore) { +} + + +// Diff has several chunk (3). See the table below. + +/* +chunks: (new <- old) + 10 10 + 15 20 + + 35 40 + 50 40 + + 70 60 + 70 70 +*/ + +var MultiChunkTranslator = new Debug.LiveEdit.TestApi.PosTranslator([10, 20, 15, 40, 40, 50, 60, 70, 70 ]); +assertEquals(5, MultiChunkTranslator.Translate(5)); +assertEquals(9, MultiChunkTranslator.Translate(9)); +assertEquals(2010, MultiChunkTranslator.Translate(10, Return2010)); +assertEquals(15, MultiChunkTranslator.Translate(20)); +assertEquals(20, MultiChunkTranslator.Translate(25)); +assertEquals(34, MultiChunkTranslator.Translate(39)); +assertEquals(50, MultiChunkTranslator.Translate(40, Return2010)); +assertEquals(55, MultiChunkTranslator.Translate(45)); +assertEquals(69, MultiChunkTranslator.Translate(59)); +assertEquals(2010, MultiChunkTranslator.Translate(60, Return2010)); +assertEquals(70, MultiChunkTranslator.Translate(70)); +assertEquals(75, MultiChunkTranslator.Translate(75)); diff --git a/deps/v8/test/debugger/debug/debug-multiple-breakpoints.js b/deps/v8/test/debugger/debug/debug-multiple-breakpoints.js new file mode 100644 index 0000000000..6e19140b6a --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-multiple-breakpoints.js @@ -0,0 +1,92 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +// Simple debug event handler which just counts the number of break points hit. +var break_point_hit_count; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + break_point_hit_count++; + } +}; + +// Add the debug event listener. +Debug.setListener(listener); + +// Test functions +function f() {a=1;b=2;}; +function g() {f();} +function h() {} + +// This test sets several break points at the same place and checks that +// several break points at the same place only makes one debug break event +// and that when the last break point is removed no more debug break events +// occours. +break_point_hit_count = 0; + +// Set a breakpoint in f. +bp1 = Debug.setBreakPoint(f); +f(); +assertEquals(1, break_point_hit_count); + +// Set another breakpoint in f at the same place. +assertThrows(() => Debug.setBreakPoint(f)); +f(); +assertEquals(2, break_point_hit_count); + +// Remove the break points. +Debug.clearBreakPoint(bp1); +f(); +assertEquals(2, break_point_hit_count); + +// Perform the same test using function g (this time removing the break points +// in the another order). +break_point_hit_count = 0; +bp1 = Debug.setBreakPoint(g); +g(); +assertEquals(1, break_point_hit_count); +assertThrows(() => Debug.setBreakPoint(g)); +g(); +assertEquals(2, break_point_hit_count); +Debug.clearBreakPoint(bp1); +g(); +assertEquals(2, break_point_hit_count); + +// Finally test with many break points. +test_count = 10; +break_point_hit_count = 0; +for (var i = 0; i < test_count; i++) { + if (i == 0) { + Debug.setBreakPoint(h); + } else { + assertThrows(() => Debug.setBreakPoint(h)); + } + h(); +} +assertEquals(test_count, break_point_hit_count); diff --git a/deps/v8/test/debugger/debug/debug-multiple-var-decl.js b/deps/v8/test/debugger/debug/debug-multiple-var-decl.js new file mode 100644 index 0000000000..2e6deb781c --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-multiple-var-decl.js @@ -0,0 +1,73 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test we break at every assignment in a var-statement with multiple +// variable declarations. + +var exception = null; +var log = [] + +function f() { + var l1 = 1, // l + l2, // m + l3 = 3; // n + let l4, // o + l5 = 5, // p + l6 = 6; // q + const l7 = 7, // r + l8 = 8, // s + l9 = 9; // t + return 0; // u +} // v + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var line = exec_state.frame(0).sourceLineText(); + var col = exec_state.frame(0).sourceColumn(); + print(line); + var match = line.match(/\/\/ (\w)$/); + assertEquals(2, match.length); + log.push(match[1] + col); + if (match[1] != "v") { + exec_state.prepareStep(Debug.StepAction.StepIn); + } + } catch (e) { + exception = e; + } +} + +var Debug = debug.Debug; +Debug.setListener(listener); + +debugger; // a +var g1 = 1, // b + g2 = 2, // c + g3; // d +let g4 = 4, // e + g5, // f + g6 = 6; // g +const g7 = 7, // h + g8 = 8, // i + g9 = f(); // j + +Debug.setListener(null); + +assertNull(exception); + +// Note that let declarations, if not explicitly initialized, implicitly +// initialize to undefined. + +var expected = [ + "a0", // debugger statement + "b9","c9", // global var + "e9","f4","g9", // global let + "h11","i11","j11", // global const + "l11","n11", // local var + "o6","p11","q11", // local let + "r13","s13","t13", // local const + "u2","v0", // return +]; +assertEquals(expected, log); diff --git a/deps/v8/test/debugger/debug/debug-negative-break-points.js b/deps/v8/test/debugger/debug/debug-negative-break-points.js new file mode 100644 index 0000000000..51ce21bab8 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-negative-break-points.js @@ -0,0 +1,98 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +var Debug = debug.Debug; +var break_count = 0; +var exception_count = 0; + +function assertCount(expected_breaks, expected_exceptions) { + assertEquals(expected_breaks, break_count); + assertEquals(expected_exceptions, exception_count); +} + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + break_count++; + } else if (event == Debug.DebugEvent.Exception) { + exception_count++; + } +} + +function f(x) { + debugger; + return x + 1; +} + +function g(x) { + try { + throw x; + } catch (e) { + } +} + +function h(x) { + var a = undefined; + try { + var x = a(); + } catch (e) { + } +} + +Debug.setListener(listener); + +assertCount(0, 0); +f(0); +assertCount(1, 0); +g(0); +assertCount(1, 0); + +Debug.setBreakOnException(); +f(0); +assertCount(2, 0); +g(0); +assertCount(2, 1); + +Debug.setBreakPoint(f, 1, 0, "x == 1"); +f(1); +assertCount(3, 1); +f(2); +assertCount(3, 1); +f(1); +assertCount(4, 1); + +assertThrows(() => Debug.setBreakPoint(f, 1, 0, "x > 0")); +f(1); +assertCount(5, 2); +f(0); +assertCount(5, 2); + +Debug.setBreakPoint(g, 2, 0, "1 == 2"); +g(1); +assertCount(5, 2); + +assertThrows(() => Debug.setBreakPoint(g, 2, 0, "x == 1")); +g(1); +assertCount(5, 3); +g(2); +assertCount(5, 3); +g(1); +assertCount(5, 3); + +assertThrows(() => Debug.setBreakPoint(g, 2, 0, "x > 0")); +g(1); +assertCount(5, 4); +g(0); +assertCount(5, 4); + +h(0); +assertCount(5, 5); +Debug.setBreakPoint(h, 3, 0, "x > 0"); +h(1); +assertCount(6, 6); +h(0); +assertCount(6, 6); + +Debug.clearBreakOnException(); +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/debug-receiver.js b/deps/v8/test/debugger/debug/debug-receiver.js new file mode 100644 index 0000000000..9096e315f6 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-receiver.js @@ -0,0 +1,122 @@ +// Copyright 2011 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug; + +var test_name; +var listener_delegate; +var listener_called; +var exception; +var expected_receiver; +var begin_test_count = 0; +var end_test_count = 0; +var break_count = 0; + +// Debug event listener which delegates. Exceptions have to be +// explictly caught here and checked later because exception in the +// listener are not propagated to the surrounding JavaScript code. +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + break_count++; + listener_called = true; + listener_delegate(exec_state); + } + } catch (e) { + exception = e; + } +} + +// Add the debug event listener. +Debug.setListener(listener); + + +// Initialize for a new test. +function BeginTest(name) { + test_name = name; + listener_called = false; + exception = null; + begin_test_count++; +} + + +// Check result of a test. +function EndTest() { + assertTrue(listener_called, "listener not called for " + test_name); + assertNull(exception, test_name); + end_test_count++; +} + + +// Check that the debugger correctly reflects that the receiver is not +// converted to object for strict mode functions. +function Strict() { "use strict"; debugger; } +function TestStrict(receiver) { + expected_receiver = receiver; + Strict.call(receiver); +} + +listener_delegate = function(exec_state) { + var receiver = exec_state.frame().receiver(); + assertEquals(expected_receiver, receiver.value()) +} + +BeginTest("strict: undefined"); TestStrict(undefined); EndTest(); +BeginTest("strict: null"); TestStrict(null); EndTest(); +BeginTest("strict: 1"); TestStrict(1); EndTest(); +BeginTest("strict: 1.2"); TestStrict(1.2); EndTest(); +BeginTest("strict: 'asdf'"); TestStrict('asdf'); EndTest(); +BeginTest("strict: true"); TestStrict(true); EndTest(); + + +// Check that the debugger correctly reflects the object conversion of +// the receiver for non-strict mode functions. +function NonStrict() { debugger; } +function TestNonStrict(receiver) { + // null and undefined should be transformed to the global object and + // primitives should be wrapped. + expected_receiver = (receiver == null) ? this : Object(receiver); + NonStrict.call(receiver); +} + +listener_delegate = function(exec_state) { + var receiver = exec_state.frame().receiver(); + assertEquals(expected_receiver, receiver.value()); +} + +BeginTest("non-strict: undefined"); TestNonStrict(undefined); EndTest(); +BeginTest("non-strict: null"); TestNonStrict(null); EndTest(); +BeginTest("non-strict: 1"); TestNonStrict(1); EndTest(); +BeginTest("non-strict: 1.2"); TestNonStrict(1.2); EndTest(); +BeginTest("non-strict: 'asdf'"); TestNonStrict('asdf'); EndTest(); +BeginTest("non-strict: true"); TestNonStrict(true); EndTest(); + + +assertEquals(begin_test_count, break_count, + 'one or more tests did not enter the debugger'); +assertEquals(begin_test_count, end_test_count, + 'one or more tests did not have its result checked'); diff --git a/deps/v8/test/debugger/debug/debug-return-value.js b/deps/v8/test/debugger/debug/debug-return-value.js new file mode 100644 index 0000000000..cb4000ea31 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-return-value.js @@ -0,0 +1,118 @@ +// Copyright 2010 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +listener_complete = false; +exception = false; +break_count = 0; +expected_return_value = 0; +debugger_source_position = 0; + +// Listener which expects to do four steps to reach returning from the function. +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) + { + break_count++; + if (break_count < 4) { + switch (break_count) { + case 1: + // Collect the position of the debugger statement. + debugger_source_position = exec_state.frame(0).sourcePosition(); + break; + case 2: + // Position now at the if statement. + assertEquals(debugger_source_position + 10, + exec_state.frame(0).sourcePosition()); + break; + case 3: + // Position now at either of the returns. + if (expected_return_value == 1) { + assertEquals(debugger_source_position + 19, + exec_state.frame(0).sourcePosition()); + } else { + assertEquals(debugger_source_position + 38, + exec_state.frame(0).sourcePosition()); + } + break; + default: + fail("Unexpected"); + } + exec_state.prepareStep(Debug.StepAction.StepIn); + } else { + // Position at the end of the function. + assertEquals(debugger_source_position + 50, + exec_state.frame(0).sourcePosition()); + + // Just about to return from the function. + assertEquals(expected_return_value, + exec_state.frame(0).returnValue().value()); + + listener_complete = true; + } + } + } catch (e) { + exception = e + print(e + e.stack) + }; +}; + +// Add the debug event listener. +Debug.setListener(listener); + +// Four steps from the debugger statement in this function will position us at +// the function return. +// 0 1 2 3 4 5 +// 0123456789012345678901234567890123456789012345678901 + +function f(x) {debugger; if (x) { return 1; } else { return 2; } }; + +// Call f expecting different return values. +break_count = 0; +expected_return_value = 2; +listener_complete = false; +f(); +assertFalse(exception, "exception in listener") +assertTrue(listener_complete); +assertEquals(4, break_count); + +break_count = 0; +expected_return_value = 1; +listener_complete = false; +f(true); +assertFalse(exception, "exception in listener") +assertTrue(listener_complete); +assertEquals(4, break_count); + +break_count = 0; +expected_return_value = 2; +listener_complete = false; +f(false); +assertFalse(exception, "exception in listener") +assertTrue(listener_complete); +assertEquals(4, break_count); diff --git a/deps/v8/test/debugger/debug/debug-scopes-suspended-generators.js b/deps/v8/test/debugger/debug/debug-scopes-suspended-generators.js new file mode 100644 index 0000000000..38fb7fab93 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-scopes-suspended-generators.js @@ -0,0 +1,458 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --ignition +// The functions used for testing backtraces. They are at the top to make the +// testing of source line/column easier. + +var Debug = debug.Debug; + +var test_name; +var exception; +var begin_test_count = 0; +var end_test_count = 0; + +// Initialize for a new test. +function BeginTest(name) { + test_name = name; + exception = null; + begin_test_count++; +} + +// Check result of a test. +function EndTest() { + assertNull(exception, test_name + " / " + exception); + end_test_count++; +} + +// Check that two scope are the same. +function assertScopeMirrorEquals(scope1, scope2) { + assertEquals(scope1.scopeType(), scope2.scopeType()); + assertEquals(scope1.scopeIndex(), scope2.scopeIndex()); + assertPropertiesEqual(scope1.scopeObject().value(), + scope2.scopeObject().value()); +} + +// Check that the scope chain contains the expected types of scopes. +function CheckScopeChain(scopes, gen) { + var all_scopes = Debug.generatorScopes(gen); + assertEquals(scopes.length, Debug.generatorScopeCount(gen)); + assertEquals(scopes.length, all_scopes.length, + "FrameMirror.allScopes length"); + for (var i = 0; i < scopes.length; i++) { + var scope = all_scopes[i]; + assertEquals(scopes[i], scope.scopeType(), + `Scope ${i} has unexpected type`); + + // Check the global object when hitting the global scope. + if (scopes[i] == debug.ScopeType.Global) { + // Objects don't have same class (one is "global", other is "Object", + // so just check the properties directly. + assertPropertiesEqual(this, scope.scopeObject().value()); + } + } +} + +// Check that the content of the scope is as expected. For functions just check +// that there is a function. +function CheckScopeContent(content, number, gen) { + var scope = Debug.generatorScope(gen, number); + var count = 0; + for (var p in content) { + var property_mirror = scope.scopeObject().property(p); + if (content[p] === undefined) { + assertTrue(property_mirror === undefined); + } else { + assertFalse(property_mirror === undefined, + 'property ' + p + ' not found in scope'); + } + if (typeof(content[p]) === 'function') { + assertTrue(typeof property_mirror == "function"); + } else { + assertEquals(content[p], property_mirror, + 'property ' + p + ' has unexpected value'); + } + count++; + } + + // 'arguments' and might be exposed in the local and closure scope. Just + // ignore this. + var scope_size = scope.scopeObject().properties().length; + if (scope.scopeObject().property('arguments') !== undefined) { + scope_size--; + } + // Ditto for 'this'. + if (scope.scopeObject().property('this') !== undefined) { + scope_size--; + } + // Temporary variables introduced by the parser have not been materialized. + assertTrue(scope.scopeObject().property('') === undefined); + + if (count != scope_size) { + print('Names found in scope:'); + var names = scope.scopeObject().propertyNames(); + for (var i = 0; i < names.length; i++) { + print(names[i]); + } + } + assertEquals(count, scope_size); +} + +// Simple empty closure scope. + +function *gen1() { + yield 1; + return 2; +} + +var g = gen1(); +CheckScopeChain([debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({}, 0, g); + +// Closure scope with a parameter. + +function *gen2(a) { + yield a; + return 2; +} + +g = gen2(42); +CheckScopeChain([debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({a: 42}, 0, g); + +// Closure scope with a parameter. + +function *gen3(a) { + var b = 1 + yield a; + return b; +} + +g = gen3(0); +CheckScopeChain([debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({a: 0, b: undefined}, 0, g); + +g.next(); // Create b. +CheckScopeContent({a: 0, b: 1}, 0, g); + +// Closure scope with a parameter. + +function *gen4(a, b) { + var x = 2; + yield a; + var y = 3; + return b; +} + +g = gen4(0, 1); +CheckScopeChain([debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({a: 0, b: 1, x: undefined, y: undefined}, 0, g); + +g.next(); // Create x. +CheckScopeContent({a: 0, b: 1, x: 2, y: undefined}, 0, g); + +g.next(); // Create y. +CheckScopeContent({a: 0, b: 1, x: 2, y: 3}, 0, g); + +// Closure introducing local variable using eval. + +function *gen5(a) { + eval('var b = 2'); + return b; +} + +g = gen5(1); +g.next(); +CheckScopeChain([debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({a: 1, b: 2}, 0, g); + +// Single empty with block. + +function *gen6() { + with({}) { + yield 1; + } + yield 2; + return 3; +} + +g = gen6(); +g.next(); +CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({}, 0, g); + +g.next(); +CheckScopeChain([debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); + +// Nested empty with blocks. + +function *gen7() { + with({}) { + with({}) { + yield 1; + } + yield 2; + } + return 3; +} + +g = gen7(); +g.next(); +CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({}, 0, g); + +// Nested with blocks using in-place object literals. + +function *gen8() { + with({a: 1,b: 2}) { + with({a: 2,b: 1}) { + yield a; + } + yield a; + } + return 3; +} + +g = gen8(); +g.next(); +CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({a: 2, b: 1}, 0, g); + +g.next(); +CheckScopeContent({a: 1, b: 2}, 0, g); + +// Catch block. + +function *gen9() { + try { + throw 42; + } catch (e) { + yield e; + } + return 3; +} + +g = gen9(); +g.next(); +CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({e: 42}, 0, g); + +// For statement with block scope. + +function *gen10() { + for (let i = 0; i < 42; i++) yield i; + return 3; +} + +g = gen10(); +g.next(); +CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Block, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({i: 0}, 0, g); + +g.next(); +CheckScopeContent({i: 1}, 0, g); +CheckScopeContent({i: 0}, 1, g); // Additional block scope with i = 0; + +// Nested generators. + +var gen12; +function *gen11() { + gen12 = function*() { + var a = 1; + yield 1; + return 2; + }(); + + var a = 0; + yield* gen12; +} + +gen11().next(); +g = gen12; + +CheckScopeChain([debug.ScopeType.Closure, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({a: 1}, 0, g); +CheckScopeContent({a: 0}, 1, g); + +// Set a variable in an empty scope. + +function *gen13() { + yield 1; + return 2; +} + +var g = gen13(); +assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("a", 42)); +CheckScopeContent({}, 0, g); + +// Set a variable in a simple scope. + +function *gen14() { + var a = 0; + yield 1; + yield a; + return 2; +} + +var g = gen14(); +assertEquals(1, g.next().value); + +CheckScopeContent({a: 0}, 0, g); + +Debug.generatorScope(g, 0).setVariableValue("a", 1); +CheckScopeContent({a: 1}, 0, g); + +assertEquals(1, g.next().value); + +// Set a variable in nested with blocks using in-place object literals. + +function *gen15() { + var c = 3; + with({a: 1,b: 2}) { + var d = 4; + yield a; + var e = 5; + } + yield e; + return e; +} + +var g = gen15(); +assertEquals(1, g.next().value); + +CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({a: 1, b: 2}, 0, g); +CheckScopeContent({c: 3, d: 4, e: undefined}, 1, g); + +// Variables don't exist in given scope. +assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("c", 42)); +assertThrows(() => Debug.generatorScope(g, 1).setVariableValue("a", 42)); + +// Variables in with scope are immutable. +assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("a", 3)); +assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("b", 3)); + +Debug.generatorScope(g, 1).setVariableValue("c", 1); +Debug.generatorScope(g, 1).setVariableValue("e", 42); + +CheckScopeContent({a: 1, b: 2}, 0, g); +CheckScopeContent({c: 1, d: 4, e: 42}, 1, g); +assertEquals(5, g.next().value); // Initialized after set. + +CheckScopeChain([debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); + +Debug.generatorScope(g, 0).setVariableValue("e", 42); + +CheckScopeContent({c: 1, d: 4, e: 42}, 0, g); +assertEquals(42, g.next().value); + +// Set a variable in nested with blocks using in-place object literals plus a +// nested block scope. + +function *gen16() { + var c = 3; + with({a: 1,b: 2}) { + let d = 4; + yield a; + let e = 5; + yield d; + } + return 3; +} + +var g = gen16(); +g.next(); + +CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.With, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({d: 4}, 0, g); +CheckScopeContent({a: 1, b: 2}, 1, g); +CheckScopeContent({c: 3}, 2, g); + +Debug.generatorScope(g, 0).setVariableValue("d", 1); +CheckScopeContent({d: 1}, 0, g); + +assertEquals(1, g.next().value); + +// Set variable in catch block. + +var yyzyzzyz = 4829; +let xxxyyxxyx = 42284; +function *gen17() { + try { + throw 42; + } catch (e) { + yield e; + yield e; + } + return 3; +} + +g = gen17(); +g.next(); + +CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], g); +CheckScopeContent({e: 42}, 0, g); +CheckScopeContent({xxxyyxxyx: 42284, + printProtocolMessages : printProtocolMessages, + activeWrapper : activeWrapper, + DebugWrapper : DebugWrapper + }, 2, g); + +Debug.generatorScope(g, 0).setVariableValue("e", 1); +CheckScopeContent({e: 1}, 0, g); + +assertEquals(1, g.next().value); + +// Script scope. +Debug.generatorScope(g, 2).setVariableValue("xxxyyxxyx", 42); +assertEquals(42, xxxyyxxyx); + +// Global scope. +assertThrows(() => Debug.generatorScope(g, 3).setVariableValue("yyzyzzyz", 42)); +assertEquals(4829, yyzyzzyz); diff --git a/deps/v8/test/debugger/debug/debug-scopes.js b/deps/v8/test/debugger/debug/debug-scopes.js new file mode 100644 index 0000000000..b2f9e33825 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-scopes.js @@ -0,0 +1,1260 @@ +// Copyright 2011 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --noanalyze-environment-liveness +// The functions used for testing backtraces. They are at the top to make the +// testing of source line/column easier. + +var Debug = debug.Debug; + +var test_name; +var listener_delegate; +var listener_called; +var exception; +var begin_test_count = 0; +var end_test_count = 0; +var break_count = 0; +var global_marker = 7; + + +// Debug event listener which delegates. +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + break_count++; + listener_called = true; + listener_delegate(exec_state); + } + } catch (e) { + exception = e; + print(e, e.stack); + } +} + +// Add the debug event listener. +Debug.setListener(listener); + + +// Initialize for a new test. +function BeginTest(name) { + test_name = name; + listener_delegate = null; + listener_called = false; + exception = null; + begin_test_count++; +} + + +// Check result of a test. +function EndTest() { + assertTrue(listener_called, "listener not called for " + test_name); + assertNull(exception, test_name + " / " + exception); + end_test_count++; +} + + +// Check that two scope are the same. +function assertScopeMirrorEquals(scope1, scope2) { + assertEquals(scope1.scopeType(), scope2.scopeType()); + assertEquals(scope1.frameIndex(), scope2.frameIndex()); + assertEquals(scope1.scopeIndex(), scope2.scopeIndex()); + assertPropertiesEqual(scope1.scopeObject().value(), scope2.scopeObject().value()); +} + +function CheckFastAllScopes(scopes, exec_state) +{ + var fast_all_scopes = exec_state.frame().allScopes(true); + var length = fast_all_scopes.length; + assertTrue(scopes.length >= length); + for (var i = 0; i < scopes.length && i < length; i++) { + var scope = fast_all_scopes[length - i - 1]; + assertEquals(scopes[scopes.length - i - 1], scope.scopeType()); + } +} + + +// Check that the scope chain contains the expected types of scopes. +function CheckScopeChain(scopes, exec_state) { + var all_scopes = exec_state.frame().allScopes(); + assertEquals(scopes.length, exec_state.frame().scopeCount()); + assertEquals(scopes.length, all_scopes.length, "FrameMirror.allScopes length"); + for (var i = 0; i < scopes.length; i++) { + var scope = exec_state.frame().scope(i); + assertEquals(scopes[i], scope.scopeType()); + assertScopeMirrorEquals(all_scopes[i], scope); + + // Check the global object when hitting the global scope. + if (scopes[i] == debug.ScopeType.Global) { + // Just check the marker of the global object. + assertEquals(scope.scopeObject().value().global_marker, global_marker); + } + } + CheckFastAllScopes(scopes, exec_state); +} + + +// Check that the scope chain contains the expected names of scopes. +function CheckScopeChainNames(names, exec_state) { + var all_scopes = exec_state.frame().allScopes(); + assertEquals(names.length, all_scopes.length, "FrameMirror.allScopes length"); + for (var i = 0; i < names.length; i++) { + var scope = exec_state.frame().scope(i); + assertEquals(names[i], scope.details().name()) + } +} + + +// Check that the scope contains at least minimum_content. For functions just +// check that there is a function. +function CheckScopeContent(minimum_content, number, exec_state) { + var scope = exec_state.frame().scope(number); + var minimum_count = 0; + for (var p in minimum_content) { + var property_mirror = scope.scopeObject().property(p); + assertFalse(property_mirror.isUndefined(), + 'property ' + p + ' not found in scope'); + assertEquals(minimum_content[p], property_mirror.value().value(), + 'property ' + p + ' has unexpected value'); + minimum_count++; + } + + // 'arguments' and might be exposed in the local and closure scope. Just + // ignore this. + var scope_size = scope.scopeObject().properties().length; + if (!scope.scopeObject().property('arguments').isUndefined()) { + scope_size--; + } + // Ditto for 'this'. + if (!scope.scopeObject().property('this').isUndefined()) { + scope_size--; + } + // Temporary variables introduced by the parser have not been materialized. + assertTrue(scope.scopeObject().property('').isUndefined()); + + if (scope_size < minimum_count) { + print('Names found in scope:'); + var names = scope.scopeObject().propertyNames(); + for (var i = 0; i < names.length; i++) { + print(names[i]); + } + } + assertTrue(scope_size >= minimum_count); +} + +// Check that the scopes have positions as expected. +function CheckScopeChainPositions(positions, exec_state) { + var all_scopes = exec_state.frame().allScopes(); + assertEquals(positions.length, all_scopes.length, "FrameMirror.allScopes length"); + for (var i = 0; i < positions.length; i++) { + var scope = exec_state.frame().scope(i); + var position = positions[i]; + if (!position) + continue; + + assertEquals(position.start, scope.details().startPosition()) + assertEquals(position.end, scope.details().endPosition()) + } +} + +// Simple empty local scope. +BeginTest("Local 1"); + +function local_1() { + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); +}; +local_1(); +EndTest(); + + +// Local scope with a parameter. +BeginTest("Local 2"); + +function local_2(a) { + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1}, 0, exec_state); +}; +local_2(1); +EndTest(); + + +// Local scope with a parameter and a local variable. +BeginTest("Local 3"); + +function local_3(a) { + var x = 3; + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,x:3}, 0, exec_state); +}; +local_3(1); +EndTest(); + + +// Local scope with parameters and local variables. +BeginTest("Local 4"); + +function local_4(a, b) { + var x = 3; + var y = 4; + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state); +}; +local_4(1, 2); +EndTest(); + + +// Empty local scope with use of eval. +BeginTest("Local 5"); + +function local_5() { + eval(''); + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); +}; +local_5(); +EndTest(); + + +// Local introducing local variable using eval. +BeginTest("Local 6"); + +function local_6() { + eval('var i = 5'); + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({i:5}, 0, exec_state); +}; +local_6(); +EndTest(); + + +// Local scope with parameters, local variables and local variable introduced +// using eval. +BeginTest("Local 7"); + +function local_7(a, b) { + var x = 3; + var y = 4; + eval('var i = 5'); + eval('var j = 6'); + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state); +}; +local_7(1, 2); +EndTest(); + + +// Single empty with block. +BeginTest("With 1"); + +function with_1() { + with({}) { + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); +}; +with_1(); +EndTest(); + + +// Nested empty with blocks. +BeginTest("With 2"); + +function with_2() { + with({}) { + with({}) { + debugger; + } + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); + CheckScopeContent({}, 1, exec_state); +}; +with_2(); +EndTest(); + + +// With block using an in-place object literal. +BeginTest("With 3"); + +function with_3() { + with({a:1,b:2}) { + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2}, 0, exec_state); +}; +with_3(); +EndTest(); + + +// Nested with blocks using in-place object literals. +BeginTest("With 4"); + +function with_4() { + with({a:1,b:2}) { + with({a:2,b:1}) { + debugger; + } + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:2,b:1}, 0, exec_state); + CheckScopeContent({a:1,b:2}, 1, exec_state); +}; +with_4(); +EndTest(); + + +// Nested with blocks using existing object. +BeginTest("With 5"); + +var with_object = {c:3,d:4}; +function with_5() { + with(with_object) { + with(with_object) { + debugger; + } + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent(with_object, 0, exec_state); + CheckScopeContent(with_object, 1, exec_state); + assertEquals(exec_state.frame().scope(0).scopeObject().value(), + exec_state.frame().scope(1).scopeObject().value()); + assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value()); +}; +with_5(); +EndTest(); + + +// Nested with blocks using existing object in global code. +BeginTest("With 6"); +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent(with_object, 0, exec_state); + CheckScopeContent(with_object, 1, exec_state); + assertEquals(exec_state.frame().scope(0).scopeObject().value(), + exec_state.frame().scope(1).scopeObject().value()); + assertEquals(with_object, exec_state.frame().scope(1).scopeObject().value()); +}; + +var with_object = {c:3,d:4}; +with(with_object) { + with(with_object) { + debugger; + } +} +EndTest(); + + +// With block in function that is marked for optimization while being executed. +BeginTest("With 7"); + +function with_7() { + with({}) { + %OptimizeFunctionOnNextCall(with_7); + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); +}; +with_7(); +EndTest(); + + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. +BeginTest("Closure 1"); + +function closure_1(a) { + function f() { + debugger; + return a; + }; + return f; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1}, 1, exec_state); + CheckScopeChainNames(["f", "closure_1", undefined, undefined], exec_state); +}; +closure_1(1)(); +EndTest(); + + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. Due to VM optimizations parts of the actual closure is +// missing from the debugger information. +BeginTest("Closure 2"); + +function closure_2(a, b) { + var x = a + 2; + var y = b + 2; + function f() { + debugger; + return a + x; + }; + return f; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,x:3}, 1, exec_state); + CheckScopeChainNames(["f", "closure_2", undefined, undefined], exec_state); +}; +closure_2(1, 2)(); +EndTest(); + + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. Using all arguments and locals from the outer function +// in the inner function makes these part of the debugger information on the +// closure. +BeginTest("Closure 3"); + +function closure_3(a, b) { + var x = a + 2; + var y = b + 2; + function f() { + debugger; + return a + b + x + y; + }; + return f; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state); + CheckScopeChainNames(["f", "closure_3", undefined, undefined], exec_state); +}; +closure_3(1, 2)(); +EndTest(); + + + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. Using all arguments and locals from the outer function +// in the inner function makes these part of the debugger information on the +// closure. Use the inner function as well... +BeginTest("Closure 4"); + +function closure_4(a, b) { + var x = a + 2; + var y = b + 2; + function f() { + debugger; + if (f) { + return a + b + x + y; + } + }; + return f; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,f:undefined}, 1, exec_state); + CheckScopeChainNames(["f", "closure_4", undefined, undefined], exec_state); +}; +closure_4(1, 2)(); +EndTest(); + + + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. In the presence of eval all arguments and locals +// (including the inner function itself) from the outer function becomes part of +// the debugger infformation on the closure. +BeginTest("Closure 5"); + +function closure_5(a, b) { + var x = 3; + var y = 4; + function f() { + eval(''); + debugger; + return 1; + }; + return f; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,f:undefined}, 1, exec_state); + CheckScopeChainNames(["f", "closure_5", undefined, undefined], exec_state) +}; +closure_5(1, 2)(); +EndTest(); + + +// Two closures. Due to optimizations only the parts actually used are provided +// through the debugger information. +BeginTest("Closure 6"); +function closure_6(a, b) { + function f(a, b) { + var x = 3; + var y = 4; + return function() { + var x = 3; + var y = 4; + debugger; + some_global = a; + return f; + }; + } + return f(a, b); +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1}, 1, exec_state); + CheckScopeContent({f:undefined}, 2, exec_state); + CheckScopeChainNames([undefined, "f", "closure_6", undefined, undefined], + exec_state); +}; +closure_6(1, 2)(); +EndTest(); + + +// Two closures. In the presence of eval all information is provided as the +// compiler cannot determine which parts are used. +BeginTest("Closure 7"); +function closure_7(a, b) { + var x = 3; + var y = 4; + eval('var i = 5'); + eval('var j = 6'); + function f(a, b) { + var x = 3; + var y = 4; + eval('var i = 5'); + eval('var j = 6'); + return function() { + debugger; + some_global = a; + return f; + }; + } + return f(a, b); +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 1, exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:undefined}, 2, exec_state); + CheckScopeChainNames([undefined, "f", "closure_7", undefined, undefined], + exec_state); +}; +closure_7(1, 2)(); +EndTest(); + + +// Closure that may be optimized out. +BeginTest("Closure 8"); +function closure_8() { + (function inner(x) { + debugger; + })(2); +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x: 2}, 0, exec_state); + CheckScopeChainNames(["inner", undefined, undefined], exec_state); +}; +closure_8(); +EndTest(); + + +BeginTest("Closure 9"); +function closure_9() { + eval("var y = 1;"); + eval("var z = 1;"); + (function inner(x) { + y++; + z++; + debugger; + })(2); +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainNames(["inner", "closure_9", undefined, undefined], + exec_state); +}; +closure_9(); +EndTest(); + + +// Test a mixture of scopes. +BeginTest("The full monty"); +function the_full_monty(a, b) { + var x = 3; + var y = 4; + eval('var i = 5'); + eval('var j = 6'); + function f(a, b) { + var x = 9; + var y = 10; + eval('var i = 11'); + eval('var j = 12'); + with ({j:13}){ + return function() { + var x = 14; + with ({a:15}) { + with ({b:16}) { + debugger; + some_global = a; + return f; + } + } + }; + } + } + return f(a, b); +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.With, + debug.ScopeType.Closure, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({b:16}, 0, exec_state); + CheckScopeContent({a:15}, 1, exec_state); + CheckScopeContent({x:14}, 2, exec_state); + CheckScopeContent({j:13}, 3, exec_state); + CheckScopeContent({a:1,b:2,x:9,y:10,i:11,j:12}, 4, exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:undefined}, 5, exec_state); + CheckScopeChainNames([undefined, undefined, undefined, "f", "f", + "the_full_monty", undefined, undefined], exec_state); +}; +the_full_monty(1, 2)(); +EndTest(); + + +BeginTest("Closure inside With 1"); +function closure_in_with_1() { + with({x:1}) { + (function inner(x) { + debugger; + })(2); + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.With, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x: 2}, 0, exec_state); + CheckScopeContent({x: 1}, 1, exec_state); +}; +closure_in_with_1(); +EndTest(); + + +BeginTest("Closure inside With 2"); +function closure_in_with_2() { + with({x:1}) { + (function inner(x) { + with({x:3}) { + debugger; + } + })(2); + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.With, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x: 3}, 0, exec_state); + CheckScopeContent({x: 2}, 1, exec_state); + CheckScopeContent({x: 1}, 2, exec_state); + CheckScopeChainNames(["inner", "inner", "closure_in_with_2", + undefined, undefined], exec_state); +}; +closure_in_with_2(); +EndTest(); + + +BeginTest("Closure inside With 3"); +function createClosure(a) { + var b = a + 1; + return function closure() { + var c = b; + (function inner(x) { + with({x:c}) { + debugger; + } + })(2); + }; +} + +function closure_in_with_3() { + var f = createClosure(0); + f(); +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainNames(["inner", "inner", "closure", "createClosure", + undefined, undefined], exec_state); +} +closure_in_with_3(); +EndTest(); + + +BeginTest("Closure inside With 4"); +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.With, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x: 2}, 0, exec_state); + CheckScopeContent({x: 1}, 1, exec_state); + CheckScopeChainNames([undefined, undefined, undefined, undefined], + exec_state); +}; + +with({x:1}) { + (function(x) { + debugger; + })(2); +} +EndTest(); + + +// Test global scope. +BeginTest("Global"); +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Script, debug.ScopeType.Global], + exec_state); + CheckScopeChainNames([undefined, undefined], exec_state); +}; +debugger; +EndTest(); + + +BeginTest("Catch block 1"); +function catch_block_1() { + try { + throw 'Exception'; + } catch (e) { + debugger; + } +}; + + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); + CheckScopeChainNames(["catch_block_1", "catch_block_1", + undefined, undefined], exec_state); +}; +catch_block_1(); +EndTest(); + + +BeginTest("Catch block 2"); +function catch_block_2() { + try { + throw 'Exception'; + } catch (e) { + with({n:10}) { + debugger; + } + } +}; + + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({n:10}, 0, exec_state); + CheckScopeContent({e:'Exception'}, 1, exec_state); + CheckScopeChainNames(["catch_block_2", "catch_block_2", "catch_block_2", + undefined, undefined], exec_state); +}; +catch_block_2(); +EndTest(); + + +BeginTest("Catch block 3"); +function catch_block_3() { + // Do eval to dynamically declare a local variable so that the context's + // extension slot is initialized with JSContextExtensionObject. + eval("var y = 78;"); + try { + throw 'Exception'; + } catch (e) { + debugger; + } +}; + + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); + CheckScopeContent({y:78}, 1, exec_state); + CheckScopeChainNames(["catch_block_3", "catch_block_3", + undefined, undefined], exec_state); +}; +catch_block_3(); +EndTest(); + + +BeginTest("Catch block 4"); +function catch_block_4() { + // Do eval to dynamically declare a local variable so that the context's + // extension slot is initialized with JSContextExtensionObject. + eval("var y = 98;"); + try { + throw 'Exception'; + } catch (e) { + with({n:10}) { + debugger; + } + } +}; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({n:10}, 0, exec_state); + CheckScopeContent({e:'Exception'}, 1, exec_state); + CheckScopeContent({y:98}, 2, exec_state); + CheckScopeChainNames(["catch_block_4", "catch_block_4", "catch_block_4", + undefined, undefined], exec_state); +}; +catch_block_4(); +EndTest(); + + +// Test catch in global scope. +BeginTest("Catch block 5"); +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); + CheckScopeChainNames([undefined, undefined, undefined], exec_state); +}; + +try { + throw 'Exception'; +} catch (e) { + debugger; +} + +EndTest(); + + +// Closure inside catch in global code. +BeginTest("Catch block 6"); +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Catch, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x: 2}, 0, exec_state); + CheckScopeContent({e:'Exception'}, 1, exec_state); + CheckScopeChainNames([undefined, undefined, undefined, undefined], + exec_state); +}; + +try { + throw 'Exception'; +} catch (e) { + (function(x) { + debugger; + })(2); +} +EndTest(); + + +// Catch block in function that is marked for optimization while being executed. +BeginTest("Catch block 7"); +function catch_block_7() { + %OptimizeFunctionOnNextCall(catch_block_7); + try { + throw 'Exception'; + } catch (e) { + debugger; + } +}; + + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); + CheckScopeChainNames(["catch_block_7", "catch_block_7", + undefined, undefined], exec_state); +}; +catch_block_7(); +EndTest(); + + +BeginTest("Classes and methods 1"); + +listener_delegate = function(exec_state) { + "use strict" + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 1, exec_state); + CheckScopeChainNames(["m", undefined, undefined], exec_state); +}; + +(function() { + "use strict"; + class C1 { + m() { + debugger; + } + } + new C1().m(); +})(); + +EndTest(); + +BeginTest("Scope positions"); +var code1 = "function f() { \n" + + " var a = 1; \n" + + " function b() { \n" + + " debugger; \n" + + " return a + 1; \n" + + " } \n" + + " b(); \n" + + "} \n" + + "f(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChainPositions( + [{start: 58, end: 118}, {start: 10, end: 162}, {}, {}], exec_state); +} +eval(code1); +EndTest(); + + +function catch_block_2() { + try { + throw 'Exception'; + } catch (e) { + with({n:10}) { + debugger; + } + } +}; + +BeginTest("Scope positions in catch and 'with' statement"); +var code2 = "function catch_block() { \n" + + " try { \n" + + " throw 'Exception'; \n" + + " } catch (e) { \n" + + " with({n : 10}) { \n" + + " debugger; \n" + + " } \n" + + " } \n" + + "} \n" + + "catch_block(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChainPositions([{start: 131, end: 173}, + {start: 94, end: 199}, + {start: 20, end: 225}, + {}, {}], exec_state); +} +eval(code2); +EndTest(); + +BeginTest("Scope positions in for statement"); +var code3 = "function for_statement() { \n" + + " for (let i = 0; i < 1; i++) { \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions( + [{start: 52, end: 111}, {start: 22, end: 145}, {}, {}], exec_state); +} +eval(code3); +EndTest(); + +BeginTest("Scope positions in for statement with lexical block"); +var code4 = "function for_statement() { \n" + + " for (let i = 0; i < 1; i++) { \n" + + " let j; \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions([{start: 66, end: 147}, + {start: 52, end: 147}, + {start: 22, end: 181}, + {}, {}], exec_state); +} +eval(code4); +EndTest(); + +BeginTest("Scope positions in lexical for each statement"); +var code5 = "function for_each_statement() { \n" + + " for (let i of [0]) { \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_each_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions( + [{start: 55, end: 111}, {start: 27, end: 145}, {}, {}], exec_state); +} +eval(code5); +EndTest(); + +BeginTest("Scope positions in lexical for each statement with lexical block"); +var code6 = "function for_each_statement() { \n" + + " for (let i of [0]) { \n" + + " let j; \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_each_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions([{start: 57, end: 147}, + {start: 55, end: 147}, + {start: 27, end: 181}, + {}, {}], exec_state); +} +eval(code6); +EndTest(); + +BeginTest("Scope positions in non-lexical for each statement"); +var code7 = "function for_each_statement() { \n" + + " var i; \n" + + " for (i of [0]) { \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_each_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions([{start: 27, end: 181}, {}, {}], exec_state); +} +eval(code7); +EndTest(); + +BeginTest( + "Scope positions in non-lexical for each statement with lexical block"); +var code8 = "function for_each_statement() { \n" + + " var i; \n" + + " for (i of [0]) { \n" + + " let j; \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_each_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions( + [{start: 89, end: 183}, {start: 27, end: 217}, {}, {}], exec_state); +} +eval(code8); +EndTest(); + +assertEquals(begin_test_count, break_count, + 'one or more tests did not enter the debugger'); +assertEquals(begin_test_count, end_test_count, + 'one or more tests did not have its result checked'); diff --git a/deps/v8/test/debugger/debug/debug-script.js b/deps/v8/test/debugger/debug/debug-script.js new file mode 100644 index 0000000000..dd704c8d4c --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-script.js @@ -0,0 +1,111 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --expose-gc --send-idle-notification +// Flags: --expose-natives-as natives +// Flags: --noharmony-shipping +// Flags: --nostress-opt + +// --nostress-opt is specified because in stress mode the compilation cache +// may hold on to old copies of scripts (see bug 1641). + +// Note: this test checks that that the number of scripts reported as native +// by Debug.scripts() is the same as a number of core native scripts. +// Native scripts that are added by --harmony-shipping are classified +// as 'experimental', but are still returned by Debug.scripts(), so +// we disable harmony-shipping for this test + +Debug = debug.Debug; +Debug.setListener(function(){}); + +Date(); +RegExp(); + +// Count script types. +var named_native_count = 0; +var named_native_names = {}; +var extension_count = 0; +var normal_count = 0; +var inspector_count = 0; +var scripts = Debug.scripts(); +for (i = 0; i < scripts.length; i++) { + if (scripts[i].type == Debug.ScriptType.Native) { + if (scripts[i].name) { + // TODO(1641): Remove check for equally named native scripts once the + // underlying issue is fixed. + if (!named_native_names[scripts[i].name]) { + named_native_names[scripts[i].name] = true; + named_native_count++; + } + } + } else if (scripts[i].type == Debug.ScriptType.Extension) { + extension_count++; + } else if (scripts[i].type == Debug.ScriptType.Normal) { + normal_count++; + } else if (scripts[i].type == Debug.ScriptType.Inspector) { + inspector_count++; + } else { + assertUnreachable('Unexpected type ' + scripts[i].type); + } +} + +// This has to be updated if the number of native scripts change. +assertEquals(%NativeScriptsCount(), named_native_count); +// The 'gc' extension and one or two extras scripts are loaded. +assertTrue(extension_count == 2 || extension_count == 3); +// This script, test-api.js and mjsunit.js has been loaded. If using d8, d8 +// loads a normal script during startup too. +assertTrue(normal_count == 3 || normal_count == 4); +assertTrue(inspector_count == 2); + +// Test a builtins script. +var array_script = Debug.findScript('native array.js'); +assertEquals('native array.js', array_script.name); +assertEquals(Debug.ScriptType.Native, array_script.type); + +// Test a debugger script. +var debug_delay_script = Debug.findScript('native debug.js'); +assertEquals('native debug.js', debug_delay_script.name); +assertEquals(Debug.ScriptType.Native, debug_delay_script.type); + +// Test an extension script. +var extension_gc_script = Debug.findScript('v8/gc'); +if (extension_gc_script) { + assertEquals('v8/gc', extension_gc_script.name); + assertEquals(Debug.ScriptType.Extension, extension_gc_script.type); +} + +// Test a normal script. +var debug_script = Debug.findScript(/debug-script.js/); +assertTrue(/debug-script.js/.test(debug_script.name)); +assertEquals(Debug.ScriptType.Normal, debug_script.type); + +// Check a nonexistent script. +var dummy_script = Debug.findScript('dummy.js'); +assertTrue(typeof dummy_script == 'undefined'); + +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/debug-scripts-throw.js b/deps/v8/test/debugger/debug/debug-scripts-throw.js new file mode 100644 index 0000000000..e703f49054 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-scripts-throw.js @@ -0,0 +1,12 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +Debug = debug.Debug; + +Debug.disable(); +assertThrows("Debug.scripts()"); + +Debug.enable(); +assertDoesNotThrow("Debug.scripts()"); diff --git a/deps/v8/test/debugger/debug/debug-set-variable-value.js b/deps/v8/test/debugger/debug/debug-set-variable-value.js new file mode 100644 index 0000000000..67417895c6 --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-set-variable-value.js @@ -0,0 +1,284 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +var Debug = debug.Debug; + +// Accepts a function/closure 'fun' that must have a debugger statement inside. +// A variable 'variable_name' must be initialized before debugger statement +// and returned after the statement. The test will alter variable value when +// on debugger statement and check that returned value reflects the change. +function RunPauseTest(scope_number, expected_old_result, variable_name, + new_value, expected_new_result, fun) { + var actual_old_result = fun(); + assertEquals(expected_old_result, actual_old_result); + + var listener_delegate; + var listener_called = false; + var exception = null; + + function listener_delegate(exec_state) { + var scope = exec_state.frame(0).scope(scope_number); + scope.setVariableValue(variable_name, new_value); + } + + function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + listener_called = true; + listener_delegate(exec_state); + } + } catch (e) { + exception = e; + } + } + + // Add the debug event listener. + Debug.setListener(listener); + + var actual_new_result; + try { + actual_new_result = fun(); + } finally { + Debug.setListener(null); + } + + if (exception != null) { + assertUnreachable("Exception in listener\n" + exception.stack); + } + assertTrue(listener_called); + + assertEquals(expected_new_result, actual_new_result); +} + + +function ClosureTestCase(scope_index, old_result, variable_name, new_value, + new_result, success_expected, factory) { + this.scope_index_ = scope_index; + this.old_result_ = old_result; + this.variable_name_ = variable_name; + this.new_value_ = new_value; + this.new_result_ = new_result; + this.success_expected_ = success_expected; + this.factory_ = factory; +} + +ClosureTestCase.prototype.run_pause_test = function() { + var th = this; + var fun = this.factory_(true); + this.run_and_catch_(function() { + RunPauseTest(th.scope_index_ + 1, th.old_result_, th.variable_name_, + th.new_value_, th.new_result_, fun); + }); +} + +ClosureTestCase.prototype.run_and_catch_ = function(runnable) { + if (this.success_expected_) { + runnable(); + } else { + assertThrows(runnable); + } +} + + +// Test scopes visible from closures. + +var closure_test_cases = [ + new ClosureTestCase(0, 'cat', 'v1', 5, 5, true, + function Factory(debug_stop) { + var v1 = 'cat'; + return function() { + if (debug_stop) debugger; + return v1; + } + }), + + new ClosureTestCase(0, 4, 't', 7, 9, true, function Factory(debug_stop) { + var t = 2; + var r = eval("t"); + return function() { + if (debug_stop) debugger; + return r + t; + } + }), + + new ClosureTestCase(0, 6, 't', 10, 13, true, function Factory(debug_stop) { + var t = 2; + var r = eval("t = 3"); + return function() { + if (debug_stop) debugger; + return r + t; + } + }), + + new ClosureTestCase(0, 17, 's', 'Bird', 'Bird', true, + function Factory(debug_stop) { + eval("var s = 17"); + return function() { + if (debug_stop) debugger; + return s; + } + }), + + new ClosureTestCase(2, 'capybara', 'foo', 77, 77, true, + function Factory(debug_stop) { + var foo = "capybara"; + return (function() { + var bar = "fish"; + try { + throw {name: "test exception"}; + } catch (e) { + return function() { + if (debug_stop) debugger; + bar = "beast"; + return foo; + } + } + })(); + }), + + new ClosureTestCase(0, 'AlphaBeta', 'eee', 5, '5Beta', true, + function Factory(debug_stop) { + var foo = "Beta"; + return (function() { + var bar = "fish"; + try { + throw "Alpha"; + } catch (eee) { + return function() { + if (debug_stop) debugger; + return eee + foo; + } + } + })(); + }) +]; + +for (var i = 0; i < closure_test_cases.length; i++) { + closure_test_cases[i].run_pause_test(); +} + + +// Test local scope. + +RunPauseTest(0, 'HelloYou', 'u', 'We', 'HelloWe', (function Factory() { + return function() { + var u = "You"; + var v = "Hello"; + debugger; + return v + u; + } +})()); + +RunPauseTest(0, 'Helloworld', 'p', 'GoodBye', 'HelloGoodBye', + (function Factory() { + function H(p) { + var v = "Hello"; + debugger; + return v + p; + } + return function() { + return H("world"); + } +})()); + +RunPauseTest(0, 'mouse', 'v1', 'dog', 'dog', (function Factory() { + return function() { + var v1 = 'cat'; + eval("v1 = 'mouse'"); + debugger; + return v1; + } +})()); + +RunPauseTest(0, 'mouse', 'v1', 'dog', 'dog', (function Factory() { + return function() { + eval("var v1 = 'mouse'"); + debugger; + return v1; + } +})()); + + +// Check that we correctly update local variable that +// is referenced from an inner closure. +RunPauseTest(0, 'Blue', 'v', 'Green', 'Green', (function Factory() { + return function() { + function A() { + var v = "Blue"; + function Inner() { + return void v; + } + debugger; + return v; + } + return A(); + } +})()); + +// Check that we correctly update parameter, that is known to be stored +// both on stack and in heap. +RunPauseTest(0, 5, 'p', 2012, 2012, (function Factory() { + return function() { + function A(p) { + function Inner() { + return void p; + } + debugger; + return p; + } + return A(5); + } +})()); + + +// Test script-scope variable. +let abc = 12; +{ + let exception; + function listener(event, exec_state) { + try { + if (event == Debug.DebugEvent.Break) { + let scope_count = exec_state.frame().scopeCount(); + let script_scope = exec_state.frame().scope(scope_count - 2); + assertEquals(debug.ScopeType.Script, script_scope.scopeType()); + script_scope.setVariableValue('abc', 42); + } + } catch(e) { exception = e } + } + + Debug.setListener(listener); + assertEquals(12, abc); + debugger; + assertEquals(42, abc); + + if (exception != null) { + assertUnreachable("Exception in listener\n" + exception.stack); + } +} + +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/debug-setbreakpoint.js b/deps/v8/test/debugger/debug/debug-setbreakpoint.js new file mode 100644 index 0000000000..bfcab7c6fd --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-setbreakpoint.js @@ -0,0 +1,140 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +// Simple function which stores the last debug event. +var listenerComplete = false; +var exception = false; +var f_script_id = 0; +var g_script_id = 0; +var h_script_id = 0; +var f_line = 0; +var g_line = 0; +var h_line = 0; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + if (listenerComplete) return; + + Debug.setScriptBreakPointById(f_script_id, f_line); + Debug.setScriptBreakPointById(g_script_id, g_line); + Debug.setScriptBreakPointById(h_script_id, h_line); + + // Indicate that all was processed. + listenerComplete = true; + } + } catch (e) { + exception = e + print(e) + }; +}; + +// Add the debug event listener. +Debug.setListener(listener); + +function f() { + a=1; +}; + +function g() { + // Comment. + f(); +}; + +eval('function h(){}'); +eval('function sourceUrlFunc() { a = 2; }\n//# sourceURL=sourceUrlScript'); + +o = {a:function(){},b:function(){}} + +// Check the script ids for the test functions. +f_script_id = Debug.findScript(f).id; +g_script_id = Debug.findScript(g).id; +h_script_id = Debug.findScript(h).id; +sourceURL_script_id = Debug.findScript(sourceUrlFunc).id; + +assertTrue(f_script_id > 0, "invalid script id for f"); +assertTrue(g_script_id > 0, "invalid script id for g"); +assertTrue(h_script_id > 0, "invalid script id for h"); +assertTrue(sourceURL_script_id > 0, "invalid script id for sourceUrlFunc"); +assertEquals(f_script_id, g_script_id); + +// Get the source line for the test functions. +f_line = Debug.findFunctionSourceLocation(f).line; +g_line = Debug.findFunctionSourceLocation(g).line; +h_line = Debug.findFunctionSourceLocation(h).line; +assertTrue(f_line > 0, "invalid line for f"); +assertTrue(g_line > 0, "invalid line for g"); +assertTrue(f_line < g_line); +assertEquals(h_line, 0, "invalid line for h"); + +// Set a break point and call to invoke the debug event listener. +Debug.setBreakPoint(g, 0, 0); +g(); + +// Make sure that the debug event listener was invoked. +assertTrue(listenerComplete, "listener did not run to completion: " + exception); + +// Try setting breakpoint by url specified in sourceURL + +var breakListenerCalled = false; + +function breakListener(event) { + if (event == Debug.DebugEvent.Break) + breakListenerCalled = true; +} + +Debug.setBreakPoint(sourceUrlFunc); + +Debug.setListener(breakListener); + +sourceUrlFunc(); + +assertTrue(breakListenerCalled, "Break listener not called on breakpoint set by sourceURL"); + + +// Breakpoint in a script with no statements test case. If breakpoint is set +// to the script body, its actual position is taken from the nearest statement +// below or like in this case is reset to the very end of the script. +// Unless some precautions made, this position becomes out-of-range and +// we get an exception. + +// Gets a script of 'i1' function and sets the breakpoint at line #4 which +// should be empty. +function SetBreakpointInI1Script() { + var i_script = Debug.findScript(i1); + assertTrue(!!i_script, "invalid script for i1"); + Debug.setScriptBreakPoint(Debug.ScriptBreakPointType.ScriptId, + i_script.id, 4); +} + +// Creates the eval script and tries to set the breakpoint. +// The tricky part is that the script function must be strongly reachable at the +// moment. Since there's no way of simply getting the pointer to the function, +// we run this code while the script function is being activated on stack. +eval('SetBreakpointInI1Script()\nfunction i1(){}\n\n\n\nfunction i2(){}\n'); diff --git a/deps/v8/test/debugger/debug/debug-sourceinfo.js b/deps/v8/test/debugger/debug/debug-sourceinfo.js new file mode 100644 index 0000000000..1085dcaadb --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-sourceinfo.js @@ -0,0 +1,199 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +function a() { b(); }; +function b() { + c(true); +}; + function c(x) { + if (x) { + return 1; + } else { + return 1; + } + }; +function d(x) { + x = 1 ; + x = 2 ; + x = 3 ; + x = 4 ; + x = 5 ; + x = 6 ; + x = 7 ; + x = 8 ; + x = 9 ; + x = 10; + x = 11; + x = 12; + x = 13; + x = 14; + x = 15; +} + +Debug = debug.Debug + +// This is the number of comment lines above the first test function. +var comment_lines = 27; + +// This is the last position in the entire file (note: this equals +// file size of <debug-sourceinfo.js> - 1, since starting at 0). +var last_position = 8022; +// This is the last line of entire file (note: starting at 0). +var last_line = 198; +// This is the last column of last line (note: starting at 0). +var last_column = 71; + +// This magic number is the length or the first line comment (actually number +// of characters before 'function a(...'. +var comment_line_length = 1599; +var start_a = 9 + comment_line_length; +var start_b = 35 + comment_line_length; +var start_c = 66 + comment_line_length; +var start_d = 151 + comment_line_length; + +// The position of the first line of d(), i.e. "x = 1 ;". +var start_code_d = start_d + 6; +// The line # of the first line of d() (note: starting at 0). +var start_line_d = 39; +var line_length_d = 10; +var num_lines_d = 15; + +assertEquals(start_a, Debug.sourcePosition(a)); +assertEquals(start_b, Debug.sourcePosition(b)); +assertEquals(start_c, Debug.sourcePosition(c)); +assertEquals(start_d, Debug.sourcePosition(d)); + +var script = Debug.findScript(a); +assertTrue(script.data === Debug.findScript(b).data); +assertTrue(script.data === Debug.findScript(c).data); +assertTrue(script.data === Debug.findScript(d).data); +assertTrue(script.source === Debug.findScript(b).source); +assertTrue(script.source === Debug.findScript(c).source); +assertTrue(script.source === Debug.findScript(d).source); + +// Test that when running through source positions the position, line and +// column progresses as expected. +var position; +var line; +var column; +for (var p = 0; p < 100; p++) { + var location = script.locationFromPosition(p); + if (p > 0) { + assertEquals(position + 1, location.position); + if (line == location.line) { + assertEquals(column + 1, location.column); + } else { + assertEquals(line + 1, location.line); + assertEquals(0, location.column); + } + } else { + assertEquals(0, location.position); + assertEquals(0, location.line); + assertEquals(0, location.column); + } + + // Remember the location. + position = location.position; + line = location.line; + column = location.column; +} + +// Every line of d() is the same length. Verify we can loop through all +// positions and find the right line # for each. +var p = start_code_d; +for (line = 0; line < num_lines_d; line++) { + for (column = 0; column < line_length_d; column++) { + var location = script.locationFromPosition(p); + assertEquals(p, location.position); + assertEquals(start_line_d + line, location.line); + assertEquals(column, location.column); + p++; + } +} + +// Test first position. +assertEquals(0, script.locationFromPosition(0).position); +assertEquals(0, script.locationFromPosition(0).line); +assertEquals(0, script.locationFromPosition(0).column); + +// Test second position. +assertEquals(1, script.locationFromPosition(1).position); +assertEquals(0, script.locationFromPosition(1).line); +assertEquals(1, script.locationFromPosition(1).column); + +// Test first position in function a(). +assertEquals(start_a, script.locationFromPosition(start_a).position); +assertEquals(0, script.locationFromPosition(start_a).line - comment_lines); +assertEquals(10, script.locationFromPosition(start_a).column); + +// Test first position in function b(). +assertEquals(start_b, script.locationFromPosition(start_b).position); +assertEquals(1, script.locationFromPosition(start_b).line - comment_lines); +assertEquals(13, script.locationFromPosition(start_b).column); + +// Test first position in function c(). +assertEquals(start_c, script.locationFromPosition(start_c).position); +assertEquals(4, script.locationFromPosition(start_c).line - comment_lines); +assertEquals(12, script.locationFromPosition(start_c).column); + +// Test first position in function d(). +assertEquals(start_d, script.locationFromPosition(start_d).position); +assertEquals(11, script.locationFromPosition(start_d).line - comment_lines); +assertEquals(10, script.locationFromPosition(start_d).column); + +// Test the Debug.findSourcePosition which wraps SourceManager. +assertEquals(0 + start_a, Debug.findFunctionSourceLocation(a, 0, 0).position); +assertEquals(0 + start_b, Debug.findFunctionSourceLocation(b, 0, 0).position); +assertEquals(5 + start_b, Debug.findFunctionSourceLocation(b, 1, 0).position); +assertEquals(7 + start_b, Debug.findFunctionSourceLocation(b, 1, 2).position); +assertEquals(16 + start_b, Debug.findFunctionSourceLocation(b, 2, 0).position); +assertEquals(0 + start_c, Debug.findFunctionSourceLocation(c, 0, 0).position); +assertEquals(6 + start_c, Debug.findFunctionSourceLocation(c, 1, 0).position); +assertEquals(19 + start_c, Debug.findFunctionSourceLocation(c, 2, 0).position); +assertEquals(35 + start_c, Debug.findFunctionSourceLocation(c, 3, 0).position); +assertEquals(48 + start_c, Debug.findFunctionSourceLocation(c, 4, 0).position); +assertEquals(64 + start_c, Debug.findFunctionSourceLocation(c, 5, 0).position); +assertEquals(70 + start_c, Debug.findFunctionSourceLocation(c, 6, 0).position); +assertEquals(0 + start_d, Debug.findFunctionSourceLocation(d, 0, 0).position); +assertEquals(6 + start_d, Debug.findFunctionSourceLocation(d, 1, 0).position); +for (i = 1; i <= num_lines_d; i++) { + assertEquals(6 + (i * line_length_d) + start_d, + Debug.findFunctionSourceLocation(d, (i + 1), 0).position); +} +assertEquals(158 + start_d, Debug.findFunctionSourceLocation(d, 17, 0).position); + +// Make sure invalid inputs work properly. +assertEquals(0, script.locationFromPosition(-1).line); +assertEquals(null, script.locationFromPosition(last_position + 2)); + +// Test last position. +assertEquals(last_position, script.locationFromPosition(last_position).position); +assertEquals(last_line, script.locationFromPosition(last_position).line); +assertEquals(last_column, script.locationFromPosition(last_position).column); +assertEquals(last_line + 1, + script.locationFromPosition(last_position + 1).line); +assertEquals(0, script.locationFromPosition(last_position + 1).column); diff --git a/deps/v8/test/debugger/debug/debug-step.js b/deps/v8/test/debugger/debug/debug-step.js index 3560efd1df..369e8a645c 100644 --- a/deps/v8/test/debugger/debug/debug-step.js +++ b/deps/v8/test/debugger/debug/debug-step.js @@ -2,20 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -Debug = new DebugWrapper(); -Debug.enable(); +Debug = debug.Debug -// Simple debug event handler which performs 100 steps and then retrieves -// the resulting value of "i" in f(). +// Simple debug event handler which first time hit will perform 1000 steps and +// second time hit will evaluate and store the value of "i". If requires that +// the global property "state" is initially zero. + +var bp1, bp2; function listener(event, exec_state, event_data, data) { if (event == Debug.DebugEvent.Break) { if (step_count > 0) { - Debug.stepInto(); + exec_state.prepareStep(Debug.StepAction.StepIn); step_count--; } else { - const frameid = exec_state.frames[0].callFrameId; - result = Debug.evaluate(frameid, "i").value; + result = exec_state.frame().evaluate("i").value(); + // Clear the break point on line 2 if set. + if (bp2) { + Debug.clearBreakPoint(bp2); + } } } }; @@ -25,19 +30,18 @@ Debug.setListener(listener); // Test debug event for break point. function f() { - var i; // Line 1. - for (i = 0; i < 100; i++) { // Line 2. - x = 1; // Line 3. + var i; // Line 1. + for (i = 0; i < 1000; i++) { // Line 2. + x = 1; // Line 3. } }; // Set a breakpoint on the for statement (line 1). -Debug.setBreakPoint(f, 1); - -// Check that performing 100 steps will make i 33. -let step_count = 100; -let result = -1; +bp1 = Debug.setBreakPoint(f, 1); +// Check that performing 1000 steps will make i 333. +var step_count = 1000; +result = -1; f(); - -assertEquals(33, result); +assertEquals(333, result); +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/debug-stepframe-clearing.js b/deps/v8/test/debugger/debug/debug-stepframe-clearing.js new file mode 100644 index 0000000000..8718636d9c --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-stepframe-clearing.js @@ -0,0 +1,96 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// This test ensures that IC learning doesn't interfere with stepping into +// property accessor. f1()'s ICs are allowed to learn to a monomorphic state, +// and the breakpoints flooding get() are allowed to expire, then we ensure +// that we can step into get() again later (when k == 1). +function f1() { + for (var k = 0; k < 2; k++) { // Break 1 + var v10 = 0; // Line 2 + for (var i = 0; i < 10; i++) { // Line 3 + var v12 = o.slappy; // Line 4 + var v13 = 3 // Line 5 + } // Line 6 + print("break here"); // Break 3 + } // Line 8 + print("exiting f1"); // Line 9 (dummy break) +} + +function get() { + var g0 = 0; // Break 2 + var g1 = 1; + return 3; +} + + +var o = {}; +Object.defineProperty(o, "slappy", { get : get }); + +Debug = debug.Debug; +var break_count = 0 +var exception = null; +var bp_f1_line7; +var bp_f1_line9; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var line = exec_state.frame(0).sourceLineText(); + print(line); + var match = line.match(/\/\/ Break (\d+)$/); + assertEquals(2, match.length); + var match_value = parseInt(match[1]); + + if (break_count >= 0 && break_count < 2) { + // 0, 1: Keep stepping through frames. + assertEquals(break_count, match_value); + exec_state.prepareStep(Debug.StepAction.StepFrame); + } else if (break_count === 2) { + // 2: let the code run to a breakpoint we set. The load should + // go monomorphic. + assertEquals(break_count, match_value); + } else if (break_count === 3) { + // 3: back to frame stepping. Does the monomorphic slappy accessor + // call still have the ability to break like before? + assertEquals(break_count, match_value); + Debug.clearBreakPoint(bp_f1_line7); + exec_state.prepareStep(Debug.StepAction.StepFrame); + } else { + assertEquals(4, break_count); + assertEquals(2, match_value); + // Apparently we can still stop in the accessor even though we cleared + // breakpoints earlier and there was a monomorphic step. + // Allow running to completion now. + Debug.clearBreakPoint(bp_f1_line9); + } + + break_count++; + } catch (e) { + print(e + e.stack); + exception = e; + } +} + +for (var j = 1; j < 3; j++) { + break_count = 0; + Debug.setListener(listener); + + // Breakpoints are added here rather than in the listener because their + // addition causes a full (clearing) gc that clears type feedback when we + // want to let it build up. Also, bp_f1_line9 is set simply because if we + // handled then deleted bp_f1_line7, then the debugger clears DebugInfo from + // f1 while we are still using it, again, resetting type feedback which is + // undesirable. + bp_f1_line7 = Debug.setBreakPoint(f1, 7); + bp_f1_line9 = Debug.setBreakPoint(f1, 9); + + debugger; // Break 0 + f1(); + Debug.setListener(null); + assertTrue(break_count === 5); +} + +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/debug-stepframe.js b/deps/v8/test/debugger/debug/debug-stepframe.js new file mode 100644 index 0000000000..cb1675994a --- /dev/null +++ b/deps/v8/test/debugger/debug/debug-stepframe.js @@ -0,0 +1,109 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +function f0() { + var v00 = 0; // Break 1 + var v01 = 1; + // Normal function call in a catch scope. + try { + throw 1; + } catch (e) { + try { + f1(); + } catch (e) { + var v02 = 2; // Break 13 + } + } + var v03 = 3; + var v04 = 4; + eval('var v05 = 5; // Break 14'); + var v06 = 6; // Break 15 +} + +function f1() { + var v10 = 0; // Break 2 + var v11 = 1; + // Getter call. + var v12 = o.get; + var v13 = 3 // Break 4 + // Setter call. + o.set = 2; + var v14 = 4; // Break 6 + // Function.prototype.call. + f2.call(); + var v15 = 5; // Break 12 + var v16 = 6; + // Exit function by throw. + throw 1; + var v17 = 7; +} + +function get() { + var g0 = 0; // Break 3 + var g1 = 1; + return 3; +} + +function set() { + var s0 = 0; // Break 5 + return 3; +} + +function f2() { + var v20 = 0; // Break 7 + // Construct call. + var v21 = new c0(); + var v22 = 2; // Break 9 + // Bound function. + b0(); + return 2; // Break 11 +} + +function c0() { + this.v0 = 0; // Break 8 + this.v1 = 1; +} + +function f3() { + var v30 = 0; // Break 10 + var v31 = 1; + return 3; +} + +var b0 = f3.bind(o); + +var o = {}; +Object.defineProperty(o, "get", { get : get }); +Object.defineProperty(o, "set", { set : set }); + +Debug = debug.Debug; +var break_count = 0 +var exception = null; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var line = exec_state.frame(0).sourceLineText(); + print(line); + var match = line.match(/\/\/ Break (\d+)$/); + assertEquals(2, match.length); + assertEquals(break_count, parseInt(match[1])); + break_count ++; + exec_state.prepareStep(Debug.StepAction.StepFrame); + } catch (e) { + print(e + e.stack); + exception = e; + } +} + + +break_count = 0; +Debug.setListener(listener); +debugger; // Break 0 +f0(); +Debug.setListener(null); // Break 16 +assertTrue(break_count > 14); + +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/es6/debug-blockscopes.js b/deps/v8/test/debugger/debug/es6/debug-blockscopes.js new file mode 100644 index 0000000000..001c098c69 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-blockscopes.js @@ -0,0 +1,487 @@ +// Copyright 2011 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --noanalyze-environment-liveness +// The functions used for testing backtraces. They are at the top to make the +// testing of source line/column easier. + +"use strict"; + +var Debug = debug.Debug; + +var test_name; +var listener_delegate; +var listener_called; +var exception; +var begin_test_count = 0; +var end_test_count = 0; +var break_count = 0; +var global_marker = 7; + + +// Debug event listener which delegates. +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + break_count++; + listener_called = true; + listener_delegate(exec_state); + } + } catch (e) { + print(e, e.stack); + exception = e; + } +} + +// Add the debug event listener. +Debug.setListener(listener); + + +// Initialize for a new test. +function BeginTest(name) { + test_name = name; + listener_delegate = null; + listener_called = false; + exception = null; + begin_test_count++; +} + + +// Check result of a test. +function EndTest() { + assertTrue(listener_called, "listener not called for " + test_name); + assertNull(exception, test_name, exception); + end_test_count++; +} + +var global_object = this; + +// Check that the scope chain contains the expected types of scopes. +function CheckScopeChain(scopes, exec_state) { + assertEquals(scopes.length, exec_state.frame().scopeCount()); + for (var i = 0; i < scopes.length; i++) { + var scope = exec_state.frame().scope(i); + assertEquals(scopes[i], scope.scopeType()); + + // Check the global object when hitting the global scope. + if (scopes[i] == debug.ScopeType.Global) { + // Objects don't have same class (one is "global", other is "Object", + // so just check the properties directly. + assertEquals(global_object.global_marker, + scope.scopeObject().value().global_marker); + } + } +} + +// Check that the content of the scope is as expected. For functions just check +// that there is a function. +function CheckScopeContent(content, number, exec_state) { + var scope = exec_state.frame().scope(number); + var count = 0; + for (var p in content) { + var property_mirror = scope.scopeObject().property(p); + if (property_mirror.isUndefined()) { + print('property ' + p + ' not found in scope'); + } + assertFalse(property_mirror.isUndefined(), + 'property ' + p + ' not found in scope'); + assertEquals(content[p], property_mirror.value().value(), + 'property ' + p + ' has unexpected value'); + count++; + } + + // 'arguments' and might be exposed in the local and closure scope. Just + // ignore this. + var scope_size = scope.scopeObject().properties().length; + if (!scope.scopeObject().property('arguments').isUndefined()) { + scope_size--; + } + // Temporary variables introduced by the parser have not been materialized. + assertTrue(scope.scopeObject().property('').isUndefined()); + + if (count != scope_size) { + print('Names found in scope:'); + var names = scope.scopeObject().propertyNames(); + for (var i = 0; i < names.length; i++) { + print(names[i]); + } + } + assertEquals(count, scope_size); +} + + +function assertEqualsUnlessOptimized(expected, value, f) { + try { + assertEquals(expected, value); + } catch (e) { + assertOptimized(f); + } +} + +// Simple empty block scope in local scope. +BeginTest("Local block 1"); + +function local_block_1() { + { + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); +}; +local_block_1(); +EndTest(); + + +// Simple empty block scope in local scope with a parameter. +BeginTest("Local 2"); + +function local_2(a) { + { + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1}, 0, exec_state); +}; +local_2(1); +EndTest(); + + +// Local scope with a parameter and a local variable. +BeginTest("Local 3"); + +function local_3(a) { + let x = 3; + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,x:3}, 0, exec_state); +}; +local_3(1); +EndTest(); + + +// Local scope with parameters and local variables. +BeginTest("Local 4"); + +function local_4(a, b) { + let x = 3; + let y = 4; + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state); +}; +local_4(1, 2); +EndTest(); + + +// Single variable in a block scope. +BeginTest("Local 5"); + +function local_5(a) { + { + let x = 5; + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x:5}, 0, exec_state); + CheckScopeContent({a:1}, 1, exec_state); +}; +local_5(1); +EndTest(); + + +// Two variables in a block scope. +BeginTest("Local 6"); + +function local_6(a) { + { + let x = 6; + let y = 7; + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x:6,y:7}, 0, exec_state); + CheckScopeContent({a:1}, 1, exec_state); +}; +local_6(1); +EndTest(); + + +// Two variables in a block scope. +BeginTest("Local 7"); + +function local_7(a) { + { + { + let x = 8; + debugger; + } + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x:8}, 0, exec_state); + CheckScopeContent({a:1}, 1, exec_state); +}; +local_7(1); +EndTest(); + + +// Simple closure formed by returning an inner function referering to an outer +// block local variable and an outer function's parameter. +BeginTest("Closure 1"); + +function closure_1(a) { + var x = 2; + let y = 3; + if (true) { + let z = 4; + function f() { + debugger; + return a + x + y + z; + }; + return f; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Block, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); + CheckScopeContent({a:1,x:2,y:3}, 2, exec_state); +}; +closure_1(1)(); +EndTest(); + + +// Simple for-in loop over the keys of an object. +BeginTest("For loop 1"); + +function for_loop_1() { + for (let x in {y:undefined}) { + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x:'y'}, 0, exec_state); + // The function scope contains a temporary iteration variable, but it is + // hidden to the debugger. +}; +for_loop_1(); +EndTest(); + + +// For-in loop over the keys of an object with a block scoped let variable +// shadowing the iteration variable. +BeginTest("For loop 2"); + +function for_loop_2() { + for (let x in {y:undefined}) { + let x = 3; + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x:3}, 0, exec_state); + CheckScopeContent({x:'y'}, 1, exec_state); + // The function scope contains a temporary iteration variable, hidden to the + // debugger. +}; +for_loop_2(); +EndTest(); + + +// Simple for loop. +BeginTest("For loop 3"); + +function for_loop_3() { + for (let x = 3; x < 4; ++x) { + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x:3}, 0, exec_state); + CheckScopeContent({}, 1, exec_state); +}; +for_loop_3(); +EndTest(); + + +// For loop with a block scoped let variable shadowing the iteration variable. +BeginTest("For loop 4"); + +function for_loop_4() { + for (let x = 3; x < 4; ++x) { + let x = 5; + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x:5}, 0, exec_state); + CheckScopeContent({x:3}, 1, exec_state); + CheckScopeContent({}, 2, exec_state); +}; +for_loop_4(); +EndTest(); + + +// For loop with two variable declarations. +BeginTest("For loop 5"); + +function for_loop_5() { + for (let x = 3, y = 5; x < 4; ++x) { + debugger; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x:3,y:5}, 0, exec_state); + CheckScopeContent({}, 1, exec_state); +}; +for_loop_5(); +EndTest(); + + +// Uninitialized variables +BeginTest("Uninitialized 1"); + +function uninitialized_1() { + { + debugger; + let x = 1; + } +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x:undefined}, 0, exec_state); +}; +uninitialized_1(); +EndTest(); + + +// Block scopes shadowing +BeginTest("Block scopes shadowing 1"); +function shadowing_1() { + let i = 0; + { + let i = 5; + debugger; + } + assertEquals(0, i); +} + +listener_delegate = function (exec_state) { + assertEqualsUnlessOptimized(5, exec_state.frame(0).evaluate("i").value()); +} +shadowing_1(); +EndTest(); + + +// Block scopes shadowing +BeginTest("Block scopes shadowing 2"); +function shadowing_2() { + let i = 0; + { + let j = 5; + debugger; + } +} + +listener_delegate = function (exec_state) { + assertEqualsUnlessOptimized(0, exec_state.frame(0).evaluate("i").value()); + assertEqualsUnlessOptimized(5, exec_state.frame(0).evaluate("j").value()); +} +shadowing_2(); +EndTest(); diff --git a/deps/v8/test/debugger/debug/es6/debug-evaluate-arrow-function-receiver.js b/deps/v8/test/debugger/debug/es6/debug-evaluate-arrow-function-receiver.js new file mode 100644 index 0000000000..6410e8decd --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-evaluate-arrow-function-receiver.js @@ -0,0 +1,115 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test that debug-evaluate can find the correct this value for an arrow +// function, if "this" is referenced within the arrow function scope. + +Debug = debug.Debug + +var break_count = 0; +var exception = null; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + for (var i = 0; i < exec_state.frameCount() - 1; i++) { + var frame = exec_state.frame(i); + var this_value = frame.evaluate("'' + this").value(); + var expected = frame.sourceLineText().match(/\/\/ (.*$)/)[1]; + print(expected, this_value, frame.sourceLineText()); + assertEquals(String(expected), String(this_value)); + } + break_count++; + } catch (e) { + exception = e; + print(e + e.stack); + } +} + +// Context-allocated receiver. +function f() { + debugger; // foo + return () => { + debugger; // foo + with ({}) { + return () => { + debugger; // foo + try { + throw new Error(); + } catch (e) { + return () => { + (() => this); // bind this. + debugger; // foo + return () => { + debugger; // undefined + return g.call("goo"); // undefined + } + }; + } + }; + } + }; +} + +// Stack-allocated receiver. +function g() { + debugger; // goo + return () => { + debugger; // undefined + with ({}) { + return () => { + debugger; // undefined + try { + throw new Error(); + } catch (e) { + return () => { + debugger; // undefined + return f.call("foo"); // undefined + }; + } + }; + } + }; +} + +Debug.setListener(listener); + +var h = f.call("foo"); +for (var i = 0; i < 20; i++) h = h(); +var h = g.call("goo"); +for (var i = 0; i < 20; i++) h = h(); + +function x() { + (() => this); // bind this. + function y() { + (() => { + (() => this); // bind this. + debugger; // Y + })(); // Y + } + y.call("Y"); // X +} +x.call("X"); + +function u() { + (() => this); + function v() { + (() => { + debugger; // undefined + })(); // V + } + v.call("V"); // U +} +u.call("U"); + +(() => { + (() => this); + debugger; // [object global] +})(); + +Debug.setListener(null); + +assertEquals(55, break_count); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/es6/debug-evaluate-blockscopes.js b/deps/v8/test/debugger/debug/es6/debug-evaluate-blockscopes.js new file mode 100644 index 0000000000..6ed3ca66e1 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-evaluate-blockscopes.js @@ -0,0 +1,111 @@ +// Copyright 2011 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Test debug evaluation for functions without local context, but with +// nested catch contexts. + +"use strict"; + +var x; +var result; + +function f() { + { // Line 1. + let i = 1; // Line 2. + try { // Line 3. + throw 'stuff'; // Line 4. + } catch (e) { // Line 5. + x = 2; // Line 6. + } + } +}; + +var Debug = debug.Debug + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + result = exec_state.frame().evaluate("i").value(); + } +}; + +// Add the debug event listener. +Debug.setListener(listener); + +//Set breakpoint on line 6. +var bp = Debug.setBreakPoint(f, 6); + +result = -1; +f(); +assertEquals(1, result); + +// Clear breakpoint. +Debug.clearBreakPoint(bp); +// Get rid of the debug event listener. +Debug.setListener(null); + + +function f1() { + { + let i = 1; + debugger; + assertEquals(2, i); + } +} + +function f2() { + { + let i = 1; + debugger; + assertEquals(2, i); + return function() { return i++; } + } +} + +var exception; +Debug.setListener(function (event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + var frame = exec_state.frame(); + assertEquals(1, frame.evaluate("i").value()); + var allScopes = frame.allScopes(); + assertEquals(1, allScopes[0].scopeObject().value().i); + allScopes[0].setVariableValue("i", 2); + } + } catch (e) { + exception = e; + } +}); + +exception = null; +f1(); +assertEquals(null, exception, exception); +exception = null; +f2(); +assertEquals(null, exception, exception); + +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/es6/debug-evaluate-receiver-before-super.js b/deps/v8/test/debugger/debug/es6/debug-evaluate-receiver-before-super.js new file mode 100644 index 0000000000..8fa8645baf --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-evaluate-receiver-before-super.js @@ -0,0 +1,38 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test that debug-evaluate doesn't crash when this is used before super() call +// in constructor. + +Debug = debug.Debug + +var result; + +function listener(event, exec_state, event_data, data) +{ + try { + if (event == Debug.DebugEvent.Break) { + result = exec_state.frame(0).evaluate("this.a").value(); + } + } catch (e) { + result = e.message; + } +} + +Debug.setListener(listener); + +class A { constructor () { this.a = 239; } } +class B extends A { + constructor () { + debugger; + assertTrue(result.indexOf("Cannot read property 'a' of undefined") >= 0); + super(); + debugger; + assertEquals(239, result); + } +} +new B(); + +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/es6/debug-exception-generators.js b/deps/v8/test/debugger/debug/es6/debug-exception-generators.js new file mode 100644 index 0000000000..192d64b599 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-exception-generators.js @@ -0,0 +1,48 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +Debug = debug.Debug + +var exception = null; +var log = []; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Exception) return; + try { + var line = exec_state.frame(0).sourceLineText(); + var match = /Exception (\w)/.exec(line); + assertNotNull(match); + assertEquals(match[1], event_data.exception()); + log.push(match[1]); + } catch (e) { + exception = e; + } +} + + +function* g() { + try { + throw "a"; // Ordinary throw. Exception a + } catch (e) {} + try { + yield 1; // Caught internally. Exception b + } catch (e) {} + yield 2; + yield 3; // Caught externally. Exception c + yield 4; +} + +Debug.setListener(listener); +Debug.setBreakOnException(); +var g_obj = g(); +assertEquals(1, g_obj.next().value); +assertEquals(2, g_obj.throw("b").value); +assertEquals(3, g_obj.next().value); +assertThrows(() => g_obj.throw("c")); +assertThrows(() => g_obj.throw("d")); // Closed generator. Exception d +Debug.setListener(null); +Debug.clearBreakOnException(); +assertEquals(["a", "b", "c", "d"], log); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/es6/debug-function-scopes.js b/deps/v8/test/debugger/debug/es6/debug-function-scopes.js new file mode 100644 index 0000000000..b64c4dfadf --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-function-scopes.js @@ -0,0 +1,136 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +"use strict"; +let top_level_let = 255; + +var Debug = debug.Debug; + +const ScopeType = debug.ScopeType; + +let exception = null; +let listenerDelegate = null; + +const expected_break_count = 5; +let break_count = 0; + +Debug.setListener(function(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + break_count++; + listenerDelegate(exec_state); + } catch (e) { + exception = e; + print(e, e.stack); + } +}); + +function CheckScope(scope_frame, scope_expectations, expected_scope_type) { + assertEquals(expected_scope_type, scope_frame.scopeType()); + + var scope_object = scope_frame.scopeObject().value(); + + for (let name in scope_expectations) { + let actual = scope_object[name]; + let expected = scope_expectations[name]; + assertEquals(expected, actual); + } +} + +// --- + +listenerDelegate = function(exec_state) { + const frame = exec_state.frame(0); + + assertEquals(6, frame.scopeCount()); + + CheckScope(frame.scope(0), {}, ScopeType.Local); + CheckScope(frame.scope(1), { a: 4, b: 5 }, ScopeType.Closure); + CheckScope(frame.scope(2), { z: 22, w: 5, v: "Capybara" }, ScopeType.Closure); + CheckScope(frame.scope(3), { x: 5 }, ScopeType.Closure); + CheckScope(frame.scope(4), { top_level_let: 255 }, ScopeType.Script); + CheckScope(frame.scope(5), {}, ScopeType.Global); +}; + +(function F1(x) { + function F2(y) { + var z = x + y; + { + var w = 5; + var v = "Capybara"; + var F3 = function(a, b) { + function F4(p) { + debugger; + return p + a + b + z + w + v.length; + } + return F4; + } + return F3(4, 5); + } + } + return F2(17); +})(5)(); + +// --- + +listenerDelegate = function(exec_state) { + const frame = exec_state.frame(0); + + assertEquals(6, frame.scopeCount()); + + CheckScope(frame.scope(0), {}, ScopeType.Local); + CheckScope(frame.scope(1), { l3: 9 }, ScopeType.Block); + CheckScope(frame.scope(2), { l2: 7 }, ScopeType.Block); + CheckScope(frame.scope(3), { v1:3, l0: 0, v3: 5, v6: 11 }, ScopeType.Closure); + CheckScope(frame.scope(4), { top_level_let: 255 }, ScopeType.Script); + CheckScope(frame.scope(5), {}, ScopeType.Global); +}; + +(function() { + var v1 = 3; + var v2 = 4; + let l0 = 0; + { + var v3 = 5; + let l1 = 6; + let l2 = 7; + { + var v4 = 8; + let l3 = 9; + { + var v5 = "Cat"; + let l4 = 11; + var v6 = l4; + return function() { + debugger; + return l0 + v1 + v3 + l2 + l3 + v6; + }; + } + } + } +})()(); diff --git a/deps/v8/test/debugger/debug/es6/debug-liveedit-new-target-1.js b/deps/v8/test/debugger/debug/es6/debug-liveedit-new-target-1.js new file mode 100644 index 0000000000..4beebec909 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-liveedit-new-target-1.js @@ -0,0 +1,74 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test that live-editing a frame that uses new.target fails. + +Debug = debug.Debug +var calls = 0; +var exceptions = 0; +var results = []; +var replace_again; + +eval(` + function LogNewTarget() { + calls++; + ReplaceOnce(); + results.push(true); + results.push(new.target); + } +`); + +function Dummy() {} + +function Replace(fun, original, patch) { + %ExecuteInDebugContext(function() { + var change_log = []; + try { + var script = Debug.findScript(fun); + var patch_pos = script.source.indexOf(original); + Debug.LiveEdit.TestApi.ApplySingleChunkPatch( + script, patch_pos, original.length, patch, change_log); + } catch (e) { + assertEquals("BLOCKED_NO_NEW_TARGET_ON_RESTART", + change_log[0].functions_on_stack[0].replace_problem); + assertInstanceof(e, Debug.LiveEdit.Failure); + exceptions++; + } + }); +} + +function ReplaceOnce() { + if (replace_again) { + replace_again = false; + Replace(LogNewTarget, "true", "false"); + } +} + +function Revert() { + Replace(LogNewTarget, "false", "true"); +} + +replace_again = true; +ReplaceOnce(); +new LogNewTarget(); +Revert(); +assertEquals(1, calls); +assertEquals(0, exceptions); +assertEquals([false, LogNewTarget], results); + +replace_again = true; +LogNewTarget(); + +replace_again = true; +new LogNewTarget(); + +replace_again = true; +Reflect.construct(LogNewTarget, [], Dummy); + +assertEquals( + [false, LogNewTarget, true, undefined, true, LogNewTarget, true, Dummy], + results); +assertEquals(4, calls); // No restarts +assertEquals(3, exceptions); // Replace failed. diff --git a/deps/v8/test/debugger/debug/es6/debug-liveedit-new-target-2.js b/deps/v8/test/debugger/debug/es6/debug-liveedit-new-target-2.js new file mode 100644 index 0000000000..e87e8b574e --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-liveedit-new-target-2.js @@ -0,0 +1,62 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test that live-editing a frame to introduce new.target fails. + +Debug = debug.Debug +var calls = 0; +var exceptions = 0; +var results = []; +var replace_again; + +eval(` + function LogNewTarget() { + calls++; + ReplaceOnce(); + results.push(true); + } +`); + +function Replace(fun, original, patch) { + %ExecuteInDebugContext(function() { + var change_log = []; + try { + var script = Debug.findScript(fun); + var patch_pos = script.source.indexOf(original); + Debug.LiveEdit.TestApi.ApplySingleChunkPatch( + script, patch_pos, original.length, patch, change_log); + } catch (e) { + assertEquals("BLOCKED_NO_NEW_TARGET_ON_RESTART", + change_log[0].functions_on_stack[0].replace_problem); + assertInstanceof(e, Debug.LiveEdit.Failure); + exceptions++; + } + }); +} + +function ReplaceOnce(x) { + if (replace_again) { + replace_again = false; + Replace(LogNewTarget, "true", "new.target"); + } +} + +function Revert() { + Replace(LogNewTarget, "new.target", "true"); +} + +replace_again = true; +ReplaceOnce(); +new LogNewTarget(); +Revert(); +assertEquals(1, calls); +assertEquals(0, exceptions); +assertEquals([LogNewTarget], results); + +replace_again = true; +new LogNewTarget(); +assertEquals(2, calls); // No restarts +assertEquals(1, exceptions); // Replace failed. +assertEquals([LogNewTarget, true], results); diff --git a/deps/v8/test/debugger/debug/es6/debug-liveedit-new-target-3.js b/deps/v8/test/debugger/debug/es6/debug-liveedit-new-target-3.js new file mode 100644 index 0000000000..866323de1a --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-liveedit-new-target-3.js @@ -0,0 +1,72 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test that live-editing a frame above one that uses new.target succeeds. + +Debug = debug.Debug +var wrapper_calls = 0; +var construct_calls = 0; +var exceptions = 0; +var results = []; +var replace_again; + +eval(` + function LogNewTarget(arg) { + construct_calls++; + results.push(new.target); + } + function Wrapper() { + wrapper_calls++; + ReplaceOnce(); + new LogNewTarget(true); + } +`); + +function Replace(fun, original, patch) { + %ExecuteInDebugContext(function() { + var change_log = []; + try { + var script = Debug.findScript(fun); + var patch_pos = script.source.indexOf(original); + Debug.LiveEdit.TestApi.ApplySingleChunkPatch( + script, patch_pos, original.length, patch, change_log); + } catch (e) { + exceptions++; + } + }); +} + +function ReplaceOnce(x) { + if (replace_again) { + replace_again = false; + Replace(Wrapper, "true", "false"); + } +} + +function Revert() { + Replace(Wrapper, "false", "true"); +} + +replace_again = true; +ReplaceOnce(); +Wrapper(); +Revert(); +assertEquals(1, construct_calls); +assertEquals(1, wrapper_calls); +assertEquals(0, exceptions); // Replace succeeds +assertEquals([LogNewTarget], results); + +Wrapper(); +assertEquals(2, construct_calls); +assertEquals(2, wrapper_calls); +assertEquals(0, exceptions); // Replace succeeds +assertEquals([LogNewTarget, LogNewTarget], results); + +replace_again = true; +Wrapper(); +assertEquals(3, construct_calls); +assertEquals(4, wrapper_calls); // Restarts +assertEquals(0, exceptions); // Replace succeeds +assertEquals([LogNewTarget, LogNewTarget, LogNewTarget], results); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/async-task-event.js b/deps/v8/test/debugger/debug/es6/debug-promises/async-task-event.js deleted file mode 100644 index fcf80825aa..0000000000 --- a/deps/v8/test/debugger/debug/es6/debug-promises/async-task-event.js +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - - -Debug = debug.Debug; - -var base_id = -1; -var exception = null; -var expected = [ - "enqueue #1", - "willHandle #1", - "then #1", - "enqueue #2", - "didHandle #1", - "willHandle #2", - "then #2", - "didHandle #2", - "enqueue #3", - "willHandle #3", - "didHandle #3" -]; - -function assertLog(msg) { - print(msg); - assertTrue(expected.length > 0); - assertEquals(expected.shift(), msg); - if (!expected.length) { - Debug.setListener(null); - } -} - -function listener(event, exec_state, event_data, data) { - if (event != Debug.DebugEvent.AsyncTaskEvent) return; - try { - if (base_id < 0) - base_id = event_data.id(); - var id = event_data.id() - base_id + 1; - assertEquals("Promise.resolve", event_data.name()); - assertLog(event_data.type() + " #" + id); - } catch (e) { - print(e + e.stack) - exception = e; - } -} - -Debug.setListener(listener); - -var resolver; -var p = new Promise(function(resolve, reject) { - resolver = resolve; -}); -p.then(function() { - assertLog("then #1"); -}).then(function() { - assertLog("then #2"); -}); -resolver(); - -%RunMicrotasks(); - -assertNull(exception); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/promise-all-uncaught.js b/deps/v8/test/debugger/debug/es6/debug-promises/promise-all-uncaught.js new file mode 100644 index 0000000000..55185e33e6 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/promise-all-uncaught.js @@ -0,0 +1,67 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we only listen to uncaught exceptions and a +// Promise p3 created by Promise.all has no catch handler, and is rejected +// because one of the Promises p2 passed to Promise.all is rejected. +// We expect one event for p2; the system recognizes the rejection of p3 +// to be redundant and based on the rejection of p2 and does not trigger +// an additional rejection. + +var Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Exception) return; + try { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("uncaught", event_data.exception().message); + // Assert that the debug event is triggered at the throw site. + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + assertTrue(event_data.uncaught()); + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +var p1 = Promise.resolve(); +p1.name = "p1"; + +var p2 = p1.then(function() { + log.push("throw"); + throw new Error("uncaught"); // event +}); + +p2.name = "p2"; + +var p3 = Promise.all([p2]); +p3.name = "p3"; + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["end main", "throw"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/promise-race-uncaught.js b/deps/v8/test/debugger/debug/es6/debug-promises/promise-race-uncaught.js new file mode 100644 index 0000000000..bd4463415d --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/promise-race-uncaught.js @@ -0,0 +1,67 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we only listen to uncaught exceptions and a +// Promise p3 created by Promise.race has no catch handler, and is rejected +// because one of the Promises p2 passed to Promise.race is rejected. +// We expect one event for p2; the system recognizes the rejection of p3 +// to be redundant and based on the rejection of p2 and does not trigger +// an additional rejection. + +var Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Exception) return; + try { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("uncaught", event_data.exception().message); + // Assert that the debug event is triggered at the throw site. + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + assertTrue(event_data.uncaught()); + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +var p1 = Promise.resolve(); +p1.name = "p1"; + +var p2 = p1.then(function() { + log.push("throw"); + throw new Error("uncaught"); // event +}); + +p2.name = "p2"; + +var p3 = Promise.race([p2]); +p3.name = "p3"; + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["end main", "throw"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/reject-caught-all.js b/deps/v8/test/debugger/debug/es6/debug-promises/reject-caught-all.js new file mode 100644 index 0000000000..9424ca7604 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/reject-caught-all.js @@ -0,0 +1,67 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we listen to all exceptions and +// there is a catch handler for the to-be-rejected Promise. +// We expect a normal Exception debug event to be triggered. + +Debug = debug.Debug; + +var log = []; +var expected_events = 1; + +var p = new Promise(function(resolve, reject) { + log.push("resolve"); + resolve(); +}); + +var q = p.then( + function(value) { + log.push("reject"); + return Promise.reject(new Error("reject")); + }); + +q.catch( + function(e) { + assertEquals("reject", e.message); + }); + + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("reject", event_data.exception().message); + assertFalse(event_data.uncaught()); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve", "end main", "reject"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/reject-caught-by-default-reject-handler.js b/deps/v8/test/debugger/debug/es6/debug-promises/reject-caught-by-default-reject-handler.js new file mode 100644 index 0000000000..bb22afcf8f --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/reject-caught-by-default-reject-handler.js @@ -0,0 +1,74 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we only listen to uncaught exceptions and +// there is only a default reject handler for the to-be-rejected Promise. +// We expect only one debug event: when the first Promise is rejected +// and only has default reject handlers. No event is triggered when +// simply forwarding the rejection with .then's default handler. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var resolve, reject; +var p0 = new Promise(function(res, rej) { resolve = res; reject = rej; }); +var p1 = p0.then(function() { + log.push("p0.then"); + return Promise.reject(new Error("123")); +}); +var p2 = p1.then(function() { + log.push("p1.then"); +}); + +var q = new Promise(function(res, rej) { + log.push("resolve q"); + res(); +}); + +q.then(function() { + log.push("resolve p"); + resolve(); +}) + + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertTrue(event_data.uncaught()); + // p1 is rejected, uncaught, with the error from the Promise.reject line + assertNotNull(event_data.sourceLineText().match("Promise.reject")); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve q", "end main", "resolve p", "p0.then"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/reject-in-constructor.js b/deps/v8/test/debugger/debug/es6/debug-promises/reject-in-constructor.js new file mode 100644 index 0000000000..5d7e83065e --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/reject-in-constructor.js @@ -0,0 +1,37 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we only listen to uncaught exceptions and +// the Promise is rejected in the Promise constructor. +// We expect an Exception debug event with a promise to be triggered. + +Debug = debug.Debug; + +var steps = 0; +var exception = null; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + steps++; + assertEquals("uncaught", event_data.exception().message); + assertTrue(event_data.uncaught()); + // Assert that the debug event is triggered at the throw site. + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + } + } catch (e) { + exception = e; + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +var p = new Promise(function(resolve, reject) { + reject(new Error("uncaught")); // event +}); + +assertEquals(1, steps); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-all.js b/deps/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-all.js new file mode 100644 index 0000000000..1d8154581f --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-all.js @@ -0,0 +1,63 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we listen to all exceptions and +// there is a catch handler for the to-be-rejected Promise. +// We expect an Exception debug event with a promise to be triggered. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var p = new Promise(function(resolve, reject) { + log.push("resolve"); + resolve(); +}); + +var q = p.then( + function() { + log.push("reject"); + return Promise.reject(new Error("uncaught reject")); + }); + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("uncaught reject", event_data.exception().message); + assertTrue(event_data.uncaught()); + // The frame comes from the Promise.reject call + assertNotNull(/Promise\.reject/.exec(event_data.sourceLineText())); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve", "end main", "reject"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-late.js b/deps/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-late.js new file mode 100644 index 0000000000..454899d575 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-late.js @@ -0,0 +1,70 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we only listen to uncaught exceptions and +// there is a catch handler for the to-be-rejected Promise. +// We expect an Exception debug event with a promise to be triggered. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var reject_closure; + +var p = new Promise(function(resolve, reject) { + log.push("postpone p"); + reject_closure = reject; +}); + +var q = new Promise(function(resolve, reject) { + log.push("resolve q"); + resolve(); +}); + +q.then(function() { + log.push("reject p"); + reject_closure(new Error("uncaught reject p")); // event +}) + + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("uncaught reject p", event_data.exception().message); + assertTrue(event_data.uncaught()); + // Assert that the debug event is triggered at the throw site. + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["postpone p", "resolve q", "end main", "reject p"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-uncaught.js b/deps/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-uncaught.js new file mode 100644 index 0000000000..1afe4b79b3 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/reject-uncaught-uncaught.js @@ -0,0 +1,63 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we only listen to uncaught exceptions and +// there is no catch handler for the to-be-rejected Promise. +// We expect an Exception debug event with a promise to be triggered. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var p = new Promise(function(resolve, reject) { + log.push("resolve"); + resolve(); +}); + +var q = p.then( + function() { + log.push("reject"); + return Promise.reject(Error("uncaught reject")); // event + }); + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("uncaught reject", event_data.exception().message); + assertTrue(event_data.uncaught()); + // The JavaScript frame is from the Promise rejection + assertTrue(/Promise\.reject/.test(event_data.sourceLineText())); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve", "end main", "reject"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/reject-with-invalid-reject.js b/deps/v8/test/debugger/debug/es6/debug-promises/reject-with-invalid-reject.js new file mode 100644 index 0000000000..78331b94a5 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/reject-with-invalid-reject.js @@ -0,0 +1,73 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when a Promise is rejected, which is caught by a custom +// promise, which has a number for reject closure. We expect an Exception debug +// events trying to call the invalid reject closure. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var p = new Promise(function(resolve, reject) { + log.push("resolve"); + resolve(); +}); + +function MyPromise(resolver) { + var reject = 1; + var resolve = function() { }; + log.push("construct"); + resolver(resolve, reject); +}; + +MyPromise.prototype = new Promise(function() {}); +p.constructor = MyPromise; + +var q = p.then( + function() { + log.push("reject caught"); + return Promise.reject(new Error("caught")); + }); + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("number is not a function", event_data.exception().message); + // All of the frames on the stack are from native Javascript. + assertEquals(0, exec_state.frameCount()); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve", "construct", "end main", "reject caught"], + log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); + +log.push("end main"); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/reject-with-throw-in-reject.js b/deps/v8/test/debugger/debug/es6/debug-promises/reject-with-throw-in-reject.js new file mode 100644 index 0000000000..218119078f --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/reject-with-throw-in-reject.js @@ -0,0 +1,83 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when a Promise is rejected, which is caught by a +// custom promise, which throws a new exception in its reject handler. +// We expect two Exception debug events: +// 1) when promise q is rejected. +// 2) when the custom reject closure in MyPromise throws an exception. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var p = new Promise(function(resolve, reject) { + log.push("resolve"); + resolve(); +}); + +function MyPromise(resolver) { + var reject = function() { + log.push("throw in reject"); + throw new Error("reject"); // event + }; + var resolve = function() { }; + log.push("construct"); + resolver(resolve, reject); +}; + +MyPromise.prototype = new Promise(function() {}); +p.constructor = MyPromise; + +var q = p.then( + function() { + log.push("reject caught"); + return Promise.reject(new Error("caught")); + }); + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("reject", event_data.exception().message); + // Assert that the debug event is triggered at the throw site. + assertTrue( + exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + } + } catch (e) { + // Signal a failure with exit code 1. This is necessary since the + // debugger swallows exceptions and we expect the chained function + // and this listener to be executed after the main script is finished. + print("Unexpected exception: " + e + "\n" + e.stack); + quit(1); + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve", "construct", "end main", + "reject caught", "throw in reject"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/reject-with-undefined-reject.js b/deps/v8/test/debugger/debug/es6/debug-promises/reject-with-undefined-reject.js new file mode 100644 index 0000000000..53d6db6cfa --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/reject-with-undefined-reject.js @@ -0,0 +1,73 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when a Promise is rejected, which is caught by a custom +// promise, which has undefined for reject closure. We expect an Exception +// debug even calling the (undefined) custom rejected closure. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var p = new Promise(function(resolve, reject) { + log.push("resolve"); + resolve(); +}); + +function MyPromise(resolver) { + var reject = undefined; + var resolve = function() { }; + log.push("construct"); + resolver(resolve, reject); +}; + +MyPromise.prototype = new Promise(function() {}); +p.constructor = MyPromise; + +var q = p.then( + function() { + log.push("reject caught"); + return Promise.reject(new Error("caught")); + }); + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("caught", event_data.exception().message); + // All of the frames on the stack are from native Javascript. + assertEquals(0, exec_state.frameCount()); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve", "construct", "end main", "reject caught"], + log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); + +log.push("end main"); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/throw-caught-all.js b/deps/v8/test/debugger/debug/es6/debug-promises/throw-caught-all.js new file mode 100644 index 0000000000..9b6e4fc3ad --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/throw-caught-all.js @@ -0,0 +1,66 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we listen to all exceptions and +// there is a catch handler for the exception thrown in a Promise. +// We expect a normal Exception debug event to be triggered. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var p = new Promise(function(resolve, reject) { + log.push("resolve"); + resolve(); +}); + +var q = p.then( + function() { + log.push("throw"); + throw new Error("caught"); + }); + +q.catch( + function(e) { + assertEquals("caught", e.message); + }); + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("caught", event_data.exception().message); + assertFalse(event_data.uncaught()); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve", "end main", "throw"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/throw-caught-by-default-reject-handler.js b/deps/v8/test/debugger/debug/es6/debug-promises/throw-caught-by-default-reject-handler.js new file mode 100644 index 0000000000..8d6319a05a --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/throw-caught-by-default-reject-handler.js @@ -0,0 +1,75 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we only listen to uncaught exceptions and +// there is only a default reject handler for the to-be-rejected Promise. +// We expect only one debug event: when the first Promise is rejected +// and only has default reject handlers. No event is triggered when +// simply forwarding the rejection with .then's default handler. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var resolve, reject; +var p0 = new Promise(function(res, rej) { resolve = res; reject = rej; }); +var p1 = p0.then(function() { + log.push("p0.then"); + throw new Error("123"); // event +}); +var p2 = p1.then(function() { + log.push("p1.then"); +}); + +var q = new Promise(function(res, rej) { + log.push("resolve q"); + res(); +}); + +q.then(function() { + log.push("resolve p"); + resolve(); +}) + + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertTrue(event_data.uncaught()); + // p1 is rejected, uncaught except for its default reject handler. + assertTrue( + exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve q", "end main", "resolve p", "p0.then"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/throw-finally-caught-all.js b/deps/v8/test/debugger/debug/es6/debug-promises/throw-finally-caught-all.js new file mode 100644 index 0000000000..bb63367dde --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/throw-finally-caught-all.js @@ -0,0 +1,70 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we listen to all exceptions and +// there is a catch handler for the exception thrown in a Promise, first +// caught by a try-finally, and immediately rethrown. +// We expect a normal Exception debug event to be triggered. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var p = new Promise(function(resolve, reject) { + log.push("resolve"); + resolve(); +}); + +var q = p.then( + function() { + log.push("throw"); + try { + throw new Error("caught"); + } finally { + } + }); + +q.catch( + function(e) { + assertEquals("caught", e.message); + }); + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("caught", event_data.exception().message); + assertFalse(event_data.uncaught()); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve", "end main", "throw"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/throw-in-constructor.js b/deps/v8/test/debugger/debug/es6/debug-promises/throw-in-constructor.js new file mode 100644 index 0000000000..a1febf448b --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/throw-in-constructor.js @@ -0,0 +1,38 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we only listen to uncaught exceptions and +// an exception is thrown in the Promise constructor. +// We expect an Exception debug event with a promise to be triggered. + +Debug = debug.Debug; + +var step = 0; +var exception = null; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + assertEquals(0, step); + assertEquals("uncaught", event_data.exception().message); + assertTrue(event_data.uncaught()); + // Assert that the debug event is triggered at the throw site. + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + step++; + } + } catch (e) { + exception = e; + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +var p = new Promise(function(resolve, reject) { + throw new Error("uncaught"); // event +}); + +assertEquals(1, step); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-all.js b/deps/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-all.js new file mode 100644 index 0000000000..8b6f34307c --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-all.js @@ -0,0 +1,64 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we listen to all exceptions and +// there is no catch handler for the exception thrown in a Promise. +// We expect an Exception debug event with a promise to be triggered. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var p = new Promise(function(resolve, reject) { + log.push("resolve"); + resolve(); +}); + +var q = p.then( + function() { + log.push("throw"); + throw new Error("uncaught"); // event + }); + +function listener(event, exec_state, event_data, data) { + try { + // Ignore exceptions during startup in stress runs. + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("uncaught", event_data.exception().message); + assertTrue(event_data.uncaught()); + // Assert that the debug event is triggered at the throw site. + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve", "end main", "throw"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-uncaught.js b/deps/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-uncaught.js new file mode 100644 index 0000000000..abdc267ac5 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/throw-uncaught-uncaught.js @@ -0,0 +1,63 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we only listen to uncaught exceptions and +// there is a catch handler for the exception thrown in a Promise. +// We expect an Exception debug event with a promise to be triggered. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var p = new Promise(function(resolve, reject) { + log.push("resolve"); + resolve(); +}); + +var q = p.then( + function() { + log.push("throw"); + throw new Error("uncaught"); // event + }); + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + assertEquals("uncaught", event_data.exception().message); + assertTrue(event_data.uncaught()); + // Assert that the debug event is triggered at the throw site. + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve", "end main", "throw"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/throw-with-throw-in-reject.js b/deps/v8/test/debugger/debug/es6/debug-promises/throw-with-throw-in-reject.js new file mode 100644 index 0000000000..b17054b06d --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/throw-with-throw-in-reject.js @@ -0,0 +1,84 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when an exception is thrown inside a Promise, which is +// caught by a custom promise, which throws a new exception in its reject +// handler. We expect two Exception debug events: +// 1) when the exception is thrown in the promise q. +// 2) when the custom reject closure in MyPromise throws an exception. + +Debug = debug.Debug; + +var expected_events = 1; +var log = []; + +var p = new Promise(function(resolve, reject) { + log.push("resolve"); + resolve(); +}); + +function MyPromise(resolver) { + var reject = function() { + log.push("throw in reject"); + throw new Error("reject"); // event + }; + var resolve = function() { }; + log.push("construct"); + resolver(resolve, reject); +}; + +MyPromise.prototype = new Promise(function() {}); +MyPromise.__proto__ = Promise; +p.constructor = MyPromise; + +var q = p.then( + function() { + log.push("throw caught"); + throw new Error("caught"); // event + }); + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + expected_events--; + assertTrue(expected_events >= 0); + if (expected_events == 0) { + assertEquals(["resolve", "construct", "end main", + "throw caught"], log); + assertEquals("caught", event_data.exception().message); + } else { + assertUnreachable(); + } + assertTrue(exec_state.frame(0).sourceLineText().indexOf('// event') > 0); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +log.push("end main"); + +function testDone(iteration) { + function checkResult() { + try { + assertTrue(iteration < 10); + if (expected_events === 0) { + assertEquals(["resolve", "construct", "end main", + "throw caught", "throw in reject"], log); + } else { + testDone(iteration + 1); + } + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } + } + + %EnqueueMicrotask(checkResult); +} + +testDone(0); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/try-reject-in-constructor.js b/deps/v8/test/debugger/debug/es6/debug-promises/try-reject-in-constructor.js new file mode 100644 index 0000000000..e11dc34424 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/try-reject-in-constructor.js @@ -0,0 +1,40 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we only listen to uncaught exceptions and +// the Promise is rejected within a try-catch in the Promise constructor. +// We expect an Exception debug event with a promise to be triggered. + +Debug = debug.Debug; + +var step = 0; +var exception = null; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + assertEquals(0, step); + assertEquals("uncaught", event_data.exception().message); + assertTrue(event_data.uncaught()); + // Assert that the debug event is triggered at the throw site. + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + step++; + } + } catch (e) { + exception = e; + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +var p = new Promise(function(resolve, reject) { + try { // This try-catch must not prevent this uncaught reject event. + reject(new Error("uncaught")); // event + } catch (e) { } +}); + +assertEquals(1, step); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/es6/debug-promises/try-throw-reject-in-constructor.js b/deps/v8/test/debugger/debug/es6/debug-promises/try-throw-reject-in-constructor.js new file mode 100644 index 0000000000..484ce146be --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-promises/try-throw-reject-in-constructor.js @@ -0,0 +1,42 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test debug events when we only listen to uncaught exceptions and +// an exception is thrown in the Promise constructor, but caught in an +// inner try-catch. The Promise is rejected afterwards. +// We expect an Exception debug event with a promise to be triggered. + +Debug = debug.Debug; + +var step = 0; +var exception = null; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + assertEquals(0, step); + assertEquals("uncaught", event_data.exception().message); + assertTrue(event_data.uncaught()); + // Assert that the debug event is triggered at the throw site. + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// event") > 0); + step++; + } + } catch (e) { + exception = e; + } +} + +Debug.setBreakOnUncaughtException(); +Debug.setListener(listener); + +var p = new Promise(function(resolve, reject) { + try { // This try-catch must not prevent this uncaught reject event. + throw new Error("caught"); + } catch (e) { } + reject(new Error("uncaught")); // event +}); + +assertEquals(1, step); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/es6/debug-scope-default-param-with-eval.js b/deps/v8/test/debugger/debug/es6/debug-scope-default-param-with-eval.js new file mode 100644 index 0000000000..b60ecebe6e --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-scope-default-param-with-eval.js @@ -0,0 +1,60 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test that the parameter initialization block scope set up for +// sloppy eval is visible to the debugger. + +var Debug = debug.Debug; +var exception = null; +var break_count = 0; + +function call_for_break() { + return 5; +} + +function test(x = eval("var y = 7; debugger; y") + call_for_break()) { + return x; +} + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var frame = exec_state.frame(0); + var block_scope; + if (break_count++ == 0) { + // Inside eval. + assertEquals([ debug.ScopeType.Eval, + debug.ScopeType.Block, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global ], + frame.allScopes().map(s => s.scopeType())); + exec_state.prepareStep(Debug.StepAction.StepOut); + block_scope = frame.scope(1); + } else { + // Outside of eval. + assertEquals([ debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global ], + frame.allScopes().map(s => s.scopeType())); + block_scope = frame.scope(0); + } + assertTrue(block_scope.scopeObject().propertyNames().includes('y')); + assertEquals(7, block_scope.scopeObject().property('y').value().value()); + } catch (e) { + print(e); + exception = e; + } +} + +Debug.setListener(listener); + +assertEquals(12, test()); + +Debug.setListener(null); + +assertNull(exception); +assertEquals(2, break_count); diff --git a/deps/v8/test/debugger/debug/es6/debug-stepin-default-parameters.js b/deps/v8/test/debugger/debug/es6/debug-stepin-default-parameters.js new file mode 100644 index 0000000000..b0683a3e31 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-stepin-default-parameters.js @@ -0,0 +1,45 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +Debug = debug.Debug + +var exception = null; +var log = []; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + print(event_data.sourceLineText()); + var entry = ""; + for (var i = 0; i < exec_state.frameCount(); i++) { + entry += exec_state.frame(i).sourceLineText().substr(-1); + entry += exec_state.frame(i).sourceColumn(); + } + log.push(entry); + exec_state.prepareStep(Debug.StepAction.StepIn); + } catch (e) { + exception = e; + } +}; + +function default_arg(x) { + return "default"; // d +} // e + +function f(arg0 = default_arg()) { // f + return arg0; // g +} // h + + +Debug.setListener(listener); +debugger; // a +var result = f(); // b +Debug.setListener(null); // c + +assertNull(exception); +assertEquals("default", result); + +assertEquals(["a0","b13","f18b13","d2f18b13","e0f18b13","g2b13","h0b13","c0"], + log); diff --git a/deps/v8/test/debugger/debug/es6/debug-stepin-generators.js b/deps/v8/test/debugger/debug/es6/debug-stepin-generators.js index 5468ea0491..f92c756c21 100644 --- a/deps/v8/test/debugger/debug/es6/debug-stepin-generators.js +++ b/deps/v8/test/debugger/debug/es6/debug-stepin-generators.js @@ -14,7 +14,11 @@ function listener(event, exec_state, event_data, data) { print(source); if (/stop stepping/.test(source)) return; if (/yield/.test(source)) yields++; - exec_state.prepareStep(Debug.StepAction.StepIn); + if (yields == 4) { + exec_state.prepareStep(Debug.StepAction.StepOut); + } else { + exec_state.prepareStep(Debug.StepAction.StepIn); + } } catch (e) { print(e, e.stack); exception = e; diff --git a/deps/v8/test/debugger/debug/es6/debug-stepin-microtasks.js b/deps/v8/test/debugger/debug/es6/debug-stepin-microtasks.js new file mode 100644 index 0000000000..dd3f7a1c9e --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-stepin-microtasks.js @@ -0,0 +1,76 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +Debug = debug.Debug +var exception = null; +var break_count = 0; +const expected_breaks = 9; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace"); + var source = exec_state.frame(0).sourceLineText(); + print("paused at: " + source); + assertTrue(source.indexOf("// Break " + break_count + ".") > 0, + "Unexpected pause at: " + source + "\n" + + "Expected: // Break " + break_count + "."); + if (source.indexOf("StepOver.") !== -1) { + exec_state.prepareStep(Debug.StepAction.StepNext); + } else if (source.indexOf("StepOut.") !== -1) { + exec_state.prepareStep(Debug.StepAction.StepOut); + } else { + exec_state.prepareStep(Debug.StepAction.StepIn); + } + ++break_count; + } + } catch (e) { + exception = e; + print(e, e.stack); + } +}; + +Debug.setListener(listener); + +Promise.resolve(42) + .then(promise1) + .then(Object) // Should skip stepping into native. + .then(Boolean) // Should skip stepping into native. + .then(promise2) + .catch(promise3) + .then(promise4) + .catch(function(e) { + %AbortJS("FAIL: uncaught exception " + e); + }); + +function promise1() { + debugger; // Break 0. + return exception || 1; // Break 1. +} // Break 2. StepOver. + +function promise2() { + throw new Error; // Break 3. +} + +function promise3() { + return break_count; // Break 4. +} // Break 5. + +function promise4() { + finalize(); // Break 6. StepOver. + return 0; // Break 7. +} // Break 8. StepOut. + +function finalize() { + Promise.resolve().then(function() { + if (expected_breaks !== break_count) { + %AbortJS("FAIL: expected <" + expected_breaks + "> breaks instead of <" + + break_count + ">"); + } + if (exception !== null) { + %AbortJS("FAIL: exception: " + exception); + } + }); +} diff --git a/deps/v8/test/debugger/debug/es6/debug-stepin-proxies.js b/deps/v8/test/debugger/debug/es6/debug-stepin-proxies.js new file mode 100644 index 0000000000..c830e775b2 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-stepin-proxies.js @@ -0,0 +1,60 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +Debug = debug.Debug + +var exception = null; +var log = []; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + print(event_data.sourceLineText()); + var entry = ""; + for (var i = 0; i < exec_state.frameCount(); i++) { + entry += exec_state.frame(i).sourceLineText().substr(-1); + entry += exec_state.frame(i).sourceColumn(); + } + log.push(entry); + exec_state.prepareStep(Debug.StepAction.StepIn); + } catch (e) { + exception = e; + } +}; + +var target = {}; +var handler = { + has: function(target, name) { + return true; // h + }, // i + get: function(target, name) { + return 42; // j + }, // k + set: function(target, name, value) { + return false; // l + }, // m +} + +var proxy = new Proxy(target, handler); + +Debug.setListener(listener); +debugger; // a +var has = "step" in proxy; // b +var get = proxy.step; // c +proxy.step = 43; // d + +Debug.setListener(null); // g + +assertNull(exception); +assertTrue(has); +assertEquals(42, get); + +assertEquals([ + "a0", + "b17", "h4b17", "i2b17", // [[Has]] + "c15", "j4c15", "k2c15", // [[Get]] + "d0", "l4d11", "m2d11", // [[Set]] + "g0" +], log); diff --git a/deps/v8/test/debugger/debug/es6/debug-stepin-string-template.js b/deps/v8/test/debugger/debug/es6/debug-stepin-string-template.js new file mode 100644 index 0000000000..d1a2ce7659 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-stepin-string-template.js @@ -0,0 +1,60 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +Debug = debug.Debug + +var exception = null; +var log = []; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + print(event_data.sourceLineText()); + var entry = ""; + for (var i = 0; i < exec_state.frameCount(); i++) { + entry += exec_state.frame(i).sourceLineText().substr(-1); + entry += exec_state.frame(i).sourceColumn(); + } + log.push(entry); + exec_state.prepareStep(Debug.StepAction.StepIn); + } catch (e) { + exception = e; + } +}; + +function u(x) { + return x.toUpperCase(); // d +} // e + +var n = 3; + +var o = { + toString: function() { + return "D"; // f + } // g +} + + + +Debug.setListener(listener); +debugger; // a +var s = `1 ${u("a")} 2 ${u("b")} 3 ${n} 4 ${o}`; // b +Debug.setListener(null); // c + +assertNull(exception); + +assertEquals([ + "a0", + "b44", + "b13", + "d2b13", + "e0b13", + "b25", + "d2b25", + "e0b25", + "f4b44", + "g2b44", + "c0" +], log); diff --git a/deps/v8/test/debugger/debug/es6/debug-stepnext-for.js b/deps/v8/test/debugger/debug/es6/debug-stepnext-for.js new file mode 100644 index 0000000000..29712d82bb --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-stepnext-for.js @@ -0,0 +1,135 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --harmony + +Debug = debug.Debug; +var break_count = 0 +var exception = null; +var log = [] + +var s = 0; +var a = [1, 2, 3]; +var b = [1, 2, 3, 4]; +var null_value = null; +var i = 0; + +function f() { + "use strict"; + debugger; // Break a + var j; // Break b + + for (var i in null_value) { // Break c + s += a[i]; + } + + for (j in null_value) { // Break d + s += a[j]; + } + + for (var i in a) { // Break e + s += a[i]; // Break E + } + + for (j in a) { // Break f + s += a[j]; // Break F + } + + for (let i in a) { // Break g + s += a[i]; // Break G + } + + for (var i of a) { // Break h + s += i; // Break H + } + + for (j of a) { // Break i + s += j; // Break I + } + + for (let i of a) { // Break j + s += i; // Break J + } + + for (var i = 0; i < 3; i++) { // Break k + s += a[i]; // Break K + } + + for (j = 0; j < 3; j++) { // Break l + s += a[j]; // Break L + } + + for (let i = 0; i < 3; i++) { // Break m + s += a[i]; // Break M + } + + for (let i of a) {} // Break n + + [1, ...a] // Break o + +} // Break y + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var line = exec_state.frame(0).sourceLineText(); + var col = exec_state.frame(0).sourceColumn(); + print(line); + var match = line.match(/\/\/ Break (\w)$/); + assertEquals(2, match.length); + log.push(match[1] + col); + exec_state.prepareStep(Debug.StepAction.StepNext); + break_count++; + } catch (e) { + exception = e; + } +} + +Debug.setListener(listener); +f(); +Debug.setListener(null); // Break z + +print("log:\n"+ JSON.stringify(log)); +// The let declaration differs from var in that the loop variable +// is declared in every iteration. +// TODO(verwaest): For-of has hacky position numbers for Symbol.iterator and +// .next. Restore to proper positions once the CallPrinter can disambiguate +// based on other values. +var expected = [ + // Entry + "a2", + // Empty for-in-var: get enumerable + "c16", + // Empty for-in: get enumerable + "d12", + // For-in-var: get enumerable, assign, body, assign, body, ... + "e16","e11","E4","e11","E4","e11","E4","e11", + // For-in: get enumerable, assign, body, assign, body, ... + "f12","f7","F4","f7","F4","f7","F4","f7", + // For-in-let: get enumerable, next, body, next, ... + "g16","g11","G4","g11","G4","g11","G4","g11", + // For-of-var: [Symbol.iterator](), next(), body, next(), body, ... + "h16","h13","H4","h13","H4","h13","H4","h13", + // For-of: [Symbol.iterator](), next(), body, next(), body, ... + "i12","i9","I4","i9","I4","i9","I4","i9", + // For-of-let: [Symbol.iterator](), next(), body, next(), ... + "j18","j14","J4","j14","J4","j14","J4","j14", + // For-var: init, condition, body, next, condition, body, ... + "k15","k20","K4","k26","k20","K4","k26","k20","K4","k26","k20", + // For: init, condition, body, next, condition, body, ... + "l7","l16","L4","l22","l16","L4","l22","l16","L4","l22","l16", + // For-let: init, condition, body, next, condition, body, ... + "m15","m20","M4","m26","m20","M4","m26","m20","M4","m26","m20", + // For-of, empty: [Symbol.iterator](), next() once + "n16", "n13", + // Spread: expression statement, spread + "o2", "o9", + // Exit. + "y0","z0", +] +print("expected:\n"+ JSON.stringify(expected)); + +assertArrayEquals(expected, log); +assertEquals(54, s); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/es6/debug-stepnext-generators.js b/deps/v8/test/debugger/debug/es6/debug-stepnext-generators.js new file mode 100644 index 0000000000..966030076e --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/debug-stepnext-generators.js @@ -0,0 +1,48 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +Debug = debug.Debug +var exception = null; +var breaks = 0; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var source = exec_state.frame(0).sourceLineText(); + assertTrue(RegExp(`B${breaks++}`).test(source)); + if (/stop/.test(source)) return; + if (/step out/.test(source)) { + exec_state.prepareStep(Debug.StepAction.StepOut); + } else if (/step in/.test(source)) { + exec_state.prepareStep(Debug.StepAction.StepIn); + } else { + exec_state.prepareStep(Debug.StepAction.StepNext); + } + } catch (e) { + print(e, e.stack); + exception = e; + } +} + +Debug.setListener(listener); + +function * g() { + debugger; // B0 + yield 1; // B1 + yield 2; // B2 step out + yield 3; // B5 + yield 4; // B6 step out + return 2 * (yield 5); +} + +var i = g(); +assertEquals(1, i.next().value); +assertEquals(2, i.next().value); // B3 +assertEquals(3, i.next().value); // B4 step in +assertEquals(4, i.next().value); // B7 +assertEquals(5, i.next().value); // B8 +assertEquals(6, i.next(3).value); // B9 stop + +assertNull(exception); +assertEquals(10, breaks); diff --git a/deps/v8/test/debugger/debug/es6/default-parameters-debug.js b/deps/v8/test/debugger/debug/es6/default-parameters-debug.js new file mode 100644 index 0000000000..87ff386b83 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/default-parameters-debug.js @@ -0,0 +1,54 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --noanalyze-environment-liveness + + +Debug = debug.Debug + +listenerComplete = false; +breakPointCount = 0; +exception = null; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + breakPointCount++; + if (breakPointCount == 1) { + // Break point in initializer for parameter `a`, invoked by + // initializer for parameter `b` + assertEquals('default', exec_state.frame(0).evaluate('mode').value()); + assertTrue(exec_state.frame(1).evaluate('b').isUndefined()); + assertTrue(exec_state.frame(1).evaluate('c').isUndefined()); + } else if (breakPointCount == 2) { + // Break point in IIFE initializer for parameter `c` + assertEquals('modeFn', exec_state.frame(1).evaluate('a.name').value()); + assertEquals('default', exec_state.frame(1).evaluate('b').value()); + assertTrue(exec_state.frame(1).evaluate('c').isUndefined()); + } else if (breakPointCount == 3) { + // Break point in function body --- `c` parameter is shadowed + assertEquals('modeFn', exec_state.frame(0).evaluate('a.name').value()); + assertEquals('default', exec_state.frame(0).evaluate('b').value()); + assertEquals('local', exec_state.frame(0).evaluate('d').value()); + } + } catch (e) { + exception = e; + } +}; + +// Add the debug event listener. +Debug.setListener(listener); + +function f(a = function modeFn(mode) { debugger; return mode; }, + b = a("default"), + c = (function() { debugger; })()) { + var d = 'local'; + debugger; +}; + +f(); + +// Make sure that the debug event listener vas invoked. +assertEquals(3, breakPointCount); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/es6/generators-debug-liveedit.js b/deps/v8/test/debugger/debug/es6/generators-debug-liveedit.js new file mode 100644 index 0000000000..1fe039c2fc --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/generators-debug-liveedit.js @@ -0,0 +1,118 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +var Debug = debug.Debug; +var LiveEdit = Debug.LiveEdit; + +unique_id = 0; + +var Generator = (function*(){}).constructor; + +function assertIteratorResult(value, done, result) { + assertEquals({value: value, done: done}, result); +} + +function MakeGenerator() { + // Prevents eval script caching. + unique_id++; + return Generator('callback', + "/* " + unique_id + "*/\n" + + "yield callback();\n" + + "return 'Cat';\n"); +} + +function MakeFunction() { + // Prevents eval script caching. + unique_id++; + return Function('callback', + "/* " + unique_id + "*/\n" + + "callback();\n" + + "return 'Cat';\n"); +} + +// First, try MakeGenerator with no perturbations. +(function(){ + var generator = MakeGenerator(); + function callback() {}; + var iter = generator(callback); + assertIteratorResult(undefined, false, iter.next()); + assertIteratorResult("Cat", true, iter.next()); +})(); + +function patch(fun, from, to) { + function debug() { + var log = new Array(); + var script = Debug.findScript(fun); + var pos = script.source.indexOf(from); + try { + LiveEdit.TestApi.ApplySingleChunkPatch(script, pos, from.length, to, + log); + } finally { + print("Change log: " + JSON.stringify(log) + "\n"); + } + } + %ExecuteInDebugContext(debug); +} + +// Try to edit a MakeGenerator while it's running, then again while it's +// stopped. +(function(){ + var generator = MakeGenerator(); + + var gen_patch_attempted = false; + function attempt_gen_patch() { + assertFalse(gen_patch_attempted); + gen_patch_attempted = true; + assertThrows(function() { patch(generator, "'Cat'", "'Capybara'") }, + LiveEdit.Failure); + }; + var iter = generator(attempt_gen_patch); + assertIteratorResult(undefined, false, iter.next()); + // Patch should not succeed because there is a live generator activation on + // the stack. + assertIteratorResult("Cat", true, iter.next()); + assertTrue(gen_patch_attempted); + + // At this point one iterator is live, but closed, so the patch will succeed. + patch(generator, "'Cat'", "'Capybara'"); + iter = generator(function(){}); + assertIteratorResult(undefined, false, iter.next()); + // Patch successful. + assertIteratorResult("Capybara", true, iter.next()); + + // Patching will fail however when a live iterator is suspended. + iter = generator(function(){}); + assertIteratorResult(undefined, false, iter.next()); + assertThrows(function() { patch(generator, "'Capybara'", "'Tapir'") }, + LiveEdit.Failure); + assertIteratorResult("Capybara", true, iter.next()); + + // Try to patch functions with activations inside and outside generator + // function activations. We should succeed in the former case, but not in the + // latter. + var fun_outside = MakeFunction(); + var fun_inside = MakeFunction(); + var fun_patch_attempted = false; + var fun_patch_restarted = false; + function attempt_fun_patches() { + if (fun_patch_attempted) { + assertFalse(fun_patch_restarted); + fun_patch_restarted = true; + return; + } + fun_patch_attempted = true; + // Patching outside a generator activation must fail. + assertThrows(function() { patch(fun_outside, "'Cat'", "'Cobra'") }, + LiveEdit.Failure); + // Patching inside a generator activation may succeed. + patch(fun_inside, "'Cat'", "'Koala'"); + } + iter = generator(function() { return fun_inside(attempt_fun_patches) }); + assertEquals('Cat', + fun_outside(function () { + assertIteratorResult('Koala', false, iter.next()); + assertTrue(fun_patch_restarted); + })); +})(); diff --git a/deps/v8/test/debugger/debug/es6/generators-debug-scopes.js b/deps/v8/test/debugger/debug/es6/generators-debug-scopes.js new file mode 100644 index 0000000000..a46dc8b22e --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/generators-debug-scopes.js @@ -0,0 +1,284 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --noanalyze-environment-liveness + +var Debug = debug.Debug; +var global_marker = 7; + +function RunTest(name, formals_and_body, args, handler, continuation) { + var handler_called = false; + var exception = null; + + function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + handler_called = true; + handler(exec_state); + } + } catch (e) { + exception = e; + } + } + + function run(thunk) { + handler_called = false; + exception = null; + + var res = thunk(); + if (continuation) + continuation(res); + + assertTrue(handler_called, "listener not called for " + name); + assertNull(exception, name + " / " + exception); + } + + var fun = Function.apply(null, formals_and_body); + var gen = (function*(){}).constructor.apply(null, formals_and_body); + + Debug.setListener(listener); + + run(function () { return fun.apply(null, args) }); + run(function () { return gen.apply(null, args).next().value }); + + // TODO(wingo): Uncomment after bug 2838 is fixed. + // Debug.setListener(null); +} + +// Check that two scope are the same. +function assertScopeMirrorEquals(scope1, scope2) { + assertEquals(scope1.scopeType(), scope2.scopeType()); + assertEquals(scope1.frameIndex(), scope2.frameIndex()); + assertEquals(scope1.scopeIndex(), scope2.scopeIndex()); + assertPropertiesEqual(scope1.scopeObject().value(), scope2.scopeObject().value()); +} + +function CheckFastAllScopes(scopes, exec_state) { + var fast_all_scopes = exec_state.frame().allScopes(true); + var length = fast_all_scopes.length; + assertTrue(scopes.length >= length); + for (var i = 0; i < scopes.length && i < length; i++) { + var scope = fast_all_scopes[length - i - 1]; + assertEquals(scopes[scopes.length - i - 1], scope.scopeType()); + } +} + +// Check that the scope chain contains the expected types of scopes. +function CheckScopeChain(scopes, exec_state) { + var all_scopes = exec_state.frame().allScopes(); + assertEquals(scopes.length, exec_state.frame().scopeCount()); + assertEquals(scopes.length, all_scopes.length, "FrameMirror.allScopes length"); + for (var i = 0; i < scopes.length; i++) { + var scope = exec_state.frame().scope(i); + assertEquals(scopes[i], scope.scopeType()); + assertScopeMirrorEquals(all_scopes[i], scope); + + // Check the global object when hitting the global scope. + if (scopes[i] == debug.ScopeType.Global) { + assertEquals(global_marker, scope.scopeObject().value().global_marker); + } + } + CheckFastAllScopes(scopes, exec_state); +} + +// Check that the content of the scope is as expected. For functions just check +// that there is a function. +function CheckScopeContent(content, number, exec_state) { + var scope = exec_state.frame().scope(number); + var count = 0; + for (var p in content) { + var property_mirror = scope.scopeObject().property(p); + assertFalse(property_mirror.isUndefined(), + 'property ' + p + ' not found in scope'); + assertEquals(content[p], property_mirror.value().value(), + 'property ' + p + ' has unexpected value'); + count++; + } + + // 'arguments' and might be exposed in the local and closure scope. Just + // ignore this. + var scope_size = scope.scopeObject().properties().length; + if (!scope.scopeObject().property('arguments').isUndefined()) { + scope_size--; + } + // Skip property with empty name. + if (!scope.scopeObject().property('').isUndefined()) { + scope_size--; + } + + if (scope_size < count) { + print('Names found in scope:'); + var names = scope.scopeObject().propertyNames(); + for (var i = 0; i < names.length; i++) { + print(names[i]); + } + } + assertTrue(scope_size >= count); +} + + +// Simple empty local scope. +RunTest("Local 1", + ['debugger;'], + [], + function (exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); + }); + +// Local scope with a parameter. +RunTest("Local 2", + ['a', 'debugger;'], + [1], + function (exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1}, 0, exec_state); + }); + +// Local scope with a parameter and a local variable. +RunTest("Local 3", + ['a', 'var x = 3; debugger;'], + [1], + function (exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,x:3}, 0, exec_state); + }); + +// Local scope with parameters and local variables. +RunTest("Local 4", + ['a', 'b', 'var x = 3; var y = 4; debugger;'], + [1, 2], + function (exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state); + }); + +// Empty local scope with use of eval. +RunTest("Local 5", + ['eval(""); debugger;'], + [], + function (exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); + }); + +// Local introducing local variable using eval. +RunTest("Local 6", + ['eval("var i = 5"); debugger;'], + [], + function (exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({i:5}, 0, exec_state); + }); + +// Local scope with parameters, local variables and local variable introduced +// using eval. +RunTest("Local 7", + ['a', 'b', + "var x = 3; var y = 4;\n" + + "eval('var i = 5'); eval ('var j = 6');\n" + + "debugger;"], + [1, 2], + function (exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state); + }); + +// Nested empty with blocks. +RunTest("With", + ["with ({a:1}) { with ({b:2}) { debugger; } }"], + [], + function (exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({b:2}, 0, exec_state); + CheckScopeContent({a:1}, 1, exec_state); + }); + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. +RunTest("Closure 1", + ['a', 'return function() { debugger; return a; }'], + [1], + function (exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1}, 1, exec_state); + }, + function (result) { result() }); + +RunTest("The full monty", + ['a', 'b', + "var x = 3;\n" + + "var y = 4;\n" + + "eval('var i = 5');\n" + + "eval('var j = 6');\n" + + "function f(a, b) {\n" + + " var x = 9;\n" + + " var y = 10;\n" + + " eval('var i = 11');\n" + + " eval('var j = 12');\n" + + " with ({j:13}){\n" + + " return function() {\n" + + " var x = 14;\n" + + " with ({a:15}) {\n" + + " with ({b:16}) {\n" + + " debugger;\n" + + " some_global = a;\n" + + " return f;\n" + + " }\n" + + " }\n" + + " };\n" + + " }\n" + + "}\n" + + "return f(a, b);"], + [1, 2], + function (exec_state) { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.With, + debug.ScopeType.Closure, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({b:16}, 0, exec_state); + CheckScopeContent({a:15}, 1, exec_state); + CheckScopeContent({x:14}, 2, exec_state); + CheckScopeContent({j:13}, 3, exec_state); + CheckScopeContent({a:1,b:2,x:9,y:10,i:11,j:12}, 4, exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6,f:undefined}, 5, + exec_state); + }, + function (result) { result() }); + +RunTest("Catch block 1", + ["try { throw 'Exception'; } catch (e) { debugger; }"], + [], + function (exec_state) { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); + }); diff --git a/deps/v8/test/debugger/debug/es6/regress/regress-468661.js b/deps/v8/test/debugger/debug/es6/regress/regress-468661.js new file mode 100644 index 0000000000..229253dec4 --- /dev/null +++ b/deps/v8/test/debugger/debug/es6/regress/regress-468661.js @@ -0,0 +1,70 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +Debug = debug.Debug +var exception = null; +var break_count = 0; +const expected_breaks = 9; + +var expected_values = + [ReferenceError, undefined, 0, 0, 0, 0, 1, + ReferenceError, ReferenceError]; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + assertTrue(exec_state.frameCount() != 0, "FAIL: Empty stack trace"); + var frameMirror = exec_state.frame(0); + + var v = null;; + try { + v = frameMirror.evaluate('i').value(); + } catch(e) { + v = e; + } + frameMirror.allScopes(); + var source = frameMirror.sourceLineText(); + print("paused at: " + source); + assertTrue(source.indexOf("// Break " + break_count + ".") > 0, + "Unexpected pause at: " + source + "\n" + + "Expected: // Break " + break_count + "."); + if (expected_values[break_count] === ReferenceError) { + assertTrue(v instanceof ReferenceError); + } else { + assertSame(expected_values[break_count], v); + } + ++break_count; + + if (break_count !== expected_breaks) { + exec_state.prepareStep(Debug.StepAction.StepIn); + print("Next step prepared"); + } + } + } catch(e) { + exception = e; + print(e, e.stack); + } +}; + +Debug.setListener(listener); + +var sum = 0; +(function (){ + 'use strict'; + + debugger; // Break 0. + + for (let i=0; // Break 1. + i < 1; // Break 2. // Break 6. + i++) { // Break 5. + let key = i; // Break 3. + sum += key; // Break 4. + } +}()); // Break 7. + +assertNull(exception); // Break 8. +assertEquals(expected_breaks, break_count); + +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-basic.js b/deps/v8/test/debugger/debug/es8/async-debug-basic.js index c22662c01b..9423fe5b2b 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-basic.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-basic.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - Debug = debug.Debug listenerComplete = false; diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception-cases.js b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception-cases.js index 99dc515bc2..f5c1ed98a8 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception-cases.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception-cases.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - Debug = debug.Debug let events = 0; @@ -208,9 +206,8 @@ function runPart(n) { Debug.clearBreakOnUncaughtException(); } if (expectedEvents != events) { - print(`producer ${producer} consumer ${consumer} expectedEvents ` + - `${expectedEvents} caught ${caught} events ${events}`); - quit(1); + %AbortJS(`producer ${producer} consumer ${consumer} expectedEvents ` + + `${expectedEvents} caught ${caught} events ${events}`); } } } diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception-cases0.js b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception-cases0.js index 6862e54a12..15b4f39d47 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception-cases0.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception-cases0.js @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await -// Files: test/debugger/debug/harmony/async-debug-caught-exception-cases.js +// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js runPart(0); diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception-cases1.js b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception-cases1.js index 17b534e8c1..35c2c75c46 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception-cases1.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception-cases1.js @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await -// Files: test/debugger/debug/harmony/async-debug-caught-exception-cases.js +// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js runPart(1); diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception-cases2.js b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception-cases2.js index 06583494a7..58dcb476cf 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception-cases2.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception-cases2.js @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await -// Files: test/debugger/debug/harmony/async-debug-caught-exception-cases.js +// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js runPart(2); diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception-cases3.js b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception-cases3.js index 451f8b9636..1302e647ea 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception-cases3.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception-cases3.js @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await -// Files: test/debugger/debug/harmony/async-debug-caught-exception-cases.js +// Files: test/debugger/debug/es8/async-debug-caught-exception-cases.js runPart(3); diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception.js b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception.js index 391a41cd15..2feecc067f 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-caught-exception.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-caught-exception.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - Debug = debug.Debug var exception = null; diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-step-abort-at-break.js b/deps/v8/test/debugger/debug/es8/async-debug-step-abort-at-break.js index d57db4e4e1..055552bfb9 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-step-abort-at-break.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-step-abort-at-break.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - var Debug = debug.Debug; var step_count = 0; diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-step-continue-at-break.js b/deps/v8/test/debugger/debug/es8/async-debug-step-continue-at-break.js index 3ae5656738..19c4001873 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-step-continue-at-break.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-step-continue-at-break.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - var Debug = debug.Debug; var step_count = 0; diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-step-in-and-out.js b/deps/v8/test/debugger/debug/es8/async-debug-step-in-and-out.js index 388fa721cf..d4b16bea11 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-step-in-and-out.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-step-in-and-out.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - var Debug = debug.Debug; var step_count = 0; diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-step-in-out-out.js b/deps/v8/test/debugger/debug/es8/async-debug-step-in-out-out.js index 09e3c6bf5e..3521b42782 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-step-in-out-out.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-step-in-out-out.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - var Debug = debug.Debug; var step_count = 0; diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-step-in.js b/deps/v8/test/debugger/debug/es8/async-debug-step-in.js index 64366a84d3..1808b1628a 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-step-in.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-step-in.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - var Debug = debug.Debug; var step_count = 0; diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-step-nested.js b/deps/v8/test/debugger/debug/es8/async-debug-step-nested.js index 9736195b46..9a1342419b 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-step-nested.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-step-nested.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - var Debug = debug.Debug; var step_count = 0; diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-step-next-constant.js b/deps/v8/test/debugger/debug/es8/async-debug-step-next-constant.js index d342790d7e..11fda38f86 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-step-next-constant.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-step-next-constant.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - var Debug = debug.Debug; var step_count = 0; diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-step-next.js b/deps/v8/test/debugger/debug/es8/async-debug-step-next.js index 59133eb46e..26be9f349d 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-step-next.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-step-next.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - var Debug = debug.Debug; var step_count = 0; diff --git a/deps/v8/test/debugger/debug/harmony/async-debug-step-out.js b/deps/v8/test/debugger/debug/es8/async-debug-step-out.js index b675523123..3ec6dd3490 100644 --- a/deps/v8/test/debugger/debug/harmony/async-debug-step-out.js +++ b/deps/v8/test/debugger/debug/es8/async-debug-step-out.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - var Debug = debug.Debug; var step_count = 0; diff --git a/deps/v8/test/debugger/debug/es8/async-function-debug-evaluate.js b/deps/v8/test/debugger/debug/es8/async-function-debug-evaluate.js new file mode 100644 index 0000000000..a635482f51 --- /dev/null +++ b/deps/v8/test/debugger/debug/es8/async-function-debug-evaluate.js @@ -0,0 +1,137 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var Debug = debug.Debug; +var breakPointCount = 0; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + ++breakPointCount; + try { + if (breakPointCount === 1) { + assertEquals( + "inner", exec_state.frame(0).evaluate("inner").value()); + assertThrows(() => exec_state.frame(0).evaluate("letInner").value(), + ReferenceError); + assertThrows(() => exec_state.frame(0).evaluate("constInner").value(), + ReferenceError); + + assertEquals("outer", exec_state.frame(0).evaluate("outer").value()); + assertEquals( + "const outer", exec_state.frame(0).evaluate("constOuter").value()); + assertEquals( + "let outer", exec_state.frame(0).evaluate("letOuter").value()); + + assertEquals("outer", exec_state.frame(1).evaluate("outer").value()); + assertEquals( + "const outer", exec_state.frame(1).evaluate("constOuter").value()); + assertEquals( + "let outer", exec_state.frame(1).evaluate("letOuter").value()); + + assertThrows(() => exec_state.frame(0).evaluate("withVar").value(), + ReferenceError); + + } else if (breakPointCount === 2) { + assertEquals( + "inner", exec_state.frame(0).evaluate("inner").value()); + assertThrows(() => exec_state.frame(0).evaluate("letInner").value(), + ReferenceError); + assertThrows(() => exec_state.frame(0).evaluate("constInner").value(), + ReferenceError); + + assertEquals(57, exec_state.frame(0).evaluate("x").value()); + assertEquals(100, exec_state.frame(0).evaluate("y").value()); + + // From breakPointCount === 1 and later, it's not possible to access + // earlier framestates. + assertEquals("outer", exec_state.frame(0).evaluate("outer").value()); + assertEquals( + "const outer", exec_state.frame(0).evaluate("constOuter").value()); + assertEquals( + "let outer", exec_state.frame(0).evaluate("letOuter").value()); + + exec_state.frame(0).evaluate("x = `x later(${x})`"); + exec_state.frame(0).evaluate("y = `y later(${y})`"); + exec_state.frame(0).evaluate("z = `ZEE`"); + + } else if (breakPointCount === 3) { + assertEquals( + "inner", exec_state.frame(0).evaluate("inner").value()); + assertEquals( + "let inner", exec_state.frame(0).evaluate("letInner").value()); + assertEquals( + "const inner", exec_state.frame(0).evaluate("constInner").value()); + + } else if (breakPointCount === 4) { + assertEquals( + "oop", exec_state.frame(0).evaluate("error.message").value()); + assertEquals( + "Error", + exec_state.frame(0).evaluate("error.constructor.name").value()); + assertEquals("floof", exec_state.frame(0).evaluate("bun").value()); + assertThrows(() => exec_state.frame(0).evaluate("cow").value(), + ReferenceError); + + assertEquals("outer", exec_state.frame(0).evaluate("outer").value()); + assertEquals( + "const outer", exec_state.frame(0).evaluate("constOuter").value()); + assertEquals( + "let outer", exec_state.frame(0).evaluate("letOuter").value()); + } + } catch (e) { + print(e.stack); + quit(1); + } +} + +Debug.setListener(listener); + +var outer = "outer"; +const constOuter = "const outer"; +let letOuter = "let outer" + +async function thrower() { + return Promise.reject(new Error("oop")); +} + +async function testLater() { + return { x: 57, y: 100 }; +} + +async function test() { + var inner = "inner"; + debugger; + + let withVar = await testLater(); + with (withVar) { + debugger; + } + + assertEquals("x later(57)", withVar.x); + assertEquals("y later(100)", withVar.y); + assertEquals(undefined, withVar.z); + assertEquals("ZEE", z); + + let letInner = "let inner"; + const constInner = "const inner"; + debugger; + + try { + await thrower(); + } catch (error) { + const bun = "floof"; + debugger; + let cow = "moo"; + } +} + +test(). +then(x => { + Debug.setListener(null); +}). +catch(error => { + print(error.stack); + quit(1); + Debug.setListener(null); +}); diff --git a/deps/v8/test/debugger/debug/es8/async-function-debug-scopes.js b/deps/v8/test/debugger/debug/es8/async-function-debug-scopes.js new file mode 100644 index 0000000000..6d54aea98b --- /dev/null +++ b/deps/v8/test/debugger/debug/es8/async-function-debug-scopes.js @@ -0,0 +1,548 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var Debug = debug.Debug; +var global_marker = 7; + +async function thrower() { throw 'Exception'; } + +async function test(name, func, args, handler, continuation) { + var handler_called = false; + var exception = null; + + function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + handler_called = true; + handler(exec_state); + } + } catch (e) { + exception = e; + } + } + + Debug.setListener(listener); + + var result; + if (typeof func === "object") + result = await func.method.apply(func, args); + else + result = await func.apply(null, args); + + if (typeof continuation === "function") { + await continuation(result); + } + + assertTrue(handler_called, `Expected ${name} handler to be called`); + if (exception) { + exception.message = `${name} / ${exception.message}`; + print(exception.stack); + quit(1); + } + + Debug.setListener(null); +} + +async function runTests() { + +// Simple +await test( + "(AsyncFunctionExpression) Local 1", + async function() { debugger; }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 1 --- resume normal", + async function() { let z = await 2; debugger; }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({z: 2}, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 1 --- resume throw", + async function() { let q = await 1; + try { let z = await thrower(); } + catch (e) { debugger; } }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e: 'Exception'}, 0, exec_state); + CheckScopeContent({q: 1}, 1, exec_state); + + }); + +// Simple With Parameter +await test( + "(AsyncFunctionExpression) Local 2", + async function(a) { debugger; }, [1], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({ a: 1 }, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 2 --- resume normal", + async function(a) { let z = await 2; debugger; }, [1], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({ a: 1, z: 2 }, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 2 --- resume throw", + async function(a) { let z = await 2; + try { await thrower(); } catch (e) { debugger; } }, [1], + exec_state => { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({ e: 'Exception' }, 0, exec_state); + CheckScopeContent({ a: 1, z: 2 }, 1, exec_state); + }); + +// Simple With Parameter and Variable +await test( + "(AsyncFunctionExpression) Local 3", + async function(a) { var b = 2; debugger; }, [1], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({ a: 1, b: 2 }, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 3 --- resume normal", + async function(a) { let y = await 3; var b = 2; let z = await 4; + debugger; }, [1], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({ a: 1, b: 2, y: 3, z: 4 }, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 3 --- resume throw", + async function(a) { let y = await 3; + try { var b = 2; let z = await thrower(); } + catch (e) { debugger; } }, [1], + exec_state => { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({ e: 'Exception' }, 0, exec_state); + CheckScopeContent({ a: 1, b: 2, y: 3 }, 1, exec_state); + }); + +// Local scope with parameters and local variables. +await test( + "(AsyncFunctionExpression) Local 4", + async function(a, b) { var x = 3; var y = 4; debugger; }, [1, 2], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 4 --- resume normal", + async function(a, b) { let q = await 5; var x = 3; var y = 4; + let r = await 6; debugger; }, [1, 2], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4, q: 5, r: 6}, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 4 --- resume throw", + async function(a, b) { let q = await 5; var x = 3; var y = 4; + try { let r = await thrower(); } + catch (e) { debugger; } }, [1, 2], + exec_state => { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e: 'Exception'}, 0, exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4, q: 5}, 1, exec_state); + }); + +// Empty local scope with use of eval. +await test( + "(AsyncFunctionExpression) Local 5", + async function() { eval(""); debugger; }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 5 --- resume normal", + async function() { let x = await 1; eval(""); let y = await 2; + debugger; }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({ x: 1, y: 2 }, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 5 --- resume throw", + async function() { let x = await 1; eval(""); + try { let y = await thrower(); } + catch (e) { debugger; } }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({ e: 'Exception' }, 0, exec_state); + CheckScopeContent({ x: 1 }, 1, exec_state); + }); + +// Local introducing local variable using eval. +await test( + "(AsyncFunctionExpression) Local 6", + async function() { eval("var i = 5"); debugger; }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({i:5}, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 6 --- resume normal", + async function() { let x = await 1; eval("var i = 5"); let y = await 2; + debugger; }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({i:5, x: 1, y: 2}, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 6 --- resume throw", + async function() { let x = await 1; eval("var i = 5"); + try { let y = await thrower(); } + catch (e) { debugger; } }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e: 'Exception' }, 0, exec_state); + CheckScopeContent({i:5, x: 1}, 1, exec_state); + }); + +// Local scope with parameters, local variables and local variable introduced +// using eval. +await test( + "(AsyncFunctionExpression) Local 7", + async function(a, b) { var x = 3; var y = 4; + eval("var i = 5;"); eval("var j = 6"); + debugger; }, [1, 2], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6}, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 7 --- resume normal", + async function(a, b) { let z = await 7; var x = 3; var y = 4; + eval("var i = 5;"); eval("var j = 6"); + let q = await 8; + debugger; }, [1, 2], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6, z:7, q:8}, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Local 7 --- resume throw", + async function(a, b) { let z = await 7; var x = 3; var y = 4; + eval("var i = 5;"); eval("var j = 6"); + try { let q = await thrower(); } + catch (e) { debugger; } }, [1, 2], + exec_state => { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e: 'Exception'}, 0, exec_state); + //CheckScopeContent({a:1,b:2,x:3,y:4,i:5,j:6, z:7}, 1, exec_state); + }); + +// Nested empty with blocks. +await test( + "(AsyncFunctionExpression) With", + async function() { with ({}) { with ({}) { debugger; } } }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); + CheckScopeContent({}, 1, exec_state); + }); + +await test( + "(AsyncFunctionExpression) With --- resume normal", + async function() { let x = await 1; with ({}) { with ({}) { + let y = await 2; debugger; } } }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({y:2}, 0, exec_state); + CheckScopeContent({}, 1, exec_state); + CheckScopeContent({}, 2, exec_state); + CheckScopeContent({x:1}, 3, exec_state); + }); + +await test( + "(AsyncFunctionExpression) With --- resume throw", + async function() { let x = await 1; with ({}) { with ({}) { + try { let y = await thrower(); } + catch (e) { debugger; } } } }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.With, + debug.ScopeType.With, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({ e: 'Exception'}, 0, exec_state); + CheckScopeContent({}, 1, exec_state); + CheckScopeContent({}, 2, exec_state); + CheckScopeContent({x:1}, 3, exec_state); + }); + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. +await test( + "(AsyncFunctionExpression) Closure 1", + async function(a) { return function() { debugger; return a; } }, [1], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1}, 1, exec_state); + }, + result => result()); + +await test( + "(AsyncFunctionExpression) Closure 1 --- resume normal", + async function(a) { let x = await 2; + return function() { debugger; return a; } }, [1], + exec_state => { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1, x: 2}, 1, exec_state); + }, + result => result()); + +await test( + "(AsyncFunctionExpression) Closure 1 --- resume throw", + async function(a) { let x = await 2; + return async function() { + try { await thrower(); } + catch (e) { debugger; } return a; }; }, [1], + exec_state => { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e: 'Exception'}, 0, exec_state); + CheckScopeContent({a:1, x: 2}, 2, exec_state); + }, + result => result()); + +await test( + "(AsyncFunctionExpression) Catch block 1", + async function() { try { throw 'Exception'; } catch (e) { debugger; } }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Catch block 1 --- resume normal", + async function() { + let x = await 1; + try { throw 'Exception'; } catch (e) { let y = await 2; debugger; } }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({y: 2}, 0, exec_state); + CheckScopeContent({e:'Exception'}, 1, exec_state); + CheckScopeContent({x: 1}, 2, exec_state); + }); + +await test( + "(AsyncFunctionExpression) Catch block 1 --- resume throw", + async function() { + let x = await 1; + try { throw 'Exception!'; } catch (e) { + try { let y = await thrower(); } catch (e) { debugger; } } }, [], + exec_state => { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); + CheckScopeContent({e:'Exception!'}, 1, exec_state); + CheckScopeContent({x: 1}, 2, exec_state); + }); +} + +runTests().catch(error => { + print(error.stack); + quit(1); +}) + +// Check that two scope are the same. +function assertScopeMirrorEquals(scope1, scope2) { + assertEquals(scope1.scopeType(), scope2.scopeType()); + assertEquals(scope1.frameIndex(), scope2.frameIndex()); + assertEquals(scope1.scopeIndex(), scope2.scopeIndex()); + assertPropertiesEqual( + scope1.scopeObject().value(), scope2.scopeObject().value()); +} + +function CheckFastAllScopes(scopes, exec_state) { + var fast_all_scopes = exec_state.frame().allScopes(true); + var length = fast_all_scopes.length; + assertTrue(scopes.length >= length); + for (var i = 0; i < scopes.length && i < length; i++) { + var scope = fast_all_scopes[length - i - 1]; + assertEquals(scopes[scopes.length - i - 1], scope.scopeType()); + } +} + +// Check that the scope chain contains the expected types of scopes. +function CheckScopeChain(scopes, exec_state) { + var all_scopes = exec_state.frame().allScopes(); + assertEquals( + scopes.length, all_scopes.length, "FrameMirror.allScopes length"); + for (var i = 0; i < scopes.length; i++) { + var scope = exec_state.frame().scope(i); + assertEquals(scopes[i], scope.scopeType()); + assertScopeMirrorEquals(all_scopes[i], scope); + + // Check the global object when hitting the global scope. + if (scopes[i] == debug.ScopeType.Global) { + assertEquals(global_marker, scope.scopeObject().value().global_marker); + } + } + CheckFastAllScopes(scopes, exec_state); +} + +// Check that the content of the scope is as expected. For functions just check +// that there is a function. +function CheckScopeContent(content, number, exec_state) { + var scope = exec_state.frame().scope(number); + var count = 0; + for (var p in content) { + var property_mirror = scope.scopeObject().property(p); + assertFalse(property_mirror.isUndefined(), + `property ${p} not found in scope`); + assertEquals(content[p], property_mirror.value().value(), + `property ${p} has unexpected value`); + count++; + } + + // 'arguments' and might be exposed in the local and closure scope. Just + // ignore this. + var scope_size = scope.scopeObject().properties().length; + if (!scope.scopeObject().property('arguments').isUndefined()) { + scope_size--; + } + // Skip property with empty name. + if (!scope.scopeObject().property('').isUndefined()) { + scope_size--; + } + + if (scope_size < count) { + print('Names found in scope:'); + var names = scope.scopeObject().propertyNames(); + for (var i = 0; i < names.length; i++) { + print(names[i]); + } + } + assertTrue(scope_size >= count); +} diff --git a/deps/v8/test/debugger/debug/harmony/debug-async-break-on-stack.js b/deps/v8/test/debugger/debug/es8/debug-async-break-on-stack.js index 5173c87ee4..df389f33d9 100644 --- a/deps/v8/test/debugger/debug/harmony/debug-async-break-on-stack.js +++ b/deps/v8/test/debugger/debug/es8/debug-async-break-on-stack.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - var Debug = debug.Debug; function assertEqualsAsync(expected, run, msg) { diff --git a/deps/v8/test/debugger/debug/harmony/debug-async-break.js b/deps/v8/test/debugger/debug/es8/debug-async-break.js index dac3474f75..3e07ba9344 100644 --- a/deps/v8/test/debugger/debug/harmony/debug-async-break.js +++ b/deps/v8/test/debugger/debug/es8/debug-async-break.js @@ -2,8 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --harmony-async-await - var Debug = debug.Debug; function assertEqualsAsync(expected, run, msg) { diff --git a/deps/v8/test/debugger/debug/es8/debug-async-liveedit.js b/deps/v8/test/debugger/debug/es8/debug-async-liveedit.js new file mode 100644 index 0000000000..cad314cfad --- /dev/null +++ b/deps/v8/test/debugger/debug/es8/debug-async-liveedit.js @@ -0,0 +1,130 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +var Debug = debug.Debug; +var LiveEdit = Debug.LiveEdit; + +unique_id = 0; + +var AsyncFunction = (async function(){}).constructor; + +function assertPromiseValue(value, promise) { + promise.then(resolve => { + went = true; + if (resolve !== value) { + print(`expected ${value} found ${resolve}`); + quit(1); + } + }, reject => { + print(`rejected ${reject}`); + quit(1); + }); +} + +function MakeAsyncFunction() { + // Prevents eval script caching. + unique_id++; + return AsyncFunction('callback', + "/* " + unique_id + "*/\n" + + "await callback();\n" + + "return 'Cat';\n"); +} + +function MakeFunction() { + // Prevents eval script caching. + unique_id++; + return Function('callback', + "/* " + unique_id + "*/\n" + + "callback();\n" + + "return 'Cat';\n"); +} + +// First, try MakeGenerator with no perturbations. +(function(){ + var asyncfn = MakeAsyncFunction(); + function callback() {}; + var promise = asyncfn(callback); + assertPromiseValue('Cat', promise); +})(); + +function patch(fun, from, to) { + function debug() { + var log = new Array(); + var script = Debug.findScript(fun); + var pos = script.source.indexOf(from); + print(`pos ${pos}`); + try { + LiveEdit.TestApi.ApplySingleChunkPatch(script, pos, from.length, to, + log); + } finally { + print("Change log: " + JSON.stringify(log) + "\n"); + } + } + %ExecuteInDebugContext(debug); +} + +// Try to edit a MakeAsyncFunction while it's running, then again while it's +// stopped. +(function(){ + var asyncfn = MakeAsyncFunction(); + + var patch_attempted = false; + function attempt_patch() { + assertFalse(patch_attempted); + patch_attempted = true; + assertThrows(function() { patch(asyncfn, "'Cat'", "'Capybara'") }, + LiveEdit.Failure); + }; + var promise = asyncfn(attempt_patch); + // Patch should not succeed because there is a live async function activation + // on the stack. + assertPromiseValue("Cat", promise); + assertTrue(patch_attempted); + + %RunMicrotasks(); + + // At this point one iterator is live, but closed, so the patch will succeed. + patch(asyncfn, "'Cat'", "'Capybara'"); + promise = asyncfn(function(){}); + // Patch successful. + assertPromiseValue("Capybara", promise); + + // Patching will fail however when an async function is suspended. + var resolve; + promise = asyncfn(function(){return new Promise(function(r){resolve = r})}); + assertThrows(function() { patch(asyncfn, "'Capybara'", "'Tapir'") }, + LiveEdit.Failure); + resolve(); + assertPromiseValue("Capybara", promise); + + // Try to patch functions with activations inside and outside async + // function activations. We should succeed in the former case, but not in the + // latter. + var fun_outside = MakeFunction(); + var fun_inside = MakeFunction(); + var fun_patch_attempted = false; + var fun_patch_restarted = false; + function attempt_fun_patches() { + if (fun_patch_attempted) { + assertFalse(fun_patch_restarted); + fun_patch_restarted = true; + return; + } + fun_patch_attempted = true; + // Patching outside an async function activation must fail. + assertThrows(function() { patch(fun_outside, "'Cat'", "'Cobra'") }, + LiveEdit.Failure); + // Patching inside an async function activation may succeed. + patch(fun_inside, "'Cat'", "'Koala'"); + } + promise = asyncfn(function() { return fun_inside(attempt_fun_patches) }); + assertEquals('Cat', + fun_outside(function () { + assertPromiseValue('Capybara', promise); + assertTrue(fun_patch_restarted); + assertTrue(fun_inside.toString().includes("'Koala'")); + })); +})(); + +%RunMicrotasks(); diff --git a/deps/v8/test/debugger/debug/function-source.js b/deps/v8/test/debugger/debug/function-source.js new file mode 100644 index 0000000000..c5ebcfe5a0 --- /dev/null +++ b/deps/v8/test/debugger/debug/function-source.js @@ -0,0 +1,47 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +// Check that the script source for all functions in a script is the same. +function f() { + function h() { + assertEquals(Debug.scriptSource(f), Debug.scriptSource(h)); + } + h(); +} + +function g() { + function h() { + assertEquals(Debug.scriptSource(f), Debug.scriptSource(h)); + } + h(); +} + +assertEquals(Debug.scriptSource(f), Debug.scriptSource(g)); +f(); +g(); diff --git a/deps/v8/test/debugger/debug/harmony/debug-async-function-async-task-event.js b/deps/v8/test/debugger/debug/harmony/debug-async-function-async-task-event.js deleted file mode 100644 index d5d506e153..0000000000 --- a/deps/v8/test/debugger/debug/harmony/debug-async-function-async-task-event.js +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2016 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Flags: --harmony-async-await - -// The test observes the callbacks that async/await makes to the inspector -// to make accurate stack traces. The pattern is based on saving a stack once -// with enqueueRecurring and restoring it multiple times. - -// Additionally, the limited number of events is an indirect indication that -// we are not doing extra Promise processing that could be associated with memory -// leaks (v8:5380). In particular, no stacks are saved and restored for extra -// Promise handling on throwaway Promises. - -// TODO(littledan): Write a test that demonstrates that the memory leak in -// the exception case is fixed. - -Debug = debug.Debug; - -var base_id = -1; -var exception = null; -var expected = [ - 'enqueueRecurring #1', - 'willHandle #1', - 'then #1', - 'didHandle #1', - 'willHandle #1', - 'then #2', - 'cancel #1', - 'didHandle #1', -]; - -function assertLog(msg) { - print(msg); - assertTrue(expected.length > 0); - assertEquals(expected.shift(), msg); - if (!expected.length) { - Debug.setListener(null); - } -} - -function listener(event, exec_state, event_data, data) { - if (event != Debug.DebugEvent.AsyncTaskEvent) return; - try { - if ("Promise.resolve" == event_data.name()) return; - if (base_id < 0) - base_id = event_data.id(); - var id = event_data.id() - base_id + 1; - assertTrue("async function" == event_data.name()); - assertLog(event_data.type() + " #" + id); - } catch (e) { - print(e + e.stack) - exception = e; - } -} - -Debug.setListener(listener); - -var resolver; -var p = new Promise(function(resolve, reject) { - resolver = resolve; -}); - -async function main() { - await p; - assertLog("then #1"); - await undefined; - assertLog("then #2"); -} -main(); -resolver(); - -%RunMicrotasks(); - -assertNull(exception); - -Debug.clearBreakOnUncaughtException(); -Debug.setListener(null); - -var resolve; -var turnOnListenerPromise = new Promise(r => resolve = r); -async function confused() { - await turnOnListenerPromise; - throw foo -} - -confused(); - -Promise.resolve().then(() => { - Debug.setListener(listener); - Debug.setBreakOnUncaughtException(); - resolve(); -}); - -%RunMicrotasks(); -assertNull(exception); diff --git a/deps/v8/test/debugger/debug/harmony/modules-debug-scopes1.js b/deps/v8/test/debugger/debug/harmony/modules-debug-scopes1.js new file mode 100644 index 0000000000..e67c42de61 --- /dev/null +++ b/deps/v8/test/debugger/debug/harmony/modules-debug-scopes1.js @@ -0,0 +1,871 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// MODULE +// Flags: --allow-natives-syntax --noanalyze-environment-liveness + +// These tests are copied from mjsunit/debug-scopes.js and adapted for modules. + + +var Debug = debug.Debug; + +var test_name; +var listener_delegate; +var listener_called; +var exception; +var begin_test_count = 0; +var end_test_count = 0; +var break_count = 0; + + +// Debug event listener which delegates. +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + break_count++; + listener_called = true; + listener_delegate(exec_state); + } + } catch (e) { + exception = e; + } +} + +// Add the debug event listener. +Debug.setListener(listener); + + +// Initialize for a new test. +function BeginTest(name) { + test_name = name; + listener_delegate = null; + listener_called = false; + exception = null; + begin_test_count++; +} + + +// Check result of a test. +function EndTest() { + assertTrue(listener_called, "listener not called for " + test_name); + assertNull(exception, test_name + " / " + exception); + end_test_count++; +} + + +// Check that two scope are the same. +function assertScopeMirrorEquals(scope1, scope2) { + assertEquals(scope1.scopeType(), scope2.scopeType()); + assertEquals(scope1.frameIndex(), scope2.frameIndex()); + assertEquals(scope1.scopeIndex(), scope2.scopeIndex()); + assertPropertiesEqual(scope1.scopeObject().value(), + scope2.scopeObject().value()); +} + +function CheckFastAllScopes(scopes, exec_state) +{ + var fast_all_scopes = exec_state.frame().allScopes(true); + var length = fast_all_scopes.length; + assertTrue(scopes.length >= length); + for (var i = 0; i < scopes.length && i < length; i++) { + var scope = fast_all_scopes[length - i - 1]; + assertEquals(scopes[scopes.length - i - 1], scope.scopeType()); + } +} + + +// Check that the scope chain contains the expected types of scopes. +function CheckScopeChain(scopes, exec_state) { + var all_scopes = exec_state.frame().allScopes(); + assertEquals(scopes.length, exec_state.frame().scopeCount()); + assertEquals(scopes.length, all_scopes.length, + "FrameMirror.allScopes length"); + for (var i = 0; i < scopes.length; i++) { + var scope = exec_state.frame().scope(i); + assertEquals(scopes[i], scope.scopeType()); + assertScopeMirrorEquals(all_scopes[i], scope); + } + CheckFastAllScopes(scopes, exec_state); +} + + +// Check that the scope chain contains the expected names of scopes. +function CheckScopeChainNames(names, exec_state) { + var all_scopes = exec_state.frame().allScopes(); + assertEquals(names.length, all_scopes.length, "FrameMirror.allScopes length"); + for (var i = 0; i < names.length; i++) { + var scope = exec_state.frame().scope(i); + assertEquals(names[i], scope.details().name()) + } +} + + +// Check that the scope contains at least minimum_content. For functions just +// check that there is a function. +function CheckScopeContent(minimum_content, number, exec_state) { + var scope = exec_state.frame().scope(number); + var minimum_count = 0; + for (var p in minimum_content) { + var property_mirror = scope.scopeObject().property(p); + assertFalse(property_mirror.isUndefined(), + 'property ' + p + ' not found in scope'); + assertEquals(minimum_content[p], property_mirror.value().value(), + 'property ' + p + ' has unexpected value'); + minimum_count++; + } + + // 'arguments' and might be exposed in the local and closure scope. Just + // ignore this. + var scope_size = scope.scopeObject().properties().length; + if (!scope.scopeObject().property('arguments').isUndefined()) { + scope_size--; + } + // Ditto for 'this'. + if (!scope.scopeObject().property('this').isUndefined()) { + scope_size--; + } + // Temporary variables introduced by the parser have not been materialized. + assertTrue(scope.scopeObject().property('').isUndefined()); + + if (scope_size < minimum_count) { + print('Names found in scope:'); + var names = scope.scopeObject().propertyNames(); + for (var i = 0; i < names.length; i++) { + print(names[i]); + } + } + assertTrue(scope_size >= minimum_count); +} + +// Check that the scopes have positions as expected. +function CheckScopeChainPositions(positions, exec_state) { + var all_scopes = exec_state.frame().allScopes(); + assertTrue(positions.length <= all_scopes.length, + "FrameMirror.allScopes length"); + for (var i = 0; i < positions.length; i++) { + var scope = exec_state.frame().scope(i); + var position = positions[i]; + if (!position) + continue; + + print( + `Checking position.start = ${position.start}, .end = ${position.end}`); + assertEquals(position.start, scope.details().startPosition()) + assertEquals(position.end, scope.details().endPosition()) + } +} + +// Simple empty local scope. +BeginTest("Local 1"); + +function local_1() { + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); +}; +local_1(); +EndTest(); + + +// Local scope with a parameter. +BeginTest("Local 2"); + +function local_2(a) { + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1}, 0, exec_state); +}; +local_2(1); +EndTest(); + + +// Local scope with a parameter and a local variable. +BeginTest("Local 3"); + +function local_3(a) { + var x = 3; + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,x:3}, 0, exec_state); +}; +local_3(1); +EndTest(); + + +// Local scope with parameters and local variables. +BeginTest("Local 4"); + +function local_4(a, b) { + var x = 3; + var y = 4; + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state); +}; +local_4(1, 2); +EndTest(); + + +// Empty local scope with use of eval. +BeginTest("Local 5"); + +function local_5() { + eval(''); + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); +}; +local_5(); +EndTest(); + + +// Local introducing local variable using eval. +BeginTest("Local 6"); + +function local_6() { + eval('var i = 5'); + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); +}; +local_6(); +EndTest(); + + +// Local scope with parameters and local variables. +BeginTest("Local 7"); + +function local_7(a, b) { + var x = 3; + var y = 4; + eval('var i = 5'); + eval('var j = 6'); + debugger; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4}, 0, exec_state); +}; +local_7(1, 2); +EndTest(); + + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. +BeginTest("Closure 1"); + +function closure_1(a) { + function f() { + debugger; + return a; + }; + return f; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1}, 1, exec_state); + CheckScopeChainNames(["f", "closure_1", undefined, undefined, undefined], exec_state) +}; +closure_1(1)(); +EndTest(); + + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. Due to VM optimizations parts of the actual closure is +// missing from the debugger information. +BeginTest("Closure 2"); + +function closure_2(a, b) { + var x = a + 2; + var y = b + 2; + function f() { + debugger; + return a + x; + }; + return f; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,x:3}, 1, exec_state); + CheckScopeChainNames(["f", "closure_2", undefined, undefined, undefined], + exec_state) +}; +closure_2(1, 2)(); +EndTest(); + + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. Using all arguments and locals from the outer function +// in the inner function makes these part of the debugger information on the +// closure. +BeginTest("Closure 3"); + +function closure_3(a, b) { + var x = a + 2; + var y = b + 2; + function f() { + debugger; + return a + b + x + y; + }; + return f; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state); + CheckScopeChainNames(["f", "closure_3", undefined, undefined, undefined], + exec_state) +}; +closure_3(1, 2)(); +EndTest(); + + + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. Using all arguments and locals from the outer function +// in the inner function makes these part of the debugger information on the +// closure. Use the inner function as well... +BeginTest("Closure 4"); + +function closure_4(a, b) { + var x = a + 2; + var y = b + 2; + function f() { + debugger; + if (f) { + return a + b + x + y; + } + }; + return f; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,f:undefined}, 1, exec_state); + CheckScopeChainNames(["f", "closure_4", undefined, undefined, undefined], + exec_state) +}; +closure_4(1, 2)(); +EndTest(); + + + +// Simple closure formed by returning an inner function referering the outer +// functions arguments. In the presence of eval all arguments and locals +// (including the inner function itself) from the outer function becomes part of +// the debugger infformation on the closure. +BeginTest("Closure 5"); + +function closure_5(a, b) { + var x = 3; + var y = 4; + function f() { + eval(''); + debugger; + return 1; + }; + return f; +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,f:undefined}, 1, exec_state); + CheckScopeChainNames(["f", "closure_5", undefined, undefined, undefined], + exec_state) +}; +closure_5(1, 2)(); +EndTest(); + + +// Two closures. Due to optimizations only the parts actually used are provided +// through the debugger information. +BeginTest("Closure 6"); +let some_global; +function closure_6(a, b) { + function f(a, b) { + var x = 3; + var y = 4; + return function() { + var x = 3; + var y = 4; + debugger; + some_global = a; + return f; + }; + } + return f(a, b); +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Closure, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({a:1}, 1, exec_state); + CheckScopeContent({f:undefined}, 2, exec_state); + CheckScopeChainNames( + [undefined, "f", "closure_6", undefined, undefined, undefined], + exec_state); +}; +closure_6(1, 2)(); +EndTest(); + + +// Two closures. In the presence of eval all information is provided as the +// compiler cannot determine which parts are used. +BeginTest("Closure 7"); +function closure_7(a, b) { + var x = 3; + var y = 4; + eval('var i = 5'); + eval('var j = 6'); + function f(a, b) { + var x = 3; + var y = 4; + eval('var i = 5'); + eval('var j = 6'); + return function() { + debugger; + some_global = a; + return f; + }; + } + return f(a, b); +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Closure, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 0, exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4}, 1, exec_state); + CheckScopeContent({a:1,b:2,x:3,y:4,f:undefined}, 2, exec_state); + CheckScopeChainNames( + [undefined, "f", "closure_7", undefined, undefined, undefined], + exec_state); +}; +closure_7(1, 2)(); +EndTest(); + + +// Closure that may be optimized out. +BeginTest("Closure 8"); +function closure_8() { + (function inner(x) { + debugger; + })(2); +} + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x: 2}, 0, exec_state); + CheckScopeChainNames(["inner", undefined, undefined, undefined], exec_state); +}; +closure_8(); +EndTest(); + + +BeginTest("Closure 9"); +let closure_9 = Function(' \ + eval("var y = 1;"); \ + eval("var z = 1;"); \ + (function inner(x) { \ + y++; \ + z++; \ + debugger; \ + })(2); \ +') + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Closure, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainNames(["inner", undefined, undefined, undefined], exec_state); +}; +closure_9(); +EndTest(); + + +// Test global scope. +BeginTest("Global"); +listener_delegate = function(exec_state) { + CheckScopeChain( + [debug.ScopeType.Module, debug.ScopeType.Script, debug.ScopeType.Global], + exec_state); + CheckScopeChainNames([undefined, undefined, undefined], exec_state); +}; +debugger; +EndTest(); + + +BeginTest("Catch block 1"); +function catch_block_1() { + try { + throw 'Exception'; + } catch (e) { + debugger; + } +}; + + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); + CheckScopeChainNames( + ["catch_block_1", "catch_block_1", undefined, undefined, undefined], + exec_state); +}; +catch_block_1(); +EndTest(); + + +BeginTest("Catch block 3"); +function catch_block_3() { + eval("var y = 78;"); + try { + throw 'Exception'; + } catch (e) { + debugger; + } +}; + + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); + CheckScopeContent({}, 1, exec_state); + CheckScopeChainNames( + ["catch_block_3", "catch_block_3", undefined, undefined, undefined], + exec_state); +}; +catch_block_3(); +EndTest(); + + +// Test catch in global scope. +BeginTest("Catch block 5"); +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); + CheckScopeChainNames([undefined, undefined, undefined, undefined], + exec_state); +}; + +try { + throw 'Exception'; +} catch (e) { + debugger; +} + +EndTest(); + + +// Closure inside catch in global code. +BeginTest("Catch block 6"); +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Catch, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({x: 2}, 0, exec_state); + CheckScopeContent({e:'Exception'}, 1, exec_state); + CheckScopeChainNames([undefined, undefined, undefined, undefined, undefined], + exec_state); +}; + +try { + throw 'Exception'; +} catch (e) { + (function(x) { + debugger; + })(2); +} +EndTest(); + + +// Catch block in function that is marked for optimization while being executed. +BeginTest("Catch block 7"); +function catch_block_7() { + %OptimizeFunctionOnNextCall(catch_block_7); + try { + throw 'Exception'; + } catch (e) { + debugger; + } +}; + + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Catch, + debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({e:'Exception'}, 0, exec_state); + CheckScopeChainNames( + ["catch_block_7", "catch_block_7", undefined, undefined, undefined], + exec_state); +}; +catch_block_7(); +EndTest(); + + +BeginTest("Classes and methods 1"); + +listener_delegate = function(exec_state) { + "use strict" + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent({}, 1, exec_state); + CheckScopeChainNames(["m", undefined, undefined, undefined], exec_state); +}; + +(function() { + "use strict"; + class C1 { + m() { + debugger; + } + } + new C1().m(); +})(); + +EndTest(); + +BeginTest("Scope positions"); +var code1 = "function f() { \n" + + " var a = 1; \n" + + " function b() { \n" + + " debugger; \n" + + " return a + 1; \n" + + " } \n" + + " b(); \n" + + "} \n" + + "f(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChainPositions([{start: 58, end: 118}, {start: 10, end: 162}], + exec_state); +} +eval(code1); +EndTest(); + + +BeginTest("Scope positions in for statement"); +var code3 = "function for_statement() { \n" + + " for (let i = 0; i < 1; i++) { \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions([{start: 52, end: 111}, {start: 22, end: 145}], + exec_state); +} +eval(code3); +EndTest(); + +BeginTest("Scope positions in for statement with lexical block"); +var code4 = "function for_statement() { \n" + + " for (let i = 0; i < 1; i++) { \n" + + " let j; \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions([{start: 66, end: 147}, + {start: 52, end: 147}, + {start: 22, end: 181}], exec_state); +} +eval(code4); +EndTest(); + +BeginTest("Scope positions in lexical for each statement"); +var code5 = "function for_each_statement() { \n" + + " for (let i of [0]) { \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_each_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions([{start: 55, end: 111}, {start: 27, end: 145}], + exec_state); +} +eval(code5); +EndTest(); + +BeginTest("Scope positions in lexical for each statement with lexical block"); +var code6 = "function for_each_statement() { \n" + + " for (let i of [0]) { \n" + + " let j; \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_each_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions([{start: 57, end: 147}, + {start: 55, end: 147}, + {start: 27, end: 181}], exec_state); +} +eval(code6); +EndTest(); + +BeginTest("Scope positions in non-lexical for each statement"); +var code7 = "function for_each_statement() { \n" + + " var i; \n" + + " for (i of [0]) { \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_each_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions([{start: 27, end: 181}], exec_state); +} +eval(code7); +EndTest(); + +BeginTest( + "Scope positions in non-lexical for each statement with lexical block"); +var code8 = "function for_each_statement() { \n" + + " var i; \n" + + " for (i of [0]) { \n" + + " let j; \n" + + " debugger; \n" + + " } \n" + + "} \n" + + "for_each_statement(); \n"; + +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Block, + debug.ScopeType.Local, + debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeChainPositions([{start: 89, end: 183}, {start: 27, end: 217}], + exec_state); +} +eval(code8); +EndTest(); + +assertEquals(begin_test_count, break_count, + 'one or more tests did not enter the debugger'); +assertEquals(begin_test_count, end_test_count, + 'one or more tests did not have its result checked'); diff --git a/deps/v8/test/debugger/debug/harmony/modules-debug-scopes2.js b/deps/v8/test/debugger/debug/harmony/modules-debug-scopes2.js new file mode 100644 index 0000000000..8b9b9e8aee --- /dev/null +++ b/deps/v8/test/debugger/debug/harmony/modules-debug-scopes2.js @@ -0,0 +1,185 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// MODULE + + +var Debug = debug.Debug; + +var test_name; +var listener_delegate; +var listener_called; +var exception; +var begin_test_count = 0; +var end_test_count = 0; +var break_count = 0; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + break_count++; + listener_called = true; + listener_delegate(exec_state); + } + } catch (e) { + exception = e; + } +} + +Debug.setListener(listener); + + +function BeginTest(name) { + test_name = name; + listener_delegate = null; + listener_called = false; + exception = null; + begin_test_count++; +} + +function EndTest() { + assertTrue(listener_called, "listener not called for " + test_name); + assertNull(exception, test_name + " / " + exception); + end_test_count++; +} + + +// Check that two scope are the same. +function assertScopeMirrorEquals(scope1, scope2) { + assertEquals(scope1.scopeType(), scope2.scopeType()); + assertEquals(scope1.frameIndex(), scope2.frameIndex()); + assertEquals(scope1.scopeIndex(), scope2.scopeIndex()); + assertPropertiesEqual(scope1.scopeObject().value(), + scope2.scopeObject().value()); +} + +function CheckFastAllScopes(scopes, exec_state) +{ + var fast_all_scopes = exec_state.frame().allScopes(true); + var length = fast_all_scopes.length; + assertTrue(scopes.length >= length); + for (var i = 0; i < scopes.length && i < length; i++) { + var scope = fast_all_scopes[length - i - 1]; + assertEquals(scopes[scopes.length - i - 1], scope.scopeType()); + } +} + + +// Check that the scope chain contains the expected types of scopes. +function CheckScopeChain(scopes, exec_state) { + var all_scopes = exec_state.frame().allScopes(); + assertEquals(scopes.length, exec_state.frame().scopeCount()); + assertEquals(scopes.length, all_scopes.length, "FrameMirror.allScopes length"); + for (var i = 0; i < scopes.length; i++) { + var scope = exec_state.frame().scope(i); + assertEquals(scopes[i], scope.scopeType()); + assertScopeMirrorEquals(all_scopes[i], scope); + } + CheckFastAllScopes(scopes, exec_state); +} + + +function CheckScopeDoesNotHave(properties, number, exec_state) { + var scope = exec_state.frame().scope(number); + for (var p of properties) { + var property_mirror = scope.scopeObject().property(p); + assertTrue(property_mirror.isUndefined(), + 'property ' + p + ' found in scope'); + } +} + + +// Check that the scope contains at least minimum_content. For functions just +// check that there is a function. +function CheckScopeContent(minimum_content, number, exec_state) { + var scope = exec_state.frame().scope(number); + var minimum_count = 0; + for (var p in minimum_content) { + var property_mirror = scope.scopeObject().property(p); + assertFalse(property_mirror.isUndefined(), + 'property ' + p + ' not found in scope'); + assertEquals(minimum_content[p], property_mirror.value().value(), + 'property ' + p + ' has unexpected value'); + minimum_count++; + } + + // 'arguments' and might be exposed in the local and closure scope. Just + // ignore this. + var scope_size = scope.scopeObject().properties().length; + if (!scope.scopeObject().property('arguments').isUndefined()) { + scope_size--; + } + // Ditto for 'this'. + if (!scope.scopeObject().property('this').isUndefined()) { + scope_size--; + } + // Temporary variables introduced by the parser have not been materialized. + assertTrue(scope.scopeObject().property('').isUndefined()); + + if (scope_size < minimum_count) { + print('Names found in scope:'); + var names = scope.scopeObject().propertyNames(); + for (var i = 0; i < names.length; i++) { + print(names[i]); + } + } + assertTrue(scope_size >= minimum_count); +} + + +//////////////////////////////////////////////////////////////////////////////// +// Actual tests. +//////////////////////////////////////////////////////////////////////////////// + + +BeginTest(); +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent( + {local_var: undefined, exported_var: undefined, imported_var: undefined}, + 0, exec_state); + CheckScopeDoesNotHave( + ["doesnotexist", "local_let", "exported_let", "imported_let"], + 0, exec_state); +}; +debugger; +EndTest(); + +let local_let = 1; +var local_var = 2; +export let exported_let = 3; +export var exported_var = 4; +import {exported_let as imported_let} from "modules-debug-scopes2.js"; +import {exported_var as imported_var} from "modules-debug-scopes2.js"; + +BeginTest(); +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent( + {local_let: 1, local_var: 2, exported_let: 3, exported_var: 4, + imported_let: 3, imported_var: 4}, 0, exec_state); +}; +debugger; +EndTest(); + +local_let += 10; +local_var += 10; +exported_let += 10; +exported_var += 10; + +BeginTest(); +listener_delegate = function(exec_state) { + CheckScopeChain([debug.ScopeType.Module, + debug.ScopeType.Script, + debug.ScopeType.Global], exec_state); + CheckScopeContent( + {local_let: 11, local_var: 12, exported_let: 13, exported_var: 14, + imported_let: 13, imported_var: 14}, 0, exec_state); +}; +debugger; +EndTest(); diff --git a/deps/v8/test/debugger/debug/ignition/debug-step-prefix-bytecodes.js b/deps/v8/test/debugger/debug/ignition/debug-step-prefix-bytecodes.js new file mode 100644 index 0000000000..b986be23e6 --- /dev/null +++ b/deps/v8/test/debugger/debug/ignition/debug-step-prefix-bytecodes.js @@ -0,0 +1,374 @@ +// Copyright 2011 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --ignition-filter=f + +// This test tests that full code compiled without debug break slots +// is recompiled with debug break slots when debugging is started. + +Debug = debug.Debug + +var done = false; +var step_count = 0; +var values = []; + +// Debug event listener which steps until the global variable done is true. +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + if (!done) exec_state.prepareStep(Debug.StepAction.StepNext); + step_count++; + } +}; + +// Set the global variables state to prpare the stepping test. +function prepare_step_test() { + done = false; + step_count = 0; +} + +// Test function to step through, uses widended bytecodes. +function f() { +var x = 10000000; +var y = x + 1; +var _aa = 0; values[_aa] = _aa; +var _ab = 1; values[_ab] = _ab; +var _ac = 2; values[_ac] = _ac; +var _ad = 3; values[_ad] = _ad; +var _ae = 4; values[_ae] = _ae; +var _af = 5; values[_af] = _af; +var _ag = 6; values[_ag] = _ag; +var _ah = 7; values[_ah] = _ah; +var _ai = 8; values[_ai] = _ai; +var _aj = 9; values[_aj] = _aj; +var _ak = 10; values[_ak] = _ak; +var _al = 11; values[_al] = _al; +var _am = 12; values[_am] = _am; +var _an = 13; values[_an] = _an; +var _ao = 14; values[_ao] = _ao; +var _ap = 15; values[_ap] = _ap; +var _ba = 16; values[_ba] = _ba; +var _bb = 17; values[_bb] = _bb; +var _bc = 18; values[_bc] = _bc; +var _bd = 19; values[_bd] = _bd; +var _be = 20; values[_be] = _be; +var _bf = 21; values[_bf] = _bf; +var _bg = 22; values[_bg] = _bg; +var _bh = 23; values[_bh] = _bh; +var _bi = 24; values[_bi] = _bi; +var _bj = 25; values[_bj] = _bj; +var _bk = 26; values[_bk] = _bk; +var _bl = 27; values[_bl] = _bl; +var _bm = 28; values[_bm] = _bm; +var _bn = 29; values[_bn] = _bn; +var _bo = 30; values[_bo] = _bo; +var _bp = 31; values[_bp] = _bp; +var _ca = 32; values[_ca] = _ca; +var _cb = 33; values[_cb] = _cb; +var _cc = 34; values[_cc] = _cc; +var _cd = 35; values[_cd] = _cd; +var _ce = 36; values[_ce] = _ce; +var _cf = 37; values[_cf] = _cf; +var _cg = 38; values[_cg] = _cg; +var _ch = 39; values[_ch] = _ch; +var _ci = 40; values[_ci] = _ci; +var _cj = 41; values[_cj] = _cj; +var _ck = 42; values[_ck] = _ck; +var _cl = 43; values[_cl] = _cl; +var _cm = 44; values[_cm] = _cm; +var _cn = 45; values[_cn] = _cn; +var _co = 46; values[_co] = _co; +var _cp = 47; values[_cp] = _cp; +var _da = 48; values[_da] = _da; +var _db = 49; values[_db] = _db; +var _dc = 50; values[_dc] = _dc; +var _dd = 51; values[_dd] = _dd; +var _de = 52; values[_de] = _de; +var _df = 53; values[_df] = _df; +var _dg = 54; values[_dg] = _dg; +var _dh = 55; values[_dh] = _dh; +var _di = 56; values[_di] = _di; +var _dj = 57; values[_dj] = _dj; +var _dk = 58; values[_dk] = _dk; +var _dl = 59; values[_dl] = _dl; +var _dm = 60; values[_dm] = _dm; +var _dn = 61; values[_dn] = _dn; +var _do = 62; values[_do] = _do; +var _dp = 63; values[_dp] = _dp; +var _ea = 64; values[_ea] = _ea; +var _eb = 65; values[_eb] = _eb; +var _ec = 66; values[_ec] = _ec; +var _ed = 67; values[_ed] = _ed; +var _ee = 68; values[_ee] = _ee; +var _ef = 69; values[_ef] = _ef; +var _eg = 70; values[_eg] = _eg; +var _eh = 71; values[_eh] = _eh; +var _ei = 72; values[_ei] = _ei; +var _ej = 73; values[_ej] = _ej; +var _ek = 74; values[_ek] = _ek; +var _el = 75; values[_el] = _el; +var _em = 76; values[_em] = _em; +var _en = 77; values[_en] = _en; +var _eo = 78; values[_eo] = _eo; +var _ep = 79; values[_ep] = _ep; +var _fa = 80; values[_fa] = _fa; +var _fb = 81; values[_fb] = _fb; +var _fc = 82; values[_fc] = _fc; +var _fd = 83; values[_fd] = _fd; +var _fe = 84; values[_fe] = _fe; +var _ff = 85; values[_ff] = _ff; +var _fg = 86; values[_fg] = _fg; +var _fh = 87; values[_fh] = _fh; +var _fi = 88; values[_fi] = _fi; +var _fj = 89; values[_fj] = _fj; +var _fk = 90; values[_fk] = _fk; +var _fl = 91; values[_fl] = _fl; +var _fm = 92; values[_fm] = _fm; +var _fn = 93; values[_fn] = _fn; +var _fo = 94; values[_fo] = _fo; +var _fp = 95; values[_fp] = _fp; +var _ga = 96; values[_ga] = _ga; +var _gb = 97; values[_gb] = _gb; +var _gc = 98; values[_gc] = _gc; +var _gd = 99; values[_gd] = _gd; +var _ge = 100; values[_ge] = _ge; +var _gf = 101; values[_gf] = _gf; +var _gg = 102; values[_gg] = _gg; +var _gh = 103; values[_gh] = _gh; +var _gi = 104; values[_gi] = _gi; +var _gj = 105; values[_gj] = _gj; +var _gk = 106; values[_gk] = _gk; +var _gl = 107; values[_gl] = _gl; +var _gm = 108; values[_gm] = _gm; +var _gn = 109; values[_gn] = _gn; +var _go = 110; values[_go] = _go; +var _gp = 111; values[_gp] = _gp; +var _ha = 112; values[_ha] = _ha; +var _hb = 113; values[_hb] = _hb; +var _hc = 114; values[_hc] = _hc; +var _hd = 115; values[_hd] = _hd; +var _he = 116; values[_he] = _he; +var _hf = 117; values[_hf] = _hf; +var _hg = 118; values[_hg] = _hg; +var _hh = 119; values[_hh] = _hh; +var _hi = 120; values[_hi] = _hi; +var _hj = 121; values[_hj] = _hj; +var _hk = 122; values[_hk] = _hk; +var _hl = 123; values[_hl] = _hl; +var _hm = 124; values[_hm] = _hm; +var _hn = 125; values[_hn] = _hn; +var _ho = 126; values[_ho] = _ho; +var _hp = 127; values[_hp] = _hp; +var _ia = 128; values[_ia] = _ia; +var _ib = 129; values[_ib] = _ib; +var _ic = 130; values[_ic] = _ic; +var _id = 131; values[_id] = _id; +var _ie = 132; values[_ie] = _ie; +var _if = 133; values[_if] = _if; +var _ig = 134; values[_ig] = _ig; +var _ih = 135; values[_ih] = _ih; +var _ii = 136; values[_ii] = _ii; +var _ij = 137; values[_ij] = _ij; +var _ik = 138; values[_ik] = _ik; +var _il = 139; values[_il] = _il; +var _im = 140; values[_im] = _im; +var _in = 141; values[_in] = _in; +var _io = 142; values[_io] = _io; +var _ip = 143; values[_ip] = _ip; +var _ja = 144; values[_ja] = _ja; +var _jb = 145; values[_jb] = _jb; +var _jc = 146; values[_jc] = _jc; +var _jd = 147; values[_jd] = _jd; +var _je = 148; values[_je] = _je; +var _jf = 149; values[_jf] = _jf; +var _jg = 150; values[_jg] = _jg; +var _jh = 151; values[_jh] = _jh; +var _ji = 152; values[_ji] = _ji; +var _jj = 153; values[_jj] = _jj; +var _jk = 154; values[_jk] = _jk; +var _jl = 155; values[_jl] = _jl; +var _jm = 156; values[_jm] = _jm; +var _jn = 157; values[_jn] = _jn; +var _jo = 158; values[_jo] = _jo; +var _jp = 159; values[_jp] = _jp; +var _ka = 160; values[_ka] = _ka; +var _kb = 161; values[_kb] = _kb; +var _kc = 162; values[_kc] = _kc; +var _kd = 163; values[_kd] = _kd; +var _ke = 164; values[_ke] = _ke; +var _kf = 165; values[_kf] = _kf; +var _kg = 166; values[_kg] = _kg; +var _kh = 167; values[_kh] = _kh; +var _ki = 168; values[_ki] = _ki; +var _kj = 169; values[_kj] = _kj; +var _kk = 170; values[_kk] = _kk; +var _kl = 171; values[_kl] = _kl; +var _km = 172; values[_km] = _km; +var _kn = 173; values[_kn] = _kn; +var _ko = 174; values[_ko] = _ko; +var _kp = 175; values[_kp] = _kp; +var _la = 176; values[_la] = _la; +var _lb = 177; values[_lb] = _lb; +var _lc = 178; values[_lc] = _lc; +var _ld = 179; values[_ld] = _ld; +var _le = 180; values[_le] = _le; +var _lf = 181; values[_lf] = _lf; +var _lg = 182; values[_lg] = _lg; +var _lh = 183; values[_lh] = _lh; +var _li = 184; values[_li] = _li; +var _lj = 185; values[_lj] = _lj; +var _lk = 186; values[_lk] = _lk; +var _ll = 187; values[_ll] = _ll; +var _lm = 188; values[_lm] = _lm; +var _ln = 189; values[_ln] = _ln; +var _lo = 190; values[_lo] = _lo; +var _lp = 191; values[_lp] = _lp; +var _ma = 192; values[_ma] = _ma; +var _mb = 193; values[_mb] = _mb; +var _mc = 194; values[_mc] = _mc; +var _md = 195; values[_md] = _md; +var _me = 196; values[_me] = _me; +var _mf = 197; values[_mf] = _mf; +var _mg = 198; values[_mg] = _mg; +var _mh = 199; values[_mh] = _mh; +var _mi = 200; values[_mi] = _mi; +var _mj = 201; values[_mj] = _mj; +var _mk = 202; values[_mk] = _mk; +var _ml = 203; values[_ml] = _ml; +var _mm = 204; values[_mm] = _mm; +var _mn = 205; values[_mn] = _mn; +var _mo = 206; values[_mo] = _mo; +var _mp = 207; values[_mp] = _mp; +var _na = 208; values[_na] = _na; +var _nb = 209; values[_nb] = _nb; +var _nc = 210; values[_nc] = _nc; +var _nd = 211; values[_nd] = _nd; +var _ne = 212; values[_ne] = _ne; +var _nf = 213; values[_nf] = _nf; +var _ng = 214; values[_ng] = _ng; +var _nh = 215; values[_nh] = _nh; +var _ni = 216; values[_ni] = _ni; +var _nj = 217; values[_nj] = _nj; +var _nk = 218; values[_nk] = _nk; +var _nl = 219; values[_nl] = _nl; +var _nm = 220; values[_nm] = _nm; +var _nn = 221; values[_nn] = _nn; +var _no = 222; values[_no] = _no; +var _np = 223; values[_np] = _np; +var _oa = 224; values[_oa] = _oa; +var _ob = 225; values[_ob] = _ob; +var _oc = 226; values[_oc] = _oc; +var _od = 227; values[_od] = _od; +var _oe = 228; values[_oe] = _oe; +var _of = 229; values[_of] = _of; +var _og = 230; values[_og] = _og; +var _oh = 231; values[_oh] = _oh; +var _oi = 232; values[_oi] = _oi; +var _oj = 233; values[_oj] = _oj; +var _ok = 234; values[_ok] = _ok; +var _ol = 235; values[_ol] = _ol; +var _om = 236; values[_om] = _om; +var _on = 237; values[_on] = _on; +var _oo = 238; values[_oo] = _oo; +var _op = 239; values[_op] = _op; +var _pa = 240; values[_pa] = _pa; +var _pb = 241; values[_pb] = _pb; +var _pc = 242; values[_pc] = _pc; +var _pd = 243; values[_pd] = _pd; +var _pe = 244; values[_pe] = _pe; +var _pf = 245; values[_pf] = _pf; +var _pg = 246; values[_pg] = _pg; +var _ph = 247; values[_ph] = _ph; +var _pi = 248; values[_pi] = _pi; +var _pj = 249; values[_pj] = _pj; +var _pk = 250; values[_pk] = _pk; +var _pl = 251; values[_pl] = _pl; +var _pm = 252; values[_pm] = _pm; +var _pn = 253; values[_pn] = _pn; +var _po = 254; values[_po] = _po; +var _pp = 255; values[_pp] = _pp; +var _qa = 256; values[_qa] = _qa; +var _qb = 257; values[_qb] = _qb; +var _qc = 258; values[_qc] = _qc; +var _qd = 259; values[_qd] = _qd; +var _qe = 260; values[_qe] = _qe; +var _qf = 261; values[_qf] = _qf; +var _qg = 262; values[_qg] = _qg; +var _qh = 263; values[_qh] = _qh; +var _qi = 264; values[_qi] = _qi; +var _qj = 265; values[_qj] = _qj; +var _qk = 266; values[_qk] = _qk; +var _ql = 267; values[_ql] = _ql; +var _qm = 268; values[_qm] = _qm; +var _qn = 269; values[_qn] = _qn; +var _qo = 270; values[_qo] = _qo; +var _qp = 271; values[_qp] = _qp; +var _ra = 272; values[_ra] = _ra; +var _rb = 273; values[_rb] = _rb; +var _rc = 274; values[_rc] = _rc; +var _rd = 275; values[_rd] = _rd; +var _re = 276; values[_re] = _re; +var _rf = 277; values[_rf] = _rf; +var _rg = 278; values[_rg] = _rg; +var _rh = 279; values[_rh] = _rh; +var _ri = 280; values[_ri] = _ri; +var _rj = 281; values[_rj] = _rj; +var _rk = 282; values[_rk] = _rk; +var _rl = 283; values[_rl] = _rl; +var _rm = 284; values[_rm] = _rm; +var _rn = 285; values[_rn] = _rn; +var _ro = 286; values[_ro] = _ro; +var _rp = 287; values[_rp] = _rp; + done = true; +}; + +function check_values() { + for (var i = 0; i < values.length; i++) { + assertEquals(values[i], i); + values[i] = -i; + } +} + +// Pass 1 - no debugger, no steps seen +prepare_step_test(); +f(); +check_values(); +assertEquals(0, step_count); + +// Pass 2 - debugger attached and stepping from BP +Debug.setListener(listener); +var bp = Debug.setBreakPoint(f, 1); +prepare_step_test(); +f(); +check_values(); +assertEquals(580, step_count); +Debug.clearBreakPoint(bp); + +// Pass 3 - debugger attached and no BP +prepare_step_test(); +f(); +check_values(); +assertEquals(0, step_count); diff --git a/deps/v8/test/debugger/debug/ignition/elided-instruction.js b/deps/v8/test/debugger/debug/ignition/elided-instruction.js new file mode 100644 index 0000000000..53bf624103 --- /dev/null +++ b/deps/v8/test/debugger/debug/ignition/elided-instruction.js @@ -0,0 +1,36 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +Debug = debug.Debug + +var exception = null; +var break_count = 0; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + print(event_data.sourceLineText()); + var column = event_data.sourceColumn(); + assertTrue(event_data.sourceLineText().indexOf( + `Break ${break_count++}. ${column}.`) > 0); + exec_state.prepareStep(Debug.StepAction.StepIn); + } catch (e) { + print(e + e.stack); + exception = e; + } +}; + +function f() { + var a = 1; // Break 2. 10. + return a; // Break 3. 2. +} // Break 4. 0. + +Debug.setListener(listener); +debugger; // Break 0. 0. +f(); // Break 1. 0. +Debug.setListener(null); // Break 5. 0. + +assertNull(exception); +assertEquals(6, break_count); diff --git a/deps/v8/test/debugger/debug/ignition/optimized-debug-frame.js b/deps/v8/test/debugger/debug/ignition/optimized-debug-frame.js new file mode 100644 index 0000000000..cc85b4786a --- /dev/null +++ b/deps/v8/test/debugger/debug/ignition/optimized-debug-frame.js @@ -0,0 +1,37 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test that PC in optimized frame would correctly translate into +// unoptimized frame when retrieving frame information in the debugger. + +function f() { + debugger; +} + +function g(x) { + return f(); +} + +var break_count = 0; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + assertEquals(14, exec_state.frame(1).sourceLine()); + assertEquals(9, exec_state.frame(1).sourceColumn()); + break_count++; +} + +g(); +g(); +%OptimizeFunctionOnNextCall(g); + +var Debug = debug.Debug; +Debug.setListener(listener); + +g(); + +Debug.setListener(null); + +assertEquals(1, break_count); diff --git a/deps/v8/test/debugger/debug/regress-5207.js b/deps/v8/test/debugger/debug/regress-5207.js new file mode 100644 index 0000000000..f2b3d7c28f --- /dev/null +++ b/deps/v8/test/debugger/debug/regress-5207.js @@ -0,0 +1,31 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Flags: --noanalyze-environment-liveness + + +'use strict'; +var Debug = debug.Debug; +var exception = null; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var scopes = exec_state.frame(0).allScopes(); + assertEquals(debug.ScopeType.Eval, scopes[0].scopeType()); + assertEquals(1, scopes[0].scopeObject().value().a); + assertEquals(debug.ScopeType.Script, scopes[1].scopeType()); + assertEquals(undefined, scopes[1].scopeObject().value().a); + assertEquals(debug.ScopeType.Global, scopes[2].scopeType()); + assertEquals(undefined, scopes[2].scopeObject().value().a); + } catch (e) { + exception = e; + } +} + +Debug.setListener(listener); +// Eval inherits strict mode. +eval("var a = 1; debugger;"); +Debug.setListener(null); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/regress/regress-102153.js b/deps/v8/test/debugger/debug/regress/regress-102153.js new file mode 100644 index 0000000000..af66245a89 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-102153.js @@ -0,0 +1,56 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Test that the break point is set before initializing the loop variable +// so that we break before any iteration has been run. + +Debug = debug.Debug; + +var break_hit = false; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) { + break_hit = true; + } +} + +Debug.setListener(listener); + +function test() { + for (var i = 0; i < 3; i++) { // Break here. + if (i == 0) break; + } +} + +Debug.setBreakPoint(test, 1, 0); + +assertTrue(Debug.showBreakPoints(test).indexOf("// Break here.") >= 0); + +test(); + +assertTrue(break_hit); diff --git a/deps/v8/test/debugger/debug/regress/regress-1081309.js b/deps/v8/test/debugger/debug/regress/regress-1081309.js new file mode 100644 index 0000000000..5e4cd88216 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-1081309.js @@ -0,0 +1,72 @@ +// Copyright 2008 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Debug = debug.Debug + +// Make sure that the backtrace command can be processed when the receiver is +// undefined. +listenerCalled = false; +exception = false; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Exception) { + // The expected backtrace is + // 1: g + // 0: [anonymous] + + assertEquals(2, exec_state.frameCount()); + assertEquals("g", exec_state.frame(0).func().name()); + assertEquals("", exec_state.frame(1).func().name()); + + listenerCalled = true; + } + } catch (e) { + print(e); + exception = e + }; +}; + +// Add the debug event listener. +Debug.setListener(listener); + +// Call method on undefined. +function g() { + (void 0).f(); +}; + +// Break on the exception to do a backtrace with undefined as receiver. +Debug.setBreakOnException(true); +try { + g(); +} catch(e) { + // Ignore the exception "Cannot call method 'x' of undefined" +} + +assertFalse(exception, "exception in listener", exception) +// Make sure that the debug event listener vas invoked. +assertTrue(listenerCalled, "listener not called"); diff --git a/deps/v8/test/debugger/debug/regress/regress-109195.js b/deps/v8/test/debugger/debug/regress/regress-109195.js new file mode 100644 index 0000000000..abf31d6125 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-109195.js @@ -0,0 +1,65 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +var Debug = debug.Debug; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + for (var i = 0, n = exec_state.frameCount(); i < n; i++) { + exec_state.frame().scopeCount(i); + } + exec_state.prepareStep(Debug.StepAction.StepNext); +} + +Debug.setListener(listener); + +var F = function () { + 1, function () { + var d = 0; + (function () { d; }); + debugger; + }(); +}; + +var src = "(" + F.toString() + ")()"; +eval(src); + +Function.prototype.__defineGetter__("f", function () { + debugger; + return 0; +}); + +var G = function () { + 1, function () { + var d = 0; + (function () { d; }); + debugger; + }['f']; +}; + +var src = "(" + G.toString() + ")()"; +eval(src); diff --git a/deps/v8/test/debugger/debug/regress/regress-119609.js b/deps/v8/test/debugger/debug/regress/regress-119609.js new file mode 100644 index 0000000000..b6da891fb0 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-119609.js @@ -0,0 +1,66 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug; + +var exception = false; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + function lookup(name) { + return exec_state.frame(0).evaluate(name).value(); + } + + assertEquals(3, lookup("e")); + assertEquals(4, lookup("f")); + assertEquals(1, lookup("a")); + + assertThrows(() => lookup("b"), ReferenceError); + } + } catch (e) { + exception = e.toString() + e.stack; + } +} + +Debug.setListener(listener); + +function f(a, b) { + var c = 3; + function d(e, f) { + var g = a; + var h = c; + debugger; + } + + return d; +} + +f(1, 2)(3, 4); + +assertFalse(exception); diff --git a/deps/v8/test/debugger/debug/regress/regress-131994.js b/deps/v8/test/debugger/debug/regress/regress-131994.js index ed90f62b6f..66bde74b25 100644 --- a/deps/v8/test/debugger/debug/regress/regress-131994.js +++ b/deps/v8/test/debugger/debug/regress/regress-131994.js @@ -24,6 +24,8 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Flags: --noanalyze-environment-liveness // Test that a variable in the local scope that shadows a context-allocated diff --git a/deps/v8/test/debugger/debug/regress/regress-94873.js b/deps/v8/test/debugger/debug/regress/regress-1639.js index ea71e8ebb9..eaaca5176d 100644 --- a/deps/v8/test/debugger/debug/regress/regress-94873.js +++ b/deps/v8/test/debugger/debug/regress/regress-1639.js @@ -1,4 +1,4 @@ -// Copyright 2011 the V8 project authors. All rights reserved. +// Copyright 2012 the V8 project authors. All rights reserved. // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: @@ -25,15 +25,9 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Debug = debug.Debug; - -function sendCommand(state, cmd) { - // Get the debug command processor in paused state. - var dcp = state.debugCommandProcessor(false); - var request = JSON.stringify(cmd); - var response = dcp.processDebugJSONRequest(request); - return JSON.parse(response); -} +Debug = debug.Debug +var breaks = 0; +var exception = false; function listener(event, exec_state, event_data, data) { try { @@ -41,36 +35,41 @@ function listener(event, exec_state, event_data, data) { var line = event_data.sourceLineText(); print('break: ' + line); - var frame = sendCommand(exec_state, { - seq: 0, - type: "request", - command: "frame" - }); - - sendCommand(exec_state, { - seq: 0, - type: "request", - command: "evaluate", - arguments: { - expression: "obj.x.toString()", - additional_context: [{ - name: "obj", - handle: frame.body.receiver.ref - }] - } - }); + assertEquals(-1, line.indexOf('NOBREAK'), + "should not break on unexpected lines") + assertEquals('BREAK ' + breaks, line.substr(-7)); + breaks++; + if (breaks < 4) exec_state.prepareStep(Debug.StepAction.StepNext); } } catch (e) { print(e); + exception = true; } } +// Add the debug event listener. Debug.setListener(listener); -function a(x, y) { - this.x = x; - this.y = y; +function a(f) { + if (f) { // NOBREAK: should not break here! + try { + f(); + } catch(e) { + } + } +} // BREAK 2 + +function b() { + c(); // BREAK 0 +} // BREAK 1 + +function c() { + a(); } -Debug.setBreakPoint(a, 0, 0); -new a(1, 2); +// Set a break point and call to invoke the debug event listener. +Debug.setBreakPoint(b, 0, 0); +a(b); +a(); // BREAK 3 + +assertFalse(exception); diff --git a/deps/v8/test/debugger/debug/regress/regress-1853.js b/deps/v8/test/debugger/debug/regress/regress-1853.js new file mode 100644 index 0000000000..8c6e9404a7 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-1853.js @@ -0,0 +1,99 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +// Test whether scripts compiled after setting the break point are +// updated correctly. + +Debug = debug.Debug; + +var break_count = 0; +var test_break_1 = false; +var test_break_2 = false; + +function setBreakPointByName(state) { + var scripts = Debug.scripts(); + for (var script of scripts) { + if (script.source_url == "testScriptOne") { + Debug.setScriptBreakPointById(script.id, 2); + } + } +} + +function setBreakPointByRegExp(state) { + var scripts = Debug.scripts(); + for (var script of scripts) { + if (/Scrip.Two/.test(script.source_url)) { + Debug.setScriptBreakPointById(script.id, 2); + } + } +} + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + switch (break_count) { + case 0: + // Set break points before the code has been compiled. + setBreakPointByName(exec_state); + setBreakPointByRegExp(exec_state); + break; + case 1: + // Set the flag to prove that we hit the first break point. + test_break_1 = true; + break; + case 2: + // Set the flag to prove that we hit the second break point. + test_break_2 = true; + break; + } + break_count++; + } + } catch (e) { + print(e); + } +} + +Debug.setListener(listener); + +eval('function test1() { \n' + + ' assertFalse(test_break_1); \n' + + ' assertTrue(test_break_1); \n' + + '} \n' + + '//# sourceURL=testScriptOne'); + +eval('function test2() { \n' + + ' assertFalse(test_break_2); \n' + + ' assertTrue(test_break_2); \n' + + '} \n' + + '//# sourceURL=testScriptTwo'); + +debugger; + +test1(); +test2(); +assertEquals(3, break_count); diff --git a/deps/v8/test/debugger/debug/regress/regress-2296.js b/deps/v8/test/debugger/debug/regress/regress-2296.js new file mode 100644 index 0000000000..230d042e3e --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-2296.js @@ -0,0 +1,43 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug + +function listener(event, exec_state, event_data, data) { + try { + event_data.script().setSource(1); + } catch (e) { + assertTrue(String(e).indexOf("Source is not a string") > 0); + } +}; + +Debug.setListener(listener); + +eval('0'); + +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/regress/regress-3960.js b/deps/v8/test/debugger/debug/regress/regress-3960.js new file mode 100644 index 0000000000..6580d4b805 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-3960.js @@ -0,0 +1,35 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +// Test that setting break point works correctly when the debugger is +// activated late, which leads to duplicate shared function infos. + +(function() { + var Debug = %GetDebugContext().Debug; + + function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + assertTrue(/foo/.test(exec_state.frame(0).sourceLineText())); + break_count++; + } catch (e) { + exception = e; + } + } + + for (var i = 0; i < 3; i++) { + var foo = function() { a = 1; } + var exception = null; + var break_count = 0; + Debug.setListener(listener); + if (i < 2) Debug.setBreakPoint(foo, 0, 0); + assertTrue(/\[B\d\]a = 1/.test(Debug.showBreakPoints(foo))); + foo(); + assertEquals(1, break_count); + assertNull(exception); + } + + Debug.setListener(null); +})(); diff --git a/deps/v8/test/debugger/debug/regress/regress-419663.js b/deps/v8/test/debugger/debug/regress/regress-419663.js new file mode 100644 index 0000000000..51bd85aa2e --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-419663.js @@ -0,0 +1,32 @@ +// Copyright 2012 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +var o = { + f: function(x) { + var a = x + 1; + o = 1; + } +} + +function sentinel() {} + +var Debug = debug.Debug; + +Debug.setListener(function() {}); + +var script = Debug.findScript(sentinel); + +// Used in Debug.setScriptBreakPointById. +var p = Debug.findScriptSourcePosition(script, 8, 0); +var q = Debug.setBreakPointByScriptIdAndPosition(script.id, p).actual_position; + +function assertLocation(p, l, c) { + var location = script.locationFromPosition(p, false); + assertEquals(l, location.line); + assertEquals(c, location.column); +} + +assertLocation(p, 8, 0); +assertLocation(q, 8, 4); diff --git a/deps/v8/test/debugger/debug/regress/regress-4309-2.js b/deps/v8/test/debugger/debug/regress/regress-4309-2.js new file mode 100644 index 0000000000..e93c8ec56e --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-4309-2.js @@ -0,0 +1,33 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +var Debug = debug.Debug; + +var exception = null; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var scope = exec_state.frame().scope(0); + assertEquals(5, scope.scopeObject().property("i").value().value()); + } catch (e) { + exception = e; + } +} + +function f() { + eval('var i = 5'); + debugger; +} + +f(); +f(); + +%OptimizeFunctionOnNextCall(f); +Debug.setListener(listener); + +f(); + +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/regress/regress-5071.js b/deps/v8/test/debugger/debug/regress/regress-5071.js index 4ad1d7ed7c..54557fe366 100644 --- a/deps/v8/test/debugger/debug/regress/regress-5071.js +++ b/deps/v8/test/debugger/debug/regress/regress-5071.js @@ -1,6 +1,8 @@ // Copyright 2016 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// +// Flags: --noanalyze-environment-liveness var Debug = debug.Debug; diff --git a/deps/v8/test/debugger/debug/regress/regress-5164.js b/deps/v8/test/debugger/debug/regress/regress-5164.js new file mode 100644 index 0000000000..2ac9d7a624 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-5164.js @@ -0,0 +1,43 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +var failure = null; +var args; + +function listener(event, exec_state, event_data, data) { + if (event != debug.Debug.DebugEvent.Break) return; + try { + args = exec_state.frame(0).evaluate('arguments').value(); + } catch (e) { + failure = e; + } +} + +debug.Debug.setListener(listener); + +function* gen(a, b) { + debugger; + yield a; + yield b; +} + +var foo = gen(1, 2); + +foo.next() +assertEquals(2, args.length); +assertEquals(undefined, args[0]); +assertEquals(undefined, args[1]); + +foo.next() +assertEquals(2, args.length); +assertEquals(undefined, args[0]); +assertEquals(undefined, args[1]); + +foo.next() +assertEquals(2, args.length); +assertEquals(undefined, args[0]); +assertEquals(undefined, args[1]); + +assertNull(failure); diff --git a/deps/v8/test/debugger/debug/regress/regress-617882.js b/deps/v8/test/debugger/debug/regress/regress-617882.js index acc332c59b..21c8ef4588 100644 --- a/deps/v8/test/debugger/debug/regress/regress-617882.js +++ b/deps/v8/test/debugger/debug/regress/regress-617882.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// Flags: --invoke-weak-callbacks --omit-quit --gc-interval=355 --expose-debug-as=debug +// Flags: --invoke-weak-callbacks --omit-quit --gc-interval=355 var __v_33 = {}; __v_4 = 70000; diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-119800.js b/deps/v8/test/debugger/debug/regress/regress-crbug-119800.js new file mode 100644 index 0000000000..b3f39b9aa8 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-119800.js @@ -0,0 +1,37 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +function f() { + print(1); + print(2); + print(3); +} + +var Debug = debug.Debug; +var exception = null; +var breaks = []; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + Debug.debuggerFlags().breakPointsActive.setValue(false); + breaks.push(exec_state.frame().sourceLineText().trimLeft()); + exec_state.prepareStep(Debug.StepAction.StepIn); + } catch (e) { + exception = e; + } +} + +Debug.setListener(listener); +Debug.setBreakPoint(f, 0, 0); + +f(); + +Debug.setListener(null); +Debug.debuggerFlags().breakPointsActive.setValue(true); + +assertNull(exception); +assertEquals(breaks, ["print(1);", "print(2);", "print(3);", "}", + "Debug.setListener(null);"]); diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-171715.js b/deps/v8/test/debugger/debug/regress/regress-crbug-171715.js new file mode 100644 index 0000000000..c50562e74b --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-171715.js @@ -0,0 +1,86 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug + +var error = null; +var test = 0; + +function check_v(expected, exec_state, frame_id) { + assertEquals(expected, exec_state.frame(frame_id).evaluate('v').value()); +} + +function listener(event, exec_state, event_data, data) { + try { + if (event != Debug.DebugEvent.Break) return; + test++; + if (test == 1) { + check_v('inner0', exec_state, 0); + check_v('inner0', exec_state, 1); + check_v('outer', exec_state, 2); + assertArrayEquals(["a", "b", "c"], + exec_state.frame(0).evaluate('arguments').value()); + } else if (test == 2) { + check_v('inner1', exec_state, 0); + check_v('inner1', exec_state, 1); + check_v('outer', exec_state, 2); + assertArrayEquals(["a", "b", "c"], + exec_state.frame(0).evaluate('arguments').value()); + } else { + assertEquals(3, test); + check_v('inner2', exec_state, 0); + check_v('inner1', exec_state, 1); + check_v('inner1', exec_state, 2); + check_v('outer', exec_state, 3); + assertArrayEquals(["x", "y", "z"], + exec_state.frame(0).evaluate('arguments').value()); + assertArrayEquals(["a", "b", "c"], + exec_state.frame(1).evaluate('arguments').value()); + } + } catch (e) { + error = e; + } +}; + +Debug.setListener(listener); + +var v = 'outer'; +(function() { // Test 1 and 2 + var v = 'inner0'; + eval("debugger; var v = 'inner1'; debugger;"); + assertEquals('inner1', v); // Overwritten by local eval. +})("a", "b", "c"); +assertNull(error); + +(function() { // Test 3 + var v = 'inner0'; // Local eval overwrites this value. + eval("var v = 'inner1'; " + + "(function() { var v = 'inner2'; debugger; })('x', 'y', 'z');"); + assertEquals('inner1', v); // Overwritten by local eval. +})("a", "b", "c"); +assertNull(error); diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-222893.js b/deps/v8/test/debugger/debug/regress/regress-crbug-222893.js new file mode 100644 index 0000000000..a0fc6d56fb --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-222893.js @@ -0,0 +1,63 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Flags: --noanalyze-environment-liveness + +Debug = debug.Debug + +var error = null; +var array = ["a", "b", "c"]; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + assertArrayEquals(array, + exec_state.frame(0).evaluate('arguments').value()); + } + } catch (e) { + error = e; + } +}; + +Debug.setListener(listener); + + +function f(a, b) { + arguments; + debugger; // Arguments object is already materialized. +} + +f.apply(this, array); +f("a", "b", "c"); +assertNull(error); + +function g(a, b) { + debugger; // Arguments object is not yet materialized. +} +g.apply(this, array); +g("a", "b", "c"); +assertNull(error); diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-405491.js b/deps/v8/test/debugger/debug/regress/regress-crbug-405491.js deleted file mode 100644 index b63378113f..0000000000 --- a/deps/v8/test/debugger/debug/regress/regress-crbug-405491.js +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright 2014 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Flags: --expose-debug-as 1 diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-424142.js b/deps/v8/test/debugger/debug/regress/regress-crbug-424142.js new file mode 100644 index 0000000000..261aa7de3c --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-424142.js @@ -0,0 +1,38 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +(function outer() { + var C = (function C_() { + var y = 1; + function CC() { + this.x = 0; + } + CC.prototype.f = function CCf() { + this.x += y; + return this.x; + }; + return CC; + })(); + + var c = new C(0); +}) + +function sentinel() {} + +Debug = debug.Debug; +Debug.setListener(function(){}); + +var script = Debug.findScript(sentinel); +var line = 14; +var line_start = Debug.findScriptSourcePosition(script, line, 0); +var line_end = Debug.findScriptSourcePosition(script, line + 1, 0) - 1; +var actual = Debug.setBreakPointByScriptIdAndPosition( + script.id, line_start).actual_position; +// Make sure the actual break position is within the line where we set +// the break point. +assertTrue(line_start <= actual); +assertTrue(actual <= line_end); + +Debug.setListener(null); diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-432493.js b/deps/v8/test/debugger/debug/regress/regress-crbug-432493.js new file mode 100644 index 0000000000..37a755886b --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-432493.js @@ -0,0 +1,56 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +function f() { + var a = 1; + var b = 2; + return a + b; +} + +var exception = null; +var break_count = 0; +var throw_count = 0; + +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + break_count++; + // Disable all breakpoints from within the debug event callback. + Debug.debuggerFlags().breakPointsActive.setValue(false); + } else if (event = Debug.DebugEvent.Exception) { + throw_count++; + // Enable all breakpoints from within the debug event callback. + Debug.debuggerFlags().breakPointsActive.setValue(true); + } + } catch (e) { + exception = e; + } +} + +Debug = debug.Debug; + +Debug.setListener(listener); +Debug.setBreakOnException(); +Debug.setBreakPoint(f, 2); + +f(); +f(); + +assertEquals(1, break_count); +assertEquals(0, throw_count); + +// Trigger exception event. +try { throw 1; } catch (e) {} + +f(); +f(); + +Debug.setListener(null); +Debug.clearBreakOnException(); +Debug.debuggerFlags().breakPointsActive.setValue(true); + +assertEquals(2, break_count); +assertEquals(1, throw_count); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-465298.js b/deps/v8/test/debugger/debug/regress/regress-crbug-465298.js new file mode 100644 index 0000000000..7ccdcd882f --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-465298.js @@ -0,0 +1,54 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --noturbo-osr --noturbo-inlining + +var stdlib = this; +var buffer = new ArrayBuffer(64 * 1024); +var foreign = { thrower: thrower, debugme: debugme } + +Debug = debug.Debug; + +var listenerCalled = false; +function listener(event, exec_state, event_data, data) { + try { + if (event == Debug.DebugEvent.Break) { + var frame = exec_state.frame(1); + assertEquals("foo", frame.func().name()); + listenerCalled = true; + } + } catch (e) { + print("Caught: " + e + " " + e.stack); + }; +} + +function thrower() { throw "boom"; } +function debugme() { Debug.setListener(listener); debugger; } + +function Module(stdlib, foreign, heap) { + "use asm"; + var thrower = foreign.thrower; + var debugme = foreign.debugme; + function foo(i) { + i = i|0; + var a = 101; // Local variables exist ... + var b = 102; // ... to make the debugger ... + var c = 103; // ... inspect them during break. + if (i > 0) { + debugme(); + i = 23; + } else { + thrower(); + i = 42; + } + return i|0; + } + return { foo: foo }; +} + +var m = Module(stdlib, foreign, buffer); + +assertThrows("m.foo(0)"); +assertEquals(23, m.foo(1)); +assertTrue(listenerCalled); diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-481896.js b/deps/v8/test/debugger/debug/regress/regress-crbug-481896.js new file mode 100644 index 0000000000..d12398070b --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-481896.js @@ -0,0 +1,55 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +function static() { + print("> static"); // Break +} + +var Debug = debug.Debug; +var exception = null; +var break_count = 0; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + print("breakpoint hit at " + exec_state.frame(0).sourceLineText()); + assertTrue(exec_state.frame(0).sourceLineText().indexOf("// Break") > 0); + break_count++; + } catch (e) { + exception = e; + } +} + +Debug.setListener(listener); + +function install() { + eval("this.dynamic = function dynamic() { \n" + + " print(\"> dynamic\"); // Break\n" + + "}\n" + + "//@ sourceURL=dynamicScript"); +} + +install(); + +var scripts = Debug.scripts(); +var dynamic_script; +var static_script; +for (var script of scripts) { + if (script.source_url == "dynamicScript") dynamic_script = script; + if (script.source_url == "staticScript") static_script = script; +} + +Debug.setScriptBreakPointById(dynamic_script.id, 1); +Debug.setScriptBreakPointById(static_script.id, 6); + +dynamic(); +static(); + +Debug.setListener(null); + +assertNull(exception); +assertEquals(2, break_count); + +//@ sourceURL=staticScript diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-487289.js b/deps/v8/test/debugger/debug/regress/regress-crbug-487289.js new file mode 100644 index 0000000000..b1815e4a2e --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-487289.js @@ -0,0 +1,19 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +var Debug = debug.Debug; +var receiver = null; + +Debug.setListener(function(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + receiver = exec_state.frame(0).evaluate('this').value(); +}); + +function f() { debugger; } + +var expected = {}; +f.call(expected); + +assertEquals(expected, receiver); diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-491943.js b/deps/v8/test/debugger/debug/regress/regress-crbug-491943.js new file mode 100644 index 0000000000..39b4a60e47 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-491943.js @@ -0,0 +1,24 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +var Debug = debug.Debug; +var receiver = null; + +Debug.setListener(function(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + receiver = exec_state.frame(0).evaluate('this').value(); +}); + + +function f() { + var context_local = 1; + (function() { return context_local; })(); + debugger; +} + +var expected = {}; +f.call(expected); + +assertEquals(expected, receiver); diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-517592.js b/deps/v8/test/debugger/debug/regress/regress-crbug-517592.js new file mode 100644 index 0000000000..c552cfa4f0 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-517592.js @@ -0,0 +1,36 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --min-preparse-length=10 + +var source = + "var foo = function foo() {\n" + + " return 1;\n" + + "}\n" + + "//@ sourceURL=test"; + +Debug = debug.Debug; +Debug.setListener(listener); +var exception = null; +var break_count = 0; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Break) break_count++; + if (event != Debug.DebugEvent.AfterCompile) return; + try { + var name = event_data.script().name(); + var id = event_data.script().id(); + assertEquals("test", name); + Debug.setScriptBreakPointById(id, 2); + } catch (e) { + exception = e; + } +} + +eval(source); + +assertEquals(0, break_count); +foo(); +assertEquals(1, break_count); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-568477-1.js b/deps/v8/test/debugger/debug/regress/regress-crbug-568477-1.js index bf1aacb88e..f9a7ba4275 100644 --- a/deps/v8/test/debugger/debug/regress/regress-crbug-568477-1.js +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-568477-1.js @@ -10,8 +10,9 @@ var log = []; function listener(event, exec_state, event_data, data) { if (event != Debug.DebugEvent.Break) return; try { - log.push(exec_state.frame(0).sourceLineText().trimLeft()); - exec_state.prepareStep(Debug.StepAction.StepNext); + var line = exec_state.frame(0).sourceLineText().trimLeft(); + log.push(line); + if (line == "debugger;") exec_state.prepareStep(Debug.StepAction.StepNext); } catch (e) { %AbortJS(e + "\n" + e.stack); } diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-568477-2.js b/deps/v8/test/debugger/debug/regress/regress-crbug-568477-2.js new file mode 100644 index 0000000000..0ea4b7ea38 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-568477-2.js @@ -0,0 +1,37 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +var Debug = debug.Debug; +var expected = ["debugger;", + "var x = y;", + "debugger;", + "var x = y;"]; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + var line = exec_state.frame(0).sourceLineText().trimLeft(); + assertEquals(expected.shift(), line); + if (line == "debugger;") exec_state.prepareStep(Debug.StepAction.StepNext); + } catch (e) { + %AbortJS(e + "\n" + e.stack); + } +} + +Debug.setListener(listener); + +function f() { + var a = 1; + debugger; + var x = y; + print(x); +} + +function call_f_with_deeper_stack() { + (() => () => () => f())()()(); +} + +new Promise(f).catch(call_f_with_deeper_stack); +var a = 1; diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-568477-3.js b/deps/v8/test/debugger/debug/regress/regress-crbug-568477-3.js index cd4c60df3e..fcc16bf9d0 100644 --- a/deps/v8/test/debugger/debug/regress/regress-crbug-568477-3.js +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-568477-3.js @@ -10,8 +10,9 @@ var log = []; function listener(event, exec_state, event_data, data) { if (event != Debug.DebugEvent.Break) return; try { - log.push(exec_state.frame(0).sourceLineText().trimLeft()); - exec_state.prepareStep(Debug.StepAction.StepNext); + var line = exec_state.frame(0).sourceLineText().trimLeft(); + log.push(line); + if (line == "debugger;") exec_state.prepareStep(Debug.StepAction.StepNext); } catch (e) { %AbortJS(e + "\n" + e.stack); } diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-568477-4.js b/deps/v8/test/debugger/debug/regress/regress-crbug-568477-4.js index 706e6c8ebb..95bc939ef2 100644 --- a/deps/v8/test/debugger/debug/regress/regress-crbug-568477-4.js +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-568477-4.js @@ -4,15 +4,15 @@ var Debug = debug.Debug; -var expected = - ["debugger;", "var x = y;", "var b = 2;", "Debug.setListener(null);"]; +var expected = ["debugger;", "var x = y;"]; var log = []; function listener(event, exec_state, event_data, data) { if (event != Debug.DebugEvent.Break) return; try { - log.push(exec_state.frame(0).sourceLineText().trimLeft()); - exec_state.prepareStep(Debug.StepAction.StepNext); + var line = exec_state.frame(0).sourceLineText().trimLeft(); + log.push(line); + if (line == "debugger;") exec_state.prepareStep(Debug.StepAction.StepNext); } catch (e) { %AbortJS(e + "\n" + e.stack); } diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-605581.js b/deps/v8/test/debugger/debug/regress/regress-crbug-605581.js new file mode 100644 index 0000000000..f151b921b8 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-605581.js @@ -0,0 +1,27 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +var Debug = debug.Debug; +var exception = null; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + assertThrows(() => exec_state.frame(0).evaluate("bar.baz"), ReferenceError); + } catch (e) { + exception = e; + } +} + +Debug.setListener(listener); + +(function() { + debugger; // bar is still in TDZ at this point. + let bar = 1; + (x => bar); // force bar to be context-allocated. +})(); + +Debug.setListener(null); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/regress/regress-crbug-621361.js b/deps/v8/test/debugger/debug/regress/regress-crbug-621361.js new file mode 100644 index 0000000000..b66767f1ea --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-crbug-621361.js @@ -0,0 +1,39 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + + +var Debug = debug.Debug; +var steps = 0; +var exception = null; + +function listener(event, execState, eventData, data) { + if (event != Debug.DebugEvent.Break) return; + try { + assertEquals([ debug.ScopeType.Local, + debug.ScopeType.Script, + debug.ScopeType.Global], + execState.frame().allScopes().map(s => s.scopeType())); + var x_value = execState.frame().evaluate("String(x)").value(); + if (steps < 2) { + assertEquals("undefined", x_value); + execState.prepareStep(Debug.StepAction.StepIn); + } else { + assertEquals("l => l", x_value); + } + steps++; + } catch (e) { + exception = e; + } +} + +Debug.setListener(listener); + +(function() { + debugger; + var x = l => l; +})(); + +Debug.setListener(null); +assertNull(exception); +assertEquals(3, steps); diff --git a/deps/v8/test/debugger/debug/regress/regress-debug-deopt-while-recompile.js b/deps/v8/test/debugger/debug/regress/regress-debug-deopt-while-recompile.js new file mode 100644 index 0000000000..e8336a8cf1 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-debug-deopt-while-recompile.js @@ -0,0 +1,83 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + try { + assertEquals("foo", exec_state.frame(0).evaluate("bar").value()); + } catch (e) { + exception = e; + }; + listened++; +}; + +var exception = null; +var listened = 0; + +var f = function() { + var bar = "foo"; + var baz = bar; // Break point should be here. + return bar; +} + +var g = function() { + var bar = "foo"; + var baz = bar; // Break point should be here. + return bar; +} + +f(); +f(); +g(); +g(); + +// Mark with builtin. +%OptimizeFunctionOnNextCall(f); +if (%IsConcurrentRecompilationSupported()) { + %OptimizeFunctionOnNextCall(g, "concurrent"); +} + +// Activate debugger. +Debug.setListener(listener); + + // Set break point. +Debug.setBreakPoint(f, 2, 0); +Debug.setBreakPoint(g, 2, 0); + +// Trigger break point. +f(); +g(); + +// Assert that break point is set at expected location. +assertTrue(Debug.showBreakPoints(f).indexOf("var baz = [B0]bar;") > 0); +assertTrue(Debug.showBreakPoints(g).indexOf("var baz = [B0]bar;") > 0); + +assertEquals(2, listened); +assertNull(exception); diff --git a/deps/v8/test/debugger/debug/regress/regress-frame-details-null-receiver.js b/deps/v8/test/debugger/debug/regress/regress-frame-details-null-receiver.js new file mode 100644 index 0000000000..2a6bbaedc8 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-frame-details-null-receiver.js @@ -0,0 +1,50 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +Debug = debug.Debug; +var listened = false; + +function listener(event, exec_state, event_data, data) { + if (event == Debug.DebugEvent.Exception) { + for (var i = 0; i < exec_state.frameCount(); i++) { + print(exec_state.frame(i).receiver()); + print(exec_state.frame(i).func().name()); + } + } + listened = true; +} + +Debug.setListener(listener); +Debug.setBreakOnException(); + +assertThrows(function() { delete null['foo']; }); + +Debug.clearBreakOnException(); +Debug.setListener(null); + +assertTrue(listened); diff --git a/deps/v8/test/debugger/debug/regress/regress-prepare-break-while-recompile.js b/deps/v8/test/debugger/debug/regress/regress-prepare-break-while-recompile.js new file mode 100644 index 0000000000..b93de76a65 --- /dev/null +++ b/deps/v8/test/debugger/debug/regress/regress-prepare-break-while-recompile.js @@ -0,0 +1,70 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Flags: --concurrent-recompilation --block-concurrent-recompilation + +if (!%IsConcurrentRecompilationSupported()) { + print("Concurrent recompilation is disabled. Skipping this test."); + quit(); +} + +Debug = debug.Debug + +function foo() { + var x = 1; + return x; +} + +function bar() { + var x = 2; + return x; +} + +foo(); +%BaselineFunctionOnNextCall(foo); +foo(); +// Mark and kick off recompilation. +%OptimizeFunctionOnNextCall(foo, "concurrent"); +foo(); + +// Set break points on an unrelated function. This clears both optimized +// and (shared) unoptimized code on foo, and sets both to lazy-compile builtin. +// Clear the break point immediately after to deactivate the debugger. +// Do all of this after compile graph has been created. +Debug.setListener(function(){}); +Debug.setBreakPoint(bar, 0, 0); +Debug.clearAllBreakPoints(); +Debug.setListener(null); + +// At this point, concurrent recompilation is still blocked. +assertUnoptimized(foo, "no sync"); +// Let concurrent recompilation proceed. +%UnblockConcurrentRecompilation(); + +// Install optimized code when concurrent optimization finishes. +// This needs to be able to deal with shared code being a builtin. +assertUnoptimized(foo, "sync"); diff --git a/deps/v8/test/debugger/debug/wasm/frame-inspection.js b/deps/v8/test/debugger/debug/wasm/frame-inspection.js new file mode 100644 index 0000000000..45fa8a96f4 --- /dev/null +++ b/deps/v8/test/debugger/debug/wasm/frame-inspection.js @@ -0,0 +1,72 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --expose-wasm + +load("test/mjsunit/wasm/wasm-constants.js"); +load("test/mjsunit/wasm/wasm-module-builder.js"); + +Debug = debug.Debug + +var exception = null; +var break_count = 0; + +const expected_frames = [ + // func-name; wasm?; pos; line; col + ['call_debugger', false], // -- + ['wasm_2', true, 56, 2, 2], // -- + ['wasm_1', true, 52, 3, 2], // -- + ['testFrameInspection', false], // -- + ['', false] +]; + +function listener(event, exec_state, event_data, data) { + if (event != Debug.DebugEvent.Break) return; + ++break_count; + try { + var break_id = exec_state.break_id; + var frame_count = exec_state.frameCount(); + assertEquals(expected_frames.length, frame_count, 'frame count'); + + for (var i = 0; i < frame_count; ++i) { + var frame = exec_state.frame(i); + assertEquals(expected_frames[i][0], frame.func().name(), 'name at ' + i); + if (expected_frames[i][1]) { // wasm frame? + assertEquals(expected_frames[i][3], frame.sourceLine(), 'line at ' + i); + assertEquals(expected_frames[i][4], frame.sourceColumn(), + 'column at ' + i); + } + } + } catch (e) { + exception = e; + } +}; + +var builder = new WasmModuleBuilder(); + +// wasm_1 calls wasm_2 on offset 2. +// wasm_2 calls call_debugger on offset 1. + +builder.addImport("mod", 'func', kSig_v_v); + +builder.addFunction('wasm_1', kSig_v_v) + .addBody([kExprNop, kExprCallFunction, 2]) + .exportAs('main'); + +builder.addFunction('wasm_2', kSig_v_v).addBody([kExprCallFunction, 0]); + +function call_debugger() { + debugger; +} + +var module = builder.instantiate({mod: {func: call_debugger}}); + +(function testFrameInspection() { + Debug.setListener(listener); + module.exports.main(); + Debug.setListener(null); + + assertEquals(1, break_count); + if (exception) throw exception; +})(); |