Skip to content

Instantly share code, notes, and snippets.

@sokra

sokra/Scopes.md Secret

Last active November 6, 2023 12:52
Show Gist options
  • Save sokra/97a53a869b9a421accadbc9681cb26f3 to your computer and use it in GitHub Desktop.
Save sokra/97a53a869b9a421accadbc9681cb26f3 to your computer and use it in GitHub Desktop.

Structure

There are two different data items that will appear in the "scopes" field: "Start scope" and "End Scope".

Note: Each DATA item represents one VLQ number.

Start scope

  • DATA relative column in the generated code **
    • Note: This is the point in generated code where the scope starts. Line is implicit, see "Encoding".
  • DATA field flags
    • Note: binary flags that specify if a field is used for this scope.
    • Note: Unknown flags would skip the whole scope.
    • 0x1 has name
    • 0x2 has definition
    • 0x4 has callsite
  • DATA info flags
    • Note: binary flags that specify behavior of the scope.
    • Note: Unknown flags can be ignored.
    • 0x1 function
      • Note: This should show as function in the stack trace.
      • Note: If not set, it will be a lexical scope not shown in stack trace.
    • 0x2 inherit parent bindings
      • Note: Bindings for parent scope are still accessible in this scope.
    • 0x4 skip when stepping
      • Note: Debuggers are encouraged to step over this scope.
    • 0x8 collapse
      • Note: doesn't show the scope in the stack trace.
      • TODO(sokra): is this already handled by the function flag?
  • name: (only existing if has name flag is set)
    • DATA relative offset into names field
    • Note: This name should be shown as function name in the stack trace
  • definition: (only existing if has definition flag is set)
    • relative offset into sources
    • DATA start line *
    • DATA start column **
    • DATA relative end line
    • DATA end column **
    • Note: Range in the original code that forms this scope.
  • callsite: (only existing if has callsite flag is set)
    • relative offset into sources
    • DATA start line *
    • DATA start column **
    • DATA relative end line
    • DATA end column **
    • Note: When this field is set, it's an inlined function, called from that expression.
  • bindings:
    • DATA number of bindings (N)
    • N times
      • DATA relative offset into names field
      • DATA relative offset into expressions field
      • Note: identifiers mentioned in expressions are resolved at the start of the scope
    • Note: Bindings available when inside of that scope.

Note: There are at least 2 DATA fields for "Start scope", which identifies it as "Start scope".

* start line is relative when the relative offset into source is 0, otherwise it's absolute.

** start/end column is relative when relative when the line was relative and is 0, otherwise it's absolute.

End scope

  • DATA relative column in the generated code **
    • Note: This is the point in generated code where the scope ends. Line is implicit, see "Encoding".

Note: There is only 1 DATA field in "End scope", which identifies it as "End scope".

Encoding

The "scopes" field uses a similar encoding as the mappings field: Multiple VLQ numbers separated by , and ;.

It has an implict line number in the generated code. It is incremented on every ;.

Example

Original Code (file.js):

var x = 1;
function z(message) {
  let y = 2; // <- Starts a scope for y
  console.log(message + y);
}
z("Hello World");

Generated Code:

var _x = 1;
function _z(_m) {
  let _y = 2;
  console.log(_m + _y);
}
console.log("Hello World2"); // <- Inlined

Scopes:

A|        var _x = 1;
 | B|     function _z(_m) {
 |  | C|    let _y = 2;
 |  |  |    console.log(_m + _y);
 |  |     }
 |    D|  console.log("Hello World2");

LX CY: Line X Column Y

Start Scope C0 { // A
  field flags: has name, has definition
  info flags: 
  name: <top level>
  definition: file.js L1 C0 - L6 C27
  bindings: x -> _x
}
;
Start Scope C17 { // B
  field flags: has name, has definition
  info flags: function, inherit parent bindings
  name: z
  definition: file L2 C0 - L5 C1
  bindings: z -> _z, message -> _m
}
;
Start Scope C2 { // C
  field flags:
  info flags: inherit parent bindings
  bindings: y -> _y
}
;
;
End Scope C0 // C
End Scope C0 // B
;
Start Scope C0 { // D
  field flags: has name, has definition
  info flags: function, inherit parent bindings
  name: z
  definition: file L2 C0 - L5 C1
  bindings: z -> <optimized away>, message -> "Hello World", y -> 2
}
End Scope C28 // D
XXXX;XXXX;XXXX;;X,X;XXXX,XXXX,X,X

expressions field

TBD separate proposal

Copy link

ghost commented Nov 6, 2023

**

Screenshot_20231106-073703
**

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment