@onting/selenium-webdriver-message-port 0.0.0-0 → 0.1.0-main.202606020948.0ed3d01

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,10 +4,113 @@
4
4
 
5
5
  ## Background
6
6
 
7
+ [`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) is the JavaScript standard communication channel. We are bringing `MessagePort` to [`selenium-webdriver`](https://npmjs.com/package/selenium-webdriver) by leveraging `executeScript` calls.
8
+
9
+ This enables libraries that use `MessagePort` to function across the host and the browser, such as [`message-port-rpc`](https://npmjs.com/package/message-port-rpc).
10
+
7
11
  ## How to use
8
12
 
13
+ In the webpage:
14
+
15
+ ```html
16
+ <script>
17
+ import { messagePort } from 'https://cdn.jsdelivr.net/npm/@onting/selenium-webdriver-message-port/dist/browser.js';
18
+
19
+ messagePort.addEventListener('message', ({ data }) => {
20
+ // Will print "Hello from host!"
21
+ console.log(data);
22
+ });
23
+
24
+ // start() will uncork events sent from the host side.
25
+ messagePort.start();
26
+
27
+ messagePort.postMessage('Hello from browser!');
28
+ </script>
29
+ ```
30
+
31
+ In the host:
32
+
33
+ ```js
34
+ import { setup } from '@onting/selenium-webdriver-message-port/host';
35
+
36
+ const { messagePort, poll } = setup(webDriver);
37
+
38
+ messagePort.addEventListener('message', ({ data }) => {
39
+ // Will print "Hello from browser!"
40
+ console.log(data);
41
+ });
42
+
43
+ // start() will uncork events sent from the browser side.
44
+ messagePort.start();
45
+
46
+ messagePort.postMessage('Hello from host!');
47
+
48
+ // poll() will receive pending messages posted from the browser.
49
+ await poll();
50
+ ```
51
+
9
52
  ## Behaviors
10
53
 
54
+ ### What can I do with `MessagePort`?
55
+
56
+ `MessagePort` is an asynchronous bidirectional communication channel between two discrete JavaScript VMs.
57
+
58
+ [`message-port-rpc`](https://npmjs.com/package/message-port-rpc) leverage `MessagePort` and turn any functions into remoting functions (RPC). Client calling the RPC function will have the arguments passed to the server via `MessagePort`. And the server returning the RPC function will have the return value pass to the client.
59
+
60
+ <details>
61
+ <summary>Click to see the sample code</summary>
62
+
63
+ ```html
64
+ <script>
65
+ import { messagePort } from 'https://cdn.jsdelivr.net/npm/@onting/selenium-webdriver-message-port/dist/browser.js';
66
+ import { messagePortRPC } from 'https://esm.sh/message-port-rpc';
67
+
68
+ messagePortRPC(messagePort, message => console.log(message));
69
+ </script>
70
+ ```
71
+
72
+ ```ts
73
+ import { setup } from '@onting/selenium-webdriver-message-port/host';
74
+ import { messagePortRPC } from 'https://esm.sh/message-port-rpc';
75
+
76
+ const { messagePort, poll } = setup(webDriver);
77
+
78
+ const log = messagePortRPC(messagePort);
79
+
80
+ await log('Hello from host!');
81
+ ```
82
+ </details>
83
+
84
+ ### What transferables are supported?
85
+
86
+ We currently support transferring `MessagePort` only.
87
+
88
+ ### Why are my tests lingering?
89
+
90
+ At the end of the test, call `messagePort.close()` to shut down. If you have transferred additional `MessagePort`, also call `close()` on them.
91
+
92
+ ### Why am I not receiving messages on host side?
93
+
94
+ Call `poll()` when your host code is idle. The `poll()` call will retrieve all pending messages from the browser via `executeScript()` and send it to the port on the host side.
95
+
96
+ Similar to `executeScript()`, special considerations must be made while calling `poll()`. WebDriver is single-threaded, all commands are processed serially. You should not call `poll()` while other WebDriver commands are being processed.
97
+
98
+ ### Why am I not receiving the first few messages?
99
+
100
+ Call `MessagePort.start()` only after all `MessagePort.addEventListener()` are registered. The `start()` will uncork the `MessagePort` and messages will flow through.
101
+
102
+ If event listeners are not registered before `start()`, messages sent before the registration will be lost.
103
+
104
+ ### Why `undefined` values are not being sent?
105
+
106
+ `executeScript()` modifies the value being passed, similar to how `JSON.parse` and `JSON.stringify` works.
107
+
108
+ Consider using `JSON.stringify` or [structured clone algorithm](https://www.npmjs.com/search?q=structured%20clone%20algorithm) to preserve values that are not safe to pass across the WebDriver serialization context.
109
+
110
+ ### Do you support [WebDriver BiDi Protocol](https://w3c.github.io/webdriver-bidi/)?
111
+
112
+ We do not support the new [WebDriver BiDi Protocol](https://w3c.github.io/webdriver-bidi/) yet but this is on our road map. Using BiDi could simplify some userland code.
113
+
11
114
  ## Contributions
12
115
 
13
116
  Like us? [Star](https://github.com/teamonting/selenium-webdriver-message-port/stargazers) us.
@@ -0,0 +1,3 @@
1
+ declare const messagePort: MessagePort;
2
+
3
+ export { messagePort };
@@ -0,0 +1,61 @@
1
+ import {
2
+ ROOT_MESSAGE_PORT,
3
+ marshal,
4
+ unmarshal,
5
+ v7_default
6
+ } from "./chunk-2MTLTUOY.js";
7
+
8
+ // src/browser/index.ts
9
+ var portMap = /* @__PURE__ */ new Map();
10
+ var queue = [];
11
+ function flushAll() {
12
+ return Object.freeze(queue.splice(0));
13
+ }
14
+ function createMessagePort(portId) {
15
+ if (portMap.has(portId)) {
16
+ throw new Error(`MessagePort with id "${portId}" is already registered, cannot register again`);
17
+ }
18
+ const { port1, port2 } = new MessageChannel();
19
+ registerMessagePort(port1, portId);
20
+ return port2;
21
+ }
22
+ function registerMessagePort(port, portId) {
23
+ if (portMap.has(portId)) {
24
+ throw new Error(`MessagePort with id "${portId}" is already registered, cannot register again`);
25
+ }
26
+ portMap.set(portId, port);
27
+ port.addEventListener("message", ({ data, ports }) => {
28
+ const transferPortIds = ports.map((port2) => {
29
+ const id = v7_default();
30
+ registerMessagePort(port2, id);
31
+ return id;
32
+ });
33
+ queue.push(
34
+ Object.freeze({
35
+ data: marshal(data, ports),
36
+ portId,
37
+ transferPortIds
38
+ })
39
+ );
40
+ });
41
+ port.start();
42
+ }
43
+ function sendToBrowser(message) {
44
+ const { data, portId, transferPortIds } = message;
45
+ const port = portMap.get(portId);
46
+ if (!port) {
47
+ console.warn(`Host should not send to unbound port "${portId}"`);
48
+ return;
49
+ }
50
+ const transfer = transferPortIds.map((transferPortId) => createMessagePort(transferPortId));
51
+ port.postMessage(unmarshal(data, transfer), transfer);
52
+ }
53
+ globalThis.__seleniumWebDriverMessagePortFacility = Object.freeze({
54
+ flushAll,
55
+ sendToBrowser
56
+ });
57
+ var messagePort = createMessagePort(ROOT_MESSAGE_PORT);
58
+ export {
59
+ messagePort
60
+ };
61
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/browser/index.ts"],"sourcesContent":["/// <reference types=\"../env.d.ts\" />\n\nimport { v7 } from 'uuid';\nimport { ROOT_MESSAGE_PORT } from '../constant.ts';\nimport { marshal, unmarshal } from '../marshal.ts';\nimport type { MessagePortFacility, SerializedMessage } from '../types.js';\n\nconst portMap = new Map<string, MessagePort>();\nconst queue: SerializedMessage[] = [];\n\nfunction flushAll(): readonly SerializedMessage[] {\n return Object.freeze(queue.splice(0));\n}\n\nfunction createMessagePort(portId: string): MessagePort {\n if (portMap.has(portId)) {\n throw new Error(`MessagePort with id \"${portId}\" is already registered, cannot register again`);\n }\n\n const { port1, port2 } = new MessageChannel();\n\n registerMessagePort(port1, portId);\n\n return port2;\n}\n\nfunction registerMessagePort(port: MessagePort, portId: string): void {\n if (portMap.has(portId)) {\n throw new Error(`MessagePort with id \"${portId}\" is already registered, cannot register again`);\n }\n\n portMap.set(portId, port);\n\n port.addEventListener('message', ({ data, ports }) => {\n // Because MessagePort will detach on send, thus, postMessage() cannot transfer the same MessagePort twice.\n // We don't need to check if the port already have an ID or not.\n // MessagePort cannot be sent twice, thus it must be new.\n // Otherwise postMessage() would have already fail and should never reach this code block.\n\n const transferPortIds = ports.map(port => {\n const id = v7();\n\n registerMessagePort(port, id);\n\n return id;\n });\n\n queue.push(\n Object.freeze({\n data: marshal(data, ports),\n portId,\n transferPortIds\n })\n );\n });\n\n port.start();\n}\n\nfunction sendToBrowser(message: SerializedMessage): void {\n const { data, portId, transferPortIds } = message;\n\n const port = portMap.get(portId);\n\n if (!port) {\n console.warn(`Host should not send to unbound port \"${portId}\"`);\n\n return;\n }\n\n // postMessage() will neuter MessagePort after sent, thus, every port received must be new transfer.\n const transfer = transferPortIds.map(transferPortId => createMessagePort(transferPortId));\n\n port.postMessage(unmarshal(data, transfer), transfer);\n}\n\nglobalThis.__seleniumWebDriverMessagePortFacility = Object.freeze({\n flushAll,\n sendToBrowser\n} satisfies MessagePortFacility);\n\nconst messagePort = createMessagePort(ROOT_MESSAGE_PORT);\n\nexport { messagePort };\n"],"mappings":";;;;;;;;AAOA,IAAM,UAAU,oBAAI,IAAyB;AAC7C,IAAM,QAA6B,CAAC;AAEpC,SAAS,WAAyC;AAChD,SAAO,OAAO,OAAO,MAAM,OAAO,CAAC,CAAC;AACtC;AAEA,SAAS,kBAAkB,QAA6B;AACtD,MAAI,QAAQ,IAAI,MAAM,GAAG;AACvB,UAAM,IAAI,MAAM,wBAAwB,MAAM,gDAAgD;AAAA,EAChG;AAEA,QAAM,EAAE,OAAO,MAAM,IAAI,IAAI,eAAe;AAE5C,sBAAoB,OAAO,MAAM;AAEjC,SAAO;AACT;AAEA,SAAS,oBAAoB,MAAmB,QAAsB;AACpE,MAAI,QAAQ,IAAI,MAAM,GAAG;AACvB,UAAM,IAAI,MAAM,wBAAwB,MAAM,gDAAgD;AAAA,EAChG;AAEA,UAAQ,IAAI,QAAQ,IAAI;AAExB,OAAK,iBAAiB,WAAW,CAAC,EAAE,MAAM,MAAM,MAAM;AAMpD,UAAM,kBAAkB,MAAM,IAAI,CAAAA,UAAQ;AACxC,YAAM,KAAK,WAAG;AAEd,0BAAoBA,OAAM,EAAE;AAE5B,aAAO;AAAA,IACT,CAAC;AAED,UAAM;AAAA,MACJ,OAAO,OAAO;AAAA,QACZ,MAAM,QAAQ,MAAM,KAAK;AAAA,QACzB;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAED,OAAK,MAAM;AACb;AAEA,SAAS,cAAc,SAAkC;AACvD,QAAM,EAAE,MAAM,QAAQ,gBAAgB,IAAI;AAE1C,QAAM,OAAO,QAAQ,IAAI,MAAM;AAE/B,MAAI,CAAC,MAAM;AACT,YAAQ,KAAK,yCAAyC,MAAM,GAAG;AAE/D;AAAA,EACF;AAGA,QAAM,WAAW,gBAAgB,IAAI,oBAAkB,kBAAkB,cAAc,CAAC;AAExF,OAAK,YAAY,UAAU,MAAM,QAAQ,GAAG,QAAQ;AACtD;AAEA,WAAW,yCAAyC,OAAO,OAAO;AAAA,EAChE;AAAA,EACA;AACF,CAA+B;AAE/B,IAAM,cAAc,kBAAkB,iBAAiB;","names":["port"]}
@@ -0,0 +1,174 @@
1
+ // ../../node_modules/uuid/dist-node/rng.js
2
+ var rnds8 = new Uint8Array(16);
3
+ function rng() {
4
+ return crypto.getRandomValues(rnds8);
5
+ }
6
+
7
+ // ../../node_modules/uuid/dist-node/stringify.js
8
+ var byteToHex = [];
9
+ for (let i = 0; i < 256; ++i) {
10
+ byteToHex.push((i + 256).toString(16).slice(1));
11
+ }
12
+ function unsafeStringify(arr, offset = 0) {
13
+ return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
14
+ }
15
+
16
+ // ../../node_modules/uuid/dist-node/v7.js
17
+ var _state = {};
18
+ function v7(options, buf, offset) {
19
+ let bytes;
20
+ if (options) {
21
+ bytes = v7Bytes(options.random ?? options.rng?.() ?? rng(), options.msecs, options.seq, buf, offset);
22
+ } else {
23
+ const now = Date.now();
24
+ const rnds = rng();
25
+ updateV7State(_state, now, rnds);
26
+ bytes = v7Bytes(rnds, _state.msecs, _state.seq, buf, offset);
27
+ }
28
+ return buf ?? unsafeStringify(bytes);
29
+ }
30
+ function updateV7State(state, now, rnds) {
31
+ state.msecs ??= -Infinity;
32
+ state.seq ??= 0;
33
+ if (now > state.msecs) {
34
+ state.seq = rnds[6] << 23 | rnds[7] << 16 | rnds[8] << 8 | rnds[9];
35
+ state.msecs = now;
36
+ } else {
37
+ state.seq = state.seq + 1 | 0;
38
+ if (state.seq === 0) {
39
+ state.msecs++;
40
+ }
41
+ }
42
+ return state;
43
+ }
44
+ function v7Bytes(rnds, msecs, seq, buf, offset = 0) {
45
+ if (rnds.length < 16) {
46
+ throw new Error("Random bytes length must be >= 16");
47
+ }
48
+ if (!buf) {
49
+ buf = new Uint8Array(16);
50
+ offset = 0;
51
+ } else {
52
+ if (offset < 0 || offset + 16 > buf.length) {
53
+ throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
54
+ }
55
+ }
56
+ msecs ??= Date.now();
57
+ seq ??= rnds[6] * 127 << 24 | rnds[7] << 16 | rnds[8] << 8 | rnds[9];
58
+ buf[offset++] = msecs / 1099511627776 & 255;
59
+ buf[offset++] = msecs / 4294967296 & 255;
60
+ buf[offset++] = msecs / 16777216 & 255;
61
+ buf[offset++] = msecs / 65536 & 255;
62
+ buf[offset++] = msecs / 256 & 255;
63
+ buf[offset++] = msecs & 255;
64
+ buf[offset++] = 112 | seq >>> 28 & 15;
65
+ buf[offset++] = seq >>> 20 & 255;
66
+ buf[offset++] = 128 | seq >>> 14 & 63;
67
+ buf[offset++] = seq >>> 6 & 255;
68
+ buf[offset++] = seq << 2 & 255 | rnds[10] & 3;
69
+ buf[offset++] = rnds[11];
70
+ buf[offset++] = rnds[12];
71
+ buf[offset++] = rnds[13];
72
+ buf[offset++] = rnds[14];
73
+ buf[offset++] = rnds[15];
74
+ return buf;
75
+ }
76
+ var v7_default = v7;
77
+
78
+ // src/constant.ts
79
+ var ROOT_MESSAGE_PORT = "00000000-0000-0000-0000-000000000000";
80
+
81
+ // ../../node_modules/workthru/dist/workthru.mjs
82
+ function workthru_(target, transformer, walked) {
83
+ if (Array.isArray(target)) {
84
+ if (walked.has(target)) {
85
+ return walked.get(target);
86
+ }
87
+ let nextArray = transformer(target);
88
+ if (nextArray !== target) {
89
+ walked.set(target, nextArray);
90
+ return nextArray;
91
+ }
92
+ walked.set(target, target);
93
+ for (const index in target) {
94
+ const value = target[index];
95
+ const nextValue = workthru_(value, transformer, walked);
96
+ if (nextValue !== value) {
97
+ if (nextArray === target) {
98
+ nextArray = [...target];
99
+ }
100
+ nextArray[index] = nextValue;
101
+ }
102
+ }
103
+ walked.set(target, nextArray);
104
+ return nextArray;
105
+ }
106
+ if (typeof target === "object" && target !== null) {
107
+ if (walked.has(target)) {
108
+ return walked.get(target);
109
+ }
110
+ const prototype = Object.getPrototypeOf(target);
111
+ if (prototype === null || prototype === Object.prototype) {
112
+ const nextTarget = transformer(target);
113
+ if (nextTarget !== target) {
114
+ walked.set(target, nextTarget);
115
+ return nextTarget;
116
+ }
117
+ walked.set(target, target);
118
+ const entries = Object.entries(target);
119
+ let nextMap = void 0;
120
+ for (const [key, value] of entries) {
121
+ const nextValue = workthru_(value, transformer, walked);
122
+ if (nextValue !== value) {
123
+ if (!nextMap) {
124
+ nextMap = new Map(entries);
125
+ }
126
+ nextMap.set(key, nextValue);
127
+ }
128
+ }
129
+ const nextObject = nextMap ? Object.fromEntries(nextMap.entries()) : target;
130
+ walked.set(target, nextObject);
131
+ return nextObject;
132
+ }
133
+ }
134
+ return transformer(target);
135
+ }
136
+ function workthru(target, transformer) {
137
+ return workthru_(target, transformer, /* @__PURE__ */ new Map());
138
+ }
139
+ var workthru_default = workthru;
140
+
141
+ // src/marshal.ts
142
+ var MESSAGE_PORT = "@@__SELENIUM_WEBDRIVER_MESSAGE_PORT__@@";
143
+ function marshal(target, transferable) {
144
+ return workthru_default(target, (value) => {
145
+ if (value instanceof MessagePort) {
146
+ const index = transferable.indexOf(value);
147
+ if (index === -1) {
148
+ throw new Error("Cannot marshal MessagePort: it must be included in the transfer list");
149
+ }
150
+ return [MESSAGE_PORT, index];
151
+ }
152
+ return value;
153
+ });
154
+ }
155
+ function unmarshal(target, transferable) {
156
+ return workthru_default(target, (value) => {
157
+ if (Array.isArray(value) && value[0] === MESSAGE_PORT) {
158
+ const index = value[1];
159
+ if (typeof index !== "number" || !Number.isInteger(index) || index < 0 || index >= transferable.length) {
160
+ throw new Error(`Cannot unmarshal MessagePort: invalid transfer index ${String(index)}`);
161
+ }
162
+ return transferable[index];
163
+ }
164
+ return value;
165
+ });
166
+ }
167
+
168
+ export {
169
+ v7_default,
170
+ ROOT_MESSAGE_PORT,
171
+ marshal,
172
+ unmarshal
173
+ };
174
+ //# sourceMappingURL=chunk-2MTLTUOY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../node_modules/uuid/dist-node/rng.js","../../../node_modules/uuid/dist-node/stringify.js","../../../node_modules/uuid/dist-node/v7.js","../src/constant.ts","../../../node_modules/workthru/src/workthru.ts","../src/marshal.ts"],"sourcesContent":["const rnds8 = new Uint8Array(16);\nexport default function rng() {\n return crypto.getRandomValues(rnds8);\n}\n","import validate from './validate.js';\nconst byteToHex = [];\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n return (byteToHex[arr[offset + 0]] +\n byteToHex[arr[offset + 1]] +\n byteToHex[arr[offset + 2]] +\n byteToHex[arr[offset + 3]] +\n '-' +\n byteToHex[arr[offset + 4]] +\n byteToHex[arr[offset + 5]] +\n '-' +\n byteToHex[arr[offset + 6]] +\n byteToHex[arr[offset + 7]] +\n '-' +\n byteToHex[arr[offset + 8]] +\n byteToHex[arr[offset + 9]] +\n '-' +\n byteToHex[arr[offset + 10]] +\n byteToHex[arr[offset + 11]] +\n byteToHex[arr[offset + 12]] +\n byteToHex[arr[offset + 13]] +\n byteToHex[arr[offset + 14]] +\n byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset);\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n return uuid;\n}\nexport default stringify;\n","import rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nconst _state = {};\nfunction v7(options, buf, offset) {\n let bytes;\n if (options) {\n bytes = v7Bytes(options.random ?? options.rng?.() ?? rng(), options.msecs, options.seq, buf, offset);\n }\n else {\n const now = Date.now();\n const rnds = rng();\n updateV7State(_state, now, rnds);\n bytes = v7Bytes(rnds, _state.msecs, _state.seq, buf, offset);\n }\n return buf ?? unsafeStringify(bytes);\n}\nexport function updateV7State(state, now, rnds) {\n state.msecs ??= -Infinity;\n state.seq ??= 0;\n if (now > state.msecs) {\n state.seq = (rnds[6] << 23) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9];\n state.msecs = now;\n }\n else {\n state.seq = (state.seq + 1) | 0;\n if (state.seq === 0) {\n state.msecs++;\n }\n }\n return state;\n}\nfunction v7Bytes(rnds, msecs, seq, buf, offset = 0) {\n if (rnds.length < 16) {\n throw new Error('Random bytes length must be >= 16');\n }\n if (!buf) {\n buf = new Uint8Array(16);\n offset = 0;\n }\n else {\n if (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n }\n }\n msecs ??= Date.now();\n seq ??= ((rnds[6] * 0x7f) << 24) | (rnds[7] << 16) | (rnds[8] << 8) | rnds[9];\n buf[offset++] = (msecs / 0x10000000000) & 0xff;\n buf[offset++] = (msecs / 0x100000000) & 0xff;\n buf[offset++] = (msecs / 0x1000000) & 0xff;\n buf[offset++] = (msecs / 0x10000) & 0xff;\n buf[offset++] = (msecs / 0x100) & 0xff;\n buf[offset++] = msecs & 0xff;\n buf[offset++] = 0x70 | ((seq >>> 28) & 0x0f);\n buf[offset++] = (seq >>> 20) & 0xff;\n buf[offset++] = 0x80 | ((seq >>> 14) & 0x3f);\n buf[offset++] = (seq >>> 6) & 0xff;\n buf[offset++] = ((seq << 2) & 0xff) | (rnds[10] & 0x03);\n buf[offset++] = rnds[11];\n buf[offset++] = rnds[12];\n buf[offset++] = rnds[13];\n buf[offset++] = rnds[14];\n buf[offset++] = rnds[15];\n return buf;\n}\nexport default v7;\n","const ROOT_MESSAGE_PORT = '00000000-0000-0000-0000-000000000000';\n\nexport { ROOT_MESSAGE_PORT };\n","/**\n * Internal recursive helper for {@link workthru}.\n *\n * For arrays and plain objects, calls transformer first. If transformer returns the same reference,\n * recursively walks children and rebuilds the container only when a child changes (structural sharing).\n * Class instances, primitives, functions, and null are passed directly to transformer without recursion.\n *\n * The `walked` map tracks already-visited nodes to handle circular references and avoid duplicate work.\n *\n * @param target - Value to transform.\n * @param transformer - Called on every visited value; return the original value to recurse into children.\n * @param walked - Cycle-detection map from original value to its transformed counterpart.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction workthru_(target: any, transformer: (value: any) => any, walked: Map<any, any>): any {\n if (Array.isArray(target)) {\n if (walked.has(target)) {\n return walked.get(target);\n }\n\n let nextArray = transformer(target);\n\n if (nextArray !== target) {\n walked.set(target, nextArray);\n\n return nextArray;\n }\n\n walked.set(target, target);\n\n // for-in loop can handle sparse array.\n for (const index in target) {\n const value = target[index];\n const nextValue = workthru_(value, transformer, walked);\n\n if (nextValue !== value) {\n if (nextArray === target) {\n nextArray = [...target];\n }\n\n nextArray[index] = nextValue;\n }\n }\n\n walked.set(target, nextArray);\n\n return nextArray;\n }\n\n if (typeof target === 'object' && target !== null) {\n if (walked.has(target)) {\n return walked.get(target);\n }\n\n const prototype = Object.getPrototypeOf(target);\n\n if (prototype === null || prototype === Object.prototype) {\n const nextTarget = transformer(target);\n\n if (nextTarget !== target) {\n walked.set(target, nextTarget);\n\n return nextTarget;\n }\n\n walked.set(target, target);\n\n const entries = Object.entries(target);\n let nextMap = undefined;\n\n for (const [key, value] of entries) {\n const nextValue = workthru_(value, transformer, walked);\n\n if (nextValue !== value) {\n if (!nextMap) {\n nextMap = new Map(entries);\n }\n\n nextMap.set(key, nextValue);\n }\n }\n\n const nextObject = nextMap ? Object.fromEntries(nextMap.entries()) : target;\n\n walked.set(target, nextObject);\n\n return nextObject;\n }\n }\n\n return transformer(target);\n}\n\n/**\n * Recursively walks the input in a depth-first search manner and transforms value as needed.\n *\n * Every traversed value will be passed to the `transformer` function.\n *\n * - If the `transformer` return the original value, the traversal for this branch will be continued\n * - If the `transformer` return a new value, the traversal for this branch will be ended\n *\n * The following data types are supported:\n *\n * - boolean, number, string\n * - array will be transformed on itself and every of the element\n * - plain object will be transformed on itself and every of its member value\n *\n * Notes:\n *\n * - Values with unsupported will be kept as-is;\n * - Values that are not transformed will be kept as-is\n *\n * @param target - The value to be worked through\n * @param transformer - The function to transform the value\n * @returns - The transformed value if the input has been transformed, otherwise, return the original value\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction workthru(target: any, transformer: (value: any) => any): any {\n return workthru_(target, transformer, new Map());\n}\n\nexport default workthru;\n","import { workthru } from 'workthru';\n\nconst MESSAGE_PORT = '@@__SELENIUM_WEBDRIVER_MESSAGE_PORT__@@';\n\n/**\n * Marshals the data and mask `MessagePort` into ['@@__SELENIUM_WEBDRIVER_MESSAGE_PORT__@@', 1].\n *\n * MessagePort cannot be sent directly across WebDriver.executeScript.\n *\n * We are walking the postMessage(data) and turning MessagePort into ['@@__SELENIUM_WEBDRIVER_MESSAGE_PORT__@@', 1].\n *\n * The second argument is the index of the MessagePort as they appear in Transferable[].\n *\n * @param target\n * @param transferable\n * @returns\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction marshal(target: any, transferable: readonly Transferable[]): any {\n return workthru(target, value => {\n if (value instanceof MessagePort) {\n const index = transferable.indexOf(value);\n\n if (index === -1) {\n throw new Error('Cannot marshal MessagePort: it must be included in the transfer list');\n }\n\n return [MESSAGE_PORT, index] as const;\n }\n\n return value;\n });\n}\n\n/**\n * Unmarshals the data and unmask ['@@__SELENIUM_WEBDRIVER_MESSAGE_PORT__@@', 1] into `MessagePort`.\n *\n * MessagePort cannot be sent directly across WebDriver.executeScript.\n *\n * We are walking the postMessage(data) and turning MessagePort into ['@@__SELENIUM_WEBDRIVER_MESSAGE_PORT__@@', 1].\n *\n * The second argument is the index of the MessagePort as they appear in Transferable[].\n *\n * @param target\n * @param transferable\n * @returns\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction unmarshal(target: any, transferable: readonly Transferable[]): any {\n return workthru(target, value => {\n if (Array.isArray(value) && value[0] === MESSAGE_PORT) {\n const index = value[1];\n\n if (typeof index !== 'number' || !Number.isInteger(index) || index < 0 || index >= transferable.length) {\n throw new Error(`Cannot unmarshal MessagePort: invalid transfer index ${String(index)}`);\n }\n\n return transferable[index];\n }\n\n return value;\n });\n}\n\nexport { marshal, unmarshal };\n"],"mappings":"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","names":[]}
package/dist/host.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ import { WebDriver } from 'selenium-webdriver';
2
+
3
+ declare function setup(webDriver: WebDriver): {
4
+ messagePort: MessagePort;
5
+ poll(): Promise<void>;
6
+ };
7
+
8
+ export { setup };
package/dist/host.js ADDED
@@ -0,0 +1,105 @@
1
+ import {
2
+ ROOT_MESSAGE_PORT,
3
+ marshal,
4
+ unmarshal,
5
+ v7_default
6
+ } from "./chunk-2MTLTUOY.js";
7
+
8
+ // src/host/createSequencer.ts
9
+ function createSequencer() {
10
+ const backlog = [];
11
+ let isBusy = false;
12
+ async function kickoff() {
13
+ if (isBusy) {
14
+ return;
15
+ }
16
+ isBusy = true;
17
+ try {
18
+ let fn;
19
+ while (fn = backlog.shift()) {
20
+ await fn();
21
+ }
22
+ } finally {
23
+ isBusy = false;
24
+ }
25
+ }
26
+ return (fn) => new Promise((resolve, reject) => {
27
+ backlog.push(async () => {
28
+ try {
29
+ resolve(await fn());
30
+ } catch (error) {
31
+ reject(error);
32
+ }
33
+ });
34
+ kickoff();
35
+ });
36
+ }
37
+ var createSequencer_default = createSequencer;
38
+
39
+ // src/host/setup.ts
40
+ function setup(webDriver) {
41
+ const portMap = /* @__PURE__ */ new Map();
42
+ const executeScriptSequencer = createSequencer_default();
43
+ const createMessagePort = (id) => {
44
+ if (portMap.has(id)) {
45
+ throw new Error(`MessagePort with id "${id}" is already registered, cannot register again`);
46
+ }
47
+ const { port1, port2 } = new MessageChannel();
48
+ registerMessagePort(port1, id);
49
+ return port2;
50
+ };
51
+ const registerMessagePort = (port, portId) => {
52
+ if (portMap.has(portId)) {
53
+ throw new Error(`MessagePort with id "${portId}" is already registered, cannot register again`);
54
+ }
55
+ portMap.set(portId, port);
56
+ port.addEventListener("message", ({ data, ports }) => {
57
+ void executeScriptSequencer(async () => {
58
+ await webDriver.executeScript(
59
+ (message) => {
60
+ if (!globalThis.__seleniumWebDriverMessagePortFacility) {
61
+ throw new Error("The page does not have harness installed, cannot send message");
62
+ }
63
+ globalThis.__seleniumWebDriverMessagePortFacility.sendToBrowser(message);
64
+ },
65
+ {
66
+ data: marshal(data, ports),
67
+ portId,
68
+ transferPortIds: ports.map((port2) => {
69
+ const id = v7_default();
70
+ registerMessagePort(port2, id);
71
+ return id;
72
+ })
73
+ }
74
+ );
75
+ }).catch((error) => console.error(error));
76
+ });
77
+ port.start();
78
+ };
79
+ const poll = async () => {
80
+ const entries = await webDriver.executeScript(() => {
81
+ if (!globalThis.__seleniumWebDriverMessagePortFacility) {
82
+ throw new Error("The page does not have harness installed");
83
+ }
84
+ return globalThis.__seleniumWebDriverMessagePortFacility.flushAll();
85
+ });
86
+ for (const { data, portId, transferPortIds } of entries) {
87
+ const port = portMap.get(portId);
88
+ if (!port) {
89
+ console.warn(`Browser should not send to unbound port "${portId}"`);
90
+ continue;
91
+ }
92
+ const transfer = transferPortIds.map((transferPortId) => createMessagePort(transferPortId));
93
+ port.postMessage(unmarshal(data, transfer), transfer);
94
+ }
95
+ };
96
+ return Object.freeze({
97
+ messagePort: createMessagePort(ROOT_MESSAGE_PORT),
98
+ poll
99
+ });
100
+ }
101
+ var setup_default = setup;
102
+ export {
103
+ setup_default as setup
104
+ };
105
+ //# sourceMappingURL=host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/host/createSequencer.ts","../src/host/setup.ts"],"sourcesContent":["type Fn<T = unknown> = () => Promise<T>;\n\n// We could use `p-queue` and set `{ concurrency: 1 }` but it has too many features and too big.\n\n/**\n * Creates a sequencer which sequence function calls with concurrency of 1.\n *\n * @returns A function, when called, will queue the passing function into the sequencer.\n */\nfunction createSequencer(): <T>(fn: Fn<T>) => Promise<T> {\n const backlog: Fn<void>[] = [];\n let isBusy = false;\n\n async function kickoff() {\n if (isBusy) {\n return;\n }\n\n isBusy = true;\n\n try {\n let fn: Fn<void> | undefined;\n\n while ((fn = backlog.shift())) {\n await fn();\n }\n } finally {\n isBusy = false;\n }\n }\n\n return <T>(fn: Fn<T>): Promise<T> =>\n new Promise<T>((resolve, reject) => {\n backlog.push(async () => {\n try {\n resolve(await fn());\n } catch (error) {\n reject(error);\n }\n });\n\n kickoff();\n });\n}\n\nexport default createSequencer;\n","/// <reference types=\"../env.d.ts\" />\n\nimport type { WebDriver } from 'selenium-webdriver';\nimport { v7 } from 'uuid';\nimport { ROOT_MESSAGE_PORT } from '../constant.ts';\nimport { marshal, unmarshal } from '../marshal.ts';\nimport type { SerializedMessage } from '../types.ts';\nimport createSequencer from './createSequencer.ts';\n\nfunction setup(webDriver: WebDriver): {\n messagePort: MessagePort;\n poll(): Promise<void>;\n} {\n const portMap = new Map<string, MessagePort>();\n\n // `executeScript()` calls (and all calls) are not queued in `selenium-webdriver`, they are HTTP POST in parallel.\n // Thus, multiple `executeScript()` calls could be processed in random order.\n // Thus, `MessagePort` could be used before they are transferred.\n // We need to sequence all `executeScript()` calls.\n const executeScriptSequencer = createSequencer();\n\n const createMessagePort = (id: string): MessagePort => {\n if (portMap.has(id)) {\n throw new Error(`MessagePort with id \"${id}\" is already registered, cannot register again`);\n }\n\n const { port1, port2 } = new MessageChannel();\n\n registerMessagePort(port1, id);\n\n return port2;\n };\n\n const registerMessagePort = (port: MessagePort, portId: string): void => {\n if (portMap.has(portId)) {\n throw new Error(`MessagePort with id \"${portId}\" is already registered, cannot register again`);\n }\n\n portMap.set(portId, port);\n\n port.addEventListener('message', ({ data, ports }) => {\n void executeScriptSequencer(async () => {\n await webDriver.executeScript<void>(\n (message: SerializedMessage) => {\n if (!globalThis.__seleniumWebDriverMessagePortFacility) {\n throw new Error('The page does not have harness installed, cannot send message');\n }\n\n globalThis.__seleniumWebDriverMessagePortFacility.sendToBrowser(message);\n },\n {\n data: marshal(data, ports),\n portId,\n transferPortIds: ports.map(port => {\n // Because MessagePort will be neutered on transfer, thus, postMessage() cannot transfer the same MessagePort twice.\n // We don't need to check if the port already have an ID or not, it must be new.\n // Otherwise postMessage() would have already fail and should never reach this code block.\n const id = v7();\n\n registerMessagePort(port, id);\n\n return id;\n })\n } satisfies SerializedMessage\n );\n }).catch(error => console.error(error));\n });\n\n port.start();\n };\n\n const poll = async () => {\n const entries = await webDriver.executeScript<SerializedMessage[]>(() => {\n if (!globalThis.__seleniumWebDriverMessagePortFacility) {\n throw new Error('The page does not have harness installed');\n }\n\n return globalThis.__seleniumWebDriverMessagePortFacility.flushAll();\n });\n\n for (const { data, portId, transferPortIds } of entries) {\n const port = portMap.get(portId);\n\n if (!port) {\n console.warn(`Browser should not send to unbound port \"${portId}\"`);\n\n continue;\n }\n\n // postMessage() will neuter MessagePort after sent, thus, every port received must be new transfer.\n const transfer = transferPortIds.map(transferPortId => createMessagePort(transferPortId));\n\n port.postMessage(unmarshal(data, transfer), transfer);\n }\n };\n\n return Object.freeze({\n messagePort: createMessagePort(ROOT_MESSAGE_PORT),\n poll\n });\n}\n\nexport default setup;\n"],"mappings":";;;;;;;;AASA,SAAS,kBAAgD;AACvD,QAAM,UAAsB,CAAC;AAC7B,MAAI,SAAS;AAEb,iBAAe,UAAU;AACvB,QAAI,QAAQ;AACV;AAAA,IACF;AAEA,aAAS;AAET,QAAI;AACF,UAAI;AAEJ,aAAQ,KAAK,QAAQ,MAAM,GAAI;AAC7B,cAAM,GAAG;AAAA,MACX;AAAA,IACF,UAAE;AACA,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO,CAAI,OACT,IAAI,QAAW,CAAC,SAAS,WAAW;AAClC,YAAQ,KAAK,YAAY;AACvB,UAAI;AACF,gBAAQ,MAAM,GAAG,CAAC;AAAA,MACpB,SAAS,OAAO;AACd,eAAO,KAAK;AAAA,MACd;AAAA,IACF,CAAC;AAED,YAAQ;AAAA,EACV,CAAC;AACL;AAEA,IAAO,0BAAQ;;;ACpCf,SAAS,MAAM,WAGb;AACA,QAAM,UAAU,oBAAI,IAAyB;AAM7C,QAAM,yBAAyB,wBAAgB;AAE/C,QAAM,oBAAoB,CAAC,OAA4B;AACrD,QAAI,QAAQ,IAAI,EAAE,GAAG;AACnB,YAAM,IAAI,MAAM,wBAAwB,EAAE,gDAAgD;AAAA,IAC5F;AAEA,UAAM,EAAE,OAAO,MAAM,IAAI,IAAI,eAAe;AAE5C,wBAAoB,OAAO,EAAE;AAE7B,WAAO;AAAA,EACT;AAEA,QAAM,sBAAsB,CAAC,MAAmB,WAAyB;AACvE,QAAI,QAAQ,IAAI,MAAM,GAAG;AACvB,YAAM,IAAI,MAAM,wBAAwB,MAAM,gDAAgD;AAAA,IAChG;AAEA,YAAQ,IAAI,QAAQ,IAAI;AAExB,SAAK,iBAAiB,WAAW,CAAC,EAAE,MAAM,MAAM,MAAM;AACpD,WAAK,uBAAuB,YAAY;AACtC,cAAM,UAAU;AAAA,UACd,CAAC,YAA+B;AAC9B,gBAAI,CAAC,WAAW,wCAAwC;AACtD,oBAAM,IAAI,MAAM,+DAA+D;AAAA,YACjF;AAEA,uBAAW,uCAAuC,cAAc,OAAO;AAAA,UACzE;AAAA,UACA;AAAA,YACE,MAAM,QAAQ,MAAM,KAAK;AAAA,YACzB;AAAA,YACA,iBAAiB,MAAM,IAAI,CAAAA,UAAQ;AAIjC,oBAAM,KAAK,WAAG;AAEd,kCAAoBA,OAAM,EAAE;AAE5B,qBAAO;AAAA,YACT,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF,CAAC,EAAE,MAAM,WAAS,QAAQ,MAAM,KAAK,CAAC;AAAA,IACxC,CAAC;AAED,SAAK,MAAM;AAAA,EACb;AAEA,QAAM,OAAO,YAAY;AACvB,UAAM,UAAU,MAAM,UAAU,cAAmC,MAAM;AACvE,UAAI,CAAC,WAAW,wCAAwC;AACtD,cAAM,IAAI,MAAM,0CAA0C;AAAA,MAC5D;AAEA,aAAO,WAAW,uCAAuC,SAAS;AAAA,IACpE,CAAC;AAED,eAAW,EAAE,MAAM,QAAQ,gBAAgB,KAAK,SAAS;AACvD,YAAM,OAAO,QAAQ,IAAI,MAAM;AAE/B,UAAI,CAAC,MAAM;AACT,gBAAQ,KAAK,4CAA4C,MAAM,GAAG;AAElE;AAAA,MACF;AAGA,YAAM,WAAW,gBAAgB,IAAI,oBAAkB,kBAAkB,cAAc,CAAC;AAExF,WAAK,YAAY,UAAU,MAAM,QAAQ,GAAG,QAAQ;AAAA,IACtD;AAAA,EACF;AAEA,SAAO,OAAO,OAAO;AAAA,IACnB,aAAa,kBAAkB,iBAAiB;AAAA,IAChD;AAAA,EACF,CAAC;AACH;AAEA,IAAO,gBAAQ;","names":["port"]}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onting/selenium-webdriver-message-port",
3
- "version": "0.0.0-0",
3
+ "version": "0.1.0-main.202606020948.0ed3d01",
4
4
  "description": "MessagePort for passing bidirectional messages between WebDriver host and browser",
5
5
  "homepage": "https://github.com/teamonting/selenium-webdriver-message-port#readme",
6
6
  "publishConfig": {
@@ -15,20 +15,23 @@
15
15
  },
16
16
  "license": "MIT",
17
17
  "author": "",
18
+ "type": "module",
19
+ "main": "./dist/index.js",
20
+ "typings": "./dist/index.d.ts",
18
21
  "exports": {
19
22
  ".": {
20
- "import": {
21
- "types": "./dist/selenium-webdriver-message-port.d.mts",
22
- "default": "./dist/selenium-webdriver-message-port.mjs"
23
- },
24
- "require": {
25
- "types": "./dist/selenium-webdriver-message-port.d.ts",
26
- "default": "./dist/selenium-webdriver-message-port.js"
27
- }
23
+ "types": "./dist/index.d.ts",
24
+ "default": "./dist/index.js"
25
+ },
26
+ "./browser": {
27
+ "types": "./dist/browser.d.ts",
28
+ "default": "./dist/browser.js"
29
+ },
30
+ "./host": {
31
+ "types": "./dist/host.d.ts",
32
+ "default": "./dist/host.js"
28
33
  }
29
34
  },
30
- "main": "./dist/selenium-webdriver-message-port.js",
31
- "typings": "./dist/selenium-webdriver-message-port.d.ts",
32
35
  "files": [
33
36
  "./*.js",
34
37
  "./CHANGELOG.md",
@@ -59,6 +62,7 @@
59
62
  "@tsconfig/recommended": "^1.0.13",
60
63
  "@tsconfig/strictest": "^2.0.8",
61
64
  "@types/node": "^25.9.1",
65
+ "@types/selenium-webdriver": "^4.35.6",
62
66
  "escape-string-regexp": "^4.0.0",
63
67
  "expect": "^30.4.1",
64
68
  "publint": "^0.3.21",
@@ -67,5 +71,10 @@
67
71
  },
68
72
  "localPeerDependencies": {
69
73
  "@onting/test-harness": "0.0.0-0"
74
+ },
75
+ "dependencies": {
76
+ "@onting/selenium-webdriver-message-port": "^0.1.0-main.202606020948.0ed3d01",
77
+ "uuid": "^14.0.0",
78
+ "workthru": "^0.1.0"
70
79
  }
71
80
  }
@@ -1,2 +0,0 @@
1
-
2
- export { }
@@ -1,19 +0,0 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __copyProps = (to, from, except, desc) => {
7
- if (from && typeof from === "object" || typeof from === "function") {
8
- for (let key of __getOwnPropNames(from))
9
- if (!__hasOwnProp.call(to, key) && key !== except)
10
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
- }
12
- return to;
13
- };
14
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
-
16
- // src/index.ts
17
- var src_exports = {};
18
- module.exports = __toCommonJS(src_exports);
19
- //# sourceMappingURL=selenium-webdriver-message-port.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {};\n"],"mappings":";;;;;;;;;;;;;;;;AAAA;AAAA;","names":[]}
@@ -1 +0,0 @@
1
- //# sourceMappingURL=selenium-webdriver-message-port.mjs.map