UNPKG

14.4 kBJavaScriptView Raw
1/* Partytown 0.2.1 - MIT builder.io */
2(self => {
3 const ContextKey = Symbol();
4 const MediaSourceKey = Symbol();
5 const ReadyStateKey = Symbol();
6 const SourceBuffersKey = Symbol();
7 const SourceBufferTasksKey = Symbol();
8 const TimeRangesKey = Symbol();
9 const EMPTY_ARRAY = [];
10 const defineCstr = (cstrName, Cstr) => self[cstrName] = defineCstrName(cstrName, Cstr);
11 const defineCstrName = (cstrName, Cstr) => Object.defineProperty(Cstr, "name", {
12 value: cstrName
13 });
14 const [getter, setter, callMethod, constructGlobal, definePrototypePropertyDescriptor, randomId, WorkerProxy, WorkerEventTargetProxy, WinIdKey, InstanceIdKey, ApplyPathKey] = self.ptm;
15 class TimeRanges extends WorkerProxy {
16 start(...args) {
17 return callMethod(this, [ "start" ], args);
18 }
19 end(...args) {
20 return callMethod(this, [ "end" ], args);
21 }
22 get length() {
23 return getter(this, [ "length" ]);
24 }
25 }
26 defineCstr("TimeRanges", TimeRanges);
27 const HTMLMediaDescriptorMap = {
28 buffered: {
29 get() {
30 if (!this[TimeRangesKey]) {
31 this[TimeRangesKey] = new TimeRanges(this[WinIdKey], this[InstanceIdKey], [ "buffered" ]);
32 setTimeout((() => {
33 this[TimeRangesKey] = void 0;
34 }), 5e3);
35 }
36 return this[TimeRangesKey];
37 }
38 },
39 readyState: {
40 get() {
41 if (4 === this[ReadyStateKey]) {
42 return 4;
43 }
44 if ("number" != typeof this[ReadyStateKey]) {
45 this[ReadyStateKey] = getter(this, [ "readyState" ]);
46 setTimeout((() => {
47 this[ReadyStateKey] = void 0;
48 }), 1e3);
49 }
50 return this[ReadyStateKey];
51 }
52 }
53 };
54 definePrototypePropertyDescriptor(self.HTMLMediaElement, HTMLMediaDescriptorMap);
55 var _a;
56 class SourceBufferList extends Array {
57 constructor(mediaSource) {
58 super();
59 this[MediaSourceKey] = mediaSource;
60 }
61 addEventListener(...args) {
62 callMethod(this[MediaSourceKey], [ "sourceBuffers", "addEventListener" ], args, 3);
63 }
64 removeEventListener(...args) {
65 callMethod(this[MediaSourceKey], [ "sourceBuffers", "removeEventListener" ], args, 3);
66 }
67 }
68 class SourceBuffer extends WorkerEventTargetProxy {
69 constructor(mediaSource) {
70 super(mediaSource[WinIdKey], mediaSource[InstanceIdKey], [ "sourceBuffers" ]);
71 this[_a] = [];
72 this[MediaSourceKey] = mediaSource;
73 }
74 abort() {
75 const sbIndex = getSourceBufferIndex(this);
76 callMethod(this, [ sbIndex, "appendWindowStart" ], EMPTY_ARRAY, 1);
77 }
78 addEventListener(...args) {
79 console.log("addEventListener");
80 const sbIndex = getSourceBufferIndex(this);
81 callMethod(this, [ sbIndex, "addEventListener" ], args, 3);
82 }
83 appendBuffer(buf) {
84 this[SourceBufferTasksKey].push([ "appendBuffer", [ buf ], buf ]);
85 drainSourceBufferQueue(this);
86 }
87 get appendWindowStart() {
88 const sbIndex = getSourceBufferIndex(this);
89 return getter(this, [ sbIndex, "appendWindowStart" ]);
90 }
91 set appendWindowStart(value) {
92 const sbIndex = getSourceBufferIndex(this);
93 setter(this, [ sbIndex, "appendWindowStart" ], value);
94 }
95 get appendWindowEnd() {
96 const sbIndex = getSourceBufferIndex(this);
97 return getter(this, [ sbIndex, "appendWindowEnd" ]);
98 }
99 set appendWindowEnd(value) {
100 const sbIndex = getSourceBufferIndex(this);
101 setter(this, [ sbIndex, "appendWindowEnd" ], value);
102 }
103 get buffered() {
104 const mediaSource = this[MediaSourceKey];
105 const sbIndex = getSourceBufferIndex(this);
106 const timeRanges = new TimeRanges(mediaSource[WinIdKey], mediaSource[InstanceIdKey], [ "sourceBuffers", sbIndex, "buffered" ]);
107 return timeRanges;
108 }
109 changeType(mimeType) {
110 const sbIndex = getSourceBufferIndex(this);
111 callMethod(this, [ sbIndex, "changeType" ], [ mimeType ], 2);
112 }
113 get mode() {
114 const sbIndex = getSourceBufferIndex(this);
115 return getter(this, [ sbIndex, "mode" ]);
116 }
117 set mode(value) {
118 const sbIndex = getSourceBufferIndex(this);
119 setter(this, [ sbIndex, "mode" ], value);
120 }
121 remove(start, end) {
122 this[SourceBufferTasksKey].push([ "remove", [ start, end ] ]);
123 drainSourceBufferQueue(this);
124 }
125 removeEventListener(...args) {
126 const sbIndex = getSourceBufferIndex(this);
127 callMethod(this, [ sbIndex, "removeEventListener" ], args, 3);
128 }
129 get timestampOffset() {
130 const sbIndex = getSourceBufferIndex(this);
131 return getter(this, [ sbIndex, "timestampOffset" ]);
132 }
133 set timestampOffset(value) {
134 const sbIndex = getSourceBufferIndex(this);
135 setter(this, [ sbIndex, "timestampOffset" ], value);
136 }
137 get updating() {
138 const sbIndex = getSourceBufferIndex(this);
139 return getter(this, [ sbIndex, "updating" ]);
140 }
141 }
142 _a = SourceBufferTasksKey;
143 const drainSourceBufferQueue = sourceBuffer => {
144 if (sourceBuffer[SourceBufferTasksKey].length) {
145 if (!sourceBuffer.updating) {
146 const task = sourceBuffer[SourceBufferTasksKey].shift();
147 if (task) {
148 const sbIndex = getSourceBufferIndex(sourceBuffer);
149 callMethod(sourceBuffer, [ sbIndex, task[0] ], task[1], 3, void 0, task[2]);
150 }
151 }
152 setTimeout((() => drainSourceBufferQueue(sourceBuffer)), 50);
153 }
154 };
155 const getSourceBufferIndex = sourceBuffer => {
156 if (sourceBuffer) {
157 const mediaSource = sourceBuffer[MediaSourceKey];
158 const sourceBufferList = mediaSource[SourceBuffersKey];
159 return sourceBufferList.indexOf(sourceBuffer);
160 }
161 return -1;
162 };
163 defineCstr("SourceBufferList", SourceBufferList);
164 defineCstr("SourceBuffer", SourceBuffer);
165 const isStaticTypeSupported = new Map;
166 const HTMLVideoDescriptorMap = {
167 currentTime: {
168 get: () => 0
169 },
170 playbackRate: {
171 get: () => 1
172 }
173 };
174 definePrototypePropertyDescriptor(self.HTMLVideoElement, HTMLVideoDescriptorMap);
175 const createContext2D = (canvasInstance, contextType, contextAttributes) => {
176 const winId = canvasInstance[WinIdKey];
177 const ctxInstanceId = randomId();
178 const ctxInstance = {
179 [WinIdKey]: winId,
180 [InstanceIdKey]: ctxInstanceId,
181 [ApplyPathKey]: []
182 };
183 const ctx = callMethod(canvasInstance, [ "getContext" ], [ contextType, contextAttributes ], 1, ctxInstanceId);
184 const CanvasRenderingContext2D = {
185 get: (target, propName) => "string" == typeof propName && propName in ctx ? "function" == typeof ctx[propName] ? (...args) => {
186 if (propName.startsWith("create")) {
187 const instanceId = randomId();
188 callMethod(ctxInstance, [ propName ], args, 2, instanceId);
189 if ("createImageData" === propName || "createPattern" === propName) {
190 (api => {
191 console.warn(`${api} not implemented`);
192 })(`${propName}()`);
193 return {
194 setTransform: () => {}
195 };
196 }
197 return new CanvasGradient(winId, instanceId);
198 }
199 const methodCallType = ctx2dGetterMethods.includes(propName) ? 1 : 2;
200 return callMethod(ctxInstance, [ propName ], args, methodCallType);
201 } : ctx[propName] : target[propName],
202 set(target, propName, value) {
203 if ("string" == typeof propName && propName in ctx) {
204 ctx[propName] !== value && "function" != typeof value && setter(ctxInstance, [ propName ], value);
205 ctx[propName] = value;
206 } else {
207 target[propName] = value;
208 }
209 return true;
210 }
211 };
212 return new Proxy(ctx, CanvasRenderingContext2D);
213 };
214 const CanvasGradient = class {
215 constructor(winId, instanceId) {
216 this[WinIdKey] = winId;
217 this[InstanceIdKey] = instanceId;
218 this[ApplyPathKey] = [];
219 }
220 addColorStop(...args) {
221 callMethod(this, [ "addColorStop" ], args, 2);
222 }
223 };
224 defineCstr("CanvasGradient", CanvasGradient);
225 defineCstr("CanvasPattern", CanvasPattern);
226 const ctx2dGetterMethods = "getContextAttributes,getImageData,getLineDash,getTransform,isPointInPath,isPointInStroke,measureText".split(",");
227 const createContextWebGL = (canvasInstance, contextType, contextAttributes) => {
228 const winId = canvasInstance[WinIdKey];
229 const ctxInstanceId = randomId();
230 const ctxInstance = {
231 [WinIdKey]: winId,
232 [InstanceIdKey]: ctxInstanceId,
233 [ApplyPathKey]: []
234 };
235 const ctx = callMethod(canvasInstance, [ "getContext" ], [ contextType, contextAttributes ], 1, ctxInstanceId);
236 const WebGLRenderingContextHandler = {
237 get: (target, propName) => "string" == typeof propName ? "function" != typeof ctx[propName] ? ctx[propName] : (...args) => callMethod(ctxInstance, [ propName ], args, getWebGlMethodCallType(propName)) : target[propName],
238 set(target, propName, value) {
239 if ("string" == typeof propName && propName in ctx) {
240 ctx[propName] !== value && "function" != typeof value && setter(ctxInstance, [ propName ], value);
241 ctx[propName] = value;
242 } else {
243 target[propName] = value;
244 }
245 return true;
246 }
247 };
248 return new Proxy(ctx, WebGLRenderingContextHandler);
249 };
250 const ctxWebGLGetterMethods = "checkFramebufferStatus,makeXRCompatible".split(",");
251 const getWebGlMethodCallType = methodName => methodName.startsWith("create") || methodName.startsWith("get") || methodName.startsWith("is") || ctxWebGLGetterMethods.includes(methodName) ? 1 : 2;
252 const HTMLCanvasDescriptorMap = {
253 getContext: {
254 value(contextType, contextAttributes) {
255 this[ContextKey] || (this[ContextKey] = (contextType.includes("webgl") ? createContextWebGL : createContext2D)(this, contextType, contextAttributes));
256 return this[ContextKey];
257 }
258 }
259 };
260 definePrototypePropertyDescriptor(self.HTMLCanvasElement, HTMLCanvasDescriptorMap);
261 const MediaCstrs = {
262 Audio: env => defineCstrName("HTMLAudioElement", class {
263 constructor(src) {
264 const audio = env.$document$.createElement("audio");
265 audio.src = src;
266 return audio;
267 }
268 }),
269 MediaSource: (env, win, cstrName) => {
270 const winURL = win.URL = defineCstrName("URL", class extends URL {});
271 winURL.createObjectURL = obj => callMethod(win, [ "URL", "createObjectURL" ], [ obj ]);
272 winURL.revokeObjectURL = obj => callMethod(win, [ "URL", "revokeObjectURL" ], [ obj ]);
273 return defineCstrName(cstrName, class extends WorkerEventTargetProxy {
274 constructor() {
275 super(env.$winId$, randomId());
276 this[SourceBuffersKey] = new SourceBufferList(this);
277 constructGlobal(this, cstrName, EMPTY_ARRAY);
278 }
279 get activeSourceBuffers() {
280 return [];
281 }
282 addSourceBuffer(mimeType) {
283 const sourceBuffer = new SourceBuffer(this);
284 this[SourceBuffersKey].push(sourceBuffer);
285 callMethod(this, [ "addSourceBuffer" ], [ mimeType ]);
286 return sourceBuffer;
287 }
288 clearLiveSeekableRange() {
289 callMethod(this, [ "clearLiveSeekableRange" ], EMPTY_ARRAY, 2);
290 }
291 get duration() {
292 return getter(this, [ "duration" ]);
293 }
294 set duration(value) {
295 setter(this, [ "duration" ], value);
296 }
297 endOfStream(endOfStreamError) {
298 callMethod(this, [ "endOfStream" ], [ endOfStreamError ], 3);
299 }
300 get readyState() {
301 return getter(this, [ "readyState" ]);
302 }
303 removeSourceBuffer(sourceBuffer) {
304 const index = getSourceBufferIndex(sourceBuffer);
305 if (index > -1) {
306 this[SourceBuffersKey].splice(index, 1);
307 callMethod(this, [ "removeSourceBuffer" ], [ index ], 1);
308 }
309 }
310 setLiveSeekableRange(start, end) {
311 callMethod(this, [ "setLiveSeekableRange" ], [ start, end ], 2);
312 }
313 get sourceBuffers() {
314 return this[SourceBuffersKey];
315 }
316 static isTypeSupported(mimeType) {
317 if (!isStaticTypeSupported.has(mimeType)) {
318 const isSupported = callMethod(win, [ cstrName, "isTypeSupported" ], [ mimeType ]);
319 isStaticTypeSupported.set(mimeType, isSupported);
320 }
321 return isStaticTypeSupported.get(mimeType);
322 }
323 });
324 }
325 };
326 self.ptm = MediaCstrs;
327})(self);