forked from ckknight/gorillascript
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathGorkfile
More file actions
373 lines (333 loc) · 12.2 KB
/
Gorkfile
File metadata and controls
373 lines (333 loc) · 12.2 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
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
require! fs
require! './lib/gorilla'
require! path
let {exec} = require 'child_process'
let {string-repeat, pad-left, pad-right} = require './lib/utils'
option \uglify, "u", "Use UglifyJS2 to minify the result"
option \minify, null, "Minimize the use of unnecessary whitespace"
option \file, "f", "Build a specific file", "file"
option \prefix, null, "Path to install to (/usr/local by default)"
//option \js, null, "Compile to JavaScript (default)"
let get-lang(options) -> "js"
command \install, "Install GorillaScript to /usr/local or --prefix", #(options, cb)
async! cb, filename-path <- fs.realpath __filename
let install-path = options.prefix or "/usr/local"
let bin = path.join install-path, "bin"
let files = ["gorilla", "gork", "gjs-gorilla"]
let cmds = [
"mkdir -p $bin"
...for file in files
"ln -sfn $(path.join filename-path, '..', 'bin', file) $bin/$file"
]
exec cmds.join(" && "), #(err, stdout, stderr)
if err
console.error stderr.trim()
else
output "done\n"
cb()
command \build, "Build GorillaScript from source", #(options, cb)
async! cb, filename-path <- fs.realpath __filename
let src-path = path.join(path.dirname(filename-path), "src")
async! cb, mutable files <- fs.readdir src-path
files := for filter file in files
not r'prelude\.gs$'.test(file)
if options.file
let file-filter = options.file.split ","
for file in file-filter
if file not in files
return cb "Cannot build unknown file: $file"
files := for filter file in files
file in file-filter
if files.length == 0
return cb("No files to build")
async! cb <- gorilla.init(lang: get-lang(options))
files.sort #(a, b) -> a.to-lower-case() <=> b.to-lower-case()
let inputs = {}
asyncfor(0) next, file in files
async! cb, text <- fs.read-file path.join(src-path, file), "utf-8"
inputs[file] := text
next()
let longest-name-len = for reduce file in files, current = 0; current max file.length
output string-repeat(" ", longest-name-len)
output " parse macro reduce translate compile $(if options.uglify then ' uglify ' else '')| total\n"
let totals = {}
let mutable total-time = 0
let results = {}
asyncfor err <- next, file in files
let code = inputs[file]
output "$(pad-right file & ':', longest-name-len + 1, ' ') "
let start-file-time = Date.now()
let progress = #(name, time)!
totals[name] := (totals[name] or 0) + time
output " $(pad-left ((time / 1000_ms).to-fixed 3), 6, ' ') s"
async err, compiled <- gorilla.compile code, { extends options, filename: file, progress: progress }
if err?
output "\n"
return next(err)
results[file] := compiled.code
let end-file-time = Date.now()
let file-time = end-file-time - start-file-time
output " | $(pad-left ((file-time / 1000_ms).to-fixed 3), 6, ' ') s\n"
total-time += file-time
gc?()
next()
if err?
return cb(err)
if files.length > 1
output string-repeat "-", longest-name-len + 53
if options.uglify
output string-repeat "-", 10
output "+"
output string-repeat "-", 9
output "\n"
output pad-right "total: ", longest-name-len + 2, ' '
for part in [\parse, \macro-expand, \reduce, \translate, \compile, ...if options.uglify then [\uglify] else []]
output " $(pad-left ((totals[part] / 1000_ms).to-fixed 3), 6, ' ') s"
output " | $(pad-left ((total-time / 1000_ms).to-fixed 3), 6, ' ') s\n"
asyncfor(0) err <- next, file in files
let compiled = results[file]
let output-file = path.join "./lib", file.replace r"\.gs\$", ".js"
async err <- fs.rename output-file, "$(output-file).bak"
if err? and err.code != \ENOENT
return next(err)
async! next <- fs.write-file output-file, compiled, "utf8"
next()
cb(err)
command "build:full", "Build GorillaScript twice and run tests", #(options, cb)
delete options.file
async! cb <- invoke \build
async! cb <- invoke \build
async! cb <- invoke "build:browser"
invoke \test, cb
command "build:browser", "Merge GorillaScript for use in the browser", #(options, cb)
async! cb, filename-path <- fs.realpath __filename
let lib-path = path.join(path.dirname(filename-path), "lib")
let parts = []
asyncfor next, file in ["utils", "jsutils", "types", "jsast", "parser", "jstranslator", "gorilla", "browser"]
async! cb, text <- fs.read-file path.join(lib-path, file & ".js"), "utf8"
parts.push """
require['./$file'] = function () {
var module = { exports: this };
var exports = this;
$(text.split("\n").join("\n "))
return module.exports;
};
"""
next()
async! cb, mutable serialized-prelude <- gorilla.get-serialized-prelude("js")
let mutable deserialized-prelude = JSON.parse serialized-prelude
if options.uglify
for k, v of deserialized-prelude
if is-array! v
for item, i in v
if typeof item.code == \string and item.code.substring(0, 7) == "return "
let mutable minified = require("uglify-js").minify(item.code.substring(7), from-string: true).code
if minified.char-at(0) == "("
minified := "return$minified"
else
minified := "return $minified"
item.code := minified
serialized-prelude := require('./lib/jsutils').to-JS-source deserialized-prelude, null, indent: 2
let mutable code = """
;(function (root) {
var GorillaScript = (function () {
function require(path) {
var has = Object.prototype.hasOwnProperty;
if (has.call(require._cache, path)) {
return require._cache[path];
} else if (has.call(require, path)) {
var func = require[path];
delete require[path];
return require._cache[path] = func.call({});
}
}
require._cache = {};
$(parts.join("\n").split("\n").join("\n "))
require("./browser");
return require("./gorilla").withPrelude("js", $serialized-prelude);
}());
if (typeof define === "function" && define.amd) {
define(function () { return GorillaScript; });
} else {
root.GorillaScript = GorillaScript;
}
}(this));
"""
if options.uglify
output "Built gorillascript.js, uglifying... "
let start-time = new Date().get-time()
code := require("uglify-js").minify(code, from-string: true).code
output "$(((new Date().get-time() - start-time) / 1000_ms).to-fixed 3) s\n"
else
output "Built gorillascript.js\n"
async! cb <- fs.write-file path.join(path.join(path.dirname(filename-path), "extras"), "gorillascript.js"), code, "utf8"
cb()
command \test, "Run the GorillaScript test suite", #(options, cb)
async! cb, filename-path <- fs.realpath __filename
let tests-path = path.join(path.dirname(filename-path), "tests")
async! cb, mutable files <- fs.readdir tests-path
if options.file
let file-filter = options.file.split ","
for file in file-filter
if file not in files
return cb "Cannot build unknown file: $file"
files := for filter file in files
file in file-filter
else
files := for filter file in files
path.extname(file) == ".gs"
if files.length == 0
return cb("No files to test")
require! assert
let sandbox = {}
let mutable passed-tests = 0
let add-sandbox(name, func)
sandbox[name] := #(...args)
let result = func ...args
passed-tests += 1
result
for k of assert
add-sandbox k, assert[k]
let fail = assert.fail
let success = add-sandbox \success, #->
sandbox.eq := sandbox.strict-equal
sandbox.run-once := #(value)
let f = #
if f.ran
fail "called more than once"
f.ran := true
value
f.ran := false
f
sandbox.gorilla := gorilla
let mutable current-file = null
let mutable num-failures = 0
let add-failure(filename, error)!
num-failures += 1
if filename
console.log filename
if error.description
console.log " $(error.description)"
if error.stack
console.log error.stack
else
console.log String(error)
if error.source
console.log error.source
sandbox.test := #(description, fn)!
try
fn.test := {
description
current-file
}
fn@ fn
catch e
try
e.description := description
e.source := fn.to-string()
catch x
void
add-failure fn.test.filename, e
let waiters = [[], []]
let handle-waiters()
let mutable found = true
while found
found := false
for type in waiters
if type.length
found := true
type.splice((Math.random() * type.length) \ 1, 1)[0]()
break
sandbox.async-test := #(description, fn)!
fn.wait := #(get-value as ->, cb as ->)!
waiters[0].push #-> fn.dont-wait(get-value, cb)
fn.after := #(get-value as ->, cb as (null|Function))!
waiters[1].push #-> fn.dont-wait(get-value, cb or #->)
fn.dont-wait := #(get-value as ->, cb as ->)!
let mutable result = void
try
result := get-value()
catch e
cb(e)
else
try
cb(null, result)
catch e
e.description := description
e.source := fn.to-string()
add-failure fn.test.current-file, e
sandbox.test description, fn
let array-equal = #(a, b)
if is-array! a
unless is-array! b and a.length == b.length
false
else
for every item, i in a
array-equal item, b[i]
else
a is b
sandbox.array-eq := #(a, b, msg)
if not array-equal a, b
let {inspect} = require('util')
fail "$(JSON.stringify(a) or 'undefined') != $(JSON.stringify(b) or 'undefined')$(if msg then ': ' & msg else '')"
else
success()
let inputs = {}
asyncfor(0) err <- next, file, i in files
unless r'\.gs$'i.test(file)
return next()
let filename = path.join tests-path, file
async! next, code <- fs.read-file filename, "utf-8"
inputs[file] := {code, filename}
next()
let longest-name-len = for reduce file in files, current = 0; current max file.length
async! cb <- gorilla.init(lang: get-lang(options))
output string-repeat(" ", longest-name-len)
output " parse macro reduce translate compile $(if options.uglify then ' uglify ' else '') eval | total\n"
let mutable total-time = 0
let totals = {}
asyncfor err <- next, file in files
if inputs not ownskey file
return next(new Error("Missing file input for $file"))
let {code, filename} = inputs[file]
let basename = path.basename filename
output "$(pad-right basename & ':', longest-name-len + 1, ' ') "
let start = Date.now()
let mutable failure = false
let start-time = Date.now()
current-file := filename
let progress = #(name, time)
totals[name] := (totals[name] or 0) + time
output " $(pad-left ((time / 1000_ms).to-fixed 3), 6, ' ') s"
async err, result <- gorilla.eval code.to-string(), { extends options, filename, sandbox, include-globals: true, no-prelude: options["no-prelude"], progress }
if err?
output "\n"
failure := true
add-failure basename, err
handle-waiters()
let end-time = Date.now()
total-time += end-time - start-time
output " | $(if failure then 'fail' else 'pass') $(pad-left ((end-time - start-time) / 1000_ms).to-fixed(3), 6, ' ') s\n"
gc?()
next()
throw? err
if files.length > 1
output string-repeat "-", longest-name-len + 63
if options.uglify
output string-repeat "-", 10
output "+"
output string-repeat "-", 14
output "\n"
output pad-right "total: ", longest-name-len + 2, ' '
for part in [\parse, \macro-expand, \reduce, \translate, \compile, ...if options.uglify then [\uglify] else [], \eval]
output " $(pad-left ((totals[part] / 1000_ms).to-fixed 3), 6, ' ') s"
output " | "
output if num-failures == 0 then "pass" else "fail"
output " $(pad-left ((total-time / 1000_ms).to-fixed 3), 6, ' ') s\n"
let message = "passed $passed-tests tests"
if num-failures == 0
console.log message
cb(null)
else
console.log "failed $num-failures"
set-timeout (# -> process.exit(1)), 100