Skip to content

Commit 71e76ab

Browse files
committed
Scopes: initial draft of the algorithm for computing original stack frames
1 parent f15b006 commit 71e76ab

1 file changed

Lines changed: 385 additions & 0 deletions

File tree

spec.emu

Lines changed: 385 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2532,6 +2532,391 @@ return lastURL;</code></pre>
25322532
</emu-clause>
25332533
</emu-clause>
25342534

2535+
<emu-clause id="sec-computing-original-stack-frames">
2536+
<h1>Computing original stack frames</h1>
2537+
<p></p>
2538+
2539+
<emu-clause id="sec-debugger-position-record-type">
2540+
<h1>Debugger Position Record</h1>
2541+
<p>A <dfn id="debugger-position-record">Debugger Position Record</dfn> is a tuple of a source URL and non-negative line and column numbers.</p>
2542+
<emu-table id="table-debugger-position-record-fields">
2543+
<table>
2544+
<thead>
2545+
<tr>
2546+
<th>Field Name</th>
2547+
<th>Value Type</th>
2548+
</tr>
2549+
</thead>
2550+
<tr>
2551+
<td>[[URL]]</td>
2552+
<td>a URL or *null*</td>
2553+
</tr>
2554+
<tr>
2555+
<td>[[Line]]</td>
2556+
<td>a non-negative integral Number</td>
2557+
</tr>
2558+
<tr>
2559+
<td>[[Column]]</td>
2560+
<td>a non-negative integral Number</td>
2561+
</tr>
2562+
</table>
2563+
</emu-table>
2564+
</emu-clause>
2565+
2566+
<emu-clause id="sec-debugger-bindings-record-type">
2567+
<h1>Debugger Bindings Records</h1>
2568+
<p>A <dfn id="debugger-bindings-record">Debugger Bindings Record</dfn> associates variable names to implementation-defined representations of javascript values in the debuggee or to ~unavailable~.</p>
2569+
</emu-clause>
2570+
2571+
<emu-clause id="sec-debugger-scope-record-type">
2572+
<h1>Debugger Scope Record</h1>
2573+
<p>A <dfn id="debugger-scope-record" variants="Debugger Scope Records">Debugger Scope Record</dfn> is a tuple of start and end positions and a Debugger Bindings Record.</p>
2574+
<emu-table id="table-debugger-scope-record-fields">
2575+
<table>
2576+
<thead>
2577+
<tr>
2578+
<th>Field Name</th>
2579+
<th>Value</th>
2580+
<th>Meaning</th>
2581+
</tr>
2582+
</thead>
2583+
<tr>
2584+
<td>[[Start]]</td>
2585+
<td>A Debugger Position Record</td>
2586+
<td>The line and column (inclusive) where the scope starts.</td>
2587+
</tr>
2588+
<tr>
2589+
<td>[[End]]</td>
2590+
<td>A Debugger Position Record</td>
2591+
<td>The line and column (exclusive) where the scope ends.</td>
2592+
</tr>
2593+
<tr>
2594+
<td>[[Bindings]]</td>
2595+
<td>A Debugger Bindings Record</td>
2596+
<td>The bindings of the scope.</td>
2597+
</tr>
2598+
</table>
2599+
</emu-table>
2600+
</emu-clause>
2601+
2602+
<emu-clause id="sec-debugger-frame-record-type">
2603+
<h1>Debugger Frame Record</h1>
2604+
<p>A <dfn id="debugger-frame-record" variants="Debugger Frame Records">Debugger Frame Record</dfn> is a tuple of a position, a list of scopes and an optional name.</p>
2605+
<emu-table id="table-debugger-frame-record-fields">
2606+
<table>
2607+
<thead>
2608+
<tr>
2609+
<th>Field Name</th>
2610+
<th>Value</th>
2611+
<th>Meaning</th>
2612+
</tr>
2613+
</thead>
2614+
<tr>
2615+
<td>[[Position]]</td>
2616+
<td>A Debugger Position Record</td>
2617+
<td>The position where execution was paused.</td>
2618+
</tr>
2619+
<tr>
2620+
<td>[[Scopes]]</td>
2621+
<td>A List of Debugger Scope Records</td>
2622+
<td>The scopes of the frame, starting with the innermost scope.</td>
2623+
</tr>
2624+
<tr>
2625+
<td>[[Name]]</td>
2626+
<td>A String or *null*</td>
2627+
<td>The name of the frame.</td>
2628+
</tr>
2629+
</table>
2630+
</emu-table>
2631+
</emu-clause>
2632+
2633+
<emu-clause id="sec-sourcemapped-frame-record-type">
2634+
<h1>SourceMapped Frame Record</h1>
2635+
<p>A <dfn id="sourcemapped-frame-record" variants="SourceMapped Frame Records">SourceMapped Frame Record</dfn> contains the name and position of an original frame and the index of its corresponding generated frame.</p>
2636+
<emu-table id="table-sourcemapped-frame-record-fields">
2637+
<table>
2638+
<thead>
2639+
<tr>
2640+
<th>Field Name</th>
2641+
<th>Value</th>
2642+
<th>Meaning</th>
2643+
</tr>
2644+
</thead>
2645+
<tr>
2646+
<td>[[Name]]</td>
2647+
<td>A String or *null*</td>
2648+
<td>The name of the original frame.</td>
2649+
</tr>
2650+
<tr>
2651+
<td>[[OriginalPosition]]</td>
2652+
<td>A Debugger Position Record</td>
2653+
<td>The position of the original frame.</td>
2654+
</tr>
2655+
<tr>
2656+
<td>[[GeneratedFrameIndex]]</td>
2657+
<td>a non-negative integral Number</td>
2658+
<td>The index of the corresponding generated frame.</td>
2659+
</tr>
2660+
</table>
2661+
</emu-table>
2662+
</emu-clause>
2663+
2664+
<emu-clause id="sec-EvaluateInScope" type="abstract operation">
2665+
<h1>
2666+
EvaluateInScope (
2667+
_frameIndex_: a non-negative integral Number,
2668+
_scopeIndex_: a non-negative integral Number,
2669+
_expression_: a String,
2670+
)
2671+
</h1>
2672+
<dl class="header">
2673+
<dt>description</dt>
2674+
<dd>
2675+
The debugger must provide an operation for evaluating an expression in the frame and scope from the current stack indicated by their indices.
2676+
EvaluateInScope(0, 0, _expression_) evaluates _expression_ in the innermost scope of the current top frame.
2677+
</dd>
2678+
</dl>
2679+
</emu-clause>
2680+
2681+
<emu-clause id="sec-FindInnermostGeneratedRange" type="abstract operation">
2682+
<h1>
2683+
FindInnermostGeneratedRange (
2684+
_ranges_: a List of Generated Range Records,
2685+
_position_: a Debugger Position Record,
2686+
): a Generated Range Record or *null*
2687+
</h1>
2688+
<dl class="header"></dl>
2689+
<emu-alg>
2690+
1. For each Generated Range Record _range_ of _ranges_, do
2691+
1. If ComparePositions(_range_.[[Start]], _position_) is not ~greater~ and ComparePositions(_range_.[[End]], _position_) is ~greater~, then
2692+
1. Let _descendantRange_ be FindInnermostGeneratedRange(_range_.[[Children]], _position_).
2693+
1. If _descendantRange_ is not *null*, then
2694+
1. Return _descendantRange_.
2695+
1. Else,
2696+
1. return _range_.
2697+
1. Return *null*.
2698+
</emu-alg>
2699+
</emu-clause>
2700+
2701+
<emu-clause id="sec-FindInnermostOriginalScope" type="abstract operation">
2702+
<h1>
2703+
FindInnermostOriginalScope (
2704+
_scope_: an Original Scope Record,
2705+
_position_: a Debugger Position Record,
2706+
): an Original Scope Record
2707+
</h1>
2708+
<dl class="header"></dl>
2709+
<emu-alg>
2710+
1. For each Original Scope Record _childScope_ of _scope_.[[Children]], do
2711+
1. If ComparePositions(_childScope_.[[Start]], _position_) is not ~greater~ and ComparePositions(_childScope_.[[End]], _position_) is ~greater~, then
2712+
1. return FindInnermostOriginalScope(_childScope_, _position_).
2713+
1. Return _scope_.
2714+
</emu-alg>
2715+
</emu-clause>
2716+
2717+
<emu-clause id="sec-FindSourceForURL" type="abstract operation">
2718+
<h1>
2719+
FindSourceForURL (
2720+
_sources_: a List of Decoded Source Records,
2721+
_URL_: a URL,
2722+
): a Decoded Source Record or *null*
2723+
</h1>
2724+
<dl class="header"></dl>
2725+
<emu-alg>
2726+
1. For each Decoded Source Record _source_ of _sources_, do
2727+
1. If _source_.[[URL]] is _URL_, then
2728+
1. Return _source_.
2729+
1. Return *null*.
2730+
</emu-alg>
2731+
</emu-clause>
2732+
2733+
<emu-clause id="sec-FindAncestorRangeForDefinition" type="abstract operation">
2734+
<h1>
2735+
FindAncestorRangeForDefinition (
2736+
_range_: a Generated Range Record,
2737+
_definition_: an Original Scope Record,
2738+
): a Generated Range Record or *null*
2739+
</h1>
2740+
<dl class="header"></dl>
2741+
<emu-alg>
2742+
1. Repeat, while _range_ is not *null*,
2743+
1. If _range_.[[Definition]] is _definition_, then
2744+
1. Return _range_.
2745+
1. Set _range_ to its parent or *null* if it has no parent.
2746+
1. Return *null*.
2747+
</emu-alg>
2748+
</emu-clause>
2749+
2750+
<emu-clause id="sec-FindFunctionName" type="abstract operation">
2751+
<h1>
2752+
FindFunctionName (
2753+
_scope_: an Original Scope Record,
2754+
): String or *null*
2755+
</h1>
2756+
<dl class="header"></dl>
2757+
<emu-alg>
2758+
1. If _scope_.[[IsStackFrame]], then
2759+
1. Return _scope_.[[Name]].
2760+
1. Let _parentScope_ be the parent of _scope_ or *null* if it has no parent.
2761+
1. If _parentScope_ is not *null*, then
2762+
1. Return FindFunctionName(_parentScope_).
2763+
1. Return *null*.
2764+
</emu-alg>
2765+
</emu-clause>
2766+
2767+
<emu-clause id="sec-FindDebuggerScopeIndexForRange" type="abstract operation">
2768+
<h1>
2769+
FindDebuggerScopeIndexForRange (
2770+
_debuggerScopes_: a List of Debugger Scope Records,
2771+
_start_: a Debugger Position Record,
2772+
_end_: a Debugger Position Record,
2773+
): a non-negative integral Number or *null*
2774+
</h1>
2775+
<dl class="header"></dl>
2776+
<emu-alg>
2777+
1. Let _index_ be 0.
2778+
1. Repeat, while _index_ is smaller than the length of _debuggerScopes_,
2779+
1. Let _scope_ be _debuggerScopes_[_index_].
2780+
1. If ComparePositions(_scope_.[[Start]], _start_) is not ~greater~ and ComparePositions(_scope_.[[End]], _end_) is not ~less~, then
2781+
1. Return _index_.
2782+
1. Set _index_ to _index_ + 1.
2783+
1. Return *null*.
2784+
</emu-alg>
2785+
</emu-clause>
2786+
2787+
<emu-clause id="sec-FindBindingRecord" type="abstract operation">
2788+
<h1>
2789+
FindBindingRecord (
2790+
_subRangeBindings_: a List of Binding Records,
2791+
_position_: a Debugger Position Record,
2792+
): a Binding Record or *null*
2793+
</h1>
2794+
<dl class="header"></dl>
2795+
<emu-alg>
2796+
1. For each Binding Record _subRangeBinding_ in _subRangeBindings_, in reverse List order, do
2797+
1. If ComparePositions(_subRangeBinding_.[[From]], _position_) is not ~greater~, then
2798+
1. Return _subRangeBinding_.
2799+
1. Return *null*.
2800+
</emu-alg>
2801+
</emu-clause>
2802+
2803+
<emu-clause id="sec-GetOriginalPosition" type="abstract operation">
2804+
<h1>
2805+
GetOriginalPosition (
2806+
_sourceMapRecord_: a Decoded Source Map Record,
2807+
_generatedPosition_: a Position Record,
2808+
): a Decoded Mapping Record or *null*
2809+
</h1>
2810+
<dl class="header">TODO: to be added in https://github.com/tc39/ecma426/pull/195</dl>
2811+
</emu-clause>
2812+
2813+
<emu-clause id="sec-ComputeOriginalFrames" type="abstract operation">
2814+
<h1>
2815+
ComputeOriginalFrames (
2816+
_sourceMap_: a Decoded Source Map Record,
2817+
_generatedFrames_: a List of Debugger Frame Records,
2818+
): a List of Debugger Frame Records
2819+
</h1>
2820+
<dl class="header"></dl>
2821+
<emu-alg>
2822+
1. Let _framePositions_ be a new empty List.
2823+
1. For each Debugger Frame Record _frame_ of _generatedFrames_, do
2824+
1. Append _frame_.[[Position]] to _framePositions_.
2825+
1. Let _sourceMappedFrames_ be SymbolizeStackTrace(_sourceMap_, _framePositions_).
2826+
1. Let _originalFrames_ be a new empty List.
2827+
1. For each SourceMapped Frame Record _sourceMappedFrame_ of _sourceMappedFrames_, do
2828+
1. Let _generatedFrameIndex_ be _sourceMappedFrame_.[[GeneratedFrameIndex]].
2829+
1. Let _generatedFrame_ be _generatedFrames_[_generatedFrameIndex_].
2830+
1. Let _originalPosition_ be _sourceMappedFrame_.[[OriginalPosition]].
2831+
1. Let _originalScopes_ be BuildScopeChain(_sourceMap_, _generatedFrame_.[[Scopes]], _generatedFrame_.[[Position]], _generatedFrameIndex_, _originalPosition_).
2832+
1. Append { [[Position]]: _originalPosition_, [[Scopes]]: _originalScopes_, [[Name]]: _sourceMappedFrame_.[[Name]] } to _originalFrames_.
2833+
1. Return _originalFrames_.
2834+
</emu-alg>
2835+
</emu-clause>
2836+
2837+
<emu-clause id="sec-SymbolizeStackTrace" type="abstract operation">
2838+
<h1>
2839+
SymbolizeStackTrace (
2840+
_sourceMap_: a Decoded Source Map Record,
2841+
_framePositions_: a List of Debugger Position Records,
2842+
): a List of SourceMapped Frame Records
2843+
</h1>
2844+
<dl class="header"></dl>
2845+
<emu-alg>
2846+
1. Let _sourceMappedFrames_ be a new empty List.
2847+
1. Let _i_ be 0.
2848+
1. Let _hideNextFrame_ be *false*.
2849+
1. Repeat, while _i_ is smaller than the length of _framePositions_,
2850+
1. Let _generatedPosition_ be _framePositions_[i].
2851+
1. If _hideNextFrame_ is *false*, then
2852+
1. Let _mapping_ be GetOriginalPosition(_sourceMap_, _generatedPosition_).
2853+
1. Assert: _mapping_ is not *null*.
2854+
1. Let _originalPosition_ be _mapping_.[[OriginalPosition]].
2855+
1. Let _originalSource_ be FindSourceForURL(_sourceMap_.[[Sources]], _originalPosition_.[[URL]]).
2856+
1. Assert: _originalSource_ is not *null*.
2857+
1. Let _originalScope_ be FindInnermostOriginalScope(_originalSource_.[[Scope]], _originalPosition_).
2858+
1. Let _name_ be FindFunctionName(_originalScope_).
2859+
1. Append { [[Name]]: _name_, [[OriginalPosition]]: _originalPosition_, [[GeneratedFrameIndex]]: _i_ } to _sourceMappedFrames_.
2860+
1. Let _generatedRange_ be FindInnermostGeneratedRange(_sourceMap_, _generatedPosition_).
2861+
1. Repeat, while _generatedRange_ is not *null* and _generatedRange_.[[StackFrameType]] is ~none~,
2862+
1. Let _callSite_ be _generatedRange_.[[CallSite]].
2863+
1. If _callSite_ is not *null*, then
2864+
1. Let _callSiteSource_ be _callSite_.[[Source]].
2865+
1. Let _callSiteScope_ be FindInnermostOriginalScope(_callSiteSource_.[[Scope]], _callSite_).
2866+
1. Let _callSiteName_ be FindFunctionName(_callSiteScope_).
2867+
1. Append { [[Name]]: _callSiteName_, [[OriginalPosition]]: _callSite_, [[GeneratedFrameIndex]]: _i_ } to _sourceMappedFrames_.
2868+
1. Set _generatedRange_ to its parent or *null* if it has no parent.
2869+
1. If _generatedRange_ is not *null* and _generatedRange_.[[StackFrameType]] is ~hidden~, then
2870+
1. Let _hideNextFrame_ be *true*.
2871+
1. Else,
2872+
1. Let _hideNextFrame_ be *false*.
2873+
1. Return _sourceMappedFrames_.
2874+
</emu-alg>
2875+
</emu-clause>
2876+
2877+
<emu-clause id="sec-BuildScopeChain" type="abstract operation">
2878+
<h1>
2879+
BuildScopeChain (
2880+
_sourceMap_: a Decoded Source Map Record,
2881+
_debuggerScopes_: a List of Debugger Scope Records,
2882+
_generatedPosition_: a Debugger Position Record,
2883+
_generatedFrameIndex_: a non-negative integral Number,
2884+
_originalPosition_: a Debugger Position Record,
2885+
): a List of Debugger Scope Records
2886+
</h1>
2887+
<dl class="header"></dl>
2888+
<emu-alg>
2889+
1. Let _innermostGeneratedRange_ be FindInnermostGeneratedRange(_sourceMap_.[[Ranges]], _generatedPosition_).
2890+
1. Assert: _innermostGeneratedRange_ is not *null*.
2891+
1. Let _originalSource_ be FindSourceForURL(_sourceMap_.[[Sources]], _originalPosition_.[[URL]]).
2892+
1. Assert: _originalSource_ is not *null*.
2893+
1. Let _originalScope_ be FindInnermostOriginalScope(_originalSource_.[[Scope]], _originalPosition_).
2894+
1. Let _originalDebuggerScopes_ be a new empty List.
2895+
1. Repeat, while _originalScope_ is not *null*,
2896+
1. Let _generatedRange_ be FindAncestorRangeForDefinition(_innermostGeneratedRange_, _originalScope_).
2897+
1. Let _originalBindings_ be a new empty Debugger Bindings Record.
2898+
1. If _generatedRange_ is not *null*, then
2899+
1. Assert: The length of _originalScope_.[[Variables]] is equal to the length of _generatedRange_.[[Bindings]].
2900+
1. Let _scopeIndex_ be FindDebuggerScopeIndexForRange(_debuggerScopes_, _generatedRange_.[[Start]], _generatedRange_.[[End]]).
2901+
1. Let _i_ be 0.
2902+
1. Repeat, while _i_ is smaller than the length of _originalScope_.[[Variables]],
2903+
1. Let _variable_ be _originalScope_.[[Variables]][i].
2904+
1. Let _binding_ be FindBindingRecord(_generatedRange_.[[Bindings]][i], _generatedPosition_).
2905+
1. Assert: _binding_ is not *null*.
2906+
1. Let _value_ be ~unavailable~.
2907+
1. If _binding_.[[Binding]] is not *null*, then
2908+
1. Set _value_ to EvaluateInScope(_generatedFrameIndex_, _scopeIndex_, __binding_.[[Binding]]).
2909+
1. Set the value of _variable_ in _originalBindings_ to _value_.
2910+
1. Set _i_ to _i_ + 1.
2911+
1. Else,
2912+
1. For each String _variable_ of _originalScope_.[[Variables]], do
2913+
1. Set the value of _variable_ in _originalBindings_ to ~unavailable~.
2914+
1. Append { [[Start]]: _originalScope_.[[Start]], [[End]]: _originalScope_.[[End]], [[Bindings]]: _originalBindings_ } to _originalDebuggerScopes_.
2915+
1. Return _originalDebuggerScopes_.
2916+
</emu-alg>
2917+
</emu-clause>
2918+
</emu-clause>
2919+
25352920
<emu-annex id="sec-conventions">
25362921
<h1>Conventions</h1>
25372922

0 commit comments

Comments
 (0)