Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge remote-tracking branch 'upstream/master'

  • Loading branch information...
commit 25b015d23e37b5f27b5a5374963d3eea9091511c 2 parents 4707fe1 + 9967c36
@jeremys jeremys authored
View
32 doc/api/modules.markdown
@@ -330,6 +330,38 @@ Because `module` provides a `filename` property (normally equivalent to
`__filename`), the entry point of the current application can be obtained
by checking `require.main.filename`.
+## AMD Compatibility
+
+Node's modules have access to a function named `define`, which may be
+used to specify the module's return value. This is not necessary in node
+programs, but is present in the node API in order to provide
+compatibility with module loaders that use the Asynchronous Module
+Definition pattern.
+
+The example module above could be structured like so:
+
+ define(function (require, exports, module) {
+ var PI = Math.PI;
+
+ exports.area = function (r) {
+ return PI * r * r;
+ };
+
+ exports.circumference = function (r) {
+ return 2 * PI * r;
+ };
+ });
+
+* Only the last argument to `define()` matters. Other module loaders
+ sometimes use a `define(id, [deps], cb)` pattern, but since this is
+ not relevant in node programs, the other arguments are ignored.
+* If the `define` callback returns a value other than `undefined`, then
+ that value is assigned to `module.exports`.
+* **Important**: Despite being called "AMD", the node module loader **is
+ in fact synchronous**, and using `define()` does not change this fact.
+ Node executes the callback immediately, so please plan your programs
+ accordingly.
+
## Addenda: Package Manager Tips
The semantics of Node's `require()` function were designed to be general
View
39 lib/module.js
@@ -381,6 +381,7 @@ Module.prototype._compile = function(content, filename) {
require.cache = Module._cache;
var dirname = path.dirname(filename);
+ var define = makeDefine(require, self);
if (Module._contextLoad) {
if (self.id !== '.') {
@@ -397,6 +398,7 @@ Module.prototype._compile = function(content, filename) {
sandbox.module = self;
sandbox.global = sandbox;
sandbox.root = root;
+ sandbox.define = define;
return runInNewContext(content, sandbox, filename, true);
}
@@ -408,6 +410,7 @@ Module.prototype._compile = function(content, filename) {
global.__filename = filename;
global.__dirname = dirname;
global.module = self;
+ global.define = define;
return runInThisContext(content, filename, true);
}
@@ -419,10 +422,44 @@ Module.prototype._compile = function(content, filename) {
if (filename === process.argv[1] && global.v8debug) {
global.v8debug.Debug.setBreakPoint(compiledWrapper, 0, 0);
}
- var args = [self.exports, require, self, filename, dirname];
+
+ var args = [self.exports, require, self, filename, dirname, define];
return compiledWrapper.apply(self.exports, args);
};
+// AMD compatibility
+function makeDefine(require, module) {
+ var called = false;
+ function define() {
+ if (called) {
+ throw new Error("define() may only be called once.");
+ }
+ called = true;
+
+ // only care about the last argument
+ var cb = arguments[ arguments.length - 1 ];
+
+ // set exports immediately:
+ // define({ foo: "bar" })
+ if (typeof cb !== 'function') {
+ module.exports = cb;
+ return;
+ }
+
+ var ret = cb(require, module.exports, module);
+
+ if (ret !== undefined) {
+ // set exports with return statement
+ // define(function () { return { foo: "bar" } })
+ module.exports = ret;
+ }
+ }
+
+ return define;
+}
+
+
+
// Native extension for .js
Module._extensions['.js'] = function(module, filename) {
var content = NativeModule.require('fs').readFileSync(filename, 'utf8');
View
4 src/node.cc
@@ -1287,7 +1287,7 @@ void DisplayExceptionLine (TryCatch &try_catch) {
//
// When reporting errors on the first line of a script, this wrapper
// function is leaked to the user. This HACK is to remove it. The length
- // of the wrapper is 62. That wrapper is defined in src/node.js
+ // of the wrapper is 70. That wrapper is defined in src/node.js
//
// If that wrapper is ever changed, then this number also has to be
// updated. Or - someone could clean this up so that the two peices
@@ -1295,7 +1295,7 @@ void DisplayExceptionLine (TryCatch &try_catch) {
//
// Even better would be to get support into V8 for wrappers that
// shouldn't be reported to users.
- int offset = linenum == 1 ? 62 : 0;
+ int offset = linenum == 1 ? 70 : 0;
fprintf(stderr, "%s\n", sourceline_string + offset);
// Print wavy underline (GetUnderline is deprecated).
View
2  src/node.js
@@ -436,7 +436,7 @@
};
NativeModule.wrapper = [
- '(function (exports, require, module, __filename, __dirname) { ',
+ '(function (exports, require, module, __filename, __dirname, define) { ',
'\n});'
];
View
3  test/fixtures/amd-modules/extra-args.js
@@ -0,0 +1,3 @@
+define(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, function(r, e, m) {
+ exports.ok = require("./regular.js").ok;
+});
View
3  test/fixtures/amd-modules/module-exports.js
@@ -0,0 +1,3 @@
+define(function(require, exports, module) {
+ module.exports = { ok: require("./regular.js").ok };
+});
View
1  test/fixtures/amd-modules/object.js
@@ -0,0 +1 @@
+define({ ok: require("./regular.js").ok });
View
14 test/fixtures/amd-modules/regular.js
@@ -0,0 +1,14 @@
+var R = require;
+var E = exports;
+var M = module;
+
+define(function(require, exports, module, nothingHere) {
+ if (R !== require) throw new Error("invalid require in AMD cb");
+ if (E !== exports) throw new Error("invalid exports in AMD cb");
+ if (M !== module) throw new Error("invalid module in AMD cb");
+ if (nothingHere !== undefined) {
+ throw new Error("unknown args to AMD cb");
+ }
+
+ exports.ok = { ok: true };
+});
View
3  test/fixtures/amd-modules/return.js
@@ -0,0 +1,3 @@
+define(function() {
+ return { ok: require("./regular.js").ok };
+});
View
20 test/simple/test-module-loading.js
@@ -187,6 +187,26 @@ try {
assert.equal(require(loadOrder + 'file8').file8, 'file8/index.reg', msg);
assert.equal(require(loadOrder + 'file9').file9, 'file9/index.reg2', msg);
+
+// test the async module definition pattern modules
+var amdFolder = '../fixtures/amd-modules';
+var amdreg = require(amdFolder + '/regular.js');
+assert.deepEqual(amdreg.ok, {ok: true}, 'regular amd module failed');
+
+// make sure they all get the same 'ok' object.
+var amdModuleExports = require(amdFolder + '/module-exports.js');
+assert.equal(amdModuleExports.ok, amdreg.ok, 'amd module.exports failed');
+
+var amdReturn = require(amdFolder + '/return.js');
+assert.equal(amdReturn.ok, amdreg.ok, 'amd return failed');
+
+var amdObj = require(amdFolder + '/object.js');
+assert.equal(amdObj.ok, amdreg.ok, 'amd object literal failed');
+
+var amdExtraArgs = require(amdFolder + '/extra-args.js');
+assert.equal(amdExtraArgs.ok, amdreg.ok, 'amd extra args failed');
+
+
process.addListener('exit', function() {
assert.ok(common.indirectInstanceOf(a.A, Function));
assert.equal('A done', a.A());
Please sign in to comment.
Something went wrong with that request. Please try again.