2 * Copyright 2013 Mozilla Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 module
.exports = function(grunt
) {
19 var VERSION_BASELINE
= '2bbdb5ce0db7796b';
20 var VERSION_BASE
= '0.11.';
22 // require it at the top and pass in the grunt instance
23 require('time-grunt')(grunt
);
25 // work around a grunt bug where color output is written to non-tty output
26 if (!process
.stdout
.isTTY
) {
27 grunt
.option("color", false);
30 var tscCommand
= 'node ./node_modules/typescript/bin/tsc.js';
31 var commonArguments
= tscCommand
+ ' --target ES5 --sourcemap -d --out build/ts/';
33 var defaultBrowserManifestFile
= './resources/browser_manifests/browser_manifest.json';
34 var defaultTestsManifestFile
= 'test_manifest.json';
36 var parallelArgs
= ['bundle', 'threads', 'sha1', 'rebuild', 'tests', 'bundle',
37 'noPrompts'].filter(function (s
) {
38 return grunt
.option(s
) !== undefined;
40 return '--' + s
+ '=' + grunt
.option(s
);
43 function expandFilePattern(pattern
) {
44 return '"' + grunt
.file
.expand(pattern
).join('" "') + '"'
48 pkg
: grunt
.file
.readJSON('package.json'),
51 configuration
: grunt
.file
.readJSON("tslint.json")
53 all
: ['src/base/**/*.ts', 'src/flash/**/*.ts', 'src/avm2/**/*.ts'] // TODO: Add more directories.
57 cmd
: 'make -C web/ build'
60 cmd
: 'make -C extension/firefox/ build'
63 cmd
: 'make -C extension/mozcentral/ build'
66 cmd
: commonArguments
+ 'base.js src/base/references.ts'
69 cmd
: commonArguments
+ 'tools.js src/tools/references.ts'
72 cmd
: commonArguments
+ 'swf.js src/swf/references.ts'
75 cmd
: commonArguments
+ 'avm2.js src/avm2/references.ts'
78 cmd
: 'make -C test/avm2/'
81 cmd
: commonArguments
+ 'avm1.js src/avm1/references.ts'
84 cmd
: commonArguments
+ 'gfx.js src/gfx/references.ts'
87 cmd
: commonArguments
+ 'gfx-base.js src/gfx/references-base.ts'
90 cmd
: commonArguments
+ 'flash.js src/flash/references.ts'
93 cmd
: commonArguments
+ 'player.js src/player/references.ts'
96 cmd
: tscCommand
+ ' --target ES5 --sourcemap --out build/ts/shell.js src/shell/references.ts'
99 cmd
: 'node build.js -t ' + (+grunt
.option('threads') || 9) +
100 (grunt
.option('sha1') ? ' -s' : '') +
101 (grunt
.option('rebuild') ? ' -r' : ''),
102 cwd
: 'utils/playerglobal-builder'
104 build_playerglobal_single
: {
105 cmd
: 'node single.js',
106 cwd
: 'utils/playerglobal-builder'
109 cmd
: 'node examples/inspector/debug/server.js'
112 cmd
: '"utils/jsshell/js" build/ts/shell.js -x -g ' +
113 (grunt
.option('verbose') ? '-v ' : '') +
114 (grunt
.option('tests') || expandFilePattern('test/perf/pass/*.js'))
117 cmd
: '"utils/jsshell/js" build/ts/shell.js -x -g ' +
118 (grunt
.option('verbose') ? '-v ' : '') +
119 (grunt
.option('tests') || expandFilePattern('test/gfx/pass/*.js'))
124 cmd
: 'find -L build/test -name "*.run" | xargs cat | grep "Not Implemented\\|Uncaught VM-internal\\|FAILED\\|EXCEPTED";'
127 // TODO: Add more files.
128 cmd
: 'node utils/spell/spell.js build/ts/flash.js build/ts/avm2.js'
131 cmd
: 'echo "SUCCESS: no lint errors"'
133 // Run all tests from shumway.txt in one instance of Shumway and save the output in |test/avm2/shumway.run|.
136 cmd
: 'mkdir -p build/test/avm2; ' +
137 'cat test/avm2/shumway.txt | xargs utils/jsshell/js build/ts/shell.js -x -det --printABCFileName > build/test/test_avm2_shumway.run; ' +
138 // Run all tests from shumway.txt each in many instances of Tamarin and save the output in |test/avm2/shumway.baseline|.
139 // Between each run, emit the test name as "::: test :::" so it's easy to identify where things go wrong.
140 'rm test/test_avm2_shumway.baseline; cat test/avm2/shumway.txt | grep -v @ | xargs -L 1 -I \'{}\' sh -c \'echo "::: {} :::" >> test/test_avm2_shumway.baseline; utils/tamarin-redux/bin/shell/avmshell {} >> test/test_avm2_shumway.baseline;\'; ' +
142 'diff test/test_avm2_shumway.baseline build/test/test_avm2_shumway.run'
144 // Runs tamarin acceptance tests and tests against the current baseline. If you get more tests to pass, update the baseline.
145 test_avm2_acceptance
: {
147 cmd
: 'mkdir -p build/test; ' +
148 'utils/jsshell/js build/ts/shell.js -x -det -v test/avm2/acceptance.json | tee build/test/test_avm2_acceptance_stdout.run | node test/avm2/count_totals.js | tee build/test/test_avm2_acceptance.run && ' +
149 'diff test/test_avm2_acceptance.baseline build/test/test_avm2_acceptance.run'
151 // Runs the pypy tests and tests against the current baseline. If you get more tests to pass, update the baseline.
154 cmd
: 'mkdir -p build/test; ' +
155 'find -L test/avm2/pypy -name "*.abc" | xargs -I {} utils/jsshell/js build/ts/shell.js -x -det -v {} | tee build/test/test_avm2_pypy.run &&' +
156 'diff test/test_avm2_pypy.baseline build/test/test_avm2_pypy.run'
158 // Runs archive SWFs and tests against the current baseline. If you get more tests to pass, update the baseline.
159 // TODO: We need to pass the -k flag to parallel to keep the output in the right order, do what once we're ready
160 // to make this part of grunt gate.
163 cmd
: 'mkdir -p build/test/; ' +
164 'find -L test/arch/swfs -name "*.swf" | parallel --gnu -X -N1 utils/jsshell/js build/ts/shell.js -x -det -fc 10 {} | tee build/test_arch.run;' +
165 'echo "Output saved to build/test_arch.run, at some point create a baseline and stick to it."'
166 // 'diff test/arch/arch.baseline build/test/arch/arch.run'
168 // Runs SWFs and tests against the current baseline. If you get more tests to pass, update the baseline.
171 cmd
: 'find -L test/swf -name "*.swf" | parallel -k --gnu -X -N1 utils/jsshell/js build/ts/shell.js -x -det -fc 10 {} | LC_ALL=C sort > build/test/test_swf.run && ' +
172 'diff test/test_swf.baseline build/test/test_swf.run'
174 // Runs SWF trace tests.
177 cmd
: 'node test/trace_test_run.js -j ' + (+grunt
.option('threads') || 6)
179 // Runs SWF (AVM1) swfdec trace tests.
182 cmd
: 'node test/trace_test_run.js -j ' + (+grunt
.option('threads') || 6) +
183 ' -m test/swfdec_test_manifest.json'
187 cmd
: 'mkdir -p build/test; ' +
188 'cat test/ats/test_swf_avm2.txt | parallel -k --gnu -X -N50 utils/jsshell/js build/ts/shell.js -x -det -fc 10 {} > build/test/test_avm2_ats.run; ' +
189 'if [ ! -f "test/test_avm2_ats.baseline" ]; then echo "Creating Baseline"; cp build/test/test_avm2_ats.run test/test_avm2_ats.baseline; fi;' +
190 'diff test/test_avm2_ats.baseline build/test/test_avm2_ats.run;'
192 // Run this to make sure the SWF parser still works.
193 test_avm2_ats_parse
: {
195 cmd
: 'cat test/ats/test_swf_avm2.txt | parallel --gnu -X -N50 utils/jsshell/js build/ts/shell.js -p -v' +
196 (grunt
.option('verbose') ? '-v ' : '') + ' {}'
199 cmd
: '"utils/jsshell/js" build/ts/shell.js -x -g ' +
200 (grunt
.option('verbose') ? '-v ' : '') +
201 (grunt
.option('tests') || expandFilePattern('test/unit/pass/*.js'))
205 cmd
: 'mongo ats --eval \'db.swfs.find({"parse_result.uses_avm1": false}).forEach(function (x) { print("test/ats/swfs/" + x.file); })\' | parallel --gnu -k -X -N10 --timeout 200% utils/jsshell/js build/ts/shell.js -x -det -fc 10 {} | tee test/ats/test_swf_avm2_all.run;'
209 cmd
: 'mongo ats --eval \'db.swfs.find({}).forEach(function (x) { print("test/ats/swfs/" + x.file); })\' | parallel --gnu -k -X -N10 --timeout 200% utils/jsshell/js build/ts/shell.js -x -det -fc 10 {} | tee test/ats/test_swf_all.run;'
213 cmd
: 'mongo ats --eval \'db.swfs.find({"parse_result.file_size":{$lt:204800},ad_result:{$ne:null}}).forEach(function (x) { print("test/ats/swfs/" + x.file); })\' | parallel --gnu -k -X -N10 --timeout 200% utils/jsshell/js build/ts/shell.js -x -det -fc 10 {} | tee test/ats/test_swf_ads.run;'
217 cmd
: 'mkdir -p build/test;' +
218 'utils/jsshell/js build/ts/shell.js -x -det test/mock/jwplayer.js examples/jwplayer/jwplayer.flash.swf -fc 10 > build/test/test_mock.run;' +
219 'diff test/test_mock.baseline build/test/test_mock.run;'
223 cmd
: 'find -L test/avm2/jsbench -name "*.abc" | xargs utils/jsshell/js build/ts/shell.js -x --printABCFileName'
225 perf_avm2_acceptance
: {
227 cmd
: 'utils/jsshell/js build/ts/shell.js -x -det -r --porcelain test/avm2/acceptance.json > /dev/null 2>&1'
229 // Parses all ABCs in the acceptance suite. This is useful to run if you've made changes to the parser.
230 trace_avm2_acceptance_parse
: {
232 cmd
: 'find -L test/avm2/acceptance -name "*.abc" | parallel -k --gnu -X -N50 utils/jsshell/js build/ts/shell.js -d -v {}'
235 cmd
: 'node test/trace_test_run.js -j ' + (+grunt
.option('threads') || 6) +
236 ' -m test/test_manifest_fuzz.json'
239 cmd: function(path
) {
240 var targetPath
= path
.replace(".swf", ".instrumented.swf");
241 console
.info("Instrumenting " + path
+ " (" + targetPath
+ "), this may take a while if the file is large.");
242 return 'swfmill swf2xml ' + path
+ ' | xsltproc utils/instrument-swf.xslt - | swfmill xml2swf stdin ' + targetPath
;
246 cmd
: "make -C utils/ install-js"
248 install_avmshell_travis
: {
249 cmd
: "make -C utils/ install-avmshell"
251 install_swfdec_travis
: {
252 cmd
: "make -C utils/ install-swfdec || echo 'Ignoring the error'"
255 cmd
: "parallel --gnu --version; utils/jsshell/js --version; utils/tamarin-redux/bin/shell/avmshell -Dversion;"
258 cmd
: "npm install mongojs@0.18.1"
261 cmd
: "test -e /tmp/ats.pid || mongod --dbpath test/ats/db --fork --logpath test/ats/db/log --pidfilepath /tmp/ats.pid || rm /tmp/ats.pid"
264 cmd
: "test -e /tmp/ats.pid && kill $(cat /tmp/ats.pid); rm /tmp/ats.pid"
267 cmd
: "parallel --will-cite node run.js --task parse ::: 0 1 2 3 4 5 6 7 8 9 a b c d e f",
271 cmd
: 'make restartless PROFILE="' + (grunt
.option('profile') || '') + '"',
272 cwd
: "extension/firefox"
281 'exec:test_avm2_shumway',
282 'exec:test_avm2_acceptance',
284 'exec:test_avm2_ats',
292 { args
: ['generate-version'], grunt
: true },
293 { args
: ['buildlibs'], grunt
: true },
294 { args
: ['exec:build_base_ts'].concat(parallelArgs
), grunt
: true },
299 { args
: ['exec:build_playerglobal'].concat(parallelArgs
), grunt
: true },
314 { args
: ['exec:build_playerglobal'].concat(parallelArgs
), grunt
: true },
315 { args
: ['exec:build_flash_ts'].concat(parallelArgs
), grunt
: true },
316 { args
: ['exec:build_avm1_ts'].concat(parallelArgs
), grunt
: true }
321 { args
: ['exec:build_avm1_ts'].concat(parallelArgs
), grunt
: true }
326 { args
: ['exec:build_playerglobal'].concat(parallelArgs
), grunt
: true },
327 { args
: ['exec:build_flash_ts'].concat(parallelArgs
), grunt
: true }
333 files
: 'extension/firefox/**/*',
337 files
: 'extension/firefox/**/*',
338 tasks
: ['build-extension']
341 files
: 'src/base/**/*',
342 tasks
: ['exec:build_base_ts']
345 files
: ['src/flash/**/*.as',
346 'utils/playerglobal-builder/manifest.json'],
347 tasks
: ['exec:build_playerglobal']
350 files
: ['src/swf/**/*.ts'],
351 tasks
: ['exec:build_swf_ts']
354 files
: ['src/avm2/**/*.ts',
355 'src/flash/**/*.ts'],
356 tasks
: ['exec:build_flash_ts']
359 files
: ['src/gfx/**/*.ts'],
360 tasks
: ['exec:build_gfx_base_ts']
363 files
: ['src/gfx/**/*.ts'],
364 tasks
: ['exec:build_gfx_ts']
367 files
: ['src/avm2/**/*.ts'],
368 tasks
: ['exec:build_avm2_ts']
371 files
: ['src/avm1/*.ts'],
372 tasks
: ['exec:build_avm1_ts']
375 files
: ['src/flash/**/*.ts',
376 'src/player/**/*.ts'],
377 tasks
: ['exec:build_player_ts']
380 files
: ['src/tools/**/*.ts'],
381 tasks
: ['exec:build_tools_ts']
386 grunt
.loadNpmTasks('grunt-tslint');
387 grunt
.loadNpmTasks('grunt-contrib-watch');
388 grunt
.loadNpmTasks('grunt-exec');
389 grunt
.loadNpmTasks('grunt-parallel');
391 grunt
.registerTask('lint', ['tslint:all', 'exec:lint_success']);
393 grunt
.registerTask('update-refs', function () {
394 var updateRefs
= require('./utils/update-flash-refs.js').updateRefs
;
395 updateRefs('examples/inspector/inspector.gfx.html', {gfx
: true});
396 updateRefs('examples/xlsimport/index.html', {gfx
: true, player
: true});
397 updateRefs('examples/inspector/inspector.player.html', {player
: true});
398 updateRefs('src/shell/shell.ts', {player
: true, onlyIncludes
: true});
400 grunt
.registerTask('update-flash-refs', ['update-refs']); // TODO deprecated
402 grunt
.registerTask('buildlibs', function() {
403 var outputDir
= 'build/libs/';
404 grunt
.file
.mkdir(outputDir
);
405 var done
= this.async();
406 var buildLibs
= require('./src/libs/buildlibs.js').buildLibs
;
407 buildLibs(outputDir
, false, null, function () {
411 grunt
.registerTask('copy_relooper', function() {
412 grunt
.file
.copy('src/avm2/compiler/relooper/relooper.js', 'build/libs/relooper.js');
414 grunt
.registerTask('bundles', function () {
415 var outputDir
= 'build/bundles/';
416 grunt
.file
.mkdir(outputDir
);
417 var packageRefs
= require('./utils/update-flash-refs.js').packageRefs
;
418 var license
= grunt
.file
.read('./src/license.js');
419 packageRefs(['gfx'], outputDir
+ 'shumway.gfx.js', license
);
420 packageRefs(['player'], outputDir
+ 'shumway.player.js', license
);
423 grunt
.registerTask('merge-modules', function () {
424 mergeModules("build/bundles/shumway.player.js");
425 mergeModules("build/bundles/shumway.gfx.js");
428 function mergeModules(path
) {
429 var mergeModules
= require('typescript-module-merger').mergeModulesInFile
;
430 grunt
.file
.write(path
, mergeModules(path
, !!grunt
.option('verbose')));
433 function runClosure(jsFiles
, output
, warnings
, done
) {
434 // This needs a special build of closure that has SHUMWAY_OPTIMIZATIONS.
435 var closureCmd
= 'java';
436 var closureArgs
= ['-jar', 'utils/closure.jar',
437 '--define', 'release=true',
438 '--compilation_level', 'SHUMWAY_OPTIMIZATIONS',
439 '--language_in', 'ECMASCRIPT5'];
441 closureArgs
.push('--warning_level', 'QUIET');
443 closureArgs
= closureArgs
.concat(jsFiles
).concat(['--js_output_file', output
]);
444 console
.log('Running closure for ' + jsFiles
.join(', ') + ' ...');
448 opts
: { stdio
: 'inherit' }
449 }, function (error
, result
) {
450 if (error
|| result
.code
) {
454 console
.log('Closure output is created at ' + output
);
459 function runClosureTasks(tasks
, warnings
, done
) {
461 (function runNextTask() {
462 if (i
< tasks
.length
) {
463 var task
= tasks
[i
++];
464 runClosure([task
[0]], task
[1], warnings
, function (success
) {
477 grunt
.registerTask('ensure-build-folder', function() {
478 grunt
.file
.mkdir('build');
481 grunt
.registerTask('ensure-test-folder', function() {
482 grunt
.file
.mkdir('build/test');
485 grunt
.registerTask('closure-bundles', function () {
486 var inputDir
= 'build/bundles/';
487 var outputDir
= 'build/bundles-cc/';
488 grunt
.file
.mkdir(outputDir
);
491 [inputDir
+ 'shumway.gfx.js', outputDir
+ 'shumway.gfx.js'],
492 [inputDir
+ 'shumway.player.js', outputDir
+ 'shumway.player.js']
493 ], !!grunt
.option('verbose'), this.async());
496 grunt
.registerTask('closure', function () {
503 "build/ts/gfx-base.js",
506 ], "build/shumway.cc.js", true, this.async());
509 grunt
.registerTask('closure-all', function () {
510 var outputDir
= 'build/ts-cc/';
511 grunt
.file
.mkdir(outputDir
);
513 ["build/ts/base.js", outputDir
+ "base.js"],
514 ["build/ts/tools.js", outputDir
+ "tools.js"],
515 ["build/ts/avm2.js", outputDir
+ "avm2.js"],
516 ["build/ts/flash.js", outputDir
+ "flash.js"],
517 ["build/ts/avm1.js", outputDir
+ "avm1.js"],
518 ["build/ts/gfx-base.js", outputDir
+ "gfx-base.js"],
519 ["build/ts/gfx.js", outputDir
+ "gfx.js"],
520 ["build/ts/player.js", outputDir
+ "player.js"]
521 ], true, this.async());
524 grunt
.registerTask('server', function () {
525 function isLogFileRequest(path
) {
526 if (path
.indexOf('/logs/') !== 0) {
529 return /^\/logs\/\w+\.(txt|log)$/i.test(path
);
531 grunt
.file
.mkdir('build/logs/');
532 var WebServer
= require('./test/webserver.js').WebServer
;
533 var done
= this.async();
534 var server
= new WebServer();
535 if (grunt
.option('host')) {
536 server
.host
= grunt
.option('host');
538 if (grunt
.option('port')) {
539 server
.port
= +grunt
.option('port');
541 if (grunt
.option('port_ssl')) {
542 server
.port_ssl
= +grunt
.option('port_ssl');
544 var url
= require('url'), fs
= require('fs');
545 server
.hooks
['POST'].push(function (req
, res
) {
546 var parsedUrl
= url
.parse(req
.url
, true);
547 var pathname
= parsedUrl
.pathname
;
548 if (!isLogFileRequest(pathname
)) {
551 var filename
= 'build' + pathname
;
553 req
.on('data', function (data
) {
556 req
.on('end', function () {
557 fs
.appendFile(filename
, body
, function () {
558 res
.writeHead(204, {'Content-Type': 'text/plain'});
564 server
.hooks
['DELETE'].push(function (req
, res
) {
565 var parsedUrl
= url
.parse(req
.url
, true);
566 var pathname
= parsedUrl
.pathname
;
567 if (!isLogFileRequest(pathname
)) {
570 var filename
= 'build' + pathname
;
571 fs
.unlink(filename
, function () {
572 res
.writeHead(204, {'Content-Type': 'text/plain'});
580 grunt
.registerTask('reftest', function () {
581 if (grunt
.file
.exists('test/tmp')) {
582 throw new Error('The test/tmp/ folder exists from the previous makeref attempt. ' +
583 'You may want to copy those images to test/refs/. Remove test/tmp/ to proceed with reftest.')
585 if (!grunt
.option('browserManifestFile') && !grunt
.file
.exists('test', defaultBrowserManifestFile
)) {
586 throw new Error('Browser manifest file is not found at test/' + defaultBrowserManifestFile
+ '. Create one using the examples at test/resources/browser_manifests/.');
588 var browserManifestFile
= grunt
.option('browserManifestFile') || defaultBrowserManifestFile
;
589 var testManifestFile
= grunt
.option('manifestFile') || defaultTestsManifestFile
;
590 var done
= this.async();
592 if (grunt
.option('extension')) {
593 params
.push('--extension');
595 if (grunt
.option('noPrompts')) {
596 params
.push('--noPrompts');
600 args
: ['test.js', '--reftest', '--browserManifestFile=' + browserManifestFile
,
601 '--manifestFile=' + testManifestFile
].concat(params
),
602 opts
: { cwd
: 'test', stdio
: 'inherit' }
608 grunt
.registerTask('reftest-extension', function () {
609 grunt
.option('extension', true);
610 grunt
.task
.run('firefox', 'reftest');
613 grunt
.registerTask('reftest-swfdec', function () {
614 if (grunt
.file
.exists('test/tmp')) {
615 throw new Error('The test/tmp/ folder exists from the previous makeref attempt. ' +
616 'You may want to copy those images to test/refs/. Remove test/tmp/ to proceed with reftest.')
618 if (!grunt
.option('browserManifestFile') && !grunt
.file
.exists('test', defaultBrowserManifestFile
)) {
619 throw new Error('Browser manifest file is not found at test/' + defaultBrowserManifestFile
+ '. Create one using the examples at test/resources/browser_manifests/.');
621 var browserManifestFile
= grunt
.option('browserManifestFile') || defaultBrowserManifestFile
;
622 var testManifestFile
= 'swfdec_reftest_manifest.json';
623 var done
= this.async();
625 if (grunt
.option('extension')) {
626 params
.push('--extension');
628 if (grunt
.option('noPrompts')) {
629 params
.push('--noPrompts');
633 args
: ['test.js', '--browserManifestFile=' + browserManifestFile
,
634 '--manifestFile=' + testManifestFile
].concat(params
),
635 opts
: { cwd
: 'test', stdio
: 'inherit' }
641 grunt
.registerTask('makeref', function () {
642 if (!grunt
.option('browserManifestFile') && !grunt
.file
.exists('test', defaultBrowserManifestFile
)) {
643 throw new Error('Browser manifest file is not found at test/' + defaultBrowserManifestFile
+ '. Create one using the examples at test/resources/browser_manifests/.');
645 var browserManifestFile
= grunt
.option('browserManifestFile') || defaultBrowserManifestFile
;
646 var done
= this.async();
648 if (grunt
.option('extension')) {
649 params
.push('--extension');
651 if (grunt
.option('noPrompts')) {
652 params
.push('--noPrompts');
656 args
: ['test.js', '-m', '--browserManifestFile=' + browserManifestFile
].concat(params
),
657 opts
: { cwd
: 'test', stdio
: 'inherit'}}, function () {
662 grunt
.registerTask('shell-package', function () {
663 var outputDir
= 'build/shell';
664 grunt
.file
.mkdir(outputDir
);
665 var path
= require('path');
667 grunt
.file
.copy('build/libs/builtin.abc', outputDir
+ '/build/libs/builtin.abc');
668 grunt
.file
.copy('build/libs/shell.abc', outputDir
+ '/build/libs/shell.abc');
669 grunt
.file
.copy('build/playerglobal/playerglobal.abcs', outputDir
+ '/build/playerglobal/playerglobal.abcs');
670 grunt
.file
.copy('build/playerglobal/playerglobal.json', outputDir
+ '/build/playerglobal/playerglobal.json');
671 grunt
.file
.copy('build/libs/relooper.js', outputDir
+ '/build/libs/relooper.js');
672 grunt
.file
.expand('build/ts/*.js').forEach(function (file
) {
673 grunt
.file
.copy(file
, outputDir
+ '/build/ts/' + path
.basename(file
));
675 grunt
.file
.expand('build/bundles/*.js').forEach(function (file
) {
676 grunt
.file
.copy(file
, outputDir
+ '/build/bundles/' + path
.basename(file
));
678 grunt
.file
.expand('build/bundles-cc/*.js').forEach(function (file
) {
679 grunt
.file
.copy(file
, outputDir
+ '/build/bundles-cc/' + path
.basename(file
));
681 grunt
.file
.copy('src/shell/shell-node.js', outputDir
+ '/src/shell/shell-node.js');
682 grunt
.file
.copy('build/version/version.txt', outputDir
+ '/version.txt');
683 grunt
.file
.copy('LICENSE', outputDir
+ '/LICENSE');
685 var waitFor
= 0, done
= this.async();
686 grunt
.file
.expand('src/shell/runners/run-*').forEach(function (file
) {
687 var dest
= outputDir
+ '/bin/' + path
.basename(file
);
688 grunt
.file
.copy(file
, dest
);
690 grunt
.util
.spawn({cmd
: 'chmod', args
: ['+x', dest
]}, function () {
702 grunt
.registerTask('tracetest', ['exec:test_trace']);
703 grunt
.registerTask('tracetest-swfdec', ['exec:test_trace_swfdec']);
705 grunt
.registerTask('watch-playerglobal', ['exec:build_playerglobal', 'watch:playerglobal']);
706 grunt
.registerTask('watch-base', ['exec:build_base_ts', 'watch:base']);
707 grunt
.registerTask('watch-avm2', ['exec:build_avm2_ts', 'watch:avm2_ts']);
708 grunt
.registerTask('watch-swf', ['exec:build_swf_ts', 'watch:swf_ts']);
709 grunt
.registerTask('watch-flash', ['exec:build_flash_ts', 'watch:flash_ts']);
710 grunt
.registerTask('watch-player', ['exec:build_player_ts', 'watch:player_ts']);
711 grunt
.registerTask('watch-gfx', ['exec:build_gfx_base_ts', 'exec:build_gfx_ts', 'watch:gfx_ts']);
712 grunt
.registerTask('watch-tools', ['exec:build_tools_ts', 'watch:tools_ts']);
714 // temporary make/python calls based on grunt-exec
715 grunt
.registerTask('build-playerglobal', ['exec:build_playerglobal']);
716 grunt
.registerTask('playerglobal', ['exec:build_playerglobal']);
717 grunt
.registerTask('playerglobal-single', ['exec:build_playerglobal_single']);
719 grunt
.registerTask('base', ['exec:build_base_ts', 'test-quick']);
720 grunt
.registerTask('swf', ['exec:build_swf_ts', 'test-quick']);
721 grunt
.registerTask('flash', ['parallel:flash', 'test-quick']);
722 grunt
.registerTask('avm1', ['parallel:avm1', 'test-quick']);
723 grunt
.registerTask('player', ['exec:build_player_ts', 'test-quick']);
724 grunt
.registerTask('shell', ['exec:build_shell_ts', 'test-quick']);
725 grunt
.registerTask('tools', ['exec:build_tools_ts', 'test-quick']);
726 grunt
.registerTask('avm2', ['exec:build_avm2_ts', 'copy_relooper', 'test-quick']);
727 grunt
.registerTask('gfx', ['exec:build_gfx_base_ts', 'exec:build_gfx_ts', 'test-quick']);
728 grunt
.registerTask('gfx-base', ['exec:build_gfx_base_ts']);
729 grunt
.registerTask('perf', ['exec:perf']);
730 grunt
.registerTask('gfx-test', ['exec:gfx-test']);
731 grunt
.registerTask('build', "Builds all modules.", [
732 'ensure-build-folder',
734 'parallel:playerglobal',
735 'exec:build_tools_ts',
736 'exec:build_gfx_base_ts',
740 'exec:build_player_ts',
741 'exec:build_shell_ts',
745 grunt
.registerTask('shu', [
749 grunt
.registerTask('travis', "Makes sure your local build will succeed on travis.", [
750 'exec:install_js_travis',
751 'exec:install_avmshell_travis',
752 // 'exec:versions_travis', AVMShell exits with 1 for some reason.
756 'exec:test_avm2_shumway',
757 'exec:test_avm2_acceptance',
758 // 'exec:test_avm2_pypy',
762 'exec:install_swfdec_travis',
763 'exec:test_trace_swfdec',
764 //'exec:test_avm2_ats',
765 //'exec:test_avm2_ats_parse',
769 grunt
.registerTask('gate', "Run this before checking in any code.", [
770 'ensure-test-folder',
771 // 'tslint:all', // Annoyingly slow, and not very useful most of the time.
772 // 'closure', REDUX: Temporarily commented out.
777 grunt
.registerTask('warn', "Run this before checking in any code to report warnings.", [
782 grunt
.registerTask('perf-gate', "Run this before checking in any code to make sure you don't regress performance.", [
783 'exec:perf_avm2_acceptance'
785 // Quick sanity test that runs after a module is compiled.
786 grunt
.registerTask('test-quick', [
790 grunt
.registerTask('test', [
791 'exec:test_avm2_shumway',
792 'exec:test_avm2_acceptance',
793 // 'exec:test_avm2_pypy',
797 // 'exec:test_trace_swfdec', // Takes too long.
798 'exec:test_avm2_ats',
799 'exec:test_avm2_ats_parse',
802 grunt
.registerTask('mozcentralshu', [
803 'mozcentralbaseline',
807 grunt
.registerTask('mozcentralbaseline', function () {
808 if (!grunt
.option('baseline')) {
809 throw new Error('--baseline parameter is not specified.');
811 var baseline
= grunt
.option('baseline');
812 var BASELINE_DIR
= 'build/mozcentralbaseline';
813 grunt
.file
.delete(BASELINE_DIR
, {force
: true});
814 grunt
.file
.mkdir(BASELINE_DIR
);
815 var done
= this.async();
816 var gitClone = function () {
819 args
: ['clone', '../..', '.'],
820 opts
: { cwd
: BASELINE_DIR
, stdio
: 'inherit'}}, function (error
) {
828 var gitCheckout = function () {
831 args
: ['checkout', baseline
],
832 opts
: { cwd
: BASELINE_DIR
, stdio
: 'inherit'}}, function (error
) {
840 var bootstrap = function () {
843 args
: ['link-utils', 'BASE=../..'],
844 opts
: { cwd
: BASELINE_DIR
, stdio
: 'inherit'}}, function (error
) {
852 var build = function () {
855 args
: ['mozcentral'],
856 opts
: { cwd
: BASELINE_DIR
, stdio
: 'inherit'}}, function (error
) {
867 grunt
.registerTask('mozcentraldiff', function () {
868 var BASELINE_BUILD_DIR
= 'build/mozcentralbaseline/build/mozcentral';
869 if (!grunt
.file
.exists(BASELINE_BUILD_DIR
)) {
870 throw new Error('mozcentralbaseline was not run.');
872 var NON_DELTA_BINARIES
= [
873 'browser/extensions/shumway/content/libs/builtin.abc',
874 'browser/extensions/shumway/content/playerglobal/playerglobal.abcs'
876 var MOZCENTRAL_DIR
= 'build/mozcentral';
877 var DIFF_DIR
= 'build/mozcentraldiff';
878 grunt
.file
.delete(DIFF_DIR
, {force
: true});
879 grunt
.file
.mkdir(DIFF_DIR
);
880 var done
= this.async();
881 var rsync = function () {
884 args
: ['-r'].concat(grunt
.file
.expand(BASELINE_BUILD_DIR
+ '/*'), [DIFF_DIR
]),
885 opts
: { stdio
: 'inherit' }}, function (error
) {
893 // HACK to avoid 'delta' for 'GIT binary patch'
894 var fixNonDelta = function (index
) {
895 if (index
>= NON_DELTA_BINARIES
.length
) {
899 var nonDelta
= NON_DELTA_BINARIES
[index
];
902 args
: [DIFF_DIR
+ '/' + nonDelta
, MOZCENTRAL_DIR
+ '/' + nonDelta
]
903 }, function (error
, result
, code
) {
905 // ... we need to truncate the file
906 grunt
.file
.write(DIFF_DIR
+ '/' + nonDelta
, '');
912 fixNonDelta(index
+ 1);
915 var gitCommit = function () {
919 opts
: { cwd
: DIFF_DIR
, stdio
: 'inherit'}}, function (error
) {
927 opts
: { cwd
: DIFF_DIR
, stdio
: 'inherit'}}, function (error
) {
934 args
: ['commit', '--message=baseline'],
935 opts
: { cwd
: DIFF_DIR
, stdio
: 'inherit'}}, function (error
) {
945 var refresh = function () {
948 args
: ['-rc', '--delete'].concat(grunt
.file
.expand(MOZCENTRAL_DIR
+ '/*'), [DIFF_DIR
]),
949 opts
: { stdio
: 'inherit'}}, function (error
) {
957 var gitDiff = function () {
960 args
: ['add', '--all'],
961 opts
: { cwd
: DIFF_DIR
, stdio
: 'inherit'}}, function (error
) {
966 var diffOutput
= require('fs').openSync('build/mozcentral.diff', 'w');
969 args
: ['diff', '--binary', '--cached', '--unified=8'],
970 opts
: { cwd
: DIFF_DIR
, stdio
: [null, diffOutput
, null]}}, function (error
, result
, code
) {
982 grunt
.registerTask('generate-version', function () {
983 function generateFiles() {
984 console
.log('Generating version files for ' + version
+ ' (' + sha
+ ')');
985 grunt
.file
.write(outputDir
+ '/version.json',
986 JSON
.stringify({version
: version
, sha
: sha
}));
987 grunt
.file
.write(outputDir
+ '/version.txt', version
+ '\n' + sha
+ '\n');
988 grunt
.file
.write(outputDir
+ '/version.ts',
989 'module Shumway {\n export var version = \'' + version
+ '\';\n' +
990 ' export var build = \'' + sha
+ '\';\n}\n');
991 grunt
.file
.write(outputDir
+ '/version.js',
992 'var Shumway;\n(function (Shumway) {\n' +
993 ' Shumway.version = \'' + version
+ '\';\n' +
994 ' Shumway.build = \'' + sha
+ '\';\n' +
995 '})(Shumway || (Shumway = {}));\n');
998 function getDefaultVersion() {
1000 return d
.getFullYear() * 100000000 + (d
.getMonth() + 1) * 1000000 +
1001 d
.getDate() * 10000 + d
.getHours() * 100 + d
.getMinutes()
1004 var version
= getDefaultVersion(), sha
= 'unknown';
1006 var outputDir
= 'build/version';
1007 grunt
.file
.mkdir(outputDir
);
1009 var done
= this.async();
1012 args
: ['log', '--format=oneline', VERSION_BASELINE
+ '..']
1013 }, function (error
, result
, code
) {
1016 done('Error code ' + code
+ ': ' + error
);
1019 version
= VERSION_BASE
+ (String(result
).split(/\n/g).length
);
1022 args
: ['log', '--format=%h', '-n', '1']
1023 }, function (error
, result
, code
) {
1026 done('Error code ' + code
+ ': ' + error
);
1029 sha
= String(result
);
1035 grunt
.registerTask('shuobject-package', function () {
1036 var outputDir
= 'build/shuobject';
1037 grunt
.file
.mkdir(outputDir
);
1038 var path
= require('path');
1040 grunt
.file
.copy('build/libs/builtin.abc', outputDir
+ '/build/libs/builtin.abc');
1041 grunt
.file
.copy('build/playerglobal/playerglobal.abcs', outputDir
+ '/build/playerglobal/playerglobal.abcs');
1042 grunt
.file
.copy('build/playerglobal/playerglobal.json', outputDir
+ '/build/playerglobal/playerglobal.json');
1043 grunt
.file
.copy('build/libs/relooper.js', outputDir
+ '/build/libs/relooper.js');
1044 grunt
.file
.expand('build/bundles-cc/*.js').forEach(function (file
) { // TODO closure bundles
1045 grunt
.file
.copy(file
, outputDir
+ '/build/bundles/' + path
.basename(file
));
1047 grunt
.file
.expand('web/iframe/*').forEach(function (file
) {
1048 grunt
.file
.copy(file
, outputDir
+ '/iframe/' + path
.basename(file
));
1050 grunt
.file
.copy('extension/shuobject/shuobject.js', outputDir
+ '/shuobject.js');
1051 grunt
.file
.expand('extension/shuobject/examples/*').forEach(function (file
) {
1052 grunt
.file
.copy(file
, outputDir
+ '/examples/' + path
.basename(file
));
1054 grunt
.file
.copy('web/demo.swf', outputDir
+ '/examples/demo.swf');
1055 grunt
.file
.copy('examples/external/externalinterface/avm2.swf', outputDir
+ '/examples/external_interface.swf');
1057 grunt
.file
.copy('build/version/version.txt', outputDir
+ '/version.txt');
1058 grunt
.file
.copy('LICENSE', outputDir
+ '/LICENSE');
1059 grunt
.file
.copy('LICENSE-OFL.txt', outputDir
+ '/LICENSE-OFL.txt');
1060 grunt
.file
.copy('README-LICENSE.txt', outputDir
+ '/README-LICENSE.txt');
1063 function copyFilesUsingPattern(src
, dest
, callback
) {
1064 var path
= require('path');
1065 grunt
.file
.expand(src
).forEach(function (file
) {
1066 var p
= path
.join(dest
, path
.basename(file
));
1067 grunt
.file
.copy(file
, p
);
1074 grunt
.registerTask('dist-package', function() {
1075 var done
= this.async();
1076 var outputDir
= 'build/dist';
1077 var repoURL
= 'https://github.com/mozilla/shumway-dist';
1079 var path
= require('path');
1080 var fs
= require('fs');
1081 var versionJSON
= JSON
.parse(fs
.readFileSync('build/version/version.json'));
1083 function prepareFiles(done
) {
1084 grunt
.file
.copy('build/libs/builtin.abc', outputDir
+ '/build/libs/builtin.abc');
1085 grunt
.file
.copy('build/playerglobal/playerglobal.abcs', outputDir
+ '/build/playerglobal/playerglobal.abcs');
1086 grunt
.file
.copy('build/playerglobal/playerglobal.json', outputDir
+ '/build/playerglobal/playerglobal.json');
1087 grunt
.file
.copy('build/libs/relooper.js', outputDir
+ '/build/libs/relooper.js');
1088 copyFilesUsingPattern('build/bundles-cc/*.js', outputDir
+ '/build/bundles');
1090 // shuobject packaging
1091 copyFilesUsingPattern('web/iframe/*', outputDir
+ '/iframe');
1092 grunt
.file
.copy('extension/shuobject/shuobject.js', outputDir
+ '/shuobject.js');
1093 grunt
.file
.copy('src/compatibility.js', outputDir
+ '/src/compatibility.js');
1096 grunt
.file
.copy('build/ts/shell.js', outputDir
+ '/build/ts/shell.js');
1097 fs
.writeFileSync(outputDir
+ '/build/ts/shell.conf', 'dist');
1098 grunt
.file
.copy('src/shell/shell-node.js', outputDir
+ '/src/shell/shell-node.js');
1101 copyFilesUsingPattern('src/shell/runners/run-*', outputDir
+ '/bin', function (dest
) {
1103 grunt
.util
.spawn({cmd
: 'chmod', args
: ['+x', dest
]}, function () {
1105 if (waitFor
=== 0) {
1113 "name": "shumway-dist",
1114 "version": versionJSON
.version
,
1115 "description": "Generic build of Mozilla's Shumway library.",
1120 "homepage": "http://mozilla.github.io/shumway/",
1121 "bugs": "https://github.com/mozilla/shumway/issues",
1122 "license": "Apache-2.0",
1125 "url": "https://github.com/mozilla/shumway-dist"
1128 fs
.writeFileSync(outputDir
+ '/package.json', JSON
.stringify(packageJSON
, null, 2));
1130 "name": "shumway-dist",
1131 "version": versionJSON
.version
,
1141 fs
.writeFileSync(outputDir
+ '/bower.json', JSON
.stringify(bowerJSON
, null, 2));
1143 grunt
.file
.copy('build/version/version.txt', outputDir
+ '/version.txt');
1144 grunt
.file
.copy('LICENSE', outputDir
+ '/LICENSE');
1145 grunt
.file
.copy('utils/dist/README.md', outputDir
+ '/README.md');
1147 if (--waitFor
=== 0) {
1152 function addCommitMessages(done
) {
1153 var message
= 'Shumway version ' + versionJSON
.version
;
1154 var tag
= 'v' + versionJSON
.version
;
1155 grunt
.util
.spawn({cmd
: 'git', args
: ['add', '--all'], opts
: {cwd
: outputDir
}}, function (error
) {
1156 grunt
.util
.spawn({cmd
: 'git', args
: ['commit', '-am', message
], opts
: {cwd
: outputDir
}}, function () {
1157 grunt
.util
.spawn({cmd
: 'git', args
: ['tag', '-a', tag
, '-m', message
], opts
: {cwd
: outputDir
}}, function () {
1164 grunt
.file
.delete(outputDir
);
1165 grunt
.file
.mkdir(outputDir
);
1167 grunt
.util
.spawn({cmd
: 'git', args
: ['clone', '--depth', '1', repoURL
, outputDir
]}, function () {
1168 prepareFiles(function () {
1169 addCommitMessages(function () {
1171 console
.info('Done. Push with');
1172 console
.info(' cd ' + outputDir
+ '; git push --tags ' + repoURL
+ ' master');
1181 grunt
.registerTask('clean', function () {
1182 var filesToRemove
= [
1183 'build', // Deletes entire 'build' folder!
1188 filesToRemove
.forEach(function (files
) {
1189 grunt
.file
.expand(files
).forEach(function (file
) {
1190 grunt
.file
.delete(file
);
1195 grunt
.registerTask('firefox', ['build', 'closure-bundles', 'exec:build_extension']);
1196 grunt
.registerTask('mozcentral', ['build', 'closure-bundles', 'exec:build_mozcentral']);
1197 grunt
.registerTask('web', ['build', 'closure-bundles', 'exec:build_extension', 'shell-package', 'shuobject-package', 'exec:build_web']);
1198 grunt
.registerTask('dist', ['build', 'closure-bundles', 'dist-package']);