From def389517ff47def5d5f249cfe5176be06cd6378 Mon Sep 17 00:00:00 2001 From: yofreke Date: Sat, 18 Jul 2015 18:08:37 -0700 Subject: [PATCH 01/23] added individualCompile option --- src/build/common/jsCompiler.js | 40 ++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index f6b3b0b..871f8d7 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -65,6 +65,7 @@ exports.JSCompiler = Class(function () { var jsioOpts = { cwd: opts.cwd || appPath, + outputPath: opts.outputPath, environment: opts.env, path: [require('jsio').__env.getPath(), '.', 'lib'].concat(this._path), includeJsio: 'includeJsio' in opts ? opts.includeJsio : true, @@ -223,8 +224,43 @@ var DevKitJsioInterface = Class(EventEmitter, function () { this.emit('error', e); }; - this.onFinish = function (opts, src) { - this.emit('code', src); + this.onFinish = function (opts, src, table) { + if (opts.individualCompile) { + var binPath = path.join(opts.outputPath, 'bin'); + + mkdirp(binPath, function () { + var keys = Object.keys(table); + logger.info('Writing individual compile files: ' + keys.length); + + var complete = 0; + + var onFileWrite = function(err) { + if (err) throw err; + complete++; + if (complete === keys.length) { + this.emit('code', src); + } + }.bind(this); + + keys.forEach(function(key) { + var fname = path.join(binPath, key.replace(/\//g, '.')); + // Check the bin dir + fs.stat(fname, function(err, binStat) { + if (!err) { + var srcStat = fs.statSync(path.join(opts.cwd, key)); + if (srcStat.mtime < binStat.mtime) { + logger.info('Already in bin, skipping based on modified time: ' + key); + onFileWrite(); + return; + } + } + fs.writeFile(fname, JSON.stringify(table[key]), onFileWrite); + }) + }); + }.bind(this)); + } else { + this.emit('code', src); + } }; /** From 282953dfaa15f4260c22472826947e330b8bc371 Mon Sep 17 00:00:00 2001 From: yofreke Date: Mon, 20 Jul 2015 08:28:42 -0700 Subject: [PATCH 02/23] updates for preloading --- node_modules/jsio | 2 +- src/build/browser/browser-static/bootstrap.js | 1 + src/build/browser/index.js | 8 +- src/build/common/jsCompiler.js | 91 +++++++++++++------ src/clientapi/browser/launchClient.js | 5 +- src/clientapi/native/launchClient.js | 2 +- 6 files changed, 73 insertions(+), 36 deletions(-) diff --git a/node_modules/jsio b/node_modules/jsio index a4a90e7..346738b 160000 --- a/node_modules/jsio +++ b/node_modules/jsio @@ -1 +1 @@ -Subproject commit a4a90e715d1ab2798a5ea4e3ca82c3c70a71277a +Subproject commit 346738b9204d48f234ec9eee142b9ab4189828f3 diff --git a/src/build/browser/browser-static/bootstrap.js b/src/build/browser/browser-static/bootstrap.js index 2c55cf3..8f55590 100644 --- a/src/build/browser/browser-static/bootstrap.js +++ b/src/build/browser/browser-static/bootstrap.js @@ -136,6 +136,7 @@ function bootstrap(initialImport, target) { w._continueLoad = function() { if (!loaded) { loaded = true; + // Include the game code var el = d.createElement('script'); el.src = target + '.js'; d.getElementsByTagName('head')[0].appendChild(el); diff --git a/src/build/browser/index.js b/src/build/browser/index.js index 85c0def..f6d2f29 100644 --- a/src/build/browser/index.js +++ b/src/build/browser/index.js @@ -77,7 +77,7 @@ exports.build = function (api, app, config, cb) { function getPreloadJS() { // get preload JS if (/^native/.test(config.target)) { - return Promise.resolve('jsio=function(){window._continueLoad()}'); + return Promise.resolve('(window.jsio) ? (window._continueLoad()) : (jsio=function(){window._continueLoad()})'); } var isLiveEdit = (config.target === 'live-edit'); @@ -178,6 +178,10 @@ exports.build = function (api, app, config, cb) { config.browser.headHTML.push(''); } + if (config.isSimulated) { + config.browser.headHTML.push(''); + } + var hasIndexPage = !isMobile; tasks.push(gameHTML.generate(api, app, config) .then(function (html) { @@ -218,7 +222,7 @@ exports.build = function (api, app, config, cb) { contents: new Buffer('NATIVE=false;' + 'CACHE=' + JSON.stringify(inlineCache) + ';\n' + jsSrc + ';' - + 'jsio("import ' + INITIAL_IMPORT + '");') + + 'jsio.__env.preloadModules(function() { jsio("import ' + INITIAL_IMPORT + '"); });') })); files.forEach(function (file) { diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index 871f8d7..144dd26 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -121,7 +121,11 @@ exports.JSCompiler = Class(function () { // start the compile by passing something equivalent to argv (first argument is // ignored, but traditionally should be the name of the executable?) + // Compile the game code mkdirp(jsCachePath, function () { + jsioOpts.noCompile = true; + jsioOpts.includeJsio = false; + jsioOpts.separateJsio = true; compiler.start(['jsio_compile', jsioOpts.cwd || '.', importStatement], jsioOpts); }); }; @@ -224,40 +228,69 @@ var DevKitJsioInterface = Class(EventEmitter, function () { this.emit('error', e); }; + this._writeJsioBin = function(binPath) { + var destPath = path.join(binPath, 'jsio.js'); + + // Dont overwrite existing if mtime check fails + if (fs.existsSync(destPath)) { + var srcPath = require.resolve('jsio'); + var srcStat = fs.statSync(srcPath); + var existingStat = fs.statSync(destPath); + if (existingStat.mtime > srcStat.mtime) { + return; + } + } + + // Write the new src + var src = jsio.__jsio.__init__.toString(-1); + if (src.substring(0, 8) == 'function') { + src = 'jsio=(' + src + ')();'; + } + fs.writeFileSync(destPath, src); + }; + this.onFinish = function (opts, src, table) { - if (opts.individualCompile) { - var binPath = path.join(opts.outputPath, 'bin'); + var binPath = path.join(opts.outputPath, 'bin'); + + // Only call mkdirp once + if (opts.separateJsio || opts.individualCompile) { + mkdirp.sync(binPath); + } - mkdirp(binPath, function () { - var keys = Object.keys(table); - logger.info('Writing individual compile files: ' + keys.length); + // maybe write out a new jsio + if (opts.separateJsio) { + this._writeJsioBin(binPath); + } - var complete = 0; + if (opts.individualCompile) { + var keys = Object.keys(table); + logger.info('Writing individual compile files: ' + keys.length); - var onFileWrite = function(err) { - if (err) throw err; - complete++; - if (complete === keys.length) { - this.emit('code', src); - } - }.bind(this); - - keys.forEach(function(key) { - var fname = path.join(binPath, key.replace(/\//g, '.')); - // Check the bin dir - fs.stat(fname, function(err, binStat) { - if (!err) { - var srcStat = fs.statSync(path.join(opts.cwd, key)); - if (srcStat.mtime < binStat.mtime) { - logger.info('Already in bin, skipping based on modified time: ' + key); - onFileWrite(); - return; - } + var complete = 0; + + var onFileWrite = function(err) { + if (err) throw err; + complete++; + if (complete === keys.length) { + this.emit('code', src); + } + }.bind(this); + + keys.forEach(function(key) { + var fname = path.join(binPath, key.replace(/\//g, '.')); + // Check the bin dir + fs.stat(fname, function(err, binStat) { + if (!err) { + var srcStat = fs.statSync(path.join(opts.cwd, key)); + if (srcStat.mtime < binStat.mtime) { + logger.info('Already in bin, skipping based on modified time: ' + key); + onFileWrite(); + return; } - fs.writeFile(fname, JSON.stringify(table[key]), onFileWrite); - }) - }); - }.bind(this)); + } + fs.writeFile(fname, JSON.stringify(table[key]), onFileWrite); + }) + }); } else { this.emit('code', src); } diff --git a/src/clientapi/browser/launchClient.js b/src/clientapi/browser/launchClient.js index 4995e70..72bdb4a 100644 --- a/src/clientapi/browser/launchClient.js +++ b/src/clientapi/browser/launchClient.js @@ -17,9 +17,9 @@ /* globals jsio, CONFIG, DEBUG */ // no dynamic source fetching -jsio.__env.fetch = function (filename) { return false; }; +// jsio.__env.fetch = function (filename) { return false; }; -import Promise; +import ..api.Promise as Promise; GLOBAL.Promise = Promise; var isSimulator = GLOBAL.CONFIG && !!CONFIG.simulator; @@ -133,7 +133,6 @@ function queueStart() { } function startApp () { - // setup timestep device API import device; import platforms.browser.initialize; diff --git a/src/clientapi/native/launchClient.js b/src/clientapi/native/launchClient.js index 4437578..1445a36 100644 --- a/src/clientapi/native/launchClient.js +++ b/src/clientapi/native/launchClient.js @@ -20,7 +20,7 @@ GLOBAL.console = logging.get('console'); window.self = window; // add bluebird promise implementation to global scope -import Promise; +import ..api.Promise as Promise; GLOBAL.Promise = Promise; // initialize native JS API wrappers From 120f7cb998863f1811fb0b3e8563cf1dae62fbc0 Mon Sep 17 00:00:00 2001 From: yofreke Date: Mon, 20 Jul 2015 17:01:08 +0000 Subject: [PATCH 03/23] move jsio path cache to its own file --- node_modules/jsio | 2 +- src/build/browser/index.js | 1 + src/build/common/jsCompiler.js | 8 +++++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/node_modules/jsio b/node_modules/jsio index 346738b..1b2a816 160000 --- a/node_modules/jsio +++ b/node_modules/jsio @@ -1 +1 @@ -Subproject commit 346738b9204d48f234ec9eee142b9ab4189828f3 +Subproject commit 1b2a8166b5dd064b88b0003ede1d171b3b0d9e5c diff --git a/src/build/browser/index.js b/src/build/browser/index.js index f6d2f29..c527f4c 100644 --- a/src/build/browser/index.js +++ b/src/build/browser/index.js @@ -180,6 +180,7 @@ exports.build = function (api, app, config, cb) { if (config.isSimulated) { config.browser.headHTML.push(''); + config.browser.headHTML.push(''); } var hasIndexPage = !isMobile; diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index 144dd26..005cb7f 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -229,9 +229,15 @@ var DevKitJsioInterface = Class(EventEmitter, function () { }; this._writeJsioBin = function(binPath) { - var destPath = path.join(binPath, 'jsio.js'); + // Write the jsio_path.js + var destPath = path.join(binPath, 'jsio_path.js'); + logger.info('\n\n\ngetting the path') + logger.info(jsio.__env.getCwd()) + var src = this._compiler.getCompiler().getPathJS(); + fs.writeFileSync(destPath, src); // Dont overwrite existing if mtime check fails + var destPath = path.join(binPath, 'jsio.js'); if (fs.existsSync(destPath)) { var srcPath = require.resolve('jsio'); var srcStat = fs.statSync(srcPath); From 9fb2e4f3359fede3857e0f5c6ccdbd7353a870ca Mon Sep 17 00:00:00 2001 From: yofreke Date: Mon, 20 Jul 2015 19:02:01 -0700 Subject: [PATCH 04/23] checkpoint - ~0.6 second simulator builds --- node_modules/jsio | 2 +- src/build/browser/html.js | 73 ++++++++++-- src/build/browser/index.js | 132 ++++++++++++++++------ src/build/common/FileGenerator.js | 177 ++++++++++++++++++++++++++++++ src/build/common/jsCompiler.js | 74 ++++++------- 5 files changed, 372 insertions(+), 86 deletions(-) create mode 100644 src/build/common/FileGenerator.js diff --git a/node_modules/jsio b/node_modules/jsio index 1b2a816..c3a69a0 160000 --- a/node_modules/jsio +++ b/node_modules/jsio @@ -1 +1 @@ -Subproject commit 1b2a8166b5dd064b88b0003ede1d171b3b0d9e5c +Subproject commit c3a69a08908ba53055a5bea157644257f128d8c9 diff --git a/src/build/browser/html.js b/src/build/browser/html.js index d09c2f4..1275555 100644 --- a/src/build/browser/html.js +++ b/src/build/browser/html.js @@ -1,12 +1,12 @@ var path = require('path'); var fs = require('fs'); -var stylus = require('stylus'); -var nib = require('nib'); var printf = require('printf'); var JSCompiler = require('../common/jsCompiler').JSCompiler; var getBase64Image = require('./datauri').getBase64Image; +var FileGenerator = require('../common/FileGenerator'); + var TARGET_APPLE_TOUCH_ICON_SIZE = 152; exports.IndexHTML = Class(function () { @@ -76,14 +76,64 @@ exports.IndexHTML = Class(function () { }; }); +var renderStylus = function(cssString, shouldCompress) { + // Only import if used, otherwise it takes forever + var stylus = require('stylus'); + var nib = require('nib'); + + // process the stylus into css + var stylusRenderer = stylus(cssString) + .set('compress', shouldCompress) + .use(nib()); + return stylusRenderer.render(); +}; + exports.GameHTML = Class(function () { - this.init = function () { + this.init = function (config) { this._css = []; this._js = []; + + this._config = config; + this._binPath = path.join(config.outputPath, 'bin', 'html'); }; - this.addCSS = function (css) { this._css.push(css); }; - this.addJS = function (js) { this._js.push(js); }; + /** + * @param {string} css Path to some stylus file + */ + // TODO: Actually should be "addStylus" + this.addCSS = function (name, css) { + var dest = path.join(this._binPath, 'css', name.replace(/\//g, '_')); + var shouldCompress = this._config.compress; + + this._css.push(FileGenerator.dynamic( + css, + dest, + function(cb) { + cb(null, renderStylus(css, shouldCompress)); + } + )); + }; + + this.addCSSFile = function(cssPath) { + var dest = path.join(this._binPath, 'css', cssPath.replace(/\//g, '_')); + var shouldCompress = this._config.compress; + + this._css.push(FileGenerator( + cssPath, + dest, + function(cb) { + fs.readFile(cssPath, 'utf8', function(err, cssSrc) { + if (err) { reject(err); return; } + + cb(null, renderStylus(cssSrc, shouldCompress)); + }); + } + )); + }; + + this.addJS = function (js) { + this._js.push(js); + }; // return smallest icon size larger than targetSize or the largest icon if // none are larger than targetSize @@ -126,16 +176,17 @@ exports.GameHTML = Class(function () { this.generate = function (api, app, config) { var logger = api.logging.get('build-html'); - var css = this._css.join('\n'); + var theCss = Promise.reduce(this._css, function(total, src) { + return total += src + '\n'; + }, ''); + + var js = this._js.join(';'); - var stylusRenderer = stylus(css) - .set('compress', config.compress) - .use(nib()); var jsCompiler = new JSCompiler(api, app); - var renderCSS = Promise.promisify(stylusRenderer.render, stylusRenderer); var compileJS = Promise.promisify(jsCompiler.compress, jsCompiler); + return Promise.all([ - renderCSS(), + theCss, config.compress ? compileJS('[bootstrap]', js, {showWarnings: false}) : js diff --git a/src/build/browser/index.js b/src/build/browser/index.js index c527f4c..b59f32b 100644 --- a/src/build/browser/index.js +++ b/src/build/browser/index.js @@ -14,15 +14,6 @@ * along with the Game Closure SDK. If not, see . */ var path = require('path'); -var printf = require('printf'); -var fs = require('graceful-fs'); -var File = require('vinyl'); -var vfs = require('vinyl-fs'); -// var newer = require('gulp-newer'); -var slash = require('slash'); -var streamFromArray = require('stream-from-array'); - -var readFile = Promise.promisify(fs.readFile); var logger; var INITIAL_IMPORT = 'devkit.browser.launchClient'; @@ -52,27 +43,76 @@ exports.configure = function (api, app, config, cb) { cb && cb(); }; +var _timeLogger = null; +var _times = {}; +function startTime(name) { + _times[name] = new Date().getTime(); +} +function endTime(name) { + _timeLogger.info(name + ': ' + (new Date().getTime() - _times[name])); + delete _times[name]; +} + exports.build = function (api, app, config, cb) { + + var printf = require('printf'); + var fs = require('graceful-fs'); + var File = require('vinyl'); + var vfs = require('vinyl-fs'); + // var newer = require('gulp-newer'); + var slash = require('slash'); + var streamFromArray = require('stream-from-array'); + + var readFile = Promise.promisify(fs.readFile); + + // config.spriteImages = false; logger = api.logging.get('build-browser'); + _timeLogger = api.logging.get('--------TIMER--------'); + + startTime('browser-main'); + startTime('setup-require'); var isMobile = (config.target !== 'browser-desktop'); var isLiveEdit = (config.target === 'live-edit'); + //console.time('import-1') var resources = require('../common/resources'); + //console.timeEnd('import-1') + //console.time('import-2') var CSSFontList = require('./fonts').CSSFontList; + //console.timeEnd('import-2') + //console.time('import-3') var JSConfig = require('../common/jsConfig').JSConfig; + //console.timeEnd('import-3') + //console.time('import-4') var JSCompiler = require('../common/jsCompiler').JSCompiler; + //console.timeEnd('import-4') - var sprite = require('../common/spriter') - .sprite - .bind(null, api, app, config); + var sprite = null; + if (config.spriteImages) { + sprite = require('../common/spriter') + .sprite + .bind(null, api, app, config); + } + //console.time('import-5') var html = require('./html'); - var gameHTML = new html.GameHTML(); + //console.timeEnd('import-5') + //console.time('import-6') + var gameHTML = new html.GameHTML(config); + //console.timeEnd('import-6') + //console.time('import-7') var fontList = new CSSFontList(); + //console.timeEnd('import-7') + //console.time('import-8') var jsConfig = new JSConfig(api, app, config); + //console.timeEnd('import-8') + //console.time('import-9') var jsCompiler = new JSCompiler(api, app, config, jsConfig); + //console.timeEnd('import-9') + //console.time('import-10') var compileJS = Promise.promisify(jsCompiler.compile, jsCompiler); + //console.timeEnd('import-10') function getPreloadJS() { // get preload JS @@ -100,37 +140,52 @@ exports.build = function (api, app, config, cb) { }; } - return compileJS({ + var compileOpts = { initialImport: 'devkit.browser.bootstrap.launchBrowser', appendImport: false, preCompress: config.preCompressCallback - }); + }; + if (config.isSimulated) { + compileOpts.noCompile = true; + compileOpts.includeJsio = false; + compileOpts.separateJsio = true; + } + return compileJS(compileOpts); } var baseDirectory = config.outputResourcePath; + endTime('setup-require'); + startTime('main-spread'); + resources.getDirectories(api, app, config) .then(function (directories) { + var compileOpts = { + env: 'browser', + initialImport: [INITIAL_IMPORT].concat(config.imports).join(', '), + appendImport: false, + includeJsio: !config.excludeJsio, + debug: config.scheme === 'debug', + preCompress: config.preCompressCallback + }; + if (config.isSimulated) { + compileOpts.noCompile = true; + compileOpts.includeJsio = false; + compileOpts.separateJsio = true; + } return Promise.all([ resources.getFiles(baseDirectory, directories), readFile(getLocalFilePath('../../clientapi/browser/cache-worker.js'), 'utf8'), getPreloadJS(), - readFile(STATIC_BOOTSTRAP_CSS, 'utf8'), readFile(STATIC_BOOTSTRAP_JS, 'utf8'), isLiveEdit && readFile(STATIC_LIVE_EDIT_JS, 'utf8'), config.spriteImages !== false && sprite(directories), - compileJS({ - env: 'browser', - initialImport: [INITIAL_IMPORT].concat(config.imports).join(', '), - appendImport: false, - includeJsio: !config.excludeJsio, - debug: config.scheme === 'debug', - preCompress: config.preCompressCallback - }) + compileJS(compileOpts) ]); }) - .spread(function (files, cacheWorkerJS, preloadJS, bootstrapCSS, bootstrapJS, + .spread(function (files, cacheWorkerJS, preloadJS, bootstrapJS, liveEditJS, spriterResult, jsSrc) { + endTime('main-spread'); logger.log('Creating HTML and JavaScript...'); jsConfig.add('embeddedFonts', fontList.getNames()); @@ -150,19 +205,23 @@ exports.build = function (api, app, config, cb) { var tasks = []; - // We need to generate a couple different files if this is going to be a - gameHTML.addCSS(bootstrapCSS); - gameHTML.addCSS(fontList.getCSS({ + // ----- ----- GENERATE CSS ----- ----- // + + gameHTML.addCSSFile(STATIC_BOOTSTRAP_CSS); + + gameHTML.addCSS('fontList', fontList.getCSS({ embedFonts: config.browser.embedFonts, formats: require('./fonts').getFormatsForTarget(config.target) })); if (config.browser.canvas.css) { - gameHTML.addCSS('#timestep_onscreen_canvas{' + gameHTML.addCSS('canvas', '#timestep_onscreen_canvas{' + config.browser.canvas.css + '}'); } + // ----- ----- GENERATE JS ----- ----- // + gameHTML.addJS(jsConfig.toString()); gameHTML.addJS(bootstrapJS); gameHTML.addJS(printf('bootstrap("%(initialImport)s", "%(target)s")', { @@ -173,6 +232,8 @@ exports.build = function (api, app, config, cb) { liveEditJS && gameHTML.addJS(liveEditJS); + // ----- ----- // + var hasWebAppManifest = !!config.browser.webAppManifest; if (hasWebAppManifest) { config.browser.headHTML.push(''); @@ -207,6 +268,7 @@ exports.build = function (api, app, config, cb) { })); } + startTime('inline-cache'); var InlineCache = require('../common/inlineCache').InlineCache; var inlineCache = new InlineCache(logger); var addToInlineCache = inlineCache.add.bind(inlineCache); @@ -217,6 +279,8 @@ exports.build = function (api, app, config, cb) { .filter(addToInlineCache); }) .then(function (files) { + endTime('inline-cache'); + startTime('files'); files.push(new File({ base: baseDirectory, path: path.join(baseDirectory, config.target + '.js'), @@ -317,16 +381,22 @@ exports.build = function (api, app, config, cb) { }); // https://github.com/petkaantonov/bluebird/issues/332 - logger.log('Writing files...'); + logger.log('Writing files...' + files.length); + startTime('files-write'); return new Promise(function (resolve, reject) { streamFromArray.obj(files) // .pipe(newer(baseDirectory)) .pipe(vfs.dest(baseDirectory)) - .on('end', resolve) + .on('end', function() { + endTime('files-write'); + endTime('files'); + resolve(); + }) .on('error', reject); }); }); }).then(function () { + endTime('browser-main'); logger.log('Done'); }).nodeify(cb); }; diff --git a/src/build/common/FileGenerator.js b/src/build/common/FileGenerator.js new file mode 100644 index 0000000..fe9bf42 --- /dev/null +++ b/src/build/common/FileGenerator.js @@ -0,0 +1,177 @@ + +var fs = require('fs'); +var path = require('path'); +var mkdirp = require('mkdirp'); + +var crypto = require('crypto'); + +// Only rewrite files if needed + +var hashString = function(str) { + var md5sum = crypto.createHash('md5'); + md5sum.update(str); + return md5sum.digest('hex'); +}; + +var runGenerator = function(opts) { + var doWrite = function(err, src) { + mkdirp(path.dirname(opts.outputPath), function(err) { + if (err) { opts.cb(err); return; } + + fs.writeFile(opts.outputPath, src, function(err) { + if (err) { opts.cb(err); return; } + + // For dynamic calls the hash should be that of the input string, not the output file + if (opts.useInputHash) { + fs.writeFile(opts.outputHashPath, opts.inputHash, function(err) { + if (err) { opts.cb(err); return; } + opts.cb(null, src); + }); + } else { + opts.cb(null, src); + } + }); + + }); + }; + + var useOldOutput = function() { + // Old one is still good, just read it + fs.readFile(opts.outputPath, 'utf8', function(err, src) { + if (err) { opts.cb(err); return; } + + opts.cb(null, src); + }); + } + + var checkModifiedTimes = function() { + fs.stat(opts.sourcePath, function(err, srcStat) { + if (err) { opts.cb(err); return; } + + fs.stat(opts.outputPath, function(err, existingStat) { + if (err) { opts.cb(err); return; } + + if (existingStat.mtime > srcStat.mtime) { + useOldOutput(); + return; + } + + opts.generateFn(doWrite); + }); + }); + }; + + var checkInputHash = function() { + // Cheating: add to opts so we have it inside of doWrite + opts.useInputHash = true; + opts.outputHashPath = opts.outputPath + '.hash'; + opts.inputHash = hashString(opts.sourceContents); + + // Get the output hash + fs.exists(opts.outputHashPath, function(exists) { + if (exists) { + + // Check the hashes + fs.readFile(opts.outputHashPath, 'utf-8', function(err, outputHash) { + if (err) { opts.cb(err); return; } + + if (opts.inputHash === outputHash) { + useOldOutput(); + return; + } + + opts.generateFn(doWrite); + }); + + } else { + opts.generateFn(doWrite); + } + }); + }; + + // Check if the output exists + fs.exists(opts.outputPath, function(exists) { + if (exists) { + if (opts.sourcePath !== undefined) { + // It does, check the modified times + checkModifiedTimes(); + } else if (opts.sourceContents !== undefined) { + checkInputHash(); + } else { + throw new Error('unknown input'); + } + } else { + opts.generateFn(doWrite); + } + }); +}; + + +/** take an input file (source), and generate the output with generateFn. finally +run cb with cb(err, src). Will only run generateFn if the output file is older than +the source file */ +module.exports = function(source, output, generateFn, cb) { + // If there is no callback, make it a promise + var def; + if (cb === undefined) { + def = Promise.defer(); + cb = function(err, src) { + if (err) { + def.reject(err); + } else { + def.resolve(src); + } + }; + } + + runGenerator({ + sourcePath: source, + outputPath: output, + generateFn: generateFn, + cb: cb + }); + + return def ? def.promise : undefined; +}; + +module.exports.runGenerator = runGenerator; + +/** Use this when the source doesn't live on disk, but is generated dynamically. +Will only run the generateFn if the sourceContents hash does not match the bin output hash */ +module.exports.dynamic = function(sourceContents, output, generateFn, cb) { + var def; + if (cb === undefined) { + def = Promise.defer(); + cb = function(err, src) { + if (err) { + def.reject(err); + } else { + def.resolve(src); + } + }; + } + + runGenerator({ + sourceContents: sourceContents, + outputPath: output, + generateFn: generateFn, + cb: cb + }); + + return def ? def.promise : undefined; +}; + +module.exports.sync = function(source, output, generateFn) { + if (fs.existsSync(output)) { + var srcStat = fs.statSync(source); + var existingStat = fs.statSync(output); + if (existingStat.mtime > srcStat.mtime) { + return false; + } + } + var src = generateFn(); + fs.writeFileSync(output, src); + + return src; +}; + diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index 005cb7f..9116e56 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -5,12 +5,11 @@ var crypto = require('crypto'); var argv = require('optimist').argv; var mkdirp = require('mkdirp'); var EventEmitter = require('events').EventEmitter; -var color = require('cli-color'); // clone to modify the path for this jsio but not any others -var jsio = require('jsio').clone(); +var jsio = require('jsio').clone(); // ~10ms -var uglify = require('uglify-js'); +var FileGenerator = require('./FileGenerator'); function deepCopy(obj) { return obj && JSON.parse(JSON.stringify(obj)); } @@ -51,6 +50,7 @@ exports.JSCompiler = Class(function () { }; this.compile = function (opts, cb) { + console.time('JS_COMPILE') var opts = merge({}, opts, this._opts); var appPath = this._app.paths.root; @@ -77,7 +77,10 @@ exports.JSCompiler = Class(function () { printOutput: opts.printJSIOCompileOutput, gcManifest: path.join(appPath, 'manifest.json'), gcDebug: opts.debug, - preprocessors: ['cls', 'logger'] + preprocessors: ['cls', 'logger'], + + noCompile: opts.noCompile, + separateJsio: opts.separateJsio }; if (opts.compress) { @@ -113,6 +116,7 @@ exports.JSCompiler = Class(function () { jsioOpts.interface = new DevKitJsioInterface(this) .on('error', cb) .on('code', function (code) { + console.timeEnd('JS_COMPILE') cb && cb(null, code); }); @@ -123,22 +127,16 @@ exports.JSCompiler = Class(function () { // Compile the game code mkdirp(jsCachePath, function () { - jsioOpts.noCompile = true; - jsioOpts.includeJsio = false; - jsioOpts.separateJsio = true; compiler.start(['jsio_compile', jsioOpts.cwd || '.', importStatement], jsioOpts); }); }; - /** - * use the class opts to compress source code directly - */ - - this.strip = function (src, cb) { - exports.strip(src, this.opts, cb); - }; - + /** + * use the class opts to compress source code directly + */ this.compress = function (filename, src, opts, cb) { + // Import here because it takes a while, ~70ms + var color = require('cli-color'); var closureOpts = [ '--compilation_level', 'SIMPLE_OPTIMIZATIONS', @@ -195,6 +193,8 @@ exports.JSCompiler = Class(function () { } try { + // Import here because it takes a while, ~70ms + var uglify = require('uglify-js'); var result = uglify.minify(src, { fromString: true, global_defs: defines @@ -231,28 +231,19 @@ var DevKitJsioInterface = Class(EventEmitter, function () { this._writeJsioBin = function(binPath) { // Write the jsio_path.js var destPath = path.join(binPath, 'jsio_path.js'); - logger.info('\n\n\ngetting the path') - logger.info(jsio.__env.getCwd()) var src = this._compiler.getCompiler().getPathJS(); fs.writeFileSync(destPath, src); // Dont overwrite existing if mtime check fails + var srcPath = require.resolve('jsio'); var destPath = path.join(binPath, 'jsio.js'); - if (fs.existsSync(destPath)) { - var srcPath = require.resolve('jsio'); - var srcStat = fs.statSync(srcPath); - var existingStat = fs.statSync(destPath); - if (existingStat.mtime > srcStat.mtime) { - return; + FileGenerator.sync(srcPath, destPath, function() { + var src = jsio.__jsio.__init__.toString(-1); + if (src.substring(0, 8) == 'function') { + src = 'jsio=(' + src + ')();'; } - } - - // Write the new src - var src = jsio.__jsio.__init__.toString(-1); - if (src.substring(0, 8) == 'function') { - src = 'jsio=(' + src + ')();'; - } - fs.writeFileSync(destPath, src); + return src; + }); }; this.onFinish = function (opts, src, table) { @@ -283,19 +274,16 @@ var DevKitJsioInterface = Class(EventEmitter, function () { }.bind(this); keys.forEach(function(key) { + var srcFname = path.join(opts.cwd, key); var fname = path.join(binPath, key.replace(/\//g, '.')); - // Check the bin dir - fs.stat(fname, function(err, binStat) { - if (!err) { - var srcStat = fs.statSync(path.join(opts.cwd, key)); - if (srcStat.mtime < binStat.mtime) { - logger.info('Already in bin, skipping based on modified time: ' + key); - onFileWrite(); - return; - } - } - fs.writeFile(fname, JSON.stringify(table[key]), onFileWrite); - }) + FileGenerator( + srcFname, + fname, + function(cb) { + cb(JSON.stringify(table[key])); + }, + onFileWrite + ); }); } else { this.emit('code', src); From 132bc0350705c4f629e9e8ebdc270775447efc79 Mon Sep 17 00:00:00 2001 From: yofreke Date: Thu, 23 Jul 2015 01:00:06 -0700 Subject: [PATCH 05/23] remove old comments --- src/build/browser/browser-static/bootstrap.js | 93 ------------------- src/build/browser/html.js | 1 - 2 files changed, 94 deletions(-) diff --git a/src/build/browser/browser-static/bootstrap.js b/src/build/browser/browser-static/bootstrap.js index 8f55590..6009b5f 100644 --- a/src/build/browser/browser-static/bootstrap.js +++ b/src/build/browser/browser-static/bootstrap.js @@ -4,36 +4,6 @@ function bootstrap(initialImport, target) { var loc = w.location; var q = loc.search + loc.hash; - // check to see if we need chrome frame - // if (target && (target=="desktop" || target=="facebook") && /MSIE/i.test(navigator.userAgent) && !d.createElement('canvas').getContext) { - // var chromeframe_url = 'chromeframe.html' + (loc.search ? loc.search + "&" : "?") + "target="+ target; - // bootstrap = function() {}; - // try { - // var obj = new ActiveXObject('ChromeTab.ChromeFrame'); - // if (!obj) { - // throw "bad object"; - // } - // loc.replace(chromeframe_url); - // } catch(e) { - // w.onload = function() { - // var e = d.createElement('script'); - // e.async = true; - // e.src = "http://ajax.googleapis.com/ajax/libs/chrome-frame/1/CFInstall.min.js"; - // e.onreadystatechange= function () { - // if (this.readyState == 'loaded') { - // CFInstall.check({ - // mode: "overlay", - // oninstall: function() { loc.replace(chromeframe_url) }, - // url: "http://www.google.com/chromeframe/eula.html?user=true" - // }); - // } - // } - // d.getElementsByTagName('head')[0].appendChild(e); - // } - // } - // return; - // } - // for tracking when the page started loading w.__initialTime = +new Date(); @@ -75,18 +45,6 @@ function bootstrap(initialImport, target) { var mobile = (/(iPod|iPhone|iPad)/i.test(ua) ? 'ios' : /BlackBerry/.test(ua) ? 'blackberry' : /Mobile Safari/.test(ua) ? 'android' : ''); var isKik = /Kik\/\d/.test(ua); - // if (loc.search.match(/exportSettings=true/)) { - // // just export localStorage - // exportSettings(); - // } else if (mobile != 'blackberry' && !w.CONFIG.noRedirect) { - // // redirect based on device - // if (mobile && target != 'browser-mobile') { - // return loc.replace('//' + loc.host + '/browser-mobile/' + loc.hash); - // } else if (!mobile && target == 'browser-mobile') { - // return loc.replace('//' + loc.host + '/browser-desktop/' + loc.hash); - // } - // } - // set the viewport if (mobile == 'ios') { // Using initial-scale on android makes everything blurry! I think only IOS @@ -174,16 +132,6 @@ function bootstrap(initialImport, target) { if (mobile && supportedOrientations) { checkOrientation(); - // if (!orientationOk) { - // var el = d.body.appendChild(d.createElement('div')); - // el.innerHTML = 'please rotate your phone
\u21bb'; - // var width = d.body.offsetWidth; - // el.style.cssText = 'opacity:0;z-index:9000;color:#FFF;background:rgba(40,40,40,0.8);border-radius:25px;text-align:center;padding:' + width / 10 + 'px;font-size:' + width / 20 + 'px;position:absolute;left:50%;width:' + width * 5 / 8 + 'px;margin-left:-' + width * 5 / 16 + 'px;margin-top:80px;pointer-events:none'; - // w.addEventListener('resize', function () { - // checkOrientation(); - // el.style.display = orientationOk ? 'none': 'block'; - // }); - // } } var appCache = window.applicationCache; @@ -191,55 +139,14 @@ function bootstrap(initialImport, target) { appCache.addEventListener(evt, handleCacheEvent, false); }); - // status 0 == UNCACHED - // if (appCache.status) { - - // appCache.update(); // Attempt to update the user's cache. - // } - function handleCacheEvent(evt) { if (evt.type == 'updateready') { - // var el = d.body.appendChild(d.createElement('div')); - // el.style.cssText = 'opacity:0;position:absolute;z-index:9900000;top:-20px;margin:0px auto' - // + 'height:20px;width:200px;' - // + '-webkit-border-radius:0px 0px 5px 5px;' - // + '-webkit-transition:all 0.7s ease-in-out;' - // + '-webkit-transform:scale(' + w.devicePixelRatio + ');' - // + '-webkit-transform-origin:50% 0%;' - // + '-webkit-box-shadow:0px 2px 3px rgba(0, 0, 0, 0.4);' - // + 'background:rgba(0,0,0,0.7);color:#FFF;' - // + 'padding:10px 15px;' - // + 'font-size: 15px;'; - // + 'text-align: center;'; - // + 'cursor:pointer;'; - - // if (CONFIG.embeddedFonts && CONFIG.embeddedFonts.length) { - // el.style.fontFamily = CONFIG.embeddedFonts[0]; - // } - - // el.innerText = 'game updated! tap here'; - // el.style.left = (d.body.offsetWidth - 200) / 2 + 'px'; - - // el.setAttribute('noCapture', true); // prevent DevKit from stopping clicks on this event - // el.addEventListener('click', reload, true); - // el.addEventListener('touchstart', reload, true); - - // setTimeout(function () { - // el.style.top='0px'; - // el.style.opacity='1'; - // }, 0); - - // setTimeout(function () { - // el.style.top='-20px'; - // el.style.opacity='0'; - // }, 30000); console.log("update ready"); // reload immediately if splash is still visible var splash = d.getElementById('_GCSplash'); if (splash && splash.parentNode) { try { appCache.swapCache(); } catch (e) {} - //location.reload(); } } } diff --git a/src/build/browser/html.js b/src/build/browser/html.js index 1275555..dcbff34 100644 --- a/src/build/browser/html.js +++ b/src/build/browser/html.js @@ -180,7 +180,6 @@ exports.GameHTML = Class(function () { return total += src + '\n'; }, ''); - var js = this._js.join(';'); var jsCompiler = new JSCompiler(api, app); var compileJS = Promise.promisify(jsCompiler.compress, jsCompiler); From a4e26772483139087124cf5ed45831efe2d4e4a4 Mon Sep 17 00:00:00 2001 From: yofreke Date: Thu, 23 Jul 2015 01:01:06 -0700 Subject: [PATCH 06/23] partial load (for preloading only and then waiting) --- src/build/browser/browser-static/bootstrap.js | 41 +++++++++++--- src/build/browser/index.js | 10 +++- src/build/common/FileGenerator.js | 2 +- src/build/common/jsCompiler.js | 56 ++++++++++--------- 4 files changed, 73 insertions(+), 36 deletions(-) diff --git a/src/build/browser/browser-static/bootstrap.js b/src/build/browser/browser-static/bootstrap.js index 6009b5f..ec8bcd5 100644 --- a/src/build/browser/browser-static/bootstrap.js +++ b/src/build/browser/browser-static/bootstrap.js @@ -92,12 +92,39 @@ function bootstrap(initialImport, target) { var loaded = false; w._continueLoad = function() { - if (!loaded) { - loaded = true; - // Include the game code - var el = d.createElement('script'); - el.src = target + '.js'; - d.getElementsByTagName('head')[0].appendChild(el); + var doThings = function() { + if (!loaded) { + loaded = true; + // Include the game code + var el = d.createElement('script'); + el.src = target + '.js'; + d.getElementsByTagName('head')[0].appendChild(el); + } + }; + + var _continueLoadDefer; + + w.addEventListener('message', function(event) { + if (event.data === 'partialLoadContinue') { + if (_continueLoadDefer) { + _continueLoadDefer.resolve(); + _continueLoadDefer = undefined; + } + } + }); + // Preload suggestions and then tell the parent bootstrapping is complete + jsio.__env.preloadModules(function() { + w.parent.postMessage('bootstrapping', '*'); + }); + + var partialLoadKey = jsio.__env.getNamespace('partialLoad'); + if (localStorage && localStorage.getItem(partialLoadKey)) { + localStorage.removeItem(partialLoadKey); + + _continueLoadDefer = Promise.defer(); + _continueLoadDefer.promise.then(doThings); + } else { + doThings(); } }; @@ -192,6 +219,6 @@ function bootstrap(initialImport, target) { if (h > min) { increased = true; } min = h; // } - }, 50); + }, 20); } } diff --git a/src/build/browser/index.js b/src/build/browser/index.js index b59f32b..becb7ec 100644 --- a/src/build/browser/index.js +++ b/src/build/browser/index.js @@ -117,7 +117,13 @@ exports.build = function (api, app, config, cb) { function getPreloadJS() { // get preload JS if (/^native/.test(config.target)) { - return Promise.resolve('(window.jsio) ? (window._continueLoad()) : (jsio=function(){window._continueLoad()})'); + var preloadSrc; + if (config.isSimulated) { + preloadSrc = ''; + } else { + preloadSrc = '(window.jsio) ? (window._continueLoad()) : (jsio=function(){window._continueLoad()})'; + } + return Promise.resolve(preloadSrc); } var isLiveEdit = (config.target === 'live-edit'); @@ -287,7 +293,7 @@ exports.build = function (api, app, config, cb) { contents: new Buffer('NATIVE=false;' + 'CACHE=' + JSON.stringify(inlineCache) + ';\n' + jsSrc + ';' - + 'jsio.__env.preloadModules(function() { jsio("import ' + INITIAL_IMPORT + '"); });') + + 'jsio("import ' + INITIAL_IMPORT + '");') })); files.forEach(function (file) { diff --git a/src/build/common/FileGenerator.js b/src/build/common/FileGenerator.js index fe9bf42..ffd075e 100644 --- a/src/build/common/FileGenerator.js +++ b/src/build/common/FileGenerator.js @@ -154,7 +154,7 @@ module.exports.dynamic = function(sourceContents, output, generateFn, cb) { runGenerator({ sourceContents: sourceContents, outputPath: output, - generateFn: generateFn, + generateFn: generateFn || function(cb) { cb(null, sourceContents); }, cb: cb }); diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index 9116e56..601874a 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -229,25 +229,36 @@ var DevKitJsioInterface = Class(EventEmitter, function () { }; this._writeJsioBin = function(binPath) { - // Write the jsio_path.js + var tasks = []; + + // Write jsio_path.js var destPath = path.join(binPath, 'jsio_path.js'); var src = this._compiler.getCompiler().getPathJS(); - fs.writeFileSync(destPath, src); + tasks.push( + FileGenerator.dynamic(src, destPath) + ); - // Dont overwrite existing if mtime check fails + // Write jsio.js var srcPath = require.resolve('jsio'); var destPath = path.join(binPath, 'jsio.js'); - FileGenerator.sync(srcPath, destPath, function() { - var src = jsio.__jsio.__init__.toString(-1); - if (src.substring(0, 8) == 'function') { - src = 'jsio=(' + src + ')();'; + tasks.push(FileGenerator( + srcPath, + destPath, + function(cb) { + var src = jsio.__jsio.__init__.toString(-1); + if (src.substring(0, 8) == 'function') { + src = 'jsio=(' + src + ')();'; + } + cb(null, src); } - return src; - }); + )); + + return tasks; }; this.onFinish = function (opts, src, table) { var binPath = path.join(opts.outputPath, 'bin'); + var tasks = []; // Only call mkdirp once if (opts.separateJsio || opts.individualCompile) { @@ -256,38 +267,31 @@ var DevKitJsioInterface = Class(EventEmitter, function () { // maybe write out a new jsio if (opts.separateJsio) { - this._writeJsioBin(binPath); + tasks.concat(this._writeJsioBin(binPath)); } if (opts.individualCompile) { var keys = Object.keys(table); logger.info('Writing individual compile files: ' + keys.length); - var complete = 0; - - var onFileWrite = function(err) { - if (err) throw err; - complete++; - if (complete === keys.length) { - this.emit('code', src); - } - }.bind(this); - keys.forEach(function(key) { var srcFname = path.join(opts.cwd, key); var fname = path.join(binPath, key.replace(/\//g, '.')); - FileGenerator( + tasks.push(FileGenerator( srcFname, fname, function(cb) { cb(JSON.stringify(table[key])); - }, - onFileWrite - ); + } + )); }); - } else { - this.emit('code', src); } + + Promise.all(tasks) + .bind(this) + .then(function() { + this.emit('code', src); + }); }; /** From 48b50ee4312e88e12864abac4c69b3226d480d53 Mon Sep 17 00:00:00 2001 From: yofreke Date: Thu, 23 Jul 2015 03:07:09 -0700 Subject: [PATCH 07/23] use FileGenerator for index.html and native-ios.js --- node_modules/jsio | 2 +- src/build/browser/index.js | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/node_modules/jsio b/node_modules/jsio index c3a69a0..ce91cf9 160000 --- a/node_modules/jsio +++ b/node_modules/jsio @@ -1 +1 @@ -Subproject commit c3a69a08908ba53055a5bea157644257f128d8c9 +Subproject commit ce91cf9106930a67d2a7c0f9466cd12219319133 diff --git a/src/build/browser/index.js b/src/build/browser/index.js index becb7ec..fce4be5 100644 --- a/src/build/browser/index.js +++ b/src/build/browser/index.js @@ -62,6 +62,7 @@ exports.build = function (api, app, config, cb) { // var newer = require('gulp-newer'); var slash = require('slash'); var streamFromArray = require('stream-from-array'); + var FileGenerator = require('../common/FileGenerator'); var readFile = Promise.promisify(fs.readFile); @@ -253,13 +254,10 @@ exports.build = function (api, app, config, cb) { var hasIndexPage = !isMobile; tasks.push(gameHTML.generate(api, app, config) .then(function (html) { - files.push(new File({ - base: baseDirectory, - path: path.join(baseDirectory, hasIndexPage + var destPath = path.join(baseDirectory, hasIndexPage ? 'game.html' - : 'index.html'), - contents: new Buffer(html) - })); + : 'index.html') + return FileGenerator.dynamic(html, destPath); })); if (hasIndexPage) { @@ -287,14 +285,6 @@ exports.build = function (api, app, config, cb) { .then(function (files) { endTime('inline-cache'); startTime('files'); - files.push(new File({ - base: baseDirectory, - path: path.join(baseDirectory, config.target + '.js'), - contents: new Buffer('NATIVE=false;' - + 'CACHE=' + JSON.stringify(inlineCache) + ';\n' - + jsSrc + ';' - + 'jsio("import ' + INITIAL_IMPORT + '");') - })); files.forEach(function (file) { if (file.history.length > 1) { @@ -400,6 +390,14 @@ exports.build = function (api, app, config, cb) { }) .on('error', reject); }); + }) + .then(function() { + var src = 'NATIVE=false;' + + 'CACHE=' + JSON.stringify(inlineCache) + ';\n' + + jsSrc + ';' + + 'jsio("import ' + INITIAL_IMPORT + '");'; + var destPath = path.join(baseDirectory, config.target + '.js'); + return FileGenerator.dynamic(src, destPath); }); }).then(function () { endTime('browser-main'); From f500a0a683e8a93dafc3a1ca9dbd08f0746116bb Mon Sep 17 00:00:00 2001 From: yofreke Date: Thu, 23 Jul 2015 18:04:01 -0700 Subject: [PATCH 08/23] support for new simulator (fake) spritesheet maps --- src/build/browser/index.js | 64 +++------------ src/build/common/jsCompiler.js | 2 - src/build/common/spritesheetMapGenerator.js | 89 +++++++++++++++++++++ src/clientapi/index.js | 23 ++++-- 4 files changed, 116 insertions(+), 62 deletions(-) create mode 100644 src/build/common/spritesheetMapGenerator.js diff --git a/src/build/browser/index.js b/src/build/browser/index.js index fce4be5..a164ac9 100644 --- a/src/build/browser/index.js +++ b/src/build/browser/index.js @@ -43,18 +43,10 @@ exports.configure = function (api, app, config, cb) { cb && cb(); }; -var _timeLogger = null; -var _times = {}; -function startTime(name) { - _times[name] = new Date().getTime(); -} -function endTime(name) { - _timeLogger.info(name + ': ' + (new Date().getTime() - _times[name])); - delete _times[name]; -} - exports.build = function (api, app, config, cb) { + config.spriteImages = false; + var printf = require('printf'); var fs = require('graceful-fs'); var File = require('vinyl'); @@ -66,54 +58,33 @@ exports.build = function (api, app, config, cb) { var readFile = Promise.promisify(fs.readFile); - // config.spriteImages = false; logger = api.logging.get('build-browser'); - _timeLogger = api.logging.get('--------TIMER--------'); - - startTime('browser-main'); - startTime('setup-require'); var isMobile = (config.target !== 'browser-desktop'); var isLiveEdit = (config.target === 'live-edit'); - //console.time('import-1') var resources = require('../common/resources'); - //console.timeEnd('import-1') - //console.time('import-2') var CSSFontList = require('./fonts').CSSFontList; - //console.timeEnd('import-2') - //console.time('import-3') var JSConfig = require('../common/jsConfig').JSConfig; - //console.timeEnd('import-3') - //console.time('import-4') var JSCompiler = require('../common/jsCompiler').JSCompiler; - //console.timeEnd('import-4') var sprite = null; if (config.spriteImages) { sprite = require('../common/spriter') - .sprite - .bind(null, api, app, config); + .sprite + .bind(null, api, app, config); + } else { + sprite = require('../common/spritesheetMapGenerator') + .sprite + .bind(null, api, app, config); } - //console.time('import-5') var html = require('./html'); - //console.timeEnd('import-5') - //console.time('import-6') var gameHTML = new html.GameHTML(config); - //console.timeEnd('import-6') - //console.time('import-7') var fontList = new CSSFontList(); - //console.timeEnd('import-7') - //console.time('import-8') var jsConfig = new JSConfig(api, app, config); - //console.timeEnd('import-8') - //console.time('import-9') var jsCompiler = new JSCompiler(api, app, config, jsConfig); - //console.timeEnd('import-9') - //console.time('import-10') var compileJS = Promise.promisify(jsCompiler.compile, jsCompiler); - //console.timeEnd('import-10') function getPreloadJS() { // get preload JS @@ -162,9 +133,6 @@ exports.build = function (api, app, config, cb) { var baseDirectory = config.outputResourcePath; - endTime('setup-require'); - startTime('main-spread'); - resources.getDirectories(api, app, config) .then(function (directories) { var compileOpts = { @@ -180,19 +148,19 @@ exports.build = function (api, app, config, cb) { compileOpts.includeJsio = false; compileOpts.separateJsio = true; } + return Promise.all([ - resources.getFiles(baseDirectory, directories), + config.isSimulated ? resources.getFiles(baseDirectory, directories) : [], readFile(getLocalFilePath('../../clientapi/browser/cache-worker.js'), 'utf8'), getPreloadJS(), readFile(STATIC_BOOTSTRAP_JS, 'utf8'), isLiveEdit && readFile(STATIC_LIVE_EDIT_JS, 'utf8'), - config.spriteImages !== false && sprite(directories), + sprite(directories), compileJS(compileOpts) ]); }) .spread(function (files, cacheWorkerJS, preloadJS, bootstrapJS, liveEditJS, spriterResult, jsSrc) { - endTime('main-spread'); logger.log('Creating HTML and JavaScript...'); jsConfig.add('embeddedFonts', fontList.getNames()); @@ -272,7 +240,6 @@ exports.build = function (api, app, config, cb) { })); } - startTime('inline-cache'); var InlineCache = require('../common/inlineCache').InlineCache; var inlineCache = new InlineCache(logger); var addToInlineCache = inlineCache.add.bind(inlineCache); @@ -283,9 +250,6 @@ exports.build = function (api, app, config, cb) { .filter(addToInlineCache); }) .then(function (files) { - endTime('inline-cache'); - startTime('files'); - files.forEach(function (file) { if (file.history.length > 1) { sourceMap[slash(file.relative)] = file.history[0]; @@ -377,15 +341,12 @@ exports.build = function (api, app, config, cb) { }); // https://github.com/petkaantonov/bluebird/issues/332 - logger.log('Writing files...' + files.length); - startTime('files-write'); + logger.log('Writing ' + files.length + ' files...'); return new Promise(function (resolve, reject) { streamFromArray.obj(files) // .pipe(newer(baseDirectory)) .pipe(vfs.dest(baseDirectory)) .on('end', function() { - endTime('files-write'); - endTime('files'); resolve(); }) .on('error', reject); @@ -400,7 +361,6 @@ exports.build = function (api, app, config, cb) { return FileGenerator.dynamic(src, destPath); }); }).then(function () { - endTime('browser-main'); logger.log('Done'); }).nodeify(cb); }; diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index 601874a..3d81011 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -50,7 +50,6 @@ exports.JSCompiler = Class(function () { }; this.compile = function (opts, cb) { - console.time('JS_COMPILE') var opts = merge({}, opts, this._opts); var appPath = this._app.paths.root; @@ -116,7 +115,6 @@ exports.JSCompiler = Class(function () { jsioOpts.interface = new DevKitJsioInterface(this) .on('error', cb) .on('code', function (code) { - console.timeEnd('JS_COMPILE') cb && cb(null, code); }); diff --git a/src/build/common/spritesheetMapGenerator.js b/src/build/common/spritesheetMapGenerator.js new file mode 100644 index 0000000..0d35cff --- /dev/null +++ b/src/build/common/spritesheetMapGenerator.js @@ -0,0 +1,89 @@ + +var path = require('path'); +var glob = Promise.promisify(require('glob')); +var File = require('vinyl'); +var sizeOf = require('image-size'); + +var spritePattern = /((?:.*)\/.*?)[-_ ](.*?)[-_ ](\d+)/; +var allowedPattern = /\.png$|\.jpg$|\.jpeg$/; + +// TODO: implement source map +exports.sprite = function (api, app, config, directories) { + var baseDirectory = config.outputResourcePath; + var relativeSpritesheetsDirectory = 'spritesheets'; + var spritesheetsDirectory = path.join(baseDirectory, + relativeSpritesheetsDirectory); + + var sheetMap = {}; + var sourceMap = {}; + + return Promise.resolve(directories) + .map(exports.spriteDirectory.bind(exports, api, config)) + .each(function (allFiles) { + allFiles.forEach(function(file) { + // TODO: Put all the files in to a single object, then return it + if (file.info) { + sheetMap[file.target] = file.info; + } + + sourceMap[file.originalRelativePath] = true; + }); + }) + .then(function () { + // Needs to return: sourceMap{}, files[] + var obj = { + files: [ + new File({ + base: baseDirectory, + path: path.join(spritesheetsDirectory, + 'map.json'), + contents: new Buffer(JSON.stringify(sheetMap)) + }) + ], + sourceMap: sourceMap + }; + return obj; + }); +}; + +/** Walk the dir, get all the sprite files */ +exports.spriteDirectory = function (api, config, directory) { + var files = []; + + var root = directory.src; + return glob('**/*', {cwd: root, nodir: true}) + .map(function (filename) { + + if (!allowedPattern.exec(filename)) { + return; + } + + var srcPath = path.join(root, filename); + // var relativeRoot = root.substring(directory.src.length + 1, root.length); + var target = path.join(directory.target, filename); + + var fileData = { + src: srcPath, + target: target, + originalRelativePath: filename, + info: exports.makeInfoFor(srcPath, target) + }; + + files.push(fileData); + }) + .then(function() { + return files; + }); +}; + +/** Make a spritesheets/map.json info object for this path */ +exports.makeInfoFor = function(path, target) { + var dimensions = sizeOf(path); + + var info = { + w: dimensions.width, + h: dimensions.height + }; + + return info; +}; diff --git a/src/clientapi/index.js b/src/clientapi/index.js index d1bc8c2..d489066 100644 --- a/src/clientapi/index.js +++ b/src/clientapi/index.js @@ -118,18 +118,25 @@ exports.ClientAPI = Class(lib.PubSub, function () { import .UI; this.ui = new UI(); - - // this.track({ - // name: "campaignID", - // category: "campaign", - // subcategory: "id", - // data: campaign - // }); - var map; try { if (GLOBAL.CACHE) { map = JSON.parse(GLOBAL.CACHE['spritesheets/map.json']); + + // Add some defaults + for (var key in map) { + var entry = map[key]; + entry.marginLeft = entry.marginLeft !== undefined ? entry.marginLeft : 0; + entry.marginRight = entry.marginRight !== undefined ? entry.marginRight : 0; + entry.marginTop = entry.marginTop !== undefined ? entry.marginTop : 0; + entry.marginBottom = entry.marginBottom !== undefined ? entry.marginBottom : 0; + + entry.x = entry.x !== undefined ? entry.x : 0; + entry.y = entry.y !== undefined ? entry.y : 0; + entry.scale = entry.scale !== undefined ? entry.scale : 0; + + entry.sheet = entry.sheet !== undefined ? entry.sheet : key; + } } } catch (e) { logger.warn("spritesheet map failed to parse", e); From 8059d067a86e84e83c4c4f3d2a55d746d13cc61f Mon Sep 17 00:00:00 2001 From: yofreke Date: Mon, 27 Jul 2015 17:16:56 -0700 Subject: [PATCH 09/23] clean up + ensure broswer and native builds work --- src/build/browser/index.js | 21 +++++---------------- src/build/common/jsCompiler.js | 5 ----- src/build/native/env.js | 21 +++++++++++++++++++++ 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/build/browser/index.js b/src/build/browser/index.js index a164ac9..4b3e490 100644 --- a/src/build/browser/index.js +++ b/src/build/browser/index.js @@ -45,8 +45,6 @@ exports.configure = function (api, app, config, cb) { exports.build = function (api, app, config, cb) { - config.spriteImages = false; - var printf = require('printf'); var fs = require('graceful-fs'); var File = require('vinyl'); @@ -68,7 +66,7 @@ exports.build = function (api, app, config, cb) { var JSCompiler = require('../common/jsCompiler').JSCompiler; var sprite = null; - if (config.spriteImages) { + if (config.spriteImages && !config.isSimulated) { sprite = require('../common/spriter') .sprite .bind(null, api, app, config); @@ -88,13 +86,9 @@ exports.build = function (api, app, config, cb) { function getPreloadJS() { // get preload JS - if (/^native/.test(config.target)) { - var preloadSrc; - if (config.isSimulated) { - preloadSrc = ''; - } else { - preloadSrc = '(window.jsio) ? (window._continueLoad()) : (jsio=function(){window._continueLoad()})'; - } + if (/^native/.test(config.target) && !config.isSimulated) { + var preloadSrc = '(window.jsio) ? (window._continueLoad()) : (jsio=function(){window._continueLoad()})'; + return Promise.resolve(preloadSrc); } @@ -143,11 +137,6 @@ exports.build = function (api, app, config, cb) { debug: config.scheme === 'debug', preCompress: config.preCompressCallback }; - if (config.isSimulated) { - compileOpts.noCompile = true; - compileOpts.includeJsio = false; - compileOpts.separateJsio = true; - } return Promise.all([ config.isSimulated ? resources.getFiles(baseDirectory, directories) : [], @@ -156,7 +145,7 @@ exports.build = function (api, app, config, cb) { readFile(STATIC_BOOTSTRAP_JS, 'utf8'), isLiveEdit && readFile(STATIC_LIVE_EDIT_JS, 'utf8'), sprite(directories), - compileJS(compileOpts) + config.isSimulated ? '' : compileJS(compileOpts) ]); }) .spread(function (files, cacheWorkerJS, preloadJS, bootstrapJS, diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index 3d81011..51fddff 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -258,11 +258,6 @@ var DevKitJsioInterface = Class(EventEmitter, function () { var binPath = path.join(opts.outputPath, 'bin'); var tasks = []; - // Only call mkdirp once - if (opts.separateJsio || opts.individualCompile) { - mkdirp.sync(binPath); - } - // maybe write out a new jsio if (opts.separateJsio) { tasks.concat(this._writeJsioBin(binPath)); diff --git a/src/build/native/env.js b/src/build/native/env.js index ee940c6..c3b33f0 100644 --- a/src/build/native/env.js +++ b/src/build/native/env.js @@ -602,6 +602,27 @@ var JSIO_ENV_CTOR = function() { this.getPath = function() { return './sdk/jsio/'; }; this.eval = function(code, path) { return NATIVE.eval(code, path); }; this.fetch = function(filePath) { return false; } + + this.getNamespace = function(key) { return CONFIG.shortName + ':' + key }; + this.hasFetchFailed = function() { return false; }; + this.setFetchFailed = function() {}; + this.registerFoundModule = function() {}; + this.preloadModules = function(cb) { cb(); }; + + var srcCache; + this.setCache = function(cache) { srcCache = cache; }; + + this.setCachedSrc = function(path, src, locked) { + if (srcCache[path] && srcCache[path].locked) { + console.warn('Cache is ignoring (already present and locked) src ' + path); + return; + } + srcCache[path] = { path: path, src: src, locked: locked }; + }; + this.getCachedSrc = function(path) { + return srcCache[path]; + }; + }; NATIVE.console.log(NATIVE.location); From 64fc51b389f64efa295b2247a07a9cf654f73dd9 Mon Sep 17 00:00:00 2001 From: yofreke Date: Mon, 27 Jul 2015 17:30:40 -0700 Subject: [PATCH 10/23] moved jsio dependency back to package.json --- .gitmodules | 3 --- node_modules/jsio | 1 - package.json | 4 ++-- 3 files changed, 2 insertions(+), 6 deletions(-) delete mode 160000 node_modules/jsio diff --git a/.gitmodules b/.gitmodules index daeb1dd..220494d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,6 +10,3 @@ [submodule "modules/squill"] path = modules/squill url = https://github.com/gameclosure/squill -[submodule "node_modules/jsio"] - path = node_modules/jsio - url = https://github.com/gameclosure/js.io diff --git a/node_modules/jsio b/node_modules/jsio deleted file mode 160000 index ce91cf9..0000000 --- a/node_modules/jsio +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ce91cf9106930a67d2a7c0f9466cd12219319133 diff --git a/package.json b/package.json index 9b68f5b..8b2f693 100644 --- a/package.json +++ b/package.json @@ -15,8 +15,8 @@ "fs-extra": "^0.18.4", "glob": "^5.0.2", "graceful-fs": "^3.0.2", - "image-size": "0.3.2", - "jsio": "^2.1.0", + "image-size": "^0.3.2", + "jsio": "git+https://github.com/gameclosure/js.io#feat-noCompile", "mime": "1.2.11", "mkdirp": "0.5.0", "nib": "1.0.3", From 8ddc08590b58d6cd8e48d9589702226f619ef7ef Mon Sep 17 00:00:00 2001 From: yofreke Date: Mon, 27 Jul 2015 17:40:45 -0700 Subject: [PATCH 11/23] update spritesheetmapgenerator comments --- src/build/common/spritesheetMapGenerator.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/build/common/spritesheetMapGenerator.js b/src/build/common/spritesheetMapGenerator.js index 0d35cff..6288c7b 100644 --- a/src/build/common/spritesheetMapGenerator.js +++ b/src/build/common/spritesheetMapGenerator.js @@ -7,7 +7,8 @@ var sizeOf = require('image-size'); var spritePattern = /((?:.*)\/.*?)[-_ ](.*?)[-_ ](\d+)/; var allowedPattern = /\.png$|\.jpg$|\.jpeg$/; -// TODO: implement source map +/** Don't actually sprite these directories, just build the map in the same way the + spriter would (so that the client knows what sprites are available) */ exports.sprite = function (api, app, config, directories) { var baseDirectory = config.outputResourcePath; var relativeSpritesheetsDirectory = 'spritesheets'; @@ -21,7 +22,6 @@ exports.sprite = function (api, app, config, directories) { .map(exports.spriteDirectory.bind(exports, api, config)) .each(function (allFiles) { allFiles.forEach(function(file) { - // TODO: Put all the files in to a single object, then return it if (file.info) { sheetMap[file.target] = file.info; } From 3ec9fd5684faa0ad7312c7e69f9067f97a649f76 Mon Sep 17 00:00:00 2001 From: yofreke Date: Fri, 31 Jul 2015 14:31:17 -0700 Subject: [PATCH 12/23] doThings -> loadTargetJS --- src/build/browser/browser-static/bootstrap.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/build/browser/browser-static/bootstrap.js b/src/build/browser/browser-static/bootstrap.js index ec8bcd5..3d0210d 100644 --- a/src/build/browser/browser-static/bootstrap.js +++ b/src/build/browser/browser-static/bootstrap.js @@ -92,7 +92,7 @@ function bootstrap(initialImport, target) { var loaded = false; w._continueLoad = function() { - var doThings = function() { + var loadTargetJS = function() { if (!loaded) { loaded = true; // Include the game code @@ -122,9 +122,9 @@ function bootstrap(initialImport, target) { localStorage.removeItem(partialLoadKey); _continueLoadDefer = Promise.defer(); - _continueLoadDefer.promise.then(doThings); + _continueLoadDefer.promise.then(loadTargetJS); } else { - doThings(); + loadTargetJS(); } }; From e655fa46d8a850fc7074cc9ba67ad05a876e1a80 Mon Sep 17 00:00:00 2001 From: yofreke Date: Fri, 31 Jul 2015 14:33:29 -0700 Subject: [PATCH 13/23] lower case FileGenerator --- src/build/browser/html.js | 6 +++--- src/build/browser/index.js | 6 +++--- src/build/common/jsCompiler.js | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/build/browser/html.js b/src/build/browser/html.js index 10e0391..1bcd630 100644 --- a/src/build/browser/html.js +++ b/src/build/browser/html.js @@ -5,7 +5,7 @@ var printf = require('printf'); var JSCompiler = require('../common/jsCompiler').JSCompiler; var getBase64Image = require('./datauri').getBase64Image; -var FileGenerator = require('../common/FileGenerator'); +var fileGenerator = require('../common/fileGenerator'); var TARGET_APPLE_TOUCH_ICON_SIZE = 152; @@ -105,7 +105,7 @@ exports.GameHTML = Class(function () { var dest = path.join(this._binPath, 'css', name.replace(/\//g, '_')); var shouldCompress = this._config.compress; - this._css.push(FileGenerator.dynamic( + this._css.push(fileGenerator.dynamic( css, dest, function(cb) { @@ -118,7 +118,7 @@ exports.GameHTML = Class(function () { var dest = path.join(this._binPath, 'css', cssPath.replace(/\//g, '_')); var shouldCompress = this._config.compress; - this._css.push(FileGenerator( + this._css.push(fileGenerator( cssPath, dest, function(cb) { diff --git a/src/build/browser/index.js b/src/build/browser/index.js index 79ed0f0..63330d0 100644 --- a/src/build/browser/index.js +++ b/src/build/browser/index.js @@ -52,7 +52,7 @@ exports.build = function (api, app, config, cb) { // var newer = require('gulp-newer'); var slash = require('slash'); var streamFromArray = require('stream-from-array'); - var FileGenerator = require('../common/FileGenerator'); + var fileGenerator = require('../common/fileGenerator'); var readFile = Promise.promisify(fs.readFile); @@ -214,7 +214,7 @@ exports.build = function (api, app, config, cb) { var destPath = path.join(baseDirectory, hasIndexPage ? 'game.html' : 'index.html') - return FileGenerator.dynamic(html, destPath); + return fileGenerator.dynamic(html, destPath); })); if (hasIndexPage) { @@ -345,7 +345,7 @@ exports.build = function (api, app, config, cb) { jsSrc + ';' + 'jsio("import ' + INITIAL_IMPORT + '");'; var destPath = path.join(baseDirectory, config.target + '.js'); - return FileGenerator.dynamic(src, destPath); + return fileGenerator.dynamic(src, destPath); }); }) .nodeify(cb); diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index 5cbfca2..4980694 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -9,7 +9,7 @@ var EventEmitter = require('events').EventEmitter; // clone to modify the path for this jsio but not any others var jsio = require('jsio').clone(); // ~10ms -var FileGenerator = require('./FileGenerator'); +var fileGenerator = require('./fileGenerator'); function deepCopy(obj) { return obj && JSON.parse(JSON.stringify(obj)); } @@ -237,13 +237,13 @@ var DevKitJsioInterface = Class(EventEmitter, function () { var destPath = path.join(binPath, 'jsio_path.js'); var src = this._compiler.getCompiler().getPathJS(); tasks.push( - FileGenerator.dynamic(src, destPath) + fileGenerator.dynamic(src, destPath) ); // Write jsio.js var srcPath = require.resolve('jsio'); var destPath = path.join(binPath, 'jsio.js'); - tasks.push(FileGenerator( + tasks.push(fileGenerator( srcPath, destPath, function(cb) { @@ -274,7 +274,7 @@ var DevKitJsioInterface = Class(EventEmitter, function () { keys.forEach(function(key) { var srcFname = path.join(opts.cwd, key); var fname = path.join(binPath, key.replace(/\//g, '.')); - tasks.push(FileGenerator( + tasks.push(fileGenerator( srcFname, fname, function(cb) { From 2b88f4998d544a593c9eaf076f5e320d59ef618f Mon Sep 17 00:00:00 2001 From: yofreke Date: Fri, 31 Jul 2015 14:43:37 -0700 Subject: [PATCH 14/23] normal convention --- src/build/common/FileGenerator.js | 32 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/src/build/common/FileGenerator.js b/src/build/common/FileGenerator.js index ffd075e..0a4be3e 100644 --- a/src/build/common/FileGenerator.js +++ b/src/build/common/FileGenerator.js @@ -13,22 +13,22 @@ var hashString = function(str) { return md5sum.digest('hex'); }; -var runGenerator = function(opts) { +var runGenerator = function(opts, cb) { var doWrite = function(err, src) { mkdirp(path.dirname(opts.outputPath), function(err) { - if (err) { opts.cb(err); return; } + if (err) { cb(err); return; } fs.writeFile(opts.outputPath, src, function(err) { - if (err) { opts.cb(err); return; } + if (err) { cb(err); return; } // For dynamic calls the hash should be that of the input string, not the output file if (opts.useInputHash) { fs.writeFile(opts.outputHashPath, opts.inputHash, function(err) { - if (err) { opts.cb(err); return; } - opts.cb(null, src); + if (err) { cb(err); return; } + cb(null, src); }); } else { - opts.cb(null, src); + cb(null, src); } }); @@ -38,18 +38,18 @@ var runGenerator = function(opts) { var useOldOutput = function() { // Old one is still good, just read it fs.readFile(opts.outputPath, 'utf8', function(err, src) { - if (err) { opts.cb(err); return; } + if (err) { cb(err); return; } - opts.cb(null, src); + cb(null, src); }); } var checkModifiedTimes = function() { fs.stat(opts.sourcePath, function(err, srcStat) { - if (err) { opts.cb(err); return; } + if (err) { cb(err); return; } fs.stat(opts.outputPath, function(err, existingStat) { - if (err) { opts.cb(err); return; } + if (err) { cb(err); return; } if (existingStat.mtime > srcStat.mtime) { useOldOutput(); @@ -73,7 +73,7 @@ var runGenerator = function(opts) { // Check the hashes fs.readFile(opts.outputHashPath, 'utf-8', function(err, outputHash) { - if (err) { opts.cb(err); return; } + if (err) { cb(err); return; } if (opts.inputHash === outputHash) { useOldOutput(); @@ -127,9 +127,8 @@ module.exports = function(source, output, generateFn, cb) { runGenerator({ sourcePath: source, outputPath: output, - generateFn: generateFn, - cb: cb - }); + generateFn: generateFn + }, cb); return def ? def.promise : undefined; }; @@ -154,9 +153,8 @@ module.exports.dynamic = function(sourceContents, output, generateFn, cb) { runGenerator({ sourceContents: sourceContents, outputPath: output, - generateFn: generateFn || function(cb) { cb(null, sourceContents); }, - cb: cb - }); + generateFn: generateFn || function(cb) { cb(null, sourceContents); } + }, cb); return def ? def.promise : undefined; }; From 9132381ef39f4325227e7c43ff82b9060cceb62b Mon Sep 17 00:00:00 2001 From: yofreke Date: Fri, 31 Jul 2015 15:54:24 -0700 Subject: [PATCH 15/23] normal import Promise --- src/clientapi/browser/launchClient.js | 2 +- src/clientapi/native/launchClient.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/clientapi/browser/launchClient.js b/src/clientapi/browser/launchClient.js index 72bdb4a..ba25ed2 100644 --- a/src/clientapi/browser/launchClient.js +++ b/src/clientapi/browser/launchClient.js @@ -19,7 +19,7 @@ // no dynamic source fetching // jsio.__env.fetch = function (filename) { return false; }; -import ..api.Promise as Promise; +import Promise; GLOBAL.Promise = Promise; var isSimulator = GLOBAL.CONFIG && !!CONFIG.simulator; diff --git a/src/clientapi/native/launchClient.js b/src/clientapi/native/launchClient.js index 1445a36..4437578 100644 --- a/src/clientapi/native/launchClient.js +++ b/src/clientapi/native/launchClient.js @@ -20,7 +20,7 @@ GLOBAL.console = logging.get('console'); window.self = window; // add bluebird promise implementation to global scope -import ..api.Promise as Promise; +import Promise; GLOBAL.Promise = Promise; // initialize native JS API wrappers From b859881b550cbd710cefad551fa2ecd0d711f1a3 Mon Sep 17 00:00:00 2001 From: yofreke Date: Fri, 31 Jul 2015 15:57:08 -0700 Subject: [PATCH 16/23] osx being bad at capitals --- src/build/common/{FileGenerator.js => fileGenerator.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/build/common/{FileGenerator.js => fileGenerator.js} (100%) diff --git a/src/build/common/FileGenerator.js b/src/build/common/fileGenerator.js similarity index 100% rename from src/build/common/FileGenerator.js rename to src/build/common/fileGenerator.js From 7b4cdbc26af6d859f4277d21aad26c5ffa29467e Mon Sep 17 00:00:00 2001 From: yofreke Date: Mon, 3 Aug 2015 23:06:01 -0700 Subject: [PATCH 17/23] remove promise --- src/build/browser/browser-static/bootstrap.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/build/browser/browser-static/bootstrap.js b/src/build/browser/browser-static/bootstrap.js index 3d0210d..ff8caa5 100644 --- a/src/build/browser/browser-static/bootstrap.js +++ b/src/build/browser/browser-static/bootstrap.js @@ -102,13 +102,13 @@ function bootstrap(initialImport, target) { } }; - var _continueLoadDefer; + var _continueLoadCallback; w.addEventListener('message', function(event) { if (event.data === 'partialLoadContinue') { - if (_continueLoadDefer) { - _continueLoadDefer.resolve(); - _continueLoadDefer = undefined; + if (_continueLoadCallback) { + _continueLoadCallback(); + _continueLoadCallback = undefined; } } }); @@ -120,9 +120,7 @@ function bootstrap(initialImport, target) { var partialLoadKey = jsio.__env.getNamespace('partialLoad'); if (localStorage && localStorage.getItem(partialLoadKey)) { localStorage.removeItem(partialLoadKey); - - _continueLoadDefer = Promise.defer(); - _continueLoadDefer.promise.then(loadTargetJS); + _continueLoadCallback = loadTargetJS; } else { loadTargetJS(); } From 473350d11870d42ba79bf13ec8937246c78d27b6 Mon Sep 17 00:00:00 2001 From: yofreke Date: Wed, 5 Aug 2015 01:56:29 +0000 Subject: [PATCH 18/23] mkdirp -> fs-extra.mkdirp --- package.json | 1 - src/build/common/fileGenerator.js | 5 ++--- src/build/common/jsCompiler.js | 5 ++--- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index a50a12c..6ba47d4 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,6 @@ "image-size": "^0.3.2", "jsio": "git+https://github.com/gameclosure/js.io#feat-noCompile", "mime": "1.2.11", - "mkdirp": "0.5.0", "nib": "1.0.3", "optimist": "^0.6.1", "printf": "0.2.0", diff --git a/src/build/common/fileGenerator.js b/src/build/common/fileGenerator.js index 0a4be3e..e8943b3 100644 --- a/src/build/common/fileGenerator.js +++ b/src/build/common/fileGenerator.js @@ -1,7 +1,6 @@ -var fs = require('fs'); +var fs = require('fs-extra'); var path = require('path'); -var mkdirp = require('mkdirp'); var crypto = require('crypto'); @@ -15,7 +14,7 @@ var hashString = function(str) { var runGenerator = function(opts, cb) { var doWrite = function(err, src) { - mkdirp(path.dirname(opts.outputPath), function(err) { + fs.mkdirp(path.dirname(opts.outputPath), function(err) { if (err) { cb(err); return; } fs.writeFile(opts.outputPath, src, function(err) { diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index 4980694..791adea 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -1,9 +1,8 @@ var path = require('path'); -var fs = require('fs'); +var fs = require('fs-extra'); var crypto = require('crypto'); var argv = require('optimist').argv; -var mkdirp = require('mkdirp'); var EventEmitter = require('events').EventEmitter; // clone to modify the path for this jsio but not any others @@ -128,7 +127,7 @@ exports.JSCompiler = Class(function () { // ignored, but traditionally should be the name of the executable?) // Compile the game code - mkdirp(jsCachePath, function () { + fs.mkdirp(jsCachePath, function () { compiler.start(['jsio_compile', jsioOpts.cwd || '.', importStatement], jsioOpts); }); }; From 0bbfc5268cec807f6c8596b2d62fa3f5f3e9598a Mon Sep 17 00:00:00 2001 From: yofreke Date: Wed, 5 Aug 2015 10:56:06 +0000 Subject: [PATCH 19/23] no more server side compilation still need to finalize this --- src/build/browser/index.js | 55 ++++++++++++++++++----- src/build/common/jsCompiler.js | 81 ++++++++++++++++++++++++++++------ 2 files changed, 113 insertions(+), 23 deletions(-) diff --git a/src/build/browser/index.js b/src/build/browser/index.js index 63330d0..7309c20 100644 --- a/src/build/browser/index.js +++ b/src/build/browser/index.js @@ -63,7 +63,7 @@ exports.build = function (api, app, config, cb) { var resources = require('../common/resources'); var CSSFontList = require('./fonts').CSSFontList; var JSConfig = require('../common/jsConfig').JSConfig; - var JSCompiler = require('../common/jsCompiler').JSCompiler; + var JSCompiler = require('../common/jsCompiler'); var sprite = null; if (config.spriteImages && !config.isSimulated) { @@ -80,13 +80,12 @@ exports.build = function (api, app, config, cb) { var gameHTML = new html.GameHTML(config); var fontList = new CSSFontList(); var jsConfig = new JSConfig(api, app, config); - var jsCompiler = new JSCompiler(api, app, config, jsConfig); + var jsCompiler = new JSCompiler.JSCompiler(api, app, config, jsConfig); var compileJS = Promise.promisify(jsCompiler.compile, jsCompiler); function getPreloadJS() { - // get preload JS - if (/^native/.test(config.target) && !config.isSimulated) { + if (/^native/.test(config.target)) { var preloadSrc = '(window.jsio) ? (window._continueLoad()) : (jsio=function(){window._continueLoad()})'; return Promise.resolve(preloadSrc); @@ -117,11 +116,6 @@ exports.build = function (api, app, config, cb) { appendImport: false, preCompress: config.preCompressCallback }; - if (config.isSimulated) { - compileOpts.noCompile = true; - compileOpts.includeJsio = false; - compileOpts.separateJsio = true; - } return compileJS(compileOpts); } @@ -141,7 +135,7 @@ exports.build = function (api, app, config, cb) { return Promise.all([ config.isSimulated ? resources.getFiles(baseDirectory, directories) : [], readFile(getLocalFilePath('../../clientapi/browser/cache-worker.js'), 'utf8'), - getPreloadJS(), + config.isSimulated ? '' : getPreloadJS(), readFile(STATIC_BOOTSTRAP_JS, 'utf8'), isLiveEdit && readFile(STATIC_LIVE_EDIT_JS, 'utf8'), config.spritesheets || config.spriteImages !== false && sprite(directories), @@ -204,6 +198,47 @@ exports.build = function (api, app, config, cb) { } if (config.isSimulated) { + // Write the jsio.js and jsio_path.js files + var binPath = path.join(config.outputPath, 'bin'); + tasks.push( + JSCompiler.writeJsioBin(binPath) + ); + + // TODO: MOVE THIS SOMEWHERE ELSE + var jsioPath = require('jsio').__env.getPath(); + var _path = [jsioPath, '.', 'lib']; + var _pathCache = { + 'jsio': jsioPath + }; + var addClientPaths = function (clientPaths) { + for (var key in clientPaths) { + if (key !== '*') { + _pathCache[key] = clientPaths[key]; + } else { + _path.push.apply(_path, clientPaths['*']); + } + } + }; + if (config && config.clientPaths) { + addClientPaths(config.clientPaths); + } + + if (app && app.clientPaths) { + addClientPaths(app.clientPaths); + } + // TODO: THE PATH MAP SHOULD PROBABLY COME IN ON THE API OBJECT + var _pathMap = {}; + _pathMap[api.paths.devkit] = '/devkit'; + tasks.push( + JSCompiler.writeJsioPath({ + cwd: app.paths.root, + path: _path, + pathCache: _pathCache, + pathMap: _pathMap, + binPath: binPath + }) + ); + config.browser.headHTML.push(''); config.browser.headHTML.push(''); } diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index 791adea..3a5464b 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -208,6 +208,72 @@ exports.JSCompiler = Class(function () { }; }); +/** binPath is where the output should go */ +exports.writeJsioBin = function(binPath) { + var srcPath = require.resolve('jsio'); + var destPath = path.join(binPath, 'jsio.js'); + return fileGenerator( + srcPath, + destPath, + function(cb) { + var src = jsio.__jsio.__init__.toString(-1); + if (src.substring(0, 8) == 'function') { + src = 'jsio=(' + src + ')();'; + } + cb(null, src); + } + ); +}; + + +function replaceSlashes(str) { + return str.replace(/\\+/g, '/').replace(/\/{2,}/g, '/'); +} + +/** path is the array of wildcards + pathCache is a dictionary of exact paths + binPath is where the output should go */ +exports.writeJsioPath = function(opts) { + var cwd = opts.cwd || jsio.__env.getCwd(); + var _path = opts.path || []; + var pathCache = opts.pathCache || {}; + var pathMap = opts.pathMap || null; + var binPath = opts.binPath; + + // TODO: FINISH THIS FUNCTION + var util = jsio.__jsio.__util; + + var cache = {}; + Object.keys(pathCache).forEach(function (key) { + var pathCacheValue = pathCache[key]; + + var resultPath; + if (path.isAbsolute(pathCacheValue)) { + // Check for a path mapping + for (var p in pathMap) { + if (pathCacheValue.indexOf(p) === 0) { + resultPath = pathCacheValue.replace(p, pathMap[p]); + break; + } + } + } + + if (!resultPath) { + resultPath = util.relative(cwd, pathCacheValue); + } + + cache[key] = replaceSlashes(resultPath) || './'; + }); + + var contents = 'jsio.path.set(' + + JSON.stringify(_path.map(function (value) { + return replaceSlashes(util.relative(cwd, value)); + })) + ');jsio.path.cache=' + JSON.stringify(cache) + ';'; + + var destPath = path.join(binPath, 'jsio_path.js'); + return fileGenerator.dynamic(contents, destPath); +} + var DevKitJsioInterface = Class(EventEmitter, function () { this.init = function (bridge) { @@ -233,6 +299,7 @@ var DevKitJsioInterface = Class(EventEmitter, function () { var tasks = []; // Write jsio_path.js + // TODO: use exports.writeJsioPath var destPath = path.join(binPath, 'jsio_path.js'); var src = this._compiler.getCompiler().getPathJS(); tasks.push( @@ -240,19 +307,7 @@ var DevKitJsioInterface = Class(EventEmitter, function () { ); // Write jsio.js - var srcPath = require.resolve('jsio'); - var destPath = path.join(binPath, 'jsio.js'); - tasks.push(fileGenerator( - srcPath, - destPath, - function(cb) { - var src = jsio.__jsio.__init__.toString(-1); - if (src.substring(0, 8) == 'function') { - src = 'jsio=(' + src + ')();'; - } - cb(null, src); - } - )); + tasks.push(exports.writeJsioBin(binPath)); return tasks; }; From 8620a31a2128421220d93612e9503f6c0adfa0ad Mon Sep 17 00:00:00 2001 From: yofreke Date: Wed, 5 Aug 2015 23:15:02 +0000 Subject: [PATCH 20/23] remove separateJsio option and replace it with simulator only functionality (manually building the separate jsio and jsio_path) --- src/build/browser/index.js | 38 +++++++--------- src/build/common/jsCompiler.js | 79 +++++++++++++++++++++------------- 2 files changed, 65 insertions(+), 52 deletions(-) diff --git a/src/build/browser/index.js b/src/build/browser/index.js index 7309c20..c51903e 100644 --- a/src/build/browser/index.js +++ b/src/build/browser/index.js @@ -53,6 +53,7 @@ exports.build = function (api, app, config, cb) { var slash = require('slash'); var streamFromArray = require('stream-from-array'); var fileGenerator = require('../common/fileGenerator'); + var glob = require('glob'); var readFile = Promise.promisify(fs.readFile); @@ -204,36 +205,27 @@ exports.build = function (api, app, config, cb) { JSCompiler.writeJsioBin(binPath) ); - // TODO: MOVE THIS SOMEWHERE ELSE - var jsioPath = require('jsio').__env.getPath(); - var _path = [jsioPath, '.', 'lib']; - var _pathCache = { - 'jsio': jsioPath - }; - var addClientPaths = function (clientPaths) { - for (var key in clientPaths) { - if (key !== '*') { - _pathCache[key] = clientPaths[key]; - } else { - _path.push.apply(_path, clientPaths['*']); + var pathAndCache = JSCompiler.getPathAndCache(app, config); + // Walk module dirs and add to the path cache (for fewer client side 404's) + pathAndCache.path.forEach(function(modulePath) { + var files = glob.sync(path.join(app.paths.root, modulePath, '**/*.js'), { }); + files.forEach(function(filePath) { + var relative = path.relative(path.join(app.paths.root, modulePath), filePath); + relative = relative.replace(/^\/|\.js$/g, ''); // replace leading slash and trailing .js + var key = relative.replace(/\//g, '.'); + if (!pathAndCache.pathCache[key]) { + pathAndCache.pathCache[key] = path.join(modulePath, relative); } - } - }; - if (config && config.clientPaths) { - addClientPaths(config.clientPaths); - } - - if (app && app.clientPaths) { - addClientPaths(app.clientPaths); - } + }); + }); // TODO: THE PATH MAP SHOULD PROBABLY COME IN ON THE API OBJECT var _pathMap = {}; _pathMap[api.paths.devkit] = '/devkit'; tasks.push( JSCompiler.writeJsioPath({ cwd: app.paths.root, - path: _path, - pathCache: _pathCache, + path: pathAndCache.path, + pathCache: pathAndCache.pathCache, pathMap: _pathMap, binPath: binPath }) diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index 3a5464b..07bf509 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -77,8 +77,7 @@ exports.JSCompiler = Class(function () { gcDebug: opts.debug, preprocessors: ['cls', 'logger'], - noCompile: opts.noCompile, - separateJsio: opts.separateJsio + noCompile: opts.noCompile }; if (opts.compress) { @@ -208,7 +207,10 @@ exports.JSCompiler = Class(function () { }; }); -/** binPath is where the output should go */ +/** + * @param {String} binPath Where jsio.js should be written to + * @return {Promise} FileGenerator promise + */ exports.writeJsioBin = function(binPath) { var srcPath = require.resolve('jsio'); var destPath = path.join(binPath, 'jsio.js'); @@ -230,9 +232,49 @@ function replaceSlashes(str) { return str.replace(/\\+/g, '/').replace(/\/{2,}/g, '/'); } -/** path is the array of wildcards - pathCache is a dictionary of exact paths - binPath is where the output should go */ +/** + * @param {Object} app + * @param {Object} config + * @return {Object} object with path and pathCache variables + */ +exports.getPathAndCache = function(app, config) { + var jsioPath = jsio.__env.getPath(); + var _path = []; + var _pathCache = { + jsio: jsioPath + }; + var addClientPaths = function (clientPaths) { + for (var key in clientPaths) { + if (key !== '*') { + _pathCache[key] = clientPaths[key]; + } else { + _path.push.apply(_path, clientPaths['*']); + } + } + }; + if (config && config.clientPaths) { + addClientPaths(config.clientPaths); + } + + if (app && app.clientPaths) { + addClientPaths(app.clientPaths); + } + + return { + path: _path, + pathCache: _pathCache + }; +}; + +/** + * @param {Object} opts + * @param {String} [opts.cwd] + * @param {String[]} [path] The array of wildcards + * @param {Object} [pathCache] A dictionary of exact paths + * @param {String} binPath Where the output should go + * @param {Object} [pathMap] Map pathCache results somewhere else + * @return {Promise} FileGenerator promise + */ exports.writeJsioPath = function(opts) { var cwd = opts.cwd || jsio.__env.getCwd(); var _path = opts.path || []; @@ -240,9 +282,10 @@ exports.writeJsioPath = function(opts) { var pathMap = opts.pathMap || null; var binPath = opts.binPath; - // TODO: FINISH THIS FUNCTION var util = jsio.__jsio.__util; + _path = [jsio.__env.getPath(), '.', 'lib'].concat(_path); + var cache = {}; Object.keys(pathCache).forEach(function (key) { var pathCacheValue = pathCache[key]; @@ -295,32 +338,10 @@ var DevKitJsioInterface = Class(EventEmitter, function () { this.emit('error', e); }; - this._writeJsioBin = function(binPath) { - var tasks = []; - - // Write jsio_path.js - // TODO: use exports.writeJsioPath - var destPath = path.join(binPath, 'jsio_path.js'); - var src = this._compiler.getCompiler().getPathJS(); - tasks.push( - fileGenerator.dynamic(src, destPath) - ); - - // Write jsio.js - tasks.push(exports.writeJsioBin(binPath)); - - return tasks; - }; - this.onFinish = function (opts, src, table) { var binPath = path.join(opts.outputPath, 'bin'); var tasks = []; - // maybe write out a new jsio - if (opts.separateJsio) { - tasks.concat(this._writeJsioBin(binPath)); - } - if (opts.individualCompile) { var keys = Object.keys(table); logger.info('Writing individual compile files: ' + keys.length); From c83a22d274e6758db7096aa8a95ee942b1be29d1 Mon Sep 17 00:00:00 2001 From: yofreke Date: Wed, 5 Aug 2015 23:15:02 +0000 Subject: [PATCH 21/23] use only top level dirs in pathCache instead of each individual file --- src/build/browser/index.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/build/browser/index.js b/src/build/browser/index.js index c51903e..ff6f276 100644 --- a/src/build/browser/index.js +++ b/src/build/browser/index.js @@ -208,13 +208,15 @@ exports.build = function (api, app, config, cb) { var pathAndCache = JSCompiler.getPathAndCache(app, config); // Walk module dirs and add to the path cache (for fewer client side 404's) pathAndCache.path.forEach(function(modulePath) { - var files = glob.sync(path.join(app.paths.root, modulePath, '**/*.js'), { }); + // Note: We could probably just look for folders 1 level deep + var files = glob.sync(path.join(app.paths.root, modulePath, '**/*.js')); files.forEach(function(filePath) { - var relative = path.relative(path.join(app.paths.root, modulePath), filePath); - relative = relative.replace(/^\/|\.js$/g, ''); // replace leading slash and trailing .js - var key = relative.replace(/\//g, '.'); + var key = path.relative(path.join(app.paths.root, modulePath), filePath); + key = key.replace(/^\/|\.js$/g, ''); // replace leading slash and trailing .js + key = key.split('/', 1)[0]; // Get the top level + if (!pathAndCache.pathCache[key]) { - pathAndCache.pathCache[key] = path.join(modulePath, relative); + pathAndCache.pathCache[key] = path.join(modulePath, key); } }); }); From 9e8b8fdcdc836c63bf52bece79ab8623776828cd Mon Sep 17 00:00:00 2001 From: yofreke Date: Thu, 20 Aug 2015 12:01:15 +0000 Subject: [PATCH 22/23] use relative (no sym link resolution) jsio path --- package.json | 3 ++- src/build/common/jsCompiler.js | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 6ba47d4..f5a3394 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "stylus": "0.48.1", "uglify-js": "^2.4.17", "vinyl": "^0.4.6", - "vinyl-fs": "^1.0.0" + "vinyl-fs": "^1.0.0", + "resolve": "1.1.6" }, "scripts": { "preinstall": "sh scripts/preinstall.sh" diff --git a/src/build/common/jsCompiler.js b/src/build/common/jsCompiler.js index 07bf509..8fa89c2 100644 --- a/src/build/common/jsCompiler.js +++ b/src/build/common/jsCompiler.js @@ -1,6 +1,7 @@ var path = require('path'); var fs = require('fs-extra'); var crypto = require('crypto'); +var resolve = require('resolve'); var argv = require('optimist').argv; var EventEmitter = require('events').EventEmitter; @@ -238,7 +239,9 @@ function replaceSlashes(str) { * @return {Object} object with path and pathCache variables */ exports.getPathAndCache = function(app, config) { - var jsioPath = jsio.__env.getPath(); + var devkitCorePath = path.join(app.paths.root, 'modules', 'devkit-core'); + var jsioPath = path.dirname(resolve.sync('jsio', { basedir: devkitCorePath })); + var _path = []; var _pathCache = { jsio: jsioPath @@ -284,7 +287,15 @@ exports.writeJsioPath = function(opts) { var util = jsio.__jsio.__util; - _path = [jsio.__env.getPath(), '.', 'lib'].concat(_path); + var jsioPath; + if (opts.cwd) { + var devkitCorePath = path.join(opts.cwd, 'modules', 'devkit-core'); + jsioPath = path.dirname(resolve.sync('jsio', { basedir: devkitCorePath })); + } else { + jsioPath = jsio.__env.getPath(); + } + + _path = [jsioPath, '.', 'lib'].concat(_path); var cache = {}; Object.keys(pathCache).forEach(function (key) { From 91f11c0414b4fc1de633ccf721f10cc28ef014cc Mon Sep 17 00:00:00 2001 From: Martin Hunt Date: Wed, 16 Sep 2015 00:38:10 -0700 Subject: [PATCH 23/23] native: add a debugpath for native jsio env use either the packageName or bundleID as the domain name Conflicts: src/build/native/env.js --- src/build/native/env.js | 21 ++++++++++----------- src/clientapi/native/launchClient.js | 9 ++++++++- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/build/native/env.js b/src/build/native/env.js index c3b33f0..fa16d03 100644 --- a/src/build/native/env.js +++ b/src/build/native/env.js @@ -1,5 +1,7 @@ // this file is included at the end of the embedded JS +/* globals NATIVE, JSIO_ENV_CTOR: true */ + // it's responsible for initializing the js.io environment var util = {}; var formatRegExp = /%[sdj%]/g; @@ -587,20 +589,18 @@ util._errnoException = function(err, syscall, original) { return e; }; -var JSIO_ENV_CTOR = function() { - var SLICE = Array.prototype.slice, - cwd = null; - - this.name = /android/.test(GLOBAL.userAgent) ? 'android' : 'ios'; +JSIO_ENV_CTOR = function() { + this.name = /android/i.test(GLOBAL.userAgent) ? 'android' : 'ios'; - this.global = GLOBAL; - this.log = util.getLogger(NATIVE.console.log); - this.getCwd = getCwd; + this.global = GLOBAL; + this.log = util.getLogger(NATIVE.console.log); + this.getCwd = getCwd; - function getCwd() { return NATIVE.location.substring(0, NATIVE.location.lastIndexOf('/') + 1) + 'code/__cmd__/'; } + function getCwd() { return NATIVE.location; } + this.debugPath = function (path) { return path; }; this.getPath = function() { return './sdk/jsio/'; }; - this.eval = function(code, path) { return NATIVE.eval(code, path); }; + this.eval = function(code, path) { return NATIVE.eval(code, this.debugPath(path)); }; this.fetch = function(filePath) { return false; } this.getNamespace = function(key) { return CONFIG.shortName + ':' + key }; @@ -622,7 +622,6 @@ var JSIO_ENV_CTOR = function() { this.getCachedSrc = function(path) { return srcCache[path]; }; - }; NATIVE.console.log(NATIVE.location); diff --git a/src/clientapi/native/launchClient.js b/src/clientapi/native/launchClient.js index 4437578..fd42409 100644 --- a/src/clientapi/native/launchClient.js +++ b/src/clientapi/native/launchClient.js @@ -14,7 +14,14 @@ * along with the Game Closure SDK. If not, see . */ -/* globals jsio, logging, logger */ +/* globals jsio, logging, logger, CONFIG, DEBUG */ + +var env = jsio.__env; +env.debugPath = function (path) { + var protocol = 'http:'; + var domain = env.name == 'android' ? CONFIG.packageName : CONFIG.bundleID; + return protocol + '//' + domain + '/' + path.replace(/^[.\/\\]+/, ''); +}; GLOBAL.console = logging.get('console'); window.self = window;