From 93f7f0dca01ff00faf59e8c4e5dd01b043dee4f1 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 20 Apr 2009 02:55:08 +0200 Subject: [PATCH] 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. --- src/main.js | 196 +++++++++++++++++++++++++++++++++++++++--------------- src/node.cc | 60 +---------------- test/cat.js | 25 ++----- test/stats.js | 3 +- test/test-test.js | 19 +++--- 5 files changed, 162 insertions(+), 141 deletions(-) diff --git a/src/main.js b/src/main.js index 2a74003..e37784a 100644 --- a/src/main.js +++ b/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); +})(); diff --git a/src/node.cc b/src/node.cc index 35b4d2b..480dd77 100644 --- a/src/node.cc +++ b/src/node.cc @@ -83,59 +83,7 @@ ExecuteString(v8::Handle source, return scope.Close(result); } -JS_METHOD(cat) -{ - if (args.Length() < 1) return v8::Undefined(); - HandleScope scope; - - String::Utf8Value filename(args[0]); - - Local 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 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 node = Object::New(); g->Set(String::New("node"), node); - Local 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 arguments = Array::New(argc); for (int i = 0; i < argc; i++) { diff --git a/test/cat.js b/test/cat.js index b8cc489..9f6aa61 100644 --- a/test/cat.js +++ b/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"); diff --git a/test/stats.js b/test/stats.js index 4d670f8..157a2d0 100644 --- a/test/stats.js +++ b/test/stats.js @@ -8,7 +8,8 @@ File.stat(ARGV[2], function (status, stats) { } }); - File.exists(ARGV[2], function (r) { puts("file exists: " + r); }); + + diff --git a/test/test-test.js b/test/test-test.js index 18a364f..ac9d89b 100644 --- a/test/test-test.js +++ b/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__); +} -- 2.7.4