开发者工具-sources(源代码选项)
一、概要说明
源代码面板从视觉效果上分为三个区域:菜单区、内容区、监听区。

- 菜单区里面有5个子分类:
- 网页(Page):
指页面源的集合体内容, 包括主页面以及所有子域名下的内容, 这些内容均会被包含进来, 特别是iframe窗口中的资源信息,方便我们对资源信息进行查看。 - 文件系统(Filesystem)(工作区):可以关
与本地一个存储目录相关联, 当在内容区域修改该目录中的数据时, 系统会同步更新磁盘上的对应数据, 这种机制非常适合于实时性编辑项目相关数据。 - 替换(Overrides):
可以通过本地存储的资源信息来替代表现为当前页面的内容, 这种操作特别适合于在调试过程中快速修改代码片段。 - 内容脚本(Content scripts):用来
展示当前工作区中所有运行过的扩展程序的相关代码, 这种功能特别适合于了解当前运行状态并辅助调试。 - 代码段(Snippets):
专门用于执行一些预先编写的脚本代码, 这种机制能够帮助我们快速调用常用的逻辑模块而无需每次都从头编写同样的代码。
内容区是用来展示不同文件的代码片段,并便于设置断点等操作流程;同时支持代码格式化功能。
-监听区
监控区域主要负责对程序运行中的停顿点进行管理与审查,并对用户设定的各项事件进行监控。通常涵盖如下十个具体功能模块。

- 操作区域顶端:主要负责管理断点的运行。
- 监视功能(Watch)允许用户查看当前作用域链中的变量情况。
- 断点设置(Breakpoints)提供当前断点的位置信息及其相关细节。
- 作用域管理(Scope)涵盖本地、脚本及全局范围内的所有变量。
- 调用堆栈(Call Stack)反映当前代码的调用上下文。
- XHR功能(XHR/提取断点)提供一种方法来设置请求中断点。
- DOM操作中断(DOM Breakpoints)当对DOM元素设置断 point 时,在此位置显示相关的元素状态。
- 全局事件监听(Global Listeners)存储注册的所有全局事件信息。
- 事件监听器中断(Event Listener Breakpoints)根据注册的具体事件类型,在相应触发条件下自动启动相关代码路径并设置相应的执行中断。
- 内容安全策略违规中断(CSP Violation Breakpoints)这是一种内容安全策略指示符。当启用该 CSP 策略后,在检测到可能的安全风险行为时会立即暂停执行并发出警告提示。
二、详解
- 菜单区:
- 文件系统(Filesystem)
主要功能是与本地文件建立关联,并提供了一个集成化的编辑与管理界面。类似于一个集成开发环境(IDE),这个工具类似于Visual Studio Code这样的开发工具,在界面上提供了类似的编辑窗口和工作区布局。通过这个功能你能够访问并操作指定的项目目录,并通过其提供的丰富功能实现代码管理和协作工作。你可以将它视为一个完整的项目空间,在此空间中你可以创建、编辑和管理各种类型的电子文档和其他资源。这个工具特别适合用于团队协作场景,在这种情况下它可以帮助所有参与者在一个统一的环境中进行文档管理和版本控制操作。


当我们希望在网页界面直接编辑代码进行调试时, 但又不希望将修改的内容本地保存至硬盘后再编辑, 那么我们可以采用替换功能。具体来说, 可以将当前修改的文件副本临时存档至我们预先指定的一个工作目录中, 然后用该临时文件替换当前页面中的对应文件, 从而实现即时性的代码调试效果。
在项目路径下之前内设了一个replace文件夹用于配置临时替换文件的位置

然后我们把这个replace作为选择放置替换项的文件夹

为了对9.js进行调整,在网页(page)中修改相关代码块。将函数体内的表达式从m+n+1更改为m+n+5后保存页面后会看到替换行为的变化。

同时输出值也发生了实时的改变。

而且本地源文件是没有变化的。

通过这一功能实现,在页面调试过程中我们就可以直接修改文件内容并即时查看处理结果。同时,在此过程中无需对原始代码进行任何修改或干扰。
- 内容脚本(Content scripts)
对于对此感兴趣的朋友来说主要涉及一些软件扩展工具例如Vue插件等工具这些属于本项目不涉及的内容因此无需过多阐述细节
- 代码段(Snippets)
可以把这个`视为处于当前作用域内有效的可运行文件,并且需要注意的是,在常规情况下以及断点调试期间都可以访问并运行这段代码块
比如我们想要获取页面中的所有input。

那么首先新建一个代码段,命名为“页面中所有input”,并编写文件的内容。

然后我们在左侧的这个代码段名称上面右键点击,在左侧代码块名称处单击以打开选项菜单;接着,在选项菜单中选择打印或获取allInput变量的值;最后观察结果如何。

很神奇有没有?我们发现当前作用域下,该变量是完全可用的。
接下来我们试着调试一下文章开始的那段代码。

然后我们在页面的return处打上断点,刷新页面重新加载一下。

可以看到变量m和n当前的值分别为3和4。程序逻辑中决定新建一个‘修改add返回值’的代码段,并设置变量m和n的新值分别为10和7。完成保存操作后立即执行下一步骤。

我们把鼠标放上去看看有什么变化?

通过观察得知,在此过程中m和n的值发生了变化。实际上,在再次按下F10键后,断点将重新执行一次,请查看结果。

这下是不是更清晰了,现在我们把断点放过去,来看一下控制台的输出。

结果已经受到影响,并不如同一开始那个结果一般无二。大家是不是完全明白呢?这个时候,在控制台打印出m和n的值吧!看看会发生些什么情况。

我们发现,在当时执行代码段时的上下文已经不再存在。这具体原因在于,在执行代码块的过程中,默认会将该操作脱离当前作用域范围,并将其独立为一个临时实体存储起来。因此我们可以利用这一特性为我们提供了一个独特的机会,在实际应用中,则可以通过这种方式实现各种创新性的功能。比如在逆向爬虫中常用到hook技术就可以很好地体现这一思想
监听区
-
- 顶部操作区
这里的操作涵盖了我们在调试时的所有内容,在打断时会被频繁使用。请确保大家对这些按钮已经很熟悉了,在这里仅做一个简要的介绍。

- 继续执行当前脚本流程。
- 跳过后续函数的调用。
- 深入下个函数体。
- 退出当前方法。
- 逐行执行。
- 关闭所有断点设置。
- 如果选择在发生异常时暂停代码运行,则会自动暂停代码的执行;如果选择不在异常时暂停,则即使发生异常也不会停止代码的执行。

-
- 监视
该系统能够具备对当前执行环境的作用域链上所有可监控的变量和表达式进行跟踪,并且例如,在计算最大差值时使用的函数.

- 我们可以
监视任意合法的表达式,甚至可以进行赋值。

代码的原始执行结果应为13, 然而当我们重新将min赋值时, 结果发生了变化

一旦放开断点之后,在赋值语句执行时原先属于局部变量范围内的min值会被转换为全局变量

-
- 断点(Breakpoints)
显示断点位置及其对应内容

并且可以通过右键进行一些其他的操作。

-
- 作用域(Scope)
会展示出当前断点位置的作用域链上的所有变量。

- 如果是函数的话,则会有局部变量用于代表该函数内部所使用的各项参数与中间结果。
- 脚本指那些可以在运行时被访问到并操作其内容的对象中的数据元素。例如,在另一个引入的js文件中定义了k、m、t等变量(如var k=5; var m=10; var t='hello';),但需要注意的是这些额外定义的全局变量只有在当前代码行之前被引用时才可被访问到。
- 全局指的是作为与window相关的存储空间而存在的特殊数据区域。由于我们声明的所有变数均使用了let关键字进行类型说明与初始化操作(如let average=60;),因此这些变数不会被分配到window对象中而只能存在于特定的数据容器内。如果将average用var关键字声明(如var average=60;),则该变数将脱离当前脚本环境并存放在全局存储区。
而且如果增加闭包的话,情况会有一些变化。

我们注意到多了一个闭包区域,并且其中仅包含max这一项。这可能让人感到疑惑的是,在上面提到的min变量确实被声明并赋值了数值。那么为何它不会显示出来呢?这是因为min变量并未在闭包函数内部被使用到,在生成闭包环境的过程中也没有将其包含进去。因此,在当前作用域中无法获得关于min变量的引用信息,请参考此时控制台上的输出结果以获取相关信息

看来这会儿已经看得比较清楚了。从这里可以看出当前执行的代码作用域非常清楚。
-
- 调用堆栈(Call Stack)
该工具能够显示当前代码在哪里被调用。当存在更高层次的调用栈时...$...$...。
我们来构造一个案例,看看它的效果。

id的方法比info方法先执行
-
- XHR/提取断点(XHR/fetch Breakpoints)
根据指定标识,在发起请求时(注意:仅限于XHR或fetch形式),如果某个请求路径包含该标识,则会触发断点)。如果选择的是js或css等类型(即使设置了相关参数也不会生效),也可以选择性地设置条件或不设置。
假设我们有如下代码:
//9.js
var xhr = new XMLHttpRequest();
xhr.open("GET", "8.json");
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(xhr.responseText);
}
};
xhr.send();
bash
//8.json
{
"name": "liu",
"sex": 0,
"age": 15
}
bash
我们设置过滤条件为网址包含8.json

同时在页面加载的过程中包含这个标识的请求就会自动触发断点。

当希望避免拦截所有请求时,在完成标识添加后,请直接单击空白区域以继续操作。
-
- DOM断点(DOM Breakpoints)
可以给DOM元素配置合适的断点条件
假设我们有如下代码:
//9.html
<body>
<div id="div" date-key="divKey">我就是我</div>
<input type="text" id="myInput">
<input type="button" value="点我" id="btn">
<script src="9.js"></script>
</body>
bash
//9.js
document
.getElementById("btn")
.addEventListener("click",
function (e) {
document
.getElementById("div")
.classList
.add("active");
}
);
bash
![]()
当我们给页面中的id为div的元素添加属性修改断点时:

我们看到面板中已经显示:

这时我们单击按钮,触发修改属性行为。

我们发现代码已经在第8行暂停执行了。
-
- 全局监听器(Global Listeners)
当我们在配置一些全球性事件时,在此位置会展示出来,并且能够方便地识别哪些地方采用了全球性事件监听功能。我们还支持对这些操作执行临时性的移除功能。
假设我们有以下代码:
//9.js
window.onerror = function (e) {
console.log(e);
};
window.onfocus = function (e) {
console.log(e);
};
window.onload = function (e) {
console.log(e);
};
bash
![]()
那么我们将看到:

-
- 事件监听器断点(Event Listener Breakpoints)
当一段代码响应一些事件时,则会在该代码位置自动设置断点。由于这段代码内容较为丰富且涉及多个功能模块,请仅选取两个典型情况进行举例说明作为参考依据;其他情况则依此类推即可。

① 节点插入事件,假如我们有如下代码:
//9.js
document
.getElementById("btn")
.addEventListener("click",
function (e) {
let d = document.createElement('div')
d.id = "myDiv"
d.innerHTML = "新的div"
document.body.appendChild(d)
}
);
document.addEventListener("DOMNodeInserted",
function (e) {
console.log(e);
}
);
bash
![]()
我们勾选上插入DOM节点的事件监听。

那么当我们单击按钮时, 就会触发相应的事件监听机制, 并在相应的代码位置设置断点.
② 复制事件,假如我们有如下代码:
//9.js
document.addEventListener("copy",
function (e) {
console.log(e);
}
);
bash
我们勾选上copy操作的事件监听。

那么当我们在页面中进行复制操作时

-
- CSP违规断点(CSP Violation Breakpoints)
当服务端实现了并配置了Content Security Policy(CSP)后,并且客户端浏览器也支持相应的机制时,在遇到违反安全策略的行为时将立即触发阻止响应
我们先在页面中使用meta的方式来模拟一下,以触发该策略。
比如我们有以下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- 注意这行代码即开启CSP策略 --><meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
<title>source源代码</title>
<style></style>
</head>
<body>
<div id="div" date-key="divKey">我就是我</div>
<input type="text" id="myInput">
<input type="button" value="点我" id="btn">
<script src="9.js"></script>
<script>
console.log('abc')
</script>
</body>
</html>
bash
![]()
//9.js
eval("{}")
let func = new Function()
setTimeout(function() {
console.log(1)
})
bash
我们会看到控制台报如下错误:

我们可以观察到文件内部的样式表(style)以及脚本(script)部分出现了问题,在JavaScript(js)环境中,“eval”函数也触发了错误。实际上,“new Function”和“setTimeout”等操作同样违反了策略;只要这些错误阻止了代码执行,“eval”的异常处理至关重要。
