webruby 0.1.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (518) hide show
  1. checksums.yaml +4 -4
  2. data/driver/driver.c +12 -0
  3. data/lib/webruby/config.rb +3 -3
  4. data/lib/webruby/environment.rb +1 -0
  5. data/lib/webruby/rake/files.rake +22 -22
  6. data/lib/webruby/rake/general.rake +0 -1
  7. data/lib/webruby/utility.rb +2 -0
  8. data/modules/emscripten/AUTHORS +12 -1
  9. data/modules/emscripten/cmake/Platform/Emscripten.cmake +152 -15
  10. data/modules/emscripten/em++ +2 -0
  11. data/modules/emscripten/em++.bat +1 -1
  12. data/modules/emscripten/em-config.bat +1 -1
  13. data/modules/emscripten/emar.bat +1 -1
  14. data/modules/emscripten/emcc +233 -95
  15. data/modules/emscripten/emcc.bat +1 -1
  16. data/modules/emscripten/emconfigure.bat +1 -1
  17. data/modules/emscripten/emmake.bat +1 -1
  18. data/modules/emscripten/emranlib.bat +1 -1
  19. data/modules/emscripten/emscripten.py +221 -217
  20. data/modules/emscripten/package.json +7 -0
  21. data/modules/emscripten/src/analyzer.js +1437 -1385
  22. data/modules/emscripten/src/compiler.js +30 -6
  23. data/modules/emscripten/src/compiler_phase.html +33 -0
  24. data/modules/emscripten/src/fastLong.js +6 -6
  25. data/modules/emscripten/src/headless.js +47 -656
  26. data/modules/emscripten/src/headlessCanvas.js +618 -0
  27. data/modules/emscripten/src/intertyper.js +1038 -899
  28. data/modules/emscripten/src/jsifier.js +818 -714
  29. data/modules/emscripten/src/library.js +1794 -2968
  30. data/modules/emscripten/src/library_browser.js +81 -16
  31. data/modules/emscripten/src/library_egl.js +9 -3
  32. data/modules/emscripten/src/library_fs.js +1585 -0
  33. data/modules/emscripten/src/library_gl.js +445 -202
  34. data/modules/emscripten/src/library_glfw.js +4 -1
  35. data/modules/emscripten/src/library_glut.js +61 -13
  36. data/modules/emscripten/src/library_idbfs.js +216 -0
  37. data/modules/emscripten/src/library_memfs.js +279 -0
  38. data/modules/emscripten/src/library_nodefs.js +234 -0
  39. data/modules/emscripten/src/library_openal.js +131 -150
  40. data/modules/emscripten/src/library_path.js +3 -0
  41. data/modules/emscripten/src/library_sdl.js +499 -229
  42. data/modules/emscripten/src/library_sockfs.js +576 -0
  43. data/modules/emscripten/src/library_tty.js +146 -0
  44. data/modules/emscripten/src/modules.js +30 -35
  45. data/modules/emscripten/src/parseTools.js +356 -161
  46. data/modules/emscripten/src/postamble.js +76 -31
  47. data/modules/emscripten/src/preamble.js +271 -41
  48. data/modules/emscripten/src/proxyClient.js +82 -0
  49. data/modules/emscripten/src/proxyWorker.js +143 -0
  50. data/modules/emscripten/src/relooper/Relooper.cpp +60 -24
  51. data/modules/emscripten/src/relooper/Relooper.h +3 -2
  52. data/modules/emscripten/src/relooper/emscripten/glue.js +20 -10
  53. data/modules/emscripten/src/relooper/fuzzer.py +19 -10
  54. data/modules/emscripten/src/relooper/test.cpp +50 -50
  55. data/modules/emscripten/src/relooper/test.txt +147 -30
  56. data/modules/emscripten/src/relooper/test2.c +13 -13
  57. data/modules/emscripten/src/relooper/test2.txt +17 -3
  58. data/modules/emscripten/src/relooper/test3.c +7 -7
  59. data/modules/emscripten/src/relooper/test3.txt +36 -7
  60. data/modules/emscripten/src/relooper/test4.cpp +7 -7
  61. data/modules/emscripten/src/relooper/test4.txt +28 -7
  62. data/modules/emscripten/src/relooper/test5.cpp +6 -6
  63. data/modules/emscripten/src/relooper/test5.txt +34 -10
  64. data/modules/emscripten/src/relooper/test6.cpp +4 -4
  65. data/modules/emscripten/src/relooper/test6.txt +17 -3
  66. data/modules/emscripten/src/relooper/test_dead.cpp +2 -2
  67. data/modules/emscripten/src/relooper/test_debug.cpp +4 -4
  68. data/modules/emscripten/src/relooper/test_debug.txt +17 -3
  69. data/modules/emscripten/src/relooper/test_fuzz1.cpp +9 -9
  70. data/modules/emscripten/src/relooper/test_fuzz1.txt +45 -5
  71. data/modules/emscripten/src/relooper/test_fuzz2.cpp +4 -4
  72. data/modules/emscripten/src/relooper/test_fuzz2.txt +18 -1
  73. data/modules/emscripten/src/relooper/test_fuzz3.cpp +5 -5
  74. data/modules/emscripten/src/relooper/test_fuzz3.txt +16 -0
  75. data/modules/emscripten/src/relooper/test_fuzz4.cpp +5 -5
  76. data/modules/emscripten/src/relooper/test_fuzz4.txt +25 -3
  77. data/modules/emscripten/src/relooper/test_fuzz5.cpp +10 -10
  78. data/modules/emscripten/src/relooper/test_fuzz5.txt +49 -15
  79. data/modules/emscripten/src/relooper/test_fuzz6.cpp +92 -92
  80. data/modules/emscripten/src/relooper/test_fuzz6.txt +201 -18
  81. data/modules/emscripten/src/relooper/test_inf.cpp +184 -184
  82. data/modules/emscripten/src/relooper/test_inf.txt +1078 -332
  83. data/modules/emscripten/src/runtime.js +69 -45
  84. data/modules/emscripten/src/settings.js +48 -919
  85. data/modules/emscripten/src/shell.html +1 -1
  86. data/modules/emscripten/src/shell.js +14 -8
  87. data/modules/emscripten/src/shell_sharedlib.js +18 -1
  88. data/modules/emscripten/src/simd.js +958 -0
  89. data/modules/emscripten/src/struct_info.json +1045 -0
  90. data/modules/emscripten/src/utility.js +11 -0
  91. data/modules/emscripten/system/bin/sdl-config +13 -0
  92. data/modules/emscripten/system/include/compat/ctype.h +17 -0
  93. data/modules/emscripten/system/include/compat/malloc.h +48 -0
  94. data/modules/emscripten/system/include/compat/math.h +14 -0
  95. data/modules/emscripten/system/include/compat/netdb.h +22 -0
  96. data/modules/emscripten/system/include/compat/stdarg.h +16 -0
  97. data/modules/emscripten/system/include/compat/stdlib.h +16 -0
  98. data/modules/emscripten/system/include/compat/string.h +17 -0
  99. data/modules/emscripten/system/include/compat/sys/socketvar.h +14 -0
  100. data/modules/emscripten/system/include/compat/sys/stat.h +20 -0
  101. data/modules/emscripten/system/include/{libc → compat}/sys/timeb.h +3 -7
  102. data/modules/emscripten/system/include/compat/time.h +18 -0
  103. data/modules/emscripten/system/include/compat/unistd.h +16 -0
  104. data/modules/emscripten/system/include/compat/xlocale.h +19 -0
  105. data/modules/emscripten/system/include/emscripten/emscripten.h +48 -7
  106. data/modules/emscripten/system/include/emscripten/vector.h +6 -0
  107. data/modules/emscripten/system/include/libc/aio.h +69 -0
  108. data/modules/emscripten/system/include/libc/alloca.h +13 -13
  109. data/modules/emscripten/system/include/libc/ar.h +19 -63
  110. data/modules/emscripten/system/include/libc/arpa/ftp.h +35 -0
  111. data/modules/emscripten/system/include/libc/arpa/inet.h +36 -0
  112. data/modules/emscripten/system/include/libc/arpa/nameser.h +467 -0
  113. data/modules/emscripten/system/include/libc/arpa/nameser_compat.h +2 -0
  114. data/modules/emscripten/system/include/libc/arpa/telnet.h +251 -0
  115. data/modules/emscripten/system/include/libc/arpa/tftp.h +31 -0
  116. data/modules/emscripten/system/include/libc/assert.h +9 -36
  117. data/modules/emscripten/system/include/libc/bits/alltypes.h +397 -0
  118. data/modules/emscripten/system/include/libc/bits/endian.h +1 -0
  119. data/modules/emscripten/system/include/libc/bits/errno.h +134 -0
  120. data/modules/emscripten/system/include/libc/bits/fcntl.h +38 -0
  121. data/modules/emscripten/system/include/libc/bits/fenv.h +34 -0
  122. data/modules/emscripten/system/include/libc/bits/float.h +17 -0
  123. data/modules/emscripten/system/include/libc/bits/io.h +0 -0
  124. data/modules/emscripten/system/include/libc/bits/ioctl.h +197 -0
  125. data/modules/emscripten/system/include/libc/bits/ipc.h +14 -0
  126. data/modules/emscripten/system/include/libc/bits/limits.h +8 -0
  127. data/modules/emscripten/system/include/libc/bits/mman.h +62 -0
  128. data/modules/emscripten/system/include/libc/bits/msg.h +16 -0
  129. data/modules/emscripten/system/include/libc/bits/posix.h +2 -0
  130. data/modules/emscripten/system/include/libc/bits/reg.h +19 -0
  131. data/modules/emscripten/system/include/libc/bits/setjmp.h +1 -0
  132. data/modules/emscripten/system/include/libc/bits/shm.h +18 -0
  133. data/modules/emscripten/system/include/libc/bits/signal.h +112 -0
  134. data/modules/emscripten/system/include/libc/bits/socket.h +17 -0
  135. data/modules/emscripten/system/include/libc/bits/stat.h +22 -0
  136. data/modules/emscripten/system/include/libc/bits/statfs.h +7 -0
  137. data/modules/emscripten/system/include/libc/bits/stdarg.h +4 -0
  138. data/modules/emscripten/system/include/libc/bits/stdint.h +20 -0
  139. data/modules/emscripten/system/include/libc/bits/syscall.h +696 -0
  140. data/modules/emscripten/system/include/libc/bits/termios.h +160 -0
  141. data/modules/emscripten/system/include/libc/bits/user.h +48 -0
  142. data/modules/emscripten/system/include/libc/byteswap.h +26 -0
  143. data/modules/emscripten/system/include/libc/complex.h +55 -54
  144. data/modules/emscripten/system/include/libc/cpio.h +29 -0
  145. data/modules/emscripten/system/include/libc/crypt.h +20 -0
  146. data/modules/emscripten/system/include/libc/ctype.h +58 -187
  147. data/modules/emscripten/system/include/libc/dirent.h +69 -6
  148. data/modules/emscripten/system/include/libc/dlfcn.h +42 -0
  149. data/modules/emscripten/system/include/libc/elf.h +2555 -0
  150. data/modules/emscripten/system/include/libc/endian.h +80 -1
  151. data/modules/emscripten/system/include/libc/err.h +25 -0
  152. data/modules/emscripten/system/include/libc/errno.h +23 -7
  153. data/modules/emscripten/system/include/libc/fcntl.h +175 -1
  154. data/modules/emscripten/system/include/libc/features.h +32 -0
  155. data/modules/emscripten/system/include/libc/fenv.h +28 -0
  156. data/modules/emscripten/system/include/libc/float.h +34 -0
  157. data/modules/emscripten/system/include/libc/fnmatch.h +24 -50
  158. data/modules/emscripten/system/include/libc/ftw.h +42 -0
  159. data/modules/emscripten/system/include/libc/getopt.h +22 -187
  160. data/modules/emscripten/system/include/libc/glob.h +42 -83
  161. data/modules/emscripten/system/include/libc/grp.h +37 -79
  162. data/modules/emscripten/system/include/libc/iconv.h +18 -56
  163. data/modules/emscripten/system/include/libc/ifaddrs.h +24 -53
  164. data/modules/emscripten/system/include/libc/inttypes.h +208 -271
  165. data/modules/emscripten/system/include/libc/iso646.h +5 -28
  166. data/modules/emscripten/system/include/libc/langinfo.h +88 -316
  167. data/modules/emscripten/system/include/libc/lastlog.h +1 -0
  168. data/modules/emscripten/system/include/libc/libgen.h +5 -13
  169. data/modules/emscripten/system/include/libc/libintl.h +25 -0
  170. data/modules/emscripten/system/include/libc/limits.h +140 -149
  171. data/modules/emscripten/system/include/libc/link.h +54 -0
  172. data/modules/emscripten/system/include/libc/locale.h +72 -70
  173. data/modules/emscripten/system/include/libc/malloc.h +0 -169
  174. data/modules/emscripten/system/include/libc/math.h +393 -573
  175. data/modules/emscripten/system/include/libc/memory.h +1 -0
  176. data/modules/emscripten/system/include/libc/mntent.h +44 -0
  177. data/modules/emscripten/system/include/libc/monetary.h +23 -0
  178. data/modules/emscripten/system/include/libc/mqueue.h +36 -0
  179. data/modules/emscripten/system/include/libc/net/ethernet.h +55 -0
  180. data/modules/emscripten/system/include/libc/net/if.h +135 -0
  181. data/modules/emscripten/system/include/libc/net/if_arp.h +133 -0
  182. data/modules/emscripten/system/include/libc/net/route.h +124 -0
  183. data/modules/emscripten/system/include/libc/netdb.h +161 -0
  184. data/modules/emscripten/system/include/libc/netinet/ether.h +14 -0
  185. data/modules/emscripten/system/include/libc/netinet/icmp6.h +305 -0
  186. data/modules/emscripten/system/include/libc/netinet/if_ether.h +126 -0
  187. data/modules/emscripten/system/include/libc/netinet/in.h +336 -0
  188. data/modules/emscripten/system/include/libc/netinet/in_systm.h +9 -0
  189. data/modules/emscripten/system/include/libc/netinet/ip.h +186 -0
  190. data/modules/emscripten/system/include/libc/netinet/ip6.h +142 -0
  191. data/modules/emscripten/system/include/libc/netinet/ip_icmp.h +192 -0
  192. data/modules/emscripten/system/include/libc/netinet/tcp.h +71 -0
  193. data/modules/emscripten/system/include/libc/netinet/udp.h +35 -0
  194. data/modules/emscripten/system/include/libc/netpacket/packet.h +44 -0
  195. data/modules/emscripten/system/include/libc/nl_types.h +22 -0
  196. data/modules/emscripten/system/include/libc/paths.h +30 -5
  197. data/modules/emscripten/system/include/libc/poll.h +46 -0
  198. data/modules/emscripten/system/include/libc/pthread.h +191 -331
  199. data/modules/emscripten/system/include/libc/pty.h +18 -0
  200. data/modules/emscripten/system/include/libc/pwd.h +33 -62
  201. data/modules/emscripten/system/include/libc/readme.txt +2 -2
  202. data/modules/emscripten/system/include/libc/regex.h +53 -93
  203. data/modules/emscripten/system/include/libc/resolv.h +144 -0
  204. data/modules/emscripten/system/include/libc/sched.h +124 -89
  205. data/modules/emscripten/system/include/libc/search.h +40 -48
  206. data/modules/emscripten/system/include/libc/semaphore.h +35 -0
  207. data/modules/emscripten/system/include/libc/setjmp.h +35 -13
  208. data/modules/emscripten/system/include/libc/shadow.h +44 -0
  209. data/modules/emscripten/system/include/libc/signal.h +245 -20
  210. data/modules/emscripten/system/include/libc/spawn.h +74 -0
  211. data/modules/emscripten/system/include/libc/stdalign.h +15 -0
  212. data/modules/emscripten/system/include/libc/stdarg.h +18 -43
  213. data/modules/emscripten/system/include/libc/stdbool.h +14 -0
  214. data/modules/emscripten/system/include/libc/stddef.h +12 -58
  215. data/modules/emscripten/system/include/libc/stdint.h +82 -458
  216. data/modules/emscripten/system/include/libc/stdio.h +184 -679
  217. data/modules/emscripten/system/include/libc/stdio_ext.h +34 -0
  218. data/modules/emscripten/system/include/libc/stdlib.h +146 -205
  219. data/modules/emscripten/system/include/libc/stdnoreturn.h +5 -0
  220. data/modules/emscripten/system/include/libc/string.h +86 -89
  221. data/modules/emscripten/system/include/libc/strings.h +27 -27
  222. data/modules/emscripten/system/include/libc/stropts.h +139 -0
  223. data/modules/emscripten/system/include/libc/sys/acct.h +75 -0
  224. data/modules/emscripten/system/include/libc/sys/cachectl.h +22 -0
  225. data/modules/emscripten/system/include/libc/sys/dir.h +0 -8
  226. data/modules/emscripten/system/include/libc/sys/epoll.h +67 -0
  227. data/modules/emscripten/system/include/libc/sys/errno.h +2 -190
  228. data/modules/emscripten/system/include/libc/sys/eventfd.h +26 -0
  229. data/modules/emscripten/system/include/libc/sys/fcntl.h +2 -4
  230. data/modules/emscripten/system/include/libc/sys/file.h +20 -1
  231. data/modules/emscripten/system/include/libc/sys/fsuid.h +20 -0
  232. data/modules/emscripten/system/include/libc/sys/inotify.h +57 -0
  233. data/modules/emscripten/system/include/libc/sys/io.h +17 -0
  234. data/modules/emscripten/system/include/libc/sys/ioctl.h +14 -0
  235. data/modules/emscripten/system/include/libc/sys/ipc.h +42 -0
  236. data/modules/emscripten/system/include/{sys/sysctl.h → libc/sys/klog.h} +4 -4
  237. data/modules/emscripten/system/include/libc/sys/mman.h +55 -0
  238. data/modules/emscripten/system/include/libc/sys/mount.h +72 -0
  239. data/modules/emscripten/system/include/libc/sys/msg.h +52 -0
  240. data/modules/emscripten/system/include/libc/sys/mtio.h +188 -0
  241. data/modules/emscripten/system/include/libc/sys/param.h +29 -19
  242. data/modules/emscripten/system/include/libc/sys/personality.h +46 -0
  243. data/modules/emscripten/system/include/libc/sys/poll.h +2 -0
  244. data/modules/emscripten/system/include/libc/sys/prctl.h +101 -0
  245. data/modules/emscripten/system/include/libc/sys/procfs.h +65 -0
  246. data/modules/emscripten/system/include/libc/sys/ptrace.h +96 -0
  247. data/modules/emscripten/system/include/libc/sys/reboot.h +20 -0
  248. data/modules/emscripten/system/include/libc/sys/reg.h +9 -0
  249. data/modules/emscripten/system/include/libc/sys/resource.h +89 -45
  250. data/modules/emscripten/system/include/libc/sys/select.h +42 -0
  251. data/modules/emscripten/system/include/libc/sys/sem.h +82 -0
  252. data/modules/emscripten/system/include/libc/sys/sendfile.h +22 -0
  253. data/modules/emscripten/system/include/libc/sys/shm.h +61 -0
  254. data/modules/emscripten/system/include/libc/sys/signal.h +1 -315
  255. data/modules/emscripten/system/include/libc/sys/signalfd.h +44 -0
  256. data/modules/emscripten/system/include/libc/sys/socket.h +299 -0
  257. data/modules/emscripten/system/include/libc/sys/stat.h +95 -204
  258. data/modules/emscripten/system/include/libc/sys/statfs.h +32 -0
  259. data/modules/emscripten/system/include/libc/sys/statvfs.h +57 -0
  260. data/modules/emscripten/system/include/libc/sys/stropts.h +1 -0
  261. data/modules/emscripten/system/include/libc/sys/swap.h +21 -0
  262. data/modules/emscripten/system/include/libc/sys/syscall.h +6 -0
  263. data/modules/emscripten/system/include/libc/sys/sysctl.h +17 -0
  264. data/modules/emscripten/system/include/libc/sys/sysinfo.h +36 -0
  265. data/modules/emscripten/system/include/libc/sys/syslog.h +1 -0
  266. data/modules/emscripten/system/include/libc/sys/sysmacros.h +15 -0
  267. data/modules/emscripten/system/include/libc/sys/termios.h +2 -280
  268. data/modules/emscripten/system/include/libc/sys/time.h +40 -68
  269. data/modules/emscripten/system/include/libc/sys/timerfd.h +24 -0
  270. data/modules/emscripten/system/include/libc/sys/times.h +14 -16
  271. data/modules/emscripten/system/include/libc/sys/timex.h +98 -0
  272. data/modules/emscripten/system/include/libc/sys/ttydefaults.h +34 -92
  273. data/modules/emscripten/system/include/libc/sys/types.h +87 -481
  274. data/modules/emscripten/system/include/libc/sys/ucontext.h +1 -0
  275. data/modules/emscripten/system/include/libc/sys/uio.h +48 -0
  276. data/modules/emscripten/system/include/libc/sys/un.h +32 -0
  277. data/modules/emscripten/system/include/libc/sys/user.h +16 -0
  278. data/modules/emscripten/system/include/libc/sys/utsname.h +30 -0
  279. data/modules/emscripten/system/include/libc/sys/vfs.h +1 -0
  280. data/modules/emscripten/system/include/libc/sys/wait.h +41 -26
  281. data/modules/emscripten/system/include/libc/sys/xattr.h +30 -0
  282. data/modules/emscripten/system/include/libc/syscall.h +1 -0
  283. data/modules/emscripten/system/include/libc/sysexits.h +21 -0
  284. data/modules/emscripten/system/include/libc/syslog.h +104 -0
  285. data/modules/emscripten/system/include/libc/tar.h +27 -33
  286. data/modules/emscripten/system/include/libc/termios.h +40 -1
  287. data/modules/emscripten/system/include/libc/tgmath.h +270 -0
  288. data/modules/emscripten/system/include/libc/time.h +96 -237
  289. data/modules/emscripten/system/include/libc/ucontext.h +25 -0
  290. data/modules/emscripten/system/include/libc/ulimit.h +17 -0
  291. data/modules/emscripten/system/include/libc/unistd.h +517 -4
  292. data/modules/emscripten/system/include/libc/utime.h +15 -3
  293. data/modules/emscripten/system/include/libc/utmp.h +40 -1
  294. data/modules/emscripten/system/include/libc/utmpx.h +58 -0
  295. data/modules/emscripten/system/include/libc/values.h +39 -0
  296. data/modules/emscripten/system/include/libc/wchar.h +164 -175
  297. data/modules/emscripten/system/include/libc/wctype.h +67 -37
  298. data/modules/emscripten/system/include/libc/wordexp.h +31 -42
  299. data/modules/emscripten/system/include/libcxx/__locale +6 -6
  300. data/modules/emscripten/system/include/libcxx/locale +1 -1
  301. data/modules/emscripten/system/lib/libc/musl/readme.txt +9 -1
  302. data/modules/emscripten/system/lib/libc/musl/src/internal/locale_impl.h +5 -0
  303. data/modules/emscripten/system/lib/libc/musl/src/internal/stdio_impl.h +92 -0
  304. data/modules/emscripten/system/lib/libc/musl/src/locale/big5.h +1085 -0
  305. data/modules/emscripten/system/lib/libc/musl/src/locale/codepages.h +238 -0
  306. data/modules/emscripten/system/lib/libc/musl/src/locale/gb18030.h +1836 -0
  307. data/modules/emscripten/system/lib/libc/musl/src/locale/hkscs.h +390 -0
  308. data/modules/emscripten/system/lib/libc/musl/src/locale/iconv.c +454 -0
  309. data/modules/emscripten/system/lib/libc/musl/src/locale/iswalnum_l.c +6 -0
  310. data/modules/emscripten/system/lib/libc/musl/src/locale/iswalpha_l.c +6 -0
  311. data/modules/emscripten/system/lib/libc/musl/src/locale/iswblank_l.c +6 -0
  312. data/modules/emscripten/system/lib/libc/musl/src/locale/iswcntrl_l.c +6 -0
  313. data/modules/emscripten/system/lib/libc/musl/src/locale/iswctype_l.c +9 -0
  314. data/modules/emscripten/system/lib/libc/musl/src/locale/iswdigit_l.c +6 -0
  315. data/modules/emscripten/system/lib/libc/musl/src/locale/iswgraph_l.c +6 -0
  316. data/modules/emscripten/system/lib/libc/musl/src/locale/iswlower_l.c +6 -0
  317. data/modules/emscripten/system/lib/libc/musl/src/locale/iswprint_l.c +6 -0
  318. data/modules/emscripten/system/lib/libc/musl/src/locale/iswpunct_l.c +6 -0
  319. data/modules/emscripten/system/lib/libc/musl/src/locale/iswspace_l.c +6 -0
  320. data/modules/emscripten/system/lib/libc/musl/src/locale/iswupper_l.c +6 -0
  321. data/modules/emscripten/system/lib/libc/musl/src/locale/iswxdigit_l.c +6 -0
  322. data/modules/emscripten/system/lib/libc/musl/src/locale/jis0208.h +550 -0
  323. data/modules/emscripten/system/lib/libc/musl/src/locale/ksc.h +640 -0
  324. data/modules/emscripten/system/lib/libc/musl/src/locale/legacychars.h +39 -0
  325. data/modules/emscripten/system/lib/libc/musl/src/locale/strfmon.c +101 -0
  326. data/modules/emscripten/system/lib/libc/musl/src/locale/strxfrm.c +18 -0
  327. data/modules/emscripten/system/lib/libc/musl/src/locale/towctrans_l.c +6 -0
  328. data/modules/emscripten/system/lib/libc/musl/src/locale/towlower_l.c +9 -0
  329. data/modules/emscripten/system/lib/libc/musl/src/locale/towupper_l.c +9 -0
  330. data/modules/emscripten/system/lib/libc/musl/src/locale/wcscoll.c +16 -0
  331. data/modules/emscripten/system/lib/libc/musl/src/locale/wcscoll_l.c +6 -0
  332. data/modules/emscripten/system/lib/libc/musl/src/locale/wcsxfrm.c +21 -0
  333. data/modules/emscripten/system/lib/libc/musl/src/locale/wcsxfrm_l.c +6 -0
  334. data/modules/emscripten/system/lib/libc/musl/src/locale/wctrans_l.c +6 -0
  335. data/modules/emscripten/system/lib/libc/musl/src/locale/wctype_l.c +9 -0
  336. data/modules/emscripten/system/lib/libc/musl/src/stdio/fwprintf.c +13 -0
  337. data/modules/emscripten/system/lib/libc/musl/src/stdio/swprintf.c +14 -0
  338. data/modules/emscripten/system/lib/libc/musl/src/stdio/vfwprintf.c +361 -0
  339. data/modules/emscripten/system/lib/libc/musl/src/stdio/vswprintf.c +53 -0
  340. data/modules/emscripten/system/lib/libc/musl/src/stdio/vwprintf.c +7 -0
  341. data/modules/emscripten/system/lib/libc/musl/src/stdio/wprintf.c +13 -0
  342. data/modules/emscripten/system/lib/libcextra.symbols +44 -0
  343. data/modules/emscripten/system/lib/libcxx/exception.cpp +3 -3
  344. data/modules/emscripten/system/lib/libcxx/locale.cpp +12 -12
  345. data/modules/emscripten/system/lib/libcxxabi/src/cxa_new_delete.cpp +1 -1
  346. data/modules/emscripten/tools/asm_module.py +2 -0
  347. data/modules/emscripten/tools/autodebugger.py +3 -1
  348. data/modules/emscripten/tools/eliminator/asm-eliminator-test-output.js +0 -4835
  349. data/modules/emscripten/tools/eliminator/asm-eliminator-test.js +0 -6495
  350. data/modules/emscripten/tools/file_packager.py +53 -56
  351. data/modules/emscripten/tools/find_bigfuncs.py +2 -2
  352. data/modules/emscripten/tools/find_bigvars.py +24 -0
  353. data/modules/emscripten/tools/gen_struct_info.py +509 -0
  354. data/modules/emscripten/tools/gen_struct_info.pyc +0 -0
  355. data/modules/emscripten/tools/js-optimizer.js +177 -86
  356. data/modules/emscripten/tools/js_optimizer.py +54 -19
  357. data/modules/emscripten/tools/js_optimizer.pyc +0 -0
  358. data/modules/emscripten/tools/jsrun.py +17 -7
  359. data/modules/emscripten/tools/jsrun.pyc +0 -0
  360. data/modules/emscripten/tools/response_file.py +2 -2
  361. data/modules/emscripten/tools/response_file.pyc +0 -0
  362. data/modules/emscripten/tools/shared.py +257 -123
  363. data/modules/emscripten/tools/shared.pyc +0 -0
  364. data/modules/emscripten/tools/source-maps/sourcemapper.js +37 -6
  365. data/modules/emscripten/tools/tempfiles.py +1 -0
  366. data/modules/emscripten/tools/tempfiles.pyc +0 -0
  367. data/modules/emscripten/tools/test-js-optimizer-asm-minlast-output.js +2 -0
  368. data/modules/emscripten/tools/test-js-optimizer-asm-minlast.js +8 -0
  369. data/modules/emscripten/tools/test-js-optimizer-asm-outline1-output.js +412 -169
  370. data/modules/emscripten/tools/test-js-optimizer-asm-outline1.js +88 -0
  371. data/modules/emscripten/tools/test-js-optimizer-asm-outline2-output.js +311 -265
  372. data/modules/emscripten/tools/test-js-optimizer-asm-pre-output.js +0 -20
  373. data/modules/emscripten/tools/test-js-optimizer-asm-pre.js +0 -21
  374. data/modules/emscripten/tools/test-js-optimizer-asm-regs.js +2 -2
  375. data/modules/emscripten/tools/test-js-optimizer-regs-output.js +8 -8
  376. data/modules/emscripten/tools/test-js-optimizer-regs.js +1 -1
  377. data/modules/emscripten/tools/validate_asmjs.py +82 -0
  378. data/modules/mruby/Rakefile +2 -2
  379. data/modules/mruby/include/mruby/class.h +2 -2
  380. data/modules/mruby/include/mruby/compile.h +12 -4
  381. data/modules/mruby/include/mruby/data.h +8 -3
  382. data/modules/mruby/include/mruby/debug.h +65 -0
  383. data/modules/mruby/include/mruby/dump.h +10 -2
  384. data/modules/mruby/include/mruby/irep.h +1 -0
  385. data/modules/mruby/include/mruby/string.h +2 -1
  386. data/modules/mruby/include/mruby/value.h +20 -13
  387. data/modules/mruby/include/mruby/variable.h +1 -0
  388. data/modules/mruby/include/mruby.h +5 -6
  389. data/modules/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +6 -4
  390. data/modules/mruby/mrbgems/mruby-math/src/math.c +4 -0
  391. data/modules/mruby/mrbgems/mruby-objectspace/src/mruby_objectspace.c +1 -1
  392. data/modules/mruby/mrbgems/mruby-proc-ext/src/proc.c +1 -1
  393. data/modules/mruby/mrbgems/mruby-random/src/random.c +1 -4
  394. data/modules/mruby/mrbgems/mruby-string-ext/src/string.c +25 -16
  395. data/modules/mruby/mrbgems/mruby-string-ext/test/string.rb +4 -0
  396. data/modules/mruby/mrbgems/mruby-struct/src/struct.c +1 -1
  397. data/modules/mruby/mrbgems/mruby-symbol-ext/mrblib/symbol.rb +51 -0
  398. data/modules/mruby/mrbgems/mruby-symbol-ext/test/symbol.rb +22 -0
  399. data/modules/mruby/mrbgems/mruby-time/src/time.c +38 -60
  400. data/modules/mruby/mrblib/class.rb +2 -2
  401. data/modules/mruby/src/backtrace.c +96 -23
  402. data/modules/mruby/src/class.c +43 -41
  403. data/modules/mruby/src/codegen.c +52 -46
  404. data/modules/mruby/src/debug.c +214 -0
  405. data/modules/mruby/src/dump.c +245 -17
  406. data/modules/mruby/src/error.c +14 -6
  407. data/modules/mruby/src/etc.c +17 -10
  408. data/modules/mruby/src/gc.c +9 -9
  409. data/modules/mruby/src/kernel.c +1 -1
  410. data/modules/mruby/src/load.c +137 -1
  411. data/modules/mruby/src/object.c +1 -1
  412. data/modules/mruby/src/parse.y +162 -37
  413. data/modules/mruby/src/state.c +2 -0
  414. data/modules/mruby/src/string.c +28 -19
  415. data/modules/mruby/src/symbol.c +0 -1
  416. data/modules/mruby/src/variable.c +12 -15
  417. data/modules/mruby/src/vm.c +38 -22
  418. data/modules/mruby/tasks/mrbgem_spec.rake +6 -4
  419. data/modules/mruby/tasks/mrbgems_test.rake +9 -9
  420. data/modules/mruby/tasks/mruby_build_gem.rake +9 -0
  421. data/modules/mruby/tasks/toolchains/androideabi.rake +2 -0
  422. data/modules/mruby/test/driver.c +3 -3
  423. data/modules/mruby/test/t/array.rb +13 -0
  424. data/modules/mruby/test/t/class.rb +28 -0
  425. data/modules/mruby/test/t/exception.rb +10 -0
  426. data/modules/mruby/test/t/literals.rb +50 -0
  427. data/modules/mruby/test/t/module.rb +22 -0
  428. data/modules/mruby/test/t/proc.rb +37 -0
  429. data/modules/mruby/test/t/string.rb +20 -21
  430. data/modules/mruby/tools/mrbc/mrbc.c +2 -4
  431. data/scripts/gen_post.rb +1 -0
  432. data/scripts/gen_require.rb +107 -0
  433. data/templates/minimal/Rakefile +20 -0
  434. metadata +210 -88
  435. data/driver/main.c +0 -40
  436. data/modules/emscripten/cmake/Platform/Emscripten_unix.cmake +0 -24
  437. data/modules/emscripten/emlibtool +0 -11
  438. data/modules/emscripten/emlibtool.bat +0 -2
  439. data/modules/emscripten/src/framework.js +0 -257
  440. data/modules/emscripten/system/include/bsd/float.h +0 -91
  441. data/modules/emscripten/system/include/bsd/readme.txt +0 -2
  442. data/modules/emscripten/system/include/bsd/sys/mman.h +0 -180
  443. data/modules/emscripten/system/include/bsd/sys/utsname.h +0 -70
  444. data/modules/emscripten/system/include/dlfcn.h +0 -31
  445. data/modules/emscripten/system/include/err.h +0 -95
  446. data/modules/emscripten/system/include/features.h +0 -3
  447. data/modules/emscripten/system/include/libc/_ansi.h +0 -135
  448. data/modules/emscripten/system/include/libc/_syslist.h +0 -40
  449. data/modules/emscripten/system/include/libc/argz.h +0 -33
  450. data/modules/emscripten/system/include/libc/envlock.h +0 -15
  451. data/modules/emscripten/system/include/libc/envz.h +0 -16
  452. data/modules/emscripten/system/include/libc/fastmath.h +0 -13
  453. data/modules/emscripten/system/include/libc/ieeefp.h +0 -256
  454. data/modules/emscripten/system/include/libc/machine/_default_types.h +0 -121
  455. data/modules/emscripten/system/include/libc/machine/_types.h +0 -8
  456. data/modules/emscripten/system/include/libc/machine/ansi.h +0 -1
  457. data/modules/emscripten/system/include/libc/machine/endian.h +0 -31
  458. data/modules/emscripten/system/include/libc/machine/fastmath.h +0 -100
  459. data/modules/emscripten/system/include/libc/machine/ieeefp.h +0 -376
  460. data/modules/emscripten/system/include/libc/machine/malloc.h +0 -8
  461. data/modules/emscripten/system/include/libc/machine/param.h +0 -1
  462. data/modules/emscripten/system/include/libc/machine/setjmp-dj.h +0 -43
  463. data/modules/emscripten/system/include/libc/machine/setjmp.h +0 -361
  464. data/modules/emscripten/system/include/libc/machine/stdlib.h +0 -8
  465. data/modules/emscripten/system/include/libc/machine/termios.h +0 -1
  466. data/modules/emscripten/system/include/libc/machine/time.h +0 -19
  467. data/modules/emscripten/system/include/libc/machine/types.h +0 -30
  468. data/modules/emscripten/system/include/libc/newlib.h +0 -2
  469. data/modules/emscripten/system/include/libc/process.h +0 -44
  470. data/modules/emscripten/system/include/libc/reent.h +0 -183
  471. data/modules/emscripten/system/include/libc/regdef.h +0 -7
  472. data/modules/emscripten/system/include/libc/sys/_default_fcntl.h +0 -223
  473. data/modules/emscripten/system/include/libc/sys/_types.h +0 -93
  474. data/modules/emscripten/system/include/libc/sys/cdefs.h +0 -123
  475. data/modules/emscripten/system/include/libc/sys/config.h +0 -255
  476. data/modules/emscripten/system/include/libc/sys/custom_file.h +0 -2
  477. data/modules/emscripten/system/include/libc/sys/dirent.h +0 -58
  478. data/modules/emscripten/system/include/libc/sys/features.h +0 -212
  479. data/modules/emscripten/system/include/libc/sys/iconvnls.h +0 -77
  480. data/modules/emscripten/system/include/libc/sys/lock.h +0 -24
  481. data/modules/emscripten/system/include/libc/sys/queue.h +0 -471
  482. data/modules/emscripten/system/include/libc/sys/reent.h +0 -843
  483. data/modules/emscripten/system/include/libc/sys/sched.h +0 -67
  484. data/modules/emscripten/system/include/libc/sys/stdio.h +0 -27
  485. data/modules/emscripten/system/include/libc/sys/string.h +0 -2
  486. data/modules/emscripten/system/include/libc/sys/syslimits.h +0 -65
  487. data/modules/emscripten/system/include/libc/sys/unistd.h +0 -514
  488. data/modules/emscripten/system/include/libc/sys/utime.h +0 -26
  489. data/modules/emscripten/system/include/libc/unctrl.h +0 -46
  490. data/modules/emscripten/system/include/memory.h +0 -10
  491. data/modules/emscripten/system/include/mntent.h +0 -23
  492. data/modules/emscripten/system/include/net/arpa/inet.h +0 -32
  493. data/modules/emscripten/system/include/net/arpa/nameser.h +0 -535
  494. data/modules/emscripten/system/include/net/arpa/nameser_compat.h +0 -187
  495. data/modules/emscripten/system/include/net/if.h +0 -106
  496. data/modules/emscripten/system/include/net/netinet/in.h +0 -230
  497. data/modules/emscripten/system/include/net/netinet/tcp.h +0 -246
  498. data/modules/emscripten/system/include/net/resolv.h +0 -389
  499. data/modules/emscripten/system/include/netdb.h +0 -130
  500. data/modules/emscripten/system/include/nl_types.h +0 -19
  501. data/modules/emscripten/system/include/poll.h +0 -3
  502. data/modules/emscripten/system/include/pty.h +0 -6
  503. data/modules/emscripten/system/include/semaphore.h +0 -31
  504. data/modules/emscripten/system/include/spawn.h +0 -105
  505. data/modules/emscripten/system/include/stdbool.h +0 -16
  506. data/modules/emscripten/system/include/sys/bitypes.h +0 -3
  507. data/modules/emscripten/system/include/sys/io.h +0 -14
  508. data/modules/emscripten/system/include/sys/ioctl.h +0 -78
  509. data/modules/emscripten/system/include/sys/poll.h +0 -31
  510. data/modules/emscripten/system/include/sys/select.h +0 -16
  511. data/modules/emscripten/system/include/sys/sendfile.h +0 -16
  512. data/modules/emscripten/system/include/sys/socket.h +0 -247
  513. data/modules/emscripten/system/include/sys/socketvar.h +0 -3
  514. data/modules/emscripten/system/include/sys/statvfs.h +0 -32
  515. data/modules/emscripten/system/include/sys/uio.h +0 -22
  516. data/modules/emscripten/system/include/sys/un.h +0 -66
  517. data/modules/emscripten/system/include/sysexits.h +0 -108
  518. data/modules/emscripten/system/include/xlocale.h +0 -47
@@ -0,0 +1,1585 @@
1
+ mergeInto(LibraryManager.library, {
2
+ $FS__deps: ['$ERRNO_CODES', '$ERRNO_MESSAGES', '__setErrNo', '$PATH', '$TTY', '$MEMFS', '$IDBFS', '$NODEFS', 'stdin', 'stdout', 'stderr', 'fflush'],
3
+ $FS__postset: 'FS.staticInit();' +
4
+ '__ATINIT__.unshift({ func: function() { if (!Module["noFSInit"] && !FS.init.initialized) FS.init() } });' +
5
+ '__ATMAIN__.push({ func: function() { FS.ignorePermissions = false } });' +
6
+ '__ATEXIT__.push({ func: function() { FS.quit() } });' +
7
+ // export some names through closure
8
+ 'Module["FS_createFolder"] = FS.createFolder;' +
9
+ 'Module["FS_createPath"] = FS.createPath;' +
10
+ 'Module["FS_createDataFile"] = FS.createDataFile;' +
11
+ 'Module["FS_createPreloadedFile"] = FS.createPreloadedFile;' +
12
+ 'Module["FS_createLazyFile"] = FS.createLazyFile;' +
13
+ 'Module["FS_createLink"] = FS.createLink;' +
14
+ 'Module["FS_createDevice"] = FS.createDevice;',
15
+ $FS: {
16
+ root: null,
17
+ mounts: [],
18
+ devices: [null],
19
+ streams: [null],
20
+ nextInode: 1,
21
+ nameTable: null,
22
+ currentPath: '/',
23
+ initialized: false,
24
+ // Whether we are currently ignoring permissions. Useful when preparing the
25
+ // filesystem and creating files inside read-only folders.
26
+ // This is set to false when the runtime is initialized, allowing you
27
+ // to modify the filesystem freely before run() is called.
28
+ ignorePermissions: true,
29
+
30
+ ErrnoError: null, // set during init
31
+
32
+ handleFSError: function(e) {
33
+ if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace();
34
+ return ___setErrNo(e.errno);
35
+ },
36
+
37
+ //
38
+ // paths
39
+ //
40
+ lookupPath: function(path, opts) {
41
+ path = PATH.resolve(FS.cwd(), path);
42
+ opts = opts || { recurse_count: 0 };
43
+
44
+ if (opts.recurse_count > 8) { // max recursive lookup of 8
45
+ throw new FS.ErrnoError(ERRNO_CODES.ELOOP);
46
+ }
47
+
48
+ // split the path
49
+ var parts = PATH.normalizeArray(path.split('/').filter(function(p) {
50
+ return !!p;
51
+ }), false);
52
+
53
+ // start at the root
54
+ var current = FS.root;
55
+ var current_path = '/';
56
+
57
+ for (var i = 0; i < parts.length; i++) {
58
+ var islast = (i === parts.length-1);
59
+ if (islast && opts.parent) {
60
+ // stop resolving
61
+ break;
62
+ }
63
+
64
+ current = FS.lookupNode(current, parts[i]);
65
+ current_path = PATH.join(current_path, parts[i]);
66
+
67
+ // jump to the mount's root node if this is a mountpoint
68
+ if (FS.isMountpoint(current)) {
69
+ current = current.mount.root;
70
+ }
71
+
72
+ // follow symlinks
73
+ // by default, lookupPath will not follow a symlink if it is the final path component.
74
+ // setting opts.follow = true will override this behavior.
75
+ if (!islast || opts.follow) {
76
+ var count = 0;
77
+ while (FS.isLink(current.mode)) {
78
+ var link = FS.readlink(current_path);
79
+ current_path = PATH.resolve(PATH.dirname(current_path), link);
80
+
81
+ var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count });
82
+ current = lookup.node;
83
+
84
+ if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
85
+ throw new FS.ErrnoError(ERRNO_CODES.ELOOP);
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ return { path: current_path, node: current };
92
+ },
93
+ getPath: function(node) {
94
+ var path;
95
+ while (true) {
96
+ if (FS.isRoot(node)) {
97
+ return path ? PATH.join(node.mount.mountpoint, path) : node.mount.mountpoint;
98
+ }
99
+ path = path ? PATH.join(node.name, path) : node.name;
100
+ node = node.parent;
101
+ }
102
+ },
103
+
104
+ //
105
+ // nodes
106
+ //
107
+ hashName: function(parentid, name) {
108
+ var hash = 0;
109
+
110
+ #if CASE_INSENSITIVE_FS
111
+ name = name.toLowerCase();
112
+ #endif
113
+
114
+ for (var i = 0; i < name.length; i++) {
115
+ hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
116
+ }
117
+ return ((parentid + hash) >>> 0) % FS.nameTable.length;
118
+ },
119
+ hashAddNode: function(node) {
120
+ var hash = FS.hashName(node.parent.id, node.name);
121
+ node.name_next = FS.nameTable[hash];
122
+ FS.nameTable[hash] = node;
123
+ },
124
+ hashRemoveNode: function(node) {
125
+ var hash = FS.hashName(node.parent.id, node.name);
126
+ if (FS.nameTable[hash] === node) {
127
+ FS.nameTable[hash] = node.name_next;
128
+ } else {
129
+ var current = FS.nameTable[hash];
130
+ while (current) {
131
+ if (current.name_next === node) {
132
+ current.name_next = node.name_next;
133
+ break;
134
+ }
135
+ current = current.name_next;
136
+ }
137
+ }
138
+ },
139
+ lookupNode: function(parent, name) {
140
+ var err = FS.mayLookup(parent);
141
+ if (err) {
142
+ throw new FS.ErrnoError(err);
143
+ }
144
+ var hash = FS.hashName(parent.id, name);
145
+ #if CASE_INSENSITIVE_FS
146
+ name = name.toLowerCase();
147
+ #endif
148
+ for (var node = FS.nameTable[hash]; node; node = node.name_next) {
149
+ var nodeName = node.name;
150
+ #if CASE_INSENSITIVE_FS
151
+ nodeName = nodeName.toLowerCase();
152
+ #endif
153
+ if (node.parent.id === parent.id && nodeName === name) {
154
+ return node;
155
+ }
156
+ }
157
+ // if we failed to find it in the cache, call into the VFS
158
+ return FS.lookup(parent, name);
159
+ },
160
+ createNode: function(parent, name, mode, rdev) {
161
+ var node = {
162
+ id: FS.nextInode++,
163
+ name: name,
164
+ mode: mode,
165
+ node_ops: {},
166
+ stream_ops: {},
167
+ rdev: rdev,
168
+ parent: null,
169
+ mount: null
170
+ };
171
+ if (!parent) {
172
+ parent = node; // root node sets parent to itself
173
+ }
174
+ node.parent = parent;
175
+ node.mount = parent.mount;
176
+ // compatibility
177
+ var readMode = {{{ cDefine('S_IRUGO') }}} | {{{ cDefine('S_IXUGO') }}};
178
+ var writeMode = {{{ cDefine('S_IWUGO') }}};
179
+ // NOTE we must use Object.defineProperties instead of individual calls to
180
+ // Object.defineProperty in order to make closure compiler happy
181
+ Object.defineProperties(node, {
182
+ read: {
183
+ get: function() { return (node.mode & readMode) === readMode; },
184
+ set: function(val) { val ? node.mode |= readMode : node.mode &= ~readMode; }
185
+ },
186
+ write: {
187
+ get: function() { return (node.mode & writeMode) === writeMode; },
188
+ set: function(val) { val ? node.mode |= writeMode : node.mode &= ~writeMode; }
189
+ },
190
+ isFolder: {
191
+ get: function() { return FS.isDir(node.mode); },
192
+ },
193
+ isDevice: {
194
+ get: function() { return FS.isChrdev(node.mode); },
195
+ },
196
+ });
197
+ FS.hashAddNode(node);
198
+ return node;
199
+ },
200
+ destroyNode: function(node) {
201
+ FS.hashRemoveNode(node);
202
+ },
203
+ isRoot: function(node) {
204
+ return node === node.parent;
205
+ },
206
+ isMountpoint: function(node) {
207
+ return node.mounted;
208
+ },
209
+ isFile: function(mode) {
210
+ return (mode & {{{ cDefine('S_IFMT') }}}) === {{{ cDefine('S_IFREG') }}};
211
+ },
212
+ isDir: function(mode) {
213
+ return (mode & {{{ cDefine('S_IFMT') }}}) === {{{ cDefine('S_IFDIR') }}};
214
+ },
215
+ isLink: function(mode) {
216
+ return (mode & {{{ cDefine('S_IFMT') }}}) === {{{ cDefine('S_IFLNK') }}};
217
+ },
218
+ isChrdev: function(mode) {
219
+ return (mode & {{{ cDefine('S_IFMT') }}}) === {{{ cDefine('S_IFCHR') }}};
220
+ },
221
+ isBlkdev: function(mode) {
222
+ return (mode & {{{ cDefine('S_IFMT') }}}) === {{{ cDefine('S_IFBLK') }}};
223
+ },
224
+ isFIFO: function(mode) {
225
+ return (mode & {{{ cDefine('S_IFMT') }}}) === {{{ cDefine('S_IFIFO') }}};
226
+ },
227
+ isSocket: function(mode) {
228
+ return (mode & {{{ cDefine('S_IFSOCK') }}}) === {{{ cDefine('S_IFSOCK') }}};
229
+ },
230
+
231
+ //
232
+ // permissions
233
+ //
234
+ flagModes: {
235
+ '"r"': {{{ cDefine('O_RDONLY') }}},
236
+ '"rs"': {{{ cDefine('O_RDONLY') }}} | {{{ cDefine('O_SYNC') }}},
237
+ '"r+"': {{{ cDefine('O_RDWR') }}},
238
+ '"w"': {{{ cDefine('O_TRUNC') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_WRONLY') }}},
239
+ '"wx"': {{{ cDefine('O_TRUNC') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_WRONLY') }}} | {{{ cDefine('O_EXCL') }}},
240
+ '"xw"': {{{ cDefine('O_TRUNC') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_WRONLY') }}} | {{{ cDefine('O_EXCL') }}},
241
+ '"w+"': {{{ cDefine('O_TRUNC') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_RDWR') }}},
242
+ '"wx+"': {{{ cDefine('O_TRUNC') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_RDWR') }}} | {{{ cDefine('O_EXCL') }}},
243
+ '"xw+"': {{{ cDefine('O_TRUNC') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_RDWR') }}} | {{{ cDefine('O_EXCL') }}},
244
+ '"a"': {{{ cDefine('O_APPEND') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_WRONLY') }}},
245
+ '"ax"': {{{ cDefine('O_APPEND') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_WRONLY') }}} | {{{ cDefine('O_EXCL') }}},
246
+ '"xa"': {{{ cDefine('O_APPEND') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_WRONLY') }}} | {{{ cDefine('O_EXCL') }}},
247
+ '"a+"': {{{ cDefine('O_APPEND') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_RDWR') }}},
248
+ '"ax+"': {{{ cDefine('O_APPEND') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_RDWR') }}} | {{{ cDefine('O_EXCL') }}},
249
+ '"xa+"': {{{ cDefine('O_APPEND') }}} | {{{ cDefine('O_CREAT') }}} | {{{ cDefine('O_RDWR') }}} | {{{ cDefine('O_EXCL') }}}
250
+ },
251
+ // convert the 'r', 'r+', etc. to it's corresponding set of O_* flags
252
+ modeStringToFlags: function(str) {
253
+ var flags = FS.flagModes[str];
254
+ if (typeof flags === 'undefined') {
255
+ throw new Error('Unknown file open mode: ' + str);
256
+ }
257
+ return flags;
258
+ },
259
+ // convert O_* bitmask to a string for nodePermissions
260
+ flagsToPermissionString: function(flag) {
261
+ var accmode = flag & {{{ cDefine('O_ACCMODE') }}};
262
+ var perms = ['r', 'w', 'rw'][accmode];
263
+ if ((flag & {{{ cDefine('O_TRUNC') }}})) {
264
+ perms += 'w';
265
+ }
266
+ return perms;
267
+ },
268
+ nodePermissions: function(node, perms) {
269
+ if (FS.ignorePermissions) {
270
+ return 0;
271
+ }
272
+ // return 0 if any user, group or owner bits are set.
273
+ if (perms.indexOf('r') !== -1 && !(node.mode & {{{ cDefine('S_IRUGO') }}})) {
274
+ return ERRNO_CODES.EACCES;
275
+ } else if (perms.indexOf('w') !== -1 && !(node.mode & {{{ cDefine('S_IWUGO') }}})) {
276
+ return ERRNO_CODES.EACCES;
277
+ } else if (perms.indexOf('x') !== -1 && !(node.mode & {{{ cDefine('S_IXUGO') }}})) {
278
+ return ERRNO_CODES.EACCES;
279
+ }
280
+ return 0;
281
+ },
282
+ mayLookup: function(dir) {
283
+ return FS.nodePermissions(dir, 'x');
284
+ },
285
+ mayCreate: function(dir, name) {
286
+ try {
287
+ var node = FS.lookupNode(dir, name);
288
+ return ERRNO_CODES.EEXIST;
289
+ } catch (e) {
290
+ }
291
+ return FS.nodePermissions(dir, 'wx');
292
+ },
293
+ mayDelete: function(dir, name, isdir) {
294
+ var node;
295
+ try {
296
+ node = FS.lookupNode(dir, name);
297
+ } catch (e) {
298
+ return e.errno;
299
+ }
300
+ var err = FS.nodePermissions(dir, 'wx');
301
+ if (err) {
302
+ return err;
303
+ }
304
+ if (isdir) {
305
+ if (!FS.isDir(node.mode)) {
306
+ return ERRNO_CODES.ENOTDIR;
307
+ }
308
+ if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
309
+ return ERRNO_CODES.EBUSY;
310
+ }
311
+ } else {
312
+ if (FS.isDir(node.mode)) {
313
+ return ERRNO_CODES.EISDIR;
314
+ }
315
+ }
316
+ return 0;
317
+ },
318
+ mayOpen: function(node, flags) {
319
+ if (!node) {
320
+ return ERRNO_CODES.ENOENT;
321
+ }
322
+ if (FS.isLink(node.mode)) {
323
+ return ERRNO_CODES.ELOOP;
324
+ } else if (FS.isDir(node.mode)) {
325
+ if ((flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_RDONLY')}}} || // opening for write
326
+ (flags & {{{ cDefine('O_TRUNC') }}})) {
327
+ return ERRNO_CODES.EISDIR;
328
+ }
329
+ }
330
+ return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
331
+ },
332
+
333
+ //
334
+ // streams
335
+ //
336
+ MAX_OPEN_FDS: 4096,
337
+ nextfd: function(fd_start, fd_end) {
338
+ fd_start = fd_start || 1;
339
+ fd_end = fd_end || FS.MAX_OPEN_FDS;
340
+ for (var fd = fd_start; fd <= fd_end; fd++) {
341
+ if (!FS.streams[fd]) {
342
+ return fd;
343
+ }
344
+ }
345
+ throw new FS.ErrnoError(ERRNO_CODES.EMFILE);
346
+ },
347
+ getStream: function(fd) {
348
+ return FS.streams[fd];
349
+ },
350
+ // TODO parameterize this function such that a stream
351
+ // object isn't directly passed in. not possible until
352
+ // SOCKFS is completed.
353
+ createStream: function(stream, fd_start, fd_end) {
354
+ var fd = FS.nextfd(fd_start, fd_end);
355
+ stream.fd = fd;
356
+ // compatibility
357
+ Object.defineProperties(stream, {
358
+ object: {
359
+ get: function() { return stream.node; },
360
+ set: function(val) { stream.node = val; }
361
+ },
362
+ isRead: {
363
+ get: function() { return (stream.flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_WRONLY') }}}; }
364
+ },
365
+ isWrite: {
366
+ get: function() { return (stream.flags & {{{ cDefine('O_ACCMODE') }}}) !== {{{ cDefine('O_RDONLY') }}}; }
367
+ },
368
+ isAppend: {
369
+ get: function() { return (stream.flags & {{{ cDefine('O_APPEND') }}}); }
370
+ }
371
+ });
372
+ FS.streams[fd] = stream;
373
+ return stream;
374
+ },
375
+ closeStream: function(fd) {
376
+ FS.streams[fd] = null;
377
+ },
378
+
379
+ //
380
+ // devices
381
+ //
382
+ // each character device consists of a device id + stream operations.
383
+ // when a character device node is created (e.g. /dev/stdin) it is
384
+ // assigned a device id that lets us map back to the actual device.
385
+ // by default, each character device stream (e.g. _stdin) uses chrdev_stream_ops.
386
+ // however, once opened, the stream's operations are overridden with
387
+ // the operations of the device its underlying node maps back to.
388
+ chrdev_stream_ops: {
389
+ open: function(stream) {
390
+ var device = FS.getDevice(stream.node.rdev);
391
+ // override node's stream ops with the device's
392
+ stream.stream_ops = device.stream_ops;
393
+ // forward the open call
394
+ if (stream.stream_ops.open) {
395
+ stream.stream_ops.open(stream);
396
+ }
397
+ },
398
+ llseek: function() {
399
+ throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
400
+ }
401
+ },
402
+ major: function(dev) {
403
+ return ((dev) >> 8);
404
+ },
405
+ minor: function(dev) {
406
+ return ((dev) & 0xff);
407
+ },
408
+ makedev: function(ma, mi) {
409
+ return ((ma) << 8 | (mi));
410
+ },
411
+ registerDevice: function(dev, ops) {
412
+ FS.devices[dev] = { stream_ops: ops };
413
+ },
414
+ getDevice: function(dev) {
415
+ return FS.devices[dev];
416
+ },
417
+
418
+ //
419
+ // core
420
+ //
421
+ syncfs: function(populate, callback) {
422
+ if (typeof(populate) === 'function') {
423
+ callback = populate;
424
+ populate = false;
425
+ }
426
+
427
+ var completed = 0;
428
+ var total = FS.mounts.length;
429
+ var done = function(err) {
430
+ if (err) {
431
+ return callback(err);
432
+ }
433
+ if (++completed >= total) {
434
+ callback(null);
435
+ }
436
+ };
437
+
438
+ // sync all mounts
439
+ for (var i = 0; i < FS.mounts.length; i++) {
440
+ var mount = FS.mounts[i];
441
+ if (!mount.type.syncfs) {
442
+ done(null);
443
+ continue;
444
+ }
445
+ mount.type.syncfs(mount, populate, done);
446
+ }
447
+ },
448
+ mount: function(type, opts, mountpoint) {
449
+ var lookup;
450
+ if (mountpoint) {
451
+ lookup = FS.lookupPath(mountpoint, { follow: false });
452
+ mountpoint = lookup.path; // use the absolute path
453
+ }
454
+ var mount = {
455
+ type: type,
456
+ opts: opts,
457
+ mountpoint: mountpoint,
458
+ root: null
459
+ };
460
+ // create a root node for the fs
461
+ var root = type.mount(mount);
462
+ root.mount = mount;
463
+ mount.root = root;
464
+ // assign the mount info to the mountpoint's node
465
+ if (lookup) {
466
+ lookup.node.mount = mount;
467
+ lookup.node.mounted = true;
468
+ // compatibility update FS.root if we mount to /
469
+ if (mountpoint === '/') {
470
+ FS.root = mount.root;
471
+ }
472
+ }
473
+ // add to our cached list of mounts
474
+ FS.mounts.push(mount);
475
+ return root;
476
+ },
477
+ lookup: function(parent, name) {
478
+ return parent.node_ops.lookup(parent, name);
479
+ },
480
+ // generic function for all node creation
481
+ mknod: function(path, mode, dev) {
482
+ var lookup = FS.lookupPath(path, { parent: true });
483
+ var parent = lookup.node;
484
+ var name = PATH.basename(path);
485
+ var err = FS.mayCreate(parent, name);
486
+ if (err) {
487
+ throw new FS.ErrnoError(err);
488
+ }
489
+ if (!parent.node_ops.mknod) {
490
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
491
+ }
492
+ return parent.node_ops.mknod(parent, name, mode, dev);
493
+ },
494
+ // helpers to create specific types of nodes
495
+ create: function(path, mode) {
496
+ mode = mode !== undefined ? mode : 0666;
497
+ mode &= {{{ cDefine('S_IALLUGO') }}};
498
+ mode |= {{{ cDefine('S_IFREG') }}};
499
+ return FS.mknod(path, mode, 0);
500
+ },
501
+ mkdir: function(path, mode) {
502
+ mode = mode !== undefined ? mode : 0777;
503
+ mode &= {{{ cDefine('S_IRWXUGO') }}} | {{{ cDefine('S_ISVTX') }}};
504
+ mode |= {{{ cDefine('S_IFDIR') }}};
505
+ return FS.mknod(path, mode, 0);
506
+ },
507
+ mkdev: function(path, mode, dev) {
508
+ if (typeof(dev) === 'undefined') {
509
+ dev = mode;
510
+ mode = 0666;
511
+ }
512
+ mode |= {{{ cDefine('S_IFCHR') }}};
513
+ return FS.mknod(path, mode, dev);
514
+ },
515
+ symlink: function(oldpath, newpath) {
516
+ var lookup = FS.lookupPath(newpath, { parent: true });
517
+ var parent = lookup.node;
518
+ var newname = PATH.basename(newpath);
519
+ var err = FS.mayCreate(parent, newname);
520
+ if (err) {
521
+ throw new FS.ErrnoError(err);
522
+ }
523
+ if (!parent.node_ops.symlink) {
524
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
525
+ }
526
+ return parent.node_ops.symlink(parent, newname, oldpath);
527
+ },
528
+ rename: function(old_path, new_path) {
529
+ var old_dirname = PATH.dirname(old_path);
530
+ var new_dirname = PATH.dirname(new_path);
531
+ var old_name = PATH.basename(old_path);
532
+ var new_name = PATH.basename(new_path);
533
+ // parents must exist
534
+ var lookup, old_dir, new_dir;
535
+ try {
536
+ lookup = FS.lookupPath(old_path, { parent: true });
537
+ old_dir = lookup.node;
538
+ lookup = FS.lookupPath(new_path, { parent: true });
539
+ new_dir = lookup.node;
540
+ } catch (e) {
541
+ throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
542
+ }
543
+ // need to be part of the same mount
544
+ if (old_dir.mount !== new_dir.mount) {
545
+ throw new FS.ErrnoError(ERRNO_CODES.EXDEV);
546
+ }
547
+ // source must exist
548
+ var old_node = FS.lookupNode(old_dir, old_name);
549
+ // old path should not be an ancestor of the new path
550
+ var relative = PATH.relative(old_path, new_dirname);
551
+ if (relative.charAt(0) !== '.') {
552
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
553
+ }
554
+ // new path should not be an ancestor of the old path
555
+ relative = PATH.relative(new_path, old_dirname);
556
+ if (relative.charAt(0) !== '.') {
557
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY);
558
+ }
559
+ // see if the new path already exists
560
+ var new_node;
561
+ try {
562
+ new_node = FS.lookupNode(new_dir, new_name);
563
+ } catch (e) {
564
+ // not fatal
565
+ }
566
+ // early out if nothing needs to change
567
+ if (old_node === new_node) {
568
+ return;
569
+ }
570
+ // we'll need to delete the old entry
571
+ var isdir = FS.isDir(old_node.mode);
572
+ var err = FS.mayDelete(old_dir, old_name, isdir);
573
+ if (err) {
574
+ throw new FS.ErrnoError(err);
575
+ }
576
+ // need delete permissions if we'll be overwriting.
577
+ // need create permissions if new doesn't already exist.
578
+ err = new_node ?
579
+ FS.mayDelete(new_dir, new_name, isdir) :
580
+ FS.mayCreate(new_dir, new_name);
581
+ if (err) {
582
+ throw new FS.ErrnoError(err);
583
+ }
584
+ if (!old_dir.node_ops.rename) {
585
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
586
+ }
587
+ if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
588
+ throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
589
+ }
590
+ // if we are going to change the parent, check write permissions
591
+ if (new_dir !== old_dir) {
592
+ err = FS.nodePermissions(old_dir, 'w');
593
+ if (err) {
594
+ throw new FS.ErrnoError(err);
595
+ }
596
+ }
597
+ // remove the node from the lookup hash
598
+ FS.hashRemoveNode(old_node);
599
+ // do the underlying fs rename
600
+ try {
601
+ old_dir.node_ops.rename(old_node, new_dir, new_name);
602
+ } catch (e) {
603
+ throw e;
604
+ } finally {
605
+ // add the node back to the hash (in case node_ops.rename
606
+ // changed its name)
607
+ FS.hashAddNode(old_node);
608
+ }
609
+ },
610
+ rmdir: function(path) {
611
+ var lookup = FS.lookupPath(path, { parent: true });
612
+ var parent = lookup.node;
613
+ var name = PATH.basename(path);
614
+ var node = FS.lookupNode(parent, name);
615
+ var err = FS.mayDelete(parent, name, true);
616
+ if (err) {
617
+ throw new FS.ErrnoError(err);
618
+ }
619
+ if (!parent.node_ops.rmdir) {
620
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
621
+ }
622
+ if (FS.isMountpoint(node)) {
623
+ throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
624
+ }
625
+ parent.node_ops.rmdir(parent, name);
626
+ FS.destroyNode(node);
627
+ },
628
+ readdir: function(path) {
629
+ var lookup = FS.lookupPath(path, { follow: true });
630
+ var node = lookup.node;
631
+ if (!node.node_ops.readdir) {
632
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR);
633
+ }
634
+ return node.node_ops.readdir(node);
635
+ },
636
+ unlink: function(path) {
637
+ var lookup = FS.lookupPath(path, { parent: true });
638
+ var parent = lookup.node;
639
+ var name = PATH.basename(path);
640
+ var node = FS.lookupNode(parent, name);
641
+ var err = FS.mayDelete(parent, name, false);
642
+ if (err) {
643
+ // POSIX says unlink should set EPERM, not EISDIR
644
+ if (err === ERRNO_CODES.EISDIR) err = ERRNO_CODES.EPERM;
645
+ throw new FS.ErrnoError(err);
646
+ }
647
+ if (!parent.node_ops.unlink) {
648
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
649
+ }
650
+ if (FS.isMountpoint(node)) {
651
+ throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
652
+ }
653
+ parent.node_ops.unlink(parent, name);
654
+ FS.destroyNode(node);
655
+ },
656
+ readlink: function(path) {
657
+ var lookup = FS.lookupPath(path, { follow: false });
658
+ var link = lookup.node;
659
+ if (!link.node_ops.readlink) {
660
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
661
+ }
662
+ return link.node_ops.readlink(link);
663
+ },
664
+ stat: function(path, dontFollow) {
665
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
666
+ var node = lookup.node;
667
+ if (!node.node_ops.getattr) {
668
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
669
+ }
670
+ return node.node_ops.getattr(node);
671
+ },
672
+ lstat: function(path) {
673
+ return FS.stat(path, true);
674
+ },
675
+ chmod: function(path, mode, dontFollow) {
676
+ var node;
677
+ if (typeof path === 'string') {
678
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
679
+ node = lookup.node;
680
+ } else {
681
+ node = path;
682
+ }
683
+ if (!node.node_ops.setattr) {
684
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
685
+ }
686
+ node.node_ops.setattr(node, {
687
+ mode: (mode & {{{ cDefine('S_IALLUGO') }}}) | (node.mode & ~{{{ cDefine('S_IALLUGO') }}}),
688
+ timestamp: Date.now()
689
+ });
690
+ },
691
+ lchmod: function(path, mode) {
692
+ FS.chmod(path, mode, true);
693
+ },
694
+ fchmod: function(fd, mode) {
695
+ var stream = FS.getStream(fd);
696
+ if (!stream) {
697
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
698
+ }
699
+ FS.chmod(stream.node, mode);
700
+ },
701
+ chown: function(path, uid, gid, dontFollow) {
702
+ var node;
703
+ if (typeof path === 'string') {
704
+ var lookup = FS.lookupPath(path, { follow: !dontFollow });
705
+ node = lookup.node;
706
+ } else {
707
+ node = path;
708
+ }
709
+ if (!node.node_ops.setattr) {
710
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
711
+ }
712
+ node.node_ops.setattr(node, {
713
+ timestamp: Date.now()
714
+ // we ignore the uid / gid for now
715
+ });
716
+ },
717
+ lchown: function(path, uid, gid) {
718
+ FS.chown(path, uid, gid, true);
719
+ },
720
+ fchown: function(fd, uid, gid) {
721
+ var stream = FS.getStream(fd);
722
+ if (!stream) {
723
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
724
+ }
725
+ FS.chown(stream.node, uid, gid);
726
+ },
727
+ truncate: function(path, len) {
728
+ if (len < 0) {
729
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
730
+ }
731
+ var node;
732
+ if (typeof path === 'string') {
733
+ var lookup = FS.lookupPath(path, { follow: true });
734
+ node = lookup.node;
735
+ } else {
736
+ node = path;
737
+ }
738
+ if (!node.node_ops.setattr) {
739
+ throw new FS.ErrnoError(ERRNO_CODES.EPERM);
740
+ }
741
+ if (FS.isDir(node.mode)) {
742
+ throw new FS.ErrnoError(ERRNO_CODES.EISDIR);
743
+ }
744
+ if (!FS.isFile(node.mode)) {
745
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
746
+ }
747
+ var err = FS.nodePermissions(node, 'w');
748
+ if (err) {
749
+ throw new FS.ErrnoError(err);
750
+ }
751
+ node.node_ops.setattr(node, {
752
+ size: len,
753
+ timestamp: Date.now()
754
+ });
755
+ },
756
+ ftruncate: function(fd, len) {
757
+ var stream = FS.getStream(fd);
758
+ if (!stream) {
759
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
760
+ }
761
+ if ((stream.flags & {{{ cDefine('O_ACCMODE') }}}) === {{{ cDefine('O_RDONLY')}}}) {
762
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
763
+ }
764
+ FS.truncate(stream.node, len);
765
+ },
766
+ utime: function(path, atime, mtime) {
767
+ var lookup = FS.lookupPath(path, { follow: true });
768
+ var node = lookup.node;
769
+ node.node_ops.setattr(node, {
770
+ timestamp: Math.max(atime, mtime)
771
+ });
772
+ },
773
+ open: function(path, flags, mode, fd_start, fd_end) {
774
+ path = PATH.normalize(path);
775
+ flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags;
776
+ mode = typeof mode === 'undefined' ? 0666 : mode;
777
+ if ((flags & {{{ cDefine('O_CREAT') }}})) {
778
+ mode = (mode & {{{ cDefine('S_IALLUGO') }}}) | {{{ cDefine('S_IFREG') }}};
779
+ } else {
780
+ mode = 0;
781
+ }
782
+ var node;
783
+ try {
784
+ var lookup = FS.lookupPath(path, {
785
+ follow: !(flags & {{{ cDefine('O_NOFOLLOW') }}})
786
+ });
787
+ node = lookup.node;
788
+ } catch (e) {
789
+ // ignore
790
+ }
791
+ // perhaps we need to create the node
792
+ if ((flags & {{{ cDefine('O_CREAT') }}})) {
793
+ if (node) {
794
+ // if O_CREAT and O_EXCL are set, error out if the node already exists
795
+ if ((flags & {{{ cDefine('O_EXCL') }}})) {
796
+ throw new FS.ErrnoError(ERRNO_CODES.EEXIST);
797
+ }
798
+ } else {
799
+ // node doesn't exist, try to create it
800
+ node = FS.mknod(path, mode, 0);
801
+ }
802
+ }
803
+ if (!node) {
804
+ throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
805
+ }
806
+ // can't truncate a device
807
+ if (FS.isChrdev(node.mode)) {
808
+ flags &= ~{{{ cDefine('O_TRUNC') }}};
809
+ }
810
+ // check permissions
811
+ var err = FS.mayOpen(node, flags);
812
+ if (err) {
813
+ throw new FS.ErrnoError(err);
814
+ }
815
+ // do truncation if necessary
816
+ if ((flags & {{{ cDefine('O_TRUNC')}}})) {
817
+ FS.truncate(node, 0);
818
+ }
819
+ // we've already handled these, don't pass down to the underlying vfs
820
+ flags &= ~({{{ cDefine('O_EXCL') }}} | {{{ cDefine('O_TRUNC') }}});
821
+
822
+ // register the stream with the filesystem
823
+ var stream = FS.createStream({
824
+ node: node,
825
+ path: FS.getPath(node), // we want the absolute path to the node
826
+ flags: flags,
827
+ seekable: true,
828
+ position: 0,
829
+ stream_ops: node.stream_ops,
830
+ // used by the file family libc calls (fopen, fwrite, ferror, etc.)
831
+ ungotten: [],
832
+ error: false
833
+ }, fd_start, fd_end);
834
+ // call the new stream's open function
835
+ if (stream.stream_ops.open) {
836
+ stream.stream_ops.open(stream);
837
+ }
838
+ if (Module['logReadFiles'] && !(flags & {{{ cDefine('O_WRONLY')}}})) {
839
+ if (!FS.readFiles) FS.readFiles = {};
840
+ if (!(path in FS.readFiles)) {
841
+ FS.readFiles[path] = 1;
842
+ Module['printErr']('read file: ' + path);
843
+ }
844
+ }
845
+ return stream;
846
+ },
847
+ close: function(stream) {
848
+ try {
849
+ if (stream.stream_ops.close) {
850
+ stream.stream_ops.close(stream);
851
+ }
852
+ } catch (e) {
853
+ throw e;
854
+ } finally {
855
+ FS.closeStream(stream.fd);
856
+ }
857
+ },
858
+ llseek: function(stream, offset, whence) {
859
+ if (!stream.seekable || !stream.stream_ops.llseek) {
860
+ throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
861
+ }
862
+ return stream.stream_ops.llseek(stream, offset, whence);
863
+ },
864
+ read: function(stream, buffer, offset, length, position) {
865
+ if (length < 0 || position < 0) {
866
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
867
+ }
868
+ if ((stream.flags & {{{ cDefine('O_ACCMODE') }}}) === {{{ cDefine('O_WRONLY')}}}) {
869
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
870
+ }
871
+ if (FS.isDir(stream.node.mode)) {
872
+ throw new FS.ErrnoError(ERRNO_CODES.EISDIR);
873
+ }
874
+ if (!stream.stream_ops.read) {
875
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
876
+ }
877
+ var seeking = true;
878
+ if (typeof position === 'undefined') {
879
+ position = stream.position;
880
+ seeking = false;
881
+ } else if (!stream.seekable) {
882
+ throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
883
+ }
884
+ var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
885
+ if (!seeking) stream.position += bytesRead;
886
+ return bytesRead;
887
+ },
888
+ write: function(stream, buffer, offset, length, position, canOwn) {
889
+ if (length < 0 || position < 0) {
890
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
891
+ }
892
+ if ((stream.flags & {{{ cDefine('O_ACCMODE') }}}) === {{{ cDefine('O_RDONLY')}}}) {
893
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
894
+ }
895
+ if (FS.isDir(stream.node.mode)) {
896
+ throw new FS.ErrnoError(ERRNO_CODES.EISDIR);
897
+ }
898
+ if (!stream.stream_ops.write) {
899
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
900
+ }
901
+ var seeking = true;
902
+ if (typeof position === 'undefined') {
903
+ position = stream.position;
904
+ seeking = false;
905
+ } else if (!stream.seekable) {
906
+ throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
907
+ }
908
+ if (stream.flags & {{{ cDefine('O_APPEND') }}}) {
909
+ // seek to the end before writing in append mode
910
+ FS.llseek(stream, 0, {{{ cDefine('SEEK_END') }}});
911
+ }
912
+ var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
913
+ if (!seeking) stream.position += bytesWritten;
914
+ return bytesWritten;
915
+ },
916
+ allocate: function(stream, offset, length) {
917
+ if (offset < 0 || length <= 0) {
918
+ throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
919
+ }
920
+ if ((stream.flags & {{{ cDefine('O_ACCMODE') }}}) === {{{ cDefine('O_RDONLY')}}}) {
921
+ throw new FS.ErrnoError(ERRNO_CODES.EBADF);
922
+ }
923
+ if (!FS.isFile(stream.node.mode) && !FS.isDir(node.mode)) {
924
+ throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
925
+ }
926
+ if (!stream.stream_ops.allocate) {
927
+ throw new FS.ErrnoError(ERRNO_CODES.EOPNOTSUPP);
928
+ }
929
+ stream.stream_ops.allocate(stream, offset, length);
930
+ },
931
+ mmap: function(stream, buffer, offset, length, position, prot, flags) {
932
+ // TODO if PROT is PROT_WRITE, make sure we have write access
933
+ if ((stream.flags & {{{ cDefine('O_ACCMODE') }}}) === {{{ cDefine('O_WRONLY')}}}) {
934
+ throw new FS.ErrnoError(ERRNO_CODES.EACCES);
935
+ }
936
+ if (!stream.stream_ops.mmap) {
937
+ throw new FS.errnoError(ERRNO_CODES.ENODEV);
938
+ }
939
+ return stream.stream_ops.mmap(stream, buffer, offset, length, position, prot, flags);
940
+ },
941
+ ioctl: function(stream, cmd, arg) {
942
+ if (!stream.stream_ops.ioctl) {
943
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTTY);
944
+ }
945
+ return stream.stream_ops.ioctl(stream, cmd, arg);
946
+ },
947
+ readFile: function(path, opts) {
948
+ opts = opts || {};
949
+ opts.flags = opts.flags || 'r';
950
+ opts.encoding = opts.encoding || 'binary';
951
+ var ret;
952
+ var stream = FS.open(path, opts.flags);
953
+ var stat = FS.stat(path);
954
+ var length = stat.size;
955
+ var buf = new Uint8Array(length);
956
+ FS.read(stream, buf, 0, length, 0);
957
+ if (opts.encoding === 'utf8') {
958
+ ret = '';
959
+ var utf8 = new Runtime.UTF8Processor();
960
+ for (var i = 0; i < length; i++) {
961
+ ret += utf8.processCChar(buf[i]);
962
+ }
963
+ } else if (opts.encoding === 'binary') {
964
+ ret = buf;
965
+ } else {
966
+ throw new Error('Invalid encoding type "' + opts.encoding + '"');
967
+ }
968
+ FS.close(stream);
969
+ return ret;
970
+ },
971
+ writeFile: function(path, data, opts) {
972
+ opts = opts || {};
973
+ opts.flags = opts.flags || 'w';
974
+ opts.encoding = opts.encoding || 'utf8';
975
+ var stream = FS.open(path, opts.flags, opts.mode);
976
+ if (opts.encoding === 'utf8') {
977
+ var utf8 = new Runtime.UTF8Processor();
978
+ var buf = new Uint8Array(utf8.processJSString(data));
979
+ FS.write(stream, buf, 0, buf.length, 0);
980
+ } else if (opts.encoding === 'binary') {
981
+ FS.write(stream, data, 0, data.length, 0);
982
+ } else {
983
+ throw new Error('Invalid encoding type "' + opts.encoding + '"');
984
+ }
985
+ FS.close(stream);
986
+ },
987
+
988
+ //
989
+ // module-level FS code
990
+ //
991
+ cwd: function() {
992
+ return FS.currentPath;
993
+ },
994
+ chdir: function(path) {
995
+ var lookup = FS.lookupPath(path, { follow: true });
996
+ if (!FS.isDir(lookup.node.mode)) {
997
+ throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR);
998
+ }
999
+ var err = FS.nodePermissions(lookup.node, 'x');
1000
+ if (err) {
1001
+ throw new FS.ErrnoError(err);
1002
+ }
1003
+ FS.currentPath = lookup.path;
1004
+ },
1005
+ createDefaultDirectories: function() {
1006
+ FS.mkdir('/tmp');
1007
+ },
1008
+ createDefaultDevices: function() {
1009
+ // create /dev
1010
+ FS.mkdir('/dev');
1011
+ // setup /dev/null
1012
+ FS.registerDevice(FS.makedev(1, 3), {
1013
+ read: function() { return 0; },
1014
+ write: function() { return 0; }
1015
+ });
1016
+ FS.mkdev('/dev/null', FS.makedev(1, 3));
1017
+ // setup /dev/tty and /dev/tty1
1018
+ // stderr needs to print output using Module['printErr']
1019
+ // so we register a second tty just for it.
1020
+ TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
1021
+ TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
1022
+ FS.mkdev('/dev/tty', FS.makedev(5, 0));
1023
+ FS.mkdev('/dev/tty1', FS.makedev(6, 0));
1024
+ // we're not going to emulate the actual shm device,
1025
+ // just create the tmp dirs that reside in it commonly
1026
+ FS.mkdir('/dev/shm');
1027
+ FS.mkdir('/dev/shm/tmp');
1028
+ },
1029
+ createStandardStreams: function() {
1030
+ // TODO deprecate the old functionality of a single
1031
+ // input / output callback and that utilizes FS.createDevice
1032
+ // and instead require a unique set of stream ops
1033
+
1034
+ // by default, we symlink the standard streams to the
1035
+ // default tty devices. however, if the standard streams
1036
+ // have been overwritten we create a unique device for
1037
+ // them instead.
1038
+ if (Module['stdin']) {
1039
+ FS.createDevice('/dev', 'stdin', Module['stdin']);
1040
+ } else {
1041
+ FS.symlink('/dev/tty', '/dev/stdin');
1042
+ }
1043
+ if (Module['stdout']) {
1044
+ FS.createDevice('/dev', 'stdout', null, Module['stdout']);
1045
+ } else {
1046
+ FS.symlink('/dev/tty', '/dev/stdout');
1047
+ }
1048
+ if (Module['stderr']) {
1049
+ FS.createDevice('/dev', 'stderr', null, Module['stderr']);
1050
+ } else {
1051
+ FS.symlink('/dev/tty1', '/dev/stderr');
1052
+ }
1053
+
1054
+ // open default streams for the stdin, stdout and stderr devices
1055
+ var stdin = FS.open('/dev/stdin', 'r');
1056
+ {{{ makeSetValue(makeGlobalUse('_stdin'), 0, 'stdin.fd', 'void*') }}};
1057
+ assert(stdin.fd === 1, 'invalid handle for stdin (' + stdin.fd + ')');
1058
+
1059
+ var stdout = FS.open('/dev/stdout', 'w');
1060
+ {{{ makeSetValue(makeGlobalUse('_stdout'), 0, 'stdout.fd', 'void*') }}};
1061
+ assert(stdout.fd === 2, 'invalid handle for stdout (' + stdout.fd + ')');
1062
+
1063
+ var stderr = FS.open('/dev/stderr', 'w');
1064
+ {{{ makeSetValue(makeGlobalUse('_stderr'), 0, 'stderr.fd', 'void*') }}};
1065
+ assert(stderr.fd === 3, 'invalid handle for stderr (' + stderr.fd + ')');
1066
+ },
1067
+ ensureErrnoError: function() {
1068
+ if (FS.ErrnoError) return;
1069
+ FS.ErrnoError = function ErrnoError(errno) {
1070
+ this.errno = errno;
1071
+ for (var key in ERRNO_CODES) {
1072
+ if (ERRNO_CODES[key] === errno) {
1073
+ this.code = key;
1074
+ break;
1075
+ }
1076
+ }
1077
+ this.message = ERRNO_MESSAGES[errno];
1078
+ this.stack = stackTrace();
1079
+ };
1080
+ FS.ErrnoError.prototype = new Error();
1081
+ FS.ErrnoError.prototype.constructor = FS.ErrnoError;
1082
+ },
1083
+ staticInit: function() {
1084
+ FS.ensureErrnoError();
1085
+
1086
+ FS.nameTable = new Array(4096);
1087
+
1088
+ FS.root = FS.createNode(null, '/', {{{ cDefine('S_IFDIR') }}} | 0777, 0);
1089
+ FS.mount(MEMFS, {}, '/');
1090
+
1091
+ FS.createDefaultDirectories();
1092
+ FS.createDefaultDevices();
1093
+ },
1094
+ init: function(input, output, error) {
1095
+ assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)');
1096
+ FS.init.initialized = true;
1097
+
1098
+ FS.ensureErrnoError();
1099
+
1100
+ // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
1101
+ Module['stdin'] = input || Module['stdin'];
1102
+ Module['stdout'] = output || Module['stdout'];
1103
+ Module['stderr'] = error || Module['stderr'];
1104
+
1105
+ FS.createStandardStreams();
1106
+ },
1107
+ quit: function() {
1108
+ FS.init.initialized = false;
1109
+ for (var i = 0; i < FS.streams.length; i++) {
1110
+ var stream = FS.streams[i];
1111
+ if (!stream) {
1112
+ continue;
1113
+ }
1114
+ FS.close(stream);
1115
+ }
1116
+ },
1117
+
1118
+ //
1119
+ // old v1 compatibility functions
1120
+ //
1121
+ getMode: function(canRead, canWrite) {
1122
+ var mode = 0;
1123
+ if (canRead) mode |= {{{ cDefine('S_IRUGO') }}} | {{{ cDefine('S_IXUGO') }}};
1124
+ if (canWrite) mode |= {{{ cDefine('S_IWUGO') }}};
1125
+ return mode;
1126
+ },
1127
+ joinPath: function(parts, forceRelative) {
1128
+ var path = PATH.join.apply(null, parts);
1129
+ if (forceRelative && path[0] == '/') path = path.substr(1);
1130
+ return path;
1131
+ },
1132
+ absolutePath: function(relative, base) {
1133
+ return PATH.resolve(base, relative);
1134
+ },
1135
+ standardizePath: function(path) {
1136
+ return PATH.normalize(path);
1137
+ },
1138
+ findObject: function(path, dontResolveLastLink) {
1139
+ var ret = FS.analyzePath(path, dontResolveLastLink);
1140
+ if (ret.exists) {
1141
+ return ret.object;
1142
+ } else {
1143
+ ___setErrNo(ret.error);
1144
+ return null;
1145
+ }
1146
+ },
1147
+ analyzePath: function(path, dontResolveLastLink) {
1148
+ // operate from within the context of the symlink's target
1149
+ try {
1150
+ var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
1151
+ path = lookup.path;
1152
+ } catch (e) {
1153
+ }
1154
+ var ret = {
1155
+ isRoot: false, exists: false, error: 0, name: null, path: null, object: null,
1156
+ parentExists: false, parentPath: null, parentObject: null
1157
+ };
1158
+ try {
1159
+ var lookup = FS.lookupPath(path, { parent: true });
1160
+ ret.parentExists = true;
1161
+ ret.parentPath = lookup.path;
1162
+ ret.parentObject = lookup.node;
1163
+ ret.name = PATH.basename(path);
1164
+ lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
1165
+ ret.exists = true;
1166
+ ret.path = lookup.path;
1167
+ ret.object = lookup.node;
1168
+ ret.name = lookup.node.name;
1169
+ ret.isRoot = lookup.path === '/';
1170
+ } catch (e) {
1171
+ ret.error = e.errno;
1172
+ };
1173
+ return ret;
1174
+ },
1175
+ createFolder: function(parent, name, canRead, canWrite) {
1176
+ var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name);
1177
+ var mode = FS.getMode(canRead, canWrite);
1178
+ return FS.mkdir(path, mode);
1179
+ },
1180
+ createPath: function(parent, path, canRead, canWrite) {
1181
+ parent = typeof parent === 'string' ? parent : FS.getPath(parent);
1182
+ var parts = path.split('/').reverse();
1183
+ while (parts.length) {
1184
+ var part = parts.pop();
1185
+ if (!part) continue;
1186
+ var current = PATH.join(parent, part);
1187
+ try {
1188
+ FS.mkdir(current);
1189
+ } catch (e) {
1190
+ // ignore EEXIST
1191
+ }
1192
+ parent = current;
1193
+ }
1194
+ return current;
1195
+ },
1196
+ createFile: function(parent, name, properties, canRead, canWrite) {
1197
+ var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name);
1198
+ var mode = FS.getMode(canRead, canWrite);
1199
+ return FS.create(path, mode);
1200
+ },
1201
+ createDataFile: function(parent, name, data, canRead, canWrite, canOwn) {
1202
+ var path = name ? PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name) : parent;
1203
+ var mode = FS.getMode(canRead, canWrite);
1204
+ var node = FS.create(path, mode);
1205
+ if (data) {
1206
+ if (typeof data === 'string') {
1207
+ var arr = new Array(data.length);
1208
+ for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
1209
+ data = arr;
1210
+ }
1211
+ // make sure we can write to the file
1212
+ FS.chmod(path, mode | {{{ cDefine('S_IWUGO') }}});
1213
+ var stream = FS.open(path, 'w');
1214
+ FS.write(stream, data, 0, data.length, 0, canOwn);
1215
+ FS.close(stream);
1216
+ FS.chmod(path, mode);
1217
+ }
1218
+ return node;
1219
+ },
1220
+ createDevice: function(parent, name, input, output) {
1221
+ var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name);
1222
+ var mode = FS.getMode(!!input, !!output);
1223
+ if (!FS.createDevice.major) FS.createDevice.major = 64;
1224
+ var dev = FS.makedev(FS.createDevice.major++, 0);
1225
+ // Create a fake device that a set of stream ops to emulate
1226
+ // the old behavior.
1227
+ FS.registerDevice(dev, {
1228
+ open: function(stream) {
1229
+ stream.seekable = false;
1230
+ },
1231
+ close: function(stream) {
1232
+ // flush any pending line data
1233
+ if (output && output.buffer && output.buffer.length) {
1234
+ output({{{ charCode('\n') }}});
1235
+ }
1236
+ },
1237
+ read: function(stream, buffer, offset, length, pos /* ignored */) {
1238
+ var bytesRead = 0;
1239
+ for (var i = 0; i < length; i++) {
1240
+ var result;
1241
+ try {
1242
+ result = input();
1243
+ } catch (e) {
1244
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
1245
+ }
1246
+ if (result === undefined && bytesRead === 0) {
1247
+ throw new FS.ErrnoError(ERRNO_CODES.EAGAIN);
1248
+ }
1249
+ if (result === null || result === undefined) break;
1250
+ bytesRead++;
1251
+ buffer[offset+i] = result;
1252
+ }
1253
+ if (bytesRead) {
1254
+ stream.node.timestamp = Date.now();
1255
+ }
1256
+ return bytesRead;
1257
+ },
1258
+ write: function(stream, buffer, offset, length, pos) {
1259
+ for (var i = 0; i < length; i++) {
1260
+ try {
1261
+ output(buffer[offset+i]);
1262
+ } catch (e) {
1263
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
1264
+ }
1265
+ }
1266
+ if (length) {
1267
+ stream.node.timestamp = Date.now();
1268
+ }
1269
+ return i;
1270
+ }
1271
+ });
1272
+ return FS.mkdev(path, mode, dev);
1273
+ },
1274
+ createLink: function(parent, name, target, canRead, canWrite) {
1275
+ var path = PATH.join(typeof parent === 'string' ? parent : FS.getPath(parent), name);
1276
+ return FS.symlink(target, path);
1277
+ },
1278
+ // Makes sure a file's contents are loaded. Returns whether the file has
1279
+ // been loaded successfully. No-op for files that have been loaded already.
1280
+ forceLoadFile: function(obj) {
1281
+ if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
1282
+ var success = true;
1283
+ if (typeof XMLHttpRequest !== 'undefined') {
1284
+ throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
1285
+ } else if (Module['read']) {
1286
+ // Command-line.
1287
+ try {
1288
+ // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as
1289
+ // read() will try to parse UTF8.
1290
+ obj.contents = intArrayFromString(Module['read'](obj.url), true);
1291
+ } catch (e) {
1292
+ success = false;
1293
+ }
1294
+ } else {
1295
+ throw new Error('Cannot load without read() or XMLHttpRequest.');
1296
+ }
1297
+ if (!success) ___setErrNo(ERRNO_CODES.EIO);
1298
+ return success;
1299
+ },
1300
+ // Creates a file record for lazy-loading from a URL. XXX This requires a synchronous
1301
+ // XHR, which is not possible in browsers except in a web worker! Use preloading,
1302
+ // either --preload-file in emcc or FS.createPreloadedFile
1303
+ createLazyFile: function(parent, name, url, canRead, canWrite) {
1304
+ if (typeof XMLHttpRequest !== 'undefined') {
1305
+ if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc';
1306
+ // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse.
1307
+ var LazyUint8Array = function() {
1308
+ this.lengthKnown = false;
1309
+ this.chunks = []; // Loaded chunks. Index is the chunk number
1310
+ }
1311
+ LazyUint8Array.prototype.get = function(idx) {
1312
+ if (idx > this.length-1 || idx < 0) {
1313
+ return undefined;
1314
+ }
1315
+ var chunkOffset = idx % this.chunkSize;
1316
+ var chunkNum = Math.floor(idx / this.chunkSize);
1317
+ return this.getter(chunkNum)[chunkOffset];
1318
+ }
1319
+ LazyUint8Array.prototype.setDataGetter = function(getter) {
1320
+ this.getter = getter;
1321
+ }
1322
+ LazyUint8Array.prototype.cacheLength = function() {
1323
+ // Find length
1324
+ var xhr = new XMLHttpRequest();
1325
+ xhr.open('HEAD', url, false);
1326
+ xhr.send(null);
1327
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
1328
+ var datalength = Number(xhr.getResponseHeader("Content-length"));
1329
+ var header;
1330
+ var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
1331
+ #if SMALL_XHR_CHUNKS
1332
+ var chunkSize = 1024; // Chunk size in bytes
1333
+ #else
1334
+ var chunkSize = 1024*1024; // Chunk size in bytes
1335
+ #endif
1336
+
1337
+ if (!hasByteServing) chunkSize = datalength;
1338
+
1339
+ // Function to get a range from the remote URL.
1340
+ var doXHR = (function(from, to) {
1341
+ if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
1342
+ if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!");
1343
+
1344
+ // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
1345
+ var xhr = new XMLHttpRequest();
1346
+ xhr.open('GET', url, false);
1347
+ if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
1348
+
1349
+ // Some hints to the browser that we want binary data.
1350
+ if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer';
1351
+ if (xhr.overrideMimeType) {
1352
+ xhr.overrideMimeType('text/plain; charset=x-user-defined');
1353
+ }
1354
+
1355
+ xhr.send(null);
1356
+ if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
1357
+ if (xhr.response !== undefined) {
1358
+ return new Uint8Array(xhr.response || []);
1359
+ } else {
1360
+ return intArrayFromString(xhr.responseText || '', true);
1361
+ }
1362
+ });
1363
+ var lazyArray = this;
1364
+ lazyArray.setDataGetter(function(chunkNum) {
1365
+ var start = chunkNum * chunkSize;
1366
+ var end = (chunkNum+1) * chunkSize - 1; // including this byte
1367
+ end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block
1368
+ if (typeof(lazyArray.chunks[chunkNum]) === "undefined") {
1369
+ lazyArray.chunks[chunkNum] = doXHR(start, end);
1370
+ }
1371
+ if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!");
1372
+ return lazyArray.chunks[chunkNum];
1373
+ });
1374
+
1375
+ this._length = datalength;
1376
+ this._chunkSize = chunkSize;
1377
+ this.lengthKnown = true;
1378
+ }
1379
+
1380
+ var lazyArray = new LazyUint8Array();
1381
+ Object.defineProperty(lazyArray, "length", {
1382
+ get: function() {
1383
+ if(!this.lengthKnown) {
1384
+ this.cacheLength();
1385
+ }
1386
+ return this._length;
1387
+ }
1388
+ });
1389
+ Object.defineProperty(lazyArray, "chunkSize", {
1390
+ get: function() {
1391
+ if(!this.lengthKnown) {
1392
+ this.cacheLength();
1393
+ }
1394
+ return this._chunkSize;
1395
+ }
1396
+ });
1397
+
1398
+ var properties = { isDevice: false, contents: lazyArray };
1399
+ } else {
1400
+ var properties = { isDevice: false, url: url };
1401
+ }
1402
+
1403
+ var node = FS.createFile(parent, name, properties, canRead, canWrite);
1404
+ // This is a total hack, but I want to get this lazy file code out of the
1405
+ // core of MEMFS. If we want to keep this lazy file concept I feel it should
1406
+ // be its own thin LAZYFS proxying calls to MEMFS.
1407
+ if (properties.contents) {
1408
+ node.contents = properties.contents;
1409
+ } else if (properties.url) {
1410
+ node.contents = null;
1411
+ node.url = properties.url;
1412
+ }
1413
+ // override each stream op with one that tries to force load the lazy file first
1414
+ var stream_ops = {};
1415
+ var keys = Object.keys(node.stream_ops);
1416
+ keys.forEach(function(key) {
1417
+ var fn = node.stream_ops[key];
1418
+ stream_ops[key] = function() {
1419
+ if (!FS.forceLoadFile(node)) {
1420
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
1421
+ }
1422
+ return fn.apply(null, arguments);
1423
+ };
1424
+ });
1425
+ // use a custom read function
1426
+ stream_ops.read = function(stream, buffer, offset, length, position) {
1427
+ if (!FS.forceLoadFile(node)) {
1428
+ throw new FS.ErrnoError(ERRNO_CODES.EIO);
1429
+ }
1430
+ var contents = stream.node.contents;
1431
+ if (position >= contents.length)
1432
+ return 0;
1433
+ var size = Math.min(contents.length - position, length);
1434
+ assert(size >= 0);
1435
+ if (contents.slice) { // normal array
1436
+ for (var i = 0; i < size; i++) {
1437
+ buffer[offset + i] = contents[position + i];
1438
+ }
1439
+ } else {
1440
+ for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR
1441
+ buffer[offset + i] = contents.get(position + i);
1442
+ }
1443
+ }
1444
+ return size;
1445
+ };
1446
+ node.stream_ops = stream_ops;
1447
+ return node;
1448
+ },
1449
+ // Preloads a file asynchronously. You can call this before run, for example in
1450
+ // preRun. run will be delayed until this file arrives and is set up.
1451
+ // If you call it after run(), you may want to pause the main loop until it
1452
+ // completes, if so, you can use the onload parameter to be notified when
1453
+ // that happens.
1454
+ // In addition to normally creating the file, we also asynchronously preload
1455
+ // the browser-friendly versions of it: For an image, we preload an Image
1456
+ // element and for an audio, and Audio. These are necessary for SDL_Image
1457
+ // and _Mixer to find the files in preloadedImages/Audios.
1458
+ // You can also call this with a typed array instead of a url. It will then
1459
+ // do preloading for the Image/Audio part, as if the typed array were the
1460
+ // result of an XHR that you did manually.
1461
+ createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn) {
1462
+ Browser.init();
1463
+ // TODO we should allow people to just pass in a complete filename instead
1464
+ // of parent and name being that we just join them anyways
1465
+ var fullname = name ? PATH.resolve(PATH.join(parent, name)) : parent;
1466
+ function processData(byteArray) {
1467
+ function finish(byteArray) {
1468
+ if (!dontCreateFile) {
1469
+ FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
1470
+ }
1471
+ if (onload) onload();
1472
+ removeRunDependency('cp ' + fullname);
1473
+ }
1474
+ var handled = false;
1475
+ Module['preloadPlugins'].forEach(function(plugin) {
1476
+ if (handled) return;
1477
+ if (plugin['canHandle'](fullname)) {
1478
+ plugin['handle'](byteArray, fullname, finish, function() {
1479
+ if (onerror) onerror();
1480
+ removeRunDependency('cp ' + fullname);
1481
+ });
1482
+ handled = true;
1483
+ }
1484
+ });
1485
+ if (!handled) finish(byteArray);
1486
+ }
1487
+ addRunDependency('cp ' + fullname);
1488
+ if (typeof url == 'string') {
1489
+ Browser.asyncLoad(url, function(byteArray) {
1490
+ processData(byteArray);
1491
+ }, onerror);
1492
+ } else {
1493
+ processData(url);
1494
+ }
1495
+ },
1496
+
1497
+ //
1498
+ // persistence
1499
+ //
1500
+ indexedDB: function() {
1501
+ return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
1502
+ },
1503
+
1504
+ DB_NAME: function() {
1505
+ return 'EM_FS_' + window.location.pathname;
1506
+ },
1507
+ DB_VERSION: 20,
1508
+ DB_STORE_NAME: 'FILE_DATA',
1509
+
1510
+ // asynchronously saves a list of files to an IndexedDB. The DB will be created if not already existing.
1511
+ saveFilesToDB: function(paths, onload, onerror) {
1512
+ onload = onload || function(){};
1513
+ onerror = onerror || function(){};
1514
+ var indexedDB = FS.indexedDB();
1515
+ try {
1516
+ var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
1517
+ } catch (e) {
1518
+ return onerror(e);
1519
+ }
1520
+ openRequest.onupgradeneeded = function() {
1521
+ console.log('creating db');
1522
+ var db = openRequest.result;
1523
+ db.createObjectStore(FS.DB_STORE_NAME);
1524
+ };
1525
+ openRequest.onsuccess = function() {
1526
+ var db = openRequest.result;
1527
+ var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite');
1528
+ var files = transaction.objectStore(FS.DB_STORE_NAME);
1529
+ var ok = 0, fail = 0, total = paths.length;
1530
+ function finish() {
1531
+ if (fail == 0) onload(); else onerror();
1532
+ }
1533
+ paths.forEach(function(path) {
1534
+ var putRequest = files.put(FS.analyzePath(path).object.contents, path);
1535
+ putRequest.onsuccess = function() { ok++; if (ok + fail == total) finish() };
1536
+ putRequest.onerror = function() { fail++; if (ok + fail == total) finish() };
1537
+ });
1538
+ transaction.onerror = onerror;
1539
+ };
1540
+ openRequest.onerror = onerror;
1541
+ },
1542
+
1543
+ // asychronously loads a file from IndexedDB.
1544
+ loadFilesFromDB: function(paths, onload, onerror) {
1545
+ onload = onload || function(){};
1546
+ onerror = onerror || function(){};
1547
+ var indexedDB = FS.indexedDB();
1548
+ try {
1549
+ var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
1550
+ } catch (e) {
1551
+ return onerror(e);
1552
+ }
1553
+ openRequest.onupgradeneeded = onerror; // no database to load from
1554
+ openRequest.onsuccess = function() {
1555
+ var db = openRequest.result;
1556
+ try {
1557
+ var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly');
1558
+ } catch(e) {
1559
+ onerror(e);
1560
+ return;
1561
+ }
1562
+ var files = transaction.objectStore(FS.DB_STORE_NAME);
1563
+ var ok = 0, fail = 0, total = paths.length;
1564
+ function finish() {
1565
+ if (fail == 0) onload(); else onerror();
1566
+ }
1567
+ paths.forEach(function(path) {
1568
+ var getRequest = files.get(path);
1569
+ getRequest.onsuccess = function() {
1570
+ if (FS.analyzePath(path).exists) {
1571
+ FS.unlink(path);
1572
+ }
1573
+ FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);
1574
+ ok++;
1575
+ if (ok + fail == total) finish();
1576
+ };
1577
+ getRequest.onerror = function() { fail++; if (ok + fail == total) finish() };
1578
+ });
1579
+ transaction.onerror = onerror;
1580
+ };
1581
+ openRequest.onerror = onerror;
1582
+ }
1583
+ }
1584
+ });
1585
+