debug-scopes-suspended-generators.js 10.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// 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.
37 38 39
function CheckScopeChain(scopes, gen) {
  var all_scopes = Debug.generatorScopes(gen);
  assertEquals(scopes.length, Debug.generatorScopeCount(gen));
40 41 42
  assertEquals(scopes.length, all_scopes.length,
               "FrameMirror.allScopes length");
  for (var i = 0; i < scopes.length; i++) {
43
    var scope = all_scopes[i];
44 45 46 47 48 49 50 51 52 53 54 55 56 57
    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.
58 59
function CheckScopeContent(content, number, gen) {
  var scope = Debug.generatorScope(gen, number);
60 61 62
  var count = 0;
  for (var p in content) {
    var property_mirror = scope.scopeObject().property(p);
63 64 65 66 67 68
    if (content[p] === undefined) {
      assertTrue(property_mirror === undefined);
    } else {
      assertFalse(property_mirror === undefined,
                  'property ' + p + ' not found in scope');
    }
69
    if (typeof(content[p]) === 'function') {
70
      assertTrue(typeof property_mirror == "function");
71
    } else {
72
      assertEquals(content[p], property_mirror,
73 74 75 76 77 78 79 80
                   '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;
81
  if (scope.scopeObject().property('arguments') !== undefined) {
82 83 84
    scope_size--;
  }
  // Ditto for 'this'.
85
  if (scope.scopeObject().property('this') !== undefined) {
86 87 88
    scope_size--;
  }
  // Temporary variables introduced by the parser have not been materialized.
89
  assertTrue(scope.scopeObject().property('') === undefined);
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108

  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();
109
CheckScopeChain([debug.ScopeType.Local,
110
                 debug.ScopeType.Script,
111 112
                 debug.ScopeType.Global], g);
CheckScopeContent({}, 0, g);
113 114 115 116 117 118 119 120 121

// Closure scope with a parameter.

function *gen2(a) {
  yield a;
  return 2;
}

g = gen2(42);
122
CheckScopeChain([debug.ScopeType.Local,
123
                 debug.ScopeType.Script,
124 125
                 debug.ScopeType.Global], g);
CheckScopeContent({a: 42}, 0, g);
126 127 128 129 130 131 132 133 134 135

// Closure scope with a parameter.

function *gen3(a) {
  var b = 1
  yield a;
  return b;
}

g = gen3(0);
136
CheckScopeChain([debug.ScopeType.Local,
137
                 debug.ScopeType.Script,
138 139
                 debug.ScopeType.Global], g);
CheckScopeContent({a: 0, b: undefined}, 0, g);
140 141

g.next();  // Create b.
142
CheckScopeContent({a: 0, b: 1}, 0, g);
143 144 145 146 147 148 149

// Closure scope with a parameter.

function *gen4(a, b) {
  var x = 2;
  yield a;
  var y = 3;
150
  yield a;
151 152 153 154
  return b;
}

g = gen4(0, 1);
155
CheckScopeChain([debug.ScopeType.Local,
156
                 debug.ScopeType.Script,
157 158
                 debug.ScopeType.Global], g);
CheckScopeContent({a: 0, b: 1, x: undefined, y: undefined}, 0, g);
159 160

g.next();  // Create x.
161
CheckScopeContent({a: 0, b: 1, x: 2, y: undefined}, 0, g);
162 163

g.next();  // Create y.
164
CheckScopeContent({a: 0, b: 1, x: 2, y: 3}, 0, g);
165 166 167 168 169

// Closure introducing local variable using eval.

function *gen5(a) {
  eval('var b = 2');
170
  yield a;
171 172 173 174 175
  return b;
}

g = gen5(1);
g.next();
176
CheckScopeChain([debug.ScopeType.Local,
177
                 debug.ScopeType.Script,
178 179
                 debug.ScopeType.Global], g);
CheckScopeContent({a: 1, b: 2}, 0, g);
180 181 182 183 184 185 186 187 188 189 190 191 192 193

// Single empty with block.

function *gen6() {
  with({}) {
    yield 1;
  }
  yield 2;
  return 3;
}

g = gen6();
g.next();
CheckScopeChain([debug.ScopeType.With,
194
                 debug.ScopeType.Local,
195
                 debug.ScopeType.Script,
196 197
                 debug.ScopeType.Global], g);
CheckScopeContent({}, 0, g);
198 199

g.next();
200
CheckScopeChain([debug.ScopeType.Local,
201
                 debug.ScopeType.Script,
202
                 debug.ScopeType.Global], g);
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219

// 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,
220
                 debug.ScopeType.Local,
221
                 debug.ScopeType.Script,
222 223
                 debug.ScopeType.Global], g);
CheckScopeContent({}, 0, g);
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240

// 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,
241
                 debug.ScopeType.Local,
242
                 debug.ScopeType.Script,
243 244
                 debug.ScopeType.Global], g);
CheckScopeContent({a: 2, b: 1}, 0, g);
245 246

g.next();
247
CheckScopeContent({a: 1, b: 2}, 0, g);
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262

// Catch block.

function *gen9() {
  try {
    throw 42;
  } catch (e) {
    yield e;
  }
  return 3;
}

g = gen9();
g.next();
CheckScopeChain([debug.ScopeType.Catch,
263
                 debug.ScopeType.Local,
264
                 debug.ScopeType.Script,
265 266
                 debug.ScopeType.Global], g);
CheckScopeContent({e: 42}, 0, g);
267 268 269 270 271 272 273 274 275 276 277

// 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,
278
                 debug.ScopeType.Local,
279
                 debug.ScopeType.Script,
280
                 debug.ScopeType.Global], g);
281
CheckScopeContent({i: 0}, 0, g);
282 283

g.next();
284
CheckScopeContent({i: 1}, 0, g);
285 286 287 288 289

// Nested generators.

var gen12;
function *gen11() {
290
  var b = 2;
291 292 293
  gen12 = function*() {
    var a = 1;
    yield 1;
294
    return b;
295 296 297 298 299 300
  }();

  var a = 0;
  yield* gen12;
}

301 302
gen11().next();
g = gen12;
303

304
CheckScopeChain([debug.ScopeType.Local,
305 306
                 debug.ScopeType.Closure,
                 debug.ScopeType.Script,
307 308
                 debug.ScopeType.Global], g);
CheckScopeContent({a: 1}, 0, g);
309
CheckScopeContent({b: 2}, 1, g);
310 311 312 313 314 315 316 317 318

// Set a variable in an empty scope.

function *gen13() {
  yield 1;
  return 2;
}

var g = gen13();
319 320
assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("a", 42));
CheckScopeContent({}, 0, g);
321 322 323 324 325 326 327 328 329 330 331 332 333

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

334
CheckScopeContent({a: 0}, 0, g);
335

336 337
Debug.generatorScope(g, 0).setVariableValue("a", 1);
CheckScopeContent({a: 1}, 0, g);
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357

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,
358
                 debug.ScopeType.Local,
359
                 debug.ScopeType.Script,
360 361 362
                 debug.ScopeType.Global], g);
CheckScopeContent({a: 1, b: 2}, 0, g);
CheckScopeContent({c: 3, d: 4, e: undefined}, 1, g);
363 364

// Variables don't exist in given scope.
365 366
assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("c", 42));
assertThrows(() => Debug.generatorScope(g, 1).setVariableValue("a", 42));
367 368

// Variables in with scope are immutable.
369 370
assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("a", 3));
assertThrows(() => Debug.generatorScope(g, 0).setVariableValue("b", 3));
371

372 373
Debug.generatorScope(g, 1).setVariableValue("c", 1);
Debug.generatorScope(g, 1).setVariableValue("e", 42);
374

375 376
CheckScopeContent({a: 1, b: 2}, 0, g);
CheckScopeContent({c: 1, d: 4, e: 42}, 1, g);
377 378
assertEquals(5, g.next().value);  // Initialized after set.

379
CheckScopeChain([debug.ScopeType.Local,
380
                 debug.ScopeType.Script,
381
                 debug.ScopeType.Global], g);
382

383
Debug.generatorScope(g, 0).setVariableValue("e", 42);
384

385
CheckScopeContent({c: 1, d: 4, e: 42}, 0, g);
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
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,
407
                 debug.ScopeType.Local,
408
                 debug.ScopeType.Script,
409
                 debug.ScopeType.Global], g);
410
CheckScopeContent({d: 4, e: undefined}, 0, g);
411 412
CheckScopeContent({a: 1, b: 2}, 1, g);
CheckScopeContent({c: 3}, 2, g);
413

414
Debug.generatorScope(g, 0).setVariableValue("d", 1);
415
CheckScopeContent({d: 1, e: undefined}, 0, g);
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436

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,
437
                 debug.ScopeType.Local,
438
                 debug.ScopeType.Script,
439 440 441 442 443 444 445
                 debug.ScopeType.Global], g);
CheckScopeContent({e: 42}, 0, g);
CheckScopeContent({xxxyyxxyx: 42284,
                   printProtocolMessages : printProtocolMessages,
                   activeWrapper : activeWrapper,
                   DebugWrapper : DebugWrapper
                  }, 2, g);
446

447 448
Debug.generatorScope(g, 0).setVariableValue("e", 1);
CheckScopeContent({e: 1}, 0, g);
449 450 451 452

assertEquals(1, g.next().value);

// Script scope.
453
Debug.generatorScope(g, 2).setVariableValue("xxxyyxxyx", 42);
454 455 456
assertEquals(42, xxxyyxxyx);

// Global scope.
457
assertThrows(() => Debug.generatorScope(g, 3).setVariableValue("yyzyzzyz", 42));
458
assertEquals(4829, yyzyzzyz);