sproutit-narwhal 0.1.106

Sign up to get free protection for your applications and to get access to all the features.
Files changed (291) hide show
  1. data/DISTRIBUTION.yml +15 -0
  2. data/README.md +86 -0
  3. data/Rakefile +349 -0
  4. data/VERSION.yml +7 -0
  5. data/bin/activate +50 -0
  6. data/bin/activate.bash +50 -0
  7. data/bin/activate.cmd +3 -0
  8. data/bin/js +67 -0
  9. data/bin/json +2 -0
  10. data/bin/narwhal +67 -0
  11. data/bin/narwhal.cmd +29 -0
  12. data/bin/sea +45 -0
  13. data/bin/sea.cmd +25 -0
  14. data/bin/tusk +2 -0
  15. data/bin/tusk.cmd +5 -0
  16. data/catalog.json +902 -0
  17. data/docs/available-packages.md +32 -0
  18. data/docs/browser-api-plan.md +290 -0
  19. data/docs/browser-api.md +153 -0
  20. data/docs/download.md +25 -0
  21. data/docs/engines.md +32 -0
  22. data/docs/json-tool.md +121 -0
  23. data/docs/lib/binary.wiki +242 -0
  24. data/docs/lib/file.wiki +325 -0
  25. data/docs/lib/os/popen.md +70 -0
  26. data/docs/modules.md +38 -0
  27. data/docs/narwhal.md +487 -0
  28. data/docs/packages-howto.md +32 -0
  29. data/docs/packages.md +30 -0
  30. data/docs/posts/2009-07-29-hello-0.1.md +19 -0
  31. data/docs/quick-start.md +69 -0
  32. data/docs/sea.md +49 -0
  33. data/engines/browser/lib/binary.js +2 -0
  34. data/engines/browser/lib/reactor.js +21 -0
  35. data/engines/browser/lib/system.js +3 -0
  36. data/engines/default/lib/array.js +164 -0
  37. data/engines/default/lib/binary-engine.js +53 -0
  38. data/engines/default/lib/binary.js +755 -0
  39. data/engines/default/lib/date.js +8 -0
  40. data/engines/default/lib/file-engine.js +119 -0
  41. data/engines/default/lib/function.js +119 -0
  42. data/engines/default/lib/global.js +11 -0
  43. data/engines/default/lib/io-engine.js +26 -0
  44. data/engines/default/lib/json.js +488 -0
  45. data/engines/default/lib/object.js +69 -0
  46. data/engines/default/lib/os-engine.js +3 -0
  47. data/engines/default/lib/reactor.js +12 -0
  48. data/engines/default/lib/string.js +84 -0
  49. data/engines/default/lib/system.js +20 -0
  50. data/engines/default/lib/worker.js +133 -0
  51. data/engines/jsc/README.md +18 -0
  52. data/engines/jsc/bootstrap.js +53 -0
  53. data/engines/jsc/deps/http-parser/LICENSE +77 -0
  54. data/engines/jsc/deps/http-parser/README.md +145 -0
  55. data/engines/jsc/deps/http-parser/http_parser.c +6087 -0
  56. data/engines/jsc/deps/http-parser/http_parser.h +141 -0
  57. data/engines/jsc/deps/http-parser/http_parser.rl +500 -0
  58. data/engines/jsc/deps/http-parser/test.c +858 -0
  59. data/engines/jsc/include/binary-engine.h +11 -0
  60. data/engines/jsc/include/io-engine.h +23 -0
  61. data/engines/jsc/include/narwhal.h +427 -0
  62. data/engines/jsc/lib/file-engine.js +31 -0
  63. data/engines/jsc/lib/http.js +1 -0
  64. data/engines/jsc/lib/io-engine.js +202 -0
  65. data/engines/jsc/lib/os-engine.js +25 -0
  66. data/engines/jsc/lib/system.js +18 -0
  67. data/engines/jsc/lib/zip.js +1 -0
  68. data/engines/jsc/narwhal-jsc.c +273 -0
  69. data/engines/jsc/narwhal.c +29 -0
  70. data/engines/jsc/package.json +8 -0
  71. data/engines/jsc/src/binary-engine.cc +290 -0
  72. data/engines/jsc/src/file-engine.cc +405 -0
  73. data/engines/jsc/src/io-engine.cc +423 -0
  74. data/engines/jsc/src/jack/handler/jill.cc +710 -0
  75. data/engines/jsc/src/os-engine.cc +210 -0
  76. data/engines/rhino/bin/narwhal-rhino +68 -0
  77. data/engines/rhino/bin/narwhal-rhino.cmd +34 -0
  78. data/engines/rhino/bootstrap.js +119 -0
  79. data/engines/rhino/jars/jline.jar +0 -0
  80. data/engines/rhino/jars/jna.jar +0 -0
  81. data/engines/rhino/jars/js.jar +0 -0
  82. data/engines/rhino/lib/binary-engine.js +83 -0
  83. data/engines/rhino/lib/concurrency.js +6 -0
  84. data/engines/rhino/lib/event-queue.js +18 -0
  85. data/engines/rhino/lib/file-engine.js +216 -0
  86. data/engines/rhino/lib/http-client-engine.js +90 -0
  87. data/engines/rhino/lib/http-engine.js +10 -0
  88. data/engines/rhino/lib/io-engine.js +347 -0
  89. data/engines/rhino/lib/md5-engine.js +40 -0
  90. data/engines/rhino/lib/os-engine.js +150 -0
  91. data/engines/rhino/lib/packages-engine.js +71 -0
  92. data/engines/rhino/lib/sandbox-engine.js +70 -0
  93. data/engines/rhino/lib/system.js +38 -0
  94. data/engines/rhino/lib/worker-engine.js +23 -0
  95. data/engines/rhino/lib/zip.js +78 -0
  96. data/engines/rhino/package.json +4 -0
  97. data/engines/secure/lib/file.js +6 -0
  98. data/engines/secure/lib/system.js +6 -0
  99. data/engines/template/bin/narwhal-engine-name +32 -0
  100. data/engines/template/bootstrap.js +40 -0
  101. data/engines/template/lib/file-engine.js +118 -0
  102. data/engines/template/lib/system.js +17 -0
  103. data/examples/browser-deployment-jackconfig.js +35 -0
  104. data/examples/fibonacci-worker.js +35 -0
  105. data/examples/fibonacci.js +19 -0
  106. data/examples/hello +2 -0
  107. data/examples/narwhal +3 -0
  108. data/examples/not-quite-a-quine.js +1 -0
  109. data/extconf.rb +44 -0
  110. data/gem_bin/narwhal +5 -0
  111. data/gem_bin/sea +4 -0
  112. data/gem_bin/tusk +4 -0
  113. data/lib/args.js +849 -0
  114. data/lib/base16.js +16 -0
  115. data/lib/base64.js +120 -0
  116. data/lib/codec/base64.js +8 -0
  117. data/lib/crc32.js +60 -0
  118. data/lib/file-bootstrap.js +187 -0
  119. data/lib/file.js +659 -0
  120. data/lib/hash.js +28 -0
  121. data/lib/hashp.js +65 -0
  122. data/lib/html.js +16 -0
  123. data/lib/http-client.js +134 -0
  124. data/lib/http.js +17 -0
  125. data/lib/io.js +98 -0
  126. data/lib/jsmin.js +315 -0
  127. data/lib/jsonpath.js +89 -0
  128. data/lib/logger.js +55 -0
  129. data/lib/md4.js +146 -0
  130. data/lib/md5.js +164 -0
  131. data/lib/mime.js +166 -0
  132. data/lib/narwhal.js +102 -0
  133. data/lib/narwhal/client.js +261 -0
  134. data/lib/narwhal/compile.js +99 -0
  135. data/lib/narwhal/env.js +140 -0
  136. data/lib/narwhal/inline.js +106 -0
  137. data/lib/narwhal/json.js +324 -0
  138. data/lib/narwhal/json.md +178 -0
  139. data/lib/narwhal/repl.js +96 -0
  140. data/lib/narwhal/server-test.js +6 -0
  141. data/lib/narwhal/server.js +270 -0
  142. data/lib/narwhal/tusk.js +170 -0
  143. data/lib/narwhal/tusk/bin.js +13 -0
  144. data/lib/narwhal/tusk/bundle.js +0 -0
  145. data/lib/narwhal/tusk/catalog.js +22 -0
  146. data/lib/narwhal/tusk/clone.js +66 -0
  147. data/lib/narwhal/tusk/consolidate.js +25 -0
  148. data/lib/narwhal/tusk/create-catalog.js +80 -0
  149. data/lib/narwhal/tusk/engine.js +42 -0
  150. data/lib/narwhal/tusk/freeze.js +0 -0
  151. data/lib/narwhal/tusk/init.js +56 -0
  152. data/lib/narwhal/tusk/install.js +288 -0
  153. data/lib/narwhal/tusk/list.js +20 -0
  154. data/lib/narwhal/tusk/orphans.js +0 -0
  155. data/lib/narwhal/tusk/reheat.js +15 -0
  156. data/lib/narwhal/tusk/remove.js +15 -0
  157. data/lib/narwhal/tusk/search.js +145 -0
  158. data/lib/narwhal/tusk/update.js +21 -0
  159. data/lib/narwhal/tusk/upgrade.js +0 -0
  160. data/lib/os.js +33 -0
  161. data/lib/packages.js +423 -0
  162. data/lib/printf.js +169 -0
  163. data/lib/promise.js +352 -0
  164. data/lib/querystring.js +176 -0
  165. data/lib/ref-send.js +257 -0
  166. data/lib/regexp.js +12 -0
  167. data/lib/sandbox.js +422 -0
  168. data/lib/sha.js +112 -0
  169. data/lib/sha256.js +102 -0
  170. data/lib/struct.js +228 -0
  171. data/lib/term.js +179 -0
  172. data/lib/test/assert.js +95 -0
  173. data/lib/test/equiv.js +188 -0
  174. data/lib/test/jsdump.js +165 -0
  175. data/lib/test/runner.js +129 -0
  176. data/lib/unload.js +13 -0
  177. data/lib/uri.js +378 -0
  178. data/lib/url.js +5 -0
  179. data/lib/utf8.js +64 -0
  180. data/lib/util.js +985 -0
  181. data/lib/uuid.js +89 -0
  182. data/lib/xregexp.js +521 -0
  183. data/local.json.template +1 -0
  184. data/narwhal.gemspec +105 -0
  185. data/narwhal.js +213 -0
  186. data/package.json +26 -0
  187. data/packages/readline/engines/default/lib/readline.js +4 -0
  188. data/packages/readline/engines/rhino/lib/readline.js +6 -0
  189. data/packages/readline/package.json +5 -0
  190. data/sources.json +207 -0
  191. data/tests/all-tests.js +17 -0
  192. data/tests/args.js +31 -0
  193. data/tests/args/domain.js +215 -0
  194. data/tests/args/options.js +36 -0
  195. data/tests/args/shifting.js +92 -0
  196. data/tests/args/validation.js +31 -0
  197. data/tests/base64.js +23 -0
  198. data/tests/commonjs.js +3 -0
  199. data/tests/commonjs/all-tests.js +12 -0
  200. data/tests/commonjs/bytearray-encodings-tests.js +69 -0
  201. data/tests/commonjs/bytearray-tests.js +465 -0
  202. data/tests/commonjs/bytestring-encodings-tests.js +89 -0
  203. data/tests/commonjs/bytestring-tests.js +263 -0
  204. data/tests/commonjs/es5/all-tests.js +3 -0
  205. data/tests/commonjs/es5/bind.js +29 -0
  206. data/tests/commonjs/file-tests.js +315 -0
  207. data/tests/commonjs/file/dirname.js +31 -0
  208. data/tests/commonjs/file/extension.js +45 -0
  209. data/tests/commonjs/file/is-absolute.js +11 -0
  210. data/tests/commonjs/file/iterator.js +101 -0
  211. data/tests/commonjs/file/normal.js +27 -0
  212. data/tests/commonjs/file/path.js +17 -0
  213. data/tests/commonjs/file/relative.js +42 -0
  214. data/tests/commonjs/file/resolve.js +44 -0
  215. data/tests/commonjs/module-tests.js +9 -0
  216. data/tests/commonjs/modules/absolute/b.js +1 -0
  217. data/tests/commonjs/modules/absolute/program.js +5 -0
  218. data/tests/commonjs/modules/absolute/submodule/a.js +3 -0
  219. data/tests/commonjs/modules/absolute/test.js +9 -0
  220. data/tests/commonjs/modules/all-tests.js +47 -0
  221. data/tests/commonjs/modules/config.js +11 -0
  222. data/tests/commonjs/modules/cyclic/a.js +4 -0
  223. data/tests/commonjs/modules/cyclic/b.js +4 -0
  224. data/tests/commonjs/modules/cyclic/program.js +10 -0
  225. data/tests/commonjs/modules/cyclic/test.js +9 -0
  226. data/tests/commonjs/modules/determinism/program.js +3 -0
  227. data/tests/commonjs/modules/determinism/submodule/a.js +8 -0
  228. data/tests/commonjs/modules/determinism/submodule/b.js +2 -0
  229. data/tests/commonjs/modules/determinism/test.js +9 -0
  230. data/tests/commonjs/modules/exactExports/a.js +3 -0
  231. data/tests/commonjs/modules/exactExports/program.js +4 -0
  232. data/tests/commonjs/modules/exactExports/test.js +9 -0
  233. data/tests/commonjs/modules/hasOwnProperty/hasOwnProperty.js +0 -0
  234. data/tests/commonjs/modules/hasOwnProperty/program.js +3 -0
  235. data/tests/commonjs/modules/hasOwnProperty/test.js +9 -0
  236. data/tests/commonjs/modules/hasOwnProperty/toString.js +0 -0
  237. data/tests/commonjs/modules/method/a.js +12 -0
  238. data/tests/commonjs/modules/method/program.js +8 -0
  239. data/tests/commonjs/modules/method/test.js +9 -0
  240. data/tests/commonjs/modules/missing/program.js +8 -0
  241. data/tests/commonjs/modules/missing/test.js +9 -0
  242. data/tests/commonjs/modules/monkeys/a.js +1 -0
  243. data/tests/commonjs/modules/monkeys/program.js +4 -0
  244. data/tests/commonjs/modules/monkeys/test.js +9 -0
  245. data/tests/commonjs/modules/nested/a/b/c/d.js +3 -0
  246. data/tests/commonjs/modules/nested/program.js +3 -0
  247. data/tests/commonjs/modules/nested/test.js +9 -0
  248. data/tests/commonjs/modules/relative/program.js +5 -0
  249. data/tests/commonjs/modules/relative/submodule/a.js +1 -0
  250. data/tests/commonjs/modules/relative/submodule/b.js +2 -0
  251. data/tests/commonjs/modules/relative/test.js +9 -0
  252. data/tests/commonjs/modules/transitive/a.js +1 -0
  253. data/tests/commonjs/modules/transitive/b.js +1 -0
  254. data/tests/commonjs/modules/transitive/c.js +3 -0
  255. data/tests/commonjs/modules/transitive/program.js +3 -0
  256. data/tests/commonjs/modules/transitive/test.js +9 -0
  257. data/tests/file/all-tests.js +61 -0
  258. data/tests/file/fnmatch.js +102 -0
  259. data/tests/file/glob.js +466 -0
  260. data/tests/file/match.js +102 -0
  261. data/tests/global.js +6 -0
  262. data/tests/global/array.js +19 -0
  263. data/tests/hashes.js +94 -0
  264. data/tests/html.js +13 -0
  265. data/tests/io/stringio.js +21 -0
  266. data/tests/os/all-tests.js +4 -0
  267. data/tests/os/popen.js +41 -0
  268. data/tests/os/system.js +22 -0
  269. data/tests/printf.js +123 -0
  270. data/tests/query-string.js +87 -0
  271. data/tests/sandbox/byte-io.js +20 -0
  272. data/tests/sandbox/fileName.js +3 -0
  273. data/tests/sandbox/foo.js +0 -0
  274. data/tests/sandbox/reload.js +79 -0
  275. data/tests/string.js +35 -0
  276. data/tests/uri.js +41 -0
  277. data/tests/util/all-tests.js +79 -0
  278. data/tests/util/array.js +207 -0
  279. data/tests/util/array/is-arguments.js +29 -0
  280. data/tests/util/array/is-array-like.js +29 -0
  281. data/tests/util/case.js +9 -0
  282. data/tests/util/collection.js +104 -0
  283. data/tests/util/eq.js +57 -0
  284. data/tests/util/expand.js +45 -0
  285. data/tests/util/object.js +125 -0
  286. data/tests/util/operator.js +25 -0
  287. data/tests/util/range.js +19 -0
  288. data/tests/util/repr.js +26 -0
  289. data/tests/util/string.js +34 -0
  290. data/tests/util/unique.js +12 -0
  291. metadata +434 -0
@@ -0,0 +1,32 @@
1
+ * `activejs`: The Cross Platform JavaScript MVC, http://activejs.org/
2
+ * `appengine-java-sdk`: Java components necessary for deploying applications on Google's App Engine.
3
+ * `appengine`: A port of the Python AppEngine API to JavaScript
4
+ * `browserjs`: A simulated web browser environment, includes XMLHttpRequest, timeouts, console, a DOM, etc
5
+ * `chiron`: A system of interoperable JavaScript modules, including a Pythonic type system and types
6
+ * `creolejs`: A JavaScript implementation of the CreoleWiki language, for browsers.
7
+ * `env`:
8
+ * `inspec`:
9
+ * `jack-dav`: A JSGI compatible WebDAV server, based on RackDAV
10
+ * `jack-servlet`: A Java servlet for running JSGI applications
11
+ * `jack`: A library of JSGI middleware, handlers, and utilities, based on Rack
12
+ * `jake`: A build system for ServerJS, inspired by Rake
13
+ * `jsdocs`: Tool for generating template-formatted, multi-page HTML (or XML, JSON, or any other text-based) documentation from commented JavaScript source code.
14
+ * `json-rpc`: An implementation of JSON-RPC for CommonJS, include a JSGI appliance
15
+ * `jsont`: JSON transforms, akin to XSLT but for JSON: http://goessner.net/articles/jsont/
16
+ * `kupo`:
17
+ * `markdown`: A port of markdown to JavaScript
18
+ * `narcissus`: JavaScript implemented in JavaScript
19
+ * `narwhal-jaxer`:
20
+ * `narwhal-johnson`: Johnson (Ruby-JavaScript bridge, using SpiderMonkey) engine support for Narwhal
21
+ * `narwhal-jsc`: JavaScriptCore engine support for Narwhal
22
+ * `narwhal-v8`: V8 engine support for Narwhal
23
+ * `narwhal-xulrunner`:
24
+ * `narwhal`: A general purpose JavaScript platform
25
+ * `nitro`: A Web Application Framework
26
+ * `objj`: Objective-J and Cappuccino tools
27
+ * `seethrough`: Seethrough is a simple XML/XHTML template engine for JavaScript based on E4X. It’s a port of a former project for Erlang.
28
+ * `speller`: A JavaScript spell-checker
29
+ * `syntax-stroop`: A syntax highlighter based on Google-code-prettify.
30
+ * `template`: A simple templating engine
31
+ * `wiky`: A bidirectional Wiki markup to and from HTML converter written in JavaScript.
32
+ * `xbin`: A suite of Unix command line tools for enlightened pipelines.
@@ -0,0 +1,290 @@
1
+
2
+ Deploying Modules to Browsers
3
+ =============================
4
+
5
+ /!\ Warning: most of the techniques described below have not yet been implemented. This document sets forth the design for a variety of solutions.
6
+
7
+ There are a myriad of ways to deploy Narwhal modules to web browsers, although none of them are as familiar as adding the module files with script tags.
8
+
9
+ The ideal loader would work for both development or production, with static files hosted by your media server or CDN or with files served by your web application, both in modules and in subsequent inline script tags with or without a load event handler, with blocking calls to require and non-blocking calls to require, and with high performance always, both on the initial page load and on subsequent page loads mostly from cache, and with the minimal download size.
10
+
11
+ * development or production
12
+ * static or dynamic
13
+ * synchronous or asynchronous
14
+ * bundled, combined, or individual
15
+ * minified or debugable
16
+ * same origin, media server, CDN
17
+
18
+ Since many of these requirements are mutually exclusive, there is not a single loader that will work for every situation. This document is intended to describe the loader you should use for each particular scenario, and to describe how those loaders work.
19
+
20
+
21
+ Usage
22
+ -----
23
+
24
+ If you are using a JSGI server, you can let Narwhal's `narwhal/server` application embed light-weight module loaders in your HTML. Using this application, the syntax for various use cases remains the same across all configurable scenarios.
25
+
26
+ var app = ...
27
+ var server = require("narwhal/server");
28
+ app = server.App(app, options);
29
+ ...
30
+
31
+ Wherever you install this App on your request routing, the app will intercept any requests on the "/javascript" path. Otherwise, the application tracks the `env.SCRIPT_NAME` at that point in the request router so it can construct URL's for the modules. The "/javascript" path is configurable.
32
+
33
+ app = server.App(app, {
34
+ "path": "/.js"
35
+ });
36
+
37
+ The most simple use case embeds a loader that will asynchronously load your main module and its transitive dependencies and then "require" the main module.
38
+
39
+ <script>{env.require('main')}</script>
40
+
41
+ If you want to asynchronously preload a set of modules and their transitive dependencies, you can embed a nonblocking preloader and observe a ready signal in subsequent inline scripts.
42
+
43
+ <script>{env.require.nonblock(['foo', 'bar/baz'])}</script>
44
+ <script>
45
+ require.ready(function () {
46
+ var foo = require("foo");
47
+ var baz = require("bar/baz");
48
+ });
49
+ </script>
50
+
51
+ If you want to syncronously preload a set of modules and their transitive dependencies, you can embed a blocking preloader. Because of technical limitations, this technique is not available in production with modules hosted statically. In other scenarios, this technique is not advisable since the modules are not very cacheable. When used at all, this technique should only be used at the bottom of the HTML `<body>` tag because it prevents most modern browsers from queueing the download of subsequent static resources in the HTML stream.
52
+
53
+ <script>{env.require.block(['foo', 'bar/baz'])}</script>
54
+ <script>
55
+ (function () {
56
+ var foo = require("foo");
57
+ var baz = require("bar/baz");
58
+ })();
59
+ </script>
60
+
61
+ You can use "require.async" and the "promise" module to load modules with calculated identifiers (as opposite to statically analyzable String literal identifiers, like `require("foo")`).
62
+
63
+ var Q = require("promise");
64
+
65
+ exports.plugin = function (name) {
66
+ return require.async("plugins/" + name);
67
+ };
68
+
69
+ Q.when(exports.plugin("widget"), function (widget) {
70
+ });
71
+
72
+
73
+ Development
74
+ -----------
75
+
76
+ For debugging, you want line numbers, file names, and the original source code. Performance is not as much of a concern, but you would like it to resemble the user experience. It would also be optimal if you did not have to perform a build step or restart your web server between writing code and debugging your application.
77
+
78
+ You can configure the server application to run in debug mode when Narwhal is in debug mode, as set with the `-d` or `--debug` command line switches.
79
+
80
+ app = server.App(app, {
81
+ "debug": system.debug
82
+ });
83
+
84
+ You can pass any `Boolean` value to the `App` options to configure it for debug scenarios.
85
+
86
+
87
+ ### Server Component ###
88
+
89
+ If you are using a JSGI server, you can use Narwhal's server application to host the individual modules dynamically. The application also sends updated versions of your modules when they change. For performance, the server induces browser caching by selecting a unique URL and an expiration date in the distant future. The module loader provides a global "require" function.
90
+
91
+ Each individual module will be wrapped by the server in a bit of code that will register the module factory with the loader. This defers execution of the module and adds it to the loader's module factory table. To avoid interfering with line numbers, the server condenses the entire boilerplate onto a single line.
92
+
93
+ require.register({ // no newline
94
+ "bar/baz": // no newline
95
+ function (require, exports, module, system, print) { // no newline
96
+ // module text here
97
+ // */ and newline here to break out of comments
98
+ }
99
+ });
100
+
101
+ In the ideal deployment scenario, you have separated your frontend concerns among behavior (JavaScript), content (raw HTML), and presentation (HTML and CSS). This suggests that each page would have a cacheable module for its programmatic beahvior. The Narwhal server application favors the syntax for this use case, enabling you to embed a small preloader with the necessary data about the main module and its static dependency graph, automatically loading the "main" module when all of its dependencies have arrived.
102
+
103
+ <script>{env.require('main')}</script>
104
+
105
+ If you prefer to embed behavior in your HTML, you can embed a preloader and use the ready signal in subsequent inline scripts. Each of the modules and their transitive dependencies will be registered asynchronously and the `ready` signal will be sent when they have all been registered.
106
+
107
+ <script>{env.require.nonblock(["foo", "bar/baz"])}</script>
108
+ <script>
109
+ require.ready(function () {
110
+ var foo = require("foo");
111
+ var baz = require("bar/baz");
112
+ });
113
+ </script>
114
+
115
+ If you absolutely must have a blocking script tag for your modules, the application optionally can download all of the dependencies in a single file, but the price is performance and that your line numbers and file names will no longer correspond with the source. You are unlikely to benefit from browser caching, and it would be unwise to use a blocking script download anywhere but the bottom of the page.
116
+
117
+ ...
118
+ <script src="{env.require.block('foo', 'bar/baz')">
119
+ </script>
120
+ <script>
121
+ (function () {
122
+ var foo = require("foo");
123
+ var baz = require("bar/baz");
124
+ })();
125
+ </script>
126
+ </body>
127
+
128
+ There is also an option that will allow you to embed the module factories directly in the text of your HTML, that guarantees blocking but prevents caching.
129
+
130
+ ...
131
+ <script>{env.require.embed("foo", "bar/baz")}</script>
132
+ <script>
133
+ (function () {
134
+ var foo = require("foo");
135
+ var baz = require("bar/baz");
136
+ })();
137
+ </script>
138
+ </body>
139
+
140
+
141
+ ### Build Step ###
142
+
143
+ If you can not use a server side component, but you are willing to perform a build step every time you go from writing code to debugging, Narwhal has Tusk commands that will assist deployment.
144
+
145
+ One Tusk command generates a script media directory composed of module factories for the modules of higest precedent for each top level identifier in every package, for the browser engine.
146
+
147
+ $ tusk browser --debug build [<target>]
148
+
149
+ Another Tusk command generates code snippets to include in your HTML to load these modules.
150
+
151
+ $ tusk browser --debug require <id>
152
+ $ tusk browser --debug block [<id> [...]]
153
+ $ tusk browser --debug nonblock [<id> [...]]
154
+ $ tusk browser --debug embed [<id> [...]]
155
+
156
+
157
+ ### Static Files ###
158
+
159
+ If you can not use a server side component and are not willing to perform a build step, but are willing to sacrifice meaningful line numbers and file names in many browsers and to constrain yourself to serving modules from the same host as the origin document, Narwhal provides a loader that can even be used to run modules on the local file system directly from the web browser. You will need to run a Tusk command to construct a directory that contains a symbolic link to every Narwhal module path so the client can search for modules.
160
+
161
+ $ tusk browser build-path
162
+
163
+ This creates "media/js/{n}/" symlinks in numeric order for each of the directories in `require.paths` for a browser deployment. The client has to make a `HEAD` request for the top level identifier of the module in each subdirectory until it finds the module and issues a `GET`. All of these operations are performed with a blocking XML HTTP Request, which is fine for debugging but very low performance, with many round trips, no parallelism or bundling, and the risk of locking up the entire browser user interface in browsers that can't handle a situation where a synchronous HTTP request is made and the server never responds [citation needed].
164
+
165
+ Then loading a main module is a matter of adding a blocking script with the main module as a query string.
166
+
167
+ <script src="/media/js/modules.js?foo"></script>
168
+
169
+
170
+ Production
171
+ ----------
172
+
173
+ In production, all techniques minify modules before sending them to the browser.
174
+
175
+ If you can use a server-side component and you are willing to serve your modules from your origin document server instead of a static media server, the method for hosting those files is similar to hosting those files from the server in developer mode. The key difference is that the server minifies the modules.
176
+
177
+ With this architecture, in the future it will be possible to write a smarter module loader that will balance the cost of downloading modules serially as a bundle or individually in parallel by maintaining knowledge in persistent session storage about which individual modules have been presumably cached by the browser. Initial page loads would be expedited by bundling. The client would wait an interval and begin redownloading individual modules, which would be tracked by the server in persistent session storage. On subsequent pages, the server would decide, based on what it knows is present in the browser cache, whether to send individual modules or a bundle.
178
+
179
+ app = session.App(app);
180
+ app = server.App(app, {
181
+ "sessionNamespace": "require",
182
+ "cacheReloaderDelay": 2000 // miliseconds
183
+ });
184
+
185
+ If you are using a CDN, you can use the same technique as above, serving the JavaScript from origin (where the CDN will look for cache misses) and with CDN URLs (so the client looks for the modules on the CDN). You will need to configure the CDN and the Narwhal server to know about each other. The CDN will need to be configured to look for JavaScript modules on your origin server. The Narwhal application will need to be configured to write CDN URLs instead of origin server URLs.
186
+
187
+ app = server.App(app, {
188
+ "proxy": "http://your.content-delivery.net/work/js"
189
+ });
190
+
191
+ With this architecture, it will be possible in the future to implement a smarter loader that can be configured to proactively invalidate URLs from the proxy's cache by issuing `POST` and `DELETE` HTTP requests to the proxy from the origin server.
192
+
193
+ If you would like to host certain modules from other URL's, like common libraries from a free CDN, you can configure the server application to use alternate URLs to load particular individual module factories or factory combinations or bundles. This will hypothetically improve cacheability of certain modules across sites.
194
+
195
+ app = server.App(app, {
196
+ "catalog": {
197
+ "jquery": "http://example.net/js/jquery-1.6.js"
198
+ }
199
+ });
200
+
201
+
202
+ ### Build Step ###
203
+
204
+ If your solution must be static with no server-side component, as would be needed to serve from a static media server, you will need to use a Tusk build step to overlay the library directories of all packages into a single directory tree.
205
+
206
+ $ tusk browser build [<target>]
207
+
208
+ You will also need to configure the server to look for individual modules in that directory tree, so it can configure the embedded loaders properly.
209
+
210
+ app = server.App(app, {
211
+ "static": "/media/js"
212
+ })
213
+
214
+ If you cannot use the JSGI application to construct module loader embeddings, you can generate loader snippets with Tusk as well. Each of these snippets can be placed in a `<script>` tag in your HTML.
215
+
216
+ $ tusk browser require <id>
217
+ $ tusk browser nonblock [<id> [...]]
218
+ $ tusk browser embed [<id> [...]]
219
+
220
+ You can configure Tusk to use an alternate media path with command line options:
221
+
222
+ $ tusk browser --media/js <alternate-path> ...
223
+
224
+ With a static loader, it is not possible to serve dynamically created bundles, so you cannot use `env.require.block(ids)`. However you can generate bundles with Tusk.
225
+
226
+ $ tusk browser bundle <target> [<id> [...]]
227
+
228
+ The bundle command does not search for static dependencies, on the presumption that you might create combinations of bundles with some common dependencies. You can use Tusk to scan the transitive dependencies of a module in the browser engine:
229
+
230
+ $ tusk browser dependencies <id>
231
+
232
+ The list will begin with the selfsame identifier so you can pass it directly to the bundler with `xargs`.
233
+
234
+ $ tusk browser dependencies <id> |\
235
+ tusk browser bundle media/js/bundle-<id>.js
236
+
237
+ If you have a bundle, you can create a snippet that will block the browser until the entire bundle has been registered, just as you would get from `require.block`.
238
+
239
+ $ tusk browser block [<bundle-id>]
240
+
241
+
242
+ Background
243
+ ----------
244
+
245
+ This design is based on several propositions:
246
+
247
+ * synchronous XHR -> blocks most HTML parsers, delaying subsequent static resource enqueue -> bad for performance -> bad for production
248
+ * synchronous XHR -> breaks browsers when the server fails to respond -> bad for reliability -> bad for production
249
+ * XHR -> same origin limitation -> not feasible for static media server or CDN -> sometimes bad for production
250
+ * asynchronous XHR -> does not block browser parsing -> not bad for production
251
+ * asynchronous XHR -> paired with eval, does not need module factory boilerplate
252
+ * asynchronous XHR -> does not preserve file names -> bad for development
253
+ * script injection -> requires module factory boilerplate -> build step OR module server
254
+ * script injection -> line numbers and file names preserved -> good for development
255
+ * build step -> bad for development
256
+ * module server -> not statically deployable -> only good for production in conjunction with a CDN
257
+ * CDNs and static files are distinct deployment scenarios
258
+ * individual modules -> cacheable -> good for subsequent page loads
259
+ * individual modules -> chatty (round trip between requests) -> bad for initial page loads
260
+ * bundles -> less chatty (fewer round trips) -> faster download -> good for initial page loads
261
+ * bundles -> less cacheable -> not good for subsequent page loads
262
+ * balancing bundles, combos, and individuals -> server side logic and session state required
263
+ * combinations -> more cacheable than bundles AND less cacheable than individual modules
264
+ * embedding -> not cacheable -> bad for production
265
+ * minification -> changes line numbers -> bad for development
266
+ * minification -> decreases download size -> good for production
267
+ * embeded scripts -> not cacheable -> bad for performance -> bad for production
268
+ * blocking script -> bundle OR synchronous XHR
269
+ * static files -> build step -> bad for debug
270
+
271
+ +--------------------+------------------+--------------+
272
+ | Debug / Production | Static / Dynamic | Sync / Async |
273
+ +-------+------------+--------+---------+------+-------+
274
+ | Debug | | Static | | Sync | |
275
+ +-------+------------+--------+---------+------+-------+
276
+ | Debug | | Static | | | Async |
277
+ +-------+------------+--------+---------+------+-------+
278
+ | Debug | | | Dynamic | Sync | |
279
+ +-------+------------+--------+---------+------+-------+
280
+ | Debug | | | Dynamic | | Async |
281
+ +-------+------------+--------+---------+------+-------+
282
+ | | Production | Static | | Sync | | production and synchronous (by way of bundling or sync XHR) are incompatible
283
+ +-------+------------+--------+---------+------+-------+
284
+ | | Production | Static | | | Async | build step
285
+ +-------+------------+--------+---------+------+-------+
286
+ | | Production | | Dynamic | Sync | | production and synchronous (by way of bundling or sync XHR) are incompatible
287
+ +-------+------------+--------+---------+------+-------+
288
+ | | Production | | Dynamic | | Async | module server
289
+ +-------+------------+--------+---------+------+-------+
290
+
@@ -0,0 +1,153 @@
1
+
2
+ Browser Deployment
3
+ ==================
4
+
5
+ To use modules on the client side, one option is to use a
6
+ JSGI application provided with Narwhal.
7
+
8
+ var SERVER = require("narwhal/server");
9
+ var app = ...
10
+ app = SERVER.App(app, options);
11
+ ...
12
+
13
+ Options:
14
+
15
+ * `debug`: causes the loader to favor debug information over
16
+ performance. This disables bundling, minification,
17
+ and caching (maybe).
18
+ * `path`: overrides the path used for server-hosted modules.
19
+ For example, "javascript/" instead of the default, ".js/".
20
+ This is intended to avoid collisions with existing services
21
+ down the routing cascade.
22
+ * `proxy`: Alternate URL to search for scripts.
23
+
24
+ This option has not been implemented yet:
25
+
26
+ * `catalog`: Alternate URLs for individual scripts or
27
+ script bundles.
28
+
29
+ This introduces an API to the "env" for all subsequent
30
+ poritions of the request route. The first form loads a module
31
+ and its transitive dependencies:
32
+
33
+ env.script.require(id)
34
+
35
+ The second form aynchronously loads the given modules and
36
+ their transitive dependencies, but does not invoke any
37
+ of them.
38
+
39
+ env.script.preload([id...])
40
+
41
+ You can also embed a call to require a module and its transitive dependencies
42
+ instead of loading them with asynchronous script injection.
43
+
44
+ env.script.embed("main")
45
+
46
+ If you just need to install the loader and you intend to use the loader
47
+ manually, you can inject it. The `script.loader` function will return a bit of
48
+ JavaScript that will return an expression that evaluates to the `require`
49
+ object in JavaScript. The first time it's called, this will be the full text
50
+ of the loader, but thereafter it will simply be the global `require` variable.
51
+
52
+ env.script.loader()
53
+
54
+ These functions return unescaped JavaScript text
55
+ suitable for inserting in an HTML `<script>` tag. The intent
56
+ is for you to use these functions through whatever template
57
+ formatting system your site uses, as in this speculative
58
+ example:
59
+
60
+ <script>{{env.script.require("main")|javascript}}</script>
61
+
62
+ Or, with a higher level API that could be implemented to look like:
63
+
64
+ {% script.require "main" %}
65
+
66
+ If you intend to use modules in inline scripts, you will need to wait for the
67
+ desired modules to load before you execute your code. The `require.when`
68
+ function executes a block of code when a module is *ready* to be required.
69
+
70
+ <script>
71
+ require.when("main", function () {
72
+ var MAIN = require("main");
73
+ ...
74
+ });
75
+ </script>
76
+
77
+ You can also use promises directly with the `require.async` call, which
78
+ performs an asynchronous require that fulfills the returned promise with the
79
+ required module's exports.
80
+
81
+ <script>
82
+ (function () {
83
+ var Q = require("promise");
84
+ Q.when(require.async("main"), function (MAIN) {
85
+ ...
86
+ });
87
+ })();
88
+ </script>
89
+
90
+ The synchronous `require` call may throw an error if you use it without
91
+ ensuring that the module you want has been loaded.
92
+
93
+ {{env.script.preload(["foo"])|javascript}}
94
+ <script>
95
+ require("bar"); // throws up
96
+ </script>
97
+
98
+ However, you can make asynchronous require calls without preloading the
99
+ corresponding modules. Missing dependencies will be fetched on demand in a
100
+ dynamic, albeit chatty fashion that may not take full advantage of the network
101
+ capacity.
102
+
103
+ {{env.script.loader()|javascript}}
104
+ <script>
105
+ (function () {
106
+ var Q = require("promise");
107
+ Q.when(require.async("bar"), function (MAIN) {
108
+ ...
109
+ });
110
+ })();
111
+ </script>
112
+
113
+
114
+ Fin
115
+ ===
116
+
117
+ Features below this line have not been implemented.
118
+
119
+
120
+ *****
121
+
122
+ If you want to use modules but are not using a JSGI application
123
+ to host them, you will need to use "tusk" to build a module
124
+ root. You will need to do this every time any of your
125
+ modules change.
126
+
127
+ tusk ...
128
+
129
+ To load the modules in the browser, use the require script
130
+ with the name of the desired root module as the anchor.
131
+
132
+ <script src="require.js#main"></script>
133
+
134
+ Or
135
+
136
+ <script src="require.js"></script>
137
+ <script>
138
+ require.load("main");
139
+ require.ready(function () {
140
+ var MAIN = require("main");
141
+ });
142
+ </script>
143
+
144
+ Or use tusk to generate a script that you can include in
145
+ your static HTML.
146
+
147
+ tusk ...
148
+
149
+ Or, if you can't tolerate a build step, and are willing to
150
+ host your package tree from origin, you can use the XHR loader.
151
+
152
+ <script src="require-xhr.js#main"></script>
153
+