Browse Source

reimplement module loading

still missing several important features and its mostly untested but the script
test/test-test.js is working and thats enough for now.
v0.7.4-release
Ryan 16 years ago
parent
commit
93f7f0dca0
  1. 196
      src/main.js
  2. 60
      src/node.cc
  3. 25
      test/cat.js
  4. 3
      test/stats.js
  5. 19
      test/test-test.js

196
src/main.js

@ -7,65 +7,157 @@ Array.prototype.encodeUtf8 = function () {
}
node.path = new function () {
this.join = function () {
var joined = "";
for (var i = 0; i < arguments.length; i++) {
var part = arguments[i].toString();
if (i === 0) {
part = part.replace(/\/*$/, "/");
} else if (i === arguments.length - 1) {
part = part.replace(/^\/*/, "");
} else {
part = part.replace(/^\/*/, "")
.replace(/\/*$/, "/");
}
joined += part;
this.join = function () {
var joined = "";
for (var i = 0; i < arguments.length; i++) {
var part = arguments[i].toString();
if (i === 0) {
part = part.replace(/\/*$/, "/");
} else if (i === arguments.length - 1) {
part = part.replace(/^\/*/, "");
} else {
part = part.replace(/^\/*/, "")
.replace(/\/*$/, "/");
}
joined += part;
}
return joined;
};
this.dirname = function (path) {
var parts = path.split("/");
return parts.slice(0, parts.length-1);
};
};
// Namespace for module loading functionality
(function () {
function findScript(base_directory, name, callback) {
// in the future this function will be more complicated
if (name.charAt(0) == "/")
throw "absolute module paths are not yet supported.";
var filename = node.path.join(base_directory, name) + ".js";
File.exists(filename, function (status) {
if (status)
callback(filename);
else
callback(null);
});
}
// Constructor for submodule.
// "name" is like a path but without .js. e.g. "database/mysql"
// "target" is an object into which the submodule will be loaded.
function Sub (name, target) {
this.name = name;
this.target = target;
//puts("new Sub. name = " + name);
this.load = function (base_directory, callback) {
findScript(base_directory, name, function (filename) {
if (filename === null) {
stderr.puts("Cannot find a script matching: " + name);
process.exit(1);
}
return joined;
//puts("load subscript: " + filename);
//puts(" target = " + target);
loadScript(filename, target, callback);
});
};
this.dirname = function (path) {
var parts = path.split("/");
return parts.slice(0, parts.length-1);
};
};
this.toString = function () {
return "[sub name=" + name + " target=" + target.toString() + "]";
}
}
function __include (module, path) {
var export = module.require(path);
for (var i in export) {
if (export.hasOwnProperty(i))
module[i] = export[i];
function Scaffold (source, filename, module) {
// wrap the source in a strange function
var source = "function (__filename) {\n"
+ " var on_load;\n"
+ " var exports = this;\n"
+ " var require = this.__require;\n"
+ " var include = this.__include;\n"
+ source + "\n"
+ " this.__on_load = on_load;\n"
+ "};"
;
// returns the function
var compiled = node.compile(source, filename);
module.__subs = [];
module.__require = function (name) {
var target = {};
module.__subs.push(new Sub(name, target));
return target;
}
}
module.__include = function (name) {
module.__subs.push(new Sub(name, module));
}
// execute the script of interest
compiled.apply(module, [filename]);
function __require (path, loading_file) {
// The module still needs to have its submodules loaded.
this.module = module;
this.subs = module.__subs;
this.on_load = module.__on_load;
var filename = path;
// relative path
// absolute path
if (path.slice(0,1) === "/") {
} else {
//filename = node.path.join(node.path.dirname(loading_file), path);
/*
puts("new Scaffold.");
for(var i = 0; i < this.subs.length; i++) {
puts("- subs[" + i.toString() + "] " + this.subs[i].toString());
}
//stdout.puts("require: " + filename);
var source = node.blocking.cat(filename);
// wrap the source in a function
source = "function (__file__, __dir__) { "
+ " var exports = {};"
+ " function require (m) { return __require(m, __file__); }"
+ " function include (m) { return __include(this, m); }"
+ source
+ " return exports;"
+ "};"
;
var create_module = node.blocking.exec(source, filename);
// execute the function wrap
return create_module(filename, node.path.dirname(filename));
}
*/
// remove these references so they don't get exported.
delete module.__subs;
delete module.__on_load;
delete module.__require;
delete module.__include;
}
function loadScript (filename, target, callback) {
File.cat(filename, function (status, content) {
if (status != 0) {
stderr.puts("Error reading " + filename + ": " + File.strerror(status));
process.exit(1);
}
//puts("loadScript: " + filename);
var scaffold = new Scaffold(content, filename, target);
function finish() {
if (scaffold.on_load instanceof Function)
scaffold.on_load();
else
; //puts("no on_load for " + filename + " .. scaffold.on_load = " + scaffold.on_load);
if (callback instanceof Function)
callback();
else
; //puts("no loadScript callback for " + filename);
}
// Each time require() or include() was called inside the script
// a key/value was added to scaffold.__subs.
// Now we loop though each one and recursively load each.
if (scaffold.subs.length == 0) {
finish();
} else {
while (scaffold.subs.length > 0) {
var sub = scaffold.subs.shift();
sub.load(node.path.dirname(filename), function () {
//puts("finish sub load: " + sub.name);
if(scaffold.subs.length != 0) return;
finish();
});
}
}
});
}
// main script execution.
__require(ARGV[1], ".");
loadScript(ARGV[1], this);
})();

60
src/node.cc

@ -83,59 +83,7 @@ ExecuteString(v8::Handle<v8::String> source,
return scope.Close(result);
}
JS_METHOD(cat)
{
if (args.Length() < 1) return v8::Undefined();
HandleScope scope;
String::Utf8Value filename(args[0]);
Local<String> error_msg = String::New("File I/O error");
FILE* file = fopen(*filename, "rb");
if (file == NULL) {
// Raise error
perror("fopen()");
return ThrowException(error_msg);
}
int r = fseek(file, 0, SEEK_END);
if (r < 0) {
perror("fseek()");
return ThrowException(error_msg);
}
int size = ftell(file);
if (size < 0) {
perror("ftell()");
return ThrowException(error_msg);
}
rewind(file);
char chars[size+1];
chars[size] = '\0';
for (int i = 0; i < size;) {
int read = fread(&chars[i], 1, size - i, file);
if(read <= 0) {
perror("read()");
return ThrowException(error_msg);
}
i += read;
}
uint16_t expanded_base[size+1];
expanded_base[size] = '\0';
for(int i = 0; i < size; i++)
expanded_base[i] = chars[i];
fclose(file);
Local<String> contents = String::New(expanded_base, size);
return scope.Close(contents);
}
JS_METHOD(exec)
JS_METHOD(compile)
{
if (args.Length() < 2)
return Undefined();
@ -233,11 +181,7 @@ main (int argc, char *argv[])
Local<Object> node = Object::New();
g->Set(String::New("node"), node);
Local<Object> blocking = Object::New();
node->Set(String::New("blocking"), blocking);
JS_SET_METHOD(blocking, "exec", exec);
JS_SET_METHOD(blocking, "cat", cat);
JS_SET_METHOD(node, "compile", compile);
Local<Array> arguments = Array::New(argc);
for (int i = 0; i < argc; i++) {

25
test/cat.js

@ -1,21 +1,8 @@
var filename = ARGV[2];
function cat (file) {
file.read(100, function (status, data) {
if (status == 0 && data) {
stdout.write(data.encodeUtf8());
cat(file);
} else {
file.close();
}
});
}
var f = new File;
f.open(filename, "r", function (status) {
puts("open!");
if (status == 0)
cat(f);
File.cat(filename, function (status, content) {
if (status == 0)
puts(content);
else
puts("error?");
})
puts("error");
});
puts("hello world");

3
test/stats.js

@ -8,7 +8,8 @@ File.stat(ARGV[2], function (status, stats) {
}
});
File.exists(ARGV[2], function (r) {
puts("file exists: " + r);
});

19
test/test-test.js

@ -1,12 +1,9 @@
node.blocking.print(__file__);
/*
if (node.path.dirname(__file__) !== "test-test.js") {
throw "wrong __file__ argument";
}
*/
var mjsunit = require("./mjsunit.js");
node.blocking.print(__file__);
puts(__filename);
include("mjsunit");
puts(__filename);
mjsunit.assertFalse(false, "testing the test program.");
//mjsunit.assertEquals("test-test.js", __file__);
function on_load () {
assertFalse(false, "testing the test program.");
puts("i think everything is okay.");
//mjsunit.assertEquals("test-test.js", __file__);
}

Loading…
Cancel
Save