@wix/himalaya-cli 0.1451.0 → 0.1452.0

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.
@@ -1,25 +1,15 @@
1
- // ../../core/sdk/webview/src/index.ts
2
- function runtime() {
3
- const himalaya = globalThis.himalaya;
4
- if (!himalaya?.webview) {
5
- throw new Error(
6
- '@himalaya/webview: called outside a Himalaya runtime, or the host did not install the webview bridge. This binding must run inside a worker-backed webview screen (Tier 5 + webview renderer) with the "webview" capability declared.'
7
- );
8
- }
9
- return himalaya.webview;
10
- }
11
- function postToPage(msg) {
12
- runtime().postToPage(msg);
13
- }
14
- function onPageMessage(cb) {
15
- runtime().onPageMessage(cb);
16
- }
1
+ // ../../core/sdk/webview/src/dispatcher.ts
17
2
  var PAGE_HANDSHAKE_CAPABILITY = "himalaya";
18
3
  var PAGE_HANDSHAKE_METHOD = "capabilities";
4
+ var RESERVED_NAMESPACES = /* @__PURE__ */ new Set(["call", "on", "probe", "version", "then", "constructor", "general"]);
5
+ var UNREACHABLE_SEGMENTS = /* @__PURE__ */ new Set(["then", "toString", "valueOf"]);
6
+ var NAMESPACE_PATTERN = /^[a-z][a-z0-9_]{0,63}$/;
7
+ var METHOD_PATTERN = /^[A-Za-z][A-Za-z0-9_]{0,63}(?:\.[A-Za-z][A-Za-z0-9_]{0,63}){0,3}$/;
8
+ var ID_PATTERN = /^[A-Za-z0-9-]{1,96}$/;
19
9
  function pageRequest(value) {
20
10
  if (!value || typeof value !== "object") return null;
21
11
  const request = value;
22
- if (request.v !== 1 || typeof request.id !== "string" || !/^[A-Za-z0-9-]{1,96}$/.test(request.id) || typeof request.capability !== "string" || !/^[a-z][a-z0-9_]{0,63}$/.test(request.capability) || typeof request.method !== "string" || !/^[A-Za-z][A-Za-z0-9_]{0,63}(?:\.[A-Za-z][A-Za-z0-9_]{0,63}){0,3}$/.test(request.method) || !Array.isArray(request.args) || request.args.length > 12) return null;
12
+ if (request.v !== 1 || typeof request.id !== "string" || !ID_PATTERN.test(request.id) || typeof request.capability !== "string" || !NAMESPACE_PATTERN.test(request.capability) || typeof request.method !== "string" || !METHOD_PATTERN.test(request.method) || !Array.isArray(request.args) || request.args.length > 12) return null;
23
13
  return request;
24
14
  }
25
15
  function pageError(value) {
@@ -30,52 +20,518 @@ function pageError(value) {
30
20
  ...typeof code === "string" && code ? { code } : {}
31
21
  };
32
22
  }
33
- function exposeCapabilitiesToPage(capabilities) {
34
- if (Object.prototype.hasOwnProperty.call(capabilities, PAGE_HANDSHAKE_CAPABILITY)) {
35
- throw new Error(`"${PAGE_HANDSHAKE_CAPABILITY}" is reserved for the page handshake and cannot be exposed`);
36
- }
37
- const allowed = new Map(
38
- Object.entries(capabilities).map(([id, entry]) => [id, {
39
- module: entry.module,
40
- methods: new Set(entry.methods)
41
- }])
42
- );
43
- const manifest = Object.fromEntries(
44
- [...allowed].map(([id, entry]) => [id, [...entry.methods].sort()])
45
- );
46
- onPageMessage((message) => {
47
- const request = pageRequest(message);
48
- if (!request) return;
49
- if (request.capability === PAGE_HANDSHAKE_CAPABILITY) {
50
- if (request.method === PAGE_HANDSHAKE_METHOD) {
51
- postToPage({ v: 1, id: request.id, ok: true, result: { v: 1, capabilities: manifest } });
23
+ var key = (instanceId, id) => `${instanceId}\0${id}`;
24
+ var instanceOf = (value) => typeof value === "string" ? value : "";
25
+ function createPageDispatcher(runtime2) {
26
+ let installed = false;
27
+ let lifecycleInstalled = false;
28
+ let raw = null;
29
+ const exposed = /* @__PURE__ */ new Map();
30
+ const namespaces = /* @__PURE__ */ new Map();
31
+ const inFlight = /* @__PURE__ */ new Map();
32
+ const lingering = /* @__PURE__ */ new Map();
33
+ let calling = null;
34
+ const crashed = /* @__PURE__ */ new Set();
35
+ const streams = /* @__PURE__ */ new Map();
36
+ const handles = /* @__PURE__ */ new WeakMap();
37
+ const live = /* @__PURE__ */ new Set();
38
+ const inactive = /* @__PURE__ */ new Set();
39
+ const gone = /* @__PURE__ */ new Set();
40
+ const lifecycleSubscribers = /* @__PURE__ */ new Set();
41
+ const consoleSubscribers = /* @__PURE__ */ new Set();
42
+ const instanceAware = () => typeof runtime2.onPageLifecycle === "function";
43
+ const register = runtime2.onPageMessage;
44
+ try {
45
+ runtime2.onPageMessage = (cb) => {
46
+ raw = typeof cb === "function" ? (msg, instanceId) => cb(msg, instanceId) : null;
47
+ if (!installed) register.call(runtime2, cb);
48
+ };
49
+ } catch {
50
+ }
51
+ function assertFree(name) {
52
+ if (exposed.has(name)) throw new Error(`page capability "${name}" is already exposed`);
53
+ if (namespaces.has(name)) throw new Error(`page namespace "${name}" is already registered`);
54
+ }
55
+ function install() {
56
+ if (!installed) {
57
+ installed = true;
58
+ register.call(runtime2, (msg, instanceId) => onPage(msg, instanceOf(instanceId)));
59
+ }
60
+ if (!lifecycleInstalled && instanceAware()) {
61
+ lifecycleInstalled = true;
62
+ runtime2.onPageLifecycle((envelope, instanceId) => onLifecycle(envelope, instanceId));
63
+ }
64
+ }
65
+ function setRawHandler(cb) {
66
+ raw = cb;
67
+ install();
68
+ }
69
+ function assertReachable(name, kind) {
70
+ if (typeof name !== "string" || !NAMESPACE_PATTERN.test(name)) {
71
+ throw new Error(`page ${kind} ${JSON.stringify(name)} must match ${NAMESPACE_PATTERN}`);
72
+ }
73
+ if (RESERVED_NAMESPACES.has(name)) {
74
+ throw new Error(`page ${kind} "${name}" is reserved: the page's himalaya.${name} is not a namespace`);
75
+ }
76
+ }
77
+ function expose(capabilities) {
78
+ for (const id of Object.keys(capabilities)) {
79
+ if (id === PAGE_HANDSHAKE_CAPABILITY) {
80
+ throw new Error(`"${PAGE_HANDSHAKE_CAPABILITY}" is reserved for the page handshake and cannot be exposed`);
52
81
  }
82
+ assertReachable(id, "capability");
83
+ assertFree(id);
84
+ }
85
+ for (const [id, entry] of Object.entries(capabilities)) {
86
+ exposed.set(id, { module: entry.module, methods: new Set(entry.methods) });
87
+ }
88
+ install();
89
+ }
90
+ function addNamespace(namespace, handlers) {
91
+ if (namespace === PAGE_HANDSHAKE_CAPABILITY) {
92
+ throw new Error(`"${PAGE_HANDSHAKE_CAPABILITY}" is reserved for the page handshake and cannot be a namespace`);
93
+ }
94
+ assertReachable(namespace, "namespace");
95
+ assertFree(namespace);
96
+ const methods = /* @__PURE__ */ new Map();
97
+ for (const [method, handler] of Object.entries(handlers ?? {})) {
98
+ if (!METHOD_PATTERN.test(method)) {
99
+ throw new Error(`page method ${JSON.stringify(`${namespace}.${method}`)} must match ${METHOD_PATTERN}`);
100
+ }
101
+ const segments = method.split(".");
102
+ if (segments[0] === "on" || segments.some((segment) => UNREACHABLE_SEGMENTS.has(segment))) {
103
+ throw new Error(`page method ${JSON.stringify(`${namespace}.${method}`)} is reserved: the page proxy cannot call it`);
104
+ }
105
+ if (typeof handler !== "function") throw new Error(`page handler ${namespace}.${method} is not a function`);
106
+ methods.set(method, handler);
107
+ }
108
+ namespaces.set(namespace, methods);
109
+ install();
110
+ }
111
+ function subscribeLifecycle(cb) {
112
+ lifecycleSubscribers.add(cb);
113
+ install();
114
+ return () => {
115
+ lifecycleSubscribers.delete(cb);
116
+ };
117
+ }
118
+ function subscribeConsole(cb) {
119
+ consoleSubscribers.add(cb);
120
+ install();
121
+ return () => {
122
+ consoleSubscribers.delete(cb);
123
+ };
124
+ }
125
+ function post(instanceId, msg) {
126
+ if (instanceAware()) runtime2.postToPage(msg, instanceId);
127
+ else if (instanceId === "") runtime2.postToPage(msg);
128
+ }
129
+ function emit(target, event, data) {
130
+ install();
131
+ const dot = typeof event === "string" ? event.indexOf(".") : -1;
132
+ const ns = dot > 0 ? event.slice(0, dot) : "";
133
+ const ev = dot > 0 ? event.slice(dot + 1) : "";
134
+ if (!NAMESPACE_PATTERN.test(ns) || !ev) {
135
+ throw new Error(`emitToPage event ${JSON.stringify(event)} must be "<namespace>.<event>"`);
136
+ }
137
+ const envelope = { v: 1, ev, ns, data };
138
+ if (target === "*") {
139
+ const targets = instanceAware() ? live : /* @__PURE__ */ new Set([...live, ""]);
140
+ for (const instanceId of [...targets]) post(instanceId, envelope);
141
+ } else {
142
+ post(target, envelope);
143
+ }
144
+ }
145
+ function openStream(instanceId, requestId) {
146
+ const k = key(instanceId, requestId);
147
+ let pending;
148
+ let ambiguous = false;
149
+ if (calling?.k === k) pending = calling.pending;
150
+ else {
151
+ pending = inFlight.get(k);
152
+ ambiguous = (lingering.get(k)?.size ?? 0) > 0;
153
+ }
154
+ const existing = streams.get(k);
155
+ if (existing && !ambiguous && pending && existing.owner === pending) return existing.handle;
156
+ if (pending?.abandoned || ambiguous || pending && existing) {
157
+ const dead = {
158
+ owner: null,
159
+ instanceId,
160
+ sid: requestId,
161
+ buffer: null,
162
+ closed: true,
163
+ aborted: true,
164
+ cancelled: [],
165
+ handle: void 0
166
+ };
167
+ dead.handle = {
168
+ next: () => {
169
+ },
170
+ end: () => {
171
+ },
172
+ error: () => {
173
+ },
174
+ onCancel: (cb) => {
175
+ if (typeof cb === "function") runCancel(cb);
176
+ },
177
+ get closed() {
178
+ return true;
179
+ }
180
+ };
181
+ handles.set(dead.handle, dead);
182
+ return dead.handle;
183
+ }
184
+ if (!pending) {
185
+ throw new Error(`openPageStream: no request ${JSON.stringify(requestId)} is awaiting an answer on instance ${JSON.stringify(instanceId)}`);
186
+ }
187
+ const state = {
188
+ owner: pending,
189
+ instanceId,
190
+ sid: requestId,
191
+ buffer: [],
192
+ closed: false,
193
+ aborted: false,
194
+ cancelled: [],
195
+ handle: void 0
196
+ };
197
+ const send = (envelope, last) => {
198
+ if (state.closed) return;
199
+ if (last) state.closed = true;
200
+ if (state.buffer) state.buffer.push(envelope);
201
+ else post(instanceId, envelope);
202
+ if (last && !state.buffer && streams.get(k) === state) streams.delete(k);
203
+ };
204
+ state.handle = {
205
+ // JSON drops an `undefined` member, and a page reads `{ v, sid }` alone as no chunk at all.
206
+ next: (data) => send({ v: 1, sid: state.sid, chunk: data === void 0 ? null : data }, false),
207
+ end: () => send({ v: 1, sid: state.sid, end: true }, true),
208
+ error: (e) => send({ v: 1, sid: state.sid, error: pageError(e) }, true),
209
+ onCancel: (cb) => {
210
+ if (typeof cb !== "function") return;
211
+ if (state.aborted) runCancel(cb);
212
+ else state.cancelled.push(cb);
213
+ },
214
+ get closed() {
215
+ return state.closed;
216
+ }
217
+ };
218
+ streams.set(k, state);
219
+ handles.set(state.handle, state);
220
+ return state.handle;
221
+ }
222
+ function onPage(msg, instanceId) {
223
+ const sys = msg && typeof msg === "object" && msg.v === 1 ? msg.sys : void 0;
224
+ if (sys === "cancel") return cancel(instanceId, msg.sid);
225
+ if (sys === "console") return forwardConsole(instanceId, msg);
226
+ const dead = gone.has(instanceId);
227
+ if (!dead) live.add(instanceId);
228
+ const request = exposed.size > 0 || namespaces.size > 0 ? pageRequest(msg) : null;
229
+ if (!request) {
230
+ raw?.(msg, instanceId);
231
+ return;
232
+ }
233
+ if (!dead) route(request, instanceId, msg);
234
+ }
235
+ function route(request, instanceId, message) {
236
+ const respond = (response) => post(instanceId, { v: 1, id: request.id, ...response });
237
+ if (request.capability === PAGE_HANDSHAKE_CAPABILITY) {
238
+ if (request.method === PAGE_HANDSHAKE_METHOD) respond({ ok: true, result: { v: 1, capabilities: manifest() } });
239
+ return;
240
+ }
241
+ const capability = exposed.get(request.capability);
242
+ if (capability) {
243
+ const { fn, receiver } = resolvePath(capability.module, request.method);
244
+ if (!capability.methods.has(request.method) || !fn) return;
245
+ const pending2 = begin(key(instanceId, request.id));
246
+ void Promise.resolve().then(() => fn.apply(receiver, request.args)).then(
247
+ (result) => {
248
+ if (settle(key(instanceId, request.id), pending2)) respond({ ok: true, result });
249
+ },
250
+ (error) => {
251
+ if (settle(key(instanceId, request.id), pending2)) respond({ ok: false, error: pageError(error) });
252
+ }
253
+ );
254
+ return;
255
+ }
256
+ const methods = namespaces.get(request.capability);
257
+ if (!methods) {
258
+ raw?.(message, instanceId);
53
259
  return;
54
260
  }
55
- const capability = allowed.get(request.capability);
56
- let candidate = capability?.module;
57
- let receiver = void 0;
58
- for (const segment of request.method.split(".")) {
59
- if (!candidate || typeof candidate !== "object" || !Object.prototype.hasOwnProperty.call(candidate, segment)) {
60
- candidate = void 0;
261
+ const handler = methods.get(request.method);
262
+ if (!handler) {
263
+ respond({
264
+ ok: false,
265
+ error: { message: `Unknown page method: ${request.capability}.${request.method}`, code: "unknown_method" }
266
+ });
267
+ return;
268
+ }
269
+ const k = key(instanceId, request.id);
270
+ const pending = begin(k);
271
+ const ctx = {
272
+ instanceId,
273
+ requestId: request.id,
274
+ get active() {
275
+ return !inactive.has(instanceId) && !gone.has(instanceId);
276
+ }
277
+ };
278
+ void Promise.resolve().then(() => {
279
+ calling = { k, pending };
280
+ try {
281
+ return handler(request.args, ctx);
282
+ } finally {
283
+ calling = null;
284
+ }
285
+ }).then(
286
+ (result) => {
287
+ const reader = settle(k, pending);
288
+ const stream = ownStream(k, pending);
289
+ if (!reader) {
290
+ if (stream) discard(k, stream);
291
+ return;
292
+ }
293
+ if (stream && result === stream.handle) {
294
+ respond({ ok: true, stream: true });
295
+ const buffered = stream.buffer ?? [];
296
+ stream.buffer = null;
297
+ for (const envelope of buffered) post(instanceId, envelope);
298
+ if (stream.closed && streams.get(k) === stream) streams.delete(k);
299
+ return;
300
+ }
301
+ if (stream) discard(k, stream);
302
+ const returned = result && typeof result === "object" ? handles.get(result) : void 0;
303
+ if (returned) {
304
+ respond({
305
+ ok: false,
306
+ error: { message: "The page stream was closed before it was returned", code: "stream_closed" }
307
+ });
308
+ return;
309
+ }
310
+ respond({ ok: true, result });
311
+ },
312
+ (error) => {
313
+ const reader = settle(k, pending);
314
+ const stream = ownStream(k, pending);
315
+ if (stream) discard(k, stream);
316
+ if (reader) respond({ ok: false, error: pageError(error) });
317
+ }
318
+ );
319
+ }
320
+ function settle(k, pending) {
321
+ if (inFlight.get(k) === pending) inFlight.delete(k);
322
+ const left = lingering.get(k);
323
+ if (left?.delete(pending) && left.size === 0) lingering.delete(k);
324
+ return !pending.abandoned;
325
+ }
326
+ function begin(k) {
327
+ const previous = inFlight.get(k);
328
+ if (previous && !previous.abandoned) {
329
+ abandon(k, previous);
330
+ const stream = ownStream(k, previous);
331
+ if (stream) discard(k, stream);
332
+ }
333
+ const pending = { abandoned: false };
334
+ inFlight.set(k, pending);
335
+ return pending;
336
+ }
337
+ function abandon(k, pending) {
338
+ pending.abandoned = true;
339
+ let left = lingering.get(k);
340
+ if (!left) lingering.set(k, left = /* @__PURE__ */ new Set());
341
+ left.add(pending);
342
+ }
343
+ function ownStream(k, pending) {
344
+ const stream = streams.get(k);
345
+ return stream?.owner === pending ? stream : void 0;
346
+ }
347
+ function manifest() {
348
+ const out = {};
349
+ for (const [id, entry] of exposed) out[id] = [...entry.methods].sort();
350
+ for (const [ns, methods] of namespaces) out[ns] = [...methods.keys()].sort();
351
+ return Object.fromEntries(Object.entries(out).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
352
+ }
353
+ function runCancel(cb) {
354
+ try {
355
+ cb();
356
+ } catch {
357
+ }
358
+ }
359
+ function discard(k, stream) {
360
+ const wasOpen = !stream.closed;
361
+ stream.closed = true;
362
+ stream.buffer = null;
363
+ if (streams.get(k) === stream) streams.delete(k);
364
+ if (!wasOpen || stream.aborted) return;
365
+ stream.aborted = true;
366
+ for (const cb of stream.cancelled.splice(0)) runCancel(cb);
367
+ }
368
+ function cancel(instanceId, sid) {
369
+ if (typeof sid !== "string") return;
370
+ const k = key(instanceId, sid);
371
+ const stream = streams.get(k);
372
+ if (stream) discard(k, stream);
373
+ }
374
+ function forwardConsole(instanceId, msg) {
375
+ const event = {
376
+ instanceId,
377
+ level: typeof msg.level === "string" ? msg.level : "log",
378
+ args: Array.isArray(msg.args) ? msg.args : []
379
+ };
380
+ for (const cb of [...consoleSubscribers]) {
381
+ try {
382
+ cb(event);
383
+ } catch {
384
+ }
385
+ }
386
+ }
387
+ function onLifecycle(rawEnvelope, stamped) {
388
+ let envelope = rawEnvelope;
389
+ if (typeof envelope === "string") {
390
+ try {
391
+ envelope = JSON.parse(envelope);
392
+ } catch {
393
+ return;
394
+ }
395
+ }
396
+ const e = envelope;
397
+ if (!e || typeof e !== "object" || e.v !== 1 || e.sys !== "lifecycle" || typeof e.state !== "string") return;
398
+ const instanceId = typeof stamped === "string" ? stamped : instanceOf(e.iid);
399
+ switch (e.state) {
400
+ // A document start ends any crash pair: a host that restarts a crashed instance this way
401
+ // sends no `reloaded` for it, so the next `reloaded` is a boundary of its own.
402
+ case "mounted":
403
+ live.add(instanceId);
404
+ gone.delete(instanceId);
405
+ crashed.delete(instanceId);
406
+ break;
407
+ case "loaded":
408
+ crashed.delete(instanceId);
409
+ break;
410
+ case "active":
411
+ inactive.delete(instanceId);
412
+ break;
413
+ case "inactive":
414
+ inactive.add(instanceId);
415
+ break;
416
+ // A new document: the old one's streams and pending requests have no reader any more.
417
+ // `crashed` is followed by `reloaded` once the host remounted: one boundary, not two, or the
418
+ // second sweep would hit the NEW document's first requests.
419
+ case "crashed":
420
+ crashed.add(instanceId);
421
+ endDocument(instanceId);
61
422
  break;
423
+ case "reloaded":
424
+ if (!crashed.delete(instanceId)) endDocument(instanceId);
425
+ break;
426
+ case "unmounted":
427
+ unmount(instanceId);
428
+ break;
429
+ }
430
+ const event = { instanceId, state: e.state, ..."detail" in e ? { detail: e.detail } : {} };
431
+ for (const cb of [...lifecycleSubscribers]) {
432
+ try {
433
+ cb(event);
434
+ } catch {
62
435
  }
63
- receiver = candidate;
64
- candidate = candidate[segment];
65
436
  }
66
- if (!capability || !capability.methods.has(request.method) || typeof candidate !== "function") return;
67
- void Promise.resolve().then(() => candidate.apply(receiver, request.args)).then(
68
- (result) => postToPage({ v: 1, id: request.id, ok: true, result }),
69
- (error) => postToPage({ v: 1, id: request.id, ok: false, error: pageError(error) })
437
+ }
438
+ function endDocument(instanceId) {
439
+ for (const stream of [...streams.values()]) {
440
+ if (stream.instanceId === instanceId) cancel(instanceId, stream.sid);
441
+ }
442
+ const prefix = key(instanceId, "");
443
+ for (const [k, pending] of inFlight) {
444
+ if (!k.startsWith(prefix)) continue;
445
+ abandon(k, pending);
446
+ }
447
+ }
448
+ function unmount(instanceId) {
449
+ live.delete(instanceId);
450
+ inactive.delete(instanceId);
451
+ gone.add(instanceId);
452
+ crashed.delete(instanceId);
453
+ endDocument(instanceId);
454
+ }
455
+ return {
456
+ runtime: runtime2,
457
+ get instanceAware() {
458
+ return instanceAware();
459
+ },
460
+ setRawHandler,
461
+ expose,
462
+ addNamespace,
463
+ subscribeLifecycle,
464
+ subscribeConsole,
465
+ post,
466
+ emit,
467
+ openStream
468
+ };
469
+ }
470
+ function resolvePath(module, method) {
471
+ let candidate = module;
472
+ let receiver = void 0;
473
+ for (const segment of method.split(".")) {
474
+ if (!candidate || typeof candidate !== "object" || !Object.prototype.hasOwnProperty.call(candidate, segment)) {
475
+ return {};
476
+ }
477
+ receiver = candidate;
478
+ candidate = candidate[segment];
479
+ }
480
+ return typeof candidate === "function" ? { fn: candidate, receiver } : {};
481
+ }
482
+
483
+ // ../../core/sdk/webview/src/index.ts
484
+ function runtime() {
485
+ const himalaya = globalThis.himalaya;
486
+ if (!himalaya?.webview) {
487
+ throw new Error(
488
+ '@himalaya/webview: called outside a Himalaya runtime, or the host did not install the webview bridge. This binding must run inside a worker-backed webview screen (Tier 5 + webview renderer) with the "webview" capability declared.'
70
489
  );
71
- });
490
+ }
491
+ return himalaya.webview;
492
+ }
493
+ var current;
494
+ function dispatcher() {
495
+ const rt = runtime();
496
+ if (current?.runtime !== rt) current = createPageDispatcher(rt);
497
+ return current;
498
+ }
499
+ if (globalThis.himalaya?.webview) dispatcher();
500
+ function postToPage(msg) {
501
+ runtime().postToPage(msg);
502
+ }
503
+ function onPageMessage(cb) {
504
+ dispatcher().setRawHandler(cb);
505
+ }
506
+ function onPageRequest(namespace, handlers) {
507
+ dispatcher().addNamespace(namespace, handlers);
508
+ }
509
+ function emitToPage(instanceId, event, data) {
510
+ dispatcher().emit(instanceId, event, data);
511
+ }
512
+ function openPageStream(instanceId, requestId) {
513
+ return dispatcher().openStream(instanceId, requestId);
514
+ }
515
+ function onPageLifecycle(cb) {
516
+ return dispatcher().subscribeLifecycle(cb);
517
+ }
518
+ function onPageConsole(cb) {
519
+ return dispatcher().subscribeConsole(cb);
520
+ }
521
+ function exposeCapabilitiesToPage(capabilities) {
522
+ dispatcher().expose(capabilities);
72
523
  }
73
524
  var version = 1;
74
525
  export {
75
526
  PAGE_HANDSHAKE_CAPABILITY,
76
527
  PAGE_HANDSHAKE_METHOD,
528
+ emitToPage,
77
529
  exposeCapabilitiesToPage,
530
+ onPageConsole,
531
+ onPageLifecycle,
78
532
  onPageMessage,
533
+ onPageRequest,
534
+ openPageStream,
79
535
  postToPage,
80
536
  version
81
537
  };