html-video-element-webworker-polyfill 0.1.2 → 0.2.1

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
@@ -3,112 +3,135 @@
3
3
  [![CI](https://github.com/stepancar/html-video-element-webworker-polyfill/actions/workflows/ci.yml/badge.svg)](https://github.com/stepancar/html-video-element-webworker-polyfill/actions/workflows/ci.yml)
4
4
  [![npm](https://img.shields.io/npm/v/html-video-element-webworker-polyfill)](https://www.npmjs.com/package/html-video-element-webworker-polyfill)
5
5
 
6
- Create and control an [`HTMLVideoElement`][HTMLVideoElement] from a [Web Worker][Web Workers] and read its decoded
7
- frames there.
8
-
9
- ```ts
10
- const video = document.createElement("video");
11
- video.src = "https://example.com/movie.webm";
12
- video.addEventListener("seeked", () => {
13
- ctx.drawImage(video, 0, 0);
14
- });
15
- video.currentTime = 12.5;
16
- ```
17
-
6
+ [`HTMLVideoElement`][HTMLVideoElement] for [Web Workers][Web Workers].
18
7
  **[Live demo](https://stepancar.github.io/html-video-element-webworker-polyfill/)** ·
19
- **[Open in StackBlitz](https://stackblitz.com/github/stepancar/html-video-element-webworker-polyfill/tree/main/examples/stackblitz?file=worker.js&initialPath=/index.html&startScript=start)**
20
-
21
- ## Why not WebCodecs?
22
-
23
- [WebCodecs][WebCodecs] gives you a decoder, not a player: you demux containers yourself, configure codecs, feed chunks
24
- and find keyframes to seek. [`HTMLVideoElement`][HTMLVideoElement] already handles every format the browser can play
25
- and gives frame-accurate seeking with [`currentTime`][currentTime] and [`seeked`][seeked] out of the box. It just does not exist in workers. This package makes it available there.
26
-
27
- ## Install
8
+ **[npm package](https://www.npmjs.com/package/html-video-element-webworker-polyfill)**
28
9
 
29
10
  ```sh
30
11
  npm install html-video-element-webworker-polyfill
31
12
  ```
32
13
 
33
- ## Usage
14
+ ## 1. Get video frames in a worker and draw them on a canvas
34
15
 
35
- Main thread:
16
+ `main.js`
36
17
 
37
- ```ts
18
+ ```js
38
19
  import { createVideoHost } from "html-video-element-webworker-polyfill/host";
39
20
 
40
- const worker = new Worker(new URL("./worker.ts", import.meta.url), { type: "module" });
21
+ const worker = new Worker("./worker.js", { type: "module" });
41
22
  createVideoHost(worker);
23
+
24
+ const canvas = document.querySelector("canvas").transferControlToOffscreen();
25
+ worker.postMessage({ canvas }, [canvas]);
42
26
  ```
43
27
 
44
- Worker:
28
+ `worker.js`
45
29
 
46
- ```ts
30
+ ```js
47
31
  import { polyfillDocument } from "html-video-element-webworker-polyfill/worker";
48
32
  import { polyfill2dCanvasApi } from "html-video-element-webworker-polyfill/canvas2d";
49
33
 
50
34
  polyfillDocument();
51
35
  polyfill2dCanvasApi();
52
36
 
53
- const ctx = new OffscreenCanvas(640, 360).getContext("2d")!;
54
- const video = document.createElement("video");
55
- video.src = "/movie.webm";
56
- video.addEventListener("loadedmetadata", () => {
57
- video.currentTime = 10;
58
- });
59
- video.addEventListener("seeked", () => {
60
- ctx.drawImage(video, 0, 0, 640, 360);
37
+ self.addEventListener("message", ({ data }) => {
38
+ if (!data.canvas) return;
39
+ const ctx = data.canvas.getContext("2d");
40
+ const video = document.createElement("video");
41
+ video.muted = true;
42
+ video.src = "movie.mp4";
43
+ video.play();
44
+ video.requestVideoFrameCallback(function draw() {
45
+ ctx.drawImage(video, 0, 0, ctx.canvas.width, ctx.canvas.height);
46
+ video.requestVideoFrameCallback(draw);
47
+ });
61
48
  });
62
49
  ```
63
50
 
64
- Or without global patches:
51
+ [Open in StackBlitz][example-process]
52
+
53
+ ## 2. Connect to an existing video and manage it from a worker
54
+
55
+ `index.html`
56
+
57
+ ```html
58
+ <video id="player" src="movie.mp4"></video>
59
+ ```
60
+
61
+ `main.js`
62
+
63
+ ```js
64
+ import { createVideoHost } from "html-video-element-webworker-polyfill/host";
65
+
66
+ createVideoHost(new Worker("./worker.js", { type: "module" }));
67
+ ```
68
+
69
+ `worker.js`
70
+
71
+ ```js
72
+ import { connectToHostVideo } from "html-video-element-webworker-polyfill/worker";
73
+
74
+ const video = await connectToHostVideo("#player");
75
+ video.currentTime = 42;
76
+ ```
77
+
78
+ [Open in StackBlitz][example-manage]
65
79
 
66
- ```ts
67
- import { createVideoElement } from "html-video-element-webworker-polyfill/worker";
80
+ ## 3. React to a video created by the worker and add it to the page
68
81
 
69
- const video = createVideoElement();
70
- video.src = "/movie.webm";
71
- await video.play();
82
+ `main.js`
72
83
 
73
- video.requestVideoFrameCallback(function onFrame() {
74
- render(video.currentFrame);
75
- video.requestVideoFrameCallback(onFrame);
84
+ ```js
85
+ import { createVideoHost } from "html-video-element-webworker-polyfill/host";
86
+
87
+ createVideoHost(new Worker("./worker.js", { type: "module" }), {
88
+ onVideoCreated(video) {
89
+ if (video.id === "preview") document.body.append(video);
90
+ },
76
91
  });
92
+ ```
77
93
 
78
- video.dispose();
94
+ `worker.js`
95
+
96
+ ```js
97
+ import { polyfillDocument } from "html-video-element-webworker-polyfill/worker";
98
+
99
+ polyfillDocument();
100
+
101
+ const video = document.createElement("video");
102
+ video.id = "preview";
103
+ video.muted = true;
104
+ video.src = "movie.mp4";
105
+ video.play();
79
106
  ```
80
107
 
81
- ## API
108
+ [Open in StackBlitz][example-create]
82
109
 
83
- | Import | Exports |
84
- | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
85
- | `html-video-element-webworker-polyfill/host` | `createVideoHost(worker, { container? })` — main thread |
86
- | `html-video-element-webworker-polyfill/worker` | `createVideoElement()`, `WorkerVideoElement`, `polyfillDocument()` — [`document.createElement`][createElement] |
87
- | `html-video-element-webworker-polyfill/canvas2d` | `polyfill2dCanvasApi()` — [`drawImage`][drawImage], [`createPattern`][createPattern] |
88
- | `html-video-element-webworker-polyfill/webgl` | `polyfillWebglAPI()` — [`texImage2D`][texImage2D] and friends, [WebGL][WebGL] 1 and 2 |
89
- | `html-video-element-webworker-polyfill/webgpu` | `polyfillWebgpu()` — [`copyExternalImageToTexture`][copyExternalImageToTexture], [`importExternalTexture`][importExternalTexture] |
90
- | `html-video-element-webworker-polyfill/image-bitmap` | `polyfillCreateImageBitmap()` — [`createImageBitmap`][createImageBitmap], `polyfillVideoFrame()` — [`new VideoFrame`][VideoFrame constructor] |
91
- | `html-video-element-webworker-polyfill/auto` | installs every worker polyfill |
110
+ ## Why not WebCodecs?
92
111
 
93
- Each entry point is tree-shakeable, so you only ship what you import.
112
+ [WebCodecs][WebCodecs] gives you a decoder, not a player: you demux containers yourself, configure codecs, feed chunks
113
+ and find keyframes to seek. `HTMLVideoElement` already handles every format the browser can play and seeks
114
+ frame-accurately. It just does not exist in workers. This package makes it available there.
94
115
 
95
- The worker element implements the [`HTMLVideoElement`][HTMLVideoElement] API: properties, [`play()`][play],
96
- [`pause()`][pause], [`load()`][load], seeking, [media events][media events] and
97
- [`requestVideoFrameCallback`][requestVideoFrameCallback]. It adds two non-standard members:
116
+ ## API
98
117
 
99
- - `currentFrame` — the [`VideoFrame`][VideoFrame] currently on screen, or `null`. It is closed when the next frame
100
- arrives; [`clone()`][clone] it to keep it.
101
- - `dispose()` — releases the element. Unreferenced elements are also released automatically on garbage collection
102
- via [`FinalizationRegistry`][FinalizationRegistry].
118
+ | Import | Exports |
119
+ | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
120
+ | `html-video-element-webworker-polyfill/host` | `createVideoHost(worker, { container?, onVideoCreated?, canConnect? })` — main thread |
121
+ | `html-video-element-webworker-polyfill/worker` | `createVideoElement()`, `connectToHostVideo(selector)`, `polyfillDocument()` ([`document.createElement`][createElement]), `WorkerVideoElement` |
122
+ | `html-video-element-webworker-polyfill/canvas2d` | `polyfill2dCanvasApi()` — [`drawImage`][drawImage], [`createPattern`][createPattern] |
123
+ | `html-video-element-webworker-polyfill/webgl` | `polyfillWebglAPI()` — [`texImage2D`][texImage2D] and friends, [WebGL][WebGL] 1 and 2 |
124
+ | `html-video-element-webworker-polyfill/webgpu` | `polyfillWebgpu()` — [`copyExternalImageToTexture`][copyExternalImageToTexture], [`importExternalTexture`][importExternalTexture] |
125
+ | `html-video-element-webworker-polyfill/image-bitmap` | `polyfillCreateImageBitmap()` — [`createImageBitmap`][createImageBitmap], `polyfillVideoFrame()` — [`new VideoFrame`][VideoFrame constructor] |
126
+ | `html-video-element-webworker-polyfill/auto` | installs every worker polyfill |
103
127
 
104
- Calling a main-thread function in a worker, or a worker function on the main thread, throws an
105
- `InvalidEnvironmentError`.
128
+ The worker element implements the [`HTMLVideoElement`][HTMLVideoElement] API, plus `currentFrame` (the
129
+ [`VideoFrame`][VideoFrame] on screen) and `dispose()`.
106
130
 
107
131
  ## Notes
108
132
 
109
- - Cross-origin media needs [CORS][CORS] ([`crossOrigin`][crossOrigin] `= "anonymous"`), as with drawing a video on a
110
- canvas.
111
- - Frames are decoded on the main thread, so it must not be blocked for long.
133
+ - Cross-origin media needs [CORS][CORS].
134
+ - The package shares the worker's `postMessage` channel with your code, so check your own messages, as in example 1.
112
135
  - Requires [`VideoFrame`][VideoFrame] and [`requestVideoFrameCallback`][requestVideoFrameCallback]: Chrome/Edge 94+,
113
136
  Firefox 132+, Safari 17+.
114
137
 
@@ -116,15 +139,12 @@ Calling a main-thread function in a worker, or a worker function on the main thr
116
139
 
117
140
  Apache-2.0
118
141
 
142
+ [example-process]: https://stackblitz.com/github/stepancar/html-video-element-webworker-polyfill/tree/main/examples/process-frames?file=worker.js&initialPath=/index.html&startScript=start
143
+ [example-manage]: https://stackblitz.com/github/stepancar/html-video-element-webworker-polyfill/tree/main/examples/manage-existing-video?file=worker.js&initialPath=/index.html&startScript=start
144
+ [example-create]: https://stackblitz.com/github/stepancar/html-video-element-webworker-polyfill/tree/main/examples/create-and-mount?file=worker.js&initialPath=/index.html&startScript=start
119
145
  [HTMLVideoElement]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement
120
146
  [Web Workers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API
121
147
  [WebCodecs]: https://developer.mozilla.org/en-US/docs/Web/API/WebCodecs_API
122
- [currentTime]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/currentTime
123
- [seeked]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/seeked_event
124
- [play]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play
125
- [pause]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/pause
126
- [load]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/load
127
- [media events]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement#events
128
148
  [requestVideoFrameCallback]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLVideoElement/requestVideoFrameCallback
129
149
  [createElement]: https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
130
150
  [drawImage]: https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage
@@ -136,7 +156,4 @@ Apache-2.0
136
156
  [createImageBitmap]: https://developer.mozilla.org/en-US/docs/Web/API/Window/createImageBitmap
137
157
  [VideoFrame]: https://developer.mozilla.org/en-US/docs/Web/API/VideoFrame
138
158
  [VideoFrame constructor]: https://developer.mozilla.org/en-US/docs/Web/API/VideoFrame/VideoFrame
139
- [clone]: https://developer.mozilla.org/en-US/docs/Web/API/VideoFrame/clone
140
- [FinalizationRegistry]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry
141
159
  [CORS]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS
142
- [crossOrigin]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/crossOrigin
package/dist/auto.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as installWorkerPolyfills } from "./install-BDVttfHM.js";
1
+ import { t as installWorkerPolyfills } from "./install-BV6rqIiK.js";
2
2
  //#region src/auto.ts
3
3
  installWorkerPolyfills();
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { a as isProtocolMessage, r as MEDIA_EVENTS, t as CHANNEL } from "./protocol-Be-N8xdd.js";
1
+ import { a as isProtocolMessage, r as MEDIA_EVENTS, t as CHANNEL } from "./protocol--LD8Qk5Y.js";
2
2
  import { a as isMessageEndpoint, r as assertWorker } from "./environment-De2r8LaA.js";
3
3
  import { t as FRAME_SOURCE } from "./frame-source-BG--PzqD.js";
4
4
  //#region src/worker/bridge.ts
@@ -7,12 +7,16 @@ var Bridge = class {
7
7
  endpoint;
8
8
  timeOffset = 0;
9
9
  #seq = 0;
10
+ #outbox = [];
11
+ #outboxTransfer = [];
12
+ #flushScheduled = false;
10
13
  #nextId = 1;
11
14
  #nextCallId = 1;
12
15
  #receivers = /* @__PURE__ */ new Map();
13
16
  #pinned = /* @__PURE__ */ new Set();
14
17
  #calls = /* @__PURE__ */ new Map();
15
18
  #canPlayType = /* @__PURE__ */ new Map();
19
+ #ids = /* @__PURE__ */ new Map();
16
20
  #registry;
17
21
  #welcomed = false;
18
22
  #missingHostTimer;
@@ -42,13 +46,31 @@ var Bridge = class {
42
46
  }
43
47
  post(message, transfer = []) {
44
48
  const seq = ++this.#seq;
45
- this.endpoint.postMessage({
49
+ this.#outbox.push({
46
50
  ...message,
47
51
  [CHANNEL]: 1,
48
52
  seq
49
- }, transfer);
53
+ });
54
+ this.#outboxTransfer.push(...transfer);
55
+ if (!this.#flushScheduled) {
56
+ this.#flushScheduled = true;
57
+ queueMicrotask(this.#flush);
58
+ }
50
59
  return seq;
51
60
  }
61
+ #flush = () => {
62
+ this.#flushScheduled = false;
63
+ const messages = this.#outbox;
64
+ const transfer = this.#outboxTransfer;
65
+ this.#outbox = [];
66
+ this.#outboxTransfer = [];
67
+ if (messages.length === 1) this.endpoint.postMessage(messages[0], transfer);
68
+ else if (messages.length > 1) this.endpoint.postMessage({
69
+ [CHANNEL]: 1,
70
+ kind: "batch",
71
+ messages
72
+ }, transfer);
73
+ };
52
74
  call(message, transfer) {
53
75
  const callId = this.#nextCallId++;
54
76
  const promise = new Promise((resolve, reject) => this.#calls.set(callId, {
@@ -72,6 +94,15 @@ var Bridge = class {
72
94
  this.#registry?.unregister(receiver);
73
95
  this.#pinned.delete(element);
74
96
  }
97
+ claimId(id, element) {
98
+ if (id === "") return;
99
+ const owner = this.#ids.get(id)?.deref();
100
+ if (owner && owner !== element && !owner.disposed) throw new DOMException(`html-video-element-webworker-polyfill: a video element with id "${id}" already exists in this worker.`, "InvalidStateError");
101
+ this.#ids.set(id, new WeakRef(element));
102
+ }
103
+ releaseId(id, element) {
104
+ if (this.#ids.get(id)?.deref() === element) this.#ids.delete(id);
105
+ }
75
106
  pin(element, pinned) {
76
107
  if (pinned) this.#pinned.add(element);
77
108
  else this.#pinned.delete(element);
@@ -205,6 +236,7 @@ var WorkerMediaError = class {
205
236
  };
206
237
  //#endregion
207
238
  //#region src/worker/video-element.ts
239
+ const CONNECT = Symbol("connect");
208
240
  const EMPTY_STATE = {
209
241
  currentSrc: "",
210
242
  currentTime: 0,
@@ -223,7 +255,8 @@ const EMPTY_STATE = {
223
255
  buffered: [],
224
256
  played: [],
225
257
  seekable: [],
226
- quality: null
258
+ quality: null,
259
+ props: {}
227
260
  };
228
261
  const LOAD_RESET = {
229
262
  currentTime: 0,
@@ -291,8 +324,18 @@ const ATTRIBUTES = {
291
324
  width: {
292
325
  prop: "width",
293
326
  type: "number"
327
+ },
328
+ id: {
329
+ prop: "id",
330
+ type: "string"
294
331
  }
295
332
  };
333
+ function frameReleaser(holder) {
334
+ return () => {
335
+ holder.current?.close();
336
+ holder.current = null;
337
+ };
338
+ }
296
339
  var Internals = class {
297
340
  element;
298
341
  bridge;
@@ -307,6 +350,7 @@ var Internals = class {
307
350
  disablePictureInPicture: false,
308
351
  disableRemotePlayback: false,
309
352
  height: 0,
353
+ id: "",
310
354
  loop: false,
311
355
  playsInline: false,
312
356
  poster: "",
@@ -324,20 +368,47 @@ var Internals = class {
324
368
  handlers = /* @__PURE__ */ new Map();
325
369
  loadSeq = 0;
326
370
  disposed = false;
327
- constructor(element, bridge) {
371
+ ready;
372
+ constructor(element, bridge, selector) {
328
373
  this.element = element;
329
374
  this.bridge = bridge;
330
375
  this.id = bridge.nextId();
331
- const frame = this.frame;
332
- bridge.register(this.id, element, this, () => {
333
- frame.current?.close();
334
- frame.current = null;
335
- });
336
- bridge.post({
337
- kind: "create",
376
+ bridge.register(this.id, element, this, frameReleaser(this.frame));
377
+ if (selector === void 0) {
378
+ bridge.post({
379
+ kind: "create",
380
+ id: this.id,
381
+ props: {}
382
+ });
383
+ this.ready = Promise.resolve();
384
+ } else this.ready = this.connect(selector);
385
+ }
386
+ async connect(selector) {
387
+ const [seq, result] = this.bridge.call({
388
+ kind: "connect",
338
389
  id: this.id,
339
- props: {}
390
+ selector
340
391
  });
392
+ const connected = await result;
393
+ this.applyState(seq, connected.state);
394
+ if (connected.frame) this.setFrame(connected.frame);
395
+ }
396
+ markProps(seq, ...props) {
397
+ if (!seq) return;
398
+ for (const prop of props) this.localWrites.set(`props.${prop}`, seq);
399
+ }
400
+ applyProps(ack, props) {
401
+ for (const [prop, value] of Object.entries(props)) {
402
+ const key = `props.${prop}`;
403
+ const pending = this.localWrites.get(key);
404
+ if (pending !== void 0) {
405
+ if (pending > ack) continue;
406
+ this.localWrites.delete(key);
407
+ }
408
+ if (prop === "src") this.src = value;
409
+ else if (prop === "hasSrcAttribute") this.hasSrcAttribute = value;
410
+ else if (prop in this.props) this.props[prop] = value;
411
+ }
341
412
  }
342
413
  write(prop, value, local = {}, transfer) {
343
414
  if (this.disposed) return 0;
@@ -379,6 +450,10 @@ var Internals = class {
379
450
  applyState(ack, state) {
380
451
  const target = this.state;
381
452
  for (const [key, value] of Object.entries(state)) {
453
+ if (key === "props") {
454
+ this.applyProps(ack, value);
455
+ continue;
456
+ }
382
457
  const pending = this.localWrites.get(key);
383
458
  if (pending !== void 0) {
384
459
  if (pending > ack) continue;
@@ -480,7 +555,7 @@ var WorkerVideoElement = class extends EventTarget {
480
555
  super();
481
556
  const bridge = bridgeFor(options.transport);
482
557
  bridge.watchForHost();
483
- internals.set(this, new Internals(this, bridge));
558
+ internals.set(this, new Internals(this, bridge, options[CONNECT]));
484
559
  }
485
560
  get currentFrame() {
486
561
  const frame = $(this).frame.current;
@@ -500,6 +575,7 @@ var WorkerVideoElement = class extends EventTarget {
500
575
  core.setFrame(null);
501
576
  core.frameCallbacks.clear();
502
577
  core.bridge.unregister(core.id, core, this);
578
+ core.bridge.releaseId(core.props.id, this);
503
579
  core.state = { ...EMPTY_STATE };
504
580
  core.localWrites.clear();
505
581
  }
@@ -513,11 +589,13 @@ var WorkerVideoElement = class extends EventTarget {
513
589
  const core = $(this);
514
590
  core.src = core.resolveUrl(String(value));
515
591
  core.hasSrcAttribute = true;
516
- core.markLoad(core.write("src", core.src, {
592
+ const seq = core.write("src", core.src, {
517
593
  ...LOAD_RESET,
518
594
  currentSrc: "",
519
595
  networkState: 0
520
- }));
596
+ });
597
+ core.markLoad(seq);
598
+ core.markProps(seq, "src", "hasSrcAttribute");
521
599
  }
522
600
  get srcObject() {
523
601
  return $(this).srcObject;
@@ -657,6 +735,16 @@ var WorkerVideoElement = class extends EventTarget {
657
735
  set disableRemotePlayback(value) {
658
736
  this.#mirror("disableRemotePlayback", Boolean(value));
659
737
  }
738
+ get id() {
739
+ return $(this).props.id;
740
+ }
741
+ set id(value) {
742
+ const core = $(this);
743
+ const id = String(value);
744
+ core.bridge.claimId(id, this);
745
+ if (core.props.id !== id) core.bridge.releaseId(core.props.id, this);
746
+ this.#mirror("id", id);
747
+ }
660
748
  get height() {
661
749
  return $(this).props.height;
662
750
  }
@@ -707,7 +795,7 @@ var WorkerVideoElement = class extends EventTarget {
707
795
  #mirror(prop, value) {
708
796
  const core = $(this);
709
797
  core.props[prop] = value;
710
- core.write(prop, value);
798
+ core.markProps(core.write(prop, value), prop);
711
799
  }
712
800
  getAttribute(name) {
713
801
  const core = $(this);
@@ -745,7 +833,7 @@ var WorkerVideoElement = class extends EventTarget {
745
833
  if (attribute.prop === "src") {
746
834
  core.src = "";
747
835
  core.hasSrcAttribute = false;
748
- core.invoke("removeAttribute", ["src"]);
836
+ core.markProps(core.invoke("removeAttribute", ["src"]), "src", "hasSrcAttribute");
749
837
  return;
750
838
  }
751
839
  const target = this;
@@ -844,6 +932,18 @@ for (const type of MEDIA_EVENTS) Object.defineProperty(WorkerVideoElement.protot
844
932
  function createVideoElement(options) {
845
933
  return new WorkerVideoElement(options);
846
934
  }
935
+ function connectToHostVideo(selector, options = {}) {
936
+ assertWorker("connectToHostVideo()");
937
+ if (typeof selector !== "string" || selector.trim() === "") throw new TypeError("html-video-element-webworker-polyfill: connectToHostVideo() expects a CSS selector string.");
938
+ const video = new WorkerVideoElement({
939
+ ...options,
940
+ [CONNECT]: selector
941
+ });
942
+ return $(video).ready.then(() => video, (error) => {
943
+ video.dispose();
944
+ throw error;
945
+ });
946
+ }
847
947
  //#endregion
848
948
  //#region src/worker/document.ts
849
949
  const PATCHED = Symbol.for("html-video-element-webworker-polyfill.patched");
@@ -874,6 +974,6 @@ function isVideo(tagName) {
874
974
  return String(tagName).toLowerCase() === "video";
875
975
  }
876
976
  //#endregion
877
- export { WorkerTimeRanges as a, WorkerMediaError as i, WorkerVideoElement as n, configureVideoTransport as o, createVideoElement as r, polyfillDocument as t };
977
+ export { WorkerMediaError as a, createVideoElement as i, WorkerVideoElement as n, WorkerTimeRanges as o, connectToHostVideo as r, configureVideoTransport as s, polyfillDocument as t };
878
978
 
879
- //# sourceMappingURL=document-GIe-DKmi.js.map
979
+ //# sourceMappingURL=document-BhePs2Wq.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"document-BhePs2Wq.js","names":[],"sources":["../src/worker/bridge.ts","../src/worker/media-types.ts","../src/worker/video-element.ts","../src/worker/document.ts"],"sourcesContent":["import {\n CHANNEL,\n type CanPlayTypeResult,\n type ClientMessage,\n type HostMessage,\n type MessageEndpoint,\n isProtocolMessage,\n} from \"../shared/protocol.ts\";\nimport { assertWorker, isMessageEndpoint } from \"../shared/environment.ts\";\n\nexport const MISSING_HOST_WARNING_DELAY = 3000;\n\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\nexport type OutgoingMessage = DistributiveOmit<ClientMessage, typeof CHANNEL | \"seq\">;\n\nexport interface ElementReceiver {\n receive(message: Extract<HostMessage, { id: number }>): void;\n}\n\ninterface Finalizable {\n id: number;\n release: () => void;\n}\n\nexport class Bridge {\n readonly endpoint: MessageEndpoint;\n timeOffset = 0;\n\n #seq = 0;\n #outbox: Array<Record<string, unknown>> = [];\n #outboxTransfer: Transferable[] = [];\n #flushScheduled = false;\n #nextId = 1;\n #nextCallId = 1;\n readonly #receivers = new Map<number, WeakRef<ElementReceiver>>();\n readonly #pinned = new Set<object>();\n readonly #calls = new Map<number, { resolve: (value: unknown) => void; reject: (error: unknown) => void }>();\n readonly #canPlayType = new Map<string, CanPlayTypeResult>();\n readonly #ids = new Map<string, WeakRef<{ disposed: boolean }>>();\n readonly #registry: FinalizationRegistry<Finalizable> | null;\n #welcomed = false;\n #missingHostTimer: ReturnType<typeof setTimeout> | undefined;\n\n constructor(endpoint: MessageEndpoint) {\n this.endpoint = endpoint;\n this.#registry =\n typeof FinalizationRegistry === \"function\"\n ? new FinalizationRegistry<Finalizable>(({ id, release }) => {\n release();\n this.#receivers.delete(id);\n this.post({ kind: \"dispose\", id });\n })\n : null;\n endpoint.addEventListener(\"message\", this.#onMessage);\n endpoint.start?.();\n this.post({ kind: \"hello\" });\n }\n\n watchForHost(): void {\n if (this.#welcomed || this.#missingHostTimer !== undefined) return;\n this.#missingHostTimer = setTimeout(() => {\n if (this.#welcomed) return;\n console.warn(\n \"html-video-element-webworker-polyfill: no VideoHost answered this worker. \" +\n \"Call createVideoHost(worker) on the main thread right after creating the worker, otherwise videos never load.\",\n );\n }, MISSING_HOST_WARNING_DELAY);\n }\n\n nextId(): number {\n return this.#nextId++;\n }\n\n post(message: OutgoingMessage, transfer: Transferable[] = []): number {\n const seq = ++this.#seq;\n this.#outbox.push({ ...message, [CHANNEL]: 1, seq });\n this.#outboxTransfer.push(...transfer);\n if (!this.#flushScheduled) {\n this.#flushScheduled = true;\n queueMicrotask(this.#flush);\n }\n return seq;\n }\n\n #flush = (): void => {\n this.#flushScheduled = false;\n const messages = this.#outbox;\n const transfer = this.#outboxTransfer;\n this.#outbox = [];\n this.#outboxTransfer = [];\n if (messages.length === 1) this.endpoint.postMessage(messages[0], transfer);\n else if (messages.length > 1) this.endpoint.postMessage({ [CHANNEL]: 1, kind: \"batch\", messages }, transfer);\n };\n\n call(message: OutgoingMessage & { kind: \"call\" | \"connect\" }, transfer?: Transferable[]): [number, Promise<unknown>] {\n const callId = this.#nextCallId++;\n const promise = new Promise((resolve, reject) => this.#calls.set(callId, { resolve, reject }));\n return [this.post({ ...message, callId }, transfer), promise];\n }\n\n register(id: number, element: object, receiver: ElementReceiver, release: () => void): void {\n this.#receivers.set(id, new WeakRef(receiver));\n this.#registry?.register(element, { id, release }, receiver);\n }\n\n unregister(id: number, receiver: ElementReceiver, element: object): void {\n this.#receivers.delete(id);\n this.#registry?.unregister(receiver);\n this.#pinned.delete(element);\n }\n\n claimId(id: string, element: { disposed: boolean }): void {\n if (id === \"\") return;\n const owner = this.#ids.get(id)?.deref();\n if (owner && owner !== element && !owner.disposed) {\n throw new DOMException(\n `html-video-element-webworker-polyfill: a video element with id \"${id}\" already exists in this worker.`,\n \"InvalidStateError\",\n );\n }\n this.#ids.set(id, new WeakRef(element));\n }\n\n releaseId(id: string, element: object): void {\n if (this.#ids.get(id)?.deref() === element) this.#ids.delete(id);\n }\n\n pin(element: object, pinned: boolean): void {\n if (pinned) this.#pinned.add(element);\n else this.#pinned.delete(element);\n }\n\n canPlayType(type: string): CanPlayTypeResult {\n const cached = this.#canPlayType.get(type);\n if (cached !== undefined) return cached;\n const callId = this.#nextCallId++;\n this.#calls.set(callId, {\n resolve: (value) => this.#canPlayType.set(type, value as CanPlayTypeResult),\n reject: () => {},\n });\n this.post({ kind: \"canPlayType\", type, callId });\n return guessCanPlayType(type);\n }\n\n #onMessage = (event: MessageEvent): void => {\n if (!isProtocolMessage(event.data)) return;\n const message = event.data as HostMessage;\n switch (message.kind) {\n case \"welcome\": {\n this.#welcomed = true;\n clearTimeout(this.#missingHostTimer);\n this.timeOffset = message.timeOrigin - performance.timeOrigin;\n for (const [type, result] of Object.entries(message.canPlayType)) this.#canPlayType.set(type, result);\n return;\n }\n case \"result\": {\n const call = this.#calls.get(message.callId);\n if (!call) return;\n this.#calls.delete(message.callId);\n if (message.error) call.reject(new DOMException(message.error.message, message.error.name));\n else call.resolve(message.value);\n return;\n }\n default: {\n const receiver = this.#receivers.get(message.id)?.deref();\n if (receiver) receiver.receive(message);\n else if (\"frame\" in message) message.frame?.close();\n if (message.kind === \"frame\") this.post({ kind: \"frameAck\", id: message.id });\n }\n }\n };\n}\n\nconst CONTAINER_CODECS: Record<string, string[]> = {\n \"video/webm\": [\"vp8\", \"vp9\", \"av01.0.05M.08\"],\n \"video/mp4\": [\"avc1.42E01E\", \"av01.0.05M.08\", \"hvc1.1.6.L93.B0\", \"vp09.00.10.08\"],\n \"audio/webm\": [\"opus\", \"vorbis\"],\n \"audio/mp4\": [\"mp4a.40.2\", \"opus\", \"flac\"],\n};\n\nfunction guessCanPlayType(type: string): CanPlayTypeResult {\n const MediaSourceCtor = (globalThis as { MediaSource?: { isTypeSupported(type: string): boolean } }).MediaSource;\n if (!MediaSourceCtor) return \"\";\n if (/codecs\\s*=/i.test(type)) return MediaSourceCtor.isTypeSupported(type) ? \"probably\" : \"\";\n if (MediaSourceCtor.isTypeSupported(type)) return \"maybe\";\n const container = type.split(\";\")[0]!.trim().toLowerCase();\n const codecs = CONTAINER_CODECS[container] ?? [];\n return codecs.some((codec) => MediaSourceCtor.isTypeSupported(`${container}; codecs=\"${codec}\"`)) ? \"maybe\" : \"\";\n}\n\nconst bridges = new WeakMap<object, Bridge>();\nlet defaultEndpoint: MessageEndpoint | undefined;\n\nexport function bridgeFor(endpoint: MessageEndpoint | undefined): Bridge {\n const target = endpoint ?? defaultEndpoint ?? (globalThis as unknown as MessageEndpoint);\n if (!isMessageEndpoint(target)) {\n throw new TypeError(\n \"html-video-element-webworker-polyfill: `transport` must be a MessagePort or another object with postMessage/addEventListener/removeEventListener.\",\n );\n }\n let bridge = bridges.get(target);\n if (!bridge) {\n bridge = new Bridge(target);\n bridges.set(target, bridge);\n }\n return bridge;\n}\n\nexport function configureVideoTransport(endpoint: MessageEndpoint): void {\n assertWorker(\"configureVideoTransport()\");\n if (!isMessageEndpoint(endpoint)) {\n throw new TypeError(\n \"html-video-element-webworker-polyfill: configureVideoTransport() expects a MessagePort or another object with postMessage/addEventListener/removeEventListener.\",\n );\n }\n defaultEndpoint = endpoint;\n}\n","import type { Ranges, SerializedMediaError } from \"../shared/protocol.ts\";\n\nexport class WorkerTimeRanges implements TimeRanges {\n readonly #ranges: Ranges;\n\n constructor(ranges: Ranges = []) {\n this.#ranges = ranges;\n }\n\n get length(): number {\n return this.#ranges.length;\n }\n\n start(index: number): number {\n return this.#at(index)[0];\n }\n\n end(index: number): number {\n return this.#at(index)[1];\n }\n\n #at(index: number): [number, number] {\n const range = this.#ranges[index];\n if (!range) {\n throw new DOMException(\n `The index provided (${index}) is greater than or equal to the maximum bound (${this.#ranges.length}).`,\n \"IndexSizeError\",\n );\n }\n return range;\n }\n}\n\nexport class WorkerMediaError implements MediaError {\n static readonly MEDIA_ERR_ABORTED = 1 as const;\n static readonly MEDIA_ERR_NETWORK = 2 as const;\n static readonly MEDIA_ERR_DECODE = 3 as const;\n static readonly MEDIA_ERR_SRC_NOT_SUPPORTED = 4 as const;\n readonly MEDIA_ERR_ABORTED = 1 as const;\n readonly MEDIA_ERR_NETWORK = 2 as const;\n readonly MEDIA_ERR_DECODE = 3 as const;\n readonly MEDIA_ERR_SRC_NOT_SUPPORTED = 4 as const;\n\n readonly code: number;\n readonly message: string;\n\n constructor({ code, message }: SerializedMediaError) {\n this.code = code;\n this.message = message;\n }\n}\n","import { assertWorker } from \"../shared/environment.ts\";\nimport { FRAME_SOURCE } from \"../shared/frame-source.ts\";\nimport {\n type CanPlayTypeResult,\n type ConnectResult,\n type FrameMetadata,\n type HostMessage,\n MEDIA_EVENTS,\n type MediaState,\n type MessageEndpoint,\n} from \"../shared/protocol.ts\";\nimport { type Bridge, type ElementReceiver, bridgeFor } from \"./bridge.ts\";\nimport { WorkerMediaError, WorkerTimeRanges } from \"./media-types.ts\";\n\nconst CONNECT: unique symbol = Symbol(\"connect\") as never;\n\ninterface InternalOptions extends CreateVideoElementOptions {\n [CONNECT]?: string;\n}\n\nexport interface CreateVideoElementOptions {\n transport?: MessageEndpoint;\n}\n\nexport type VideoFrameRequestCallback = (now: number, metadata: FrameMetadata) => void;\n\ntype EventHandler = ((this: WorkerVideoElement, event: Event) => unknown) | null;\n\ninterface MirroredProps {\n autoplay: boolean;\n controls: boolean;\n crossOrigin: string | null;\n defaultMuted: boolean;\n defaultPlaybackRate: number;\n disablePictureInPicture: boolean;\n disableRemotePlayback: boolean;\n height: number;\n id: string;\n loop: boolean;\n playsInline: boolean;\n poster: string;\n preload: \"\" | \"none\" | \"metadata\" | \"auto\";\n preservesPitch: boolean;\n width: number;\n}\n\nconst EMPTY_STATE: MediaState = {\n currentSrc: \"\",\n currentTime: 0,\n duration: Number.NaN,\n ended: false,\n error: null,\n muted: false,\n networkState: 0,\n paused: true,\n playbackRate: 1,\n readyState: 0,\n seeking: false,\n videoHeight: 0,\n videoWidth: 0,\n volume: 1,\n buffered: [],\n played: [],\n seekable: [],\n quality: null,\n props: {},\n};\n\nconst LOAD_RESET: Partial<MediaState> = {\n currentTime: 0,\n duration: Number.NaN,\n ended: false,\n error: null,\n paused: true,\n readyState: 0,\n seeking: false,\n videoHeight: 0,\n videoWidth: 0,\n buffered: [],\n played: [],\n seekable: [],\n};\n\nconst ATTRIBUTES: Record<string, { prop: string; type: \"bool\" | \"string\" | \"number\" | \"nullable\" }> = {\n autoplay: { prop: \"autoplay\", type: \"bool\" },\n controls: { prop: \"controls\", type: \"bool\" },\n crossorigin: { prop: \"crossOrigin\", type: \"nullable\" },\n disablepictureinpicture: { prop: \"disablePictureInPicture\", type: \"bool\" },\n disableremoteplayback: { prop: \"disableRemotePlayback\", type: \"bool\" },\n height: { prop: \"height\", type: \"number\" },\n loop: { prop: \"loop\", type: \"bool\" },\n muted: { prop: \"defaultMuted\", type: \"bool\" },\n playsinline: { prop: \"playsInline\", type: \"bool\" },\n poster: { prop: \"poster\", type: \"string\" },\n preload: { prop: \"preload\", type: \"string\" },\n src: { prop: \"src\", type: \"string\" },\n width: { prop: \"width\", type: \"number\" },\n id: { prop: \"id\", type: \"string\" },\n};\n\nfunction frameReleaser(holder: { current: VideoFrame | null }): () => void {\n return () => {\n holder.current?.close();\n holder.current = null;\n };\n}\n\nclass Internals implements ElementReceiver {\n readonly element: WorkerVideoElement;\n readonly bridge: Bridge;\n readonly id: number;\n state: MediaState = { ...EMPTY_STATE };\n props: MirroredProps = {\n autoplay: false,\n controls: false,\n crossOrigin: null,\n defaultMuted: false,\n defaultPlaybackRate: 1,\n disablePictureInPicture: false,\n disableRemotePlayback: false,\n height: 0,\n id: \"\",\n loop: false,\n playsInline: false,\n poster: \"\",\n preload: \"metadata\",\n preservesPitch: true,\n width: 0,\n };\n src = \"\";\n srcObject: unknown = null;\n hasSrcAttribute = false;\n readonly frame: { current: VideoFrame | null } = { current: null };\n readonly localWrites = new Map<string, number>();\n readonly frameCallbacks = new Map<number, VideoFrameRequestCallback>();\n nextFrameCallbackId = 1;\n readonly handlers = new Map<string, { handler: EventHandler; listener: (event: Event) => void }>();\n loadSeq = 0;\n disposed = false;\n readonly ready: Promise<void>;\n\n constructor(element: WorkerVideoElement, bridge: Bridge, selector?: string) {\n this.element = element;\n this.bridge = bridge;\n this.id = bridge.nextId();\n bridge.register(this.id, element, this, frameReleaser(this.frame));\n if (selector === undefined) {\n bridge.post({ kind: \"create\", id: this.id, props: {} });\n this.ready = Promise.resolve();\n } else {\n this.ready = this.connect(selector);\n }\n }\n\n async connect(selector: string): Promise<void> {\n const [seq, result] = this.bridge.call({ kind: \"connect\", id: this.id, selector });\n const connected = (await result) as ConnectResult;\n this.applyState(seq, connected.state);\n if (connected.frame) this.setFrame(connected.frame);\n }\n\n markProps(seq: number, ...props: string[]): void {\n if (!seq) return;\n for (const prop of props) this.localWrites.set(`props.${prop}`, seq);\n }\n\n applyProps(ack: number, props: Record<string, unknown>): void {\n for (const [prop, value] of Object.entries(props)) {\n const key = `props.${prop}`;\n const pending = this.localWrites.get(key);\n if (pending !== undefined) {\n if (pending > ack) continue;\n this.localWrites.delete(key);\n }\n if (prop === \"src\") this.src = value as string;\n else if (prop === \"hasSrcAttribute\") this.hasSrcAttribute = value as boolean;\n else if (prop in this.props) (this.props as unknown as Record<string, unknown>)[prop] = value;\n }\n }\n\n write(prop: string, value: unknown, local: Partial<MediaState> = {}, transfer?: Transferable[]): number {\n if (this.disposed) return 0;\n const seq = this.bridge.post({ kind: \"set\", id: this.id, prop, value }, transfer);\n this.applyLocal(seq, local);\n return seq;\n }\n\n invoke(\n method: \"pause\" | \"load\" | \"fastSeek\" | \"removeAttribute\",\n args: unknown[],\n local: Partial<MediaState> = {},\n ): number {\n if (this.disposed) return 0;\n const seq = this.bridge.post({ kind: \"call\", id: this.id, method, args });\n this.applyLocal(seq, local);\n return seq;\n }\n\n markLoad(seq: number): void {\n if (seq) this.loadSeq = seq;\n }\n\n applyLocal(seq: number, local: Partial<MediaState>): void {\n for (const [key, value] of Object.entries(local)) {\n (this.state as unknown as Record<string, unknown>)[key] = value;\n this.localWrites.set(key, seq);\n }\n if (\"readyState\" in local && (local.readyState ?? 0) < 2) this.setFrame(null);\n this.updatePin();\n }\n\n updatePin(): void {\n const { paused, seeking, networkState } = this.state;\n this.bridge.pin(this.element, !paused || seeking || networkState === 2);\n }\n\n applyState(ack: number, state: MediaState): void {\n const target = this.state as unknown as Record<string, unknown>;\n for (const [key, value] of Object.entries(state)) {\n if (key === \"props\") {\n this.applyProps(ack, value as Record<string, unknown>);\n continue;\n }\n const pending = this.localWrites.get(key);\n if (pending !== undefined) {\n if (pending > ack) continue;\n this.localWrites.delete(key);\n }\n target[key] = value;\n }\n this.updatePin();\n }\n\n setFrame(frame: VideoFrame | null): void {\n if (this.frame.current === frame) return;\n this.frame.current?.close();\n this.frame.current = frame;\n }\n\n receive(message: Extract<HostMessage, { id: number }>): void {\n if (this.disposed || (message.kind !== \"state\" && message.ack < this.loadSeq)) {\n if (\"frame\" in message) message.frame?.close();\n if (this.disposed) return;\n }\n this.applyState(message.ack, message.state);\n if (message.kind !== \"state\" && message.ack < this.loadSeq) return;\n switch (message.kind) {\n case \"state\":\n return;\n case \"frame\":\n this.setFrame(message.frame);\n this.runFrameCallbacks(message.metadata);\n return;\n case \"event\": {\n if (message.frame) this.setFrame(message.frame);\n else if (message.type === \"emptied\") this.setFrame(null);\n this.element.dispatchEvent(new Event(message.type));\n if (message.frame && message.metadata) this.runFrameCallbacks(message.metadata);\n }\n }\n }\n\n runFrameCallbacks(metadata: FrameMetadata): void {\n if (this.frameCallbacks.size === 0) return;\n const callbacks = [...this.frameCallbacks.values()];\n this.frameCallbacks.clear();\n const offset = this.bridge.timeOffset;\n const local: FrameMetadata = {\n ...metadata,\n presentationTime: metadata.presentationTime + offset,\n expectedDisplayTime: metadata.expectedDisplayTime + offset,\n };\n const now = performance.now();\n for (const callback of callbacks) {\n try {\n callback.call(this.element, now, local);\n } catch (error) {\n reportError(error);\n }\n }\n }\n\n resolveUrl(value: string): string {\n if (value === \"\") return value;\n const base = (globalThis as { location?: { href: string } }).location?.href;\n try {\n return new URL(value, base).href;\n } catch {\n return value;\n }\n }\n}\n\nfunction reportError(error: unknown): void {\n const report = (globalThis as { reportError?: (error: unknown) => void }).reportError;\n if (report) report(error);\n else\n setTimeout(() => {\n throw error;\n });\n}\n\nconst internals = new WeakMap<WorkerVideoElement, Internals>();\n\nfunction $(element: WorkerVideoElement): Internals {\n const value = internals.get(element);\n if (!value) throw new TypeError(\"Illegal invocation\");\n return value;\n}\n\nexport class WorkerVideoElement extends EventTarget {\n static readonly NETWORK_EMPTY = 0 as const;\n static readonly NETWORK_IDLE = 1 as const;\n static readonly NETWORK_LOADING = 2 as const;\n static readonly NETWORK_NO_SOURCE = 3 as const;\n static readonly HAVE_NOTHING = 0 as const;\n static readonly HAVE_METADATA = 1 as const;\n static readonly HAVE_CURRENT_DATA = 2 as const;\n static readonly HAVE_FUTURE_DATA = 3 as const;\n static readonly HAVE_ENOUGH_DATA = 4 as const;\n readonly NETWORK_EMPTY = 0 as const;\n readonly NETWORK_IDLE = 1 as const;\n readonly NETWORK_LOADING = 2 as const;\n readonly NETWORK_NO_SOURCE = 3 as const;\n readonly HAVE_NOTHING = 0 as const;\n readonly HAVE_METADATA = 1 as const;\n readonly HAVE_CURRENT_DATA = 2 as const;\n readonly HAVE_FUTURE_DATA = 3 as const;\n readonly HAVE_ENOUGH_DATA = 4 as const;\n\n readonly tagName = \"VIDEO\" as const;\n readonly nodeName = \"VIDEO\" as const;\n readonly localName = \"video\" as const;\n\n constructor(options: CreateVideoElementOptions = {}) {\n assertWorker(\"createVideoElement()\");\n super();\n const bridge = bridgeFor(options.transport);\n bridge.watchForHost();\n internals.set(this, new Internals(this, bridge, (options as InternalOptions)[CONNECT]));\n }\n\n get currentFrame(): VideoFrame | null {\n const frame = $(this).frame.current;\n return frame && frame.format !== null ? frame : null;\n }\n\n get disposed(): boolean {\n return $(this).disposed;\n }\n\n dispose(): void {\n const core = $(this);\n if (core.disposed) return;\n core.bridge.post({ kind: \"dispose\", id: core.id });\n core.disposed = true;\n core.setFrame(null);\n core.frameCallbacks.clear();\n core.bridge.unregister(core.id, core, this);\n core.bridge.releaseId(core.props.id, this);\n core.state = { ...EMPTY_STATE };\n core.localWrites.clear();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n get src(): string {\n return $(this).src;\n }\n set src(value: string) {\n const core = $(this);\n core.src = core.resolveUrl(String(value));\n core.hasSrcAttribute = true;\n const seq = core.write(\"src\", core.src, { ...LOAD_RESET, currentSrc: \"\", networkState: 0 });\n core.markLoad(seq);\n core.markProps(seq, \"src\", \"hasSrcAttribute\");\n }\n\n get srcObject(): unknown {\n return $(this).srcObject;\n }\n set srcObject(value: unknown) {\n const core = $(this);\n core.srcObject = value ?? null;\n const transfer = value ? [value as Transferable] : [];\n core.markLoad(core.write(\"srcObject\", value ?? null, { ...LOAD_RESET, currentSrc: \"\", networkState: 0 }, transfer));\n }\n\n get currentSrc(): string {\n return $(this).state.currentSrc;\n }\n\n get duration(): number {\n return $(this).state.duration;\n }\n get paused(): boolean {\n return $(this).state.paused;\n }\n get ended(): boolean {\n return $(this).state.ended;\n }\n get seeking(): boolean {\n return $(this).state.seeking;\n }\n get readyState(): number {\n return $(this).state.readyState;\n }\n get networkState(): number {\n return $(this).state.networkState;\n }\n get videoWidth(): number {\n return $(this).state.videoWidth;\n }\n get videoHeight(): number {\n return $(this).state.videoHeight;\n }\n get error(): MediaError | null {\n const error = $(this).state.error;\n return error ? new WorkerMediaError(error) : null;\n }\n get buffered(): TimeRanges {\n return new WorkerTimeRanges($(this).state.buffered);\n }\n get played(): TimeRanges {\n return new WorkerTimeRanges($(this).state.played);\n }\n get seekable(): TimeRanges {\n return new WorkerTimeRanges($(this).state.seekable);\n }\n\n get currentTime(): number {\n return $(this).state.currentTime;\n }\n set currentTime(value: number) {\n const time = Number(value);\n if (!Number.isFinite(time)) {\n throw new TypeError(\"Failed to set the 'currentTime' property: The provided double value is non-finite.\");\n }\n const core = $(this);\n const local: Partial<MediaState> = { currentTime: time, ended: false };\n if (core.state.readyState > 0) local.seeking = true;\n core.write(\"currentTime\", time, local);\n }\n\n fastSeek(time: number): void {\n const core = $(this);\n const local: Partial<MediaState> = { currentTime: time, ended: false };\n if (core.state.readyState > 0) local.seeking = true;\n core.invoke(\"fastSeek\", [time], local);\n }\n\n get volume(): number {\n return $(this).state.volume;\n }\n set volume(value: number) {\n const volume = Number(value);\n if (!(volume >= 0 && volume <= 1)) {\n throw new DOMException(\n `Failed to set the 'volume' property: The volume provided (${value}) is outside the range [0, 1].`,\n \"IndexSizeError\",\n );\n }\n $(this).write(\"volume\", volume, { volume });\n }\n\n get muted(): boolean {\n return $(this).state.muted;\n }\n set muted(value: boolean) {\n $(this).write(\"muted\", Boolean(value), { muted: Boolean(value) });\n }\n\n get playbackRate(): number {\n return $(this).state.playbackRate;\n }\n set playbackRate(value: number) {\n $(this).write(\"playbackRate\", Number(value), { playbackRate: Number(value) });\n }\n\n get autoplay(): boolean {\n return $(this).props.autoplay;\n }\n set autoplay(value: boolean) {\n this.#mirror(\"autoplay\", Boolean(value));\n }\n get controls(): boolean {\n return $(this).props.controls;\n }\n set controls(value: boolean) {\n this.#mirror(\"controls\", Boolean(value));\n }\n get crossOrigin(): string | null {\n return $(this).props.crossOrigin;\n }\n set crossOrigin(value: string | null) {\n this.#mirror(\"crossOrigin\", value === null ? null : String(value));\n }\n get defaultMuted(): boolean {\n return $(this).props.defaultMuted;\n }\n set defaultMuted(value: boolean) {\n this.#mirror(\"defaultMuted\", Boolean(value));\n }\n get defaultPlaybackRate(): number {\n return $(this).props.defaultPlaybackRate;\n }\n set defaultPlaybackRate(value: number) {\n this.#mirror(\"defaultPlaybackRate\", Number(value));\n }\n get disablePictureInPicture(): boolean {\n return $(this).props.disablePictureInPicture;\n }\n set disablePictureInPicture(value: boolean) {\n this.#mirror(\"disablePictureInPicture\", Boolean(value));\n }\n get disableRemotePlayback(): boolean {\n return $(this).props.disableRemotePlayback;\n }\n set disableRemotePlayback(value: boolean) {\n this.#mirror(\"disableRemotePlayback\", Boolean(value));\n }\n get id(): string {\n return $(this).props.id;\n }\n set id(value: string) {\n const core = $(this);\n const id = String(value);\n core.bridge.claimId(id, this);\n if (core.props.id !== id) core.bridge.releaseId(core.props.id, this);\n this.#mirror(\"id\", id);\n }\n\n get height(): number {\n return $(this).props.height;\n }\n set height(value: number) {\n this.#mirror(\"height\", Math.max(0, Math.trunc(Number(value))) || 0);\n }\n get width(): number {\n return $(this).props.width;\n }\n set width(value: number) {\n this.#mirror(\"width\", Math.max(0, Math.trunc(Number(value))) || 0);\n }\n get loop(): boolean {\n return $(this).props.loop;\n }\n set loop(value: boolean) {\n this.#mirror(\"loop\", Boolean(value));\n }\n get playsInline(): boolean {\n return $(this).props.playsInline;\n }\n set playsInline(value: boolean) {\n this.#mirror(\"playsInline\", Boolean(value));\n }\n get poster(): string {\n return $(this).props.poster;\n }\n set poster(value: string) {\n this.#mirror(\"poster\", $(this).resolveUrl(String(value)));\n }\n get preload(): MirroredProps[\"preload\"] {\n return $(this).props.preload;\n }\n set preload(value: MirroredProps[\"preload\"]) {\n const normalized = String(value).toLowerCase();\n this.#mirror(\"preload\", ([\"none\", \"metadata\", \"auto\"].includes(normalized) ? normalized : \"auto\") as never);\n }\n get preservesPitch(): boolean {\n return $(this).props.preservesPitch;\n }\n set preservesPitch(value: boolean) {\n this.#mirror(\"preservesPitch\", Boolean(value));\n }\n\n #mirror<K extends keyof MirroredProps>(prop: K, value: MirroredProps[K]): void {\n const core = $(this);\n core.props[prop] = value;\n core.markProps(core.write(prop, value), prop);\n }\n\n getAttribute(name: string): string | null {\n const core = $(this);\n const attribute = ATTRIBUTES[name.toLowerCase()];\n if (!attribute) return null;\n if (attribute.prop === \"src\") return core.hasSrcAttribute ? core.src : null;\n const value = (this as unknown as Record<string, unknown>)[attribute.prop];\n switch (attribute.type) {\n case \"bool\":\n return value ? \"\" : null;\n case \"nullable\":\n return value === null ? null : String(value);\n default:\n return String(value);\n }\n }\n\n hasAttribute(name: string): boolean {\n return this.getAttribute(name) !== null;\n }\n\n setAttribute(name: string, value: string): void {\n const attribute = ATTRIBUTES[name.toLowerCase()];\n if (!attribute) return;\n const target = this as unknown as Record<string, unknown>;\n switch (attribute.type) {\n case \"bool\":\n target[attribute.prop] = true;\n break;\n case \"number\":\n target[attribute.prop] = Number.parseInt(value, 10) || 0;\n break;\n default:\n target[attribute.prop] = String(value);\n }\n }\n\n removeAttribute(name: string): void {\n const attribute = ATTRIBUTES[name.toLowerCase()];\n if (!attribute) return;\n const core = $(this);\n if (attribute.prop === \"src\") {\n core.src = \"\";\n core.hasSrcAttribute = false;\n core.markProps(core.invoke(\"removeAttribute\", [\"src\"]), \"src\", \"hasSrcAttribute\");\n return;\n }\n const target = this as unknown as Record<string, unknown>;\n switch (attribute.type) {\n case \"bool\":\n target[attribute.prop] = false;\n break;\n case \"nullable\":\n target[attribute.prop] = null;\n break;\n case \"number\":\n target[attribute.prop] = 0;\n break;\n default:\n target[attribute.prop] = attribute.prop === \"preload\" ? \"metadata\" : \"\";\n }\n }\n\n play(): Promise<void> {\n const core = $(this);\n if (core.disposed) {\n return Promise.reject(new DOMException(\"The element has been disposed.\", \"InvalidStateError\"));\n }\n const [seq, promise] = core.bridge.call({ kind: \"call\", id: core.id, method: \"play\", args: [] });\n core.applyLocal(seq, { paused: false });\n return promise as Promise<void>;\n }\n\n pause(): void {\n $(this).invoke(\"pause\", [], { paused: true });\n }\n\n load(): void {\n const core = $(this);\n core.markLoad(core.invoke(\"load\", [], { ...LOAD_RESET, networkState: 0 }));\n }\n\n canPlayType(type: string): CanPlayTypeResult {\n return $(this).bridge.canPlayType(String(type));\n }\n\n getVideoPlaybackQuality(): VideoPlaybackQuality {\n const quality = $(this).state.quality;\n return (quality ?? {\n creationTime: performance.now(),\n droppedVideoFrames: 0,\n totalVideoFrames: 0,\n }) as VideoPlaybackQuality;\n }\n\n requestVideoFrameCallback(callback: VideoFrameRequestCallback): number {\n const core = $(this);\n const handle = core.nextFrameCallbackId++;\n core.frameCallbacks.set(handle, callback);\n return handle;\n }\n\n cancelVideoFrameCallback(handle: number): void {\n $(this).frameCallbacks.delete(handle);\n }\n\n requestPictureInPicture(): Promise<never> {\n return Promise.reject(new DOMException(\"Picture-in-Picture is not available in workers.\", \"NotSupportedError\"));\n }\n}\n\nexport interface WorkerVideoElement {\n [FRAME_SOURCE](): VideoFrame | null;\n onabort: EventHandler;\n oncanplay: EventHandler;\n oncanplaythrough: EventHandler;\n ondurationchange: EventHandler;\n onemptied: EventHandler;\n onencrypted: EventHandler;\n onended: EventHandler;\n onerror: EventHandler;\n onloadeddata: EventHandler;\n onloadedmetadata: EventHandler;\n onloadstart: EventHandler;\n onpause: EventHandler;\n onplay: EventHandler;\n onplaying: EventHandler;\n onprogress: EventHandler;\n onratechange: EventHandler;\n onresize: EventHandler;\n onseeked: EventHandler;\n onseeking: EventHandler;\n onstalled: EventHandler;\n onsuspend: EventHandler;\n ontimeupdate: EventHandler;\n onvolumechange: EventHandler;\n onwaiting: EventHandler;\n onwaitingforkey: EventHandler;\n}\n\nObject.defineProperty(WorkerVideoElement.prototype, FRAME_SOURCE, {\n configurable: true,\n value(this: WorkerVideoElement): VideoFrame | null {\n return this.currentFrame;\n },\n});\n\nfor (const type of MEDIA_EVENTS) {\n Object.defineProperty(WorkerVideoElement.prototype, `on${type}`, {\n configurable: true,\n enumerable: true,\n get(this: WorkerVideoElement): EventHandler {\n return $(this).handlers.get(type)?.handler ?? null;\n },\n set(this: WorkerVideoElement, handler: EventHandler) {\n const core = $(this);\n const existing = core.handlers.get(type);\n if (typeof handler !== \"function\") {\n if (existing) this.removeEventListener(type, existing.listener);\n core.handlers.delete(type);\n return;\n }\n if (existing) {\n existing.handler = handler;\n return;\n }\n const entry = {\n handler,\n listener: (event: Event) => {\n const result = entry.handler?.call(this, event);\n if (result === false) event.preventDefault();\n },\n };\n core.handlers.set(type, entry);\n this.addEventListener(type, entry.listener);\n },\n });\n}\n\nexport function createVideoElement(options?: CreateVideoElementOptions): WorkerVideoElement {\n return new WorkerVideoElement(options);\n}\n\nexport function connectToHostVideo(\n selector: string,\n options: CreateVideoElementOptions = {},\n): Promise<WorkerVideoElement> {\n assertWorker(\"connectToHostVideo()\");\n if (typeof selector !== \"string\" || selector.trim() === \"\") {\n throw new TypeError(\"html-video-element-webworker-polyfill: connectToHostVideo() expects a CSS selector string.\");\n }\n const video = new WorkerVideoElement({ ...options, [CONNECT]: selector } as InternalOptions);\n return $(video).ready.then(\n () => video,\n (error: unknown) => {\n video.dispose();\n throw error;\n },\n );\n}\n","import type { CreateVideoElementOptions } from \"./video-element.ts\";\nimport { WorkerVideoElement } from \"./video-element.ts\";\nimport { WorkerMediaError, WorkerTimeRanges } from \"./media-types.ts\";\nimport { assertWorker } from \"../shared/environment.ts\";\n\nconst PATCHED: unique symbol = Symbol.for(\"html-video-element-webworker-polyfill.patched\") as never;\n\ninterface DocumentLike {\n createElement(tagName: string, options?: unknown): unknown;\n [PATCHED]?: true;\n}\n\nexport function polyfillDocument(options?: CreateVideoElementOptions): void {\n assertWorker(\"polyfillDocument()\");\n const scope = globalThis as Record<string, unknown>;\n scope.HTMLVideoElement ??= WorkerVideoElement;\n scope.HTMLMediaElement ??= WorkerVideoElement;\n scope.MediaError ??= WorkerMediaError;\n scope.TimeRanges ??= WorkerTimeRanges;\n\n const existing = scope.document as DocumentLike | undefined;\n if (existing && typeof existing.createElement === \"function\") {\n if (existing[PATCHED]) return;\n const original = existing.createElement.bind(existing);\n existing.createElement = (tagName: string, elementOptions?: unknown) =>\n isVideo(tagName) ? new WorkerVideoElement(options) : original(tagName, elementOptions);\n existing[PATCHED] = true;\n return;\n }\n\n const document: DocumentLike = {\n createElement(tagName: string): unknown {\n if (isVideo(tagName)) return new WorkerVideoElement(options);\n throw new DOMException(\n `document.createElement(\"${tagName}\") is not supported in a worker; only \"video\" is polyfilled.`,\n \"NotSupportedError\",\n );\n },\n [PATCHED]: true,\n };\n scope.document = document;\n}\n\nfunction isVideo(tagName: string): boolean {\n return String(tagName).toLowerCase() === \"video\";\n}\n"],"mappings":"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"}