From 798ea142bcce75a73a114b0f59a7fb3101faa498 Mon Sep 17 00:00:00 2001 From: Tim van der Lippe Date: Fri, 4 Oct 2019 12:01:23 +0000 Subject: [PATCH] Migrate protocol/ to ESM - InspectorBackendCommands is now loaded via ES Modules Bug: 1006759 Change-Id: I2826518a55e1f4fd7704cfb04120885f9aa9b604 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1837772 Reviewed-by: Yang Guo Reviewed-by: Benedikt Meurer Commit-Queue: Tim Van der Lippe Cr-Original-Commit-Position: refs/heads/master@{#702821} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: 01369246df2350c6be2b0118d69313a7f56486bb --- BUILD.gn | 14 +- front_end/protocol/InspectorBackend.js | 228 +++++++++++------- front_end/protocol/NodeURL.js | 15 +- front_end/protocol/module.json | 4 +- front_end/protocol/protocol.js | 15 ++ front_end/root.js | 1 + .../sdk_test_runner/PageMockTestRunner.js | 8 +- scripts/compile_frontend.py | 6 + 8 files changed, 187 insertions(+), 104 deletions(-) create mode 100644 front_end/protocol/protocol.js diff --git a/BUILD.gn b/BUILD.gn index 87e9e3ceaa..6adb8df7e0 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -528,8 +528,6 @@ all_devtools_files = [ "front_end/profiler/ProfileTypeRegistry.js", "front_end/profiler/ProfileView.js", "front_end/profiler/TopDownProfileDataGrid.js", - "front_end/protocol/NodeURL.js", - "front_end/protocol/InspectorBackend.js", "front_end/protocol/module.json", "front_end/quick_open/CommandMenu.js", "front_end/quick_open/filteredListWidget.css", @@ -899,7 +897,9 @@ lighthouse_locale_files = [ all_devtools_files += lighthouse_locale_files all_devtools_modules = [ - "front_end/root.js", + "front_end/protocol/protocol.js", + "front_end/protocol/NodeURL.js", + "front_end/protocol/InspectorBackend.js", "front_end/host/host.js", "front_end/host/UserMetrics.js", "front_end/host/ResourceLoader.js", @@ -1191,6 +1191,9 @@ application_templates = [ ] copied_devtools_modules = [ + "$resources_out_dir/protocol/protocol.js", + "$resources_out_dir/protocol/NodeURL.js", + "$resources_out_dir/protocol/InspectorBackend.js", "$resources_out_dir/host/host.js", "$resources_out_dir/host/UserMetrics.js", "$resources_out_dir/host/ResourceLoader.js", @@ -1492,7 +1495,10 @@ action("generate_devtools_grd") { grd_files = copied_devtools_modules + generated_applications + generated_non_autostart_non_remote_modules + devtools_embedder_scripts + - [ "$resources_out_dir/devtools_extension_api.js" ] + [ + "$resources_out_dir/devtools_extension_api.js", + "$resources_out_dir/InspectorBackendCommands.js", + ] # Bundle remote modules in ChromeOS. if (is_chromeos) { diff --git a/front_end/protocol/InspectorBackend.js b/front_end/protocol/InspectorBackend.js index 81b7a8f32b..3bdb696257 100644 --- a/front_end/protocol/InspectorBackend.js +++ b/front_end/protocol/InspectorBackend.js @@ -32,16 +32,21 @@ * @typedef {string} * @suppress {checkTypes} */ -Protocol.Error = Symbol('Protocol.Error'); +export const ProtocolError = Symbol('Protocol.Error'); +export const DevToolsStubErrorCode = -32015; +// TODO(dgozman): we are not reporting generic errors in tests, but we should +// instead report them and just have some expected errors in test expectations. +const _GenericError = -32000; +const _ConnectionClosedErrorCode = -32001; /** * @unrestricted */ -Protocol.InspectorBackend = class { +export default class InspectorBackend { constructor() { - /** @type {!Map} */ + /** @type {!Map} */ this._agentPrototypes = new Map(); - /** @type {!Map} */ + /** @type {!Map} */ this._dispatcherPrototypes = new Map(); this._initialized = false; } @@ -73,31 +78,31 @@ Protocol.InspectorBackend = class { const methodName = domain.substr(0, upperCaseLength).toLowerCase() + domain.slice(upperCaseLength) + 'Agent'; /** - * @this {Protocol.TargetBase} + * @this {TargetBase} */ function agentGetter() { return this._agents[domain]; } - Protocol.TargetBase.prototype[methodName] = agentGetter; + TargetBase.prototype[methodName] = agentGetter; /** - * @this {Protocol.TargetBase} + * @this {TargetBase} */ function registerDispatcher(dispatcher) { this.registerDispatcher(domain, dispatcher); } - Protocol.TargetBase.prototype['register' + domain + 'Dispatcher'] = registerDispatcher; + TargetBase.prototype['register' + domain + 'Dispatcher'] = registerDispatcher; } /** * @param {string} domain - * @return {!Protocol.InspectorBackend._AgentPrototype} + * @return {!_AgentPrototype} */ _agentPrototype(domain) { if (!this._agentPrototypes.has(domain)) { - this._agentPrototypes.set(domain, new Protocol.InspectorBackend._AgentPrototype(domain)); + this._agentPrototypes.set(domain, new _AgentPrototype(domain)); this._addAgentGetterMethodToProtocolTargetPrototype(domain); } @@ -106,11 +111,11 @@ Protocol.InspectorBackend = class { /** * @param {string} domain - * @return {!Protocol.InspectorBackend._DispatcherPrototype} + * @return {!_DispatcherPrototype} */ _dispatcherPrototype(domain) { if (!this._dispatcherPrototypes.has(domain)) { - this._dispatcherPrototypes.set(domain, new Protocol.InspectorBackend._DispatcherPrototype()); + this._dispatcherPrototypes.set(domain, new _DispatcherPrototype()); } return this._dispatcherPrototypes.get(domain); } @@ -180,40 +185,60 @@ Protocol.InspectorBackend = class { } return callbackWrapper; } -}; +} -Protocol.DevToolsStubErrorCode = -32015; - -Protocol.inspectorBackend = new Protocol.InspectorBackend(); +/** @type {function():!Connection} */ +let _factory; /** * @interface */ -Protocol.Connection = function() {}; +export class Connection { + constructor() { + /** @type {?function(!Object)} */ + this._onMessage; + } -Protocol.Connection.prototype = { /** * @param {function((!Object|string))} onMessage */ - setOnMessage(onMessage) {}, + setOnMessage(onMessage) { + } /** * @param {function(string)} onDisconnect */ - setOnDisconnect(onDisconnect) {}, + setOnDisconnect(onDisconnect) { + } /** * @param {string} message */ - sendRawMessage(message) {}, + sendRawMessage(message) { + } /** * @return {!Promise} */ - disconnect() {}, -}; + disconnect() { + } -Protocol.test = { + /** + * @param {function():!Connection} factory + */ + static setFactory(factory) { + _factory = factory; + } + + /** + * @return {function():!Connection} + */ + static getFactory() { + return _factory; + } +} + +const test = { /** * This will get called for every protocol message. * Protocol.test.dumpProtocol = console.log @@ -241,42 +266,20 @@ Protocol.test = { /** * Set to get notified about any messages sent over protocol. - * @type {?function({domain: string, method: string, params: !Object, id: number}, ?Protocol.TargetBase)} + * @type {?function({domain: string, method: string, params: !Object, id: number}, ?TargetBase)} */ onMessageSent: null, /** * Set to get notified about any messages received over protocol. - * @type {?function(!Object, ?Protocol.TargetBase)} + * @type {?function(!Object, ?TargetBase)} */ onMessageReceived: null, }; -/** - * @param {function():!Protocol.Connection} factory - */ -Protocol.Connection.setFactory = function(factory) { - Protocol.Connection._factory = factory; -}; - - -/** @type {function():!Protocol.Connection} */ -Protocol.Connection._factory; - -/** - * Takes error and result. - * @typedef {function(?Object, ?Object)} - */ -Protocol._Callback; - -// TODO(dgozman): we are not reporting generic errors in tests, but we should -// instead report them and just have some expected errors in test expectations. -Protocol._GenericError = -32000; -Protocol._ConnectionClosedErrorCode = -32001; - -Protocol.SessionRouter = class { +export class SessionRouter { /** - * @param {!Protocol.Connection} connection + * @param {!Connection} connection */ constructor(connection) { this._connection = connection; @@ -284,14 +287,14 @@ Protocol.SessionRouter = class { this._pendingResponsesCount = 0; this._domainToLogger = new Map(); - /** @type {!Map, proxyConnection: ?Protocol.Connection}>} */ + /** @type {!Map, proxyConnection: ?Connection}>} */ this._sessions = new Map(); /** @type {!Array} */ this._pendingScripts = []; - Protocol.test.deprecatedRunAfterPendingDispatches = this._deprecatedRunAfterPendingDispatches.bind(this); - Protocol.test.sendRawMessage = this._sendRawMessageForTesting.bind(this); + test.deprecatedRunAfterPendingDispatches = this._deprecatedRunAfterPendingDispatches.bind(this); + test.sendRawMessage = this._sendRawMessageForTesting.bind(this); this._connection.setOnMessage(this._onMessage.bind(this)); @@ -304,9 +307,9 @@ Protocol.SessionRouter = class { } /** - * @param {!Protocol.TargetBase} target + * @param {!TargetBase} target * @param {string} sessionId - * @param {?Protocol.Connection} proxyConnection + * @param {?Connection} proxyConnection */ registerSession(target, sessionId, proxyConnection) { this._sessions.set(sessionId, {target, callbacks: new Map(), proxyConnection}); @@ -318,14 +321,14 @@ Protocol.SessionRouter = class { unregisterSession(sessionId) { const session = this._sessions.get(sessionId); for (const callback of session.callbacks.values()) { - Protocol.SessionRouter.dispatchConnectionError(callback); + SessionRouter.dispatchConnectionError(callback); } this._sessions.delete(sessionId); } /** * @param {string} sessionId - * @return {?Protocol.TargetBase} + * @return {?TargetBase} */ _getTargetBySessionId(sessionId) { const session = this._sessions.get(sessionId ? sessionId : ''); @@ -343,7 +346,7 @@ Protocol.SessionRouter = class { } /** - * @return {!Protocol.Connection} + * @return {!Connection} */ connection() { return this._connection; @@ -368,13 +371,13 @@ Protocol.SessionRouter = class { messageObject.sessionId = sessionId; } - if (Protocol.test.dumpProtocol) { - Protocol.test.dumpProtocol('frontend: ' + JSON.stringify(messageObject)); + if (test.dumpProtocol) { + test.dumpProtocol('frontend: ' + JSON.stringify(messageObject)); } - if (Protocol.test.onMessageSent) { + if (test.onMessageSent) { const paramsObject = JSON.parse(JSON.stringify(params || {})); - Protocol.test.onMessageSent( + test.onMessageSent( {domain, method, params: /** @type {!Object} */ (paramsObject), id: messageId}, this._getTargetBySessionId(sessionId)); } @@ -398,13 +401,13 @@ Protocol.SessionRouter = class { * @param {!Object|string} message */ _onMessage(message) { - if (Protocol.test.dumpProtocol) { - Protocol.test.dumpProtocol('backend: ' + ((typeof message === 'string') ? message : JSON.stringify(message))); + if (test.dumpProtocol) { + test.dumpProtocol('backend: ' + ((typeof message === 'string') ? message : JSON.stringify(message))); } - if (Protocol.test.onMessageReceived) { + if (test.onMessageReceived) { const messageObjectCopy = JSON.parse((typeof message === 'string') ? message : JSON.stringify(message)); - Protocol.test.onMessageReceived( + test.onMessageReceived( /** @type {!Object} */ (messageObjectCopy), this._getTargetBySessionId(messageObjectCopy.sessionId)); } @@ -497,22 +500,22 @@ Protocol.SessionRouter = class { static dispatchConnectionError(callback) { const error = { message: 'Connection is closed, can\'t dispatch pending call', - code: Protocol._ConnectionClosedErrorCode, + code: _ConnectionClosedErrorCode, data: null }; setTimeout(() => callback(error, null), 0); } -}; +} /** * @unrestricted */ -Protocol.TargetBase = class { +export class TargetBase { /** * @param {boolean} needsNodeJSPatching - * @param {?Protocol.TargetBase} parentTarget + * @param {?TargetBase} parentTarget * @param {string} sessionId - * @param {?Protocol.Connection} connection + * @param {?Connection} connection */ constructor(needsNodeJSPatching, parentTarget, sessionId, connection) { this._needsNodeJSPatching = needsNodeJSPatching; @@ -524,23 +527,22 @@ Protocol.TargetBase = class { if (sessionId) { this._router = parentTarget._router; } else if (connection) { - this._router = new Protocol.SessionRouter(connection); + this._router = new SessionRouter(connection); } else { - this._router = new Protocol.SessionRouter(Protocol.Connection._factory()); + this._router = new SessionRouter(_factory()); } this._router.registerSession(this, this._sessionId); this._agents = {}; for (const [domain, agentPrototype] of Protocol.inspectorBackend._agentPrototypes) { - this._agents[domain] = Object.create(/** @type {!Protocol.InspectorBackend._AgentPrototype} */ (agentPrototype)); + this._agents[domain] = Object.create(/** @type {!_AgentPrototype} */ (agentPrototype)); this._agents[domain]._target = this; } this._dispatchers = {}; for (const [domain, dispatcherPrototype] of Protocol.inspectorBackend._dispatcherPrototypes) { - this._dispatchers[domain] = - Object.create(/** @type {!Protocol.InspectorBackend._DispatcherPrototype} */ (dispatcherPrototype)); + this._dispatchers[domain] = Object.create(/** @type {!_DispatcherPrototype} */ (dispatcherPrototype)); this._dispatchers[domain]._dispatchers = []; } } @@ -576,17 +578,17 @@ Protocol.TargetBase = class { } /** - * @return {!Protocol.SessionRouter} + * @return {!SessionRouter} */ router() { return this._router; } -}; +} /** * @unrestricted */ -Protocol.InspectorBackend._AgentPrototype = class { +export class _AgentPrototype { /** * @param {string} domain */ @@ -607,13 +609,12 @@ Protocol.InspectorBackend._AgentPrototype = class { /** * @param {...*} vararg - * @this {Protocol.InspectorBackend._AgentPrototype} + * @this {_AgentPrototype} * @return {!Promise.<*>} */ function sendMessagePromise(vararg) { const params = Array.prototype.slice.call(arguments); - return Protocol.InspectorBackend._AgentPrototype.prototype._sendMessageToBackendPromise.call( - this, domainAndMethod, signature, params); + return _AgentPrototype.prototype._sendMessageToBackendPromise.call(this, domainAndMethod, signature, params); } this[methodName] = sendMessagePromise; @@ -621,7 +622,7 @@ Protocol.InspectorBackend._AgentPrototype = class { /** * @param {!Object} request * @return {!Promise} - * @this {Protocol.InspectorBackend._AgentPrototype} + * @this {_AgentPrototype} */ function invoke(request) { return this._invoke(domainAndMethod, request); @@ -704,8 +705,8 @@ Protocol.InspectorBackend._AgentPrototype = class { return new Promise(resolve => { const callback = (error, result) => { - if (error && !Protocol.test.suppressRequestErrors && error.code !== Protocol.DevToolsStubErrorCode && - error.code !== Protocol._GenericError && error.code !== Protocol._ConnectionClosedErrorCode) { + if (error && !test.suppressRequestErrors && error.code !== Protocol.DevToolsStubErrorCode && + error.code !== _GenericError && error.code !== _ConnectionClosedErrorCode) { console.error('Request ' + method + ' failed. ' + JSON.stringify(error)); } @@ -719,7 +720,7 @@ Protocol.InspectorBackend._AgentPrototype = class { }; if (!this._target._router) { - Protocol.SessionRouter.dispatchConnectionError(callback); + SessionRouter.dispatchConnectionError(callback); } else { this._target._router.sendMessage(this._target._sessionId, this._domain, method, params, callback); } @@ -734,8 +735,8 @@ Protocol.InspectorBackend._AgentPrototype = class { _invoke(method, request) { return new Promise(fulfill => { const callback = (error, result) => { - if (error && !Protocol.test.suppressRequestErrors && error.code !== Protocol.DevToolsStubErrorCode && - error.code !== Protocol._GenericError && error.code !== Protocol._ConnectionClosedErrorCode) { + if (error && !test.suppressRequestErrors && error.code !== Protocol.DevToolsStubErrorCode && + error.code !== _GenericError && error.code !== _ConnectionClosedErrorCode) { console.error('Request ' + method + ' failed. ' + JSON.stringify(error)); } @@ -750,18 +751,18 @@ Protocol.InspectorBackend._AgentPrototype = class { }; if (!this._target._router) { - Protocol.SessionRouter.dispatchConnectionError(callback); + SessionRouter.dispatchConnectionError(callback); } else { this._target._router.sendMessage(this._target._sessionId, this._domain, method, request, callback); } }); } -}; +} /** * @unrestricted */ -Protocol.InspectorBackend._DispatcherPrototype = class { +export class _DispatcherPrototype { constructor() { this._eventArgs = {}; } @@ -811,4 +812,47 @@ Protocol.InspectorBackend._DispatcherPrototype = class { } } } -}; +} + +/* Legacy exported object */ +self.Protocol = self.Protocol || {}; + +/* Legacy exported object */ +Protocol = Protocol || {}; + +Protocol.DevToolsStubErrorCode = DevToolsStubErrorCode; +/** @typedef {string} */ +Protocol.Error = ProtocolError; + +/** @constructor */ +Protocol.InspectorBackend = InspectorBackend; + +/** + * @unrestricted + */ +Protocol.InspectorBackend._AgentPrototype = _AgentPrototype; + +/** + * @unrestricted + */ +Protocol.InspectorBackend._DispatcherPrototype = _DispatcherPrototype; + +/** @interface */ +Protocol.Connection = Connection; + +/** @type {!InspectorBackend} */ +Protocol.inspectorBackend = new InspectorBackend(); + +Protocol.test = test; + +/** @constructor */ +Protocol.SessionRouter = SessionRouter; + +/** @constructor */ +Protocol.TargetBase = TargetBase; + +/** + * Takes error and result. + * @typedef {function(?Object, ?Object)} + */ +Protocol._Callback; \ No newline at end of file diff --git a/front_end/protocol/NodeURL.js b/front_end/protocol/NodeURL.js index 6e00a79049..d64cfc4980 100644 --- a/front_end/protocol/NodeURL.js +++ b/front_end/protocol/NodeURL.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -Protocol.NodeURL = class { +export default class NodeURL { /** * @param {!Object} object */ @@ -14,7 +14,7 @@ Protocol.NodeURL = class { * @param {string} path */ function process(object, path) { - if (object.url && Protocol.NodeURL._isPlatformPath(object.url, Host.isWin())) { + if (object.url && NodeURL._isPlatformPath(object.url, Host.isWin())) { object.url = Common.ParsedURL.platformPathToURL(object.url); } for (const entry of Object.entries(object)) { @@ -41,4 +41,13 @@ Protocol.NodeURL = class { return fileSystemPath.length ? fileSystemPath[0] === '/' : false; } } -}; +} + +/* Legacy exported object */ +self.Protocol = self.Protocol || {}; + +/* Legacy exported object */ +Protocol = Protocol || {}; + +/** @constructor */ +Protocol.NodeURL = NodeURL; diff --git a/front_end/protocol/module.json b/front_end/protocol/module.json index 9dda4bdae0..6dc2f8e411 100644 --- a/front_end/protocol/module.json +++ b/front_end/protocol/module.json @@ -3,7 +3,9 @@ "common", "host" ], - "scripts": [ + "scripts": [], + "modules": [ + "protocol.js", "NodeURL.js", "InspectorBackend.js", "../InspectorBackendCommands.js" diff --git a/front_end/protocol/protocol.js b/front_end/protocol/protocol.js new file mode 100644 index 0000000000..4b09755579 --- /dev/null +++ b/front_end/protocol/protocol.js @@ -0,0 +1,15 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import './InspectorBackend.js'; +import './NodeURL.js'; +import '../InspectorBackendCommands.js'; + +import * as InspectorBackend from './InspectorBackend.js'; +import * as NodeURL from './NodeURL.js'; + +export { + InspectorBackend, + NodeURL, +}; diff --git a/front_end/root.js b/front_end/root.js index c807e43fd7..31d9fe6e2d 100644 --- a/front_end/root.js +++ b/front_end/root.js @@ -7,4 +7,5 @@ import './platform/utilities.js'; import './dom_extension/DOMExtension.js'; import './common/common.js'; import './host/host.js'; +import './protocol/protocol.js'; import './ui/ui.js'; diff --git a/front_end/sdk_test_runner/PageMockTestRunner.js b/front_end/sdk_test_runner/PageMockTestRunner.js index febd281caf..88850796d6 100644 --- a/front_end/sdk_test_runner/PageMockTestRunner.js +++ b/front_end/sdk_test_runner/PageMockTestRunner.js @@ -48,13 +48,13 @@ SDKTestRunner.PageMock = class { this._enabledDomains.clear(); SDK.targetManager._targets = []; - const oldFactory = Protocol.Connection._factory; - Protocol.Connection._factory = () => { + const oldFactory = Protocol.Connection.getFactory(); + Protocol.Connection.setFactory(() => { this._connection = new MockPageConnection(this); return this._connection; - }; + }); const target = SDK.targetManager.createTarget(nextId('mock-target-'), targetName, this._type, null); - Protocol.Connection._factory = oldFactory; + Protocol.Connection.setFactory(oldFactory); this._target = target; return target; diff --git a/scripts/compile_frontend.py b/scripts/compile_frontend.py index befedb99a7..3319a0ff16 100755 --- a/scripts/compile_frontend.py +++ b/scripts/compile_frontend.py @@ -290,6 +290,12 @@ def prepare_closure_frontend_compile(temp_devtools_path, descriptors, namespace_ args.extend(['--js', file]) if "InspectorBackend.js" in file: args.extend(['--js', protocol_externs_file]) + + # Write a dummy file for InspectorBackendCommands. We don't type-check this file, but we + # import it from protocol/protocol.js + inspector_backends_commands_file = path.join(temp_frontend_path, 'InspectorBackendCommands.js') + modular_build.write_file(inspector_backends_commands_file, '') + args.extend(['--js', inspector_backends_commands_file]) command += args command = [arg.replace(DEVTOOLS_FRONTEND_PATH, temp_frontend_path) for arg in command] compiler_args_file = tempfile.NamedTemporaryFile(mode='wt', delete=False)