-
Notifications
You must be signed in to change notification settings - Fork 1
/
link.js
121 lines (109 loc) · 3.84 KB
/
link.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
"use strict";
var mine = require('./mine.js');
var pathJoin = require('./pathjoin.js');
// Given a loader implementation and an initial module, this will walk all dependencies
// and output an object with all the data required to generate a single js file.
module.exports = link;
function link(loader, initial, callback) {
var modules = {}; // compiled modules
var packagePaths = {}; // key is base + name , value is full path
var aliases = {}; // path aliases from the "browser" directive in package.json
resolveModule(".", initial, function (err, newPath) {
if (err) return callback(err);
callback(null, {
initial: newPath,
modules: modules
});
});
function resolvePath(path, callback) {
if (path in aliases) path = aliases[path];
if (path in modules) return callback(null, path);
if (/\.js$/.test(path)) {
return loader(path, false, onJavaScript);
}
if (/\.json$/.test(path)) {
return loader(path, false, onJson);
}
if (/#txt$/.test(path)) {
return loader(path.substr(0, path.length - 4), false, onText);
}
if (/#bin$/.test(path)) {
return loader(path.substr(0, path.length - 4), true, onBinary);
}
return callback(new Error("Invalid path extension: " + path));
function onJavaScript(err, js) {
if (err) return callback(err);
var deps = mine(js);
modules[path] = { type: "javascript", value: js, deps: deps };
next(0);
function next(index) {
var dep = deps[index];
if (!dep) return callback(null, path);
resolveModule(pathJoin(path, '..'), dep.name, function (err, newPath) {
if (err) return callback(err);
dep.newPath = newPath;
next(index + 1);
});
}
}
function onJson(err, json) {
if (json === undefined) return callback(err);
var value;
try { value = JSON.parse(json); }
catch (err) { return callback(err); }
modules[path] = { type: "json", value: value };
callback(null, path);
}
function onText(err, text) {
if (text === undefined) return callback(err);
modules[path] = { type: "text", value: text };
callback(null, path);
}
function onBinary(err, binary) {
if (binary === undefined) return callback(err);
modules[path] = { type: "binary", value: binary };
callback(null, path);
}
}
function resolveModule(base, path, callback) {
if (path[0] === ".") {
return resolvePath(pathJoin(base, path), callback);
}
// non-local requires are assumed to belong to packages
var index = path.indexOf("/");
var name = index < 0 ? path : path.substr(0, index);
return loadPackage(base, name, onPackage);
function onPackage(err, metaPath) {
if (metaPath === undefined) return callback(err);
if (index < 0) path = metaPath;
else path = pathJoin(metaPath, path.substr(index));
return resolvePath(path, callback);
}
}
function loadPackage(base, name, callback) {
var key = pathJoin(base, name);
if (key in packagePaths) return callback(null, packagePaths[key]);
var metaPath = pathJoin(base, "node_modules", name, "package.json");
loader(metaPath, false, function (err, json) {
if (err) return callback(err);
if (!json) {
if (base === "/" || base === ".") return callback();
return loadPackage(pathJoin(base, ".."), name, callback);
}
var meta;
try { meta = JSON.parse(json); }
catch (err) { return callback(err); }
base = pathJoin(metaPath, "..");
packagePaths[key] = base;
if (meta.main) {
aliases[base] = pathJoin(base, meta.main);
}
if (meta.browser) {
for (var original in meta.browser) {
aliases[pathJoin(base, original)] = pathJoin(base, meta.browser[original]);
}
}
callback(null, base);
});
}
}