-
Notifications
You must be signed in to change notification settings - Fork 46
/
require1k.js
172 lines (155 loc) · 7.03 KB
/
require1k.js
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*jshint node:false, -W082, -W017 */
R = (function (document, undefined) {
// Each module has the following properties (shorted to one letter to aid compression)
// - g: booleany, loadinG, truthy if this module has been requested for loading
// before. Used to prevent the same module being loaded twice
// - l: string, Location, the url location of this module
// - t: string, Text, the text content of the module
// - e: booleany, Error, truthy if there was an error (probably a 404) loading the module
// - n: module object, Next, instead of using this module, use the object
// pointed to by this property. Used for dependencies in other packages
// - f: function, Factory, a function to use instead of eval'ing module.t
// - exports, object, the exports of the module!
var MODULES = {};
// By using a named "eval" most browsers will execute in the global scope.
// http://www.davidflanagan.com/2010/12/global-eval-in.html
var globalEval = eval;
// this variable is reused for a number of things to reduce the repetition
// of strings. In the end is becomes "exports"
var tmp = "createElement",
baseElement = document[tmp]("base"),
relativeElement = document[tmp]("a");
document.head.appendChild(baseElement);
// Loads the given module and all of it dependencies, recursively
// - module The module object
// - callback Called when everything has been loaded
// - parentLocation Location of the parent directory to look in. Only given
// for non-relative dependencies
// - id The name of the dependency. Only used for non-relative
// dependencies
function deepLoad(module, callback, parentLocation, id) {
// If this module is already loading then don't proceed.
// This is a bug.
// If a module is requested but not loaded then the module isn't ready,
// but we callback as if it is. Oh well, 1k!
if (module.g) {
return callback(module.e, module);
}
var location = module.g = module.l;
var request = new XMLHttpRequest();
request.onload = function (deps, count) {
if (request.status == 200 || module.t) {
// Should really use an object and then Object.keys to avoid
// duplicate dependencies. But that costs bytes.
deps = [];
(module.t = module.t || request.response).replace(/(\/\*[\w\W]*?\*\/|\/\/[^\n]*|[.$]r)|\brequire\s*\(\s*["']([^"']*)["']\s*\)/g, function (_, ignore, id) {
if (!ignore) deps.push(id);
});
count = deps.length;
function loaded() {
// We call loaded straight away below in case there
// are no dependencies. Putting this check first
// and the decrement after saves us an `if` for that
// special case
if (!count--) {
callback(undefined, module);
}
}
deps.map(function (dep) {
deepLoad(
resolveModuleOrGetExports(module.l, dep),
loaded,
// If it doesn't begin with a ".", then we're searching
// node_modules, so pass in the info to make this
// possible
dep[0] != "." ? location + "/../" : undefined,
dep
);
});
loaded();
} else {
// parentLocation is only given if we're searching in node_modules
if (parentLocation) {
// Recurse up the tree trying to find the dependency
// (generating 404s on the way)
deepLoad(
module.n = resolveModuleOrGetExports(parentLocation += "../", id),
callback,
parentLocation,
id
);
} else {
module.e = request;
callback(request, module);
}
}
};
// If the module already has text because we're using a factory
// function, then there's no need to load the file!
if (module.t) {
request.onload();
} else {
request.open("GET", location, true);
request.send();
}
}
// Save bytes by combining two functions
// - resolveModule which resolves a given relative path against the given
// base, and returns an existing or new module object
// - getExports which returns the existing exports or runs the factory to
// create the exports for a module
function resolveModuleOrGetExports(baseOrModule, relative, resolved) {
// This should really be after the relative check, but because we are
// `throw`ing, it messes up the optimizations. If we are being called
// as resolveModule then the string `base` won't have the `e` property,
// so we're fine.
if (baseOrModule.e) {
throw baseOrModule.e;
}
// If 2 arguments are given, then we are resolving modules...
if (relative) {
baseElement.href = baseOrModule;
// If the relative url doesn't begin with a ".", then it's
// in node_modules
relativeElement.href = relative[0] != "." ? "./node_modules/" + relative : relative;
resolved = relativeElement.href + ".js";
baseElement.href = "";
return (MODULES[resolved] = MODULES[resolved] || {l: resolved});
}
// ...otherwise we are getting the exports
// Is this module a redirect to another one?
if (baseOrModule.n) {
return resolveModuleOrGetExports(baseOrModule.n);
}
if (!baseOrModule[tmp]) {
(baseOrModule.f || globalEval("(function(require,"+tmp+",module){" + baseOrModule.t + "\n})//# sourceURL=" + baseOrModule.l))(
function require (id) {
return resolveModuleOrGetExports(resolveModuleOrGetExports(baseOrModule.l, id));
}, // require
baseOrModule[tmp] = {}, // exports
baseOrModule // module
);
}
return baseOrModule[tmp];
}
function R(id, callback) {
// If id has a `call` property it is a function, so make a module with
// a factory
deepLoad(id.call ? {l: "", t: "" + id, f: id} : resolveModuleOrGetExports("", id), function (err, module) {
try {
id = resolveModuleOrGetExports(module);
} catch (_err) {
err = _err
}
if (callback) {
callback(err, id);
}
});
}
tmp = document.querySelector("script[data-main]");
if (tmp) {
R(tmp.dataset.main);
}
tmp = "exports";
return R;
}(document));