From cd4092f3e0b860cf66a6f22368cf6adbcdf22d13 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Tue, 20 May 2014 21:49:26 +0200 Subject: [PATCH 1/4] Allow to specify an objectToExportTo for goog.exportSymbol This allows users to build ol3 without anything exposed in the global namespace. This can e.g. be useful for creating an ol3 AMD module, by simply using a build configuration with "define('ol',function(){var o={};%output%return o.ol;});" as "output_wrapper". --- tasks/build.js | 6 +++++- tasks/generate-exports.js | 31 +++++++++++++++++++++---------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/tasks/build.js b/tasks/build.js index 4ba42ab908..247284ebaa 100644 --- a/tasks/build.js +++ b/tasks/build.js @@ -27,6 +27,10 @@ function assertValidConfig(config, callback) { callback(new Error('Config missing "exports" array')); return; } + if (config.namespace && typeof config.namespace !== 'string') { + callback(new Error('Config "namespace" must be a string')); + return; + } if (config.compile && typeof config.compile !== 'object') { callback(new Error('Config "compile" must be an object')); return; @@ -182,7 +186,7 @@ function build(config, paths, callback) { function main(config, callback) { async.waterfall([ assertValidConfig.bind(null, config), - generateExports.bind(null, config.exports), + generateExports.bind(null, config.exports, config.namespace), getDependencies.bind(null, config.src), build.bind(null, config) ], callback); diff --git a/tasks/generate-exports.js b/tasks/generate-exports.js index 70d5dd2b40..65f8481bdb 100644 --- a/tasks/generate-exports.js +++ b/tasks/generate-exports.js @@ -19,7 +19,7 @@ var build = path.join(__dirname, '..', 'build'); * @param {function(Error, Array.)} callback Called with the list of * patterns. */ -function getPatterns(configPath, callback) { +function getConfig(configPath, callback) { if (configPath) { fs.readFile(configPath, function(err, data) { if (err) { @@ -38,11 +38,17 @@ function getPatterns(configPath, callback) { callback(new Error('Expected an exports array, got: ' + patterns)); return; } - callback(null, patterns); + var namespace = obj.namespace; + if (namespace && typeof namespace !== 'string') { + callback(new Error('Expected an namespace string, got: ' + + namespace)); + return; + } + callback(null, patterns, namespace); }); } else { process.nextTick(function() { - callback(null, ['*']); + callback(null, ['*'], undefined); }); } } @@ -117,12 +123,15 @@ function filterSymbols(patterns, symbols, callback) { /** * Generate goog code to export a named symbol. * @param {string} name Symbol name. + * @param {string|undefined} namespace Target object for exported + * symbols. * @return {string} Export code. */ -function formatSymbolExport(name) { +function formatSymbolExport(name, namespace) { return 'goog.exportSymbol(\n' + ' \'' + name + '\',\n' + - ' ' + name + ');\n'; + ' ' + name + + (namespace ? ',\n ' + namespace : '') +');\n'; } @@ -145,9 +154,10 @@ function formatPropertyExport(name) { /** * Generate export code given a list symbol names. * @param {Array.} symbols List of symbols. + * @param {string|undefined} namespace Target object for exported symbols. * @return {string} Export code. */ -function generateExports(symbols) { +function generateExports(symbols, namespace) { var blocks = []; var requires = {}; symbols.forEach(function(symbol) { @@ -158,7 +168,7 @@ function generateExports(symbols) { if (name.indexOf('#') > 0) { blocks.push(formatPropertyExport(name)); } else { - blocks.push(formatSymbolExport(name)); + blocks.push(formatSymbolExport(name, namespace)); } }); blocks.unshift('\n'); @@ -173,17 +183,18 @@ function generateExports(symbols) { * Generate the exports code. * * @param {Array.} patterns List of symbol names or patterns. + * @param {string|undefined} namespace Target object for exported symbols. * @param {function(Error, string)} callback Called with the exports code or any * error generating it. */ -function main(patterns, callback) { +function main(patterns, namespace, callback) { async.waterfall([ getSymbols.bind(null, patterns), filterSymbols, function(symbols, done) { var code, err; try { - code = generateExports(symbols); + code = generateExports(symbols, namespace); } catch (e) { err = e; } @@ -212,7 +223,7 @@ if (require.main === module) { }).parse(); async.waterfall([ - getPatterns.bind(null, options.config), + getConfig.bind(null, options.config), main, fse.outputFile.bind(fse, options.output) ], function(err) { From 3447f93bfef9466196e5dec5aa6b166287e2e089 Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Tue, 20 May 2014 21:56:32 +0200 Subject: [PATCH 2/4] Document the new namespace option --- tasks/readme.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tasks/readme.md b/tasks/readme.md index 720b0c0459..da8a4fba6e 100644 --- a/tasks/readme.md +++ b/tasks/readme.md @@ -62,6 +62,16 @@ To generate a build named `ol.min.js` with the `build.json`, you would run this: node tasks/build.js build.json ol.min.js +To export the `ol` symbol to somewhere else than the global namespace, a `namespace` option is available. This can e.g. be useful for creating an ol3 AMD module, by simply providing a build configuration that contains +```js +{ + "namespace": "n", + "compile": { + "output_wrapper": "define('ol',function(){var n={};%output%return n.ol;});" + } +} +``` + ## `generate-exports.js` From 250f6901d321bc05e44e6c3b31d7b587b4ef1bc5 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 20 May 2014 22:09:18 -0600 Subject: [PATCH 3/4] Pass around single config object --- tasks/build.js | 2 +- tasks/generate-exports.js | 20 +++++++++----------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/tasks/build.js b/tasks/build.js index 247284ebaa..4481843b32 100644 --- a/tasks/build.js +++ b/tasks/build.js @@ -186,7 +186,7 @@ function build(config, paths, callback) { function main(config, callback) { async.waterfall([ assertValidConfig.bind(null, config), - generateExports.bind(null, config.exports, config.namespace), + generateExports.bind(null, config), getDependencies.bind(null, config.src), build.bind(null, config) ], callback); diff --git a/tasks/generate-exports.js b/tasks/generate-exports.js index 65f8481bdb..e736b661e3 100644 --- a/tasks/generate-exports.js +++ b/tasks/generate-exports.js @@ -11,13 +11,12 @@ var build = path.join(__dirname, '..', 'build'); /** - * Get a list of patterns from the config file. If configPath is provided + * Get the configuration from the config file. If configPath is provided * it is assumed to be a JSON file with an 'exports' member that is a list * of symbol names or patterns. * * @param {string} configPath Path to config file. - * @param {function(Error, Array.)} callback Called with the list of - * patterns. + * @param {function(Error, Object)} callback Called with config object. */ function getConfig(configPath, callback) { if (configPath) { @@ -44,11 +43,11 @@ function getConfig(configPath, callback) { namespace)); return; } - callback(null, patterns, namespace); + callback(null, obj); }); } else { process.nextTick(function() { - callback(null, ['*'], undefined); + callback(null, {exports: ['*']}); }); } } @@ -131,7 +130,7 @@ function formatSymbolExport(name, namespace) { return 'goog.exportSymbol(\n' + ' \'' + name + '\',\n' + ' ' + name + - (namespace ? ',\n ' + namespace : '') +');\n'; + (namespace ? ',\n ' + namespace : '') + ');\n'; } @@ -182,19 +181,18 @@ function generateExports(symbols, namespace) { /** * Generate the exports code. * - * @param {Array.} patterns List of symbol names or patterns. - * @param {string|undefined} namespace Target object for exported symbols. + * @param {Object} config Config object with exports and (optional) namespace. * @param {function(Error, string)} callback Called with the exports code or any * error generating it. */ -function main(patterns, namespace, callback) { +function main(config, callback) { async.waterfall([ - getSymbols.bind(null, patterns), + getSymbols.bind(null, config.exports), filterSymbols, function(symbols, done) { var code, err; try { - code = generateExports(symbols, namespace); + code = generateExports(symbols, config.namespace); } catch (e) { err = e; } From c820a7a1f8595c0e436ae4720bc88d726ac2b73f Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Tue, 20 May 2014 22:09:34 -0600 Subject: [PATCH 4/4] Additional doc for the namespace option People should be discouraged from exporting to single letter namespaces to avoid collissions with the symbols generated by the compiler. --- tasks/readme.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tasks/readme.md b/tasks/readme.md index da8a4fba6e..812170ba1b 100644 --- a/tasks/readme.md +++ b/tasks/readme.md @@ -25,6 +25,8 @@ Build configuration files are JSON files that are used to determine what should * **src** - `Array.` Optional array of [path patterns](https://github.com/isaacs/minimatch/blob/master/README.md) for source files. This defaults to `["src/**/*.js"]` which will match all `.js` files in the `src` directory. To include a different set of source files, provide an array of path patterns. Note that these patterns are `/` delimited even on Windows. + * **namespace** - `string` Optional namespace for exporting the `ol` object. By default, `ol` is assigned to the global object. + * **jvm** - `Array.` Optional array of [command line options](https://code.google.com/p/closure-compiler/wiki/FAQ#What_are_the_recommended_Java_VM_command-line_options?) for the compiler. By default, the Compiler is run with `['-server', '-XX:+TieredCompilation']`. The build task generates a list of source files sorted in dependency order and passes these to the compiler. This takes the place of the `--js` options that you would use when calling the compiler directly. If you want to add additional source files, typically you would use the `src` array described above. This works with sources that have `goog.require` and/or `goog.provide` calls (which are used to sort dependencies). If you want to force the inclusion of files that don't use `goog.require` or `goog.provide`, you can use the `js` property of the `compile` object. Paths in the `js` array will be passed to the compiler **after** all other source files. @@ -62,12 +64,15 @@ To generate a build named `ol.min.js` with the `build.json`, you would run this: node tasks/build.js build.json ol.min.js -To export the `ol` symbol to somewhere else than the global namespace, a `namespace` option is available. This can e.g. be useful for creating an ol3 AMD module, by simply providing a build configuration that contains +To export the `ol` symbol to somewhere else than the global namespace, a `namespace` option is available. This can e.g. be useful for creating an ol3 AMD module, by simply providing a build configuration like the following: + ```js { - "namespace": "n", + "exports": ["*"], + "namespace": "AMD", "compile": { - "output_wrapper": "define('ol',function(){var n={};%output%return n.ol;});" + "compilation_level": "ADVANCED_OPTIMIZATIONS", + "output_wrapper": "define('ol',function(){var AMD={};%output%return AMD.ol;});" } } ```