diff --git a/spec.emu b/spec.emu index 713af45..052fc4b 100644 --- a/spec.emu +++ b/spec.emu @@ -2638,6 +2638,413 @@ + +

Computing original stack frames

+

+ + +

Source Maps Record

+

A Source Maps Record associates source URLs to Decoded Source Map Records.

+
+ + +

Debugger Position Record

+

A Debugger Position Record is a tuple of a source URL and non-negative line and column numbers.

+ + + + + + + + + + + + + + + + + + + + +
Field NameValue Type
[[URL]]a URL or *null*
[[Line]]a non-negative integral Number
[[Column]]a non-negative integral Number
+
+
+ + +

Debugger Bindings Record

+

A Debugger Bindings Record associates variable names to implementation-defined representations of javascript values in the debuggee or to ~unavailable~.

+
+ + +

Debugger Scope Record

+

A Debugger Scope Record is a tuple of start and end positions and a Debugger Bindings Record.

+ + + + + + + + + + + + + + + + + + + + + + + + +
Field NameValueMeaning
[[Start]]A Debugger Position RecordThe line and column (inclusive) where the scope starts.
[[End]]A Debugger Position RecordThe line and column (exclusive) where the scope ends.
[[Bindings]]A Debugger Bindings RecordThe bindings of the scope.
+
+
+ + +

Debugger Frame Record

+

A Debugger Frame Record is a tuple of a position, a list of scopes and an optional name.

+ + + + + + + + + + + + + + + + + + + + + + + + +
Field NameValueMeaning
[[Position]]A Debugger Position RecordThe position where execution was paused.
[[Scopes]]A List of Debugger Scope RecordsThe scopes of the frame, starting with the innermost scope.
[[Name]]A String or *null*The name of the frame.
+
+
+ + +

SourceMapped Frame Record

+

A SourceMapped Frame Record contains the name and position of an original frame and the index of its corresponding generated frame.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Field NameValueMeaning
[[Name]]A String or *null*The name of the original frame.
[[OriginalPosition]]A Debugger Position RecordThe position of the original frame.
[[GeneratedFrameIndex]]a non-negative integral NumberThe index of the corresponding generated frame.
[[HideCaller]]a Boolean
+
+
+ + +

+ EvaluateInScope ( + _frameIndex_: a non-negative integral Number, + _scopeIndex_: a non-negative integral Number, + _expression_: a String, + ) +

+
+
description
+
+ The debugger must provide an operation for evaluating an expression in the frame and scope from the current stack indicated by their indices. + EvaluateInScope(0, 0, _expression_) evaluates _expression_ in the innermost scope of the current top frame. +
+
+
+ + +

+ FindInnermostGeneratedRange ( + _ranges_: a List of Generated Range Records, + _position_: a Debugger Position Record, + ): a Generated Range Record or *null* +

+
+ + 1. For each Generated Range Record _range_ of _ranges_, do + 1. If ComparePositions(_range_.[[Start]], _position_) is not ~greater~ and ComparePositions(_range_.[[End]], _position_) is ~greater~, then + 1. Let _descendantRange_ be FindInnermostGeneratedRange(_range_.[[Children]], _position_). + 1. If _descendantRange_ is not *null*, then + 1. Return _descendantRange_. + 1. Else, + 1. return _range_. + 1. Return *null*. + +
+ + +

+ FindInnermostOriginalScope ( + _scope_: an Original Scope Record, + _position_: a Debugger Position Record, + ): an Original Scope Record +

+
+ + 1. For each Original Scope Record _childScope_ of _scope_.[[Children]], do + 1. If ComparePositions(_childScope_.[[Start]], _position_) is not ~greater~ and ComparePositions(_childScope_.[[End]], _position_) is ~greater~, then + 1. return FindInnermostOriginalScope(_childScope_, _position_). + 1. Return _scope_. + +
+ + +

+ FindSourceForURL ( + _sources_: a List of Decoded Source Records, + _URL_: a URL, + ): a Decoded Source Record or *null* +

+
+ + 1. For each Decoded Source Record _source_ of _sources_, do + 1. If _source_.[[URL]] is _URL_, then + 1. Return _source_. + 1. Return *null*. + +
+ + +

+ FindAncestorRangeForDefinition ( + _range_: a Generated Range Record, + _definition_: an Original Scope Record, + ): a Generated Range Record or *null* +

+
+ + 1. Repeat, while _range_ is not *null*, + 1. If _range_.[[Definition]] is _definition_, then + 1. Return _range_. + 1. Set _range_ to its parent or *null* if it has no parent. + 1. Return *null*. + +
+ + +

+ FindFunctionName ( + _scope_: an Original Scope Record, + ): String or *null* +

+
+ + 1. If _scope_.[[IsStackFrame]], then + 1. Return _scope_.[[Name]]. + 1. Let _parentScope_ be the parent of _scope_ or *null* if it has no parent. + 1. If _parentScope_ is not *null*, then + 1. Return FindFunctionName(_parentScope_). + 1. Return *null*. + +
+ + +

+ FindDebuggerScopeIndexForRange ( + _debuggerScopes_: a List of Debugger Scope Records, + _start_: a Debugger Position Record, + _end_: a Debugger Position Record, + ): a non-negative integral Number or *null* +

+
+ + 1. Let _index_ be 0. + 1. Repeat, while _index_ is smaller than the length of _debuggerScopes_, + 1. Let _scope_ be _debuggerScopes_[_index_]. + 1. If ComparePositions(_scope_.[[Start]], _start_) is not ~greater~ and ComparePositions(_scope_.[[End]], _end_) is not ~less~, then + 1. Return _index_. + 1. Set _index_ to _index_ + 1. + 1. Return *null*. + +
+ + +

+ FindBindingRecord ( + _subRangeBindings_: a List of Binding Records, + _position_: a Debugger Position Record, + ): a Binding Record or *null* +

+
+ + 1. For each Binding Record _subRangeBinding_ in _subRangeBindings_, in reverse List order, do + 1. If ComparePositions(_subRangeBinding_.[[From]], _position_) is not ~greater~, then + 1. Return _subRangeBinding_. + 1. Return *null*. + +
+ + +

+ ComputeOriginalFrames ( + _sourceMap_: a Decoded Source Map Record, + _generatedFrames_: a List of Debugger Frame Records, + ): a List of Debugger Frame Records +

+
+ + 1. Let _framePositions_ be a new empty List. + 1. For each Debugger Frame Record _frame_ of _generatedFrames_, do + 1. Append _frame_.[[Position]] to _framePositions_. + 1. Let _sourceMappedFrames_ be MapStackTrace(_sourceMap_, _framePositions_). + 1. Let _originalFrames_ be a new empty List. + 1. For each SourceMapped Frame Record _sourceMappedFrame_ of _sourceMappedFrames_, do + 1. Let _generatedFrameIndex_ be _sourceMappedFrame_.[[GeneratedFrameIndex]]. + 1. Let _generatedFrame_ be _generatedFrames_[_generatedFrameIndex_]. + 1. Let _originalPosition_ be _sourceMappedFrame_.[[OriginalPosition]]. + 1. Let _originalScopes_ be BuildScopeChain(_sourceMap_, _generatedFrame_.[[Scopes]], _generatedFrame_.[[Position]], _generatedFrameIndex_, _originalPosition_). + 1. Append { [[Position]]: _originalPosition_, [[Scopes]]: _originalScopes_, [[Name]]: _sourceMappedFrame_.[[Name]] } to _originalFrames_. + 1. Return _originalFrames_. + +
+ + +

+ MapStackTrace ( + _sourceMaps_: a Source Maps Record, + _framePositions_: a List of Debugger Position Records, + ): a List of SourceMapped Frame Records +

+
+ + 1. Let _sourceMappedFrames_ be a new empty List. + 1. Let _i_ be 0. + 1. Let _hideNextFrame_ be *false*. + 1. Repeat, while _i_ is smaller than the length of _framePositions_, + 1. Let _sourceMap_ be the Decoded Source Map Record associated with _framePositions_[_i_][[URL]] in _sourceMaps_. + 1. Let _currentSourceMappedFrames_ be MapStackFrame(_sourceMap_, _framePositions_[_i_]). + 1. Let _j_ be 0. + 1. Repeat, while _j_ is smaller than the length of _currentSourceMappedFrames_, + 1. If _hideNextFrame_ is *false*, + 1. Set _currentSourceMappedFrames_[j].[[GeneratedFrameIndex]] to _i_. + 1. Append _currentSourceMappedFrames_[j] to _sourceMappedFrames_. + 1. Set _hideNextFrame_ to _currentSourceMappedFrames_[j].[[HideCaller]]. + 1. Set _j_ to _j_ + 1. + 1. Set _i_ to _i_ + 1. + 1. Return _sourceMappedFrames_. + +
+ + +

+ MapStackFrame ( + _sourceMap_: a Decoded Source Map Record, + _framePosition_: a Debugger Position Record, + ): a List of SourceMapped Frame Records +

+
+ + 1. Let _sourceMappedFrames_ be a new empty List. + 1. Let _originalPositions_ be GetOriginalPositions(_sourceMap_, _framePosition_). + 1. Assert: _originalPositions_ is not empty. + 1. Let _originalPosition_ be _originalPositions_[0]. + 1. Let _originalSource_ be FindSourceForURL(_sourceMap_.[[Sources]], _originalPosition_.[[URL]]). + 1. Assert: _originalSource_ is not *null*. + 1. Let _originalScope_ be FindInnermostOriginalScope(_originalSource_.[[Scope]], _originalPosition_). + 1. Let _name_ be FindFunctionName(_originalScope_). + 1. Append { [[Name]]: _name_, [[OriginalPosition]]: _originalPosition_, [[GeneratedFrameIndex]]: 0, [[HideCaller]]: *false* } to _sourceMappedFrames_. + 1. Let _generatedRange_ be FindInnermostGeneratedRange(_sourceMap_, _framePosition_). + 1. Repeat, while _generatedRange_ is not *null* and _generatedRange_.[[StackFrameType]] is ~none~, + 1. Let _callSite_ be _generatedRange_.[[CallSite]]. + 1. If _callSite_ is not *null*, then + 1. Let _callSiteSource_ be _callSite_.[[Source]]. + 1. Let _callSiteScope_ be FindInnermostOriginalScope(_callSiteSource_.[[Scope]], _callSite_). + 1. Let _callSiteName_ be FindFunctionName(_callSiteScope_). + 1. Append { [[Name]]: _callSiteName_, [[OriginalPosition]]: _callSite_, [[GeneratedFrameIndex]]: 0, [[HideCaller]]: *false* } to _sourceMappedFrames_. + 1. Set _generatedRange_ to its parent or *null* if it has no parent. + 1. If _generatedRange_ is not *null* and _generatedRange_.[[StackFrameType]] is ~hidden~, then + 1. Let _lastFrame_ be the last element of _sourceMappedFrames_. + 1. Set _lastFrame_.[[HideCaller]] to *true*. + 1. Return _sourceMappedFrames_. + +
+ + +

+ BuildScopeChain ( + _sourceMap_: a Decoded Source Map Record, + _debuggerScopes_: a List of Debugger Scope Records, + _generatedPosition_: a Debugger Position Record, + _generatedFrameIndex_: a non-negative integral Number, + _originalPosition_: a Debugger Position Record, + ): a List of Debugger Scope Records +

+
+ + 1. Let _innermostGeneratedRange_ be FindInnermostGeneratedRange(_sourceMap_.[[Ranges]], _generatedPosition_). + 1. Assert: _innermostGeneratedRange_ is not *null*. + 1. Let _originalSource_ be FindSourceForURL(_sourceMap_.[[Sources]], _originalPosition_.[[URL]]). + 1. Assert: _originalSource_ is not *null*. + 1. Let _originalScope_ be FindInnermostOriginalScope(_originalSource_.[[Scope]], _originalPosition_). + 1. Let _originalDebuggerScopes_ be a new empty List. + 1. Repeat, while _originalScope_ is not *null*, + 1. Let _generatedRange_ be FindAncestorRangeForDefinition(_innermostGeneratedRange_, _originalScope_). + 1. Let _originalBindings_ be a new empty Debugger Bindings Record. + 1. If _generatedRange_ is not *null*, then + 1. Assert: The length of _originalScope_.[[Variables]] is equal to the length of _generatedRange_.[[Bindings]]. + 1. Let _scopeIndex_ be FindDebuggerScopeIndexForRange(_debuggerScopes_, _generatedRange_.[[Start]], _generatedRange_.[[End]]). + 1. Let _i_ be 0. + 1. Repeat, while _i_ is smaller than the length of _originalScope_.[[Variables]], + 1. Let _variable_ be _originalScope_.[[Variables]][i]. + 1. Let _binding_ be FindBindingRecord(_generatedRange_.[[Bindings]][i], _generatedPosition_). + 1. Assert: _binding_ is not *null*. + 1. Let _value_ be ~unavailable~. + 1. If _binding_.[[Binding]] is not *null*, then + 1. Set _value_ to EvaluateInScope(_generatedFrameIndex_, _scopeIndex_, __binding_.[[Binding]]). + 1. Set the value of _variable_ in _originalBindings_ to _value_. + 1. Set _i_ to _i_ + 1. + 1. Else, + 1. For each String _variable_ of _originalScope_.[[Variables]], do + 1. Set the value of _variable_ in _originalBindings_ to ~unavailable~. + 1. Append { [[Start]]: _originalScope_.[[Start]], [[End]]: _originalScope_.[[End]], [[Bindings]]: _originalBindings_ } to _originalDebuggerScopes_. + 1. Set _originalScope_ to its parent or *null* if it has no parent. + 1. Return _originalDebuggerScopes_. + +
+
+

Conventions