devtools.inspectedWindow.eval()

在开发工具连接的窗口中执行 JavaScript。

这在某种程度上类似于使用 tabs.executeScript() 来附加内容脚本,但有两个主要区别:

首先,JavaScript 可以使用一组 浏览器通常在其开发者工具控制台实现中提供的特殊命令:例如,使用“$0”来引用“检查器”中当前选中的元素。

其次,您执行的 JavaScript 可以看到页面加载的脚本对页面所做的任何更改。这与内容脚本相反,内容脚本看到页面 就像在没有加载任何页面脚本的情况下存在的那样。但是,请注意,内容脚本提供的隔离是一项故意的安全功能,旨在让恶意或不合作的网页更难通过重新定义 DOM 函数和属性来混淆或破坏 WebExtensions API。这意味着如果您通过使用 eval() 来放弃此保护,您需要非常小心,并且除非您需要使用 eval(),否则应使用内容脚本。

脚本默认在页面的主框架中进行评估。脚本必须评估为可以表示为 JSON 的值(这意味着,例如,它可能无法评估为函数或包含任何函数的对象)。默认情况下,脚本看不到附加到页面的任何内容脚本。

您不能在特权浏览器窗口(例如“about:addons”)上调用 eval()

您可以选择提供一个 options 参数,其中包括在不同框架或已附加内容脚本的上下文中评估脚本的选项。请注意,Firefox 尚不支持 options 参数。

eval() 函数返回一个 Promise,该 Promise 解析为脚本的评估结果或错误。

辅助函数

脚本可以访问许多对象,这些对象有助于注入的脚本与开发者工具进行交互。目前支持以下辅助函数:

$0

包含对“开发者工具检查器”中当前选定元素的引用。

inspect()

给定一个对象,如果它是页面中的 DOM 元素,则在“开发者工具检查器”中选中它;否则,它会在控制台中创建一个对象预览。

查看一些示例。

语法

js
let evaluating = browser.devtools.inspectedWindow.eval(
  expression,       // string
  options           // object
)

参数

表达式

string。要评估的 JavaScript 表达式。该字符串必须评估为可表示为 JSON 的对象,否则将抛出异常。例如,expression 不能评估为函数。

options 可选

object。函数的选项(请注意,Firefox 尚不支持此选项),如下所示:

frameURL 可选

string。要评估表达式的框架的 URL。如果省略此参数,则在窗口的主框架中评估表达式。

useContentScriptContext 可选

boolean。如果为 true,则在扩展程序已附加到页面的任何内容脚本的上下文中评估表达式。如果设置此选项,则您必须确实已将某些内容脚本附加到页面,否则将抛出开发者工具错误。

contextSecurityOrigin 可选

string。在由不同扩展程序附加的内容脚本的上下文中评估表达式,其源与此处给出的值匹配。这会覆盖 useContentScriptContext

返回值

一个 Promise,它将使用一个包含两个元素的 array 来兑现。

如果没有发生错误,则第一个元素将包含评估表达式的结果,第二个元素将是 undefined

如果发生错误,第一个元素将是 undefined,第二个元素将包含一个提供错误详细信息的对象。区分两种不同类型的错误:

  • 评估 JavaScript 时遇到的错误(例如,表达式中的语法错误)。在这种情况下,第二个元素将包含:

    • 一个布尔属性 isException,设置为 true
    • 一个字符串属性 value,提供更多详细信息。
  • 其他错误(例如,表达式评估为无法表示为 JSON 的对象)。在这种情况下,第二个元素将包含:

    • 一个布尔属性 isError,设置为 true
    • 一个字符串属性 code,包含错误代码。

示例

这会测试 jQuery 是否在被检查的窗口中定义,并记录结果。请注意,这在内容脚本中不起作用,因为即使 jQuery 已定义,内容脚本也看不到它。

js
function handleError(error) {
  if (error.isError) {
    console.log(`DevTools error: ${error.code}`);
  } else {
    console.log(`JavaScript error: ${error.value}`);
  }
}

function handleResult(result) {
  console.log(result);
  if (result[0] !== undefined) {
    console.log(`jQuery: ${result[0]}`);
  } else if (result[1]) {
    handleError(result[1]);
  }
}

const checkJQuery = "typeof jQuery !== 'undefined'";

evalButton.addEventListener("click", () => {
  browser.devtools.inspectedWindow.eval(checkJQuery).then(handleResult);
});

辅助函数示例

这使用了 $0 辅助函数来设置“检查器”中当前选定元素的背景颜色。

js
const evalButton = document.querySelector("#reddinate");
const evalString = "$0.style.backgroundColor = 'red'";

function handleError(error) {
  if (error.isError) {
    console.log(`DevTools error: ${error.code}`);
  } else {
    console.log(`JavaScript error: ${error.value}`);
  }
}

function handleResult(result) {
  if (result[1]) {
    handleError(result[1]);
  }
}

evalButton.addEventListener("click", () => {
  browser.devtools.inspectedWindow.eval(evalString).then(handleResult);
});

这使用了 inspect() 辅助函数来选中页面中的第一个 <h1> 元素。

js
const inspectButton = document.querySelector("#inspect");
const inspectString = "inspect(document.querySelector('h1'))";

function handleError(error) {
  if (error.isError) {
    console.log(`DevTools error: ${error.code}`);
  } else {
    console.log(`JavaScript error: ${error.value}`);
  }
}

function handleResult(result) {
  if (result[1]) {
    handleError(result[1]);
  }
}

inspectButton.addEventListener("click", () => {
  browser.devtools.inspectedWindow.eval(inspectString).then(handleResult);
});

浏览器兼容性

注意:此 API 基于 Chromium 的 chrome.devtools API。