UNPKG

@dcloudio/uni-debugger

Version:

uni-app debugger

613 lines (554 loc) 17.6 kB
/* * Copyright (C) 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following disclaimer * in the documentation and/or other materials provided with the * distribution. * * Neither the name of Google Inc. nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** * @unrestricted */ SDK.ServiceWorkerManager = class extends SDK.SDKModel { /** * @param {!SDK.Target} target */ constructor(target) { super(target); target.registerServiceWorkerDispatcher(new SDK.ServiceWorkerDispatcher(this)); this._lastAnonymousTargetId = 0; this._agent = target.serviceWorkerAgent(); /** @type {!Map.<string, !SDK.ServiceWorkerRegistration>} */ this._registrations = new Map(); this.enable(); this._forceUpdateSetting = Common.settings.createSetting('serviceWorkerUpdateOnReload', false); if (this._forceUpdateSetting.get()) this._forceUpdateSettingChanged(); this._forceUpdateSetting.addChangeListener(this._forceUpdateSettingChanged, this); new SDK.ServiceWorkerContextNamer(target, this); } enable() { if (this._enabled) return; this._enabled = true; this._agent.enable(); } disable() { if (!this._enabled) return; this._enabled = false; this._registrations.clear(); this._agent.disable(); } /** * @return {!Map.<string, !SDK.ServiceWorkerRegistration>} */ registrations() { return this._registrations; } /** * @param {string} versionId * @return {?SDK.ServiceWorkerVersion} */ findVersion(versionId) { for (const registration of this.registrations().values()) { const version = registration.versions.get(versionId); if (version) return version; } return null; } /** * @param {string} registrationId */ deleteRegistration(registrationId) { const registration = this._registrations.get(registrationId); if (!registration) return; if (registration._isRedundant()) { this._registrations.delete(registrationId); this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationDeleted, registration); return; } registration._deleting = true; for (const version of registration.versions.values()) this.stopWorker(version.id); this._unregister(registration.scopeURL); } /** * @param {string} registrationId */ updateRegistration(registrationId) { const registration = this._registrations.get(registrationId); if (!registration) return; this._agent.updateRegistration(registration.scopeURL); } /** * @param {string} registrationId * @param {string} data */ deliverPushMessage(registrationId, data) { const registration = this._registrations.get(registrationId); if (!registration) return; const origin = Common.ParsedURL.extractOrigin(registration.scopeURL); this._agent.deliverPushMessage(origin, registrationId, data); } /** * @param {string} registrationId * @param {string} tag * @param {boolean} lastChance */ dispatchSyncEvent(registrationId, tag, lastChance) { const registration = this._registrations.get(registrationId); if (!registration) return; const origin = Common.ParsedURL.extractOrigin(registration.scopeURL); this._agent.dispatchSyncEvent(origin, registrationId, tag, lastChance); } /** * @param {string} scope */ _unregister(scope) { this._agent.unregister(scope); } /** * @param {string} scope */ startWorker(scope) { this._agent.startWorker(scope); } /** * @param {string} scope */ skipWaiting(scope) { this._agent.skipWaiting(scope); } /** * @param {string} versionId */ stopWorker(versionId) { this._agent.stopWorker(versionId); } /** * @param {string} versionId */ inspectWorker(versionId) { this._agent.inspectWorker(versionId); } /** * @param {!Array.<!Protocol.ServiceWorker.ServiceWorkerRegistration>} registrations */ _workerRegistrationUpdated(registrations) { for (const payload of registrations) { let registration = this._registrations.get(payload.registrationId); if (!registration) { registration = new SDK.ServiceWorkerRegistration(payload); this._registrations.set(payload.registrationId, registration); this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationUpdated, registration); continue; } registration._update(payload); if (registration._shouldBeRemoved()) { this._registrations.delete(registration.id); this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationDeleted, registration); } else { this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationUpdated, registration); } } } /** * @param {!Array.<!Protocol.ServiceWorker.ServiceWorkerVersion>} versions */ _workerVersionUpdated(versions) { /** @type {!Set.<!SDK.ServiceWorkerRegistration>} */ const registrations = new Set(); for (const payload of versions) { const registration = this._registrations.get(payload.registrationId); if (!registration) continue; registration._updateVersion(payload); registrations.add(registration); } for (const registration of registrations) { if (registration._shouldBeRemoved()) { this._registrations.delete(registration.id); this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationDeleted, registration); } else { this.dispatchEventToListeners(SDK.ServiceWorkerManager.Events.RegistrationUpdated, registration); } } } /** * @param {!Protocol.ServiceWorker.ServiceWorkerErrorMessage} payload */ _workerErrorReported(payload) { const registration = this._registrations.get(payload.registrationId); if (!registration) return; registration.errors.push(payload); this.dispatchEventToListeners( SDK.ServiceWorkerManager.Events.RegistrationErrorAdded, {registration: registration, error: payload}); } /** * @return {!Common.Setting} */ forceUpdateOnReloadSetting() { return this._forceUpdateSetting; } _forceUpdateSettingChanged() { this._agent.setForceUpdateOnPageLoad(this._forceUpdateSetting.get()); } }; SDK.SDKModel.register(SDK.ServiceWorkerManager, SDK.Target.Capability.Target | SDK.Target.Capability.Browser, true); /** @enum {symbol} */ SDK.ServiceWorkerManager.Events = { RegistrationUpdated: Symbol('RegistrationUpdated'), RegistrationErrorAdded: Symbol('RegistrationErrorAdded'), RegistrationDeleted: Symbol('RegistrationDeleted') }; /** * @implements {Protocol.ServiceWorkerDispatcher} * @unrestricted */ SDK.ServiceWorkerDispatcher = class { /** * @param {!SDK.ServiceWorkerManager} manager */ constructor(manager) { this._manager = manager; } /** * @override * @param {!Array.<!Protocol.ServiceWorker.ServiceWorkerRegistration>} registrations */ workerRegistrationUpdated(registrations) { this._manager._workerRegistrationUpdated(registrations); } /** * @override * @param {!Array.<!Protocol.ServiceWorker.ServiceWorkerVersion>} versions */ workerVersionUpdated(versions) { this._manager._workerVersionUpdated(versions); } /** * @override * @param {!Protocol.ServiceWorker.ServiceWorkerErrorMessage} errorMessage */ workerErrorReported(errorMessage) { this._manager._workerErrorReported(errorMessage); } }; /** * @unrestricted */ SDK.ServiceWorkerVersion = class { /** * @param {!SDK.ServiceWorkerRegistration} registration * @param {!Protocol.ServiceWorker.ServiceWorkerVersion} payload */ constructor(registration, payload) { this.registration = registration; this._update(payload); } /** * @param {!Protocol.ServiceWorker.ServiceWorkerVersion} payload */ _update(payload) { this.id = payload.versionId; this.scriptURL = payload.scriptURL; const parsedURL = new Common.ParsedURL(payload.scriptURL); this.securityOrigin = parsedURL.securityOrigin(); this.runningStatus = payload.runningStatus; this.status = payload.status; this.scriptLastModified = payload.scriptLastModified; this.scriptResponseTime = payload.scriptResponseTime; this.controlledClients = []; for (let i = 0; i < payload.controlledClients.length; ++i) this.controlledClients.push(payload.controlledClients[i]); this.targetId = payload.targetId || null; } /** * @return {boolean} */ isStartable() { return !this.registration.isDeleted && this.isActivated() && this.isStopped(); } /** * @return {boolean} */ isStoppedAndRedundant() { return this.runningStatus === Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Stopped && this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Redundant; } /** * @return {boolean} */ isStopped() { return this.runningStatus === Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Stopped; } /** * @return {boolean} */ isStarting() { return this.runningStatus === Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Starting; } /** * @return {boolean} */ isRunning() { return this.runningStatus === Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Running; } /** * @return {boolean} */ isStopping() { return this.runningStatus === Protocol.ServiceWorker.ServiceWorkerVersionRunningStatus.Stopping; } /** * @return {boolean} */ isNew() { return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.New; } /** * @return {boolean} */ isInstalling() { return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Installing; } /** * @return {boolean} */ isInstalled() { return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Installed; } /** * @return {boolean} */ isActivating() { return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Activating; } /** * @return {boolean} */ isActivated() { return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Activated; } /** * @return {boolean} */ isRedundant() { return this.status === Protocol.ServiceWorker.ServiceWorkerVersionStatus.Redundant; } /** * @return {string} */ mode() { if (this.isNew() || this.isInstalling()) return SDK.ServiceWorkerVersion.Modes.Installing; else if (this.isInstalled()) return SDK.ServiceWorkerVersion.Modes.Waiting; else if (this.isActivating() || this.isActivated()) return SDK.ServiceWorkerVersion.Modes.Active; return SDK.ServiceWorkerVersion.Modes.Redundant; } }; /** * @enum {string} */ SDK.ServiceWorkerVersion.Modes = { Installing: 'installing', Waiting: 'waiting', Active: 'active', Redundant: 'redundant' }; /** * @unrestricted */ SDK.ServiceWorkerRegistration = class { /** * @param {!Protocol.ServiceWorker.ServiceWorkerRegistration} payload */ constructor(payload) { this._update(payload); /** @type {!Map.<string, !SDK.ServiceWorkerVersion>} */ this.versions = new Map(); this._deleting = false; /** @type {!Array<!Protocol.ServiceWorker.ServiceWorkerErrorMessage>} */ this.errors = []; } /** * @param {!Protocol.ServiceWorker.ServiceWorkerRegistration} payload */ _update(payload) { this._fingerprint = Symbol('fingerprint'); this.id = payload.registrationId; this.scopeURL = payload.scopeURL; const parsedURL = new Common.ParsedURL(payload.scopeURL); this.securityOrigin = parsedURL.securityOrigin(); this.isDeleted = payload.isDeleted; this.forceUpdateOnPageLoad = payload.forceUpdateOnPageLoad; } /** * @return {symbol} */ fingerprint() { return this._fingerprint; } /** * @return {!Map<string, !SDK.ServiceWorkerVersion>} */ versionsByMode() { /** @type {!Map<string, !SDK.ServiceWorkerVersion>} */ const result = new Map(); for (const version of this.versions.values()) result.set(version.mode(), version); return result; } /** * @param {!Protocol.ServiceWorker.ServiceWorkerVersion} payload * @return {!SDK.ServiceWorkerVersion} */ _updateVersion(payload) { this._fingerprint = Symbol('fingerprint'); let version = this.versions.get(payload.versionId); if (!version) { version = new SDK.ServiceWorkerVersion(this, payload); this.versions.set(payload.versionId, version); return version; } version._update(payload); return version; } /** * @return {boolean} */ _isRedundant() { for (const version of this.versions.values()) { if (!version.isStoppedAndRedundant()) return false; } return true; } /** * @return {boolean} */ _shouldBeRemoved() { return this._isRedundant() && (!this.errors.length || this._deleting); } /** * @return {boolean} */ canBeRemoved() { return this.isDeleted || this._deleting; } clearErrors() { this._fingerprint = Symbol('fingerprint'); this.errors = []; } }; /** * @unrestricted */ SDK.ServiceWorkerContextNamer = class { /** * @param {!SDK.Target} target * @param {!SDK.ServiceWorkerManager} serviceWorkerManager */ constructor(target, serviceWorkerManager) { this._target = target; this._serviceWorkerManager = serviceWorkerManager; /** @type {!Map<string, !SDK.ServiceWorkerVersion>} */ this._versionByTargetId = new Map(); serviceWorkerManager.addEventListener( SDK.ServiceWorkerManager.Events.RegistrationUpdated, this._registrationsUpdated, this); serviceWorkerManager.addEventListener( SDK.ServiceWorkerManager.Events.RegistrationDeleted, this._registrationsUpdated, this); SDK.targetManager.addModelListener( SDK.RuntimeModel, SDK.RuntimeModel.Events.ExecutionContextCreated, this._executionContextCreated, this); } /** * @param {!Common.Event} event */ _registrationsUpdated(event) { this._versionByTargetId.clear(); const registrations = this._serviceWorkerManager.registrations().valuesArray(); for (const registration of registrations) { const versions = registration.versions.valuesArray(); for (const version of versions) { if (version.targetId) this._versionByTargetId.set(version.targetId, version); } } this._updateAllContextLabels(); } /** * @param {!Common.Event} event */ _executionContextCreated(event) { const executionContext = /** @type {!SDK.ExecutionContext} */ (event.data); const serviceWorkerTargetId = this._serviceWorkerTargetIdForWorker(executionContext.target()); if (!serviceWorkerTargetId) return; this._updateContextLabel(executionContext, this._versionByTargetId.get(serviceWorkerTargetId) || null); } /** * @param {!SDK.Target} target * @return {?string} */ _serviceWorkerTargetIdForWorker(target) { const parent = target.parentTarget(); if (!parent || parent.parentTarget() !== this._target) return null; return parent.id(); } _updateAllContextLabels() { for (const target of SDK.targetManager.targets()) { const serviceWorkerTargetId = this._serviceWorkerTargetIdForWorker(target); if (!serviceWorkerTargetId) continue; const version = this._versionByTargetId.get(serviceWorkerTargetId) || null; const runtimeModel = target.model(SDK.RuntimeModel); const executionContexts = runtimeModel ? runtimeModel.executionContexts() : []; for (const context of executionContexts) this._updateContextLabel(context, version); } } /** * @param {!SDK.ExecutionContext} context * @param {?SDK.ServiceWorkerVersion} version */ _updateContextLabel(context, version) { if (!version) { context.setLabel(''); return; } const parsedUrl = context.origin.asParsedURL(); const label = parsedUrl ? parsedUrl.lastPathComponentWithFragment() : context.name; context.setLabel(label + ' #' + version.id + ' (' + version.status + ')'); } };