webamp 2.1.1 → 2.1.2

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.
@@ -0,0 +1,127 @@
1
+ // A Fork of the NPM module `setimmediate`
2
+ // I've adapted this to only include the browser implementation and to not
3
+ // mutate the global object and instead export the `setImmediate` function.
4
+
5
+ type Handle = { callback: Function; args: any[] };
6
+ type TaskByHandle = { [handle: number]: Handle };
7
+
8
+ let nextHandle = 1; // Spec says greater than zero
9
+ const tasksByHandle: TaskByHandle = {};
10
+ let currentlyRunningATask = false;
11
+ let registerImmediate: (arg0: number) => void;
12
+
13
+ export function setImmediate(callback: Function) {
14
+ // Copy function arguments
15
+ const args = new Array(arguments.length - 1);
16
+ for (let i = 0; i < args.length; i++) {
17
+ args[i] = arguments[i + 1];
18
+ }
19
+ // Store and register the task
20
+ const task = { callback: callback, args: args };
21
+ tasksByHandle[nextHandle] = task;
22
+ registerImmediate(nextHandle);
23
+ return nextHandle++;
24
+ }
25
+
26
+ function clearImmediate(handle: number) {
27
+ delete tasksByHandle[handle];
28
+ }
29
+
30
+ function run(task: Handle) {
31
+ const callback = task.callback;
32
+ const args = task.args;
33
+ switch (args.length) {
34
+ case 0:
35
+ callback();
36
+ break;
37
+ case 1:
38
+ callback(args[0]);
39
+ break;
40
+ case 2:
41
+ callback(args[0], args[1]);
42
+ break;
43
+ case 3:
44
+ callback(args[0], args[1], args[2]);
45
+ break;
46
+ default:
47
+ // eslint-disable-next-line prefer-spread
48
+ callback.apply(undefined, args);
49
+ break;
50
+ }
51
+ }
52
+
53
+ function runIfPresent(handle: number) {
54
+ // From the spec: "Wait until any invocations of this algorithm started before this one have completed."
55
+ // So if we're currently running a task, we'll need to delay this invocation.
56
+ if (currentlyRunningATask) {
57
+ // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
58
+ // "too much recursion" error.
59
+ setTimeout(runIfPresent, 0, handle);
60
+ } else {
61
+ const task = tasksByHandle[handle];
62
+ if (task) {
63
+ currentlyRunningATask = true;
64
+ try {
65
+ run(task);
66
+ } finally {
67
+ clearImmediate(handle);
68
+ currentlyRunningATask = false;
69
+ }
70
+ }
71
+ }
72
+ }
73
+
74
+ function canUsePostMessage() {
75
+ // The test against `importScripts` prevents this implementation from being installed inside a web worker,
76
+ // where `global.postMessage` means something completely different and can't be used for this purpose.
77
+ if (!window.importScripts) {
78
+ let postMessageIsAsynchronous = true;
79
+ const oldOnMessage = window.onmessage;
80
+ window.onmessage = function () {
81
+ postMessageIsAsynchronous = false;
82
+ };
83
+ window.postMessage("", "*");
84
+ window.onmessage = oldOnMessage;
85
+ return postMessageIsAsynchronous;
86
+ }
87
+ }
88
+
89
+ function installPostMessageImplementation() {
90
+ // Installs an event handler on `global` for the `message` event: see
91
+ // * https://developer.mozilla.org/en/DOM/window.postMessage
92
+ // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
93
+
94
+ const messagePrefix = `setImmediate$${Math.random()}$`;
95
+
96
+ window.addEventListener(
97
+ "message",
98
+ (event) => {
99
+ if (
100
+ event.source === window &&
101
+ typeof event.data === "string" &&
102
+ event.data.indexOf(messagePrefix) === 0
103
+ ) {
104
+ runIfPresent(+event.data.slice(messagePrefix.length));
105
+ }
106
+ },
107
+ false
108
+ );
109
+
110
+ registerImmediate = function (handle) {
111
+ window.postMessage(messagePrefix + handle, "*");
112
+ };
113
+ }
114
+
115
+ function installSetTimeoutImplementation() {
116
+ registerImmediate = function (handle) {
117
+ setTimeout(runIfPresent, 0, handle);
118
+ };
119
+ }
120
+
121
+ if (canUsePostMessage()) {
122
+ // For non-IE10 modern browsers
123
+ installPostMessageImplementation();
124
+ } else {
125
+ // For older browsers
126
+ installSetTimeoutImplementation();
127
+ }
package/js/webamp.ts CHANGED
@@ -3,6 +3,24 @@ import * as musicMetadataBrowser from "music-metadata-browser";
3
3
  import { Options } from "./types";
4
4
  import WebampLazy, { PrivateOptions } from "./webampLazy";
5
5
 
6
+ // There is some bug between how JSZip pulls in setimmediate (which it expects
7
+ // to polyfill `window.setimmediate` and our bundler set. The result is that one
8
+ // of our bundles is missing the polyfill. If we call JSZip code from within
9
+ // that bundle the polyfill is not present and we get an error.
10
+ //
11
+ // To work around this we manually import the helper function which is the one
12
+ // place JSZip actually uses `setImmediate` and then set it to use our fork of
13
+ // the polyfill which does not require adding a property to `window`.
14
+ import { setImmediate } from "./setImmediate";
15
+ // @ts-ignore
16
+ import Utils from "jszip/lib/utils";
17
+ // @ts-ignore
18
+ Utils.delay = function (callback, args, self) {
19
+ setImmediate(() => {
20
+ callback.apply(self || null, args || []);
21
+ });
22
+ };
23
+
6
24
  export type * from "./types";
7
25
 
8
26
  export default class Webamp extends WebampLazy {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "webamp",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "description": "Winamp 2 implemented in HTML5 and JavaScript",
5
5
  "files": [
6
6
  "built",