New issue
Advanced search Search tips

Issue 753338 link

Starred by 1 user

Issue metadata

Status: Started
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 2
Type: Bug

Blocking:
issue 774318



Sign in to add a comment

Context and scope chain mismatch when debugging for-of scopes.

Project Member Reported by yangguo@chromium.org, Aug 8 2017

Issue description

Consider following test case:

var Debug = debug.Debug;

Debug.setListener(() => {});

function repro() {
  for (let [a, b = eval("debugger")] of [[0]]) {
    function f() { return a };
  }
}

repro();


To be run with test/mjsunit/mjsunit.js test/debugger/test-api.js --enable-inspector --allow-natives-syntax

We crash with

#
# Fatal error in ../../src/debug/debug-scopes.cc, line 276
# Debug check failed: context_->IsFunctionContext() || !scope_info->HasContext().
#

When run with --print-scopes, we get

function repro () { // (0x564a82491fd8) (70, 160)
  // scope calls 'eval'
  // inner scope calls 'eval'
  // will be compiled
  // 18 stack slots
  // 8 heap slots
  // temporary vars:
  TEMPORARY .for;  // (0x564a82492fa0) local[2]
  TEMPORARY .0x564a82493020;  // (0x564a82493020) local[3]
  TEMPORARY .0x564a82493100;  // (0x564a82493100) local[4]
  TEMPORARY .0x564a824931d0;  // (0x564a824931d0) local[5]
  TEMPORARY .0x564a82493260;  // (0x564a82493260) local[6]
  TEMPORARY .0x564a82493290;  // (0x564a82493290) local[7]
  TEMPORARY .0x564a824932c0;  // (0x564a824932c0) local[8]
  TEMPORARY .0x564a824cb770;  // (0x564a824cb770) local[9]
  TEMPORARY .0x564a824cbc48;  // (0x564a824cbc48) local[10]
  TEMPORARY .0x564a824cc120;  // (0x564a824cc120) local[11]
  TEMPORARY .iterator;  // (0x564a824cc7e0) local[12]
  TEMPORARY .result;  // (0x564a824cc810) local[13]
  TEMPORARY .0x564a824cc840;  // (0x564a824cc840) local[14]
  TEMPORARY .0x564a824ccc28;  // (0x564a824ccc28) local[15]
  TEMPORARY .0x564a824cd0a8;  // (0x564a824cd0a8) local[16]
  TEMPORARY .0x564a824cd568;  // (0x564a824cd568) local[17]
  // local vars:
  VAR arguments;  // (0x564a824cdda8) context[7]
  VAR f;  // (0x564a824cdd78) context[6]
  CONST .new.target;  // (0x564a824921c0) context[5]
  VAR this;  // (0x564a82492190) context[4]

  block { // (0x564a824924c8) (81, 158)
    // is hidden
    // scope calls 'eval'
    // inner scope calls 'eval'
    // 6 heap slots
    // local vars:
    LET b;  // (0x564a824cdc58) context[5]
    LET a;  // (0x564a824cdbe8) context[4]

    catch { // (0x564a824cd8f0) (-1, -1)
      // is hidden
      // 5 heap slots
      // local vars:
      VAR .catch;  // (0x564a824cda38) context[4], never assigned
    }

    catch { // (0x564a824cd3c8) (-1, -1)
      // is hidden
      // 5 heap slots
      // local vars:
      VAR .catch;  // (0x564a824cd510) context[4], never assigned
    }

    block { // (0x564a82492918) (120, 158)
      // 5 heap slots
      // local vars:
      LET b;  // (0x564a824cb8d0) local[1], never assigned, hole initialization elided
      LET a;  // (0x564a824939b8) context[4], forced context allocation, never assigned

      catch { // (0x564a824cc4c0) (-1, -1)
        // is hidden
        // 5 heap slots
        // local vars:
        VAR .catch;  // (0x564a824cc608) context[4], never assigned
      }

      catch { // (0x564a824cbf80) (-1, -1)
        // is hidden
        // 5 heap slots
        // local vars:
        VAR .catch;  // (0x564a824cc0c8) context[4], never assigned
      }

      block { // (0x564a82492b08) (122, 158)
        // local vars:
        LET f;  // (0x564a82492e58) local[0], never assigned

        function f () { // (0x564a82492c78) (138, 153)
          // lazily parsed
          // 4 heap slots
        }
      }
    }
  }
}

Note that the assignment to 'b' is happens in the second block scope. This is in accordance of the comment in parser.cc


// Rewrite a for-in/of statement of the form
//
//   for (let/const/var x in/of e) b
//
// into
//
//   {
//     var temp;
//     for (temp in/of e) {
//       let/const/var x = temp;
//       b;
//     }
//     let x;  // for TDZ
//   }

However, at the point of the debugger statement, on the second-to-topmost frame, we have the source position right at the assignment to 'b'. The source position is 94, but we actually are in the second block scope with the source range (120, 158).

The debugger inspects the scopes by parsing the function, and finding the scope chain via source position. The expectation is that the scope chain matches the current context chain. This is not the case since the context chain is [function context]->[block context]->[block context], but the scope chain we found based on source position is [function scope]->[block scope].

The reason for this is that the assignment belongs to the second block scope, but is outside the source position range attributed to that block scope.

Adam, do you have any opinion on how to fix this? This is essentially confirmed your suspicion that we need several source ranges per scope to satisfy the debugger.
 
Summary: Context and scope chain mismatch when debugging for-of scopes. (was: Context and scope chain mismatch for for-of scopes.)

Comment 2 by adamk@chromium.org, Aug 8 2017

Cc: ca...@igalia.com
I don't have any easy suggestions: the spec effectively does what our desugaring does. See https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements-runtime-semantics-labelledevaluation for the details (the bits including "ForDeclaration").
Components: -Platform>DevTools>JavaScript

Comment 4 by adamk@chromium.org, Nov 16 2017

Cc: gsat...@chromium.org
Labels: -Pri-3 Pri-2
Status: Started (was: Assigned)
Going to take a look at fixing this in the naive way: attaching multiple source ranges to such scopes.

Comment 5 by neis@chromium.org, Nov 20 2017

Does this perhaps also solve https://bugs.chromium.org/p/chromium/issues/detail?id=774318 ?

Comment 6 by adamk@chromium.org, Nov 20 2017

Blocking: 774318
I think it would at least provide a basis for solving that issue, marking as such.

Also, I have a work-in-progress up at https://chromium-review.googlesource.com/c/v8/v8/+/775538, which I'd appreciate feedback on.

Sign in to add a comment