This commit is contained in:
Matthew Arbesfeld
2014-07-16 11:34:55 -07:00
parent 738c27ad8d
commit c3891fc823
8 changed files with 104 additions and 87 deletions

View File

@@ -37,9 +37,9 @@ ConstraintSolver.PackagesResolver = function (catalog, options) {
forEveryVersion(function (packageName, version, versionDef) {
var unibuilds = {};
// XXX in theory there might be different archs but in practice they are
// always "os" and "browser". Fix this once we actually have different
// always "os" and "client". Fix this once we actually have different
// archs used.
_.each(["os", "browser"], function (arch) {
_.each(["os", "client", "client.browser", "client.test"], function (arch) {
var unitName = packageName + "#" + arch;
unibuilds[unitName] = new ConstraintSolver.UnitVersion(
unitName, version, versionDef.earliestCompatibleVersion);
@@ -128,10 +128,10 @@ ConstraintSolver.PackagesResolver.prototype.resolve =
}
// split every package name to one or more archs belonging to that package
// (["foobar"] => ["foobar#os", "foobar#browser"])
// XXX for now just put #os and #browser
// (["foobar"] => ["foobar#os", "foobar#client"])
// XXX for now just put #os and #client
options.upgrade = _.filter(_.flatten(_.map(options.upgrade, function (packageName) {
return [packageName + "#os", packageName + "#browser"];
return [packageName + "#os", packageName + "#client"];
})), _.identity);
var dc = self._splitDepsToConstraints(dependencies, constraints);
@@ -162,7 +162,7 @@ ConstraintSolver.PackagesResolver.prototype.resolve =
var resultChoices = {};
_.each(res, function (uv) {
// Since we don't yet define the interface for a an app to depend only on
// certain unibuilds of the packages (like only browser unibuilds) and we know
// certain unibuilds of the packages (like only client unibuilds) and we know
// that each unibuild weakly depends on other sibling unibuilds of the same
// version, we can safely output the whole package for each unibuild in the
// result.
@@ -198,7 +198,7 @@ ConstraintSolver.PackagesResolver.prototype.propagateExactDeps =
};
// takes dependencies and constraints and rewrites the names from "foo" to
// "foo#os" and "foo#browser"
// "foo#os" and "foo#client"
// XXX right now creates a dependency for every unibuild it can find
ConstraintSolver.PackagesResolver.prototype._splitDepsToConstraints =
function (inputDeps, inputConstraints) {
@@ -233,8 +233,8 @@ ConstraintSolver.PackagesResolver.prototype._unibuildsForPackage =
var self = this;
var unibuildPrefix = packageName + "#";
var unibuilds = [];
// XXX hardcode os and browser
_.each(["os", "browser"], function (arch) {
// XXX hardcode os and client
_.each(["os", "client", "client.browser", "client.test"], function (arch) {
if (self.resolver.unitsVersions[unibuildPrefix + arch])
unibuilds.push(unibuildPrefix + arch);
});

View File

@@ -4,7 +4,7 @@
Plugin.registerSourceHandler("css", function (compileStep) {
// XXX annoying that this is replicated in .css, .less, and .styl
if (! compileStep.archMatches('browser')) {
if (! compileStep.archMatches('client')) {
// XXX in the future, might be better to emit some kind of a
// warning if a stylesheet is included on the server, rather than
// silently ignoring it. but that would mean you can't stick .css

View File

@@ -2,8 +2,7 @@ var path = Npm.require('path');
var doHTMLScanning = function (compileStep, htmlScanner) {
// XXX use archinfo rather than rolling our own
if (! compileStep.arch.match(/^browser(\.|$)/))
if (! compileStep.archMatches("client"))
// XXX might be nice to throw an error here, but then we'd have to
// make it so that packages.js ignores html files that appear in
// the server directories in an app tree.. or, it might be nice to

View File

@@ -492,7 +492,8 @@ main.registerCommand({
directory: { type: Boolean },
architecture: { type: String },
// Undocumented
'for-deploy': { type: Boolean }
'for-deploy': { type: Boolean },
'client-arch': { type: String }
}
}, function (options) {
// XXX if they pass a file that doesn't end in .tar.gz or .tgz, add
@@ -537,7 +538,9 @@ main.registerCommand({
// default? i guess the problem with using DEPLOY_ARCH as default
// is then 'meteor bundle' with no args fails if you have any local
// packages with binary npm dependencies
arch: bundleArch
arch: bundleArch,
clientArchs: options['client-arch'] ? [options['client-arch']]
: ['client.browser']
}
});
if (bundleResult.errors) {

View File

@@ -67,6 +67,7 @@ compiler.eachUsedUnibuild = function (
callback = options;
options = {};
}
var acceptableWeakPackages = options.acceptableWeakPackages || {};
var processedBuildId = {};
@@ -81,6 +82,7 @@ compiler.eachUsedUnibuild = function (
while (!_.isEmpty(usesToProcess)) {
var use = usesToProcess.shift();
console.log(use);
var unibuild = packageLoader.getUnibuild(use.package, arch);
if (!unibuild) {
@@ -448,11 +450,11 @@ var compileUnibuild = function (unipackage, inputSourceArch, packageLoader,
// information.
// - pathForSourceMap: If this file is to be included in a source map,
// this is the name you should use for it in the map.
// - rootOutputPath: on browser targets, for resources such as
// - rootOutputPath: on client targets, for resources such as
// stylesheet and static assets, this is the root URL that
// will get prepended to the paths you pick for your output
// files so that you get your own namespace, for example
// '/packages/foo'. null on non-browser targets
// '/packages/foo'. null on non-client targets
// - fileOptions: any options passed to "api.add_files"; for
// use by the plugin. The built-in "js" plugin uses the "bare"
// option for files that shouldn't be wrapped in a closure.
@@ -464,11 +466,11 @@ var compileUnibuild = function (unipackage, inputSourceArch, packageLoader,
// file as a Buffer. If n is omitted you get the rest of the
// file.
// - appendDocument({ section: "head", data: "my markup" })
// Browser targets only. Add markup to the "head" or "body"
// Client targets only. Add markup to the "head" or "body"
// section of the document.
// - addStylesheet({ path: "my/stylesheet.css", data: "my css",
// sourceMap: "stringified json sourcemap"})
// Browser targets only. Add a stylesheet to the
// Client targets only. Add a stylesheet to the
// document. 'path' is a requested URL for the stylesheet that
// may or may not ultimately be honored. (Meteor will add
// appropriate tags to cause the stylesheet to be loaded. It
@@ -563,9 +565,9 @@ var compileUnibuild = function (unipackage, inputSourceArch, packageLoader,
return ret;
},
appendDocument: function (options) {
if (! archinfo.matches(inputSourceArch.arch, "browser"))
if (! archinfo.matches(inputSourceArch.arch, "client"))
throw new Error("Document sections can only be emitted to " +
"browser targets");
"client targets");
if (options.section !== "head" && options.section !== "body")
throw new Error("'section' must be 'head' or 'body'");
if (typeof options.data !== "string")
@@ -577,9 +579,9 @@ var compileUnibuild = function (unipackage, inputSourceArch, packageLoader,
});
},
addStylesheet: function (options) {
if (! archinfo.matches(inputSourceArch.arch, "browser"))
if (! archinfo.matches(inputSourceArch.arch, "client"))
throw new Error("Stylesheets can only be emitted to " +
"browser targets");
"client targets");
if (typeof options.data !== "string")
throw new Error("'data' option to addStylesheet must be a string");
sourceIsWatched = true;
@@ -596,8 +598,8 @@ var compileUnibuild = function (unipackage, inputSourceArch, packageLoader,
throw new Error("'data' option to addJavaScript must be a string");
if (typeof options.sourcePath !== "string")
throw new Error("'sourcePath' option must be supplied to addJavaScript. Consider passing inputPath.");
if (options.bare && ! archinfo.matches(inputSourceArch.arch, "browser"))
throw new Error("'bare' option may only be used for browser targets");
if (options.bare && ! archinfo.matches(inputSourceArch.arch, "client"))
throw new Error("'bare' option may only be used for client targets");
sourceIsWatched = true;
js.push({
source: options.data,

View File

@@ -40,6 +40,7 @@ _.extend(exports.PackageLoader.prototype, {
if (options.throwOnError === undefined) {
options.throwOnError = true;
}
var loadPath = self.getLoadPathForPackage(name);
if (! loadPath) {
if (options.throwOnError === false)

View File

@@ -667,22 +667,29 @@ _.extend(PackageSource.prototype, {
buildmessage.error("Package name invalid: " + self.name);
}
var allWheres = ['server', 'client'];
var allWhereObj = {};
_.each(allWheres, function (where) {
allWhereObj[where] = [];
});
// source files used
var sources = {client: [], server: []};
var sources = _.clone(allWhereObj);
// symbols exported
var exports = {client: [], server: []};
var exports = _.clone(allWhereObj);
// packages used and implied (keys are 'package', 'unordered', and
// 'weak'). an "implied" package is a package that will be used by a unibuild
// which uses us.
var uses = {client: [], server: []};
var implies = {client: [], server: []};
var uses = _.clone(allWhereObj);
var implies = _.clone(allWhereObj);
// For this old-style, on_use/on_test/where-based package, figure
// out its dependencies by calling its on_xxx functions and seeing
// what it does.
//
// XXX fix this comment
// We have a simple strategy. Call its on_xxx handler with no
// 'where', which is what happens when the package is added
// directly to an app, and see what files it adds to the client
@@ -702,25 +709,23 @@ _.extend(PackageSource.prototype, {
return x ? [x] : [];
};
var allWheres = ['client', 'server'];
var toWhereArray = function (where) {
if (!(where instanceof Array)) {
where = where ? [where] : allWheres;
}
where = _.uniq(where);
var realWhere = _.intersection(where, allWheres);
if (realWhere.length !== where.length) {
var badWheres = _.difference(where, allWheres);
// avoid using _.each so as to not add more frames to skip
for (var i = 0; i < badWheres.length; ++i) {
_.each(where, function (inputWhere) {
var isMatch = _.any(_.map(allWheres, function (actualWhere) {
return archinfo.matches(inputWhere, actualWhere);
}));
if (! isMatch) {
buildmessage.error(
"Invalid 'where' argument: '" + badWheres[i] + "'",
"Invalid 'where' argument: '" + indivWhere + "'",
// skip toWhereArray in addition to the actual API function
{useMyCaller: 1});
};
// recover by using the real ones only
}
return realWhere;
}
});
return where;
};
var api = {
@@ -728,7 +733,8 @@ _.extend(PackageSource.prototype, {
// used. Can also take literal package objects, if you have
// anonymous packages you want to use (eg, app packages)
//
// @param where 'client', 'server', or an array of those.
// @param where 'client', 'client.browser', 'client.test', 'server',
// or an array of those.
// The default is ['client', 'server'].
//
// options can include:
@@ -843,7 +849,7 @@ _.extend(PackageSource.prototype, {
//
// @param symbols String (eg "Foo") or array of String
// @param where 'client', 'server', or an array of those.
// The default is ['client', 'server'].
// The default is ['client', 'client.test', 'client.browser', 'server'].
// @param options 'testOnly', boolean.
export: function (symbols, where, options) {
// Support `api.export("FooTest", {testOnly: true})` without
@@ -883,7 +889,7 @@ _.extend(PackageSource.prototype, {
// packages and any remaining handlers. It violates the
// principle of least surprise to half-run a handler
// and then continue.
sources = {client: [], server: []};
sources = _.clone(allWhereObj);
fileAndDepLoader = null;
self.pluginInfo = {};
npmDependencies = null;
@@ -909,9 +915,9 @@ _.extend(PackageSource.prototype, {
// For all implies and uses, fill in the unspecified dependencies from the
// release.
_.each(['server', 'client'], function (label) {
uses[label] = _.map(uses[label], setFromRel);
implies[label] = _.map(implies[label], setFromRel);
_.each(allWheres, function (label) {
uses[label] = _.map(uses[label], setFromRel);
implies[label] = _.map(implies[label], setFromRel);
});
};
@@ -949,45 +955,47 @@ _.extend(PackageSource.prototype, {
});
// Create source architectures, one for the server and one for the client.
_.each(["browser", "os"], function (arch) {
var where = (arch === "browser") ? "client" : "server";
_.each(["client", "os"], function (arch) {
var sourceWhere = (arch === "client") ? "client" : "server";
_.each(allWheres, function (where) {
if (archinfo.matches(where, sourceWhere)) {
// Everything depends on the package 'meteor', which sets up
// the basic environment) (except 'meteor' itself, and js-analyze
// which needs to be loaded by the linker).
// XXX add a better API for js-analyze to declare itself here
if (name !== "meteor" && name !== "js-analyze" &&
!process.env.NO_METEOR_PACKAGE) {
// Don't add the dependency if one already exists. This allows the
// package to create an unordered dependency and override the one that
// we'd add here. This is necessary to resolve the circular dependency
// between meteor and underscore (underscore has an unordered
// dependency on meteor dating from when the .js extension handler was
// in the "meteor" package).
var alreadyDependsOnMeteor =
!! _.find(uses[where], function (u) {
return u.package === "meteor";
});
if (! alreadyDependsOnMeteor)
uses[where].unshift({ package: "meteor" });
}
// Everything depends on the package 'meteor', which sets up
// the basic environment) (except 'meteor' itself, and js-analyze
// which needs to be loaded by the linker).
// XXX add a better API for js-analyze to declare itself here
if (name !== "meteor" && name !== "js-analyze" &&
!process.env.NO_METEOR_PACKAGE) {
// Don't add the dependency if one already exists. This allows the
// package to create an unordered dependency and override the one that
// we'd add here. This is necessary to resolve the circular dependency
// between meteor and underscore (underscore has an unordered
// dependency on meteor dating from when the .js extension handler was
// in the "meteor" package).
var alreadyDependsOnMeteor =
!! _.find(uses[where], function (u) {
return u.package === "meteor";
});
if (! alreadyDependsOnMeteor)
uses[where].unshift({ package: "meteor" });
}
// Each unibuild has its own separate WatchSet. This is so that, eg, a test
// unibuild's dependencies doesn't end up getting merged into the
// pluginWatchSet of a package that uses it: only the use unibuild's
// dependencies need to go there!
var watchSet = new watch.WatchSet();
watchSet.addFile(packageJsPath, packageJsHash);
self.architectures.push(new SourceArch(self, {
name: "main",
arch: arch,
uses: uses[where],
implies: implies[where],
getSourcesFunc: function () { return sources[where]; },
declaredExports: exports[where],
watchSet: watchSet
}));
// Each unibuild has its own separate WatchSet. This is so that, eg, a test
// unibuild's dependencies doesn't end up getting merged into the
// pluginWatchSet of a package that uses it: only the use unibuild's
// dependencies need to go there!
var watchSet = new watch.WatchSet();
watchSet.addFile(packageJsPath, packageJsHash);
self.architectures.push(new SourceArch(self, {
name: "main",
arch: arch,
uses: uses[where],
implies: implies[where],
getSourcesFunc: function () { return sources[where]; },
declaredExports: exports[where],
watchSet: watchSet
}));
}
});
});
// If we have built this before, read the versions that we ended up using.
@@ -1034,7 +1042,7 @@ _.extend(PackageSource.prototype, {
// Determine used packages
var project = require('./project.js').project;
var names = project.getConstraints();
var arch = archName === "server" ? "os" : "browser";
var arch = archName === "server" ? "os" : "client";
// Create unibuild
var sourceArch = new SourceArch(self, {
@@ -1185,6 +1193,7 @@ _.extend(PackageSource.prototype, {
include: [/.?/],
// we DO look under dot directories here
exclude: ignoreFiles
});
_.each(assetsAndSubdirs, function (item) {

View File

@@ -156,7 +156,7 @@ _.extend(Unibuild.prototype, {
importStubServePath: isApp && '/packages/global-imports.js',
prelinkFiles: self.prelinkFiles,
packageVariables: self.packageVariables,
includeSourceMapInstructions: archinfo.matches(self.arch, "browser"),
includeSourceMapInstructions: archinfo.matches(self.arch, "client"),
name: self.pkg.name || null
});
@@ -305,7 +305,7 @@ _.extend(Unipackage.prototype, {
_.pluck(self.unibuilds, 'arch').concat(self._toolArchitectures())
).sort();
// Ensure that our buildArchitectures string does not look like
// browser+os+os.osx.x86_64
// client+os+os.osx.x86_64
// This would happen if there is an 'os' unibuild but a platform-specific
// tool (eg, in meteor-tool). This would confuse catalog.getBuildsForArches
// into thinking that it would work for Linux, since the 'os' means
@@ -336,7 +336,7 @@ _.extend(Unipackage.prototype, {
},
// Return the unibuild of the package to use for a given target architecture
// (eg, 'os.linux.x86_64' or 'browser'), or throw an exception if that
// (eg, 'os.linux.x86_64' or 'client'), or throw an exception if that
// packages can't be loaded under these circumstances.
getUnibuildAtArch: function (arch) {
var self = this;
@@ -623,6 +623,9 @@ _.extend(Unipackage.prototype, {
JSON.stringify(resource.type));
});
if (unibuildMeta.arch === 'browser')
unibuildMeta.arch = 'client'; // XXX hack, figure out how to get this work
self.unibuilds.push(new Unibuild(self, {
name: unibuildMeta.name,
arch: unibuildMeta.arch,