devtools.inspectedWindow.eval()

在 devtools 附加到的窗口中执行 JavaScript。

这有点像使用 tabs.executeScript() 附加内容脚本,但有两个主要区别

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

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

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

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

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

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

帮助器

脚本可以访问许多对象,这些对象有助于注入的脚本与开发者工具交互。以下帮助器当前受支持

$0

包含对 devtools Inspector 中当前选定的元素的引用。

inspect()

给定一个对象,如果它是页面中的 DOM 元素,则在 devtools Inspector 中选择它,否则它会在 webconsole 中创建对象预览。

查看一些示例。

语法

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

参数

expression

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

options 可选

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

frameURL 可选

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

useContentScriptContext 可选

boolean。如果为 true,则在与此扩展附加到页面的任何内容脚本的上下文中评估表达式。如果设置此选项,则必须实际将某些内容脚本附加到页面,否则会抛出 Devtools 错误。

contextSecurityOrigin 可选

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

返回值

一个 Promise,它将使用包含两个元素的 array 填充。

如果未发生错误,则元素 0 将包含评估表达式的结果,元素 1 将为 undefined

如果发生错误,则元素 0 将为 undefined,元素 1 将包含一个对象,其中提供有关错误的详细信息。区分两种不同的错误

  • 评估 JavaScript 时遇到的错误(例如,表达式中的语法错误)。在这种情况下,元素 1 将包含
    • 一个布尔属性 isException,设置为 true
    • 一个字符串属性 value,提供更多详细信息。
  • 其他错误(例如,评估结果为无法表示为 JSON 的对象的表达式)。在这种情况下,元素 1 将包含
    • 一个布尔属性 isError,设置为 true
    • 一个字符串属性 code,包含错误代码。

浏览器兼容性

BCD 表仅在启用 JavaScript 的浏览器中加载。

示例

这测试 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 帮助器设置 Inspector 中当前选定的元素的背景颜色

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。