Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

View File

@ -0,0 +1,148 @@
// 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;
}
}
%PrepareFunctionForOptimization(f);
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;
}
}
%PrepareFunctionForOptimization(f);
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.
}
}
%PrepareFunctionForOptimization(f);
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;
}
}
%PrepareFunctionForOptimization(f);
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;
}
}
%PrepareFunctionForOptimization(f);
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;
}
}
%PrepareFunctionForOptimization(f);
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);
})();

View File

@ -0,0 +1,58 @@
// Copyright 2024 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: --allow-natives-syntax --turbolev --turbofan
// Flags: --no-maglev --no-stress-concurrent-inlining
// Flags: --invocation-count-for-turbofan=3000
// This test checks that loop interrupt stack checks are properly detected are
// processed.
// Note that interrupt requests are not handled at the same time in Maglev and
// Turbofan: in Maglev, they are not directly checked but we instead rely on the
// fact budget interrupt will perform stack check interrupt, which in Turbofan,
// they are checked at every loop iteration.
var Debug = debug.Debug;
var trigger_count = 0;
var called_from;
Debug.setListener(function (event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
called_from = exec_state.frames[0].functionName;
trigger_count += 1;
}
});
function g(x) {
if (x == 0) {
%ScheduleBreak();
}
return 7;
}
function loop_interrupt_check_f(x) {
let r = 0;
for (let i = 0; i < 10; i++) {
if (i == 0) {
// Schedules an interrupt if {x} is 0.
r += g(x);
} else {
r += g(1);
}
}
return r;
}
%PrepareFunctionForOptimization(loop_interrupt_check_f);
assertEquals(70, loop_interrupt_check_f(1));
%OptimizeFunctionOnNextCall(loop_interrupt_check_f);
assertEquals(70, loop_interrupt_check_f(1));
assertOptimized(loop_interrupt_check_f);
assertEquals(0, trigger_count);
assertEquals(70, loop_interrupt_check_f(0));
assertEquals(1, trigger_count);
assertEquals("loop_interrupt_check_f", called_from);
assertOptimized(loop_interrupt_check_f);

View File

@ -0,0 +1,118 @@
// 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 changed = false;
function listenerSetJToResult(
event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
var scope = exec_state.frame(1).scope(0);
var newval = "result";
try {
scope.setVariableValue("j", newval);
changed = true;
} catch(e) {
changed = false;
}
}
}
Debug.setListener(listenerSetJToResult);
function g() { debugger; }
%NeverOptimizeFunction(g);
function ChangeSmiConstantAndOsr() {
var j = 1;
for (var i = 0; i < 4; i++) {
if (i == 2) {
%OptimizeOsr();
g();
}
}
return j;
}
%PrepareFunctionForOptimization(ChangeSmiConstantAndOsr);
var r1 = ChangeSmiConstantAndOsr();
if (changed) {
assertEquals("result", r1);
} else {
assertEquals(1, r1);
}
function ChangeFloatConstantAndOsr() {
var j = 0.1;
for (var i = 0; i < 4; i++) {
if (i == 2) {
%OptimizeOsr();
g();
}
}
return j;
}
%PrepareFunctionForOptimization(ChangeFloatConstantAndOsr);
var r2 = ChangeFloatConstantAndOsr();
if (changed) {
assertEquals("result", r2);
} else {
assertEquals(0.1, r2);
}
function ChangeFloatVarAndOsr() {
var j = 0.1;
for (var i = 0; i < 4; i++) {
j = j + 0.1;
if (i == 2) {
%OptimizeOsr();
g();
}
}
return j;
}
%PrepareFunctionForOptimization(ChangeFloatVarAndOsr);
var r3 = ChangeFloatVarAndOsr();
if (changed) {
assertEquals("result0.1", r3);
} else {
assertEquals(0.5, r3);
}
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", 100);
changed = true;
} catch(e) {
changed = false;
}
}
}
Debug.setListener(listenerSetJToObject);
function ChangeIntVarAndOsr() {
var j = 1;
for (var i = 0; i < 4; i++) {
j = j + 1|0;
if (i == 2) {
%OptimizeOsr();
g();
}
}
return j;
}
%PrepareFunctionForOptimization(ChangeIntVarAndOsr);
var r4 = ChangeIntVarAndOsr();
if (changed) {
assertEquals(101, r4);
} else {
assertEquals(5, r4);
}

View File

@ -0,0 +1,38 @@
// Copyright 2024 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: --allow-natives-syntax --turbolev --turbofan
// Flags: --no-turboshaft-loop-unrolling --expose-gc --enable-inspector
var Debug = debug.Debug;
Debug.setListener(function (event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
gc();
}
});
function foo(b) {
%ScheduleBreak();
// Allocating a first object.
let o1 = { x : 42 };
// Inserting a loop, in order to get a JSStackCheck.
let v = 0;
for (; v < 42; v = (v + 2) * 2) {}
// Allocating a second object. This should not get allocation-folded with the
// first allocation, because of the JSStackCheck's GC in the middle.
let o2 = { x : o1, y : v };
return o2;
}
%PrepareFunctionForOptimization(foo);
assertEquals({ x : { x : 42 }, y : 60 }, foo());
assertEquals({ x : { x : 42 }, y : 60 }, foo());
%OptimizeFunctionOnNextCall(foo);
assertEquals({ x : { x : 42 }, y : 60 }, foo());

View File

@ -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.
Debug = debug.Debug
var exception = null;
var break_count = 0;
const expected_breaks = 8;
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);
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 + ".");
++break_count;
if (break_count !== expected_breaks) {
exec_state.prepareStep(Debug.StepAction.StepInto);
print("Next step prepared");
}
}
} catch(e) {
exception = e;
print(e, e.stack);
}
};
Debug.setListener(listener);
var sum = 0;
(function (){
'use strict';
debugger; // Break 0.
var i = 0; // Break 1.
i++; // Break 2.
i++; // Break 3.
debugger; // Break 4.
return i // Break 5.
; // Break 6.
}());
assertNull(exception); // Break 7.
assertEquals(expected_breaks, break_count);
Debug.setListener(null);

View File

@ -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
let listenerCalled = false;
let exceptionThrown = 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) {
exceptionThrown = true;
};
};
// 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(exceptionThrown, "exception in listener");
assertTrue(listenerCalled);

View File

@ -0,0 +1,22 @@
// Copyright 2018 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
let exceptionThrown = false;
Debug.setListener(function(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
const o = exec_state.frame(0).evaluate("42n", true);
assertEquals("bigint", o.type());
assertFalse(o.isUndefined());
assertEquals("bigint", typeof(o.value()));
assertEquals(42n, o.value());
} catch (e) {
exceptionThrown = true;
};
});
!function() { debugger; }();
assertFalse(exceptionThrown, "exception in listener")

View File

@ -0,0 +1,145 @@
// Copyright 2018 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: --allow-natives-syntax
Debug = debug.Debug
Debug.setListener(function() {});
class Y {
x = 1;
y = 2;
z = 3;
}
var initializer = %GetInitializerFunction(Y);
var b1, b2, b3;
// class Y {
// x = [B0]1;
// y = [B1]2;
// z = [B2]3;
// }
b1 = Debug.setBreakPoint(initializer, 0, 0);
assertTrue(Debug.showBreakPoints(initializer).indexOf("x = [B0]1;") >= 0);
Debug.clearBreakPoint(b1);
assertTrue(Debug.showBreakPoints(initializer).indexOf("x = [B0]1;") === -1);
b2 = Debug.setBreakPoint(initializer, 1, 0);
assertTrue(Debug.showBreakPoints(initializer).indexOf("y = [B0]2;") >= 0);
Debug.clearBreakPoint(b2);
assertTrue(Debug.showBreakPoints(initializer).indexOf("y = [B0]2;") === -1);
b3 = Debug.setBreakPoint(initializer, 2, 0);
assertTrue(Debug.showBreakPoints(initializer).indexOf("z = [B0]3") >= 0);
Debug.clearBreakPoint(b3);
assertTrue(Debug.showBreakPoints(initializer).indexOf("z = [B0]3") === -1);
b1 = Debug.setBreakPoint(initializer, 0, 0);
b2 = Debug.setBreakPoint(initializer, 1, 0);
assertTrue(Debug.showBreakPoints(initializer).indexOf("x = [B0]1;") >= 0);
assertTrue(Debug.showBreakPoints(initializer).indexOf("y = [B1]2;") >= 0);
Debug.clearBreakPoint(b1);
assertTrue(Debug.showBreakPoints(initializer).indexOf("x = [B0]1;") === -1);
Debug.clearBreakPoint(b2);
assertTrue(Debug.showBreakPoints(initializer).indexOf("y = [B1]2;") === -1);
b1 = Debug.setBreakPoint(initializer, 0, 0);
b3 = Debug.setBreakPoint(initializer, 2, 0);
assertTrue(Debug.showBreakPoints(initializer).indexOf("x = [B0]1;") >= 0);
assertTrue(Debug.showBreakPoints(initializer).indexOf("z = [B1]3") >= 0);
Debug.clearBreakPoint(b1);
assertTrue(Debug.showBreakPoints(initializer).indexOf("x = [B0]1;") === -1);
Debug.clearBreakPoint(b3);
assertTrue(Debug.showBreakPoints(initializer).indexOf("z = [B1]3") === -1);
b2 = Debug.setBreakPoint(initializer, 1, 0);
b3 = Debug.setBreakPoint(initializer, 2, 0);
assertTrue(Debug.showBreakPoints(initializer).indexOf("y = [B0]2;") >= 0);
assertTrue(Debug.showBreakPoints(initializer).indexOf("z = [B1]3") >= 0);
Debug.clearBreakPoint(b2);
assertTrue(Debug.showBreakPoints(initializer).indexOf("y = [B0]2;") === -1);
Debug.clearBreakPoint(b3);
assertTrue(Debug.showBreakPoints(initializer).indexOf("z = [B1]3") === -1);
// The computed properties are evaluated during class construction,
// not as part of the initializer function. As a consequence of which,
// they aren't breakable here in the initializer function, but
// instead, are part of the enclosing function.
function foo() {}
var bar = 'bar';
class X {
[foo()] = 1;
baz = foo();
}
// class X {
// [foo()] = 1;
// baz = [B0]foo();
// }
initializer = %GetInitializerFunction(X);
b1 = Debug.setBreakPoint(initializer, 0, 0);
assertTrue(Debug.showBreakPoints(initializer).indexOf('[foo()] = 1;') >= 0);
Debug.clearBreakPoint(b1);
b1 = Debug.setBreakPoint(initializer, 1, 0);
assertTrue(Debug.showBreakPoints(initializer).indexOf('baz = [B0]foo()') >= 0);
Debug.clearBreakPoint(b1);
function t() {
class X {
[foo()] = 1;
[bar] = 2;
baz = foo();
}
}
// class X {
// [[B0]foo()] = 1;
// [[B1]bar] = 2;
// baz = foo();
// }
b1 = Debug.setBreakPoint(t, 2, 0);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B0]foo()] = 1;') >= 0);
Debug.clearBreakPoint(b1);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B0]foo()] = 1;') === -1);
b2 = Debug.setBreakPoint(t, 3, 0);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B0]bar] = 2;') >= 0);
Debug.clearBreakPoint(b2);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B0]bar] = [B0]2;') === -1);
b3 = Debug.setBreakPoint(t, 4, 0);
assertTrue(Debug.showBreakPoints(t).indexOf('baz = foo()') >= 0);
Debug.clearBreakPoint(b3);
b1 = Debug.setBreakPoint(t, 2, 0);
b2 = Debug.setBreakPoint(t, 3, 0);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B0]foo()] = 1;') >= 0);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B1]bar] = 2;') >= 0);
Debug.clearBreakPoint(b1);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B0]foo()] = 1;') === -1);
Debug.clearBreakPoint(b2);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B1]bar] = 2;') === -1);
b1 = Debug.setBreakPoint(t, 2, 0);
b3 = Debug.setBreakPoint(initializer, 4, 0);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B0]foo()] = 1;') >= 0);
assertTrue(Debug.showBreakPoints(t).indexOf('baz = foo()') >= 0);
Debug.clearBreakPoint(b1);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B0]foo()] = 1;') === -1);
Debug.clearBreakPoint(b3);
b2 = Debug.setBreakPoint(t, 3, 0);
b3 = Debug.setBreakPoint(t, 4, 0);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B0]bar] = 2;') >= 0);
assertTrue(Debug.showBreakPoints(t).indexOf('baz = foo()') >= 0);
Debug.clearBreakPoint(b2);
assertTrue(Debug.showBreakPoints(t).indexOf('[[B0]bar] = 2;') === -1);
Debug.clearBreakPoint(b3);

View File

@ -0,0 +1,80 @@
// 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.
// This test tests that deoptimization due to debug breaks works for
// inlined functions where the full-code is generated before the
// debugger is attached.
//
//See http://code.google.com/p/chromium/issues/detail?id=105375
Debug = debug.Debug;
var count = 0;
var break_count = 0;
// Debug event listener which sets a breakpoint first time it is hit
// and otherwise counts break points hit and checks that the expected
// state is reached.
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
break_count++;
if (break_count == 1) {
Debug.setBreakPoint(g, 3);
}
}
}
function f() {
g();
}
function g() {
count++;
h();
var b = 1; // Break point is set here.
}
function h() {
debugger;
}
%PrepareFunctionForOptimization(f);
f();f();f();
%OptimizeFunctionOnNextCall(f);
f();
// Add the debug event listener.
Debug.setListener(listener);
f();
assertEquals(5, count);
assertEquals(2, break_count);
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -0,0 +1,52 @@
// 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.
Debug = debug.Debug
var exception = null;
var log = [];
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
var line = exec_state.frame(0).sourceLineText();
log.push(line);
if (!/STOP/.test(line)) {
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
} catch (e) {
exception = e;
}
};
Debug.setListener(listener);
function f() {
print(1);
}
Promise.resolve().then(f).then(
function() {
return 2;
}
).then(
function() {
throw new Error();
}
).catch(
function() {
print(3);
} // STOP
);
setTimeout(function() {
Debug.setListener(null);
assertNull(exception);
var expectation =
[" print(1);","}"," return 2;"," return 2;",
" throw new Error();"," print(3);","} // STOP"];
assertEquals(log, expectation);
});
Debug.setBreakPoint(f, 1);

View File

@ -0,0 +1,39 @@
// 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.StepInto);
// 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
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);

View File

@ -0,0 +1,40 @@
// Copyright 2018 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 foo(){}
let breakpoint_count = 0;
let last_source_line = 0;
let last_source_column = 0;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
++breakpoint_count;
last_source_line = exec_state.frame(0).sourceLine();
last_source_column = exec_state.frame(0).sourceColumn();
}
};
Debug.setListener(listener);
// Run without breakpoints.
foo();
assertEquals(breakpoint_count, 0);
// Run with breakpoint.
const breakpoint = Debug.setBreakPoint(foo, 0);
foo();
assertEquals(breakpoint_count, 1);
assertEquals(last_source_line, 7);
assertEquals(last_source_column, 15);
foo();
assertEquals(breakpoint_count, 2);
assertEquals(last_source_line, 7);
assertEquals(last_source_column, 15);
// Run without breakpoints
Debug.clearBreakPoint(breakpoint);
foo();
assertEquals(breakpoint_count, 2);

View File

@ -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);

View File

@ -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.
let listenerComplete = false;
let exceptionThrown = 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) {
exceptionThrown = true;
};
};
// 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(exceptionThrown, "exception in listener")

View File

@ -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 exceptionThrown = 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) {
exceptionThrown = true;
}
};
// 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(exceptionThrown, "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);

View File

@ -0,0 +1,34 @@
// 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: --turbofan --no-always-turbofan
Debug = debug.Debug;
Debug.setListener(function() {});
function f() {}
%PrepareFunctionForOptimization(f);
f();
f();
%OptimizeFunctionOnNextCall(f);
f();
assertOptimized(f);
var bp = Debug.setBreakPoint(f);
assertUnoptimized(f);
%PrepareFunctionForOptimization(f);
f();
f();
%OptimizeFunctionOnNextCall(f);
f();
assertUnoptimized(f);
Debug.clearBreakPoint(bp);
%PrepareFunctionForOptimization(f);
%OptimizeFunctionOnNextCall(f);
f();
assertOptimized(f);
Debug.setListener(null);

View File

@ -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);

View File

@ -0,0 +1,76 @@
// 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 collects a simple call graph.
var call_graph = "";
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break)
{
call_graph += exec_state.frame().func().name();
exec_state.prepareStep(Debug.StepAction.StepInto);
}
};
// Add the debug event listener.
Debug.setListener(listener);
// Test debug event for constructor.
function a() {
new c();
}
function b() {
x = 1;
new c();
}
function c() {
this.x = 1;
d();
}
function d() {
}
// Break point stops on "new c()" and steps into c.
Debug.setBreakPoint(a, 1);
call_graph = "";
a();
Debug.clearStepping(); // Clear stepping as the listener leaves it on.
assertEquals("accdca", call_graph);
// Break point stops on "x = 1" and steps to "new c()" and then into c.
Debug.setBreakPoint(b, 1);
call_graph = "";
b();
Debug.clearStepping(); // Clear stepping as the listener leaves it on.
assertEquals("bbccdcb", call_graph);
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -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);

View File

@ -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-turbofan
// 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);

View File

@ -0,0 +1,62 @@
// 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: --allow-natives-syntax
Debug = debug.Debug;
var listened = false;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
var foo_arguments = exec_state.frame(1).evaluate("arguments").value();
var bar_arguments = exec_state.frame(0).evaluate("arguments").value();
assertArrayEquals(foo_expected, foo_arguments);
assertArrayEquals(bar_expected, bar_arguments);
listened = true;
} catch (e) {
print(e);
print(e.stack);
}
}
Debug.setListener(listener);
function foo(a) {
function bar(a,b,c) {
debugger;
return a + b + c;
}
return bar(1,2,a);
}
%PrepareFunctionForOptimization(foo);
listened = false;
foo_expected = [3];
bar_expected = [1,2,3];
assertEquals(6, foo(3));
assertTrue(listened);
listened = false;
foo_expected = [3];
bar_expected = [1,2,3];
assertEquals(6, foo(3));
assertTrue(listened);
listened = false;
foo_expected = [3];
bar_expected = [1,2,3];
%OptimizeFunctionOnNextCall(foo);
assertEquals(6, foo(3));
assertTrue(listened);
listened = false;
foo_expected = [3,4,5];
bar_expected = [1,2,3];
%PrepareFunctionForOptimization(foo);
%OptimizeFunctionOnNextCall(foo);
assertEquals(6, foo(3,4,5));
assertTrue(listened);
Debug.setListener(null);

View File

@ -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 exceptionThrown = 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);
exceptionThrown = true;
};
};
// 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(exceptionThrown, "exception in listener")
assertTrue(listenerComplete, "listener did not run to completion");

View File

@ -0,0 +1,92 @@
// 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: --no-always-turbofan
Debug = debug.Debug;
var listened = false;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
assertEquals("goo", exec_state.frame(0).evaluate("goo").value());
exec_state.frame(0).evaluate("goo = 'goo foo'");
assertEquals("bar return", exec_state.frame(0).evaluate("bar()").value());
assertEquals("inner bar", exec_state.frame(0).evaluate("inner").value());
assertEquals("outer bar", exec_state.frame(0).evaluate("outer").value());
assertEquals("baz inner", exec_state.frame(0).evaluate("baz").value());
assertEquals("baz outer", exec_state.frame(1).evaluate("baz").value());
exec_state.frame(0).evaluate("w = 'w foo'");
exec_state.frame(0).evaluate("inner = 'inner foo'");
exec_state.frame(0).evaluate("outer = 'outer foo'");
exec_state.frame(0).evaluate("baz = 'baz inner foo'");
exec_state.frame(1).evaluate("baz = 'baz outer foo'");
listened = true;
} catch (e) {
print(e);
print(e.stack);
}
}
Debug.setListener(listener);
var outer = "outer";
var baz = "baz outer";
function foo() {
var inner = "inner";
var baz = "baz inner";
var goo = "goo";
var withw = { w: "w" };
var withv = { v: "v" };
with (withv) {
var bar = function bar() {
assertEquals("goo foo", goo);
inner = "inner bar";
outer = "outer bar";
v = "v bar";
return "bar return";
};
}
with (withw) {
debugger;
}
assertEquals("inner foo", inner);
assertEquals("baz inner foo", baz);
assertEquals("w foo", withw.w);
assertEquals("v bar", withv.v);
}
foo();
assertEquals("outer foo", outer);
assertEquals("baz outer foo", baz);
assertTrue(listened);
Debug.setListener(null);

View File

@ -0,0 +1,35 @@
// Copyright 2019 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-turbofan
Debug = debug.Debug
var exception = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
// Evaluating the live function should succeed.
assertEquals(exec_state.frame(0).evaluate("live()").value(), 1);
// Evaluating the dead function should fail.
assertThrows(()=>exec_state.frame(0).evaluate("dead()"), ReferenceError);
} catch (e) {
exception = e;
print(e + e.stack);
}
}
Debug.setListener(listener);
(function() {
"use strict";
function live() { return 1; }
function dead() { return 2; }
// Use 'foo' to make it non-dead.
live;
debugger;
})();
Debug.setListener(null);
assertNull(exception);

View File

@ -0,0 +1,43 @@
// 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 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.
"use strict";
var Debug = debug.Debug
var exception = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
exec_state.frame(0).evaluate("var x = 2");
exec_state.frame(0).evaluate("'use strict'; let y = 3");
exec_state.frame(0).evaluate("var z = 4");
exec_state.frame(0).evaluate("function bar() { return 5; }");
} catch (e) {
exception = e;
print(e + e.stack);
}
}
Debug.setListener(listener);
var z = 1;
(function() {
debugger;
})();
assertEquals(2, x); // declaration
assertThrows(() => y, ReferenceError); // let-declaration does not stick
assertEquals(4, z); // re-declaration
assertEquals(5, bar()); // function declaration
Debug.setListener(null);
assertNull(exception);

View File

@ -0,0 +1,42 @@
// Copyright 2019 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 listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
var frame = exec_state.frame(0);
try {
assertTrue(frame.evaluate("f").value().startsWith("function f()"));
} catch {
assertTrue(frame.sourceLineText().endsWith("throws"));
}
}
} catch(e) {
exception = e;
print(e, e.stack);
}
};
Debug.setListener(listener);
(function f() {
f;
debugger; // works
})();
(function f() {
() => f;
debugger; // works
})();
(function f() {
debugger; // throws
})();
assertNull(exception);
Debug.setListener(null);

View File

@ -0,0 +1,37 @@
// Copyright 2019 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 *local* debug-evaluate properly works for REPL 'let'
// re-declarations.
Debug = debug.Debug
let exception = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
assertEquals(42, exec_state.frame(0).evaluate("x").value());
} catch (e) {
exception = e;
print(e + e.stack);
}
}
Debug.setListener(listener);
// First script introduces a let-binding 'x'. The value of
// 'x' lives in the ScriptContext of this REPL script.
Debug.evaluateGlobalREPL('let x = 21;');
// The second script re-declares 'x', but then breaks and
// evaluates x.
Debug.evaluateGlobalREPL(`
let x = 42;
(function foo() {
debugger;
})();
`);
Debug.setListener(null);
assertNull(exception);

View File

@ -0,0 +1,48 @@
// 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: --no-always-turbofan
Debug = debug.Debug
var exception = null;
var break_count = 0;
var f = null;
var i = null;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
var frameMirror = exec_state.frame(0);
var i = frameMirror.evaluate('f = function() { i = 5; }, f(), i').value();
assertEquals(5, i);
}
} catch(e) {
exception = e;
print(e, e.stack);
}
};
Debug.setListener(listener);
(function (){
var i = 0;
try {
throw new Error();
} catch (e) {
assertEquals(0, i);
debugger;
assertEquals(5, i);
}
}());
assertNull(exception);
assertNull(i);
f();
assertNull(i);
Debug.setListener(null);

View File

@ -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
Debug = debug.Debug
var listenerComplete = false;
var exceptionThrown = 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) {
exceptionThrown = true;
};
};
%PrepareFunctionForOptimization(f);
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(exceptionThrown, "exception in listener");
assertTrue(listenerComplete);
//Throw away type information for next run.
gc();
Debug.setListener(null);

View File

@ -0,0 +1,182 @@
// 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
Debug = debug.Debug
var listenerComplete = false;
var exceptionThrown = false;
var testingConstructCall = false;
var expected = [
{ locals: {i: 0, x0: 3, y0: 4, a0: 1, b0: 2},
args: { names: ["i", "x0", "y0"], values: [0, 3, 4] } },
{ locals: {i: 1, x1: 5, y1: 6, a1: 3, b1: 4},
args: { names: ["i", "x1", "y1"], values: [1, 5, 6] } },
{ locals: {i: 2, a2: 5, b2: 6},
args: { names: ["i"], values: [2] } },
{ locals: {i: 3, x3: 9, y3: 10, z3: undefined, a3: 7, b3: 8},
args: { names: ["i", "x3", "y3", "z3"], values: [3, 9, 10, undefined] } },
{ locals: {i: 4, x4: 11, y4: 12, a4: 9, b4: 10},
args: { names: ["i", "x4", "y4"], values: [4, 11, 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 three 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 script scope and 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) {
exceptionThrown = true;
};
};
%PrepareFunctionForOptimization(f);
for (var i = 0; i < 4; i++) f(expected.length - 1, 11, 12);
%OptimizeFunctionOnNextCall(f);
f(expected.length - 1, 11, 12);
// Add the debug event listener.
Debug.setListener(listener);
function h(i, x0, y0) {
var a0 = expected[i].locals.a0;
var b0 = expected[i].locals.b0;
debugger; // Breakpoint.
return a0 + b0;
}
function g3(i, x1, y1) {
var a1 = expected[i].locals.a1;
var b1 = expected[i].locals.b1;
h(i - 1, a1, b1);
return a1 + b1;
}
function g2(i) {
var a2 = expected[i].locals.a2;
var b2 = expected[i].locals.b2;
g3(i - 1, a2, b2);
return a2 + b2;
}
function g1(i, x3, y3, z3) {
var a3 = expected[i].locals.a3;
var b3 = expected[i].locals.b3;
new g2(i - 1, a3, b3);
return a3 + b3;
}
function f(i, x4, y4) {
var a4 = expected[i].locals.a4;
var b4 = expected[i].locals.b4;
g1(i - 1, a4, b4);
return a4 + b4;
}
// Test calling f normally and as a constructor.
f(expected.length - 1, 11, 12);
f(expected.length - 1, 11, 12, 0);
testingConstructCall = true;
new f(expected.length - 1, 11, 12);
new f(expected.length - 1, 11, 12, 0);
// Make sure that the debug event listener was invoked.
assertFalse(exceptionThrown, "exception in listener");
assertTrue(listenerComplete);
// Throw away type information for next run.
gc();
Debug.setListener(null);

View File

@ -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
let listenerComplete = false;
let exceptionThrown = 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) {
exceptionThrown = true;
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(exceptionThrown, "exception in listener");
assertTrue(listenerComplete);

View File

@ -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.
// Flags: --no-always-turbofan
Debug = debug.Debug
var exception = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
exec_state.frame(0).evaluate("a = 2");
exec_state.frame(0).evaluate("e = 3");
exec_state.frame(0).evaluate("bar()");
exec_state.frame(0).evaluate("a++");
exec_state.frame(0).evaluate("e++");
} catch (e) {
exception = e;
print(e + e.stack);
}
}
Debug.setListener(listener);
(function() {
"use strict";
try {
throw 1;
} catch (e) {
let a = 1;
function bar() {
a *= 2;
e *= 2;
}
// Make sure bar is 'used' so that it is visible to the debugger.
bar;
debugger;
assertEquals(5, a);
assertEquals(7, e);
}
})();
Debug.setListener(null);
assertNull(exception);

View File

@ -0,0 +1,32 @@
// 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 f = () => { debugger; }
var g = function() { debugger; }
var h = (function() { return () => { debugger; }; }).call({});
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
assertThrows(() => exec_state.frame(0).evaluate("this = 2"));
} catch (e) {
exception = e;
print("Caught something. " + e + " " + e.stack);
};
};
Debug.setListener(listener);
f();
g();
g.call({});
h();
Debug.setListener(null);
assertNull(exception);

View File

@ -0,0 +1,52 @@
// 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: --turbofan
Debug = debug.Debug
var exception = null;
function f() {
let a = 0;
function g() {
let a = 1;
{
let a = 2;
debugger; // Breakpoint.
if (a !== 3) {
// We cannot change stack locals in optimized frames.
assertEquals(2, a);
assertOptimized(g);
}
}
assertEquals(1, a);
}
g.call(1);
if (a !== 4) {
// We cannot change stack locals in optimized frames.
assertEquals(0, a);
assertOptimized(f);
}
}
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
exec_state.frame(0).evaluate("a = 3");
exec_state.frame(1).evaluate("a = 4");
assertThrows(() => exec_state.frame(0).evaluate("this = 2"));
} catch (e) {
exception = e;
print("Caught something. " + e + " " + e.stack);
};
};
Debug.setListener(listener);
f();
Debug.setListener(null);
assertNull(exception);

View File

@ -0,0 +1,46 @@
// Copyright 2019 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
const evaluate = Debug.evaluateGlobalREPL;
(async () => {
// Test that the completion value of the REPL script is the resolve value of the
// promise returned by evalute.
let result = evaluate('5;');
assertPromiseResult(result, (value) => {
assertEquals(5, value);
}, assertUnreachable);
// Test that top-level await in REPL mode works.
result = evaluate('let x = await Promise.resolve(42);');
assertPromiseResult(result, (value) => {
assertEquals(undefined, value);
assertEquals(42, x);
}, assertUnreachable);
// Test that a throwing REPL script results in a rejected promise.
result = evaluate('throw new Error("ba dum tsh");');
assertPromiseResult(result, assertUnreachable, (error) => {
assertEquals("ba dum tsh", error.message);
});
// Test that a rejected promise throws.
result = evaluate('await Promise.reject("Reject promise!");');
assertPromiseResult(result, assertUnreachable, (error) => {
assertEquals('Reject promise!', error);
});
// Test that we can bind a promise in REPL mode.
await evaluate('let y = Promise.resolve(21);');
assertPromiseResult(y, (value) => {
assertEquals(21, value);
}, assertUnreachable);
})().then(() => {
print("Async test completed successfully.");
}).catch(e => {
print(e.stack);
%AbortJS("Async test is failing");
});

View File

@ -0,0 +1,65 @@
// Copyright 2019 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: --turbofan
Debug = debug.Debug
const evaluate = Debug.evaluateGlobalREPL;
const evaluateNonREPL = (source) => Debug.evaluateGlobal(source, false).value();
// Test that a let declared variable 'x' bound by an optimized function is
// updated properly.
evaluate('let x = 42;');
evaluate('function foo() { return x; }');
%PrepareFunctionForOptimization(foo);
foo();
foo();
%OptimizeFunctionOnNextCall(foo);
assertEquals(42, foo());
assertOptimized(foo);
evaluate('let x = 21');
assertEquals(21, foo());
// Test that we do not throw a 'use before declaration error' and
// that the optimized code does not load the hole from the wrong
// script context.
evaluate('x; let x;');
assertEquals(undefined, foo());
// Test that a const declared variable 'y' bound by an optimized function is
// updated properly.
evaluate('const y = 42;');
evaluate('function foo1() { return y; }');
%PrepareFunctionForOptimization(foo1);
foo1();
foo1();
%OptimizeFunctionOnNextCall(foo1);
assertEquals(42, foo1());
assertOptimized(foo1);
evaluate('const y = 21');
assertEquals(21, foo1());
// Test that a const declared variable 'z' bound by an optimized function is
// updated properly.
evaluate('const z = {a:0};');
evaluate('function foo2() { z.a = 42; }');
%PrepareFunctionForOptimization(foo2);
foo2();
foo2();
%OptimizeFunctionOnNextCall(foo2);
foo2();
assertOptimized(foo2);
evaluate('const z = {a:21}');
foo2();
assertEquals(42, z.a);

View File

@ -0,0 +1,416 @@
// Copyright 2019 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
const evaluate = Debug.evaluateGlobalREPL;
const evaluateNonREPL = (source) => Debug.evaluateGlobal(source, false).value();
(async () => {
// Declare let and get value
let result;
result = await evaluate("let x = 7;");
result = await evaluate("x;");
assertEquals(7, result);
// Re-declare in the same script after declaration in another script.
assertThrows(() => evaluate("let x = 8; let x = 9;"));
result = await evaluate("x;");
assertEquals(7, result);
// Re-declare let as let
assertDoesNotThrow(async () => result = await evaluate("let x = 8;"));
result = await evaluate("x;");
assertEquals(8, result);
await evaluate("let x = 8;");
// Close over let. Inner function is only pre-parsed.
result = await evaluate("function getter() { return x; }");
assertEquals(undefined, result);
result = await evaluate("getter();");
assertEquals(8, result);
result = await evaluate("x = 9;");
assertEquals(9, result);
result = await evaluate("x;");
assertEquals(9, result);
result = await evaluate("getter();");
assertEquals(9, result);
// Modifies the original x; does not create a new one/shadow.
result = await evaluate("let x = 10;");
assertEquals(undefined, result);
result = await evaluate("x;");
assertEquals(10, result);
result = await evaluate("getter();");
assertEquals(10, result);
await evaluate("let x = 10");
// Check store from an inner scope.
result = await evaluate("{ let z; x = 11; } x;");
assertEquals(11, result);
// Check re-declare from an inner scope does nothing.
result = await evaluate("{ let z; let x = 12; } x;");
assertEquals(11, result);
assertThrowsAsync(evaluate("{ let qq = 10; } qq;"),
ReferenceError, "qq is not defined");
// Re-declare in the same script (no previous declaration).
assertThrows(() => result = evaluate("let y = 7; let y = 8;"),
SyntaxError, "Identifier 'y' has already been declared");
// Check TDZ; use before initialization.
// Do not check exact error message, it depends on the path taken through
// the IC machinery and changes sometimes, causing the test to be flaky.
assertThrowsAsync(evaluate("a; let a = 7;"), ReferenceError);
assertThrowsAsync(evaluate("a;"), ReferenceError);
// This is different to non-REPL mode, which throws the kUndefined error here.
assertThrowsAsync(evaluate("a = 7;"),
ReferenceError, "Cannot access 'a' before initialization");
result = await evaluate("let a = 8;");
assertEquals(undefined, result);
result = await evaluate("a;")
assertEquals(8, result);
// Check TDZ; store before initialization.
assertThrowsAsync(evaluate("b = 10; let b;"),
ReferenceError, "Cannot access 'b' before initialization");
// Check that b is still broken.
assertThrowsAsync(evaluate("b = 10; let b;"),
ReferenceError, "Cannot access 'b' before initialization");
// Check that b is still broken when the let defines a value.
assertThrowsAsync(evaluate("b = 10; let b = 7;"),
ReferenceError, "Cannot access 'b' before initialization");
result = await evaluate("let b = 11;");
assertEquals(undefined, result);
// We fixed 'b'!
result = await evaluate("b;");
assertEquals(11, result);
// Check that class works the same. Internally there is no difference between
// class and let so we don't test as extensively as for let.
result = evaluate("class K {};");
assertDoesNotThrow(() => result = evaluate("class K {};"));
// many tests for normal/repl script interactions.
// tests with let x = await
// result = evaluate("toString;");
// Declare const and get value
result = await evaluate("const c = 7;");
result = await evaluate("c;");
assertEquals(7, result);
// Re-declare in the same script after declaration in another script.
assertThrows(() => evaluate("let c = 8; let c = 9;"));
result = await evaluate("c;");
assertEquals(7, result);
// Re-declare const as const
result = await evaluate("const c = 8;");
result = await evaluate("c;");
assertEquals(8, result);
// Assign to const
assertThrowsAsync(evaluate("c = 11;"),
TypeError, "Assignment to constant variable.");
result = await evaluate("c;");
assertEquals(8, result);
await evaluate("const c = 8;");
// Close over const. Inner function is only pre-parsed.
result = await evaluate("function getter() { return c; }");
assertEquals(undefined, result);
result = await evaluate("getter();");
assertEquals(8, result);
// Modifies the original c; does not create a new one/shadow.
result = await evaluate("const c = 10;");
assertEquals(undefined, result);
result = await evaluate("c;");
assertEquals(10, result);
result = await evaluate("getter();");
assertEquals(10, result);
await evaluate("const c = 10");
// Check store from an inner scope throws error.
assertThrowsAsync(evaluate("{ let z; c = 11; };"),
TypeError, "Assignment to constant variable.");
result = await evaluate("c;");
assertEquals(10, result);
// Check re-declare from an inner scope does nothing.
result = await evaluate("{ let z; const c = 12; } c;");
assertEquals(10, result);
assertThrowsAsync(evaluate("{ const qq = 10; } qq;"),
ReferenceError, "qq is not defined");
// Const vs. const in same script.
assertThrows(() => result = evaluate("const d = 9; const d = 10;"),
SyntaxError, "Identifier 'd' has already been declared");
// Check TDZ; const use before initialization.
assertThrowsAsync(evaluate("e; const e = 7;"), ReferenceError);
assertThrowsAsync(evaluate("e;"), ReferenceError);
result = await evaluate("const e = 8;");
assertEquals(undefined, result);
result = await evaluate("e;")
assertEquals(8, result);
// f is marked as constant in TDZ
assertThrowsAsync(evaluate("f = 10; const f = 7;"),
TypeError, ("Assignment to constant variable."));
result = await evaluate("const f = 11;");
assertEquals(undefined, result);
// We fixed 'f'!
result = await evaluate("f;");
assertEquals(11, result);
// Re-declare let as const
evaluate("let z = 10;");
assertThrows(() => result = evaluate("const z = 9;"),
SyntaxError, "Identifier 'z' has already been declared");
result = await evaluate("z;");
assertEquals(10, result)
// Re-declare const as let
result = await evaluate("const g = 12;");
assertThrows(() => result = evaluate("let g = 13;"),
SyntaxError, "Identifier 'g' has already been declared");
result = await evaluate("g;");
assertEquals(12, result);
// Let vs. const in the same script
assertThrows(() => result = evaluate("let h = 13; const h = 14;"),
SyntaxError, "Identifier 'h' has already been declared");
assertThrows(() => result = evaluate("const i = 13; let i = 14;"),
SyntaxError, "Identifier 'i' has already been declared");
// Configurable properties of the global object can be re-declared as let.
result = await evaluate(`Object.defineProperty(globalThis, 'j', {
value: 1,
configurable: true
});`);
result = await evaluate("j;");
assertEquals(1, result);
result = await evaluate("let j = 2;");
result = await evaluate("j;");
assertEquals(2, result);
// Non-configurable properties of the global object (also created by plain old
// top-level var declarations) cannot be re-declared as let.
result = await evaluate(`Object.defineProperty(globalThis, 'k', {
value: 1,
configurable: false
});`);
result = await evaluate("k;");
assertEquals(1, result);
assertThrows(() => result = evaluate("let k = 2;"),
SyntaxError, "Identifier 'k' has already been declared");
result = await evaluate("k;");
assertEquals(1, result);
// ... Except if you do it in the same script.
result = await evaluate(`Object.defineProperty(globalThis, 'k2', {
value: 1,
configurable: false
});
let k2 = 2;`);
result = await evaluate("k2;");
assertEquals(2, result);
result = await evaluate("globalThis.k2;");
assertEquals(1, result);
// But if the property is configurable then both versions are allowed.
result = await evaluate(`Object.defineProperty(globalThis, 'k3', {
value: 1,
configurable: true
});`);
result = await evaluate("k3;");
assertEquals(1, result);
result = await evaluate("let k3 = 2;");
result = await evaluate("k3;");
assertEquals(2, result);
result = await evaluate("globalThis.k3;");
assertEquals(1, result);
result = await evaluate(`Object.defineProperty(globalThis, 'k4', {
value: 1,
configurable: true
});
let k4 = 2;`);
result = await evaluate("k4;");
assertEquals(2, result);
result = await evaluate("globalThis.k4;");
assertEquals(1, result);
// Check var followed by let in the same script.
assertThrows(() => result = evaluate("var k5 = 1; let k5 = 2;"),
SyntaxError, "Identifier 'k5' has already been declared");
// In different scripts.
result = await evaluate("var k6 = 1;");
assertThrows(() => result = evaluate("let k6 = 2;"),
SyntaxError, "Identifier 'k6' has already been declared");
// Check let followed by var in the same script.
assertThrows(() => result = evaluate("let k7 = 1; var k7 = 2;"),
SyntaxError, "Identifier 'k7' has already been declared");
// In different scripts.
result = evaluate("let k8 = 1;");
assertThrows(() => result = evaluate("var k8 = 2;"),
SyntaxError, "Identifier 'k8' has already been declared");
// Check var followed by var in the same script.
result = await evaluate("var k9 = 1; var k9 = 2;");
result = await evaluate("k9;");
assertEquals(2, result);
// In different scripts.
result = await evaluate("var k10 = 1;");
result = await evaluate("var k10 = 2;");
result = await evaluate("k10;");
assertEquals(2, result);
result = await evaluate("globalThis.k10;");
assertEquals(2, result);
// typeof should not throw for undeclared variables
result = await evaluate("typeof k11");
assertEquals("undefined", result);
// Non-configurable properties of the global object (also created by plain old
// top-level var declarations) cannot be re-declared as const.
result = await evaluate(`Object.defineProperty(globalThis, 'k12', {
value: 1,
configurable: false
});`);
result = await evaluate("k12;");
assertEquals(1, result);
assertThrows(() => result = evaluate("const k12 = 2;"),
SyntaxError, "Identifier 'k12' has already been declared");
result = await evaluate("k12;");
assertEquals(1, result);
// ... Except if you do it in the same script.
result = await evaluate(`Object.defineProperty(globalThis, 'k13', {
value: 1,
configurable: false
});
const k13 = 2;`);
result = await evaluate("k13;");
assertEquals(2, result);
result = await evaluate("globalThis.k13;");
assertEquals(1, result);
// But if the property is configurable then both versions are allowed.
result = await evaluate(`Object.defineProperty(globalThis, 'k14', {
value: 1,
configurable: true
});`);
result = await evaluate("k14;");
assertEquals(1, result);
result = await evaluate("const k14 = 2;");
result = await evaluate("k14;");
assertEquals(2, result);
result = await evaluate("globalThis.k14;");
assertEquals(1, result);
result = await evaluate(`Object.defineProperty(globalThis, 'k15', {
value: 1,
configurable: true
});
const k15 = 2;`);
result = await evaluate("k15;");
assertEquals(2, result);
result = await evaluate("globalThis.k15;");
assertEquals(1, result);
// Test lets with names on the object prototype e.g. toString to make sure
// it only works for own properties.
// result = evaluate("let valueOf;");
// REPL vs. non-REPL scripts
// We can still read let values cross-mode.
result = evaluateNonREPL("let l1 = 1; let l2 = 2; let l3 = 3;");
result = await evaluate("l1;");
assertEquals(1, result);
// But we can't re-declare page script lets in a REPL script. We might want to
// later.
assertThrows(() => result = evaluate("let l1 = 2;"),
SyntaxError, "Identifier 'l1' has already been declared");
assertThrows(() => result = evaluate("var l2 = 3;"),
SyntaxError, "Identifier 'l2' has already been declared");
assertThrows(() => result = evaluate("const l3 = 4;"),
SyntaxError, "Identifier 'l3' has already been declared");
// Re-declaring var across modes works.
result = evaluateNonREPL("var l4 = 1; const l5 = 1;");
result = await evaluate("var l4 = 2;");
result = await evaluate("l4;");
assertEquals(2, result);
// Const doesn't.
assertThrows(() => result = evaluate("const l5 = 2;"),
SyntaxError, "Identifier 'l5' has already been declared") ;
result = await evaluate("l5;");
assertEquals(1, result);
// Now REPL followed by non-REPL
result = await evaluate("let l6 = 1; const l7 = 2; let l8 = 3;");
result = evaluateNonREPL("l7;");
assertEquals(2, result);
result = evaluateNonREPL("l6;");
assertEquals(1, result);
// Check that the pattern of `l9; let l9;` does not throw for REPL scripts.
// If REPL scripts behaved the same as normal scripts, this case would
// re-introduce the hole in 'l9's script context slot, causing the IC and feedback
// to 'lie' about the current state.
result = await evaluate("let l9;");
result = await evaluate("l9; let l9;"),
assertEquals(undefined, await evaluate('l9;'));
// Check that binding and re-declaring a function via let works.
result = evaluate("let fn1 = function() { return 21; }");
assertEquals(21, fn1());
result = evaluate("let fn1 = function() { return 42; }");
assertEquals(42, fn1());
// Check that lazily parsed functions that bind a REPL-let variable work.
evaluate("let l10 = 21;");
evaluate("let l10 = 42; function fn2() { return l10; }");
evaluate("let l10 = 'foo';");
assertEquals("foo", fn2());
// Check that binding and re-declaring a function via const works.
result = evaluate("const fn3 = function() { return 21; }");
assertEquals(21, fn3());
result = evaluate("const fn3 = function() { return 42; }");
assertEquals(42, fn3());
// Check that lazily parsed functions that bind a REPL-const variable work.
evaluate("const l11 = 21;");
evaluate("const l11 = 42; function fn4() { return l11; }");
evaluate("const l11 = 'foo1';");
assertEquals("foo1", fn4());
})().catch(e => {
print(e);
print(e.stack);
%AbortJS("Async test is failing");
});

View File

@ -0,0 +1,248 @@
// 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 --experimental-reuse-locals-blocklists
// 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.
//
// This test is an exact copy of `debug-evaluate-shadowed-context` modulo an
// experimental flag. While the feature is in developement, we want to test both
// configurations without having to introduce a separate bot.
Debug = debug.Debug
let test_name;
let listener_delegate;
let listener_called;
let exception;
let begin_test_count = 0;
let end_test_count = 0;
let 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;
print(e, e.stack);
}
}
Debug.setListener(listener);
function BeginTest(name) {
test_name = name;
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++;
}
BeginTest("Check that 'x' resolves correctly and 'a' is written correctly");
var a = "a";
function f1() {
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;
}
listener_delegate = function(exec_state) {
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);
}
f1();
assertEquals("A", a);
a = "a";
EndTest();
BeginTest("Check that a context-allocated 'this' works")
function f2() {
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;
};
// Uses the same listener delgate as for `f1`.
f2();
assertEquals("A", a);
EndTest();
BeginTest("Check that we don't get confused with nested scopes");
function f3() {
var x = 1; // context allocate x
(() => x);
(function() {
var x = 2; // stack allocate shadowing x
(function() {
{ // context allocate x in a nested scope
let x = 3;
(() => x);
}
debugger;
})();
})();
}
listener_delegate = function(exec_state) {
assertThrows(() => exec_state.frame(0).evaluate("x").value());
}
f3();
EndTest();
BeginTest("Check that stack-allocated variable is unavailable");
function f4() {
let a = 1;
let b = 2;
let c = 3;
() => a + c; // a and c are context-allocated
return function g() {
let a = 2; // a is stack-allocated
return function h() {
b; // b is allocated onto f's context.
debugger;
}
}
}
listener_delegate = function(exec_state) {
assertEquals(2, exec_state.frame(0).evaluate("b").value());
assertEquals(3, exec_state.frame(0).evaluate("c").value())
assertThrows(() => exec_state.frame(0).evaluate("a").value());
};
(f4())()();
EndTest();
BeginTest("Check that block lists on the closure boundary work as expected");
function f5() {
let a = 1;
() => a; // a is context-allocated
return function g() {
let a = 2; // a is stack-allocated
{
let b = 3;
return function h() {
debugger;
}
}
}
}
listener_delegate = function(exec_state) {
assertThrows(() => exec_state.frame(0).evaluate("a").value());
};
(f5())()();
EndTest();
BeginTest("Check that outer functions also get the correct block list calculated");
// This test is important once we reuse block list info. The block list for `g`
// needs to be correctly calculated already when we stop on break_position 1.
let break_position;
function f6() {
let a = 1; // stack-allocated
return function g() { // g itself doesn't require a context.
if (break_position === 2) debugger;
let a = 2; (() => a); // context-allocated
return function h() {
if (break_position === 1) debugger;
}
}
}
listener_delegate = function (exec_state) {
assertEquals(2, exec_state.frame(0).evaluate("a").value());
}
break_position = 1;
(f6())()();
EndTest();
BeginTest("Check that outer functions also get the correct block list calculated (continued)");
listener_delegate = function (exec_state) {
assertThrows(() => exec_state.frame(0).evaluate("a").value());
}
break_position = 2;
(f6())()();
EndTest();
BeginTest("Check that 'inner' block lists, calculated on a previous pause, don't block the lookup");
function f7(o) {
let a = 1; // stack-allocated.
with (o) { // create a with-scope whos block-list has 'a' in it.
if (break_position === 2) debugger;
(function g() {
if (break_position === 1) debugger; // Trigger block-list calculation for the with-scope.
})();
}
}
listener_delegate = function (exec_state) {
assertThrows(() => exec_state.frame(0).evaluate("a").value());
}
break_position = 1;
f7({});
EndTest();
BeginTest("Check that 'inner' block lists, calculated on a previous pause, don't block the lookup (continued)");
// The second time we pause the with-scope already has a block-list, but 'a' should be accessible as a
// materialized stack-local.
listener_delegate = function (exec_state) {
assertEquals(1, exec_state.frame(0).evaluate("a").value());
}
break_position = 2;
f7({});
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');

View File

@ -0,0 +1,215 @@
// 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 --no-experimental-reuse-locals-blocklists
// 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
let test_name;
let listener_delegate;
let listener_called;
let exception;
let begin_test_count = 0;
let end_test_count = 0;
let 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;
print(e, e.stack);
}
}
Debug.setListener(listener);
function BeginTest(name) {
test_name = name;
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++;
}
BeginTest("Check that 'x' resolves correctly and 'a' is written correctly");
var a = "a";
function f1() {
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;
}
listener_delegate = function(exec_state) {
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);
}
f1();
assertEquals("A", a);
a = "a";
EndTest();
BeginTest("Check that a context-allocated 'this' works")
function f2() {
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;
};
// Uses the same listener delgate as for `f1`.
f2();
assertEquals("A", a);
EndTest();
BeginTest("Check that we don't get confused with nested scopes");
function f3() {
var x = 1; // context allocate x
(() => x);
(function() {
var x = 2; // stack allocate shadowing x
(function() {
{ // context allocate x in a nested scope
let x = 3;
(() => x);
}
debugger;
})();
})();
}
listener_delegate = function(exec_state) {
assertThrows(() => exec_state.frame(0).evaluate("x").value());
}
f3();
EndTest();
BeginTest("Check that stack-allocated variable is unavailable");
function f4() {
let a = 1;
let b = 2;
let c = 3;
() => a + c; // a and c are context-allocated
return function g() {
let a = 2; // a is stack-allocated
return function h() {
b; // b is allocated onto f's context.
debugger;
}
}
}
listener_delegate = function(exec_state) {
assertEquals(2, exec_state.frame(0).evaluate("b").value());
assertEquals(3, exec_state.frame(0).evaluate("c").value())
assertThrows(() => exec_state.frame(0).evaluate("a").value());
};
(f4())()();
EndTest();
BeginTest("Check that block lists on the closure boundary work as expected");
function f5() {
let a = 1;
() => a; // a is context-allocated
return function g() {
let a = 2; // a is stack-allocated
{
let b = 3;
return function h() {
debugger;
}
}
}
}
listener_delegate = function(exec_state) {
assertThrows(() => exec_state.frame(0).evaluate("a").value());
};
(f5())()();
EndTest();
BeginTest("Check that outer functions also get the correct block list calculated");
// This test is important once we reuse block list info. The block list for `g`
// needs to be correctly calculated already when we stop on break_position 1.
let break_position;
function f6() {
let a = 1; // stack-allocated
return function g() { // g itself doesn't require a context.
if (break_position === 2) debugger;
let a = 2; (() => a); // context-allocated
return function h() {
if (break_position === 1) debugger;
}
}
}
listener_delegate = function (exec_state) {
assertEquals(2, exec_state.frame(0).evaluate("a").value());
}
break_position = 1;
(f6())()();
EndTest();
BeginTest("Check that outer functions also get the correct block list calculated (continued)");
listener_delegate = function (exec_state) {
assertThrows(() => exec_state.frame(0).evaluate("a").value());
}
break_position = 2;
(f6())()();
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');

View File

@ -0,0 +1,82 @@
// 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: --noanalyze-environment-liveness
Debug = debug.Debug
let listenerComplete = false;
let exceptionThrown = false;
let breakPointCount = 0;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break)
{
breakPointCount++;
if (breakPointCount == 1) {
// Break point in first with block.
assertEquals(2, exec_state.frame(0).evaluate('a').value());
assertEquals(2, exec_state.frame(0).evaluate('b').value());
} else if (breakPointCount == 2) {
// Break point in second with block.
assertEquals(3, exec_state.frame(0).evaluate('a').value());
assertEquals(1, exec_state.frame(0).evaluate('b').value());
} else if (breakPointCount == 3) {
// Break point in eval with block.
assertEquals('local', exec_state.frame(0).evaluate('foo').value());
}
}
} catch (e) {
exceptionThrown = true;
};
};
// Add the debug event listener.
Debug.setListener(listener);
function f() {
var a = 1;
var b = 2;
with ({a:2}) {
debugger; // Breakpoint.
x = {a:3,b:1};
with (x) {
debugger; // Breakpoint.
}
}
};
f();
var foo = "global";
eval("with({bar:'with'}) { (function g() { var foo = 'local'; debugger; })(); }");
// Make sure that the debug event listener vas invoked.
assertEquals(3, breakPointCount);
assertFalse(exceptionThrown, "exception in listener");

View File

@ -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
let listenerComplete = false;
let exceptionThrown = 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) {
exceptionThrown = true;
};
};
// 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(exceptionThrown, "exception in listener");
// Make sure that the debug event listener vas invoked.
assertTrue(listenerComplete, "listener did not run to completion");

View File

@ -0,0 +1,71 @@
// 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.
lastDebugEvent = new Object();
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break ||
event == Debug.DebugEvent.Exception)
{
lastDebugEvent.event = event;
lastDebugEvent.frameFuncName = exec_state.frame().func().name();
lastDebugEvent.event_data = event_data;
}
};
// Add the debug event listener.
Debug.setListener(listener);
// Get events from handled exceptions.
Debug.setBreakOnException();
// Test debug event for handled exception.
(function f(){
try {
x();
} catch(e) {
// Do nothing. Ignore exception.
}
})();
assertTrue(lastDebugEvent.event == Debug.DebugEvent.Exception);
assertEquals(lastDebugEvent.frameFuncName, "f");
assertFalse(lastDebugEvent.event_data.uncaught());
Debug.clearBreakOnException();
// Test debug event for break point.
function a() {
x = 1;
y = 2;
z = 3;
};
Debug.setBreakPoint(a, 1);
a();
assertTrue(lastDebugEvent.event == Debug.DebugEvent.Break);
assertEquals(lastDebugEvent.frameFuncName, "a");
Debug.setListener(null);

View File

@ -0,0 +1,87 @@
// 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
let error = false;
let uncaught;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Exception) return;
try {
uncaught = event_data.uncaught();
} catch (e) {
error = true;
}
}
Debug.setBreakOnException();
Debug.setListener(listener);
function assertCaught(f) {
try {f()} finally {
assertFalse(uncaught);
return;
}
}
function assertUncaught(f) {
try {f()} finally {
assertTrue(uncaught);
return;
}
}
assertUncaught(() => {
for (var a of [1, 2, 3]) {
throw a
}
});
assertUncaught(() => {
for (var a of [1, 2, 3]) {
try {throw a} finally {}
}
});
assertCaught(() => {
for (var a of [1, 2, 3]) {
try {
try {throw a} finally {}
} catch(_) {}
}
});
assertCaught(() => {
try {
for (var a of [1, 2, 3]) {
try {throw a} finally {}
}
} catch(_) {}
});
// Check that an internal exception in our yield* desugaring is not observable.
{
uncaught = null;
let iter = {
next() {return {value:42, done:false}},
throw() {return {done:true}}
};
let iterable = {[Symbol.iterator]() {return iter}};
function* f() { yield* iterable }
let g = f();
g.next();
assertEquals({value: undefined, done: true}, g.throw());
assertNull(uncaught); // No exception event was generated.
}
assertFalse(error);

View File

@ -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);

View File

@ -0,0 +1,45 @@
// 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 = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
break_count++;
var line = exec_state.frame(0).sourceLineText();
print(line);
assertTrue(line.indexOf(`B${break_count}`) > 0);
} catch (e) {
exception = e;
}
}
function* g() {
setbreaks();
yield 1; // B1
}
function* f() {
yield* g();
return 2; // B2
}
function setbreaks() {
Debug.setListener(listener);
Debug.setBreakPoint(g, 2);
Debug.setBreakPoint(f, 2);
}
for (let _ of f()) { }
assertEquals(2, break_count);
assertNull(exception);
Debug.setListener(null);

View File

@ -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 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 {
break_count++;
var line = exec_state.frame(0).sourceLineText();
assertTrue(line.indexOf(`B${break_count}`) > 0);
} catch (e) {
exception = e;
}
}
Debug.setListener(listener);
function* g() {
yield 1;
}
function* f() {
yield* g(); // B1
assertEquals(2, break_count); // B2
return 1; // B3
}
Debug.setBreakPoint(f, 1);
Debug.setBreakPoint(f, 2);
Debug.setBreakPoint(f, 3);
for (let _ of f()) { }
assertEquals(3, break_count);
assertNull(exception);
Debug.setListener(null);

View File

@ -0,0 +1,45 @@
// 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: --allow-natives-syntax
Debug = debug.Debug
eval("var something1 = 25; "
+ " function ChooseAnimal() { return 'Cat'; } "
+ " ChooseAnimal.Helper = function() { return 'Help!'; }");
assertEquals("Cat", ChooseAnimal());
var orig_animal = "Cat";
var new_animal_patch = "Cap' + 'y' + 'bara";
var new_source =
Debug.scriptSource(ChooseAnimal).replace(orig_animal, new_animal_patch);
%LiveEditPatchScript(ChooseAnimal, new_source);
assertEquals("Capybara", ChooseAnimal());

View File

@ -0,0 +1,57 @@
// 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-turbofan --allow-natives-syntax
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());
// 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.
%LiveEditPatchScript(
ChooseAnimal, Debug.scriptSource(ChooseAnimal).replace("'Cat'", "'Capybara' + p"));
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());

View File

@ -0,0 +1,63 @@
// 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.
// Flags: --allow-natives-syntax
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 new_source = Debug.scriptSource(Factory).replace(
function_z_text,
'function Intermediate() {\nreturn (\n' + function_z_text + ')\n;\n}\n');
%LiveEditPatchScript(Factory, new_source);
assertEquals(8, z6());
var z100 = Factory(100)();
assertEquals(102, z100());

View File

@ -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-turbofan
// 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.
// Flags: --allow-natives-syntax
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 new_source = Debug.scriptSource(TestFunction).replace('2013', 'b');
print("new source: " + new_source);
%LiveEditPatchScript(TestFunction, new_source);
var res = TestFunction();
print(res);
// This might be 'a,b' without a bug fixed.
assertEquals('a,c', res);

View File

@ -0,0 +1,13 @@
// 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: --allow-natives-syntax
// ()=>42 will have the same start and end position as the top-level script.
var foo = eval("()=>{ return 42 }");
assertEquals(42, foo());
%LiveEditPatchScript(foo, "()=>{ return 13 }");
assertEquals(13, foo());

View File

@ -0,0 +1,142 @@
// 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: --allow-natives-syntax
Debug = debug.Debug
unique_id = 1;
function TestBase(name) {
print("TestBase constructor: " + name);
const original_source = '/* ' + unique_id + '*/\n' +
'(function ChooseAnimal(callback) {\n ' +
' callback();\n' +
' return \'Cat\';\n' +
'})\n';
const updated_source = original_source.replace('\'Cat\'', '\'Capybara\'');
this.ChooseAnimal = eval(original_source);
// Prevents eval script caching.
unique_id++;
const func = this.ChooseAnimal;
var got_exception = false;
var successfully_changed = false;
// Should be called from Debug context.
this.ScriptChanger = () => {
assertEquals(false, successfully_changed, "applying patch second time");
%LiveEditPatchScript(func, updated_source);
successfully_changed = true;
};
}
function Noop() {}
function WrapInCatcher(f, holder) {
return function() {
delete holder[0];
try {
f();
} catch (e) {
if (e.startsWith('LiveEdit failed')) {
holder[0] = e;
} else {
throw e;
}
}
};
}
function WrapInNativeCall(f) {
return function() {
return %Call(f, undefined);
};
}
function ExecuteInDebugContext(f) {
var result;
var exception = null;
Debug.setListener(function(event) {
if (event == Debug.DebugEvent.Break) {
try {
result = f();
} catch (e) {
// Rethrow this exception later.
exception = e;
}
}
});
debugger;
Debug.setListener(null);
if (exception !== null) throw exception;
return result;
}
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 C++ frame above ChooseAnimal frame");
exception_holder = {};
assertEquals("Cat", test.ChooseAnimal(WrapInNativeCall(WrapInDebuggerCall(WrapInCatcher(test.ScriptChanger, exception_holder)))));
assertTrue(!!exception_holder[0]);

View File

@ -0,0 +1,50 @@
// 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: --allow-natives-syntax
Debug = debug.Debug
eval("var something1 = 25; \n"
+ " function ChooseAnimal() { return 'Cat'; } \n"
+ " ChooseAnimal.Helper = function() { return 'Help!'; }\n");
assertEquals("Cat", ChooseAnimal());
var new_source =
Debug.scriptSource(ChooseAnimal).replace('Cat', 'Cap\' + ) + \'bara');
print('new source: ' + new_source);
var caught_exception = null;
try {
%LiveEditPatchScript(ChooseAnimal, new_source);
} catch (e) {
caught_exception = e;
}
assertNotNull(caught_exception);
assertEquals('LiveEdit failed: COMPILE_ERROR', caught_exception);

View File

@ -0,0 +1,27 @@
// 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: --allow-natives-syntax
Debug = debug.Debug
eval("var something1 = 25; "
+ " function ChooseAnimal() { return 'Cat'; } "
+ " ChooseAnimal.Helper = function() { return 'Help!'; }");
function foo() { return ChooseAnimal() }
%PrepareFunctionForOptimization(foo);
assertEquals("Cat", foo());
%OptimizeFunctionOnNextCall(foo);
foo();
var new_source =
Debug.scriptSource(ChooseAnimal).replace('Cat', "Cap' + 'y' + 'bara");
print('new source: ' + new_source);
%LiveEditPatchScript(ChooseAnimal, new_source);
assertEquals("Capybara", foo());

View File

@ -0,0 +1,88 @@
// 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: --allow-natives-syntax
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 new_source =
Debug.scriptSource(ChooseAnimalArray[0]).replace(old_expression, new_expression);
%LiveEditPatchScript(ChooseAnimalArray[0], new_source);
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'");

View File

@ -0,0 +1,71 @@
// 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: --allow-natives-syntax
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 new_source = Debug.scriptSource(ChooseAnimal).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);
%LiveEditPatchScript(ChooseAnimal, new_source);
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"));

View File

@ -0,0 +1,76 @@
// 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).
// Flags: --allow-natives-syntax
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" +
"}"
);
function Changer() {
// Line long enough to change rinfo encoding.
var new_source =
Debug.scriptSource(BeingReplaced).replace("{}", "{return 'Capybara';" +
" " +
"}");
%LiveEditPatchScript(BeingReplaced, new_source);
}
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 BeingReplaced 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);

View File

@ -0,0 +1,42 @@
// Copyright 2018 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: --allow-natives-syntax
Debug = debug.Debug;
function test(i) {
if (i == 3) {
return (function* gen() { yield test(i - 1); })().next().value;
} else if (i > 1) {
return test(i - 1);
} else {
debugger;
return 5;
}
}
let patch = null, exception = null;
Debug.setListener(listener);
patch = ['return 5', 'return 3'];
assertEquals(5, test(2)); // generator on stack
assertEquals(exception,
'LiveEdit failed: BLOCKED_BY_ACTIVE_FUNCTION');
patch = ['return 3', 'return -1'];
assertEquals(5, test(5)); // there is running generator
assertEquals(exception,
'LiveEdit failed: BLOCKED_BY_ACTIVE_FUNCTION');
Debug.setListener(null);
function listener(event) {
if (event != Debug.DebugEvent.Break || !patch) return;
try {
%LiveEditPatchScript(test,
Debug.scriptSource(test).replace(patch[0], patch[1]));
} catch (e) {
exception = e;
}
patch = null;
}

View File

@ -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.
function dbg(x) {
debugger;
}
function foo() {
arguments[0];
dbg();
}
function bar() {
var t = { a : 1 };
dbg();
return t.a;
}
%PrepareFunctionForOptimization(foo);
%PrepareFunctionForOptimization(bar);
foo(1);
foo(1);
bar(1);
bar(1);
%OptimizeFunctionOnNextCall(foo);
%OptimizeFunctionOnNextCall(bar);
var Debug = debug.Debug;
Debug.setListener(function(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
for (var i = 0; i < exec_state.frameCount(); i++) {
var f = exec_state.frame(i);
for (var j = 0; j < f.localCount(); j++) {
if (f.localValue(j).isUnavailable()) {
print(`${f.localName(j)} is unavailable`);
} else {
print("'" + f.localName(j) + "' = " + f.localValue(j).value());
}
}
}
});
foo(1);
bar(1);

View File

@ -0,0 +1,376 @@
// 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-turbofan --no-turbofan
// The first part of this file is copied over from debug-set-variable-value.js
// (a few tests were removed because they make no sense for modules). The second
// part is new.
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(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;
}
})());
// 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);
}
})());
////////////////////////////////////////////////////////////////////////////////
// From here on we test the module scope.
////////////////////////////////////////////////////////////////////////////////
// Non-existing variable.
{
let exception;
function listener(event, exec_state) {
if (event == Debug.DebugEvent.Break) {
let module_scope = exec_state.frame().scope(1);
assertEquals(debug.ScopeType.Module, module_scope.scopeType());
try {
module_scope.setVariableValue('spargel', 42);
} catch(e) { exception = e; }
}
}
Debug.setListener(listener);
assertThrows(() => spargel, ReferenceError);
debugger;
assertThrows(() => spargel, ReferenceError);
assertTrue(exception !== undefined);
}
// Local (non-exported) variable.
let salat = 12;
{
function listener(event, exec_state) {
if (event == Debug.DebugEvent.Break) {
let module_scope = exec_state.frame().scope(1);
assertEquals(debug.ScopeType.Module, module_scope.scopeType());
module_scope.setVariableValue('salat', 42);
}
}
Debug.setListener(listener);
assertEquals(12, salat);
debugger;
assertEquals(42, salat);
}
// Local (non-exported) variable, nested access.
let salad = 12;
{
function listener(event, exec_state) {
if (event == Debug.DebugEvent.Break) {
let scope_count = exec_state.frame().scopeCount();
let module_scope = exec_state.frame().scope(1);
assertEquals(debug.ScopeType.Module, module_scope.scopeType());
module_scope.setVariableValue('salad', 42);
}
}
Debug.setListener(listener);
function foo() {
assertEquals(12, salad);
debugger;
assertEquals(42, salad);
};
foo();
}
// Exported variable.
export let salami = 1;
{
function listener(event, exec_state) {
if (event == Debug.DebugEvent.Break) {
let module_scope = exec_state.frame().scope(1);
assertEquals(debug.ScopeType.Module, module_scope.scopeType());
module_scope.setVariableValue('salami', 2);
}
}
Debug.setListener(listener);
assertEquals(1, salami);
debugger;
assertEquals(2, salami);
}
// Exported variable, nested access.
export let ham = 1;
{
function listener(event, exec_state) {
if (event == Debug.DebugEvent.Break) {
let scope_count = exec_state.frame().scopeCount();
let module_scope = exec_state.frame().scope(1);
assertEquals(debug.ScopeType.Module, module_scope.scopeType());
module_scope.setVariableValue('ham', 2);
}
}
Debug.setListener(listener);
function foo() {
assertEquals(1, ham);
debugger;
assertEquals(2, ham);
};
foo();
}
// Imported variable. Setting is currently not supported.
import { salami as wurst } from "./debug-modules-set-variable-value.mjs";
{
let exception;
function listener(event, exec_state) {
if (event == Debug.DebugEvent.Break) {
let module_scope = exec_state.frame().scope(1);
assertEquals(debug.ScopeType.Module, module_scope.scopeType());
try {
module_scope.setVariableValue('wurst', 3);
} catch(e) { exception = e; }
}
}
Debug.setListener(listener);
assertEquals(2, wurst);
debugger;
assertEquals(2, wurst);
assertTrue(exception !== undefined);
}
// Imported variable, nested access. Setting is currently not supported.
import { salami as wurstl } from "./debug-modules-set-variable-value.mjs";
{
let exception;
function listener(event, exec_state) {
if (event == Debug.DebugEvent.Break) {
let scope_count = exec_state.frame().scopeCount();
let module_scope = exec_state.frame().scope(2);
assertEquals(debug.ScopeType.Module, module_scope.scopeType());
try {
module_scope.setVariableValue('wurstl', 3);
} catch(e) { exception = e; }
}
}
Debug.setListener(listener);
function foo() {
assertEquals(2, wurstl);
debugger;
assertEquals(2, wurstl);
assertTrue(exception !== undefined);
};
foo();
}
Debug.setListener(null);

View File

@ -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);

View File

@ -0,0 +1,74 @@
// 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.StepInto);
}
} 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","v3", // return
];
assertEquals(expected, log);

View File

@ -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);

View File

@ -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.
// Flags: --turbofan --no-always-turbofan --turbo-inlining
var Debug = debug.Debug;
function f1() {
return 1;
}
function f2() {
return 2;
}
function f3() {
return f1();
}
function f4() {
return 4;
}
function optimize(f) {
%PrepareFunctionForOptimization(f);
f();
f();
%OptimizeFunctionOnNextCall(f);
f();
}
optimize(f1);
optimize(f2);
optimize(f3);
Debug.setListener(function() {});
assertOptimized(f1);
assertOptimized(f2);
assertOptimized(f3);
Debug.setBreakPoint(f1, 1);
// Setting break point deoptimizes f1 and f3 (which inlines f1).
assertUnoptimized(f1);
assertOptimized(f2);
assertUnoptimized(f3);
// We can optimize with break points set.
optimize(f4);
assertOptimized(f4);
Debug.setListener(null);

View File

@ -0,0 +1,46 @@
// 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.
// Make sure printing different element kinds doesn't crash.
var array;
var obj = {};
array = [];
%DebugPrint(array);
// PACKED_SMI_ELEMENTS
array = [1, 2, 3];
%DebugPrint(array);
// HOLEY_SMI_ELEMENTS
array[10] = 100;
array[11] = 100;
%DebugPrint(array);
// PACKED_ELEMENTS
array = [1, obj, obj];
%DebugPrint(array);
// HOLEY_ELEMENTS
array[100] = obj;
array[101] = obj;
%DebugPrint(array);
// PACKED_DOUBLE_ELEMENTS
array = [1.1, 2.2, 3.3, 3.3, 3.3, NaN];
%DebugPrint(array);
array.push(NaN);
array.push(NaN);
%DebugPrint(array);
// HOLEY_DOUBLE_ELEMENTS
array[100] = 1.2;
array[101] = 1.2;
%DebugPrint(array);
// DICTIONARY_ELEMENTS
%NormalizeElements(array);
%DebugPrint(array);

View File

@ -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
// explicitly 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');

View File

@ -0,0 +1,116 @@
// 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
let listener_complete = false;
let exceptionThrown = false;
let break_count = 0;
let expected_return_value = 0;
let expected_source_position = [];
let 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(expected_source_position.shift() + debugger_source_position,
exec_state.frame(0).sourcePosition());
break;
case 3:
// Position now at either of the returns.
assertEquals(expected_source_position.shift() + debugger_source_position,
exec_state.frame(0).sourcePosition());
break;
default:
fail("Unexpected");
}
exec_state.prepareStep(Debug.StepAction.StepInto);
} else {
// Position at the end of the function.
assertEquals(expected_source_position.shift() + debugger_source_position,
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) {
exceptionThrown = true;
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;
expected_source_position = [10, 38, 47];
listener_complete = false;
f();
assertFalse(exceptionThrown, "exception in listener");
assertTrue(listener_complete);
assertEquals(4, break_count);
break_count = 0;
expected_return_value = 1;
expected_source_position = [10, 19, 28];
listener_complete = false;
f(true);
assertFalse(exceptionThrown, "exception in listener");
assertTrue(listener_complete);
assertEquals(4, break_count);
break_count = 0;
expected_return_value = 2;
expected_source_position = [10, 38, 47];
listener_complete = false;
f(false);
assertFalse(exceptionThrown, "exception in listener");
assertTrue(listener_complete);
assertEquals(4, break_count);

View File

@ -0,0 +1,460 @@
// 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-analyze-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 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.Local,
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.Local,
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.Local,
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;
yield a;
return b;
}
g = gen4(0, 1);
CheckScopeChain([debug.ScopeType.Local,
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');
yield a;
return b;
}
g = gen5(1);
g.next();
CheckScopeChain([debug.ScopeType.Local,
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.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], g);
CheckScopeContent({}, 0, g);
g.next();
CheckScopeChain([debug.ScopeType.Local,
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.Local,
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.Local,
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.Local,
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.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], g);
CheckScopeContent({i: 0}, 0, g);
g.next();
CheckScopeContent({i: 1}, 0, g);
// Nested generators.
var gen12;
function *gen11() {
var b = 2;
gen12 = function*() {
var a = 1;
yield 1;
return b;
}();
var a = 0;
yield* gen12;
}
gen11().next();
g = gen12;
CheckScopeChain([debug.ScopeType.Local,
debug.ScopeType.Closure,
debug.ScopeType.Script,
debug.ScopeType.Global], g);
CheckScopeContent({a: 1}, 0, g);
CheckScopeContent({b: 2}, 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.Local,
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.Local,
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.Local,
debug.ScopeType.Script,
debug.ScopeType.Global], g);
CheckScopeContent({d: 4, e: undefined}, 0, g);
CheckScopeContent({a: 1, b: 2}, 1, g);
CheckScopeContent({c: 3}, 2, g);
Debug.generatorScope(g, 0).setVariableValue("d", 1);
CheckScopeContent({d: 1, e: undefined}, 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.Local,
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);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,287 @@
// 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: --noalways-turbofan
// Flags: --no-always-turbofan
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);

View File

@ -0,0 +1,31 @@
// 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.
// Check that even though we schedule and break on function entry, we still
// pause on the first breakable position.
var Debug = debug.Debug;
var exception = null;
var loop = true;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
assertTrue(exec_state.frame(0).sourceLineText().indexOf("BREAK") > 0);
} catch (e) {
exception = e;
}
}
function f() {
return 1; // BREAK
}
Debug.setListener(listener);
%ScheduleBreak(); // Break on function entry.
f();
Debug.setListener(null);
assertNull(exception);

View File

@ -0,0 +1,61 @@
// 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.
const Debug = new DebugWrapper();
Debug.enable();
// This test tests that full code compiled without debug break slots
// is recompiled with debug break slots when debugging is started.
var bp;
var done = false;
var step_count = 0;
// 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) Debug.stepOver();
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.
function f() {
var i = 1;
var j = 2;
done = true;
};
prepare_step_test();
f();
// Add the debug event listener.
Debug.setListener(listener);
bp = Debug.setBreakPoint(f, 1);
prepare_step_test();
f();
assertEquals(4, step_count);
Debug.clearBreakPoint(bp);
// Set a breakpoint on the first var statement (line 1).
bp = Debug.setBreakPoint(f, 1);
// Step through the function ensuring that the var statements are hit as well.
prepare_step_test();
f();
assertEquals(4, step_count);
// Clear the breakpoint and check that no stepping happens.
Debug.clearBreakPoint(bp);
prepare_step_test();
f();
assertEquals(0, step_count);

View File

@ -0,0 +1,68 @@
// 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.
const Debug = new DebugWrapper();
Debug.enable();
// This test tests that full code compiled without debug break slots
// is recompiled with debug break slots when debugging is started.
var bp;
var done = false;
var step_count = 0;
var set_bp = false
// 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) Debug.stepOver();
step_count++;
}
};
// Set the global variables state to prepare the stepping test.
function prepare_step_test() {
done = false;
step_count = 0;
}
// Test function to step through.
function f() {
var a = 0;
if (set_bp) { bp = Debug.setBreakPoint(f, 3); }
var i = 1;
var j = 2;
done = true;
};
prepare_step_test();
f();
// Add the debug event listener.
Debug.setListener(listener);
// Make f set a breakpoint with an activation on the stack.
prepare_step_test();
set_bp = true;
f();
assertEquals(4, step_count);
Debug.clearBreakPoint(bp);
// Set a breakpoint on the first var statement (line 1).
set_bp = false;
bp = Debug.setBreakPoint(f, 3);
// Step through the function ensuring that the var statements are hit as well.
prepare_step_test();
f();
assertEquals(4, step_count);
// Clear the breakpoint and check that no stepping happens.
Debug.clearBreakPoint(bp);
prepare_step_test();
f();
assertEquals(0, step_count);
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -0,0 +1,80 @@
// 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.
const Debug = new DebugWrapper();
Debug.enable();
// Tests how debugger can step over not necessarily in the top frame.
// Simple 3 functions, that protocol their execution state in global
// variable state.
var state;
function f() {
var a = 1978;
for (state[2] = 0; state[2] < 3; state[2]++) {
void String(a);
}
}
function g() {
for (state[1] = 0; state[1] < 3; state[1]++) {
f();
}
}
function h() {
state = [-1, -1, -1];
for (state[0] = 0; state[0] < 3; state[0]++) {
g();
}
}
function TestCase(expected_final_state) {
var listener_exception = null;
var state_snapshot;
var listener_state;
var bp;
function listener(event, exec_state, event_data, data) {
const location = exec_state.frames[0].location
print("Here (" + event + "/" + listener_state + "): " +
location.lineNumber + ":" + location.columnNumber);
try {
if (event == Debug.DebugEvent.Break) {
if (listener_state == 0) {
Debug.clearBreakPoint(bp);
Debug.stepOver();
listener_state = 1;
} else if (listener_state == 1) {
state_snapshot = String(state);
print("State: " + state_snapshot);
Debug.setListener(null);
listener_state = 2;
}
}
} catch (e) {
listener_exception = e;
}
}
// Add the debug event listener.
listener_state = 0;
Debug.setListener(listener);
bp = Debug.setBreakPoint(f, 1);
h();
Debug.setListener(null);
if (listener_exception !== null) {
print("Exception caught: " + listener_exception);
assertUnreachable();
}
assertEquals(expected_final_state, state_snapshot);
}
// Warm-up -- make sure all is compiled and ready for breakpoint.
h();
TestCase("0,0,-1");

View File

@ -0,0 +1,20 @@
// 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;", ""];
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
assertEquals(expected.shift(), exec_state.frame(0).sourceLineText());
exec_state.prepareStep(Debug.StepAction.StepOver);
} catch (e) {
%AbortJS(e + "\n" + e.stack);
}
}
Debug.setListener(listener);
debugger;

View File

@ -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.
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());
assertTrue(
event_data.sourceLineText().indexOf(`Break ${break_count++}.`) > 0);
exec_state.prepareStep(Debug.StepAction.StepInto);
} catch (e) {
exception = e;
}
};
function toJsonCallback() {
return "x" // Break 2.
; // Break 3.
}
var o = {};
o.toJSON = toJsonCallback;
Debug.setListener(listener);
debugger; // Break 0.
var result = JSON.stringify(o); // Break 1.
Debug.setListener(null); // Break 4.
assertEquals('"x"', result);
assertNull(exception);

View File

@ -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.
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());
assertTrue(event_data.sourceLineText().indexOf(`Break ${break_count++}.`) > 0);
exec_state.prepareStep(Debug.StepAction.StepInto);
} catch (e) {
exception = e;
}
};
function valueOfCallback() {
return 2 // Break 2.
; // Break 3.
}
var o = {};
o.valueOf = valueOfCallback;
Debug.setListener(listener);
debugger; // Break 0.
var result = 1 + o; // Break 1.
Debug.setListener(null); // Break 4.
assertEquals(3, result);
assertNull(exception);

View File

@ -0,0 +1,52 @@
// 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.
Debug = debug.Debug
var exception = null;
var log = [];
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
var line = exec_state.frame(0).sourceLineText();
log.push(line);
if (!/STOP/.test(line)) {
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
} catch (e) {
exception = e;
}
};
Debug.setListener(listener);
Promise.resolve().then(
function() {
print(1);
}
).then(
function() {
return 2;
}
).then(
function() {
throw new Error();
}
).catch(
function() {
print(3);
} // STOP
);
setTimeout(function() {
Debug.setListener(null);
assertNull(exception);
var expectation =
["debugger;",""," print(1);","}"," return 2;"," return 2;",
" throw new Error();"," print(3);","} // STOP"];
assertEquals(log, expectation);
});
debugger;

View File

@ -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
// Simple debug event handler which counts the number of breaks hit and steps.
var break_break_point_hit_count = 0;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
break_break_point_hit_count++;
// Continue stepping until returned to bottom frame.
if (exec_state.frameCount() > 1) {
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
};
// Add the debug event listener.
Debug.setListener(listener);
// Use 'eval' to ensure that the call to print is through CodeStub CallFunction.
// See Ia32CodeGenerator::VisitCall and Ia32CodeGenerator::CallWithArguments.
function f() {
debugger;
eval('');
print('Hello, world!');
};
break_break_point_hit_count = 0;
f();
assertEquals(6, break_break_point_hit_count);
// Use an inner function to ensure that the function call is through CodeStub
// CallFunction see Ia32CodeGenerator::VisitCall and
// Ia32CodeGenerator::CallWithArguments.
function g() {
function h() {}
debugger;
h();
};
break_break_point_hit_count = 0;
g();
assertEquals(5, break_break_point_hit_count);
// Use an inner function to ensure that the function call is through CodeStub
// CallFunction.
function testCallInExpreesion() {
function h() {}
debugger;
var x = 's' + h(10, 20);
};
break_break_point_hit_count = 0;
testCallInExpreesion();
assertEquals(5, break_break_point_hit_count);
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -0,0 +1,58 @@
// 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: --turbo-filter=g
// Test that Debug::PrepareForBreakPoints can deal with turbofan code (g)
// on the stack. Without deoptimization support, we will not be able to
// replace optimized code for g by unoptimized code with debug break slots.
// This would cause stepping to fail (V8 issue 3660).
function f(x) {
g(x);
var a = 0; // Break 6
return a; // Break 7
} // Break 8
function g(x) {
if (x) h();
var a = 0; // Break 2
var b = 1; // Break 3
return a + b; // Break 4
} // Break 5
function h() {
debugger; // Break 0
} // Break 1
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 {
exec_state.prepareStep(Debug.StepAction.StepOver);
print(exec_state.frame(0).sourceLineText());
var match = exec_state.frame(0).sourceLineText().match(/Break (\d)/);
assertNotNull(match);
assertEquals(break_count++, parseInt(match[1]));
} catch (e) {
print(e + e.stack);
exception = e;
}
}
%PrepareFunctionForOptimization(g);
f(0);
f(0);
%OptimizeFunctionOnNextCall(g);
Debug.setListener(listener);
f(1);
Debug.setListener(null); // Break 9
assertNull(exception);
assertEquals(10, break_count);

View File

@ -0,0 +1,49 @@
// 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: --cache=code
Debug = debug.Debug
// 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) {
exec_state.prepareStep(Debug.StepAction.StepInto);
step_count--;
} else {
result = exec_state.frame().evaluate("i").value();
// Clear the break point on line 2 if set.
if (bp2) {
Debug.clearBreakPoint(bp2);
}
}
}
};
// Add the debug event listener.
Debug.setListener(listener);
// Test debug event for break point.
function f() {
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).
bp1 = Debug.setBreakPoint(f, 1);
// Check that performing 1000 steps will make i 333.
var step_count = 1000;
result = -1;
f();
assertEquals(333, result);
Debug.setListener(null);

View File

@ -0,0 +1,48 @@
// 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 get() {
return 3; // Break
} // Break
function set(x) {
this.x = x; // Break
} // Break
var o = {};
Object.defineProperty(o, "get", { get : get });
Object.defineProperty(o, "set", { set : set });
function f() {
for (var i = 0; i < 10; i++) { // Break
o.get; // Break
o.set = 1; // Break
}
} // Break
var break_count = 0;
var exception = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
var source_line = exec_state.frame(0).sourceLineText();
assertTrue(source_line.indexOf("// Break") > 0);
exec_state.prepareStep(Debug.StepAction.StepInto);
break_count++;
} catch (e) {
exception = e;
}
}
var Debug = debug.Debug;
Debug.setListener(listener);
debugger; // Break
f(); // Break
Debug.setListener(null); // Break
assertEquals(86, break_count);
assertNull(exception);

View File

@ -0,0 +1,247 @@
// 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 = null;
var state = 1;
var expected_source_line_text = null;
var expected_function_name = null;
// Simple debug event handler which first time will cause 'step in' action
// to get into g.call and than check that execution is stopped inside
// function 'g'.
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
if (state == 3) {
assertEquals(expected_source_line_text,
event_data.sourceLineText());
assertEquals(expected_function_name, event_data.func().name());
state = 4;
} else {
exec_state.prepareStep(Debug.StepAction.StepInto);
state++;
}
}
} catch(e) {
exception = e;
}
};
// Add the debug event listener.
Debug.setListener(listener);
var c = {
name: 'name ',
get getter1() {
return this.name; // getter 1
},
get getter2() {
return { // getter 2
'a': c.name
};
},
set setter1(n) {
this.name = n; // setter 1
}
};
c.__defineGetter__('y', function getterY() {
return this.name; // getter y
});
c.__defineGetter__(3, function getter3() {
return this.name; // getter 3
});
c.__defineSetter__('y', function setterY(n) {
this.name = n; // setter y
});
c.__defineSetter__(3, function setter3(n) {
this.name = n; // setter 3
});
var d = {
'c': c,
};
function testGetter1_1() {
expected_function_name = 'get getter1';
expected_source_line_text = ' return this.name; // getter 1';
debugger;
var x = c.getter1;
}
function testGetter1_2() {
expected_function_name = 'get getter1';
expected_source_line_text = ' return this.name; // getter 1';
debugger;
var x = c['getter1'];
}
function testGetter1_3() {
expected_function_name = 'get getter1';
expected_source_line_text = ' return this.name; // getter 1';
for (var i = 1; i < 2; i++) {
debugger;
var x = c['getter' + i];
}
}
function testGetter1_4() {
expected_function_name = 'get getter1';
expected_source_line_text = ' return this.name; // getter 1';
debugger;
var x = d.c.getter1;
}
function testGetter1_5() {
expected_function_name = 'get getter1';
expected_source_line_text = ' return this.name; // getter 1';
for (var i = 2; i != 1; i--);
debugger;
var x = d.c['getter' + i];
}
function testGetter2_1() {
expected_function_name = 'get getter2';
expected_source_line_text = ' return { // getter 2';
for (var i = 2; i != 1; i--);
debugger;
var t = d.c.getter2.name;
}
function testGetterY_1() {
expected_function_name = 'getterY';
expected_source_line_text = ' return this.name; // getter y';
debugger;
var t = d.c.y;
}
function testIndexedGetter3_1() {
expected_function_name = 'getter3';
expected_source_line_text = ' return this.name; // getter 3';
debugger;
var r = d.c[3];
}
function testSetterY_1() {
expected_function_name = 'setterY';
expected_source_line_text = ' this.name = n; // setter y';
debugger;
d.c.y = 'www';
}
function testIndexedSetter3_1() {
expected_function_name = 'setter3';
expected_source_line_text = ' this.name = n; // setter 3';
var i = 3
debugger;
d.c[3] = 'www';
}
function testSetter1_1() {
expected_function_name = 'set setter1';
expected_source_line_text = ' this.name = n; // setter 1';
debugger;
d.c.setter1 = 'aa';
}
function testSetter1_2() {
expected_function_name = 'set setter1';
expected_source_line_text = ' this.name = n; // setter 1';
debugger;
d.c['setter1'] = 'bb';
}
function testSetter1_3() {
expected_function_name = 'set setter1';
expected_source_line_text = ' this.name = n; // setter 1';
for (var i = 2; i != 1; i--);
debugger;
d.c['setter' + i] = i;
}
var e = {
name: 'e'
};
e.__proto__ = c;
function testProtoGetter1_1() {
expected_function_name = 'get getter1';
expected_source_line_text = ' return this.name; // getter 1';
debugger;
var x = e.getter1;
}
function testProtoSetter1_1() {
expected_function_name = 'set setter1';
expected_source_line_text = ' this.name = n; // setter 1';
debugger;
e.setter1 = 'aa';
}
function testProtoIndexedGetter3_1() {
expected_function_name = 'getter3';
expected_source_line_text = ' return this.name; // getter 3';
debugger;
var x = e[3];
}
function testProtoIndexedSetter3_1() {
expected_function_name = 'setter3';
expected_source_line_text = ' this.name = n; // setter 3';
debugger;
e[3] = 'new val';
}
function testProtoSetter1_2() {
expected_function_name = 'set setter1';
expected_source_line_text = ' this.name = n; // setter 1';
for (var i = 2; i != 1; i--);
debugger;
e['setter' + i] = 'aa';
}
for (var n in this) {
if (n.substr(0, 4) != 'test' ||
n == 'testRunner' || n == 'testAsync') {
continue;
}
state = 1;
this[n]();
if (exception) throw exception;
assertEquals(4, state);
}
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -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.
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());
assertTrue(
event_data.sourceLineText().indexOf(`Break ${break_count++}.`) > 0);
exec_state.prepareStep(Debug.StepAction.StepInto);
} catch (e) {
exception = e;
}
};
function replaceCallback(a) {
return "x" // Break 2.
; // Break 3.
}
var re = /x/g;
// Optimize the inner helper function for string replace.
for (var i = 0; i < 10000; i++) "x".replace(re, replaceCallback);
Debug.setListener(listener);
debugger; // Break 0.
var result = "x".replace(re, replaceCallback); // Break 1.
Debug.setListener(null); // Break 4.
assertNull(exception);

View File

@ -0,0 +1,143 @@
// 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 stepping into callbacks passed to builtin functions.
Debug = debug.Debug
var exception = null;
function array_listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
print(event_data.sourceLineText(), breaks);
assertTrue(event_data.sourceLineText().indexOf(`B${breaks++}`) > 0);
exec_state.prepareStep(Debug.StepAction.StepInto);
}
} catch (e) {
print(e);
quit();
exception = e;
}
};
function cb_false(num) {
print("element " + num); // B2 B5 B8
return false; // B3 B6 B9
} // B4 B7 B10
function cb_true(num) {
print("element " + num); // B2 B5 B8
return true; // B3 B6 B9
} // B4 B7 B10
function cb_reduce(a, b) {
print("elements " + a + " and " + b); // B2 B5
return a + b; // B3 B6
} // B4 B7
var a = [1, 2, 3];
var breaks = 0;
Debug.setListener(array_listener);
debugger; // B0
a.forEach(cb_true); // B1
Debug.setListener(null); // B11
assertNull(exception);
assertEquals(12, breaks);
breaks = 0;
Debug.setListener(array_listener);
debugger; // B0
a.some(cb_false); // B1
Debug.setListener(null); // B11
assertNull(exception);
assertEquals(12, breaks);
breaks = 0;
Debug.setListener(array_listener);
debugger; // B0
a.every(cb_true); // B1
Debug.setListener(null); // B11
assertNull(exception);
assertEquals(12, breaks);
breaks = 0;
Debug.setListener(array_listener);
debugger; // B0
a.map(cb_true); // B1
Debug.setListener(null); // B11
assertNull(exception);
assertEquals(12, breaks);
breaks = 0;
Debug.setListener(array_listener);
debugger; // B0
a.filter(cb_true); // B1
Debug.setListener(null); // B11
assertNull(exception);
assertEquals(12, breaks);
breaks = 0;
Debug.setListener(array_listener);
debugger; // B0
a.reduce(cb_reduce); // B1
Debug.setListener(null); // B8
assertNull(exception);
assertEquals(9, breaks);
breaks = 0;
Debug.setListener(array_listener);
debugger; // B0
a.reduceRight(cb_reduce); // B1
Debug.setListener(null); // B8
assertNull(exception);
assertEquals(9, breaks);
// Test two levels of builtin callbacks:
// Array.forEach calls a callback function, which by itself uses
// Array.forEach with another callback function.
function cb_true_2(num) {
print("element " + num); // B3 B6 B9 B15 B18 B21 B27 B30 B33
return true; // B4 B7 B10 B16 B19 B22 B28 B31 B34
} // B5 B8 B11 B17 B20 B23 B29 B32 B35
function cb_foreach(num) {
a.forEach(cb_true_2); // B2 B14 B20 B26
print("back."); // B12 B18 B24 B36
} // B13 B19 B25 B37
breaks = 0;
Debug.setListener(array_listener);
debugger; // B0
a.forEach(cb_foreach); // B1
Debug.setListener(null); // B38
assertNull(exception);
assertEquals(39, breaks);

View File

@ -0,0 +1,76 @@
// 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 = null;
var state = 1;
var expected_source_line_text = null;
var expected_function_name = null;
// Simple debug event handler which first time will cause 'step in' action
// and than check that execution is paused inside function
// expected_function_name.
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
if (state == 3) {
assertEquals(expected_function_name, event_data.func().name());
assertEquals(expected_source_line_text,
event_data.sourceLineText());
state = 4;
} else {
exec_state.prepareStep(Debug.StepAction.StepInto);
state++;
}
}
} catch(e) {
exception = e;
}
};
// Add the debug event listener.
Debug.setListener(listener);
var a = [1,2,3,4,5];
// Test step into function call from a function without local variables.
function testStepInArraySlice() {
expected_function_name = 'testStepInArraySlice';
expected_source_line_text = '} // expected line';
debugger;
var s = Array.prototype.slice.call(a, 2,3);
} // expected line
state = 1;
testStepInArraySlice();
assertNull(exception);
assertEquals(4, state);
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -0,0 +1,115 @@
// 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 = null;
var state = 0;
var expected_function_name = null;
var expected_source_line_text = null;
var expected_caller_source_line = null;
var step_in_count = 2;
// Simple debug event handler which first time will cause 'step in' action
// to get into g.call and than check that execution is pauesed inside
// function 'g'.
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
if (state < step_in_count) {
// Step into f().
exec_state.prepareStep(Debug.StepAction.StepInto);
state++;
} else {
assertEquals(expected_source_line_text,
event_data.sourceLineText());
assertEquals(expected_function_name, event_data.func().name());
state = 3;
}
}
} catch(e) {
exception = e;
}
};
// Add the debug event listener.
Debug.setListener(listener);
function g() {
return "s"; // expected line
}
function testFunction() {
var f = g;
var s = 1 +f(10);
}
function g2() {
return "s2"; // expected line
}
function testFunction2() {
var f = g2;
var s = 1 +f(10, 20);
}
// Run three times. First time the function will be compiled lazily,
// second time cached version will be used.
for (var i = 0; i < 3; i++) {
state = 0;
expected_function_name = 'g';
expected_source_line_text = ' return "s"; // expected line';
step_in_count = 2;
// Set a break point and call to invoke the debug event listener.
const breakid = Debug.setBreakPoint(testFunction, 1, 0);
testFunction();
Debug.clearBreakPoint(breakid);
assertNull(exception);
assertEquals(3, state);
}
// Test stepping into function call when a breakpoint is set at the place
// of call. Use different pair of functions so that g2 is compiled lazily.
// Run twice: first time function will be compiled lazily, second time
// cached version will be used.
for (var i = 0; i < 3; i++) {
state = 0;
expected_function_name = 'g2';
expected_source_line_text = ' return "s2"; // expected line';
step_in_count = 1;
// Set a break point and call to invoke the debug event listener.
const breakid = Debug.setBreakPoint(testFunction2, 2, 0);
testFunction2();
Debug.clearBreakPoint(breakid);
assertNull(exception);
assertEquals(3, state);
}
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -0,0 +1,39 @@
// 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 break_count = 0;
var exception = null;
function listener(event, exec_state, event_data, data) {
if (event != Debug.DebugEvent.Break) return;
try {
var source_line = exec_state.frame(0).sourceLineText();
print(source_line);
exec_state.prepareStep(Debug.StepAction.StepInto);
break_count++;
} catch (e) {
exception = e;
}
}
var Debug = debug.Debug;
Debug.setListener(listener);
function f() {
this.x = 1;
}
function g() {
new f();
}
Debug.setBreakPoint(g, 6);
g();
Debug.setListener(null);
assertEquals(6, break_count);
assertNull(exception);

View File

@ -0,0 +1,73 @@
// 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 counts the number of breaks hit and steps.
var break_break_point_hit_count = 0;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
break_break_point_hit_count++;
// Continue stepping until returned to bottom frame.
if (exec_state.frameCount() > 1) {
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
};
// Add the debug event listener.
Debug.setListener(listener);
// Test step into constructor with simple constructor.
function X() {
}
function f() {
debugger;
new X();
};
break_break_point_hit_count = 0;
f();
assertEquals(5, break_break_point_hit_count);
f();
assertEquals(10, break_break_point_hit_count);
f();
assertEquals(15, break_break_point_hit_count);
// Test step into constructor with builtin constructor.
function g() {
debugger;
new Date();
};
break_break_point_hit_count = 0;
g();
assertEquals(4, break_break_point_hit_count);
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -0,0 +1,47 @@
// 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.
// Tests stepping into through Array.prototype.forEach callbacks.
Debug = debug.Debug
var exception = null;
var break_count = 0;
var expected_breaks = 11;
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 + ".");
++break_count;
if (break_count !== expected_breaks) {
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
} catch(e) {
exception = e;
print(e, e.stack);
}
};
Debug.setListener(listener);
var bound_callback = callback.bind(null);
debugger; // Break 0.
[1,2].forEach(callback); // Break 1.
[3,4].forEach(bound_callback); // Break 6.
function callback(x) {
return x // Break 2. // Break 4. // Break 7. // Break 9.
; // Break 3. // Break 5. // Break 8. // Break 10.
}
assertNull(exception); // Break 11.
assertEquals(expected_breaks, break_count);
Debug.setListener(null);

View File

@ -0,0 +1,173 @@
// 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
var exception = null;
var state = 0;
// Simple debug event handler which first time will cause 'step in' action
// to get into g.call and than check that execution is pauesed inside
// function 'g'.
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
if (state < 2) {
// Step into f2.call:
exec_state.prepareStep(Debug.StepAction.StepInto);
state++;
} else {
assertEquals('g', event_data.func().name());
assertEquals(' return t + 1; // expected line',
event_data.sourceLineText());
state = 3;
}
}
} catch(e) {
exception = e;
}
};
// Add the debug event listener.
Debug.setListener(listener);
// Sample functions.
function g(t) {
return t + 1; // expected line
}
// Test step into function call from a function without local variables.
function call1() {
debugger;
g.call(null, 3);
}
// Test step into function call from a function with some local variables.
function call2() {
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
debugger;
g.call(null, 3);
}
// Test step into function call which is a part of an expression.
function call3() {
var alias = g;
debugger;
var r = 10 + alias.call(null, 3);
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
}
// Test step into function call from a function with some local variables.
function call4() {
var alias = g;
debugger;
alias.call(null, 3);
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
}
// Test step into function apply from a function without local variables.
function apply1() {
debugger;
g.apply(null, [3]);
}
// Test step into function apply from a function with some local variables.
function apply2() {
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
debugger;
g.apply(null, [3, 4]);
}
// Test step into function apply which is a part of an expression.
function apply3() {
var alias = g;
debugger;
var r = 10 + alias.apply(null, [3, 'unused arg']);
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
}
// Test step into function apply from a function with some local variables.
function apply4() {
var alias = g;
debugger;
alias.apply(null, [3]);
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
}
// Test step into bound function.
function bind1() {
var bound = g.bind(null, 3);
debugger;
bound();
}
// Test step into apply of bound function.
function applyAndBind1() {
var bound = g.bind(null, 3);
debugger;
bound.apply(null, [3]);
var aLocalVar = 'test';
var anotherLocalVar = g(aLocalVar) + 's';
var yetAnotherLocal = 10;
}
var testFunctions =
[call1, call2, call3, call4, apply1, apply2, apply3, apply4, bind1,
applyAndBind1];
for (var i = 0; i < testFunctions.length; i++) {
state = 0;
testFunctions[i]();
assertNull(exception);
assertEquals(3, state);
}
// Test global bound function.
state = 0;
var globalBound = g.bind(null, 3);
debugger;
globalBound();
assertNull(exception);
assertEquals(3, state);
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -0,0 +1,152 @@
// Copyright 2014 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: --noturbofan
Debug = debug.Debug
var exception = null;
var state = 1;
// Simple debug event handler which first time will cause 'step in' action
// to get into g.call and than check that execution is stopped inside
// function 'g'.
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
if (state < 4) {
exec_state.prepareStep(Debug.StepAction.StepInto);
state++;
} else {
assertTrue(event_data.sourceLineText().indexOf("Expected to step") > 0,
"source line: \"" + event_data.sourceLineText() + "\"");
state = 5;
}
}
} catch(e) {
print("Exception: " + e);
exception = e;
}
};
// Add the debug event listener.
Debug.setListener(listener);
var count = 0;
var obj = {
fun: function() {
++count;
return count; // Expected to step
}
};
obj.fun2 = obj.fun;
function testCall_Dots() {
debugger;
obj.fun();
}
function testCall_Quotes() {
debugger;
obj["fun"]();
}
function testCall_Call() {
debugger;
obj.fun.call(obj);
}
function testCall_Apply() {
debugger;
obj.fun.apply(obj);
}
function testCall_Variable() {
var functionName = "fun";
debugger;
obj[functionName]();
}
function testCall_Fun2() {
debugger;
obj.fun2();
}
function testCall_InternStrings() {
var cache = { "fun": "fun" };
var functionName = "fu" + "n";
debugger;
obj[cache[functionName]]();
}
function testCall_ViaFunRef() {
var functionName = "fu" + "n";
var funRef = obj[functionName];
debugger;
funRef();
}
// bug 2888
function testCall_RuntimeVariable1() {
var functionName = "fu" + "n";
debugger;
obj[functionName]();
}
// bug 2888
function testCall_RuntimeVariable2() {
var functionName = "un".replace(/u/, "fu");
debugger;
obj[functionName]();
}
// bug 2888
function testCall_RuntimeVariable3() {
var expr = "fu" + "n";
const functionName = expr;
assertEquals("fun", functionName);
debugger;
obj[functionName]();
}
var functionsCalled = 0;
for (var n in this) {
if (n.substr(0, 4) != 'test' || typeof this[n] !== "function" || n == 'testAsync') {
continue;
}
state = 1;
print("Running " + n + "...");
this[n]();
++functionsCalled;
assertNull(exception, n);
assertEquals(5, state, n);
assertEquals(functionsCalled, count, n);
}
assertEquals(11, functionsCalled);
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -0,0 +1,77 @@
// 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 = null;
var break_break_point_hit_count = 0;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
if (break_break_point_hit_count == 0) {
assertEquals(' debugger;',
event_data.sourceLineText());
assertEquals('runDoWhile', event_data.func().name());
} else if (break_break_point_hit_count == 1) {
assertEquals(' } while(condition());',
event_data.sourceLineText());
assertEquals('runDoWhile', event_data.func().name());
}
break_break_point_hit_count++;
// Continue stepping until returned to bottom frame.
if (exec_state.frameCount() > 1) {
exec_state.prepareStep(Debug.StepAction.StepOver);
}
}
} catch(e) {
exception = e;
}
};
// Add the debug event listener.
Debug.setListener(listener);
function condition() {
return false;
}
function runDoWhile() {
do {
debugger;
} while(condition());
};
break_break_point_hit_count = 0;
runDoWhile();
assertNull(exception);
assertEquals(4, break_break_point_hit_count);
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -0,0 +1,99 @@
// 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 = null;
// Simple debug event handler which counts the number of breaks hit and steps.
var break_point_hit_count = 0;
function listener(event, exec_state, event_data, data) {
try {
if (event == Debug.DebugEvent.Break) {
break_point_hit_count++;
// Continue stepping until returned to bottom frame.
if (exec_state.frameCount() > 1) {
exec_state.prepareStep(Debug.StepAction.StepOut);
}
}
} catch(e) {
exception = e;
}
};
function BeginTest(name) {
test_name = name;
break_point_hit_count = 0;
exception = null;
}
function EndTest(expected_break_point_hit_count) {
assertEquals(expected_break_point_hit_count, break_point_hit_count, test_name);
assertNull(exception, test_name);
test_name = null;
}
// Add the debug event listener.
Debug.setListener(listener);
var shouldBreak = null;
function fact(x) {
if (shouldBreak(x)) {
debugger;
}
if (x < 2) {
return 1;
} else {
return x*fact(x-1);
}
}
BeginTest('Test 1');
shouldBreak = function(x) { return x == 3; };
fact(3);
EndTest(2);
BeginTest('Test 2');
shouldBreak = function(x) { return x == 2; };
fact(3);
EndTest(3);
BeginTest('Test 3');
shouldBreak = function(x) { return x == 1; };
fact(3);
EndTest(4);
BeginTest('Test 4');
shouldBreak = function(x) { return x == 1 || x == 3; };
fact(3);
EndTest(5);
// Get rid of the debug event listener.
Debug.setListener(null);

View File

@ -0,0 +1,187 @@
// 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.
// Check that the ScopeIterator can properly recreate the scope at
// every point when stepping through functions.
var Debug = debug.Debug;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
// Access scope details.
var scope_count = exec_state.frame().scopeCount();
for (var i = 0; i < scope_count; i++) {
var scope = exec_state.frame().scope(i);
// assertTrue(scope.isScope());
scope.scopeType();
scope.scopeObject();
}
// Do steps until we reach the global scope again.
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
Debug.setListener(listener);
function test1() {
debugger;
with ({x:1}) {
x = 2;
}
}
test1();
function test2() {
if (true) {
with ({}) {
debugger;
}
} else {
with ({}) {
return 10;
}
}
}
test2();
function test3() {
if (true) {
debugger;
} else {
with ({}) {
return 10;
}
}
}
test3();
function test4() {
debugger;
with ({x:1}) x = 1
}
test4();
function test5() {
debugger;
var dummy = 1;
with ({}) {
with ({}) {
dummy = 2;
}
}
dummy = 3;
}
test5();
function test6() {
debugger;
try {
throw 'stuff';
} catch (e) {
e = 1;
}
}
test6();
function test7() {
debugger;
function foo() {}
}
test7();
function test8() {
debugger;
(function foo() {})();
}
test8();
function test10() {
debugger;
with ({}) {
return 10;
}
}
test10();
function test11() {
debugger;
try {
throw 'stuff';
} catch (e) {
return 10;
}
}
test11();
var prefixes = [
"debugger; ",
"if (false) { try { throw 0; } catch(x) { return x; } }; debugger; " ];
// Return from function constructed with Function constructor.
var anon = 12;
for (var i = 0; i < prefixes.length; ++i) {
var pre = prefixes[i];
Function(pre + "return 42")();
Function(pre + "return 42 ")();
Function(pre + "return 42;")();
Function(pre + "return 42; ")();
Function(pre + "return anon")();
Function(pre + "return anon ")();
Function(pre + "return anon;")();
Function(pre + "return anon; ")();
}
try {
with({}) {
debugger;
eval("{}$%:^");
}
} catch(e) {
nop();
}
function nop() {}
// With block as the last(!) statement in global code.
with ({}) { debugger; }

View File

@ -0,0 +1,80 @@
// 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.
// Check that the ScopeIterator can properly recreate the scope at
// every point when stepping through functions.
var Debug = debug.Debug;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
// Access scope details.
var scope_count = exec_state.frame().scopeCount();
for (var i = 0; i < scope_count; i++) {
var scope = exec_state.frame().scope(i);
// assertTrue(scope.isScope());
scope.scopeType();
scope.scopeObject();
}
// Do steps until we reach the global scope again.
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
Debug.setListener(listener);
var q = 42;
var prefixes = [ "debugger; ",
"if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; " ];
var bodies = [ "1",
"1 ",
"1;",
"1; ",
"q",
"q ",
"q;",
"q; ",
"try { throw 'stuff' } catch (e) { e = 1; }",
"try { throw 'stuff' } catch (e) { e = 1; } ",
"try { throw 'stuff' } catch (e) { e = 1; };",
"try { throw 'stuff' } catch (e) { e = 1; }; " ];
function test9() {
debugger;
for (var i = 0; i < prefixes.length; ++i) {
var pre = prefixes[i];
for (var j = 0; j < bodies.length; ++j) {
var body = bodies[j];
eval(pre + body);
eval("'use strict'; " + pre + body);
}
}
}
test9();

View File

@ -0,0 +1,77 @@
// 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.
// Check that the ScopeIterator can properly recreate the scope at
// every point when stepping through functions.
var Debug = debug.Debug;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
// Access scope details.
var scope_count = exec_state.frame().scopeCount();
for (var i = 0; i < scope_count; i++) {
var scope = exec_state.frame().scope(i);
// assertTrue(scope.isScope());
scope.scopeType();
scope.scopeObject();
}
// Do steps until we reach the global scope again.
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
Debug.setListener(listener);
var q = 42;
var prefixes = [
"debugger; ",
"if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; " ];
var with_bodies = [ "with ({}) {}",
"with ({x:1}) x",
"with ({x:1}) x = 1",
"with ({x:1}) x ",
"with ({x:1}) x = 1 ",
"with ({x:1}) x;",
"with ({x:1}) x = 1;",
"with ({x:1}) x; ",
"with ({x:1}) x = 1; " ];
function test9() {
debugger;
for (var i = 0; i < prefixes.length; ++i) {
var pre = prefixes[i];
for (var j = 0; j < with_bodies.length; ++j) {
var body = with_bodies[j];
eval(pre + body);
}
}
}
test9();

View File

@ -0,0 +1,77 @@
// 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.
// Check that the ScopeIterator can properly recreate the scope at
// every point when stepping through functions.
var Debug = debug.Debug;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
// Access scope details.
var scope_count = exec_state.frame().scopeCount();
for (var i = 0; i < scope_count; i++) {
var scope = exec_state.frame().scope(i);
// assertTrue(scope.isScope());
scope.scopeType();
scope.scopeObject();
}
// Do steps until we reach the global scope again.
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
Debug.setListener(listener);
var q = 42;
var prefixes = [
"debugger; ",
"if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; " ];
var bodies = [ "1",
"1 ",
"1;",
"1; ",
"q",
"q ",
"q;",
"q; ",
"try { throw 'stuff' } catch (e) { e = 1; }",
"try { throw 'stuff' } catch (e) { e = 1; } ",
"try { throw 'stuff' } catch (e) { e = 1; };",
"try { throw 'stuff' } catch (e) { e = 1; }; " ];
// Test global eval and function constructor.
for (var i = 0; i < prefixes.length; ++i) {
var pre = prefixes[i];
for (var j = 0; j < bodies.length; ++j) {
var body = bodies[j];
eval(pre + body);
}
}

View File

@ -0,0 +1,74 @@
// 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.
// Check that the ScopeIterator can properly recreate the scope at
// every point when stepping through functions.
var Debug = debug.Debug;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
// Access scope details.
var scope_count = exec_state.frame().scopeCount();
for (var i = 0; i < scope_count; i++) {
var scope = exec_state.frame().scope(i);
// assertTrue(scope.isScope());
scope.scopeType();
scope.scopeObject();
}
// Do steps until we reach the global scope again.
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
Debug.setListener(listener);
var q = 42;
var prefixes = [ "debugger; ",
"if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; " ];
var with_bodies = [ "with ({}) {}",
"with ({x:1}) x",
"with ({x:1}) x = 1",
"with ({x:1}) x ",
"with ({x:1}) x = 1 ",
"with ({x:1}) x;",
"with ({x:1}) x = 1;",
"with ({x:1}) x; ",
"with ({x:1}) x = 1; " ];
// Test global eval and function constructor.
for (var i = 0; i < prefixes.length; ++i) {
var pre = prefixes[i];
for (var j = 0; j < with_bodies.length; ++j) {
var body = with_bodies[j];
eval(pre + body);
Function(pre + body)();
}
}

View File

@ -0,0 +1,76 @@
// 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.
// Check that the ScopeIterator can properly recreate the scope at
// every point when stepping through functions.
var Debug = debug.Debug;
function listener(event, exec_state, event_data, data) {
if (event == Debug.DebugEvent.Break) {
// Access scope details.
var scope_count = exec_state.frame().scopeCount();
for (var i = 0; i < scope_count; i++) {
var scope = exec_state.frame().scope(i);
// assertTrue(scope.isScope());
scope.scopeType();
scope.scopeObject();
}
// Do steps until we reach the global scope again.
exec_state.prepareStep(Debug.StepAction.StepInto);
}
}
Debug.setListener(listener);
var q = 42;
var prefixes = [ "debugger; ",
"if (false) { try { throw 0; } catch(x) { this.x = x; } }; debugger; " ];
var bodies = [ "1",
"1 ",
"1;",
"1; ",
"q",
"q ",
"q;",
"q; ",
"try { throw 'stuff' } catch (e) { e = 1; }",
"try { throw 'stuff' } catch (e) { e = 1; } ",
"try { throw 'stuff' } catch (e) { e = 1; };",
"try { throw 'stuff' } catch (e) { e = 1; }; " ];
// Test global eval and function constructor.
for (var i = 0; i < prefixes.length; ++i) {
var pre = prefixes[i];
for (var j = 0; j < bodies.length; ++j) {
var body = bodies[j];
eval("'use strict'; " + pre + body);
}
}

Some files were not shown because too many files have changed in this diff Show More