Bug 1501632 - Return an unsubscribe function from SourceMapURLService.prototype.subscribe; r=loganfsmyth.

The SourceMapURLService has a subscribe and an unsubscribe
functions to respectively listen and stop listening for
source map changes on a given location (url + line + column).
The unsubscribe function need to be called with the same
parameters as the subscribe function, which means the consumer
need to keep a reference to the callback.
By making the subscribe function return the unsubscribe function,
this makes things a bit easier.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Nicolas Chevobbe 2018-10-25 17:15:45 +00:00
Родитель 5165b164ec
Коммит e1af9012ee
4 изменённых файлов: 80 добавлений и 6 удалений

Просмотреть файл

@ -324,6 +324,8 @@ SourceMapURLService.prototype._callOneCallback = async function(subscriptionEntr
* location. If false, then source maps are disabled
* and the generated location should be used; in this
* case the remaining arguments should be ignored.
* @returns {Function | undefined} An unsubscribe function or undefined if the service
* was destroyed.
*/
SourceMapURLService.prototype.subscribe = function(url, line, column, callback) {
if (!this._subscriptions) {
@ -348,6 +350,8 @@ SourceMapURLService.prototype.subscribe = function(url, line, column, callback)
if (this._prefValue) {
this._callOneCallback(subscriptionEntry, callback);
}
return () => this.unsubscribe(url, line, column, callback);
};
/**

Просмотреть файл

@ -72,6 +72,7 @@ skip-if = os == 'win' || debug # Bug 1282269, 1448084
[browser_source_map-init.js]
[browser_source_map-inline.js]
[browser_source_map-no-race.js]
[browser_source_map-pub-sub.js]
[browser_source_map-reload.js]
[browser_source_map-late-script.js]
[browser_target_from_url.js]

Просмотреть файл

@ -0,0 +1,71 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
// Test that the source map service subscribe mechanism work as expected.
"use strict";
const JS_URL = URL_ROOT + "code_bundle_no_race.js";
const PAGE_URL = `data:text/html,
<!doctype html>
<html>
<head>
<meta charset="utf-8"/>
</head>
<body>
<script src="${JS_URL}"></script>
</body>
</html>`;
const ORIGINAL_URL = "webpack:///code_no_race.js";
const GENERATED_LINE = 84;
const ORIGINAL_LINE = 11;
add_task(async function() {
// Opening the debugger causes the source actors to be created.
const toolbox = await openNewTabAndToolbox(PAGE_URL, "jsdebugger");
const service = toolbox.sourceMapURLService;
const cbCalls = [];
const cb = (...args) => cbCalls.push(args);
const expectedArgs = [true, ORIGINAL_URL, ORIGINAL_LINE, 0];
const unsubscribe1 = service.subscribe(JS_URL, GENERATED_LINE, 1, cb);
await waitForSubscribtionsPromise(service);
is(cbCalls.length, 1, "The callback function is called directly when subscribing");
Assert.deepEqual(cbCalls[0], expectedArgs, "callback called with expected arguments");
const unsubscribe2 = service.subscribe(JS_URL, GENERATED_LINE, 1, cb);
await waitForSubscribtionsPromise(service);
is(cbCalls.length, 2, "Subscribing to the same location twice works");
Assert.deepEqual(cbCalls[1], expectedArgs, "callback called with expected arguments");
info("Manually call the dispatcher to ensure subscribers are called");
service._dispatchSubscribersForURL(JS_URL);
await waitForSubscribtionsPromise(service);
is(cbCalls.length, 4, "both subscribers were called");
Assert.deepEqual(cbCalls[2], expectedArgs, "callback called with expected arguments");
Assert.deepEqual(cbCalls[2], cbCalls[3], "callbacks were passed the same arguments");
info("Check unsubscribe functions");
unsubscribe1();
service._dispatchSubscribersForURL(JS_URL);
await waitForSubscribtionsPromise(service);
is(cbCalls.length, 5, "Only remainer subscriber callback was called");
Assert.deepEqual(cbCalls[4], expectedArgs, "callback called with expected arguments");
unsubscribe2();
service._dispatchSubscribersForURL(JS_URL);
await waitForSubscribtionsPromise(service);
is(cbCalls.length, 5, "No callbacks were called");
});
async function waitForSubscribtionsPromise(service) {
for (const [, subscriptionEntry] of service._subscriptions) {
if (subscriptionEntry.promise) {
await subscriptionEntry.promise;
}
}
}

Просмотреть файл

@ -62,16 +62,14 @@ class Frame extends Component {
componentWillMount() {
if (this.props.sourceMapService) {
const { source, line, column } = this.props.frame;
this.props.sourceMapService.subscribe(source, line, column,
this._locationChanged);
this.unsubscribeSourceMapService = this.props.sourceMapService.subscribe(
source, line, column, this._locationChanged);
}
}
componentWillUnmount() {
if (this.props.sourceMapService) {
const { source, line, column } = this.props.frame;
this.props.sourceMapService.unsubscribe(source, line, column,
this._locationChanged);
if (typeof this.unsubscribeSourceMapService === "function") {
this.unsubscribeSourceMapService();
}
}