123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400 |
- "use strict";
- Object.defineProperty(exports, "__esModule", {
- value: true
- });
- exports.dispatcherSymbol = exports.RootDispatcher = exports.DispatcherConnection = exports.Dispatcher = void 0;
- exports.existingDispatcher = existingDispatcher;
- exports.setMaxDispatchersForTest = setMaxDispatchersForTest;
- var _events = require("events");
- var _validator = require("../../protocol/validator");
- var _utils = require("../../utils");
- var _errors = require("../errors");
- var _instrumentation = require("../instrumentation");
- var _eventsHelper = require("../..//utils/eventsHelper");
- var _protocolError = require("../protocolError");
- /**
- * Copyright (c) Microsoft Corporation.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const dispatcherSymbol = exports.dispatcherSymbol = Symbol('dispatcher');
- const metadataValidator = (0, _validator.createMetadataValidator)();
- function existingDispatcher(object) {
- return object[dispatcherSymbol];
- }
- let maxDispatchersOverride;
- function setMaxDispatchersForTest(value) {
- maxDispatchersOverride = value;
- }
- function maxDispatchersForBucket(gcBucket) {
- var _ref, _maxDispatchersOverri;
- return (_ref = (_maxDispatchersOverri = maxDispatchersOverride) !== null && _maxDispatchersOverri !== void 0 ? _maxDispatchersOverri : {
- 'JSHandle': 100000,
- 'ElementHandle': 100000
- }[gcBucket]) !== null && _ref !== void 0 ? _ref : 10000;
- }
- class Dispatcher extends _events.EventEmitter {
- constructor(parent, object, type, initializer, gcBucket) {
- super();
- this._connection = void 0;
- // Parent is always "isScope".
- this._parent = void 0;
- // Only "isScope" channel owners have registered dispatchers inside.
- this._dispatchers = new Map();
- this._disposed = false;
- this._eventListeners = [];
- this._guid = void 0;
- this._type = void 0;
- this._gcBucket = void 0;
- this._object = void 0;
- this._openScope = new _utils.LongStandingScope();
- this._connection = parent instanceof DispatcherConnection ? parent : parent._connection;
- this._parent = parent instanceof DispatcherConnection ? undefined : parent;
- const guid = object.guid;
- this._guid = guid;
- this._type = type;
- this._object = object;
- this._gcBucket = gcBucket !== null && gcBucket !== void 0 ? gcBucket : type;
- object[dispatcherSymbol] = this;
- this._connection.registerDispatcher(this);
- if (this._parent) {
- (0, _utils.assert)(!this._parent._dispatchers.has(guid));
- this._parent._dispatchers.set(guid, this);
- }
- if (this._parent) this._connection.sendCreate(this._parent, type, guid, initializer, this._parent._object);
- this._connection.maybeDisposeStaleDispatchers(this._gcBucket);
- }
- parentScope() {
- return this._parent;
- }
- addObjectListener(eventName, handler) {
- this._eventListeners.push(_eventsHelper.eventsHelper.addEventListener(this._object, eventName, handler));
- }
- adopt(child) {
- if (child._parent === this) return;
- const oldParent = child._parent;
- oldParent._dispatchers.delete(child._guid);
- this._dispatchers.set(child._guid, child);
- child._parent = this;
- this._connection.sendAdopt(this, child);
- }
- async _handleCommand(callMetadata, method, validParams) {
- const commandPromise = this[method](validParams, callMetadata);
- try {
- return await this._openScope.race(commandPromise);
- } catch (e) {
- if (callMetadata.potentiallyClosesScope && (0, _errors.isTargetClosedError)(e)) return await commandPromise;
- throw e;
- }
- }
- _dispatchEvent(method, params) {
- if (this._disposed) {
- if ((0, _utils.isUnderTest)()) throw new Error(`${this._guid} is sending "${String(method)}" event after being disposed`);
- // Just ignore this event outside of tests.
- return;
- }
- const sdkObject = this._object instanceof _instrumentation.SdkObject ? this._object : undefined;
- this._connection.sendEvent(this, method, params, sdkObject);
- }
- _dispose(reason) {
- this._disposeRecursively(new _errors.TargetClosedError());
- this._connection.sendDispose(this, reason);
- }
- _onDispose() {}
- _disposeRecursively(error) {
- var _this$_parent;
- (0, _utils.assert)(!this._disposed, `${this._guid} is disposed more than once`);
- this._onDispose();
- this._disposed = true;
- _eventsHelper.eventsHelper.removeEventListeners(this._eventListeners);
- // Clean up from parent and connection.
- (_this$_parent = this._parent) === null || _this$_parent === void 0 ? void 0 : _this$_parent._dispatchers.delete(this._guid);
- const list = this._connection._dispatchersByBucket.get(this._gcBucket);
- list === null || list === void 0 ? void 0 : list.delete(this._guid);
- this._connection._dispatchers.delete(this._guid);
- // Dispose all children.
- for (const dispatcher of [...this._dispatchers.values()]) dispatcher._disposeRecursively(error);
- this._dispatchers.clear();
- delete this._object[dispatcherSymbol];
- this._openScope.close(error);
- }
- _debugScopeState() {
- return {
- _guid: this._guid,
- objects: Array.from(this._dispatchers.values()).map(o => o._debugScopeState())
- };
- }
- async waitForEventInfo() {
- // Instrumentation takes care of this.
- }
- }
- exports.Dispatcher = Dispatcher;
- class RootDispatcher extends Dispatcher {
- constructor(connection, createPlaywright) {
- super(connection, {
- guid: ''
- }, 'Root', {});
- this._initialized = false;
- this.createPlaywright = createPlaywright;
- }
- async initialize(params) {
- (0, _utils.assert)(this.createPlaywright);
- (0, _utils.assert)(!this._initialized);
- this._initialized = true;
- return {
- playwright: await this.createPlaywright(this, params)
- };
- }
- }
- exports.RootDispatcher = RootDispatcher;
- class DispatcherConnection {
- constructor(isLocal) {
- this._dispatchers = new Map();
- this._dispatchersByBucket = new Map();
- this.onmessage = message => {};
- this._waitOperations = new Map();
- this._isLocal = void 0;
- this._isLocal = !!isLocal;
- }
- sendEvent(dispatcher, event, params, sdkObject) {
- const validator = (0, _validator.findValidator)(dispatcher._type, event, 'Event');
- params = validator(params, '', {
- tChannelImpl: this._tChannelImplToWire.bind(this),
- binary: this._isLocal ? 'buffer' : 'toBase64'
- });
- this._sendMessageToClient(dispatcher._guid, dispatcher._type, event, params, sdkObject);
- }
- sendCreate(parent, type, guid, initializer, sdkObject) {
- const validator = (0, _validator.findValidator)(type, '', 'Initializer');
- initializer = validator(initializer, '', {
- tChannelImpl: this._tChannelImplToWire.bind(this),
- binary: this._isLocal ? 'buffer' : 'toBase64'
- });
- this._sendMessageToClient(parent._guid, type, '__create__', {
- type,
- initializer,
- guid
- }, sdkObject);
- }
- sendAdopt(parent, dispatcher) {
- this._sendMessageToClient(parent._guid, dispatcher._type, '__adopt__', {
- guid: dispatcher._guid
- });
- }
- sendDispose(dispatcher, reason) {
- this._sendMessageToClient(dispatcher._guid, dispatcher._type, '__dispose__', {
- reason
- });
- }
- _sendMessageToClient(guid, type, method, params, sdkObject) {
- if (sdkObject) {
- var _sdkObject$attributio, _sdkObject$attributio2, _sdkObject$instrument;
- const event = {
- type: 'event',
- class: type,
- method,
- params: params || {},
- time: (0, _utils.monotonicTime)(),
- pageId: sdkObject === null || sdkObject === void 0 ? void 0 : (_sdkObject$attributio = sdkObject.attribution) === null || _sdkObject$attributio === void 0 ? void 0 : (_sdkObject$attributio2 = _sdkObject$attributio.page) === null || _sdkObject$attributio2 === void 0 ? void 0 : _sdkObject$attributio2.guid
- };
- (_sdkObject$instrument = sdkObject.instrumentation) === null || _sdkObject$instrument === void 0 ? void 0 : _sdkObject$instrument.onEvent(sdkObject, event);
- }
- this.onmessage({
- guid,
- method,
- params
- });
- }
- _tChannelImplFromWire(names, arg, path, context) {
- if (arg && typeof arg === 'object' && typeof arg.guid === 'string') {
- const guid = arg.guid;
- const dispatcher = this._dispatchers.get(guid);
- if (!dispatcher) throw new _validator.ValidationError(`${path}: no object with guid ${guid}`);
- if (names !== '*' && !names.includes(dispatcher._type)) throw new _validator.ValidationError(`${path}: object with guid ${guid} has type ${dispatcher._type}, expected ${names.toString()}`);
- return dispatcher;
- }
- throw new _validator.ValidationError(`${path}: expected guid for ${names.toString()}`);
- }
- _tChannelImplToWire(names, arg, path, context) {
- if (arg instanceof Dispatcher) {
- if (names !== '*' && !names.includes(arg._type)) throw new _validator.ValidationError(`${path}: dispatcher with guid ${arg._guid} has type ${arg._type}, expected ${names.toString()}`);
- return {
- guid: arg._guid
- };
- }
- throw new _validator.ValidationError(`${path}: expected dispatcher ${names.toString()}`);
- }
- registerDispatcher(dispatcher) {
- (0, _utils.assert)(!this._dispatchers.has(dispatcher._guid));
- this._dispatchers.set(dispatcher._guid, dispatcher);
- let list = this._dispatchersByBucket.get(dispatcher._gcBucket);
- if (!list) {
- list = new Set();
- this._dispatchersByBucket.set(dispatcher._gcBucket, list);
- }
- list.add(dispatcher._guid);
- }
- maybeDisposeStaleDispatchers(gcBucket) {
- const maxDispatchers = maxDispatchersForBucket(gcBucket);
- const list = this._dispatchersByBucket.get(gcBucket);
- if (!list || list.size <= maxDispatchers) return;
- const dispatchersArray = [...list];
- const disposeCount = maxDispatchers / 10 | 0;
- this._dispatchersByBucket.set(gcBucket, new Set(dispatchersArray.slice(disposeCount)));
- for (let i = 0; i < disposeCount; ++i) {
- const d = this._dispatchers.get(dispatchersArray[i]);
- if (!d) continue;
- d._dispose('gc');
- }
- }
- async dispatch(message) {
- var _sdkObject$attributio3, _sdkObject$attributio4, _sdkObject$attributio5, _sdkObject$attributio6, _params$info;
- const {
- id,
- guid,
- method,
- params,
- metadata
- } = message;
- const dispatcher = this._dispatchers.get(guid);
- if (!dispatcher) {
- this.onmessage({
- id,
- error: (0, _errors.serializeError)(new _errors.TargetClosedError())
- });
- return;
- }
- let validParams;
- let validMetadata;
- try {
- const validator = (0, _validator.findValidator)(dispatcher._type, method, 'Params');
- validParams = validator(params, '', {
- tChannelImpl: this._tChannelImplFromWire.bind(this),
- binary: this._isLocal ? 'buffer' : 'fromBase64'
- });
- validMetadata = metadataValidator(metadata, '', {
- tChannelImpl: this._tChannelImplFromWire.bind(this),
- binary: this._isLocal ? 'buffer' : 'fromBase64'
- });
- if (typeof dispatcher[method] !== 'function') throw new Error(`Mismatching dispatcher: "${dispatcher._type}" does not implement "${method}"`);
- } catch (e) {
- this.onmessage({
- id,
- error: (0, _errors.serializeError)(e)
- });
- return;
- }
- const sdkObject = dispatcher._object instanceof _instrumentation.SdkObject ? dispatcher._object : undefined;
- const callMetadata = {
- id: `call@${id}`,
- wallTime: validMetadata.wallTime || Date.now(),
- location: validMetadata.location,
- apiName: validMetadata.apiName,
- internal: validMetadata.internal,
- objectId: sdkObject === null || sdkObject === void 0 ? void 0 : sdkObject.guid,
- pageId: sdkObject === null || sdkObject === void 0 ? void 0 : (_sdkObject$attributio3 = sdkObject.attribution) === null || _sdkObject$attributio3 === void 0 ? void 0 : (_sdkObject$attributio4 = _sdkObject$attributio3.page) === null || _sdkObject$attributio4 === void 0 ? void 0 : _sdkObject$attributio4.guid,
- frameId: sdkObject === null || sdkObject === void 0 ? void 0 : (_sdkObject$attributio5 = sdkObject.attribution) === null || _sdkObject$attributio5 === void 0 ? void 0 : (_sdkObject$attributio6 = _sdkObject$attributio5.frame) === null || _sdkObject$attributio6 === void 0 ? void 0 : _sdkObject$attributio6.guid,
- startTime: (0, _utils.monotonicTime)(),
- endTime: 0,
- type: dispatcher._type,
- method,
- params: params || {},
- log: []
- };
- if (sdkObject && params !== null && params !== void 0 && (_params$info = params.info) !== null && _params$info !== void 0 && _params$info.waitId) {
- // Process logs for waitForNavigation/waitForLoadState/etc.
- const info = params.info;
- switch (info.phase) {
- case 'before':
- {
- this._waitOperations.set(info.waitId, callMetadata);
- await sdkObject.instrumentation.onBeforeCall(sdkObject, callMetadata);
- this.onmessage({
- id
- });
- return;
- }
- case 'log':
- {
- const originalMetadata = this._waitOperations.get(info.waitId);
- originalMetadata.log.push(info.message);
- sdkObject.instrumentation.onCallLog(sdkObject, originalMetadata, 'api', info.message);
- this.onmessage({
- id
- });
- return;
- }
- case 'after':
- {
- const originalMetadata = this._waitOperations.get(info.waitId);
- originalMetadata.endTime = (0, _utils.monotonicTime)();
- originalMetadata.error = info.error ? {
- error: {
- name: 'Error',
- message: info.error
- }
- } : undefined;
- this._waitOperations.delete(info.waitId);
- await sdkObject.instrumentation.onAfterCall(sdkObject, originalMetadata);
- this.onmessage({
- id
- });
- return;
- }
- }
- }
- await (sdkObject === null || sdkObject === void 0 ? void 0 : sdkObject.instrumentation.onBeforeCall(sdkObject, callMetadata));
- try {
- const result = await dispatcher._handleCommand(callMetadata, method, validParams);
- const validator = (0, _validator.findValidator)(dispatcher._type, method, 'Result');
- callMetadata.result = validator(result, '', {
- tChannelImpl: this._tChannelImplToWire.bind(this),
- binary: this._isLocal ? 'buffer' : 'toBase64'
- });
- } catch (e) {
- if ((0, _errors.isTargetClosedError)(e) && sdkObject) {
- const reason = closeReason(sdkObject);
- if (reason) (0, _utils.rewriteErrorMessage)(e, reason);
- } else if ((0, _protocolError.isProtocolError)(e)) {
- if (e.type === 'closed') {
- const reason = sdkObject ? closeReason(sdkObject) : undefined;
- e = new _errors.TargetClosedError(reason, e.browserLogMessage());
- } else if (e.type === 'crashed') {
- (0, _utils.rewriteErrorMessage)(e, 'Target crashed ' + e.browserLogMessage());
- }
- }
- callMetadata.error = (0, _errors.serializeError)(e);
- } finally {
- callMetadata.endTime = (0, _utils.monotonicTime)();
- await (sdkObject === null || sdkObject === void 0 ? void 0 : sdkObject.instrumentation.onAfterCall(sdkObject, callMetadata));
- }
- const response = {
- id
- };
- if (callMetadata.result) response.result = callMetadata.result;
- if (callMetadata.error) {
- response.error = callMetadata.error;
- response.log = callMetadata.log;
- }
- this.onmessage(response);
- }
- }
- exports.DispatcherConnection = DispatcherConnection;
- function closeReason(sdkObject) {
- var _sdkObject$attributio7, _sdkObject$attributio8, _sdkObject$attributio9;
- return ((_sdkObject$attributio7 = sdkObject.attribution.page) === null || _sdkObject$attributio7 === void 0 ? void 0 : _sdkObject$attributio7._closeReason) || ((_sdkObject$attributio8 = sdkObject.attribution.context) === null || _sdkObject$attributio8 === void 0 ? void 0 : _sdkObject$attributio8._closeReason) || ((_sdkObject$attributio9 = sdkObject.attribution.browser) === null || _sdkObject$attributio9 === void 0 ? void 0 : _sdkObject$attributio9._closeReason);
- }
|