Debugger.Script

一个 Debugger.Script 实例可能引用调试目标中的字节码序列或 WebAssembly 代码块。对于前者,它是 Debugger API 对 JSAPI JSScript 对象的表示。这两种情况可以通过它们的 format 属性区分,属性值为 "js""wasm"

用于 JSScripts 的 Debugger.Script

对于引用 JSScriptDebugger.Script 实例,它们的 format 属性值为 "js"

以下每个内容都由一个 JSScript 对象表示

  • 函数体——也就是说,函数中所有不包含在嵌套函数中的代码。

  • 传递给 eval 的单个调用的代码,不包括该代码定义的任何函数的函数体。

  • <script> 元素的内容。

  • DOM 事件处理程序,无论是在 HTML 中嵌入还是由其他 JavaScript 代码附加到元素上。

  • 出现在 javascript: URL 中的代码。

当调试器发现调试目标代码的脚本时,Debugger 接口会构造 Debugger.Script 对象:通过 onNewScript 处理程序方法;通过 Debugger.Framescript 属性;通过 Debugger.Object 实例的 functionScript 方法;等等。对于给定的 Debugger 实例,SpiderMonkey 为每个底层脚本对象正好构造一个 Debugger.Script 实例;调试器代码可以向脚本对象添加自己的属性并期望稍后找到它们,使用 == 来确定两个表达式是否引用同一个脚本,等等。

(如果多个 Debugger 实例正在调试相同的代码,则每个 Debugger 为给定的脚本获取一个单独的 Debugger.Script 实例。这允许使用每个 Debugger 实例的代码在其 Debugger.Script 实例上放置任何它喜欢的属性,而无需担心干扰其他调试器。)

Debugger.Script 实例是对 JSScript 对象的强引用;它防止它引用的脚本被垃圾回收。

请注意,SpiderMonkey 可能会对等效的函数或已评估的代码使用相同的 Debugger.Script 实例——也就是说,表示相同源代码、在相同源文件中的相同位置、在相同词法环境中评估的脚本。

用于 WebAssembly 的 Debugger.Script

对于引用 WebAssembly 代码块的 Debugger.Script 实例,它们的 format 属性值为 "wasm"

目前仅表示通过 new WebAssembly.Module 评估的整个模块。

Debugger.Script 用于 WebAssembly 的对象在实例化新的 WebAssembly 模块时通过 onNewScript 发现,并通过 Debugger 实例上的 findScripts 方法发现。SpiderMonkey 为每个底层 WebAssembly 模块(每个 Debugger 实例)构造正好一个 Debugger.Script

Debugger.Script 实例是对底层 WebAssembly 模块的强引用;它防止它引用的模块被垃圾回收。

请注意,在撰写本文时,对 WebAssembly 的支持还处于非常初步的阶段。下面许多属性和方法都会抛出异常。

约定

对于下面属性和方法的描述,如果属性或方法的行为在引用 JSScript 的实例或引用 WebAssembly 代码块的实例之间存在差异,则文本将分为两个部分,分别以“如果实例引用 JSScript”和“如果实例引用 WebAssembly 代码”为标题。如果行为没有差异,则不会出现此类强调标题。

Debugger.Script 原型对象的访问器属性

Debugger.Script 实例从其原型继承以下访问器属性

isGeneratorFunction

如果此实例引用使用 function* 表达式或语句定义的函数的 JSScript,则为 true。否则为 false。

isAsyncFunction

如果此实例引用使用 async function 表达式或语句定义的异步函数的 JSScript,则为 true。否则为 false。

displayName

如果实例引用 JSScript,则为脚本的显示名称(如果存在)。如果脚本没有显示名称——例如,如果它是顶级 eval 脚本——则为 undefined

如果脚本的函数具有给定的名称,则其显示名称与其函数的给定名称相同。

如果脚本的函数没有名称,则 SpiderMonkey 会尝试根据其上下文推断一个合适的名称。例如

function f() {}          // display name: f (the given name)
var g = function () {};  // display name: g
o.p = function () {};    // display name: o.p
var q = {
  r: function () {}      // display name: q.r
};

请注意,显示名称可能不是正确的 JavaScript 标识符,甚至不是正确的表达式:即使函数没有立即赋值为某个变量或属性的值,我们也尝试找到有用的名称。因此,我们使用 a/b 来引用在 a 中定义的 b,并使用 a< 来引用出现在分配给 a 的表达式的某个位置的函数。例如

function h() {
  var i = function() {};    // display name: h/i
  f(function () {});        // display name: h/<
}
var s = f(function () {});  // display name: s<``</pre>

如果实例引用 WebAssembly 代码,则抛出 TypeError

url

如果实例引用 JSScript,则为加载此脚本代码的文件名或 URL。对于由 evalFunction 构造函数创建的脚本,这可能是一个合成的文件名,以有效的 URL 开头,后跟跟踪代码如何引入系统的信息;整个字符串不是有效的 URL。对于 Function.prototype 的脚本,这是 null。如果此 Debugger.Scriptsource 属性非 null,则它等于 source.url

如果实例引用 WebAssembly 代码,则抛出 TypeError

startLine

如果实例引用 JSScript,则为此脚本代码在 url 指定的文件或文档中开始的行号。

lineCount

如果实例引用 JSScript,则为此脚本代码在 url 指定的文件或文档中占用的行数。

source

如果实例引用 JSScript,则为表示生成此脚本的源代码的 Debugger.Source 实例。如果源代码未保留,则为 null

如果实例引用 WebAssembly 代码,则为表示 WebAssembly 代码序列化文本格式的 Debugger.Source 实例。

sourceStart

如果实例引用 JSScript,则为 source 给出的 Debugger.Source 实例中此脚本代码开始处的字符;从零开始。如果这是一个函数的脚本,则这是源代码中 function 令牌开始的索引。

如果实例引用 WebAssembly 代码,则抛出 TypeError

sourceLength

如果实例引用 JSScript,则为 source 给出的 Debugger.Source 实例中此脚本代码的长度(以字符为单位)。

如果实例引用 WebAssembly 代码,则抛出 TypeError

global

如果实例引用 JSScript,则为引用此脚本运行的全局对象的 Debugger.Object 实例。结果直接引用全局对象,而不是通过包装器或 WindowProxy(在 Firefox 中为“外部窗口”)。

如果实例引用 WebAssembly 代码,则抛出 TypeError

format

如果实例引用 JSScript,则为 "js"

如果实例引用 WebAssembly 代码,则为 "wasm"

Debugger.Script 原型对象的函数属性

下面描述的函数只能使用引用 Debugger.Script 实例的 this 值来调用;它们不能用作其他类型对象的的方法。

getAllOffsets()

如果实例引用的是 JSScript,则返回一个数组 L,描述此脚本中字节码指令偏移量和源代码位置之间的关系。L 是稀疏的,并以源代码行号为索引。如果源代码行号 line 没有代码,则 L 没有 line 属性。如果 line 有代码,则 L[line] 是该行字节码指令入口点的偏移量数组。

例如,假设我们有一个脚本,其源代码如下所示

a=[]
for (i=1; i < 10; i++)
  // It's hip to be square.
  a[i] = i*i;

对该代码调用 getAllOffsets() 可能会产生如下所示的数组

[[0], [5, 20], , [10]]

此数组表示

  • 第一行代码从脚本中的偏移量 0 开始;

  • for 语句头有两个入口点,偏移量分别为 5 和 20(用于仅执行一次的初始化和每次迭代开始时执行的循环测试);

  • 第三行没有代码;

  • 第四行从偏移量 10 开始。

如果实例引用 WebAssembly 代码,则抛出 TypeError

getAllColumnOffsets():

如果实例引用的是 JSScript,则返回一个数组,描述此脚本中字节码指令偏移量和源代码位置之间的关系。与返回每行所有入口点的偏移量的 getAllOffsets() 不同,getAllColumnOffsets() 返回每个 (行,列) 对的所有入口点的偏移量。

数组的元素是对象,每个对象描述一个入口点,并包含以下属性

  • lineNumber:偏移量是其入口点的行号

  • columnNumber:偏移量是其入口点的基于 1 的列号

  • offset:入口点的字节码指令偏移量

例如,假设我们有一个脚本,其源代码如下所示

a=[]
for (i=1; i < 10; i++)
  // It's hip to be square.
a[i] = i*i;

对该代码调用 getAllColumnOffsets() 可能会产生如下所示的数组

[{ lineNumber: 0, columnNumber: 1, offset: 0 },
 { lineNumber: 1, columnNumber: 6, offset: 5 },
 { lineNumber: 1, columnNumber: 11, offset: 20 },
 { lineNumber: 3, columnNumber: 5, offset: 10 }]

如果实例引用 WebAssembly 代码,则抛出 TypeError

getLineOffsets(line)

如果实例引用的是 JSScript,则返回一个字节码指令偏移量数组,表示源代码行 line 的入口点。如果脚本在该行没有可执行代码,则返回的数组为空。

getOffsetLocation(offset)

如果实例引用的是 JSScript,则返回一个对象,描述此脚本中 offset 处的字节码对应的源代码位置。该对象具有以下属性

  • lineNumber:偏移量是其入口点的行号

  • columnNumber:偏移量是其入口点的基于 1 的列号

  • isEntryPoint:如果偏移量是列入口点(如 getAllColumnOffsets() 所报告的那样),则为 true;否则为 false。

getOffsetsCoverage():

如果实例引用的是 JSScript,则返回 null 或一个数组,其中包含所有操作码覆盖范围的信息。数组的元素是对象,每个对象描述一个操作码,并包含以下属性

  • lineNumber:当前操作码的行号。

  • columnNumber:当前操作码的基于 1 的列号。

  • offset:当前操作码的字节码指令偏移量。

  • count:当前操作码执行的次数。

如果此脚本没有覆盖范围,或者没有进行检测,则此函数将返回 null。要确保被调试者已进行检测,应将标志 Debugger.collectCoverageInfo 设置为 true

如果实例引用 WebAssembly 代码,则抛出 TypeError

getChildScripts()

如果实例引用的是 JSScript,则返回一个新数组,其元素是此脚本中每个函数的 Debugger.Script 对象。仅包含直接子项;嵌套子项可以通过遍历树来访问。

如果实例引用 WebAssembly 代码,则抛出 TypeError

setBreakpoint(offset, handler)

如果实例引用的是 JSScript,则在此脚本的 offset 处的字节码指令处设置断点,并将命中情况报告给 handlerhit 方法。如果 offset 不是此脚本中的有效偏移量,则抛出错误。

当执行到达给定指令时,SpiderMonkey 会调用 handlerhit 方法,并传递一个 Debugger.Frame 实例,表示当前正在执行的堆栈帧。 hit 方法的返回值应为恢复值,确定执行应如何继续。

可以在一个位置设置任意数量的断点;当控制权到达该点时,SpiderMonkey 会以未指定的顺序调用它们的处理程序。

任意数量的断点可以使用相同的 handler 对象。

断点处理程序方法调用是跨隔室、线程内调用:调用发生在命中断点的同一线程中,以及包含处理程序函数的隔室中(通常是调试器的隔室)。

新断点属于此脚本所属的 Debugger 实例。禁用 Debugger 实例会禁用此断点;从 Debugger 实例的被调试者集中删除全局变量会清除该 Debugger 实例在该全局变量的脚本中的所有断点。

getBreakpoints([offset])

如果实例引用的是 JSScript,则返回一个数组,其中包含在此脚本的 offset 处设置的所有断点的处理程序对象。如果省略 offset,则返回在此脚本中任何位置设置的所有断点的处理程序。如果 offset 存在,但不是此脚本中的有效偏移量,则抛出错误。

如果实例引用 WebAssembly 代码,则抛出 TypeError

clearBreakpoint(handler, [offset])

如果实例引用的是 JSScript,则删除在此 Debugger 实例中使用 handler 作为其处理程序的所有断点。如果给定 offset,则仅删除在 offset 处设置并使用 handler 的断点;如果 offset 不是此脚本中的有效偏移量,则抛出错误。

请注意,如果使用其他处理程序对象的断点设置在与 handler 相同的位置,则这些断点将保留。

clearAllBreakpoints([offset])

如果实例引用的是 JSScript,则删除在此脚本中设置的所有断点。如果 offset 存在,则删除在此脚本的该偏移量处设置的所有断点;如果 offset 不是此脚本中的有效字节码偏移量,则抛出错误。

isInCatchScope([offset])

如果实例引用的是 JSScript,则如果此偏移量落在 try 块的范围内,则为 true,否则为 false

如果实例引用 WebAssembly 代码,则抛出 TypeError

源元数据

生成自文件

js/src/doc/Debugger/Debugger.Script.md

水印

sha256:8816a4e8617be32c4ce7f3ae54970fe9c8a7d248175d215a8990ccff23e6efa9

变更集

5572465c08a9+