Bug 1572280 Part 3 - Reparse sources with GC'ed scripts to get all breakpoint positions, r=loganfsmyth.

Depends on D41127

Differential Revision: https://phabricator.services.mozilla.com/D41128

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Brian Hackett 2019-08-22 00:05:23 +00:00
parent 5c367a54cb
commit 85deb303e4
4 changed files with 62 additions and 0 deletions

View File

@ -164,3 +164,4 @@ skip-if = (os == 'linux' && debug) || (os == 'linux' && asan) || ccov #Bug 1456
[browser_dbg-message-run-to-completion.js]
[browser_dbg-remember-expanded-scopes.js]
[browser_dbg-bfcache.js]
[browser_dbg-gc-breakpoint-positions.js]

View File

@ -0,0 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
"use strict";
// Test that we can set breakpoints in scripts that have been GCed.
add_task(async function() {
const dbg = await initDebugger("doc-gc-breakpoint-positions.html",
"doc-gc-breakpoint-positions.html");
await selectSource(dbg, "doc-gc-breakpoint-positions.html");
await addBreakpoint(dbg, "doc-gc-breakpoint-positions.html", 21);
ok(true, "Added breakpoint at GC'ed script location");
});

View File

@ -0,0 +1,23 @@
<div>
Here
is
some
stuff
so
that
the
source's
start
line
is
not
one
</div>
<script>
// Make sure the source stays alive.
function foo() {
}
// After the outer script has been GC'ed, breakpoints can't be set here.
var x = null;
setTimeout(() => SpecialPowers.gc(), 0);
</script>

View File

@ -384,6 +384,29 @@ const SourceActor = ActorClassWithSpec(sourceSpec, {
const scripts = this._findDebuggeeScripts();
// We need to find all breakpoint positions, even if scripts associated with
// this source have been GC'ed. We detect this by looking for a script which
// does not have a function: a source will typically have a top level
// non-function script. If this top level script still exists, then it keeps
// all its child scripts alive and we will find all breakpoint positions by
// scanning the existing scripts. If the top level script has been GC'ed
// then we won't find its breakpoint positions, and inner functions may have
// been GC'ed as well. In this case we reparse the source and generate a new
// and complete set of scripts to look for the breakpoint positions.
// Note that in some cases like "new Function(stuff)" there might not be a
// top level non-function script, but if there is a non-function script then
// it must be at the top level and will keep all other scripts in the source
// alive.
const isWasm = this._source.introductionType === "wasm";
if (!isWasm && !scripts.some(script => !script.isFunction)) {
scripts.length = 0;
function addScripts(script) {
scripts.push(script);
script.getChildScripts().forEach(addScripts);
}
addScripts(this._source.reparse());
}
const positions = [];
for (const script of scripts) {
// This purely a performance boost to avoid needing to build an array