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
data/lib/uuid.js ADDED
@@ -0,0 +1,89 @@
1
+ /*
2
+ Based on Math.uuid.js 1.4 by Robert Kieffer
3
+
4
+ ----
5
+ Copyright (c) 2008, Robert Kieffer
6
+ All rights reserved.
7
+
8
+ Redistribution and use in source and binary forms, with or without
9
+ modification, are permitted provided that the following conditions are met:
10
+
11
+ * Redistributions of source code must retain the above copyright notice,
12
+ this list of conditions and the following disclaimer.
13
+ * Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in the
15
+ documentation and/or other materials provided with the distribution.
16
+ * Neither the name of Robert Kieffer nor the names of its contributors
17
+ may be used to endorse or promote products derived from this software
18
+ without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
+ POSSIBILITY OF SUCH DAMAGE.
31
+
32
+ */
33
+
34
+
35
+
36
+ /*
37
+ * Generate a random uuid.
38
+ *
39
+ * USAGE: uuid.uuid(length, radix)
40
+ * length - the desired number of characters
41
+ * radix - the number of allowable values for each character.
42
+ *
43
+ * EXAMPLES:
44
+ * // No arguments - returns RFC4122, version 4 ID
45
+ * >>> Math.uuid()
46
+ * "92329D39-6F5C-4520-ABFC-AAB64544E172"
47
+ *
48
+ * // One argument - returns ID of the specified length
49
+ * >>> Math.uuid(15) // 15 character ID (default base=62)
50
+ * "VcydxgltxrVZSTV"
51
+ *
52
+ * // Two arguments - returns ID of the specified length, and radix. (Radix must be <= 62)
53
+ * >>> Math.uuid(8, 2) // 8 character ID (base=2)
54
+ * "01001010"
55
+ * >>> Math.uuid(8, 10) // 8 character ID (base=10)
56
+ * "47473046"
57
+ * >>> Math.uuid(8, 16) // 8 character ID (base=16)
58
+ * "098F4D35"
59
+ */
60
+
61
+
62
+ var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
63
+ exports.uuid = function (len, radix) {
64
+ var chars = CHARS, uuid = [], rnd = Math.random;
65
+ radix = radix || chars.length;
66
+
67
+ if (len) {
68
+ // Compact form
69
+ for (var i = 0; i < len; i++) uuid[i] = chars[0 | rnd()*radix];
70
+ } else {
71
+ // rfc4122, version 4 form
72
+ var r;
73
+
74
+ // rfc4122 requires these characters
75
+ uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
76
+ uuid[14] = '4';
77
+
78
+ // Fill in random data. At i==19 set the high bits of clock sequence as
79
+ // per rfc4122, sec. 4.1.5
80
+ for (var i = 0; i < 36; i++) {
81
+ if (!uuid[i]) {
82
+ r = 0 | rnd()*16;
83
+ uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r & 0xf];
84
+ }
85
+ }
86
+ }
87
+
88
+ return uuid.join('');
89
+ };
data/lib/xregexp.js ADDED
@@ -0,0 +1,521 @@
1
+ // RegExp
2
+
3
+ /** provides an augmented, cross-browser implementation of regular expressions
4
+ including support for additional modifiers and syntax. several convenience
5
+ methods and a recursive-construct parser are also included.
6
+ */
7
+
8
+ /*preamble-steven-levithan
9
+ XRegExp 0.6.1
10
+ Copyright (c) 2007-2008 Steven Levithan <http://stevenlevithan.com>
11
+ MIT license
12
+ Based on XRegExp 0.5.1
13
+ */
14
+ /*preamble-kris-kowal
15
+ Copyright (c) 2002-2008 Kris Kowal <http://cixar.com/~kris.kowal>
16
+ MIT License
17
+ Migrated to module system
18
+ */
19
+
20
+ /** provides an augmented, cross-browser implementation of regular expressions
21
+ including support for additional modifiers and syntax. several convenience
22
+ methods and a recursive-construct parser are also included.
23
+ */
24
+
25
+ // copy various native globals for reference. can't use the name ``native``
26
+ // because it's a reserved JavaScript keyword.
27
+ var real = {
28
+ exec: RegExp.prototype.exec,
29
+ match: String.prototype.match,
30
+ replace: String.prototype.replace,
31
+ split: String.prototype.split
32
+ },
33
+ /* regex syntax parsing with support for all the necessary cross-
34
+ browser and context issues (escapings, character classes, etc.) */
35
+ lib = {
36
+ part: /(?:[^\\([#\s.]+|\\(?!k<[\w$]+>|[pP]{[^}]+})[\S\s]?|\((?=\?(?!#|<[\w$]+>)))+|(\()(?:\?(?:(#)[^)]*\)|<([$\w]+)>))?|\\(?:k<([\w$]+)>|[pP]{([^}]+)})|(\[\^?)|([\S\s])/g,
37
+ replaceVar: /(?:[^$]+|\$(?![1-9$&`']|{[$\w]+}))+|\$(?:([1-9]\d*|[$&`'])|{([$\w]+)})/g,
38
+ extended: /^(?:\s+|#.*)+/,
39
+ quantifier: /^(?:[?*+]|{\d+(?:,\d*)?})/,
40
+ classLeft: /&&\[\^?/g,
41
+ classRight: /]/g
42
+ },
43
+ indexOf = function (array, item, from) {
44
+ for (var i = from || 0; i < array.length; i++)
45
+ if (array[i] === item) return i;
46
+ return -1;
47
+ },
48
+ brokenExecUndef = /()??/.exec("")[1] !== undefined,
49
+ plugins = {};
50
+
51
+ /*** XRegExp
52
+ accepts a pattern and flags, returns a new, extended RegExp object.
53
+ differs from a native regex in that additional flags and syntax are
54
+ supported and browser inconsistencies are ameliorated.
55
+ */
56
+ XRegExp = function (pattern, flags) {
57
+ if (pattern instanceof RegExp) {
58
+ if (flags !== undefined)
59
+ throw TypeError("can't supply flags when constructing one RegExp from another");
60
+ return pattern.addFlags(); // new copy
61
+ }
62
+
63
+ var flags = flags || "",
64
+ singleline = flags.indexOf("s") > -1,
65
+ extended = flags.indexOf("x") > -1,
66
+ hasNamedCapture = false,
67
+ captureNames = [],
68
+ output = [],
69
+ part = lib.part,
70
+ match, cc, len, index, regex;
71
+
72
+ part.lastIndex = 0; // in case the last XRegExp compilation threw an error (unbalanced character class)
73
+
74
+ while (match = real.exec.call(part, pattern)) {
75
+ // comment pattern. this check must come before the capturing group check,
76
+ // because both match[1] and match[2] will be non-empty.
77
+ if (match[2]) {
78
+ // keep tokens separated unless the following token is a quantifier
79
+ if (!lib.quantifier.test(pattern.slice(part.lastIndex)))
80
+ output.push("(?:)");
81
+ // capturing group
82
+ } else if (match[1]) {
83
+ captureNames.push(match[3] || null);
84
+ if (match[3])
85
+ hasNamedCapture = true;
86
+ output.push("(");
87
+ // named backreference
88
+ } else if (match[4]) {
89
+ index = indexOf(captureNames, match[4]);
90
+ // keep backreferences separate from subsequent literal numbers
91
+ // preserve backreferences to named groups that are undefined at this point as literal strings
92
+ output.push(index > -1 ?
93
+ "\\" + (index + 1) + (isNaN(pattern.charAt(part.lastIndex)) ? "" : "(?:)") :
94
+ match[0]
95
+ );
96
+ // unicode element (requires plugin)
97
+ } else if (match[5]) {
98
+ output.push(plugins.unicode ?
99
+ plugins.unicode.get(match[5], match[0].charAt(1) === "P") :
100
+ match[0]
101
+ );
102
+ // character class opening delimiter ("[" or "[^")
103
+ // (non-native unicode elements are not supported within character classes)
104
+ } else if (match[6]) {
105
+ if (pattern.charAt(part.lastIndex) === "]") {
106
+ // for cross-browser compatibility with ECMA-262 v3 behavior,
107
+ // convert [] to (?!) and [^] to [\S\s].
108
+ output.push(match[6] === "[" ? "(?!)" : "[\\S\\s]");
109
+ part.lastIndex++;
110
+ } else {
111
+ // parse the character class with support for inner escapes and
112
+ // ES4's infinitely nesting intersection syntax ([&&[^&&[]]]).
113
+ cc = XRegExp.matchRecursive("&&" + pattern.slice(match.index), lib.classLeft, lib.classRight, "", {escapeChar: "\\"})[0];
114
+ output.push(match[6] + cc + "]");
115
+ part.lastIndex += cc.length + 1;
116
+ }
117
+ // dot ("."), pound sign ("#"), or whitespace character
118
+ } else if (match[7]) {
119
+ if (singleline && match[7] === ".") {
120
+ output.push("[\\S\\s]");
121
+ } else if (extended && lib.extended.test(match[7])) {
122
+ len = real.exec.call(lib.extended, pattern.slice(part.lastIndex - 1))[0].length;
123
+ // keep tokens separated unless the following token is a quantifier
124
+ if (!lib.quantifier.test(pattern.slice(part.lastIndex - 1 + len)))
125
+ output.push("(?:)");
126
+ part.lastIndex += len - 1;
127
+ } else {
128
+ output.push(match[7]);
129
+ }
130
+ } else {
131
+ output.push(match[0]);
132
+ }
133
+ }
134
+
135
+ regex = RegExp(output.join(""), real.replace.call(flags, /[sx]+/g, ""));
136
+ regex._x = {
137
+ source: pattern,
138
+ captureNames: hasNamedCapture ? captureNames : null
139
+ };
140
+ return regex;
141
+ };
142
+
143
+ // barebones plugin support for now (intentionally undocumented)
144
+ XRegExp.addPlugin = function (name, o) {
145
+ plugins[name] = o;
146
+ };
147
+
148
+ /*** RegExp.prototype.exec
149
+ adds named capture support, with values returned as ``result.name``.
150
+ also fixes two cross-browser issues, following the ECMA-262 v3 spec:
151
+ - captured values for non-participating capturing groups should be returned
152
+ as ``undefined``, rather than the empty string.
153
+ - the regex's ``lastIndex`` should not be incremented after zero-length
154
+ matches.
155
+ */
156
+ RegExp.prototype.exec = function (str) {
157
+ var match = real.exec.call(this, str),
158
+ name, i, r2;
159
+ if (match) {
160
+ // fix browsers whose exec methods don't consistently return
161
+ // undefined for non-participating capturing groups
162
+ if (brokenExecUndef && match.length > 1) {
163
+ // r2 doesn't need /g or /y, but they shouldn't hurt
164
+ r2 = new RegExp("^" + this.source + "$(?!\\s)", this.getNativeFlags());
165
+ real.replace.call(match[0], r2, function () {
166
+ for (i = 1; i < arguments.length - 2; i++) {
167
+ if (arguments[i] === undefined) match[i] = undefined;
168
+ }
169
+ });
170
+ }
171
+ // attach named capture properties
172
+ if (this._x && this._x.captureNames) {
173
+ for (i = 1; i < match.length; i++) {
174
+ name = this._x.captureNames[i - 1];
175
+ if (name) match[name] = match[i];
176
+ }
177
+ }
178
+ // fix browsers that increment lastIndex after zero-length matches
179
+ if (this.global && this.lastIndex > (match.index + match[0].length))
180
+ this.lastIndex--;
181
+ }
182
+ return match;
183
+ };
184
+
185
+ /*** String.prototype.match
186
+ run the altered ``exec`` when called with a non-global regex.
187
+ */
188
+ String.prototype.match = function (regex) {
189
+ if (!(regex instanceof RegExp))
190
+ regex = new XRegExp(regex);
191
+ if (regex.global)
192
+ return real.match.call(this, regex);
193
+ return regex.exec(this); // run the altered exec
194
+ };
195
+
196
+ /*** String.prototype.replace
197
+ add named capture support to replacement strings using the syntax
198
+ ``${name}``, and to replacement functions as ``arguments[0].name``.
199
+ */
200
+ String.prototype.replace = function (search, replacement) {
201
+ var captureNames = (search._x || {}).captureNames;
202
+
203
+ // if search is not a regex which uses named capture, use the native replace method
204
+ if (!(search instanceof RegExp && captureNames))
205
+ return real.replace.apply(this, arguments);
206
+
207
+ if (typeof replacement === "function") {
208
+ return real.replace.call(this, search, function () {
209
+ // change the arguments[0] string primitive to a String object which can store properties
210
+ arguments[0] = new String(arguments[0]);
211
+ // store named backreferences on arguments[0] before calling replacement
212
+ for (var i = 0; i < captureNames.length; i++) {
213
+ if (captureNames[i])
214
+ arguments[0][captureNames[i]] = arguments[i + 1];
215
+ }
216
+ return replacement.apply(window, arguments);
217
+ });
218
+ } else {
219
+ return real.replace.call(this, search, function () {
220
+ var args = arguments;
221
+ return real.replace.call(replacement, lib.replaceVar, function ($0, $1, $2) {
222
+ // numbered backreference or special variable
223
+ if ($1) {
224
+ switch ($1) {
225
+ case "$": return "$";
226
+ case "&": return args[0];
227
+ case "`": return args[args.length - 1].slice(0, args[args.length - 2]);
228
+ case "'": return args[args.length - 1].slice(args[args.length - 2] + args[0].length);
229
+ // numbered backreference
230
+ default:
231
+ /* what does "$10" mean?
232
+ - backreference 10, if 10 or more capturing groups exist
233
+ - backreference 1 followed by "0", if 1-9 capturing groups exist
234
+ - otherwise, it's the string "$10"
235
+ */
236
+ var literalNumbers = "";
237
+ $1 = +$1; // type-convert
238
+ while ($1 > captureNames.length) {
239
+ literalNumbers = real.split.call($1, "").pop() + literalNumbers;
240
+ $1 = Math.floor($1 / 10); // drop the last digit
241
+ }
242
+ return ($1 ? args[$1] : "$") + literalNumbers;
243
+ }
244
+ // named backreference
245
+ } else if ($2) {
246
+ /* what does "${name}" mean?
247
+ - backreference to named capture "name", if it exists
248
+ - otherwise, it's the string "${name}"
249
+ */
250
+ var index = indexOf(captureNames, $2);
251
+ return index > -1 ? args[index + 1] : $0;
252
+ } else {
253
+ return $0;
254
+ }
255
+ });
256
+ });
257
+ }
258
+ };
259
+
260
+ /*** String.prototype.split
261
+ a consistent cross-browser, ECMA-262 v3 compliant split method
262
+ */
263
+ String.prototype.split = function (s /* separator */, limit) {
264
+ // if separator is not a regex, use the native split method
265
+ if (!(s instanceof RegExp))
266
+ return real.split.apply(this, arguments);
267
+
268
+ var output = [],
269
+ origLastIndex = s.lastIndex,
270
+ lastLastIndex = 0,
271
+ i = 0, match, lastLength;
272
+
273
+ /* behavior for limit: if it's...
274
+ - undefined: no limit
275
+ - NaN or zero: return an empty array
276
+ - a positive number: use limit after dropping any decimal
277
+ - a negative number: no limit
278
+ - other: type-convert, then use the above rules
279
+ */
280
+ if (limit === undefined || +limit < 0) {
281
+ limit = false;
282
+ } else {
283
+ limit = Math.floor(+limit);
284
+ if (!limit)
285
+ return [];
286
+ }
287
+
288
+ if (s.global)
289
+ s.lastIndex = 0;
290
+ else
291
+ s = s.addFlags("g");
292
+
293
+ while ((!limit || i++ <= limit) && (match = s.exec(this))) { // run the altered exec!
294
+ if (s.lastIndex > lastLastIndex) {
295
+ output = output.concat(this.slice(lastLastIndex, match.index));
296
+ if (1 < match.length && match.index < this.length)
297
+ output = output.concat(match.slice(1));
298
+ lastLength = match[0].length; // only needed if s.lastIndex === this.length
299
+ lastLastIndex = s.lastIndex;
300
+ }
301
+ if (!match[0].length)
302
+ s.lastIndex++; // avoid an infinite loop
303
+ }
304
+
305
+ // since this uses test(), output must be generated before restoring lastIndex
306
+ output = lastLastIndex === this.length ?
307
+ (s.test("") && !lastLength ? output : output.concat("")) :
308
+ (limit ? output : output.concat(this.slice(lastLastIndex)));
309
+ s.lastIndex = origLastIndex; // only needed if s.global, else we're working with a copy of the regex
310
+ return output;
311
+ };
312
+
313
+ // intentionally undocumented
314
+ RegExp.prototype.getNativeFlags = function () {
315
+ return (this.global ? "g" : "") +
316
+ (this.ignoreCase ? "i" : "") +
317
+ (this.multiline ? "m" : "") +
318
+ (this.extended ? "x" : "") +
319
+ (this.sticky ? "y" : "");
320
+ };
321
+
322
+ /*** RegExp.prototype.addFlags
323
+ accepts flags; returns a new XRegExp object generated by recompiling
324
+ the regex with the additional flags (may include non-native flags).
325
+ the original regex object is not altered.
326
+ */
327
+ RegExp.prototype.addFlags = function (flags) {
328
+ var regex = new XRegExp(this.source, (flags || "") + this.getNativeFlags());
329
+ if (this._x) {
330
+ regex._x = {
331
+ source: this._x.source,
332
+ captureNames: this._x.captureNames ? this._x.captureNames.slice(0) : null
333
+ };
334
+ }
335
+ return regex;
336
+ };
337
+
338
+ /*** RegExp.prototype.call
339
+ accepts a context object and string; returns the result of calling
340
+ ``exec`` with the provided string. the context is ignored but is
341
+ accepted for congruity with ``Function.prototype.call``.
342
+ */
343
+ RegExp.prototype.call = function (context, str) {
344
+ return this.exec(str);
345
+ };
346
+
347
+ /*** RegExp.prototype.apply
348
+ accepts a context object and arguments array; returns the result of
349
+ calling ``exec`` with the first value in the arguments array. the context
350
+ is ignored but is accepted for congruity with ``Function.prototype.apply``.
351
+ */
352
+ RegExp.prototype.apply = function (context, args) {
353
+ return this.exec(args[0]);
354
+ };
355
+
356
+ /*** XRegExp.cache
357
+ accepts a pattern and flags; returns an XRegExp object. if the pattern
358
+ and flag combination has previously been cached, the cached copy is
359
+ returned, otherwise the new object is cached.
360
+ */
361
+ XRegExp.cache = function (pattern, flags) {
362
+ var key = "/" + pattern + "/" + (flags || "");
363
+ return XRegExp.cache[key] || (XRegExp.cache[key] = new XRegExp(pattern, flags));
364
+ };
365
+
366
+ /*** XRegExp.escape
367
+ accepts a string; returns the string with regex metacharacters escaped.
368
+ the returned string can safely be used within a regex to match a literal
369
+ string. escaped characters are [, ], {, }, (, ), -, *, +, ?, ., \, ^, $,
370
+ |, #, [comma], and whitespace.
371
+ */
372
+ XRegExp.escape = function (str) {
373
+ return str.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, "\\$&");
374
+ };
375
+
376
+ /*** XRegExp.matchRecursive
377
+ accepts a string to search, left and right delimiters as regex pattern
378
+ strings, optional regex flags (may include non-native s, x, and y flags),
379
+ and an options object which allows setting an escape character and changing
380
+ the return format from an array of matches to a two-dimensional array of
381
+ string parts with extended position data. returns an array of matches
382
+ (optionally with extended data), allowing nested instances of left and right
383
+ delimiters. use the g flag to return all matches, otherwise only the first
384
+ is returned. if delimiters are unbalanced within the subject data, an error
385
+ is thrown.
386
+
387
+ this function admittedly pushes the boundaries of what can be accomplished
388
+ sensibly without a "real" parser. however, by doing so it provides flexible
389
+ and powerful recursive parsing capabilities with minimal code weight.
390
+
391
+ warning: the ``escapeChar`` option is considered experimental and might be
392
+ changed or removed in future versions of XRegExp.
393
+
394
+ unsupported features:
395
+ - backreferences within delimiter patterns when using ``escapeChar``.
396
+ - although providing delimiters as regex objects adds the minor feature of
397
+ independent delimiter flags, it introduces other limitations and is only
398
+ intended to be done by the ``XRegExp`` constructor (which can't call
399
+ itself while building a regex).
400
+ */
401
+ XRegExp.matchRecursive = function (str, left, right, flags, options) {
402
+ var options = options || {},
403
+ escapeChar = options.escapeChar,
404
+ vN = options.valueNames,
405
+ flags = flags || "",
406
+ global = flags.indexOf("g") > -1,
407
+ ignoreCase = flags.indexOf("i") > -1,
408
+ multiline = flags.indexOf("m") > -1,
409
+ sticky = flags.indexOf("y") > -1,
410
+ /* sticky mode has its own handling in this function, which means you
411
+ can use flag "y" even in browsers which don't support it natively */
412
+ flags = flags.replace(/y/g, ""),
413
+ left = left instanceof RegExp ? (left.global ? left : left.addFlags("g")) : new XRegExp(left, "g" + flags),
414
+ right = right instanceof RegExp ? (right.global ? right : right.addFlags("g")) : new XRegExp(right, "g" + flags),
415
+ output = [],
416
+ openTokens = 0,
417
+ delimStart = 0,
418
+ delimEnd = 0,
419
+ lastOuterEnd = 0,
420
+ outerStart, innerStart, leftMatch, rightMatch, escaped, esc;
421
+
422
+ if (escapeChar) {
423
+ if (escapeChar.length > 1) throw SyntaxError("can't supply more than one escape character");
424
+ if (multiline) throw TypeError("can't supply escape character when using the multiline flag");
425
+ escaped = XRegExp.escape(escapeChar);
426
+ /* Escape pattern modifiers:
427
+ /g - not needed here
428
+ /i - included
429
+ /m - **unsupported**, throws error
430
+ /s - handled by XRegExp when delimiters are provided as strings
431
+ /x - handled by XRegExp when delimiters are provided as strings
432
+ /y - not needed here; supported by other handling in this function
433
+ */
434
+ esc = new RegExp(
435
+ "^(?:" + escaped + "[\\S\\s]|(?:(?!" + left.source + "|" + right.source + ")[^" + escaped + "])+)+",
436
+ ignoreCase ? "i" : ""
437
+ );
438
+ }
439
+
440
+ while (true) {
441
+ /* advance the starting search position to the end of the last delimiter match.
442
+ a couple special cases are also covered:
443
+ - if using an escape character, advance to the next delimiter's starting position,
444
+ skipping any escaped characters
445
+ - first time through, reset lastIndex in case delimiters were provided as regexes
446
+ */
447
+ left.lastIndex = right.lastIndex = delimEnd +
448
+ (escapeChar ? (esc.exec(str.slice(delimEnd)) || [""])[0].length : 0);
449
+
450
+ leftMatch = left.exec(str);
451
+ rightMatch = right.exec(str);
452
+
453
+ // only keep the result which matched earlier in the string
454
+ if (leftMatch && rightMatch) {
455
+ if (leftMatch.index <= rightMatch.index)
456
+ rightMatch = null;
457
+ else leftMatch = null;
458
+ }
459
+
460
+ /* paths*:
461
+ leftMatch | rightMatch | openTokens | result
462
+ 1 | 0 | 1 | ...
463
+ 1 | 0 | 0 | ...
464
+ 0 | 1 | 1 | ...
465
+ 0 | 1 | 0 | throw
466
+ 0 | 0 | 1 | throw
467
+ 0 | 0 | 0 | break
468
+ * - does not include the sticky mode special case
469
+ - the loop ends after the first completed match if not in global mode
470
+ */
471
+
472
+ if (leftMatch || rightMatch) {
473
+ delimStart = (leftMatch || rightMatch).index;
474
+ delimEnd = (leftMatch ? left : right).lastIndex;
475
+ } else if (!openTokens) {
476
+ break;
477
+ }
478
+
479
+ if (sticky && !openTokens && delimStart > lastOuterEnd)
480
+ break;
481
+
482
+ if (leftMatch) {
483
+ if (!openTokens++) {
484
+ outerStart = delimStart;
485
+ innerStart = delimEnd;
486
+ }
487
+ } else if (rightMatch && openTokens) {
488
+ if (!--openTokens) {
489
+ if (vN) {
490
+ if (vN[0] && outerStart > lastOuterEnd)
491
+ output.push([vN[0], str.slice(lastOuterEnd, outerStart), lastOuterEnd, outerStart]);
492
+ if (vN[1]) output.push([vN[1], str.slice(outerStart, innerStart), outerStart, innerStart]);
493
+ if (vN[2]) output.push([vN[2], str.slice(innerStart, delimStart), innerStart, delimStart]);
494
+ if (vN[3]) output.push([vN[3], str.slice(delimStart, delimEnd), delimStart, delimEnd]);
495
+ } else {
496
+ output.push(str.slice(innerStart, delimStart));
497
+ }
498
+ lastOuterEnd = delimEnd;
499
+ if (!global)
500
+ break;
501
+ }
502
+ } else {
503
+ // reset lastIndex in case delimiters were provided as regexes
504
+ left.lastIndex = right.lastIndex = 0;
505
+ throw Error("subject data contains unbalanced delimiters");
506
+ }
507
+
508
+ // if the delimiter matched an empty string, advance delimEnd to avoid an infinite loop
509
+ if (delimStart === delimEnd)
510
+ delimEnd++;
511
+ }
512
+
513
+ if (global && !sticky && vN && vN[0] && str.length > lastOuterEnd)
514
+ output.push([vN[0], str.slice(lastOuterEnd), lastOuterEnd, str.length]);
515
+
516
+ // reset lastIndex in case delimiters were provided as regexes
517
+ left.lastIndex = right.lastIndex = 0;
518
+
519
+ return output;
520
+ };
521
+