-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
executable file
·102 lines (86 loc) · 2.87 KB
/
index.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
var { build, parse } = require('./src/grammar.js'),
{ evaluate, environment, compile } = require('./src/cekvm.js'),
buildins = require('./src/buildins.js')
// precompile the grammar table
var table = require('!./grammar.loader.js!./src/grammar.js'),
uparse = parse
parse = src => uparse(src, table)
// import
var IMPORT_CACHE = { },
DEPENDENCY_MAP = { }
var checkDependency = (base, child) => {
return DEPENDENCY_MAP[child] && Object.keys(DEPENDENCY_MAP[child]).some(childDep => {
return childDep === base || checkDependency(base, childDep)
})
}
var httpFetch = url =>
fetch(url).then(resp => resp.text()),
fileFetch = path => new Promise((resolve, reject) =>
require('fs').readFile(path, (err, ret) => err ? reject(err) : resolve(ret))),
doFetch = typeof window !== 'undefined' ? httpFetch : fileFetch
var doRequireAsync = (url, root) => new Promise((resolve, reject) => {
doFetch(url).then(text => {
text = [
'doAsync(fn(yield, next)',
'require = url => yield(__asyncRequire(url, next))',
'exports = { }',
text,
'__asyncCallback(exports)',
'end)',
].join('\n')
var tree = parse(text),
code = compile(tree),
env = environment(root)
env('__asyncRequire', makeRequire(url, root))
env('__asyncCallback', resolve)
evaluate(code, env)
}).catch(err => {
console.error(err)
console.error('load module `' + url + '` failed!')
reject(err)
})
})
var doRequireSync = (url, root) => {
var text = require('fs').readFileSync(url),
tree = parse(text),
code = compile(tree),
env = environment(root)
env('require', makeRequire(url, root))
env('exports', { })
evaluate(code, env)
return env('exports')
}
var cononicalPath = require('canonical-path'),
dirName = require('utils-dirname')
var makeRequire = (base, root) => (path, callback) => {
var dir = dirName(base) || '.',
url = cononicalPath.normalize(dir + '/' + path + '.lua')
;(DEPENDENCY_MAP[base] || (DEPENDENCY_MAP[base] = { }))[url] = 1
if (checkDependency(base, url))
throw 'circular dependency found between `' + base + '` and `' + url + '` !'
// use async loader
if (callback !== undefined) {
if (!IMPORT_CACHE[url])
IMPORT_CACHE[url] = doRequireAsync(url, root)
IMPORT_CACHE[url].then(callback)
}
// use sync loader
else {
if (!IMPORT_CACHE[url])
IMPORT_CACHE[url] = doRequireSync(url, root)
return IMPORT_CACHE[url]
}
}
var loaderLib = require('raw!./lib/async.lua')
var execModule = (path, vars, callback) => {
var env = environment(null, buildins)
for (var name in vars)
env(name, vars[name])
evaluate(compile(parse(loaderLib)), env)
makeRequire('.', env)(path, callback)
}
module.exports = {
table, build, parse, compile,
evaluate, environment, buildins,
execModule
}