Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(967)

Unified Diff: test/mjsunit/debug-scopes-suspended-generators.js

Issue 2228393002: Allow access to scopes of suspended generator objects (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Remove stale TODO comment Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/runtime/runtime-debug.cc ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: test/mjsunit/debug-scopes-suspended-generators.js
diff --git a/test/mjsunit/debug-scopes-suspended-generators.js b/test/mjsunit/debug-scopes-suspended-generators.js
new file mode 100644
index 0000000000000000000000000000000000000000..f4750b7f769f95751d80f27c23e94f7e23ac833e
--- /dev/null
+++ b/test/mjsunit/debug-scopes-suspended-generators.js
@@ -0,0 +1,470 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --expose-debug-as debug --allow-natives-syntax --ignition
+// The functions used for testing backtraces. They are at the top to make the
+// testing of source line/column easier.
+
+// Get the Debug object exposed from the debug context global object.
+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.frameIndex(), scope2.frameIndex());
+ 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_mirror) {
+ var all_scopes = gen_mirror.allScopes();
+ assertEquals(scopes.length, gen_mirror.scopeCount());
+ assertEquals(scopes.length, all_scopes.length,
+ "FrameMirror.allScopes length");
+ for (var i = 0; i < scopes.length; i++) {
+ var scope = gen_mirror.scope(i);
+ assertTrue(scope.isScope());
+ assertEquals(scopes[i], scope.scopeType(),
+ `Scope ${i} has unexpected type`);
+ assertScopeMirrorEquals(all_scopes[i], scope);
+
+ // 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_mirror) {
+ var scope = gen_mirror.scope(number);
+ var count = 0;
+ for (var p in content) {
+ var property_mirror = scope.scopeObject().property(p);
+ assertFalse(property_mirror.isUndefined(),
+ 'property ' + p + ' not found in scope');
+ if (typeof(content[p]) === 'function') {
+ assertTrue(property_mirror.value().isFunction());
+ } else {
+ assertEquals(content[p], property_mirror.value().value(),
+ 'property ' + p + ' has unexpected value');
+ }
+ count++;
+ }
+
+ // 'arguments' and might be exposed in the local and closure scope. Just
+ // ignore this.
+ var scope_size = scope.scopeObject().properties().length;
+ if (!scope.scopeObject().property('arguments').isUndefined()) {
+ scope_size--;
+ }
+ // Ditto for 'this'.
+ if (!scope.scopeObject().property('this').isUndefined()) {
+ scope_size--;
+ }
+ // Temporary variables introduced by the parser have not been materialized.
+ assertTrue(scope.scopeObject().property('').isUndefined());
+
+ if (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();
+var gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({}, 0, gm);
+
+// Closure scope with a parameter.
+
+function *gen2(a) {
+ yield a;
+ return 2;
+}
+
+g = gen2(42);
+gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({a: 42}, 0, gm);
+
+// Closure scope with a parameter.
+
+function *gen3(a) {
+ var b = 1
+ yield a;
+ return b;
+}
+
+g = gen3(0);
+gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({a: 0, b: undefined}, 0, gm);
+
+g.next(); // Create b.
+CheckScopeContent({a: 0, b: 1}, 0, gm);
+
+// Closure scope with a parameter.
+
+function *gen4(a, b) {
+ var x = 2;
+ yield a;
+ var y = 3;
+ return b;
+}
+
+g = gen4(0, 1);
+gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({a: 0, b: 1, x: undefined, y: undefined}, 0, gm);
+
+g.next(); // Create x.
+CheckScopeContent({a: 0, b: 1, x: 2, y: undefined}, 0, gm);
+
+g.next(); // Create y.
+CheckScopeContent({a: 0, b: 1, x: 2, y: 3}, 0, gm);
+
+// Closure introducing local variable using eval.
+
+function *gen5(a) {
+ eval('var b = 2');
+ return b;
+}
+
+g = gen5(1);
+g.next();
+gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({a: 1, b: 2}, 0, gm);
+
+// Single empty with block.
+
+function *gen6() {
+ with({}) {
+ yield 1;
+ }
+ yield 2;
+ return 3;
+}
+
+g = gen6();
+g.next();
+gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.With,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({}, 0, gm);
+
+g.next();
+CheckScopeChain([debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+
+// Nested empty with blocks.
+
+function *gen7() {
+ with({}) {
+ with({}) {
+ yield 1;
+ }
+ yield 2;
+ }
+ return 3;
+}
+
+g = gen7();
+g.next();
+gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.With,
+ debug.ScopeType.With,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({}, 0, gm);
+
+// 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();
+gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.With,
+ debug.ScopeType.With,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({a: 2, b: 1}, 0, gm);
+
+g.next();
+CheckScopeContent({a: 1, b: 2}, 0, gm);
+
+// Catch block.
+
+function *gen9() {
+ try {
+ throw 42;
+ } catch (e) {
+ yield e;
+ }
+ return 3;
+}
+
+g = gen9();
+g.next();
+gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.Catch,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({e: 42}, 0, gm);
+
+// For statement with block scope.
+
+function *gen10() {
+ for (let i = 0; i < 42; i++) yield i;
+ return 3;
+}
+
+g = gen10();
+g.next();
+gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.Block,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({i: 0}, 0, gm);
+
+g.next();
+CheckScopeContent({i: 1}, 0, gm);
+CheckScopeContent({i: 0}, 1, gm); // Additional block scope with i = 0;
+
+// Nested generators.
+
+var gen12;
+function *gen11() {
+ gen12 = function*() {
+ var a = 1;
+ yield 1;
+ return 2;
+ }();
+
+ var a = 0;
+ yield* gen12;
+}
+
+g = gen11();
+g.next();
+
+gm = debug.MakeMirror(gen12);
+CheckScopeChain([debug.ScopeType.Closure,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({a: 1}, 0, gm);
+CheckScopeContent({a: 0}, 1, gm);
+
+// Set a variable in an empty scope.
+
+function *gen13() {
+ yield 1;
+ return 2;
+}
+
+var g = gen13();
+var gm = debug.MakeMirror(g);
+assertThrows(() => gm.scope(0).setVariableValue("a", 42));
+CheckScopeContent({}, 0, gm);
+
+// 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);
+
+var gm = debug.MakeMirror(g);
+CheckScopeContent({a: 0}, 0, gm);
+
+gm.scope(0).setVariableValue("a", 1);
+CheckScopeContent({a: 1}, 0, gm);
+
+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);
+
+var gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.With,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({a: 1, b: 2}, 0, gm);
+CheckScopeContent({c: 3, d: 4, e: undefined}, 1, gm);
+
+// Variables don't exist in given scope.
+assertThrows(() => gm.scope(0).setVariableValue("c", 42));
+assertThrows(() => gm.scope(1).setVariableValue("a", 42));
+
+// Variables in with scope are immutable.
+assertThrows(() => gm.scope(0).setVariableValue("a", 3));
+assertThrows(() => gm.scope(0).setVariableValue("b", 3));
+
+gm.scope(1).setVariableValue("c", 1);
+gm.scope(1).setVariableValue("e", 42);
+
+CheckScopeContent({a: 1, b: 2}, 0, gm);
+CheckScopeContent({c: 1, d: 4, e: 42}, 1, gm);
+assertEquals(5, g.next().value); // Initialized after set.
+
+CheckScopeChain([debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+
+gm.scope(0).setVariableValue("e", 42);
+
+CheckScopeContent({c: 1, d: 4, e: 42}, 0, gm);
+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();
+
+var gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.Block,
+ debug.ScopeType.With,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({d: 4}, 0, gm);
+CheckScopeContent({a: 1, b: 2}, 1, gm);
+CheckScopeContent({c: 3}, 2, gm);
+
+gm.scope(0).setVariableValue("d", 1);
+CheckScopeContent({d: 1}, 0, gm);
+
+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();
+
+gm = debug.MakeMirror(g);
+CheckScopeChain([debug.ScopeType.Catch,
+ debug.ScopeType.Closure,
+ debug.ScopeType.Script,
+ debug.ScopeType.Global], gm);
+CheckScopeContent({e: 42}, 0, gm);
+CheckScopeContent({xxxyyxxyx: 42284}, 2, gm);
+
+gm.scope(0).setVariableValue("e", 1);
+CheckScopeContent({e: 1}, 0, gm);
+
+assertEquals(1, g.next().value);
+
+// Script scope.
+gm.scope(2).setVariableValue("xxxyyxxyx", 42);
+assertEquals(42, xxxyyxxyx);
+
+// Global scope.
+assertThrows(() => gm.scope(3).setVariableValue("yyzyzzyz", 42));
+assertEquals(4829, yyzyzzyz);
« no previous file with comments | « src/runtime/runtime-debug.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698