Projekt

Obecné

Profil

Stáhnout (6.32 KB) Statistiky
| Větev: | Revize:
1
(function (global, undefined) {
2
    "use strict";
3

    
4
    if (global.setImmediate) {
5
        return;
6
    }
7

    
8
    var nextHandle = 1; // Spec says greater than zero
9
    var tasksByHandle = {};
10
    var currentlyRunningATask = false;
11
    var doc = global.document;
12
    var registerImmediate;
13

    
14
    function setImmediate(callback) {
15
      // Callback can either be a function or a string
16
      if (typeof callback !== "function") {
17
        callback = new Function("" + callback);
18
      }
19
      // Copy function arguments
20
      var args = new Array(arguments.length - 1);
21
      for (var i = 0; i < args.length; i++) {
22
          args[i] = arguments[i + 1];
23
      }
24
      // Store and register the task
25
      var task = { callback: callback, args: args };
26
      tasksByHandle[nextHandle] = task;
27
      registerImmediate(nextHandle);
28
      return nextHandle++;
29
    }
30

    
31
    function clearImmediate(handle) {
32
        delete tasksByHandle[handle];
33
    }
34

    
35
    function run(task) {
36
        var callback = task.callback;
37
        var args = task.args;
38
        switch (args.length) {
39
        case 0:
40
            callback();
41
            break;
42
        case 1:
43
            callback(args[0]);
44
            break;
45
        case 2:
46
            callback(args[0], args[1]);
47
            break;
48
        case 3:
49
            callback(args[0], args[1], args[2]);
50
            break;
51
        default:
52
            callback.apply(undefined, args);
53
            break;
54
        }
55
    }
56

    
57
    function runIfPresent(handle) {
58
        // From the spec: "Wait until any invocations of this algorithm started before this one have completed."
59
        // So if we're currently running a task, we'll need to delay this invocation.
60
        if (currentlyRunningATask) {
61
            // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
62
            // "too much recursion" error.
63
            setTimeout(runIfPresent, 0, handle);
64
        } else {
65
            var task = tasksByHandle[handle];
66
            if (task) {
67
                currentlyRunningATask = true;
68
                try {
69
                    run(task);
70
                } finally {
71
                    clearImmediate(handle);
72
                    currentlyRunningATask = false;
73
                }
74
            }
75
        }
76
    }
77

    
78
    function installNextTickImplementation() {
79
        registerImmediate = function(handle) {
80
            process.nextTick(function () { runIfPresent(handle); });
81
        };
82
    }
83

    
84
    function canUsePostMessage() {
85
        // The test against `importScripts` prevents this implementation from being installed inside a web worker,
86
        // where `global.postMessage` means something completely different and can't be used for this purpose.
87
        if (global.postMessage && !global.importScripts) {
88
            var postMessageIsAsynchronous = true;
89
            var oldOnMessage = global.onmessage;
90
            global.onmessage = function() {
91
                postMessageIsAsynchronous = false;
92
            };
93
            global.postMessage("", "*");
94
            global.onmessage = oldOnMessage;
95
            return postMessageIsAsynchronous;
96
        }
97
    }
98

    
99
    function installPostMessageImplementation() {
100
        // Installs an event handler on `global` for the `message` event: see
101
        // * https://developer.mozilla.org/en/DOM/window.postMessage
102
        // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
103

    
104
        var messagePrefix = "setImmediate$" + Math.random() + "$";
105
        var onGlobalMessage = function(event) {
106
            if (event.source === global &&
107
                typeof event.data === "string" &&
108
                event.data.indexOf(messagePrefix) === 0) {
109
                runIfPresent(+event.data.slice(messagePrefix.length));
110
            }
111
        };
112

    
113
        if (global.addEventListener) {
114
            global.addEventListener("message", onGlobalMessage, false);
115
        } else {
116
            global.attachEvent("onmessage", onGlobalMessage);
117
        }
118

    
119
        registerImmediate = function(handle) {
120
            global.postMessage(messagePrefix + handle, "*");
121
        };
122
    }
123

    
124
    function installMessageChannelImplementation() {
125
        var channel = new MessageChannel();
126
        channel.port1.onmessage = function(event) {
127
            var handle = event.data;
128
            runIfPresent(handle);
129
        };
130

    
131
        registerImmediate = function(handle) {
132
            channel.port2.postMessage(handle);
133
        };
134
    }
135

    
136
    function installReadyStateChangeImplementation() {
137
        var html = doc.documentElement;
138
        registerImmediate = function(handle) {
139
            // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
140
            // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
141
            var script = doc.createElement("script");
142
            script.onreadystatechange = function () {
143
                runIfPresent(handle);
144
                script.onreadystatechange = null;
145
                html.removeChild(script);
146
                script = null;
147
            };
148
            html.appendChild(script);
149
        };
150
    }
151

    
152
    function installSetTimeoutImplementation() {
153
        registerImmediate = function(handle) {
154
            setTimeout(runIfPresent, 0, handle);
155
        };
156
    }
157

    
158
    // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
159
    var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
160
    attachTo = attachTo && attachTo.setTimeout ? attachTo : global;
161

    
162
    // Don't get fooled by e.g. browserify environments.
163
    if ({}.toString.call(global.process) === "[object process]") {
164
        // For Node.js before 0.9
165
        installNextTickImplementation();
166

    
167
    } else if (canUsePostMessage()) {
168
        // For non-IE10 modern browsers
169
        installPostMessageImplementation();
170

    
171
    } else if (global.MessageChannel) {
172
        // For web workers, where supported
173
        installMessageChannelImplementation();
174

    
175
    } else if (doc && "onreadystatechange" in doc.createElement("script")) {
176
        // For IE 6–8
177
        installReadyStateChangeImplementation();
178

    
179
    } else {
180
        // For older browsers
181
        installSetTimeoutImplementation();
182
    }
183

    
184
    attachTo.setImmediate = setImmediate;
185
    attachTo.clearImmediate = clearImmediate;
186
}(typeof self === "undefined" ? typeof global === "undefined" ? this : global : self));
(2-2/2)