Skip to content

Commit

Permalink
Remove include() add node.mixin()
Browse files Browse the repository at this point in the history
include() should not be used by libraries because it will pollute the global
namespace. To discourage this behavior and bring Node more in-line with
the current CommonJS module system, include() is removed.

Small scripts like unit tests often times do want to pollute the global
namespace for ease. To avoid the boiler plate code of

  var x = require("/x.js");
  var foo = x.foo;
  var bar = x.bar;

The function node.mixin() is stolen from jQuery's jQuery.extend. So that it
can be written:

  node.mixin(require("/x.js"));

Reference:
http://docs.jquery.com/Utilities/jQuery.extend
http://groups.google.com/group/nodejs/browse_thread/thread/f9ac83e5c11e7e87
  • Loading branch information
ry committed Oct 5, 2009
1 parent 522909b commit 8185e1f
Show file tree
Hide file tree
Showing 46 changed files with 136 additions and 93 deletions.
4 changes: 2 additions & 2 deletions benchmark/http_simple.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
libDir = node.path.join(node.path.dirname(__filename), "../lib");
node.libraryPaths.unshift(libDir);

include("/utils.js");
node.mixin(require("/utils.js"));
http = require("/http.js");

fixed = ""
Expand All @@ -16,7 +16,7 @@ http.createServer(function (req, res) {
var arg = commands[2];
var status = 200;

//p(req.headers);
p(req.uri.params);

if (command == "bytes") {
var n = parseInt(arg, 10)
Expand Down
2 changes: 1 addition & 1 deletion benchmark/process_loop.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
libDir = node.path.join(node.path.dirname(__filename), "../lib");
node.libraryPaths.unshift(libDir);
include("/utils.js");
node.mixin(require("/utils.js"));
function next (i) {
if (i <= 0) return;

Expand Down
2 changes: 1 addition & 1 deletion benchmark/run.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
libDir = node.path.join(node.path.dirname(__filename), "../lib");
node.libraryPaths.unshift(libDir);
include("/utils.js");
node.mixin(require("/utils.js"));
var benchmarks = [ "static_http_server.js"
, "timers.js"
, "process_loop.js"
Expand Down
2 changes: 1 addition & 1 deletion bin/node-repl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env node

include("/utils.js");
node.mixin(require("/utils.js"));
puts("Welcome to the Node.js REPL.");
puts("Enter ECMAScript at the prompt.");
puts("Tip 1: Use 'rlwrap node-repl' for a better interface");
Expand Down
48 changes: 27 additions & 21 deletions doc/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ An example of a web server written with Node which responds with "Hello
World":

----------------------------------------
include("/utils.js");
include("/http.js");
node.mixin(require("/utils.js"));
node.mixin(require("/http.js"));
createServer(function (request, response) {
response.sendHeader(200, {"Content-Type": "text/plain"});
response.sendBody("Hello World\n");
Expand Down Expand Up @@ -61,11 +61,23 @@ error reporting.
The filename of the script being executed.

+require(path)+ ::
+include(path)+ ::
See the modules section.

+node.libraryPaths+ ::
The search path for absolute path arguments to +require()+ and +include()+.
The search path for absolute path arguments to +require()+.

+node.mixin([deep], target, object1, [objectN])+ ::
Extend one object with one or more others, returning the modified object.
If no target is specified, the +process+ namespace itself is extended.
Keep in mind that the target object will be modified, and will be returned
from +node.mixin()+.
+
If a boolean true is specified as the first argument, Node performs a deep
copy, recursively copying any objects it finds. Otherwise, the copy will
share structure with the original object(s).
+
Undefined properties are not copied. However, properties inherited from the
object's prototype will be copied over.

=== The +process+ Object

Expand Down Expand Up @@ -119,7 +131,7 @@ Executes the command as a child process, buffers the output and returns it
in a promise callback.
+
----------------------------------------
include("/utils.js");
node.mixin(require("/utils.js"));
exec("ls /").addCallback(function (stdout, stderr) {
puts(stdout);
});
Expand Down Expand Up @@ -269,7 +281,7 @@ The contents of +foo.js+:

----------------------------------------
var circle = require("circle.js");
include("/utils.js");
node.mixin(require("/utils.js"));
puts("The area of a circle of radius 4 is " + circle.area(4));
----------------------------------------

Expand All @@ -292,24 +304,20 @@ The module +circle.js+ has exported the functions +area()+ and
object. (Alternatively, one can use +this+ instead of +exports+.) Variables
local to the module will be private. In this example the variable +PI+ is
private to +circle.js+. The function +puts()+ comes from the module
+"/utils.js"+. Because +include("/utils.js")+ was called, +puts()+ is in the
global namespace.
+"/utils.js"+.

The module path is relative to the file calling +require()+. That is,
+circle.js+ must be in the same directory as +foo.js+ for +require()+ to
find it.

Like +require()+ the function +include()+ also loads a module. Instead of
returning a namespace object, +include()+ will add the module's exports into
the global namespace. For example:
Use +node.mixin()+ to include modules into the global namespace.

----------------------------------------
include("circle.js");
include("/utils.js");
node.mixin(process, require("circle.js"), require("/utils.js"));
puts("The area of a cirlce of radius 4 is " + area(4));
----------------------------------------

When an absolute path is given to +require()+ or +include()+, like
When an absolute path is given to +require()+, like
+require("/mjsunit.js")+ the module is searched for in the
+node.libraryPaths+ array. +node.libraryPaths+ on my system looks like this:

Expand Down Expand Up @@ -567,8 +575,7 @@ Objects returned from +node.fs.stat()+ are of this type.

=== HTTP

To use the HTTP server and client one must +require("/http.js")+ or
+include("/http.js")+.
To use the HTTP server and client one must +require("/http.js")+.

The HTTP interfaces in Node are designed to support many features
of the protocol which have been traditionally difficult to use.
Expand Down Expand Up @@ -990,16 +997,15 @@ stream.addListener('complete', function() {

=== TCP

To use the TCP server and client one must +require("/tcp.js")+ or
+include("/tcp.js")+.
To use the TCP server and client one must +require("/tcp.js")+.

==== +tcp.Server+

Here is an example of a echo server which listens for connections
on port 7000

----------------------------------------
include("/tcp.js");
node.mixin(require("/tcp.js"));
var server = createServer(function (socket) {
socket.setEncoding("utf8");
socket.addListener("connect", function () {
Expand Down Expand Up @@ -1237,8 +1243,8 @@ result of the last expression.

The library is called +/repl.js+ and it can be used like this:
------------------------------------
include("/utils.js");
include("/tcp.js");
node.mixin(require("/utils.js"));
node.mixin(require("/tcp.js"));
nconnections = 0;
createServer(function (c) {
error("Connection!");
Expand Down
76 changes: 58 additions & 18 deletions src/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ node.createChildProcess = function (command) {
};

node.exec = function () {
throw new Error("node.exec() has moved. Use include('/utils.js') to bring it back.");
throw new Error("node.exec() has moved. Use require('/utils.js') to bring it back.");
}

node.http.createServer = function () {
Expand All @@ -28,6 +28,61 @@ node.tcp.createConnection = function (port, host) {
throw new Error("node.tcp.createConnection() has moved. Use require('/tcp.js') to access it.");
};

/* From jQuery.extend in the jQuery JavaScript Library v1.3.2
* Copyright (c) 2009 John Resig
* Dual licensed under the MIT and GPL licenses.
* http://docs.jquery.com/License
*/
node.mixin = function() {
// copy reference to target object
var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

// Handle a deep copy situation
if ( typeof target === "boolean" ) {
deep = target;
target = arguments[1] || {};
// skip the boolean and the target
i = 2;
}

// Handle case when target is a string or something (possible in deep copy)
if ( typeof target !== "object" && !node.isFunction(target) )
target = {};

// mixin process itself if only one argument is passed
if ( length == i ) {
target = process;
--i;
}

for ( ; i < length; i++ )
// Only deal with non-null/undefined values
if ( (options = arguments[ i ]) != null )
// Extend the base object
for ( var name in options ) {
var src = target[ name ], copy = options[ name ];

// Prevent never-ending loop
if ( target === copy )
continue;

// Recurse if we're merging object values
if ( deep && copy && typeof copy === "object" && !copy.nodeType )
target[ name ] = node.mixin( deep,
// Never move original objects, clone them
src || ( copy.length != null ? [ ] : { } )
, copy );

// Don't bring in undefined values
else if ( copy !== undefined )
target[ name ] = copy;

}

// Return the modified object
return target;
};

// Timers

function setTimeout (callback, after) {
Expand Down Expand Up @@ -207,27 +262,12 @@ node.Module.prototype.loadScript = function (loadPromise) {
return requireAsync(url).wait();
}

function includeAsync (url) {
var promise = requireAsync(url)
promise.addCallback(function (t) {
// copy properties into global namespace.
for (var prop in t) {
if (t.hasOwnProperty(prop)) process[prop] = t[prop];
}
});
return promise;
}

function include (url) {
includeAsync(url).wait();
}

// create wrapper function
var wrapper = "function (__filename, exports, require, include) { " + content + "\n};";
var wrapper = "function (__filename, exports, require) { " + content + "\n};";
var compiled_wrapper = node.compile(wrapper, self.filename);

node.loadingModules.unshift(self);
compiled_wrapper.apply(self.target, [self.filename, self.target, require, include]);
compiled_wrapper.apply(self.target, [self.filename, self.target, require]);
node.loadingModules.shift();

self.waitChildrenLoad(function () {
Expand Down
10 changes: 5 additions & 5 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,21 +70,21 @@ node.path = new function () {


puts = function () {
throw new Error("puts() has moved. Use include('/utils.js') to bring it back.");
throw new Error("puts() has moved. Use require('/utils.js') to bring it back.");
}

print = function () {
throw new Error("print() has moved. Use include('/utils.js') to bring it back.");
throw new Error("print() has moved. Use require('/utils.js') to bring it back.");
}

p = function () {
throw new Error("p() has moved. Use include('/utils.js') to bring it back.");
throw new Error("p() has moved. Use require('/utils.js') to bring it back.");
}

node.debug = function () {
throw new Error("node.debug() has moved. Use include('/utils.js') to bring it back.");
throw new Error("node.debug() has moved. Use require('/utils.js') to bring it back.");
}

node.error = function () {
throw new Error("node.error() has moved. Use include('/utils.js') to bring it back.");
throw new Error("node.error() has moved. Use require('/utils.js') to bring it back.");
}
8 changes: 2 additions & 6 deletions test/mjsunit/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ exports.libDir = node.path.join(exports.testDir, "../../lib");
node.libraryPaths.unshift(exports.libDir);

var mjsunit = require("/mjsunit.js");
include("/utils.js");
// Copy mjsunit namespace out
for (var prop in mjsunit) {
if (mjsunit.hasOwnProperty(prop)) exports[prop] = mjsunit[prop];
}

var utils = require("/utils.js");
node.mixin(exports, mjsunit, utils);

2 changes: 1 addition & 1 deletion test/mjsunit/disabled/test-cat.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("common.js");
node.mixin(require("../common.js"));
http = require("/http.js");
PORT = 8888;

Expand Down
2 changes: 1 addition & 1 deletion test/mjsunit/disabled/test-http-stress.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include('../mjsunit.js');
node.mixin(require('../common.js'));

var PORT = 8003;
var request_count = 1000;
Expand Down
2 changes: 1 addition & 1 deletion test/mjsunit/disabled/test-remote-module-loading.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ var s = node.http.createServer(function (req, res) {
});
s.listen(8000);

include("mjsunit.js");
node.mixin(require("../common.js"));
var a = require("http://localhost:8000/")

assertInstanceof(a.A, Function);
Expand Down
1 change: 1 addition & 0 deletions test/mjsunit/disabled/test_dns.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node.mixin(require("../common.js"));
for (var i = 2; i < ARGV.length; i++) {
var name = ARGV[i]
puts("looking up " + name);
Expand Down
4 changes: 2 additions & 2 deletions test/mjsunit/test-buffered-file.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
include("common.js");
node.mixin(require("common.js"));

var testTxt = node.path.join(fixturesDir, "test.txt");

var libDir = node.path.join(testDir, "../../lib");
node.libraryPaths.unshift(libDir);
include("/file.js");
node.mixin(require("/file.js"));

var fileUnlinked = false;

Expand Down
2 changes: 1 addition & 1 deletion test/mjsunit/test-delayed-require.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("common.js");
node.mixin(require("common.js"));

setTimeout(function () {
a = require("fixtures/a.js");
Expand Down
2 changes: 1 addition & 1 deletion test/mjsunit/test-event-emitter-add-listeners.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("common.js");
node.mixin(require("common.js"));

var e = new node.EventEmitter();

Expand Down
2 changes: 1 addition & 1 deletion test/mjsunit/test-exec.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("common.js");
node.mixin(require("common.js"));

success_count = 0;
error_count = 0;
Expand Down
2 changes: 1 addition & 1 deletion test/mjsunit/test-file-cat-noexist.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("common.js");
node.mixin(require("common.js"));
var got_error = false;

var filename = node.path.join(fixturesDir, "does_not_exist.txt");
Expand Down
2 changes: 1 addition & 1 deletion test/mjsunit/test-fs-stat.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("common.js");
node.mixin(require("common.js"));

var got_error = false;
var success_count = 0;
Expand Down
2 changes: 1 addition & 1 deletion test/mjsunit/test-fs-write.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("common.js");
node.mixin(require("common.js"));

var path = node.path.join(fixturesDir, "write.txt");
var expected = "hello";
Expand Down
2 changes: 1 addition & 1 deletion test/mjsunit/test-http-cat.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("common.js");
node.mixin(require("common.js"));
http = require("/http.js");
PORT = 8888;

Expand Down
2 changes: 1 addition & 1 deletion test/mjsunit/test-http-client-race.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("common.js");
node.mixin(require("common.js"));
http = require("/http.js");
PORT = 8888;

Expand Down
2 changes: 1 addition & 1 deletion test/mjsunit/test-http-client-upload.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
include("common.js");
node.mixin(require("common.js"));
http = require("/http.js");
var PORT = 18032;

Expand Down
Loading

0 comments on commit 8185e1f

Please sign in to comment.