forked from playcanvas/engine
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
110 lines (90 loc) · 3.46 KB
/
script.js
File metadata and controls
110 lines (90 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import { script } from '../framework/script.js';
/**
* @class
* @name ScriptHandler
* @implements {ResourceHandler}
* @classdesc Resource handler for loading JavaScript files dynamically
* Two types of JavaScript files can be loaded, PlayCanvas scripts which contain calls to {@link createScript},
* or regular JavaScript files, such as third-party libraries.
* @param {Application} app - The running {@link Application}.
*/
class ScriptHandler {
constructor(app) {
this._app = app;
this._scripts = { };
this._cache = { };
}
static _types = [];
static _push(Type) {
if (script.legacy && ScriptHandler._types.length > 0) {
console.assert("Script Ordering Error. Contact [email protected]");
} else {
ScriptHandler._types.push(Type);
}
}
load(url, callback) {
// Scripts don't support bundling since we concatenate them. Below is for consistency.
if (typeof url === 'string') {
url = {
load: url,
original: url
};
}
const self = this;
script.app = this._app;
this._loadScript(url.load, function (err, url, extra) {
if (!err) {
if (script.legacy) {
let Type = null;
// pop the type from the loading stack
if (ScriptHandler._types.length) {
Type = ScriptHandler._types.pop();
}
if (Type) {
// store indexed by URL
this._scripts[url] = Type;
} else {
Type = null;
}
// return the resource
callback(null, Type, extra);
} else {
const obj = { };
for (let i = 0; i < ScriptHandler._types.length; i++)
obj[ScriptHandler._types[i].name] = ScriptHandler._types[i];
ScriptHandler._types.length = 0;
callback(null, obj, extra);
// no cache for scripts
delete self._loader._cache[url + 'script'];
}
} else {
callback(err);
}
}.bind(this));
}
open(url, data) {
return data;
}
patch(asset, assets) { }
_loadScript(url, callback) {
const head = document.head;
const element = document.createElement('script');
this._cache[url] = element;
// use async=false to force scripts to execute in order
element.async = false;
element.addEventListener('error', function (e) {
callback("Script: " + e.target.src + " failed to load");
}, false);
let done = false;
element.onload = element.onreadystatechange = function () {
if (!done && (!this.readyState || (this.readyState === "loaded" || this.readyState === "complete"))) {
done = true; // prevent double event firing
callback(null, url, element);
}
};
// set the src attribute after the onload callback is set, to avoid an instant loading failing to fire the callback
element.src = url;
head.appendChild(element);
}
}
export { ScriptHandler };