connection.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.Connection = void 0;
  6. var _browser = require("./browser");
  7. var _browserContext = require("./browserContext");
  8. var _browserType = require("./browserType");
  9. var _channelOwner = require("./channelOwner");
  10. var _elementHandle = require("./elementHandle");
  11. var _frame = require("./frame");
  12. var _jsHandle = require("./jsHandle");
  13. var _network = require("./network");
  14. var _page = require("./page");
  15. var _worker = require("./worker");
  16. var _dialog = require("./dialog");
  17. var _errors = require("./errors");
  18. var _cdpSession = require("./cdpSession");
  19. var _playwright = require("./playwright");
  20. var _electron = require("./electron");
  21. var _stream = require("./stream");
  22. var _writableStream = require("./writableStream");
  23. var _debugLogger = require("../common/debugLogger");
  24. var _selectors = require("./selectors");
  25. var _android = require("./android");
  26. var _artifact = require("./artifact");
  27. var _events = require("events");
  28. var _jsonPipe = require("./jsonPipe");
  29. var _fetch = require("./fetch");
  30. var _localUtils = require("./localUtils");
  31. var _tracing = require("./tracing");
  32. var _validator = require("../protocol/validator");
  33. var _clientInstrumentation = require("./clientInstrumentation");
  34. var _utils = require("../utils");
  35. /**
  36. * Copyright (c) Microsoft Corporation.
  37. *
  38. * Licensed under the Apache License, Version 2.0 (the 'License");
  39. * you may not use this file except in compliance with the License.
  40. * You may obtain a copy of the License at
  41. *
  42. * http://www.apache.org/licenses/LICENSE-2.0
  43. *
  44. * Unless required by applicable law or agreed to in writing, software
  45. * distributed under the License is distributed on an "AS IS" BASIS,
  46. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  47. * See the License for the specific language governing permissions and
  48. * limitations under the License.
  49. */
  50. class Root extends _channelOwner.ChannelOwner {
  51. constructor(connection) {
  52. super(connection, 'Root', '', {});
  53. }
  54. async initialize() {
  55. return _playwright.Playwright.from((await this._channel.initialize({
  56. sdkLanguage: 'javascript'
  57. })).playwright);
  58. }
  59. }
  60. class DummyChannelOwner extends _channelOwner.ChannelOwner {}
  61. class Connection extends _events.EventEmitter {
  62. constructor(localUtils, instrumentation) {
  63. super();
  64. this._objects = new Map();
  65. this.onmessage = message => {};
  66. this._lastId = 0;
  67. this._callbacks = new Map();
  68. this._rootObject = void 0;
  69. this._closedError = void 0;
  70. this._isRemote = false;
  71. this._localUtils = void 0;
  72. this._rawBuffers = false;
  73. // Some connections allow resolving in-process dispatchers.
  74. this.toImpl = void 0;
  75. this._tracingCount = 0;
  76. this._instrumentation = void 0;
  77. this._rootObject = new Root(this);
  78. this._localUtils = localUtils;
  79. this._instrumentation = instrumentation || (0, _clientInstrumentation.createInstrumentation)();
  80. }
  81. markAsRemote() {
  82. this._isRemote = true;
  83. }
  84. isRemote() {
  85. return this._isRemote;
  86. }
  87. useRawBuffers() {
  88. this._rawBuffers = true;
  89. }
  90. rawBuffers() {
  91. return this._rawBuffers;
  92. }
  93. localUtils() {
  94. return this._localUtils;
  95. }
  96. async initializePlaywright() {
  97. return await this._rootObject.initialize();
  98. }
  99. getObjectWithKnownName(guid) {
  100. return this._objects.get(guid);
  101. }
  102. setIsTracing(isTracing) {
  103. if (isTracing) this._tracingCount++;else this._tracingCount--;
  104. }
  105. async sendMessageToServer(object, method, params, apiName, frames, wallTime) {
  106. var _this$_localUtils;
  107. if (this._closedError) throw this._closedError;
  108. if (object._wasCollected) throw new Error('The object has been collected to prevent unbounded heap growth.');
  109. const guid = object._guid;
  110. const type = object._type;
  111. const id = ++this._lastId;
  112. const message = {
  113. id,
  114. guid,
  115. method,
  116. params
  117. };
  118. if (_debugLogger.debugLogger.isEnabled('channel')) {
  119. // Do not include metadata in debug logs to avoid noise.
  120. _debugLogger.debugLogger.log('channel', 'SEND> ' + JSON.stringify(message));
  121. }
  122. const location = frames[0] ? {
  123. file: frames[0].file,
  124. line: frames[0].line,
  125. column: frames[0].column
  126. } : undefined;
  127. const metadata = {
  128. wallTime,
  129. apiName,
  130. location,
  131. internal: !apiName
  132. };
  133. if (this._tracingCount && frames && type !== 'LocalUtils') (_this$_localUtils = this._localUtils) === null || _this$_localUtils === void 0 ? void 0 : _this$_localUtils._channel.addStackToTracingNoReply({
  134. callData: {
  135. stack: frames,
  136. id
  137. }
  138. }).catch(() => {});
  139. this.onmessage({
  140. ...message,
  141. metadata
  142. });
  143. return await new Promise((resolve, reject) => this._callbacks.set(id, {
  144. resolve,
  145. reject,
  146. apiName,
  147. type,
  148. method
  149. }));
  150. }
  151. dispatch(message) {
  152. if (this._closedError) return;
  153. const {
  154. id,
  155. guid,
  156. method,
  157. params,
  158. result,
  159. error,
  160. log
  161. } = message;
  162. if (id) {
  163. if (_debugLogger.debugLogger.isEnabled('channel')) _debugLogger.debugLogger.log('channel', '<RECV ' + JSON.stringify(message));
  164. const callback = this._callbacks.get(id);
  165. if (!callback) throw new Error(`Cannot find command to respond: ${id}`);
  166. this._callbacks.delete(id);
  167. if (error && !result) {
  168. const parsedError = (0, _errors.parseError)(error);
  169. (0, _utils.rewriteErrorMessage)(parsedError, parsedError.message + (0, _utils.formatCallLog)(log));
  170. callback.reject(parsedError);
  171. } else {
  172. const validator = (0, _validator.findValidator)(callback.type, callback.method, 'Result');
  173. callback.resolve(validator(result, '', {
  174. tChannelImpl: this._tChannelImplFromWire.bind(this),
  175. binary: this._rawBuffers ? 'buffer' : 'fromBase64'
  176. }));
  177. }
  178. return;
  179. }
  180. if (_debugLogger.debugLogger.isEnabled('channel')) _debugLogger.debugLogger.log('channel', '<EVENT ' + JSON.stringify(message));
  181. if (method === '__create__') {
  182. this._createRemoteObject(guid, params.type, params.guid, params.initializer);
  183. return;
  184. }
  185. const object = this._objects.get(guid);
  186. if (!object) throw new Error(`Cannot find object to "${method}": ${guid}`);
  187. if (method === '__adopt__') {
  188. const child = this._objects.get(params.guid);
  189. if (!child) throw new Error(`Unknown new child: ${params.guid}`);
  190. object._adopt(child);
  191. return;
  192. }
  193. if (method === '__dispose__') {
  194. object._dispose(params.reason);
  195. return;
  196. }
  197. const validator = (0, _validator.findValidator)(object._type, method, 'Event');
  198. object._channel.emit(method, validator(params, '', {
  199. tChannelImpl: this._tChannelImplFromWire.bind(this),
  200. binary: this._rawBuffers ? 'buffer' : 'fromBase64'
  201. }));
  202. }
  203. close(cause) {
  204. this._closedError = new _errors.TargetClosedError(cause === null || cause === void 0 ? void 0 : cause.toString());
  205. for (const callback of this._callbacks.values()) callback.reject(this._closedError);
  206. this._callbacks.clear();
  207. this.emit('close');
  208. }
  209. _tChannelImplFromWire(names, arg, path, context) {
  210. if (arg && typeof arg === 'object' && typeof arg.guid === 'string') {
  211. const object = this._objects.get(arg.guid);
  212. if (!object) throw new Error(`Object with guid ${arg.guid} was not bound in the connection`);
  213. if (names !== '*' && !names.includes(object._type)) throw new _validator.ValidationError(`${path}: expected channel ${names.toString()}`);
  214. return object._channel;
  215. }
  216. throw new _validator.ValidationError(`${path}: expected channel ${names.toString()}`);
  217. }
  218. _createRemoteObject(parentGuid, type, guid, initializer) {
  219. const parent = this._objects.get(parentGuid);
  220. if (!parent) throw new Error(`Cannot find parent object ${parentGuid} to create ${guid}`);
  221. let result;
  222. const validator = (0, _validator.findValidator)(type, '', 'Initializer');
  223. initializer = validator(initializer, '', {
  224. tChannelImpl: this._tChannelImplFromWire.bind(this),
  225. binary: this._rawBuffers ? 'buffer' : 'fromBase64'
  226. });
  227. switch (type) {
  228. case 'Android':
  229. result = new _android.Android(parent, type, guid, initializer);
  230. break;
  231. case 'AndroidSocket':
  232. result = new _android.AndroidSocket(parent, type, guid, initializer);
  233. break;
  234. case 'AndroidDevice':
  235. result = new _android.AndroidDevice(parent, type, guid, initializer);
  236. break;
  237. case 'APIRequestContext':
  238. result = new _fetch.APIRequestContext(parent, type, guid, initializer);
  239. break;
  240. case 'Artifact':
  241. result = new _artifact.Artifact(parent, type, guid, initializer);
  242. break;
  243. case 'BindingCall':
  244. result = new _page.BindingCall(parent, type, guid, initializer);
  245. break;
  246. case 'Browser':
  247. result = new _browser.Browser(parent, type, guid, initializer);
  248. break;
  249. case 'BrowserContext':
  250. result = new _browserContext.BrowserContext(parent, type, guid, initializer);
  251. break;
  252. case 'BrowserType':
  253. result = new _browserType.BrowserType(parent, type, guid, initializer);
  254. break;
  255. case 'CDPSession':
  256. result = new _cdpSession.CDPSession(parent, type, guid, initializer);
  257. break;
  258. case 'Dialog':
  259. result = new _dialog.Dialog(parent, type, guid, initializer);
  260. break;
  261. case 'Electron':
  262. result = new _electron.Electron(parent, type, guid, initializer);
  263. break;
  264. case 'ElectronApplication':
  265. result = new _electron.ElectronApplication(parent, type, guid, initializer);
  266. break;
  267. case 'ElementHandle':
  268. result = new _elementHandle.ElementHandle(parent, type, guid, initializer);
  269. break;
  270. case 'Frame':
  271. result = new _frame.Frame(parent, type, guid, initializer);
  272. break;
  273. case 'JSHandle':
  274. result = new _jsHandle.JSHandle(parent, type, guid, initializer);
  275. break;
  276. case 'JsonPipe':
  277. result = new _jsonPipe.JsonPipe(parent, type, guid, initializer);
  278. break;
  279. case 'LocalUtils':
  280. result = new _localUtils.LocalUtils(parent, type, guid, initializer);
  281. if (!this._localUtils) this._localUtils = result;
  282. break;
  283. case 'Page':
  284. result = new _page.Page(parent, type, guid, initializer);
  285. break;
  286. case 'Playwright':
  287. result = new _playwright.Playwright(parent, type, guid, initializer);
  288. break;
  289. case 'Request':
  290. result = new _network.Request(parent, type, guid, initializer);
  291. break;
  292. case 'Response':
  293. result = new _network.Response(parent, type, guid, initializer);
  294. break;
  295. case 'Route':
  296. result = new _network.Route(parent, type, guid, initializer);
  297. break;
  298. case 'Stream':
  299. result = new _stream.Stream(parent, type, guid, initializer);
  300. break;
  301. case 'Selectors':
  302. result = new _selectors.SelectorsOwner(parent, type, guid, initializer);
  303. break;
  304. case 'SocksSupport':
  305. result = new DummyChannelOwner(parent, type, guid, initializer);
  306. break;
  307. case 'Tracing':
  308. result = new _tracing.Tracing(parent, type, guid, initializer);
  309. break;
  310. case 'WebSocket':
  311. result = new _network.WebSocket(parent, type, guid, initializer);
  312. break;
  313. case 'Worker':
  314. result = new _worker.Worker(parent, type, guid, initializer);
  315. break;
  316. case 'WritableStream':
  317. result = new _writableStream.WritableStream(parent, type, guid, initializer);
  318. break;
  319. default:
  320. throw new Error('Missing type ' + type);
  321. }
  322. return result;
  323. }
  324. }
  325. exports.Connection = Connection;