Skip to content
This repository has been archived by the owner on Jun 15, 2021. It is now read-only.

Commit

Permalink
externs for Closure from individual packages
Browse files Browse the repository at this point in the history
the `options` object that initially contains options from the
commandline that are then passed to the minifier is first passed through
each of the source packages (bundled libs, including dependencies) and
extended if there is anything to extend. Currently just the `externs`
property.
  • Loading branch information
rvagg committed Oct 15, 2012
1 parent f09d75f commit e87a91d
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 136 deletions.
5 changes: 2 additions & 3 deletions lib/package-descriptor.js
Expand Up @@ -38,7 +38,7 @@ var overrides = {
} }


, create = function (json) { , create = function (json) {
var newJson = {} var newJson = Object.create(json) // original is available via Object.getPrototypeOf
, key , key


if (typeof json.overlay == 'object' if (typeof json.overlay == 'object'
Expand All @@ -59,12 +59,11 @@ var overrides = {
} }


for (key in json) { for (key in json) {
if (!(key in newJson)) { if (!newJson.hasOwnProperty(key)) {
newJson[key] = json[key] newJson[key] = json[key]
} }
} }


newJson._original = json
return newJson return newJson
} }


Expand Down
15 changes: 12 additions & 3 deletions lib/source-build.js
Expand Up @@ -32,6 +32,7 @@


var async = require('async') var async = require('async')
, fs = require('fs') , fs = require('fs')
, util = require('./util')
, minify = require('./minify') , minify = require('./minify')
, template = require('./template') , template = require('./template')
, argsParse = require('./args-parse') , argsParse = require('./args-parse')
Expand All @@ -57,8 +58,8 @@ var async = require('async')
//options.type == plain||minified //options.type == plain||minified
var finish = function (err, source) { var finish = function (err, source) {
if (err) return callback(err) // wrapped in template.js if (err) return callback(err) // wrapped in template.js
if (options.type === 'minified') minify.minify(this.options, source, callback) if (options.type != 'minified') return callback(null, source)
else callback(null, source) minify.minify(this.completeOptions(), source, callback)
}.bind(this) }.bind(this)


, tmplData = function (sources) { , tmplData = function (sources) {
Expand All @@ -67,7 +68,7 @@ var async = require('async')
, context: argsParse.toContextString(this.options) , context: argsParse.toContextString(this.options)
, sandbox: !!this.options.sandbox , sandbox: !!this.options.sandbox
, packages: this.packages.map(function (p) { , packages: this.packages.map(function (p) {
return p.getIdentifier() return p.identifier
}).join(' ') }).join(' ')
} }
}.bind(this) }.bind(this)
Expand All @@ -84,6 +85,14 @@ var async = require('async')
// async.map, oh my! do an asString() on each SourcePackage async but reassemble them in order // async.map, oh my! do an asString() on each SourcePackage async but reassemble them in order
async.map(this.packages, packageToString, readComplete) async.map(this.packages, packageToString, readComplete)
} }

, completeOptions: function () { // options + any additional options child packages may wish to add
var options = util.extend(this.options, {})
this.packages.forEach(function (pkg) {
pkg.extendOptions(options)
})
return options
}
} }


// a utility static method to partially read an ender build file and parse the head comment // a utility static method to partially read an ender build file and parse the head comment
Expand Down
60 changes: 41 additions & 19 deletions lib/source-package.js
Expand Up @@ -31,13 +31,11 @@
* compatible output (the less screwing with strings here the better). * compatible output (the less screwing with strings here the better).
*/ */


var fs = require('fs') var path = require('path')
, path = require('path')
, async = require('async') , async = require('async')
, template = require('./template') , template = require('./template')
, packageUtil = require('./package-util') , packageUtil = require('./package-util')
, sourcePackageUtil = require('./source-package-util') , sourcePackageUtil = require('./source-package-util')
, FilesystemError = require('./errors').FilesystemError


, templateFiles = { , templateFiles = {
'standard' : '../resources/source-package.mustache' 'standard' : '../resources/source-package.mustache'
Expand All @@ -64,17 +62,14 @@ var fs = require('fs')


// generate an object that can be fed to the templates // generate an object that can be fed to the templates
, makeTemplateData = function (sources) { , makeTemplateData = function (sources) {
return { // if this package is in the `--sandbox <packages>` list, or, if we are
packageName : this.packageJSON.name // the root package and a --sandbox option is passed, then set this to true
, options : { var isSandbox = Array.isArray(this.options.sandbox) && (
noop : this.options.noop
, sandbox :
// if this package is in the `--sandbox <packages>` list, or, if we are
// the root package and a --sandbox option is passed, then set this to true
Array.isArray(this.options.sandbox) && (
this.options.sandbox.indexOf(this.packageJSON.name) != -1 this.options.sandbox.indexOf(this.packageJSON.name) != -1
|| this.isRoot) || this.isRoot)
} return {
packageName : this.packageJSON.name
, options : { noop: this.options.noop, sandbox: isSandbox }
// these objects have lazy methods so we don't do unnecessary indent()ing // these objects have lazy methods so we don't do unnecessary indent()ing
, mainSource: sources.main && { , mainSource: sources.main && {
raw : function () { return sources.main } raw : function () { return sources.main }
Expand All @@ -101,17 +96,30 @@ var fs = require('fs')
return this return this
} }


, getIdentifier: function () { // not the overridden name, the name from the package.json
return this.packageJSON._original.name + '@' + this.packageJSON.version , get realName () {
return this.packageJSON && Object.getPrototypeOf(this.packageJSON).name
? Object.getPrototypeOf(this.packageJSON).name
: this.packageName
}

// get the `name` from the original json data, available as proto (see package-descriptor.js)
, get identifier () {
return this.realName + '@' + this.packageJSON.version
}

// the root of this package on the filesystem
, get packageRoot () {
return packageUtil.getPackageRoot(this.parents, this.realName)
} }


// this method supports multiple calls but a single execution, hence the async.memoize in init() // this method supports multiple calls but a single execution, hence the async.memoize in init()
, asString: function (callback) { , asString: function (callback) {
// note that "main" and "ender" are processed in the same way so they can both be just // note that "main" and "ender" are processed in the same way so they can both be just
// a string pointing to a source file or an array of source files that are concatenated // a string pointing to a source file or an array of source files that are concatenated
// or be left unspecified // or be left unspecified
var root = packageUtil.getPackageRoot(this.parents, this.packageName) var root = this.packageRoot
, asValidType = function (value) { , asValidType = function (value) {
return typeof value == 'string' || Array.isArray(value) ? value : [] return typeof value == 'string' || Array.isArray(value) ? value : []
} }
, mainSources = asValidType(this.packageJSON.main) , mainSources = asValidType(this.packageJSON.main)
Expand All @@ -129,18 +137,32 @@ var fs = require('fs')


generateSource( generateSource(
this.isRoot this.isRoot
, makeTemplateData.bind(this)(sources) , makeTemplateData.call(this, sources)
, callback , callback
) )
}.bind(this) }.bind(this)


, sourceLoaders = { , sourceLoaders = {
main: sourcePackageUtil.loadFiles.bind(this, root, mainSources) main : sourcePackageUtil.loadFiles.bind(this, root, mainSources)
, ender: sourcePackageUtil.loadFiles.bind(this, root, enderBridgeSources) , ender : sourcePackageUtil.loadFiles.bind(this, root, enderBridgeSources)
} }


async.parallel(sourceLoaders, handleSourceData) async.parallel(sourceLoaders, handleSourceData)
} }

, extendOptions: function (options) {
var externs = this.packageJSON && this.packageJSON.externs
, root

if (externs) {
if (!Array.isArray(externs)) externs = [ externs ]
root = this.packageRoot
if (!options.externs) options.externs = []
options.externs = options.externs.concat(externs.map(function (e) {
return path.join(root, e)
}))
}
}
} }


module.exports.create = function (packageName, parents, isRoot, packageJSON, options) { module.exports.create = function (packageName, parents, isRoot, packageJSON, options) {
Expand Down
24 changes: 8 additions & 16 deletions test/unit/package-util-test.js
Expand Up @@ -102,8 +102,7 @@ testCase('Package util', {
setupReadPackageJSON.call(this, 'node_modules/amodule/', expected) setupReadPackageJSON.call(this, 'node_modules/amodule/', expected)
packageUtil.readPackageJSON([], 'amodule', function (err, actual) { packageUtil.readPackageJSON([], 'amodule', function (err, actual) {
refute(err) refute(err)
assert.equals(actual._original, expected) assert.equals(Object.getPrototypeOf(actual), expected)
; delete actual._original
assert.equals(actual, expected) assert.equals(actual, expected)
done() done()
}) })
Expand All @@ -115,8 +114,7 @@ testCase('Package util', {
setupReadPackageJSON.call(this, 'node_modules/amodule.js/', expected) setupReadPackageJSON.call(this, 'node_modules/amodule.js/', expected)
packageUtil.readPackageJSON([], 'amodule.js', function (err, actual) { packageUtil.readPackageJSON([], 'amodule.js', function (err, actual) {
refute(err) refute(err)
assert.equals(actual._original, expected) assert.equals(Object.getPrototypeOf(actual), expected)
; delete actual._original
assert.equals(actual, expected) assert.equals(actual, expected)
done() done()
}) })
Expand All @@ -128,8 +126,7 @@ testCase('Package util', {
setupReadPackageJSON.call(this, 'node_modules/amodule/', expected) setupReadPackageJSON.call(this, 'node_modules/amodule/', expected)
packageUtil.readPackageJSON([], 'amodule@0.1.200', function (err, actual) { packageUtil.readPackageJSON([], 'amodule@0.1.200', function (err, actual) {
refute(err) refute(err)
assert.equals(actual._original, expected) assert.equals(Object.getPrototypeOf(actual), expected)
; delete actual._original
assert.equals(actual, expected) assert.equals(actual, expected)
done() done()
}) })
Expand All @@ -141,8 +138,7 @@ testCase('Package util', {
setupReadPackageJSON.call(this, 'node_modules/aparent/node_modules/amodule/', expected) setupReadPackageJSON.call(this, 'node_modules/aparent/node_modules/amodule/', expected)
packageUtil.readPackageJSON([ 'aparent' ], 'amodule', function (err, actual) { packageUtil.readPackageJSON([ 'aparent' ], 'amodule', function (err, actual) {
refute(err) refute(err)
assert.equals(actual._original, expected) assert.equals(Object.getPrototypeOf(actual), expected)
; delete actual._original
assert.equals(actual, expected) assert.equals(actual, expected)
done() done()
}) })
Expand All @@ -160,8 +156,7 @@ testCase('Package util', {
[ 'aparent1', 'aparent2', 'aparent3' ] [ 'aparent1', 'aparent2', 'aparent3' ]
, 'amodule', function (err, actual) { , 'amodule', function (err, actual) {
refute(err) refute(err)
assert.equals(actual._original, expected) assert.equals(Object.getPrototypeOf(actual), expected)
; delete actual._original
assert.equals(actual, expected) assert.equals(actual, expected)
done() done()
} }
Expand All @@ -174,8 +169,7 @@ testCase('Package util', {
setupReadPackageJSON.call(this, '.', expected) setupReadPackageJSON.call(this, '.', expected)
packageUtil.readPackageJSON([ 'this shouldn\'t matter' ], './', function (err, actual) { packageUtil.readPackageJSON([ 'this shouldn\'t matter' ], './', function (err, actual) {
refute(err) refute(err)
assert.equals(actual._original, expected) assert.equals(Object.getPrototypeOf(actual), expected)
; delete actual._original
assert.equals(actual, expected) assert.equals(actual, expected)
done() done()
}) })
Expand All @@ -187,8 +181,7 @@ testCase('Package util', {
setupReadPackageJSON.call(this, 'some/path/without/dots', expected) setupReadPackageJSON.call(this, 'some/path/without/dots', expected)
packageUtil.readPackageJSON([ 'foobar' ], 'some/path/without/dots', function (err, actual) { packageUtil.readPackageJSON([ 'foobar' ], 'some/path/without/dots', function (err, actual) {
refute(err) refute(err)
assert.equals(actual._original, expected) assert.equals(Object.getPrototypeOf(actual), expected)
; delete actual._original
assert.equals(actual, expected) assert.equals(actual, expected)
done() done()
}) })
Expand All @@ -200,8 +193,7 @@ testCase('Package util', {
setupReadPackageJSON.call(this, 'some/path/without/dots', expected) setupReadPackageJSON.call(this, 'some/path/without/dots', expected)
packageUtil.readPackageJSON([ 'what???' ], './some/path/../path/without/dots', function (err, actual) { packageUtil.readPackageJSON([ 'what???' ], './some/path/../path/without/dots', function (err, actual) {
refute(err) refute(err)
assert.equals(actual._original, expected) assert.equals(Object.getPrototypeOf(actual), expected)
; delete actual._original
assert.equals(actual, expected) assert.equals(actual, expected)
done() done()
}) })
Expand Down

0 comments on commit e87a91d

Please sign in to comment.