Files
meteor/packages/modules-runtime/modules-runtime.js
Ben Newman b3a83bd118 Install reliable stubs for all Package[name] objects.
If a Meteor package had a file called index.js, the runtime module system
would resolve "meteor/<name>" to "/node_modules/meteor/<name>/index.js",
instead of falling back to Package[<name>] as expected.

Installing a stub for Package[<name>] at /node_modules/meteor/<name>.js
means the runtime module system no longer needs the fallback, and will no
longer be confused by index.js files.

Fixes #6590.
2016-04-07 13:05:52 -04:00

68 lines
2.1 KiB
JavaScript

var options = {};
var hasOwn = options.hasOwnProperty;
// RegExp matching strings that don't start with a `.` or a `/`.
var topLevelIdPattern = /^[^./]/;
// This function will be called whenever a module identifier that hasn't
// been installed is required. For backwards compatibility, and so that we
// can require binary dependencies on the server, we implement the
// fallback in terms of Npm.require.
options.fallback = function (id, dir, error) {
// For simplicity, we honor only top-level module identifiers here.
// We could try to honor relative and absolute module identifiers by
// somehow combining `id` with `dir`, but we'd have to be really careful
// that the resulting modules were located in a known directory (not
// some arbitrary location on the file system), and we only really need
// the fallback for dependencies installed in node_modules directories.
if (topLevelIdPattern.test(id)) {
if (typeof Npm === "object" &&
typeof Npm.require === "function") {
return Npm.require(id);
}
}
throw error;
};
if (Meteor.isServer) {
// Defining Module.prototype.useNode allows the module system to
// delegate evaluation to Node, unless useNode returns false.
(options.Module = function Module(id) {
// Same as the default Module constructor implementation.
this.id = id;
this.children = [];
}).prototype.useNode = function () {
if (typeof npmRequire !== "function") {
// Can't use Node if npmRequire is not defined.
return false;
}
var parts = this.id.split("/");
var start = 0;
if (parts[start] === "") ++start;
if (parts[start] === "node_modules" &&
parts[start + 1] === "meteor") {
start += 2;
}
if (parts.indexOf("node_modules", start) < 0) {
// Don't try to use Node for modules that aren't in node_modules
// directories.
return false;
}
try {
npmRequire.resolve(this.id);
} catch (e) {
return false;
}
this.exports = npmRequire(this.id);
return true;
};
}
meteorInstall = makeInstaller(options);