sea.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /**
  2. * Add the capability to load CMD modules in node environment
  3. * @author lifesinger@gmail.com
  4. */
  5. var fs = require("fs")
  6. var path = require("path")
  7. var vm = require("vm")
  8. var normalize = require("./winos").normalize
  9. var moduleStack = []
  10. var uriCache = {}
  11. var nativeLoad
  12. runSeaJS("../dist/sea-debug.js")
  13. hackNative()
  14. attach()
  15. keep()
  16. seajs.config({ cwd: normalize(process.cwd()) + "/" })
  17. function runSeaJS(filepath) {
  18. var code = fs.readFileSync(path.join(__dirname, filepath), "utf8")
  19. code = code.replace("})(this);", "})(exports);")
  20. // Run "sea.js" code in a fake browser environment
  21. var sandbox = require("./sandbox")
  22. vm.runInNewContext(code, sandbox, "sea-debug.vm")
  23. global.seajs = sandbox.exports.seajs
  24. global.define = sandbox.exports.define
  25. }
  26. function hackNative() {
  27. var Module = module.constructor
  28. nativeLoad = Module._load
  29. Module._load = function(request, parent, isMain) {
  30. var exports = nativeLoad(request, parent, isMain)
  31. var _filename = Module._resolveFilename(request, parent)
  32. var filename = normalize(_filename)
  33. var mod = seajs.cache[filename]
  34. if (mod) {
  35. if (mod.status < seajs.Module.STATUS.EXECUTING) {
  36. seajs.use(filename)
  37. }
  38. exports = Module._cache[_filename] = mod.exports
  39. }
  40. return exports
  41. }
  42. var _compile = Module.prototype._compile
  43. Module.prototype._compile = function(content, filename) {
  44. moduleStack.push(this)
  45. try {
  46. return _compile.call(this, content, filename)
  47. }
  48. finally {
  49. moduleStack.pop()
  50. }
  51. }
  52. }
  53. function attach() {
  54. seajs.on("request", requestListener)
  55. seajs.on("define", defineListener)
  56. }
  57. function requestListener(data) {
  58. var requestUri = pure(data.requestUri)
  59. var ext = path.extname(requestUri)
  60. //process.stdout.write("requestUri = " + requestUri + "\n")
  61. if (ext === ".js") {
  62. // Use native `require` instead of script-inserted version
  63. nativeLoad(requestUri)
  64. data.onRequest()
  65. data.requested = true
  66. }
  67. // Throw error if this function is the last request handler
  68. else if (seajs.data.events["request"].length === 1) {
  69. throw new Error("Do NOT support to load this file in node environment: "
  70. + requestUri)
  71. }
  72. }
  73. function defineListener(data) {
  74. if (!data.uri) {
  75. var derivedUri = normalize(moduleStack[moduleStack.length - 1].id)
  76. data.uri = uriCache[derivedUri] || derivedUri
  77. }
  78. }
  79. function keep() {
  80. var _off = seajs.off
  81. var events = seajs.data.events
  82. seajs.off = function(name, callback) {
  83. // Remove *all* events
  84. if (!(name || callback)) {
  85. // For Node.js to work properly
  86. for (var prop in events) {
  87. delete events[prop]
  88. }
  89. }
  90. else {
  91. _off(name, callback)
  92. }
  93. attach()
  94. return seajs
  95. }
  96. }
  97. function pure(uri) {
  98. // Remove timestamp etc
  99. var ret = uri.replace(/\?.*$/, "")
  100. // Cache it
  101. if (ret !== uri) {
  102. uriCache[ret] = uri
  103. }
  104. return ret
  105. }