@scriptc/cli-darwin-arm64 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/dist/THIRD_PARTY_NOTICES +1 -1
  2. package/dist/bin/scriptc +0 -0
  3. package/dist/bin/scriptc.json +1 -1
  4. package/dist/lib/declarations/scriptc-node-fallback.d.ts +25 -15
  5. package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
  6. package/dist/lib/llvm/package.json +1 -1
  7. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_array.o +0 -0
  8. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_assert.o +0 -0
  9. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_async.o +0 -0
  10. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_async_dyn.o +0 -0
  11. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bigint.o +0 -0
  12. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes.o +0 -0
  13. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
  14. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_child.o +0 -0
  15. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_console.o +0 -0
  16. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_console_native.o +0 -0
  17. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_dyn_invoke.o +0 -0
  18. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_error.o +0 -0
  19. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_events.o +0 -0
  20. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_exception.o +0 -0
  21. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_fetch.o +0 -0
  22. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_file_handle.o +0 -0
  23. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_grapheme.o +0 -0
  24. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_http.o +0 -0
  25. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_http2.o +0 -0
  26. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_json.o +0 -0
  27. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_lib.o +0 -0
  28. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_map.o +0 -0
  29. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_net.o +0 -0
  30. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_node_builtin.o +0 -0
  31. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_object.o +0 -0
  32. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_regex.o +0 -0
  33. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_stream.o +0 -0
  34. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_string.o +0 -0
  35. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_symbol.o +0 -0
  36. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_url.o +0 -0
  37. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_array.o +0 -0
  38. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_assert.o +0 -0
  39. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_async.o +0 -0
  40. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_async_dyn.o +0 -0
  41. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bigint.o +0 -0
  42. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
  43. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
  44. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_child.o +0 -0
  45. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_console.o +0 -0
  46. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_console_native.o +0 -0
  47. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_dyn_invoke.o +0 -0
  48. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_error.o +0 -0
  49. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_events.o +0 -0
  50. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_exception.o +0 -0
  51. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_file_handle.o +0 -0
  52. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_grapheme.o +0 -0
  53. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_http.o +0 -0
  54. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_http2.o +0 -0
  55. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_island.o +0 -0
  56. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
  57. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
  58. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_map.o +0 -0
  59. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_net.o +0 -0
  60. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_node_builtin.o +0 -0
  61. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_object.o +0 -0
  62. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
  63. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_stream.o +0 -0
  64. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_string.o +0 -0
  65. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_symbol.o +0 -0
  66. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_url.o +0 -0
  67. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  68. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  69. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_array.o +0 -0
  70. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_assert.o +0 -0
  71. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bigint.o +0 -0
  72. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
  73. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
  74. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_console_native.o +0 -0
  75. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_dyn_invoke.o +0 -0
  76. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_error.o +0 -0
  77. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_exception.o +0 -0
  78. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_grapheme.o +0 -0
  79. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
  80. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
  81. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_map.o +0 -0
  82. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_node_builtin.o +0 -0
  83. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_object.o +0 -0
  84. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
  85. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_string.o +0 -0
  86. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_symbol.o +0 -0
  87. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_url.o +0 -0
  88. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  89. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_array.o +0 -0
  90. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_assert.o +0 -0
  91. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bigint.o +0 -0
  92. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
  93. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
  94. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_console_native.o +0 -0
  95. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_dyn_invoke.o +0 -0
  96. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_error.o +0 -0
  97. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_exception.o +0 -0
  98. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_grapheme.o +0 -0
  99. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_json.o +0 -0
  100. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
  101. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_map.o +0 -0
  102. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_node_builtin.o +0 -0
  103. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_object.o +0 -0
  104. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
  105. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_string.o +0 -0
  106. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_symbol.o +0 -0
  107. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_url.o +0 -0
  108. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  109. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_array.o +0 -0
  110. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_assert.o +0 -0
  111. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bigint.o +0 -0
  112. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
  113. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
  114. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_console_native.o +0 -0
  115. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_dyn_invoke.o +0 -0
  116. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_error.o +0 -0
  117. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_exception.o +0 -0
  118. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_grapheme.o +0 -0
  119. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
  120. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
  121. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_map.o +0 -0
  122. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_node_builtin.o +0 -0
  123. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_object.o +0 -0
  124. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
  125. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_string.o +0 -0
  126. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_symbol.o +0 -0
  127. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_url.o +0 -0
  128. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  129. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_array.o +0 -0
  130. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_assert.o +0 -0
  131. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bigint.o +0 -0
  132. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
  133. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
  134. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_console_native.o +0 -0
  135. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_dyn_invoke.o +0 -0
  136. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_error.o +0 -0
  137. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_exception.o +0 -0
  138. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_grapheme.o +0 -0
  139. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
  140. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
  141. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_map.o +0 -0
  142. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_node_builtin.o +0 -0
  143. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_object.o +0 -0
  144. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
  145. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_string.o +0 -0
  146. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_symbol.o +0 -0
  147. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_url.o +0 -0
  148. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  149. package/dist/lib/runtime-darwin-arm64/artifacts/licenses/v8-number-radix.txt +61 -0
  150. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_array.o +0 -0
  151. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_assert.o +0 -0
  152. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_async.o +0 -0
  153. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_async_dyn.o +0 -0
  154. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bigint.o +0 -0
  155. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes.o +0 -0
  156. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
  157. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_child.o +0 -0
  158. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_console.o +0 -0
  159. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_console_native.o +0 -0
  160. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_dyn_invoke.o +0 -0
  161. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_error.o +0 -0
  162. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_events.o +0 -0
  163. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_exception.o +0 -0
  164. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_fetch.o +0 -0
  165. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_file_handle.o +0 -0
  166. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_grapheme.o +0 -0
  167. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_http.o +0 -0
  168. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_http2.o +0 -0
  169. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_json.o +0 -0
  170. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_lib.o +0 -0
  171. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_map.o +0 -0
  172. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_net.o +0 -0
  173. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_node_builtin.o +0 -0
  174. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_object.o +0 -0
  175. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_regex.o +0 -0
  176. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_stream.o +0 -0
  177. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_string.o +0 -0
  178. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_symbol.o +0 -0
  179. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_url.o +0 -0
  180. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_array.o +0 -0
  181. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_assert.o +0 -0
  182. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_async.o +0 -0
  183. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_async_dyn.o +0 -0
  184. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bigint.o +0 -0
  185. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
  186. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
  187. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_child.o +0 -0
  188. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_console.o +0 -0
  189. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_console_native.o +0 -0
  190. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_dyn_invoke.o +0 -0
  191. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_error.o +0 -0
  192. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_events.o +0 -0
  193. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_exception.o +0 -0
  194. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_file_handle.o +0 -0
  195. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_grapheme.o +0 -0
  196. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_http.o +0 -0
  197. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_http2.o +0 -0
  198. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_island.o +0 -0
  199. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
  200. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
  201. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_map.o +0 -0
  202. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_net.o +0 -0
  203. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_node_builtin.o +0 -0
  204. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_object.o +0 -0
  205. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
  206. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_stream.o +0 -0
  207. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_string.o +0 -0
  208. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_symbol.o +0 -0
  209. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_url.o +0 -0
  210. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  211. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  212. package/dist/lib/runtime-darwin-arm64/package.json +1 -1
  213. package/dist/lib/runtime-darwin-arm64/runtime-pack.json +529 -525
  214. package/dist/lib/runtime-sources/package.json +1 -1
  215. package/dist/lib/runtime-sources/src/scr_array.c +16 -0
  216. package/dist/lib/runtime-sources/src/scr_assert.c +1 -0
  217. package/dist/lib/runtime-sources/src/scr_async.c +26 -1
  218. package/dist/lib/runtime-sources/src/scr_async_dyn.c +90 -16
  219. package/dist/lib/runtime-sources/src/scr_bigint.c +8 -0
  220. package/dist/lib/runtime-sources/src/scr_bytes.c +205 -41
  221. package/dist/lib/runtime-sources/src/scr_bytes_io.c +581 -12
  222. package/dist/lib/runtime-sources/src/scr_child.c +544 -17
  223. package/dist/lib/runtime-sources/src/scr_console.c +1 -1
  224. package/dist/lib/runtime-sources/src/scr_dyn_invoke.c +164 -31
  225. package/dist/lib/runtime-sources/src/scr_error.c +52 -5
  226. package/dist/lib/runtime-sources/src/scr_exception.c +21 -5
  227. package/dist/lib/runtime-sources/src/scr_fetch.c +266 -2
  228. package/dist/lib/runtime-sources/src/scr_http.c +3 -0
  229. package/dist/lib/runtime-sources/src/scr_island.c +38 -13
  230. package/dist/lib/runtime-sources/src/scr_json.c +1149 -91
  231. package/dist/lib/runtime-sources/src/scr_map.c +47 -0
  232. package/dist/lib/runtime-sources/src/scr_node_builtin.c +10 -0
  233. package/dist/lib/runtime-sources/src/scr_object.c +11 -0
  234. package/dist/lib/runtime-sources/src/scr_regex.c +108 -69
  235. package/dist/lib/runtime-sources/src/scr_runtime.h +190 -33
  236. package/dist/lib/runtime-sources/src/scr_stream.c +197 -0
  237. package/dist/lib/runtime-sources/src/scr_string.c +16 -1
  238. package/dist/lib/runtime-sources/src/scr_symbol.c +5 -0
  239. package/dist/lib/runtime-sources/src/scr_text_decoder_labels.h +225 -0
  240. package/dist/lib/runtime-sources/src/scr_url.c +172 -3
  241. package/dist/lib/runtime-sources/vendor/v8-number-radix/LICENSE +61 -0
  242. package/package.json +1 -1
@@ -23,10 +23,17 @@
23
23
  */
24
24
  #include "scr_runtime.h"
25
25
 
26
+ static SCR_TL ScrDyn *scr_builtin_object_prototype;
27
+
26
28
  /* Constructor capsules expose identity and name/length, but do not model
27
29
  * per-class static property tables yet. Never report a fabricated empty view. */
28
30
  static bool scr_dyn_class_reflection_fence(const ScrDyn *value) {
29
- if (!value || value->kind != SCR_DYN_FUNC || !value->v.fn.class_obj) return false;
31
+ if (value && value == scr_builtin_object_prototype) {
32
+ static const char message[] = "scriptc: Object.prototype reflection and mutation are not supported yet";
33
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
34
+ return true;
35
+ }
36
+ if (!value || value->kind != SCR_DYN_FUNC || !value->v.fn.class_obj || value->v.fn.class_obj->static_data) return false;
30
37
  static const char message[] = "scriptc: class reflection through unknown is not supported";
31
38
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
32
39
  return true;
@@ -49,12 +56,22 @@ static void scr_json_oom(void) {
49
56
  }
50
57
 
51
58
  static SCR_TL ScrDyn *scr_iterator_symbol;
59
+ static SCR_TL ScrDyn *scr_async_iterator_symbol;
60
+ static bool scr_dyn_generator(const ScrDyn *value) {
61
+ return value && value->kind == SCR_DYN_TYPED_REF &&
62
+ (!strncmp(value->v.typed_ref.type_key, "generator<", 10) || !strncmp(value->v.typed_ref.type_key, "async-generator<", 16));
63
+ }
64
+ static bool scr_dyn_generator_symbol(const ScrDyn *value, const ScrDyn *key) {
65
+ const ScrDyn *symbol = value->v.typed_ref.type_key[0] == 'a' ? scr_async_iterator_symbol : scr_iterator_symbol;
66
+ return symbol && key->v.symbol.value == symbol->v.symbol.value;
67
+ }
52
68
  static ScrDyn *scr_builtin_iterator_method(const ScrDyn *value);
53
69
  static bool scr_builtin_iterable(const ScrDyn *value) {
54
70
  return value->kind == SCR_DYN_ARR || value->kind == SCR_DYN_STR || value->kind == SCR_DYN_BYTES ||
71
+ (scr_dyn_generator(value) && value->v.typed_ref.type_key[0] != 'a') ||
55
72
  (value->kind == SCR_DYN_TYPED_REF && scr_dyn_isl_is_array(value)) ||
56
- (value->kind == SCR_DYN_HANDLE && (value->v.handle.tag == SCR_DYNH_ITERATOR ||
57
- scr_dyn_handle_ops_of(value)->iter_pack));
73
+ (value->kind == SCR_DYN_HANDLE && (value->v.handle.tag == SCR_DYNH_ITERATOR || value->v.handle.tag == SCR_DYNH_MAP || value->v.handle.tag == SCR_DYNH_SET ||
74
+ scr_dyn_handle_ops_of(value)->iter_pack || scr_dyn_handle_ops_of(value)->iter_step));
58
75
  }
59
76
  static bool scr_iterator_object(const ScrDyn *value) {
60
77
  switch (value->kind) {
@@ -82,6 +99,17 @@ static void scr_iterator_symbol_cleanup(void) {
82
99
  scr_iterator_symbol = NULL;
83
100
  }
84
101
 
102
+ static void scr_async_iterator_symbol_cleanup(void) {
103
+ scr_dyn_release(scr_async_iterator_symbol);
104
+ scr_async_iterator_symbol = NULL;
105
+ }
106
+
107
+ void scr_dyn_install_async_iterator_symbol(ScrDyn *key) {
108
+ if (scr_async_iterator_symbol) return;
109
+ scr_async_iterator_symbol = scr_dyn_retain(key);
110
+ scr_atexit(scr_async_iterator_symbol_cleanup);
111
+ }
112
+
85
113
  void scr_dyn_install_iterator_symbol(ScrDyn *key) {
86
114
  if (scr_iterator_symbol) return;
87
115
  scr_iterator_symbol = scr_dyn_retain(key);
@@ -408,6 +436,8 @@ void scr_dyn_trace_v(void *ptr, ScrTraceVisit visit, void *ctx) {
408
436
  case SCR_DYN_TYPED_REF:
409
437
  visit(d->v.typed_ref.materialized, ctx);
410
438
  if (d->v.typed_ref.traced) visit(d->v.typed_ref.ptr, ctx);
439
+ for (ScrDynTypedCast *cast = d->v.typed_ref.casts; cast; cast = cast->next)
440
+ if (cast->traced) visit(cast->ptr, ctx);
411
441
  break;
412
442
  case SCR_DYN_HANDLE:
413
443
  if (d->v.handle.traced) visit(d->v.handle.ptr, ctx);
@@ -416,6 +446,56 @@ void scr_dyn_trace_v(void *ptr, ScrTraceVisit visit, void *ctx) {
416
446
  }
417
447
  }
418
448
 
449
+ typedef struct ScrTypedRefIdentity {
450
+ ScrDyn *value; /* weak; removed before capsule disposal */
451
+ struct ScrTypedRefIdentity *next;
452
+ } ScrTypedRefIdentity;
453
+ static SCR_TL ScrTypedRefIdentity **scr_typed_ref_identities;
454
+ static SCR_TL size_t scr_typed_ref_capacity, scr_typed_ref_count;
455
+ static size_t scr_typed_ref_bucket(void *ptr) {
456
+ uintptr_t hash = (uintptr_t)ptr >> 4;
457
+ hash ^= hash >> 17;
458
+ hash *= (uintptr_t)0x9e3779b1u;
459
+ hash ^= hash >> 13;
460
+ return hash & (scr_typed_ref_capacity - 1);
461
+ }
462
+ static void scr_typed_ref_reserve(void) {
463
+ if (scr_typed_ref_capacity && scr_typed_ref_count < scr_typed_ref_capacity) return;
464
+ size_t old_capacity = scr_typed_ref_capacity;
465
+ ScrTypedRefIdentity **old = scr_typed_ref_identities;
466
+ scr_typed_ref_capacity = old_capacity ? old_capacity * 2 : 1024;
467
+ scr_typed_ref_identities = calloc(scr_typed_ref_capacity, sizeof *scr_typed_ref_identities);
468
+ if (!scr_typed_ref_identities) scr_json_oom();
469
+ for (size_t i = 0; i < old_capacity; i++) {
470
+ ScrTypedRefIdentity *entry = old[i];
471
+ while (entry) {
472
+ ScrTypedRefIdentity *next = entry->next;
473
+ size_t bucket = scr_typed_ref_bucket(entry->value->v.typed_ref.ptr);
474
+ entry->next = scr_typed_ref_identities[bucket];
475
+ scr_typed_ref_identities[bucket] = entry;
476
+ entry = next;
477
+ }
478
+ }
479
+ free(old);
480
+ }
481
+ static void scr_typed_ref_forget(ScrDyn *value) {
482
+ ScrTypedRefIdentity **link = &scr_typed_ref_identities[scr_typed_ref_bucket(value->v.typed_ref.ptr)];
483
+ while (*link) {
484
+ if ((*link)->value == value) {
485
+ ScrTypedRefIdentity *old = *link;
486
+ *link = old->next;
487
+ free(old);
488
+ if (--scr_typed_ref_count == 0) {
489
+ free(scr_typed_ref_identities);
490
+ scr_typed_ref_identities = NULL;
491
+ scr_typed_ref_capacity = 0;
492
+ }
493
+ return;
494
+ }
495
+ link = &(*link)->next;
496
+ }
497
+ }
498
+
419
499
  static void scr_dyn_gcfree(void *ptr);
420
500
 
421
501
  static ScrDyn *scr_dyn_alloc(ScrDynKind kind) {
@@ -527,11 +607,12 @@ static void scr_dyn_dispose(ScrDyn *d, bool collected) {
527
607
  scr_dyn_jsval_ops()->release(d->v.jsval.cell);
528
608
  break;
529
609
  case SCR_DYN_TYPED_REF:
610
+ scr_typed_ref_forget(d);
530
611
  if (!collected) scr_dyn_release(d->v.typed_ref.materialized);
531
612
  while (d->v.typed_ref.casts) {
532
613
  ScrDynTypedCast *cast = d->v.typed_ref.casts;
533
614
  d->v.typed_ref.casts = cast->next;
534
- cast->release(cast->ptr);
615
+ if (!collected || !cast->traced) cast->release(cast->ptr);
535
616
  free(cast);
536
617
  }
537
618
  if (!collected || !d->v.typed_ref.traced) d->v.typed_ref.release(d->v.typed_ref.ptr);
@@ -793,6 +874,10 @@ ScrDyn *scr_dyn_iter_pack(const ScrDyn *src, const ScrStr *msg) {
793
874
  return scr_dyn_not_iterable(src, msg);
794
875
  }
795
876
 
877
+ ScrDyn *scr_dyn_jsval_iter_n(const ScrDyn *src, double count) {
878
+ return scr_dyn_jsval_ops()->iter_n(src->v.jsval.cell, count);
879
+ }
880
+
796
881
  /* The for-of-over-dyn pack accessors: the emitted index loop drives them
797
882
  * over a scr_dyn_iter_pack result (ARR by construction — the defensive
798
883
  * arms cover nothing reachable from that lowering). Never throw. */
@@ -966,6 +1051,21 @@ static void scr_builtin_array_prototype_cleanup(void) {
966
1051
  scr_dyn_release(prototype);
967
1052
  }
968
1053
 
1054
+ static void scr_builtin_object_prototype_cleanup(void) {
1055
+ ScrDyn *prototype = scr_builtin_object_prototype;
1056
+ scr_builtin_object_prototype = NULL;
1057
+ scr_dyn_release(prototype);
1058
+ }
1059
+
1060
+ ScrDyn *scr_dyn_object_prototype(void) {
1061
+ if (!scr_builtin_object_prototype) {
1062
+ scr_builtin_object_prototype = scr_dyn_alloc(SCR_DYN_OBJ);
1063
+ scr_builtin_object_prototype->null_proto = true;
1064
+ scr_atexit(scr_builtin_object_prototype_cleanup);
1065
+ }
1066
+ return scr_dyn_retain(scr_builtin_object_prototype);
1067
+ }
1068
+
969
1069
  ScrDyn *scr_dyn_array_prototype_base(void) {
970
1070
  if (!scr_builtin_array_prototype) {
971
1071
  scr_builtin_array_prototype = scr_dyn_alloc(SCR_DYN_ARR);
@@ -1005,7 +1105,7 @@ ScrDyn *scr_dyn_new_obj_null_proto(void) {
1005
1105
  }
1006
1106
 
1007
1107
  ScrDyn *scr_dyn_obj_create(ScrDyn *prototype) {
1008
- if (scr_dyn_class_reflection_fence(prototype)) return NULL;
1108
+ if (prototype != scr_builtin_object_prototype && scr_dyn_class_reflection_fence(prototype)) return NULL;
1009
1109
  if (prototype->kind != SCR_DYN_OBJ && prototype->kind != SCR_DYN_ARR && prototype->kind != SCR_DYN_NULL) {
1010
1110
  static const char message[] = "Object prototype may only be an Object or null";
1011
1111
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
@@ -1017,7 +1117,15 @@ ScrDyn *scr_dyn_obj_create(ScrDyn *prototype) {
1017
1117
  }
1018
1118
 
1019
1119
  ScrDyn *scr_dyn_get_prototype(ScrDyn *object) {
1120
+ if (object == scr_builtin_object_prototype) return scr_dyn_new_null();
1020
1121
  if (scr_dyn_class_reflection_fence(object)) return NULL;
1122
+ if (object->kind == SCR_DYN_TYPED_REF && strncmp(object->v.typed_ref.type_key, "object:", 7)) {
1123
+ ScrDyn *view = scr_dyn_typed_ref_materialize(object);
1124
+ if (!view) return NULL;
1125
+ ScrDyn *result = scr_dyn_get_prototype(view);
1126
+ scr_dyn_release(view);
1127
+ return result;
1128
+ }
1021
1129
  if (object->kind == SCR_DYN_FUNC && object->v.fn.clo->props) {
1022
1130
  ScrDyn *table = scr_dyn_fn_properties(object);
1023
1131
  ScrDyn *result = table->prototype ? scr_dyn_retain(table->prototype)
@@ -1032,7 +1140,9 @@ ScrDyn *scr_dyn_get_prototype(ScrDyn *object) {
1032
1140
  if (object->kind == SCR_DYN_OBJ) {
1033
1141
  if (object->prototype) return scr_dyn_retain(object->prototype);
1034
1142
  if (object->null_proto) return scr_dyn_new_null();
1143
+ return scr_dyn_object_prototype();
1035
1144
  }
1145
+ if (object == scr_builtin_array_prototype) return scr_dyn_object_prototype();
1036
1146
  if (object->kind == SCR_DYN_NULL || object->kind == SCR_DYN_UNDEF) {
1037
1147
  static const char message[] = "Cannot convert undefined or null to object";
1038
1148
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
@@ -1045,6 +1155,15 @@ ScrDyn *scr_dyn_get_prototype(ScrDyn *object) {
1045
1155
 
1046
1156
  ScrDyn *scr_dyn_set_prototype(ScrDyn *object, ScrDyn *prototype) {
1047
1157
  if (scr_dyn_class_reflection_fence(object) || scr_dyn_class_reflection_fence(prototype)) return NULL;
1158
+ if (object->kind == SCR_DYN_TYPED_REF) {
1159
+ ScrDyn *view = scr_dyn_typed_ref_materialize(object);
1160
+ if (scr_exc_pending()) { scr_dyn_release(view); return NULL; }
1161
+ ScrDyn *result = scr_dyn_set_prototype(view, prototype);
1162
+ scr_dyn_release(view);
1163
+ if (!result) return NULL;
1164
+ scr_dyn_release(result);
1165
+ return scr_dyn_retain(object);
1166
+ }
1048
1167
  if (object->kind == SCR_DYN_FUNC) {
1049
1168
  if (prototype->kind == SCR_DYN_FUNC && object->v.fn.clo == prototype->v.fn.clo) {
1050
1169
  static const char message[] = "Cyclic __proto__ value";
@@ -1059,17 +1178,23 @@ ScrDyn *scr_dyn_set_prototype(ScrDyn *object, ScrDyn *prototype) {
1059
1178
  return scr_dyn_retain(object);
1060
1179
  }
1061
1180
  if (object->kind != SCR_DYN_OBJ ||
1062
- (prototype->kind != SCR_DYN_OBJ && prototype->kind != SCR_DYN_NULL)) {
1181
+ (prototype->kind != SCR_DYN_OBJ && prototype->kind != SCR_DYN_FUNC && prototype->kind != SCR_DYN_NULL)) {
1063
1182
  static const char message[] = "Object prototype may only be an Object or null";
1064
1183
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
1065
1184
  return NULL;
1066
1185
  }
1067
- for (ScrDyn *current = prototype; current && current->kind == SCR_DYN_OBJ; current = current->prototype) {
1186
+ for (ScrDyn *current = prototype; current;) {
1187
+ if (current->kind == SCR_DYN_FUNC) {
1188
+ ScrDyn *table = scr_dyn_fn_properties(current);
1189
+ current = table;
1190
+ scr_dyn_release(table); /* the function owns the table */
1191
+ }
1068
1192
  if (current == object) {
1069
1193
  static const char message[] = "Cyclic __proto__ value";
1070
1194
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
1071
1195
  return NULL;
1072
1196
  }
1197
+ current = current->prototype;
1073
1198
  }
1074
1199
  if (object->non_extensible && (prototype->kind == SCR_DYN_NULL ? object->prototype != NULL || !object->null_proto : object->prototype != prototype)) {
1075
1200
  static const char message[] = "Cannot set prototype of a non-extensible object";
@@ -1131,6 +1256,12 @@ bool scr_dyn_is_sealed(const ScrDyn *object) {
1131
1256
 
1132
1257
  static const ScrDyn *scr_dyn_property_owner(const ScrDyn *object, const char *key, size_t length) {
1133
1258
  for (const ScrDyn *current = object; current; current = current->prototype) {
1259
+ if (current->kind == SCR_DYN_FUNC) {
1260
+ ScrDyn *table = scr_dyn_fn_properties(current);
1261
+ const ScrDyn *owner = scr_dyn_property_owner(table, key, length);
1262
+ scr_dyn_release(table);
1263
+ return owner;
1264
+ }
1134
1265
  if (current->kind != SCR_DYN_OBJ) continue;
1135
1266
  for (size_t i = 0; i < current->v.obj.len; i++) {
1136
1267
  const ScrDynEntry *entry = &current->v.obj.entries[i];
@@ -1143,7 +1274,7 @@ static const ScrDyn *scr_dyn_property_owner(const ScrDyn *object, const char *ke
1143
1274
  static bool scr_dyn_has_object_prototype(const ScrDyn *object) {
1144
1275
  const ScrDyn *current = object;
1145
1276
  while (current->prototype) current = current->prototype;
1146
- return !current->null_proto;
1277
+ return current == scr_builtin_object_prototype || !current->null_proto;
1147
1278
  }
1148
1279
 
1149
1280
  void scr_dyn_proxy_unsupported(const char *operation) {
@@ -1168,9 +1299,20 @@ ScrDyn *scr_dyn_proxy_new(const ScrDyn *target, const ScrDyn *handler) {
1168
1299
  scr_throw_error_msg(SCR_ERR_TYPE, msg, sizeof msg - 1);
1169
1300
  return NULL;
1170
1301
  }
1171
- /* Plain dyn objects expose their live property descriptors. Other
1172
- * representations cannot promise the Proxy invariants or live identity. */
1173
- if (target->kind != SCR_DYN_OBJ || handler->kind != SCR_DYN_OBJ) {
1302
+ bool native_record = target->kind == SCR_DYN_TYPED_REF &&
1303
+ strncmp(target->v.typed_ref.type_key, "record:", 7) == 0;
1304
+ if (native_record) {
1305
+ ScrDyn *view = scr_dyn_typed_ref_materialize(target);
1306
+ bool plain = view && view->kind == SCR_DYN_OBJ;
1307
+ if (plain) for (size_t i = 0; i < view->v.obj.len; i++) {
1308
+ ScrDynEntry *entry = &view->v.obj.entries[i];
1309
+ if (entry->accessor || !entry->configurable || !entry->writable) plain = false;
1310
+ }
1311
+ scr_dyn_release(view);
1312
+ if (scr_exc_pending()) return NULL;
1313
+ native_record = plain;
1314
+ }
1315
+ if ((target->kind != SCR_DYN_OBJ && !native_record) || handler->kind != SCR_DYN_OBJ) {
1174
1316
  scr_dyn_proxy_unsupported("non-plain targets or handlers");
1175
1317
  return NULL;
1176
1318
  }
@@ -1198,6 +1340,11 @@ static ScrDyn *scr_dyn_proxy_trap(const ScrDyn *proxy, const char *name) {
1198
1340
  scr_dyn_release(method);
1199
1341
  return NULL;
1200
1342
  }
1343
+ if (proxy->v.proxy.target->kind == SCR_DYN_TYPED_REF) {
1344
+ scr_dyn_release(method);
1345
+ scr_dyn_proxy_unsupported("traps over typed native targets");
1346
+ return NULL;
1347
+ }
1201
1348
  return method;
1202
1349
  }
1203
1350
 
@@ -1227,6 +1374,12 @@ ScrDyn *scr_dyn_proxy_get(const ScrDyn *proxy, const ScrStr *key) {
1227
1374
  if (scr_exc_pending()) return NULL;
1228
1375
  if (!trap) {
1229
1376
  ScrDyn *target = proxy->v.proxy.target;
1377
+ if (target->kind == SCR_DYN_TYPED_REF) {
1378
+ ScrDyn *view = scr_dyn_typed_ref_materialize(target);
1379
+ ScrDyn *result = scr_exc_pending() ? NULL : scr_dyn_obj_read_receiver(view, key->data, key->len, proxy);
1380
+ scr_dyn_release(view);
1381
+ return result;
1382
+ }
1230
1383
  if (!scr_dyn_obj_get(target, key->data, key->len) && scr_dyn_object_proto_key(target, key)) {
1231
1384
  scr_dyn_proxy_unsupported("inherited Object.prototype member reads");
1232
1385
  return NULL;
@@ -1432,6 +1585,10 @@ void scr_dyn_proxy_set(ScrDyn *proxy, ScrStr *key, ScrDyn *value) {
1432
1585
  ScrDyn *trap = scr_dyn_proxy_trap(proxy, "set");
1433
1586
  if (scr_exc_pending()) return;
1434
1587
  if (!trap) {
1588
+ if (proxy->v.proxy.target->kind == SCR_DYN_TYPED_REF) {
1589
+ scr_dyn_key_set(proxy->v.proxy.target, key, value);
1590
+ return;
1591
+ }
1435
1592
  /* OrdinarySet uses the Proxy receiver's [[GetOwnProperty]] and
1436
1593
  * [[DefineOwnProperty]]. Keep that boundary explicit for now. */
1437
1594
  scr_dyn_proxy_unsupported("assignment without a set trap");
@@ -1498,6 +1655,15 @@ ScrDyn *scr_dyn_new_typed_ref(
1498
1655
  const char *type_key, size_t type_key_len,
1499
1656
  ScrDyn *(*materialize)(void *),
1500
1657
  void (*commit)(void *, const ScrDyn *)) {
1658
+ scr_typed_ref_reserve();
1659
+ size_t bucket = scr_typed_ref_bucket(ptr);
1660
+ for (ScrTypedRefIdentity *entry = scr_typed_ref_identities[bucket]; entry; entry = entry->next) {
1661
+ ScrDyn *value = entry->value;
1662
+ if (value->v.typed_ref.ptr == ptr && value->v.typed_ref.retain == retain &&
1663
+ value->v.typed_ref.materialize == materialize && value->v.typed_ref.commit == commit &&
1664
+ value->v.typed_ref.type_key_len == type_key_len && !memcmp(value->v.typed_ref.type_key, type_key, type_key_len))
1665
+ return scr_dyn_retain(value);
1666
+ }
1501
1667
  ScrDyn *d = scr_dyn_alloc(SCR_DYN_TYPED_REF);
1502
1668
  d->v.typed_ref.ptr = retain(ptr);
1503
1669
  d->v.typed_ref.retain = retain;
@@ -1509,6 +1675,12 @@ ScrDyn *scr_dyn_new_typed_ref(
1509
1675
  d->v.typed_ref.materialized = NULL;
1510
1676
  d->v.typed_ref.casts = NULL;
1511
1677
  d->v.typed_ref.traced = false;
1678
+ d->v.typed_ref.observed = false;
1679
+ ScrTypedRefIdentity *identity = malloc(sizeof *identity);
1680
+ if (!identity) scr_json_oom();
1681
+ identity->value = d; identity->next = scr_typed_ref_identities[bucket];
1682
+ scr_typed_ref_identities[bucket] = identity;
1683
+ scr_typed_ref_count++;
1512
1684
  return d;
1513
1685
  }
1514
1686
 
@@ -1520,6 +1692,16 @@ ScrDyn *scr_dyn_new_typed_ref_traced(
1520
1692
  ScrDyn *value = scr_dyn_new_typed_ref(ptr, retain, release, type_key,
1521
1693
  type_key_len, materialize, commit);
1522
1694
  value->v.typed_ref.traced = true;
1695
+ value->v.typed_ref.observed = true;
1696
+ return value;
1697
+ }
1698
+
1699
+ ScrDyn *scr_dyn_new_typed_ref_observed(
1700
+ void *ptr, void *(*retain)(void *), void (*release)(void *),
1701
+ const char *type_key, size_t type_key_len,
1702
+ ScrDyn *(*materialize)(void *), void (*commit)(void *, const ScrDyn *)) {
1703
+ ScrDyn *value = scr_dyn_new_typed_ref(ptr, retain, release, type_key, type_key_len, materialize, commit);
1704
+ value->v.typed_ref.observed = true;
1523
1705
  return value;
1524
1706
  }
1525
1707
 
@@ -1601,6 +1783,34 @@ ScrDyn *scr_dyn_typed_ref_materialize(const ScrDyn *d) {
1601
1783
  * detached contents without changing the cached node's address. */
1602
1784
  scr_dyn_typed_ref_preserve_children(
1603
1785
  capsule->v.typed_ref.materialized, fresh);
1786
+ /* Record layouts cannot store properties added through a checked
1787
+ * view. Keep those descriptors in the view across native refreshes. */
1788
+ ScrDyn *cached = capsule->v.typed_ref.materialized;
1789
+ if (fresh->kind == SCR_DYN_OBJ && cached->kind == SCR_DYN_OBJ &&
1790
+ capsule->v.typed_ref.type_key_len >= 7 &&
1791
+ memcmp(capsule->v.typed_ref.type_key, "record:", 7) == 0) {
1792
+ for (size_t i = 0; i < cached->v.obj.len; i++) {
1793
+ ScrDynEntry *entry = &cached->v.obj.entries[i];
1794
+ if (scr_dyn_obj_get(fresh, entry->key, entry->key_len)) continue;
1795
+ ScrStr *name = scr_str_new(entry->key, entry->key_len);
1796
+ ScrDyn *key = scr_dyn_new_str(name);
1797
+ ScrDyn *descriptor = scr_dyn_own_descriptor(cached, name);
1798
+ ScrDyn *defined = scr_dyn_define_property(fresh, key, descriptor);
1799
+ scr_dyn_release(defined);
1800
+ scr_dyn_release(descriptor);
1801
+ scr_dyn_release(key);
1802
+ scr_str_release(name);
1803
+ }
1804
+ }
1805
+ /* A native record stores its own fields, while its checked view owns
1806
+ * prototype changes. Refreshing fields must preserve that prototype. */
1807
+ scr_dyn_release(fresh->prototype);
1808
+ fresh->prototype = capsule->v.typed_ref.materialized->prototype ? scr_dyn_retain(capsule->v.typed_ref.materialized->prototype) : NULL;
1809
+ fresh->null_proto = capsule->v.typed_ref.materialized->null_proto;
1810
+ scr_dyn_release(fresh->symbol_properties);
1811
+ scr_dyn_release(fresh->symbol_keys);
1812
+ fresh->symbol_properties = capsule->v.typed_ref.materialized->symbol_properties ? scr_dyn_retain(capsule->v.typed_ref.materialized->symbol_properties) : NULL;
1813
+ fresh->symbol_keys = capsule->v.typed_ref.materialized->symbol_keys ? scr_dyn_retain(capsule->v.typed_ref.materialized->symbol_keys) : NULL;
1604
1814
  size_t cached_rc = capsule->v.typed_ref.materialized->rc;
1605
1815
  size_t fresh_rc = fresh->rc;
1606
1816
  ScrDyn old = *capsule->v.typed_ref.materialized;
@@ -1635,7 +1845,7 @@ void *scr_dyn_typed_ref_cached_cast(
1635
1845
 
1636
1846
  void scr_dyn_typed_ref_cache_cast(
1637
1847
  ScrDyn *d, const char *type_key, size_t type_key_len, void *ptr,
1638
- void *(*retain)(void *), void (*release)(void *)) {
1848
+ void *(*retain)(void *), void (*release)(void *), bool traced) {
1639
1849
  if (!ptr) return;
1640
1850
  ScrDynTypedCast *cast = malloc(sizeof *cast);
1641
1851
  if (!cast) scr_trap("scriptc: out of memory\n");
@@ -1644,10 +1854,15 @@ void scr_dyn_typed_ref_cache_cast(
1644
1854
  cast->ptr = retain(ptr);
1645
1855
  cast->retain = retain;
1646
1856
  cast->release = release;
1857
+ cast->traced = traced;
1647
1858
  cast->next = d->v.typed_ref.casts;
1648
1859
  d->v.typed_ref.casts = cast;
1649
1860
  }
1650
1861
 
1862
+ bool scr_dyn_typed_array_is(const ScrDyn *d, int elem) {
1863
+ return d && d->kind == SCR_DYN_BYTES && !d->v.bytes->is_data_view && d->v.bytes->elem == (ScrBytesElem)elem;
1864
+ }
1865
+
1651
1866
  bool scr_dyn_bytes_is(const ScrDyn *d, int elem) {
1652
1867
  return d && d->kind == SCR_DYN_BYTES && d->v.bytes->elem == (ScrBytesElem)elem;
1653
1868
  }
@@ -1656,6 +1871,110 @@ ScrBytes *scr_dyn_bytes_unbox(const ScrDyn *d) {
1656
1871
  return scr_bytes_retain(d->v.bytes);
1657
1872
  }
1658
1873
 
1874
+ /* Numeric typed-array constructor values share native function identity.
1875
+ * The cache owns one reference until runtime cleanup; arbitrary strings or
1876
+ * functions cannot impersonate one of these constructors. */
1877
+ static SCR_TL ScrDyn *scr_bytes_ctors[9];
1878
+ static void scr_bytes_ctors_cleanup(void) {
1879
+ for (size_t i = 0; i < 9; i++) {
1880
+ scr_dyn_release(scr_bytes_ctors[i]);
1881
+ scr_bytes_ctors[i] = NULL;
1882
+ }
1883
+ }
1884
+ static ScrDyn *scr_bytes_ctor_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
1885
+ (void)args; (void)argc;
1886
+ for (size_t i = 0; i < 9; i++) {
1887
+ if (!scr_bytes_ctors[i] || scr_bytes_ctors[i]->v.fn.clo != closure) continue;
1888
+ ScrJsonBuf message;
1889
+ scr_jb_init(&message);
1890
+ scr_jb_puts(&message, "Constructor ");
1891
+ scr_jb_puts(&message, scr_bytes_elem_name((ScrBytesElem)i));
1892
+ scr_jb_puts(&message, " requires 'new'");
1893
+ scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&message));
1894
+ return NULL;
1895
+ }
1896
+ scr_trap("scriptc: invalid typed array constructor\n");
1897
+ }
1898
+ static ScrDyn *scr_dyn_fn_properties(const ScrDyn *function);
1899
+ static ScrDyn *scr_bytes_constructor_for(ScrBytesElem elem) {
1900
+ if (!scr_bytes_ctors[elem]) {
1901
+ bool initialized = false;
1902
+ for (size_t i = 0; i < 9; i++) if (scr_bytes_ctors[i]) initialized = true;
1903
+ if (!initialized) scr_atexit(scr_bytes_ctors_cleanup);
1904
+ scr_bytes_ctors[elem] = scr_dyn_new_func(scr_closure_new(NULL, 0),
1905
+ scr_bytes_ctor_call, 3, "typed-array-constructor", scr_bytes_elem_name(elem));
1906
+ ScrDyn *properties = scr_dyn_fn_properties(scr_bytes_ctors[elem]);
1907
+ scr_dyn_obj_set(properties, "BYTES_PER_ELEMENT", 17, scr_dyn_new_num((double)scr_bytes_elem_size(elem)));
1908
+ ScrDynEntry *entry = &properties->v.obj.entries[properties->v.obj.len - 1];
1909
+ entry->writable = entry->enumerable = entry->configurable = false;
1910
+ scr_dyn_release(properties);
1911
+ }
1912
+ return scr_dyn_retain(scr_bytes_ctors[elem]);
1913
+ }
1914
+ ScrDyn *scr_bytes_constructor(const ScrStr *name) {
1915
+ for (size_t i = 0; i < 9; i++) {
1916
+ const char *candidate = scr_bytes_elem_name((ScrBytesElem)i);
1917
+ if (strlen(candidate) == name->len && memcmp(candidate, name->data, name->len) == 0)
1918
+ return scr_bytes_constructor_for((ScrBytesElem)i);
1919
+ }
1920
+ scr_trap("scriptc: invalid typed array constructor name\n");
1921
+ }
1922
+ static SCR_TL ScrDyn *scr_array_buffer_ctor;
1923
+ static void scr_array_buffer_ctor_cleanup(void) {
1924
+ scr_dyn_release(scr_array_buffer_ctor);
1925
+ scr_array_buffer_ctor = NULL;
1926
+ }
1927
+ static ScrDyn *scr_array_buffer_ctor_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
1928
+ (void)closure; (void)args; (void)argc;
1929
+ static const char message[] = "Constructor ArrayBuffer requires 'new'";
1930
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
1931
+ return NULL;
1932
+ }
1933
+ ScrDyn *scr_array_buffer_constructor(void) {
1934
+ if (!scr_array_buffer_ctor) {
1935
+ scr_array_buffer_ctor = scr_dyn_new_func(scr_closure_new(NULL, 0), scr_array_buffer_ctor_call, 1, "native:ArrayBuffer", "ArrayBuffer");
1936
+ scr_atexit(scr_array_buffer_ctor_cleanup);
1937
+ }
1938
+ return scr_dyn_retain(scr_array_buffer_ctor);
1939
+ }
1940
+
1941
+ bool scr_bytes_instanceof(const ScrDyn *value, const ScrDyn *callee) {
1942
+ if (!callee || callee->kind != SCR_DYN_FUNC) {
1943
+ static const char message[] = "Right-hand side of 'instanceof' is not callable";
1944
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
1945
+ return false;
1946
+ }
1947
+ if (scr_array_buffer_ctor && callee->v.fn.clo == scr_array_buffer_ctor->v.fn.clo) return scr_array_buffer_is(value);
1948
+ for (size_t i = 0; i < 9; i++) {
1949
+ if (scr_bytes_ctors[i] && callee->v.fn.clo == scr_bytes_ctors[i]->v.fn.clo)
1950
+ return scr_dyn_typed_array_is(value, (int)i);
1951
+ }
1952
+ static const char message[] = "instanceof against this native constructor is not supported yet";
1953
+ scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC1090");
1954
+ return false;
1955
+ }
1956
+ ScrDyn *scr_bytes_construct(const ScrDyn *callee, const ScrDyn *args, const ScrStr *what) {
1957
+ if (callee->kind == SCR_DYN_FUNC && scr_array_buffer_ctor && callee->v.fn.clo == scr_array_buffer_ctor->v.fn.clo)
1958
+ return scr_array_buffer_new(args->v.arr.len ? args->v.arr.items[0] : scr_dyn_undefined());
1959
+ for (size_t i = 0; i < 9; i++) {
1960
+ if (callee->kind != SCR_DYN_FUNC || !scr_bytes_ctors[i] || callee->v.fn.clo != scr_bytes_ctors[i]->v.fn.clo) continue;
1961
+ const ScrDyn *input = args->v.arr.len > 0 ? args->v.arr.items[0] : scr_dyn_undefined();
1962
+ const ScrDyn *offset = args->v.arr.len > 1 ? args->v.arr.items[1] : scr_dyn_undefined();
1963
+ const ScrDyn *length = args->v.arr.len > 2 ? args->v.arr.items[2] : scr_dyn_undefined();
1964
+ ScrBytes *bytes = scr_array_buffer_view((ScrBytesElem)i, input, offset, length);
1965
+ if (!bytes) return NULL;
1966
+ ScrDyn *result = scr_dyn_new_bytes(bytes);
1967
+ scr_bytes_release(bytes);
1968
+ return result;
1969
+ }
1970
+ ScrJsonBuf message;
1971
+ scr_jb_init(&message);
1972
+ scr_jb_write(&message, what->data, what->len);
1973
+ scr_jb_puts(&message, " is not a supported native constructor");
1974
+ scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&message));
1975
+ return NULL;
1976
+ }
1977
+
1659
1978
  /* Shared view metadata and indexed reads for both compiler backends. */
1660
1979
  ScrDyn *scr_dyn_bytes_key_get(const ScrDyn *value, const ScrStr *key) {
1661
1980
  ScrBytes *bytes = value->v.bytes;
@@ -1664,7 +1983,8 @@ ScrDyn *scr_dyn_bytes_key_get(const ScrDyn *value, const ScrStr *key) {
1664
1983
  if (key->len == 10 && memcmp(key->data, "byteOffset", 10) == 0) return scr_dyn_new_num(scr_bytes_byte_offset(bytes));
1665
1984
  if (key->len == 6 && memcmp(key->data, "buffer", 6) == 0) return scr_array_buffer_from_bytes(bytes);
1666
1985
  if (key->len == 11 && memcmp(key->data, "constructor", 11) == 0) {
1667
- /* Match the compiler's opaque JS builtin identity values. */
1986
+ if (!value->buffer) return scr_bytes_constructor_for(bytes->elem);
1987
+ /* Buffer retains its separate builtin identity. */
1668
1988
  char token[64];
1669
1989
  int length = snprintf(token, sizeof token, "[builtin %s]", value->buffer ? "Buffer" : scr_bytes_elem_name(bytes->elem));
1670
1990
  ScrStr *name = scr_str_new(token, (size_t)length);
@@ -1739,6 +2059,7 @@ static ScrDyn *scr_dyn_class_call(ScrClosure *closure, ScrDyn *const *args, size
1739
2059
 
1740
2060
  ScrDyn *scr_dyn_new_class(ScrClassObj *cls, const char *type_key) {
1741
2061
  ScrClosure *closure = scr_closure_new(NULL, 1);
2062
+ if (cls->static_data) closure->props = scr_box_retain(cls->static_data);
1742
2063
  closure->caps[0] = scr_box_new_obj(scr_classobj_retain_v, scr_classobj_release_v, scr_classobj_trace_v);
1743
2064
  scr_box_set_ref(closure->caps[0], scr_classobj_retain(cls));
1744
2065
  ScrDyn *value = scr_dyn_new_func(closure, scr_dyn_class_call, (uint32_t)cls->length, type_key, cls->name->data);
@@ -1751,6 +2072,10 @@ bool scr_dyn_class_is(const ScrDyn *value, const char *type_key) {
1751
2072
  strcmp(value->v.fn.sig, type_key) == 0;
1752
2073
  }
1753
2074
 
2075
+ bool scr_dyn_class_is_key(const ScrDyn *value, const ScrStr *type_key) {
2076
+ return scr_dyn_class_is(value, type_key->data);
2077
+ }
2078
+
1754
2079
  ScrClassObj *scr_dyn_class_check(const ScrDyn *value, const char *type_key, const ScrDynPath *path) {
1755
2080
  if (!scr_dyn_class_is(value, type_key)) {
1756
2081
  scr_dyn_check_fail(path, "class constructor", value);
@@ -2076,8 +2401,9 @@ ScrDyn *scr_dyn_new_handle(void *h, ScrDynHandleTag tag) {
2076
2401
  ScrDyn *d = scr_dyn_alloc(SCR_DYN_HANDLE);
2077
2402
  d->v.handle.ptr = scr_dyn_handle_ops(tag)->retain(h);
2078
2403
  d->v.handle.tag = tag;
2079
- d->v.handle.traced = (tag == SCR_DYNH_SET || tag == SCR_DYNH_MAP) &&
2080
- (((ScrMap *)h)->key_trace != NULL || ((ScrMap *)h)->val_trace != NULL);
2404
+ d->v.handle.traced = tag == SCR_DYNH_WEAK_MAP || tag == SCR_DYNH_WEAK_SET ||
2405
+ ((tag == SCR_DYNH_SET || tag == SCR_DYNH_MAP) &&
2406
+ (((ScrMap *)h)->key_trace != NULL || ((ScrMap *)h)->val_trace != NULL));
2081
2407
  return d;
2082
2408
  }
2083
2409
 
@@ -2086,6 +2412,7 @@ ScrDyn *scr_dyn_new_handle(void *h, ScrDynHandleTag tag) {
2086
2412
  * scr_promise_release edge installs HERE — a promise-free link never
2087
2413
  * references the fiber machinery (the unit-test subset links). */
2088
2414
  void (*scr_dyn_promise_release_fn)(ScrPromise *p) = NULL;
2415
+ bool (*scr_dyn_promise_identity_fn)(ScrPromise *a, ScrPromise *b) = NULL;
2089
2416
 
2090
2417
  ScrDyn *scr_dyn_alloc_promise(void (*release_fn)(ScrPromise *p)) {
2091
2418
  scr_dyn_promise_release_fn = release_fn;
@@ -2114,6 +2441,7 @@ const ScrDynJsvalOps *scr_dyn_jsval_ops(void) {
2114
2441
  }
2115
2442
 
2116
2443
  bool scr_dyn_isl_typeof_is(const ScrDyn *d, const char *name) {
2444
+ if (scr_dyn_generator(d)) return strcmp(name, "object") == 0;
2117
2445
  if (d->kind == SCR_DYN_TYPED_REF) {
2118
2446
  if (d->v.typed_ref.type_key_len >= 7 &&
2119
2447
  memcmp(d->v.typed_ref.type_key, "object:", 7) == 0)
@@ -2144,10 +2472,12 @@ bool scr_dyn_isl_typeof_is(const ScrDyn *d, const char *name) {
2144
2472
  }
2145
2473
 
2146
2474
  bool scr_dyn_isl_is_array(const ScrDyn *d) {
2475
+ if (scr_dyn_generator(d)) return false;
2147
2476
  if (d->kind == SCR_DYN_TYPED_REF) {
2148
2477
  if (d->v.typed_ref.type_key_len >= 7 &&
2149
2478
  memcmp(d->v.typed_ref.type_key, "object:", 7) == 0) return false;
2150
2479
  ScrDyn *materialized = scr_dyn_typed_ref_materialize(d);
2480
+ if (!materialized) return false;
2151
2481
  bool out = materialized->kind == SCR_DYN_ARR ||
2152
2482
  scr_dyn_isl_is_array(materialized);
2153
2483
  scr_dyn_release(materialized);
@@ -2157,6 +2487,14 @@ bool scr_dyn_isl_is_array(const ScrDyn *d) {
2157
2487
  }
2158
2488
 
2159
2489
  bool scr_dyn_isl_is_error(const ScrDyn *d) {
2490
+ if (scr_dyn_generator(d)) return false;
2491
+ /* Registered native Error capsules retain their brand even when their
2492
+ * public property view omits the internal error marker. */
2493
+ ScrError *error = scr_errdyn_err_of(d);
2494
+ if (error) {
2495
+ scr_error_release(error);
2496
+ return true;
2497
+ }
2160
2498
  if (d->kind == SCR_DYN_TYPED_REF) {
2161
2499
  ScrDyn *materialized = scr_dyn_typed_ref_materialize(d);
2162
2500
  bool out =
@@ -2316,6 +2654,7 @@ static ScrStr *scr_dyn_property_key(const ScrDyn *key) {
2316
2654
  }
2317
2655
 
2318
2656
  static ScrDynEntry *scr_dyn_entry(ScrDyn *obj, const ScrStr *key) {
2657
+ if (obj->kind != SCR_DYN_OBJ) return NULL;
2319
2658
  for (size_t i = 0; i < obj->v.obj.len; i++) {
2320
2659
  ScrDynEntry *entry = &obj->v.obj.entries[i];
2321
2660
  if (entry->key_len == key->len && memcmp(entry->key, key->data, key->len) == 0) return entry;
@@ -2334,6 +2673,10 @@ static bool scr_dyn_property_same_value(const ScrDyn *a, const ScrDyn *b) {
2334
2673
  return scr_dyn_strict_eq(a, b);
2335
2674
  }
2336
2675
 
2676
+ bool scr_dyn_same_value(const ScrDyn *left, const ScrDyn *right) {
2677
+ return scr_dyn_property_same_value(left, right);
2678
+ }
2679
+
2337
2680
  static void scr_dyn_descriptor_fields_drop(ScrDyn **fields) {
2338
2681
  for (size_t i = 0; i < 6; i++) scr_dyn_release(fields[i]);
2339
2682
  }
@@ -2344,6 +2687,8 @@ static void scr_error_sync_cause(ScrDyn *view, const ScrStr *key);
2344
2687
  * the configurable, non-writable builtin members once so redefinitions and
2345
2688
  * deletions retain the same behavior through every alias. Returns +1. */
2346
2689
  static ScrDyn *scr_dyn_fn_properties(const ScrDyn *function) {
2690
+ if (!function->v.fn.clo->props && function->v.fn.class_obj && function->v.fn.class_obj->static_data)
2691
+ function->v.fn.clo->props = scr_box_retain(function->v.fn.class_obj->static_data);
2347
2692
  if (!function->v.fn.clo->props) {
2348
2693
  ScrDyn *table = scr_dyn_new_obj();
2349
2694
  const char *name = function->v.fn.name ? function->v.fn.name : "";
@@ -2358,6 +2703,7 @@ static ScrDyn *scr_dyn_fn_properties(const ScrDyn *function) {
2358
2703
  ScrBox *box = scr_box_new_obj(&scr_dyn_retain_v, &scr_dyn_release_v, &scr_dyn_trace_v);
2359
2704
  scr_box_set_ref(box, table);
2360
2705
  function->v.fn.clo->props = box;
2706
+ if (function->v.fn.class_obj) function->v.fn.class_obj->static_data = scr_box_retain(box);
2361
2707
  if (function->v.fn.clo->function_kind & 4) {
2362
2708
  ScrDyn *prototype = scr_dyn_new_obj();
2363
2709
  scr_dyn_obj_set(prototype, "constructor", 11, scr_dyn_retain((ScrDyn *)function));
@@ -2371,6 +2717,22 @@ static ScrDyn *scr_dyn_fn_properties(const ScrDyn *function) {
2371
2717
  return (ScrDyn *)scr_box_get_ref(function->v.fn.clo->props);
2372
2718
  }
2373
2719
 
2720
+ ScrDyn *scr_dyn_class_inherit(ScrDyn *constructor, ScrDyn *base) {
2721
+ if (constructor->kind != SCR_DYN_FUNC || !constructor->v.fn.class_obj || (base->kind != SCR_DYN_FUNC && base->kind != SCR_DYN_UNDEF)) {
2722
+ static const char message[] = "Class inheritance requires native constructors";
2723
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
2724
+ return NULL;
2725
+ }
2726
+ ScrDyn *table = scr_dyn_fn_properties(constructor);
2727
+ if (base->kind == SCR_DYN_FUNC) scr_dyn_release(scr_dyn_fn_properties(base));
2728
+ ScrClassObj *cls = constructor->v.fn.class_obj;
2729
+ if (!cls->static_data) cls->static_data = scr_box_retain(constructor->v.fn.clo->props);
2730
+ ScrDyn *result = base->kind == SCR_DYN_UNDEF ? NULL : scr_dyn_set_prototype(table, base);
2731
+ scr_dyn_release(table);
2732
+ scr_dyn_release(result);
2733
+ return scr_exc_pending() ? NULL : scr_dyn_retain(constructor);
2734
+ }
2735
+
2374
2736
  ScrDyn *scr_dyn_class_base_prototype(ScrDyn *constructor) {
2375
2737
  if (constructor->kind != SCR_DYN_FUNC || constructor->v.fn.class_obj ||
2376
2738
  constructor->v.fn.clo->function_kind != 4) {
@@ -2399,6 +2761,35 @@ void scr_dyn_class_super(ScrDyn *constructor, ScrDyn *receiver, ScrDyn *argument
2399
2761
  scr_dyn_release(result);
2400
2762
  }
2401
2763
 
2764
+ bool scr_dyn_data_view_is(const ScrDyn *value) {
2765
+ return value->kind == SCR_DYN_BYTES && value->v.bytes->is_data_view;
2766
+ }
2767
+
2768
+ /* Ordinary native function constructors retain their live prototype table.
2769
+ * A constructor may replace the fresh receiver with another object. */
2770
+ ScrDyn *scr_dyn_construct(const ScrDyn *callee, const ScrDyn *args, const ScrStr *what) {
2771
+ if (callee->kind != SCR_DYN_FUNC || callee->v.fn.class_obj || callee->v.fn.clo->function_kind != 4)
2772
+ return scr_bytes_construct(callee, args, what);
2773
+ ScrDyn *prototype = scr_dyn_fn_get(callee, "prototype", 9);
2774
+ if (!prototype) return NULL;
2775
+ ScrDyn *receiver = scr_iterator_object(prototype) ? scr_dyn_obj_create(prototype) : scr_dyn_new_obj();
2776
+ scr_dyn_release(prototype);
2777
+ if (!receiver) return NULL;
2778
+ scr_dyn_this_push_dyn(receiver);
2779
+ ScrDyn *result = scr_dyn_call(callee, args->v.arr.items, args->v.arr.len, what->data);
2780
+ scr_dyn_this_pop();
2781
+ if (!result) {
2782
+ scr_dyn_release(receiver);
2783
+ return NULL;
2784
+ }
2785
+ if (scr_iterator_object(result)) {
2786
+ scr_dyn_release(receiver);
2787
+ return result;
2788
+ }
2789
+ scr_dyn_release(result);
2790
+ return receiver;
2791
+ }
2792
+
2402
2793
  /* Symbol descriptors use the ordinary descriptor implementation in an
2403
2794
  * inaccessible table. Keep a retained key list so identities cannot be
2404
2795
  * recycled while properties exist, and reflection returns real symbols. */
@@ -2409,11 +2800,11 @@ static ScrStr *scr_dyn_symbol_storage_key(const ScrDyn *key) {
2409
2800
  }
2410
2801
 
2411
2802
  static ScrDyn *scr_dyn_symbol_receiver(const ScrDyn *value) {
2803
+ if (value->kind == SCR_DYN_TYPED_REF) return scr_dyn_typed_ref_materialize(value);
2412
2804
  if (value->kind == SCR_DYN_FUNC) return scr_dyn_fn_properties(value);
2413
- if (value->kind == SCR_DYN_OBJ || value->kind == SCR_DYN_ARR)
2805
+ if (value->kind == SCR_DYN_OBJ || value->kind == SCR_DYN_ARR || value->kind == SCR_DYN_HANDLE)
2414
2806
  return scr_dyn_retain((ScrDyn *)value);
2415
- if (value->kind == SCR_DYN_TYPED_REF || value->kind == SCR_DYN_HANDLE ||
2416
- value->kind == SCR_DYN_PROXY || value->kind == SCR_DYN_JSVAL) {
2807
+ if (value->kind == SCR_DYN_PROXY || value->kind == SCR_DYN_JSVAL) {
2417
2808
  static const char message[] = "Symbol properties on this native value have no lowering";
2418
2809
  scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
2419
2810
  }
@@ -2425,6 +2816,12 @@ static ScrDynEntry *scr_dyn_symbol_entry(const ScrDyn *receiver, const ScrDyn *k
2425
2816
  ScrDynEntry *entry = NULL;
2426
2817
  for (const ScrDyn *current = receiver; current; current = own ? NULL : current->prototype ? current->prototype
2427
2818
  : current->kind == SCR_DYN_ARR && current != scr_builtin_array_prototype && !current->null_proto ? scr_builtin_array_prototype : NULL) {
2819
+ if (current->kind == SCR_DYN_FUNC) {
2820
+ ScrDyn *table = scr_dyn_fn_properties(current);
2821
+ entry = scr_dyn_symbol_entry(table, key, own);
2822
+ scr_dyn_release(table);
2823
+ break;
2824
+ }
2428
2825
  if (current->symbol_properties) entry = scr_dyn_entry(current->symbol_properties, name);
2429
2826
  if (entry) break;
2430
2827
  }
@@ -2442,14 +2839,19 @@ typedef struct {
2442
2839
  size_t rc;
2443
2840
  ScrDyn *source;
2444
2841
  double index;
2445
- bool string_iterator;
2842
+ unsigned kind; /* 0: array, 1: string, 2: Map, 3: Set */
2843
+ unsigned selection; /* 0: values, 1: keys, 2: entries */
2844
+ bool array_like;
2845
+ double limit;
2446
2846
  } ScrNativeIterator;
2447
2847
 
2448
- static SCR_TL ScrDyn *scr_iterator_functions[7];
2848
+ static ScrDyn *scr_iterator_read(const ScrDyn *value, const char *key, size_t len);
2849
+
2850
+ static SCR_TL ScrDyn *scr_iterator_functions[11];
2449
2851
  static SCR_TL bool scr_iterator_functions_registered;
2450
2852
 
2451
2853
  static void scr_iterator_functions_cleanup(void) {
2452
- for (size_t i = 0; i < 7; i++) {
2854
+ for (size_t i = 0; i < 11; i++) {
2453
2855
  ScrDyn *function = scr_iterator_functions[i];
2454
2856
  scr_iterator_functions[i] = NULL;
2455
2857
  scr_dyn_release(function);
@@ -2475,25 +2877,51 @@ static void *scr_native_iterator_retain(void *ptr) {
2475
2877
  static void scr_native_iterator_release(void *ptr) {
2476
2878
  ScrNativeIterator *iterator = ptr;
2477
2879
  if (--iterator->rc) return;
2880
+ scr_weak_dispose(iterator);
2881
+ if (iterator->source && (iterator->kind == 2 || iterator->kind == 3)) scr_map_iter_exit(iterator->source->v.handle.ptr);
2478
2882
  scr_dyn_release(iterator->source);
2479
2883
  free(iterator);
2480
2884
  }
2481
2885
 
2482
2886
  static ScrDyn *scr_native_iterator_next(ScrNativeIterator *iterator) {
2483
2887
  ScrDyn *source = iterator->source;
2888
+ if (source && iterator->kind == 4) {
2889
+ ScrDyn *result = scr_dyn_handle_ops_of(source)->iter_step(source->v.handle.ptr, &iterator->index, iterator->selection);
2890
+ if (!result) return NULL;
2891
+ if (scr_dyn_truthy(scr_dyn_obj_get(result, "done", 4))) {
2892
+ iterator->source = NULL;
2893
+ scr_dyn_release(source);
2894
+ }
2895
+ return result;
2896
+ }
2484
2897
  /* Native array capsules retain the live array, so refresh its view at each
2485
2898
  * step rather than iterating a snapshot taken when the iterator opened. */
2486
2899
  ScrDyn *view = source && source->kind == SCR_DYN_TYPED_REF ? scr_dyn_typed_ref_materialize(source) : NULL;
2487
2900
  if (scr_exc_pending()) { scr_dyn_release(view); return NULL; }
2488
2901
  ScrDyn *items = view ? view : source;
2489
- double length = !items ? 0 : items->kind == SCR_DYN_ARR ? (double)items->v.arr.len
2902
+ ScrMap *map = source && (iterator->kind == 2 || iterator->kind == 3) ? source->v.handle.ptr : NULL;
2903
+ if (map) while (iterator->index < scr_map_iter_count(map) && !scr_map_iter_live(map, iterator->index)) iterator->index++;
2904
+ double length = !items ? 0 : iterator->array_like ? iterator->limit : map ? scr_map_iter_count(map) : items->kind == SCR_DYN_ARR ? (double)items->v.arr.len
2490
2905
  : items->kind == SCR_DYN_BYTES ? (double)items->v.bytes->len : scr_str_utf16_len(items->v.str);
2491
2906
  bool done = !source || iterator->index >= length;
2492
2907
  ScrDyn *value;
2493
2908
  if (done) {
2494
2909
  value = scr_dyn_retain(scr_dyn_undefined());
2495
2910
  iterator->source = NULL;
2911
+ if (map) scr_map_iter_exit(map);
2496
2912
  scr_dyn_release(source);
2913
+ } else if (iterator->array_like) {
2914
+ char key[32];
2915
+ int size = snprintf(key, sizeof key, "%.0f", iterator->index++);
2916
+ value = scr_iterator_read(items, key, (size_t)size);
2917
+ } else if (map) {
2918
+ double index = iterator->index++;
2919
+ if (iterator->selection == 2) {
2920
+ value = scr_dyn_new_arr();
2921
+ scr_dyn_arr_push(value, scr_map_dyn_key(map, index));
2922
+ scr_dyn_arr_push(value, iterator->kind == 3 ? scr_map_dyn_key(map, index) : scr_map_dyn_value(map, index));
2923
+ } else value = iterator->selection == 1 || iterator->kind == 3
2924
+ ? scr_map_dyn_key(map, index) : scr_map_dyn_value(map, index);
2497
2925
  } else if (items->kind == SCR_DYN_ARR) {
2498
2926
  value = scr_dyn_arr_at(items, iterator->index++);
2499
2927
  } else if (items->kind == SCR_DYN_BYTES) {
@@ -2512,14 +2940,15 @@ static ScrDyn *scr_native_iterator_next(ScrNativeIterator *iterator) {
2512
2940
  return result;
2513
2941
  }
2514
2942
 
2515
- static ScrDyn *scr_native_iterator_next_checked(bool string_iterator) {
2943
+ static ScrDyn *scr_native_iterator_next_checked(unsigned kind) {
2516
2944
  ScrDyn *self = scr_dyn_this_get();
2517
2945
  ScrDyn *result = NULL;
2518
2946
  if (self->kind == SCR_DYN_HANDLE && self->v.handle.tag == SCR_DYNH_ITERATOR &&
2519
- ((ScrNativeIterator *)self->v.handle.ptr)->string_iterator == string_iterator)
2947
+ ((ScrNativeIterator *)self->v.handle.ptr)->kind == kind)
2520
2948
  result = scr_native_iterator_next(self->v.handle.ptr);
2521
2949
  else {
2522
- const char *message = string_iterator
2950
+ const char *message = kind == 3 ? "Method Set Iterator.prototype.next called on incompatible receiver"
2951
+ : kind == 2 ? "Method Map Iterator.prototype.next called on incompatible receiver" : kind == 1
2523
2952
  ? "Method String Iterator.prototype.next called on incompatible receiver"
2524
2953
  : "Method Array Iterator.prototype.next called on incompatible receiver";
2525
2954
  scr_throw_error_msg(SCR_ERR_TYPE, message, strlen(message));
@@ -2530,17 +2959,35 @@ static ScrDyn *scr_native_iterator_next_checked(bool string_iterator) {
2530
2959
 
2531
2960
  static ScrDyn *scr_native_array_iterator_next_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
2532
2961
  (void)closure; (void)args; (void)argc;
2533
- return scr_native_iterator_next_checked(false);
2962
+ return scr_native_iterator_next_checked(0);
2534
2963
  }
2535
2964
 
2536
2965
  static ScrDyn *scr_native_string_iterator_next_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
2537
2966
  (void)closure; (void)args; (void)argc;
2538
- return scr_native_iterator_next_checked(true);
2967
+ return scr_native_iterator_next_checked(1);
2968
+ }
2969
+
2970
+ static ScrDyn *scr_native_map_iterator_next_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
2971
+ (void)closure; (void)args; (void)argc;
2972
+ return scr_native_iterator_next_checked(2);
2973
+ }
2974
+
2975
+ static ScrDyn *scr_native_set_iterator_next_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
2976
+ (void)closure; (void)args; (void)argc;
2977
+ return scr_native_iterator_next_checked(3);
2978
+ }
2979
+
2980
+ static ScrDyn *scr_native_handle_iterator_next_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
2981
+ (void)closure; (void)args; (void)argc;
2982
+ return scr_native_iterator_next_checked(4);
2539
2983
  }
2540
2984
 
2541
2985
  static ScrDyn *scr_native_iterator_get(void *ptr, const char *key, size_t len) {
2542
2986
  if (len != 4 || memcmp(key, "next", 4)) return NULL;
2543
- return ((ScrNativeIterator *)ptr)->string_iterator
2987
+ unsigned kind = ((ScrNativeIterator *)ptr)->kind;
2988
+ if (kind == 4) return scr_iterator_function(10, &scr_native_handle_iterator_next_call, "next");
2989
+ return kind == 3 ? scr_iterator_function(8, &scr_native_set_iterator_next_call, "next")
2990
+ : kind == 2 ? scr_iterator_function(7, &scr_native_map_iterator_next_call, "next") : kind == 1
2544
2991
  ? scr_iterator_function(5, &scr_native_string_iterator_next_call, "next")
2545
2992
  : scr_iterator_function(0, &scr_native_array_iterator_next_call, "next");
2546
2993
  }
@@ -2562,12 +3009,26 @@ static ScrDyn *scr_native_iterator_new(ScrDyn *source) {
2562
3009
  ScrNativeIterator *iterator = malloc(sizeof *iterator);
2563
3010
  if (!iterator) scr_json_oom();
2564
3011
  *iterator = (ScrNativeIterator){ .rc = 1, .source = scr_dyn_retain(source), .index = 0,
2565
- .string_iterator = source->kind == SCR_DYN_STR };
3012
+ .kind = source->kind == SCR_DYN_STR ? 1 : source->kind == SCR_DYN_HANDLE && source->v.handle.tag == SCR_DYNH_MAP ? 2
3013
+ : source->kind == SCR_DYN_HANDLE && source->v.handle.tag == SCR_DYNH_SET ? 3
3014
+ : source->kind == SCR_DYN_HANDLE && scr_dyn_handle_ops_of(source)->iter_step ? 4 : 0,
3015
+ .selection = source->kind == SCR_DYN_HANDLE && (source->v.handle.tag == SCR_DYNH_MAP || scr_dyn_handle_ops_of(source)->iter_step) ? 2 : 0 };
3016
+ if (iterator->kind == 2 || iterator->kind == 3) scr_map_iter_enter(source->v.handle.ptr);
2566
3017
  ScrDyn *result = scr_dyn_new_handle(iterator, SCR_DYNH_ITERATOR);
2567
3018
  scr_native_iterator_release(iterator);
2568
3019
  return result;
2569
3020
  }
2570
3021
 
3022
+ static ScrDyn *scr_native_collection_iterator(ScrDyn *source, unsigned selection) {
3023
+ ScrDyn *result = scr_native_iterator_new(source);
3024
+ ((ScrNativeIterator *)result->v.handle.ptr)->selection = selection;
3025
+ return result;
3026
+ }
3027
+
3028
+ ScrDyn *scr_dyn_native_handle_iterator(ScrDyn *source, unsigned selection) {
3029
+ return scr_native_collection_iterator(source, selection);
3030
+ }
3031
+
2571
3032
  static ScrDyn *scr_builtin_iterator_checked(int kind) {
2572
3033
  ScrDyn *self = scr_dyn_this_get();
2573
3034
  ScrDyn *result = NULL;
@@ -2604,6 +3065,11 @@ static ScrDyn *scr_iterator_self_call(ScrClosure *closure, ScrDyn *const *args,
2604
3065
  static ScrDyn *scr_handle_iterator_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
2605
3066
  (void)closure; (void)args; (void)argc;
2606
3067
  ScrDyn *self = scr_dyn_this_get();
3068
+ if (self->kind == SCR_DYN_HANDLE && (self->v.handle.tag == SCR_DYNH_MAP || self->v.handle.tag == SCR_DYNH_SET || scr_dyn_handle_ops_of(self)->iter_step)) {
3069
+ ScrDyn *result = scr_native_iterator_new(self);
3070
+ scr_dyn_release(self);
3071
+ return result;
3072
+ }
2607
3073
  ScrDyn *items = scr_dyn_iter_pack(self, NULL);
2608
3074
  ScrDyn *result = items ? scr_native_iterator_new(items) : NULL;
2609
3075
  scr_dyn_release(items);
@@ -2616,10 +3082,11 @@ ScrDyn *scr_dyn_array_values_function(void) {
2616
3082
  }
2617
3083
 
2618
3084
  static ScrDyn *scr_builtin_iterator_method(const ScrDyn *value) {
3085
+ if (scr_dyn_generator(value)) return scr_iterator_function(4, &scr_iterator_self_call, "[Symbol.iterator]");
2619
3086
  if (value->kind == SCR_DYN_ARR || (value->kind == SCR_DYN_TYPED_REF && scr_dyn_isl_is_array(value))) return scr_dyn_array_values_function();
2620
3087
  if (value->kind == SCR_DYN_BYTES) return scr_iterator_function(2, &scr_builtin_bytes_iterator_call, "values");
2621
3088
  if (value->kind == SCR_DYN_STR) return scr_iterator_function(3, &scr_builtin_string_iterator_call, "[Symbol.iterator]");
2622
- if (value->kind == SCR_DYN_HANDLE && scr_dyn_handle_ops_of(value)->iter_pack)
3089
+ if (value->kind == SCR_DYN_HANDLE && (value->v.handle.tag == SCR_DYNH_MAP || value->v.handle.tag == SCR_DYNH_SET || scr_dyn_handle_ops_of(value)->iter_pack || scr_dyn_handle_ops_of(value)->iter_step))
2623
3090
  return scr_iterator_function(6, &scr_handle_iterator_call, "[Symbol.iterator]");
2624
3091
  return scr_iterator_function(4, &scr_iterator_self_call, "[Symbol.iterator]");
2625
3092
  }
@@ -2644,6 +3111,21 @@ static ScrDyn *scr_iterator_method(const ScrDyn *source) {
2644
3111
  }
2645
3112
 
2646
3113
  /* Compiled class methods are dispatched before this checked-object path. */
3114
+ ScrDyn *scr_dyn_iterator_optional(const ScrDyn *source) {
3115
+ ScrDyn *method = scr_iterator_method(source);
3116
+ if (!method) return NULL;
3117
+ if (method->kind == SCR_DYN_UNDEF || method->kind == SCR_DYN_NULL) {
3118
+ scr_dyn_release(method);
3119
+ return NULL;
3120
+ }
3121
+ ScrDyn *iterator = scr_iterator_call(method, source, "value[Symbol.iterator]");
3122
+ scr_dyn_release(method);
3123
+ if (!iterator) return NULL;
3124
+ ScrDyn *checked = scr_dyn_iterator_result(iterator);
3125
+ scr_dyn_release(iterator);
3126
+ return checked;
3127
+ }
3128
+
2647
3129
  ScrDyn *scr_dyn_iterator(const ScrDyn *source, const ScrStr *spell) {
2648
3130
  if (source->kind == SCR_DYN_JSVAL) return scr_dyn_jsval_ops()->iterator(source->v.jsval.cell, spell, false);
2649
3131
  if (source->kind == SCR_DYN_NULL || source->kind == SCR_DYN_UNDEF) return scr_dyn_not_iterable(source, spell);
@@ -2662,6 +3144,14 @@ ScrDyn *scr_dyn_iterator(const ScrDyn *source, const ScrStr *spell) {
2662
3144
  }
2663
3145
 
2664
3146
  static ScrDyn *scr_iterator_read(const ScrDyn *value, const char *key, size_t len) {
3147
+ if (value->kind == SCR_DYN_TYPED_REF) {
3148
+ ScrDyn *view = scr_dyn_typed_ref_materialize(value);
3149
+ if (!view) return NULL;
3150
+ ScrDyn *result = scr_iterator_read(view, key, len);
3151
+ scr_dyn_release(view);
3152
+ return result;
3153
+ }
3154
+ if (value->kind == SCR_DYN_PROXY) return scr_dyn_obj_read(value, key, len);
2665
3155
  if (value->kind == SCR_DYN_HANDLE) {
2666
3156
  ScrStr *name = scr_str_new(key, len);
2667
3157
  ScrDyn *result = scr_dyn_handle_key_get(value, name);
@@ -2701,14 +3191,10 @@ ScrDyn *scr_dyn_array_from_iterator(const ScrDyn *source) {
2701
3191
  numeric = false;
2702
3192
  }
2703
3193
  if (!numeric) { scr_dyn_release(out); return NULL; }
2704
- for (size_t i = 0; (double)i < floor(n); i++) {
2705
- char key[32];
2706
- int size = snprintf(key, sizeof key, "%zu", i);
2707
- ScrDyn *value = scr_iterator_read(source, key, (size_t)size);
2708
- if (!value) { scr_dyn_release(out); return NULL; }
2709
- scr_dyn_arr_push(out, value);
2710
- }
2711
- ScrDyn *iterator = scr_native_iterator_new(out);
3194
+ ScrDyn *iterator = scr_native_iterator_new((ScrDyn *)source);
3195
+ ScrNativeIterator *state = iterator->v.handle.ptr;
3196
+ state->array_like = true;
3197
+ state->limit = isnan(n) || n < 0 ? 0 : floor(n);
2712
3198
  scr_dyn_release(out);
2713
3199
  return iterator;
2714
3200
  }
@@ -2722,7 +3208,9 @@ ScrDyn *scr_dyn_array_from_iterator(const ScrDyn *source) {
2722
3208
  }
2723
3209
 
2724
3210
  ScrDyn *scr_dyn_symbol_key_get(const ScrDyn *value, const ScrDyn *key, bool optional) {
2725
- if (value->kind == SCR_DYN_TYPED_REF && scr_dyn_isl_is_array(value)) {
3211
+ if (scr_dyn_generator(value)) return scr_dyn_generator_symbol(value, key)
3212
+ ? scr_iterator_function(4, &scr_iterator_self_call, "[Symbol.iterator]") : scr_dyn_retain(scr_dyn_undefined());
3213
+ if (value->kind == SCR_DYN_TYPED_REF) {
2726
3214
  ScrDyn *view = scr_dyn_typed_ref_materialize(value);
2727
3215
  ScrDyn *result = scr_exc_pending() ? NULL : scr_dyn_symbol_key_get(view, key, optional);
2728
3216
  scr_dyn_release(view);
@@ -2823,7 +3311,12 @@ static bool scr_dyn_key_probe_computed(const ScrDyn *value, const ScrDyn *raw_ke
2823
3311
  scr_dyn_release(key);
2824
3312
  return out;
2825
3313
  }
2826
- if (value->kind == SCR_DYN_TYPED_REF && scr_dyn_isl_is_array(value)) {
3314
+ if (scr_dyn_generator(value)) {
3315
+ bool found = mode == 0 && scr_dyn_generator_symbol(value, key);
3316
+ scr_dyn_release(key);
3317
+ return found;
3318
+ }
3319
+ if (value->kind == SCR_DYN_TYPED_REF) {
2827
3320
  ScrDyn *view = scr_dyn_typed_ref_materialize(value);
2828
3321
  bool out = !scr_exc_pending() && scr_dyn_key_probe_computed(view, key, mode);
2829
3322
  scr_dyn_release(view);
@@ -2892,7 +3385,7 @@ void scr_dyn_key_delete_computed(ScrDyn *value, const ScrDyn *raw_key, bool stri
2892
3385
  * Refuse overrides until every typed call site observes the property table. */
2893
3386
  static bool scr_dyn_fn_property_fence(const ScrStr *key) {
2894
3387
  static const char *const reserved[] = {
2895
- "call", "apply", "bind", "toString", "valueOf", "toLocaleString",
3388
+ "call", "apply", "bind", "valueOf", "toLocaleString",
2896
3389
  "hasOwnProperty", "propertyIsEnumerable", "isPrototypeOf",
2897
3390
  "constructor", "caller", "arguments", "__proto__",
2898
3391
  };
@@ -2906,6 +3399,20 @@ static bool scr_dyn_fn_property_fence(const ScrStr *key) {
2906
3399
  }
2907
3400
 
2908
3401
  ScrDyn *scr_dyn_define_property(ScrDyn *target, ScrDyn *key, ScrDyn *descriptor) {
3402
+ if (target->kind == SCR_DYN_TYPED_REF) {
3403
+ ScrDyn *view = scr_dyn_typed_ref_materialize(target);
3404
+ ScrDyn *defined = scr_exc_pending() ? NULL : scr_dyn_define_property(view, key, descriptor);
3405
+ if (!scr_exc_pending()) scr_dyn_typed_ref_commit(target);
3406
+ scr_dyn_release(defined);
3407
+ scr_dyn_release(view);
3408
+ return scr_exc_pending() ? NULL : scr_dyn_retain(target);
3409
+ }
3410
+ if (descriptor->kind == SCR_DYN_TYPED_REF) {
3411
+ ScrDyn *view = scr_dyn_typed_ref_materialize(descriptor);
3412
+ ScrDyn *result = scr_exc_pending() ? NULL : scr_dyn_define_property(target, key, view);
3413
+ scr_dyn_release(view);
3414
+ return result;
3415
+ }
2909
3416
  if (key->kind == SCR_DYN_SYMBOL) return scr_dyn_define_symbol(target, key, descriptor);
2910
3417
  if (target->kind == SCR_DYN_PROXY || descriptor->kind == SCR_DYN_PROXY) {
2911
3418
  scr_dyn_proxy_unsupported("Object.defineProperty");
@@ -3415,6 +3922,29 @@ static SCR_TL ScrErrDynEnt *scr_errdyn_cache = NULL;
3415
3922
  static SCR_TL size_t scr_errdyn_n = 0, scr_errdyn_cap = 0;
3416
3923
  static SCR_TL bool scr_errdyn_teardown_registered = false;
3417
3924
 
3925
+ typedef struct {
3926
+ const ScrVt *vt;
3927
+ ScrDyn *(*box)(void *);
3928
+ } ScrErrorDynType;
3929
+ static SCR_TL ScrErrorDynType *scr_error_dyn_types = NULL;
3930
+ static SCR_TL size_t scr_error_dyn_type_count = 0;
3931
+
3932
+ static void scr_error_dyn_types_drop(void) {
3933
+ free(scr_error_dyn_types);
3934
+ scr_error_dyn_types = NULL;
3935
+ scr_error_dyn_type_count = 0;
3936
+ }
3937
+
3938
+ void scr_error_register_dyn(const ScrVt *vt, ScrDyn *(*box)(void *)) {
3939
+ for (size_t i = 0; i < scr_error_dyn_type_count; i++) {
3940
+ if (scr_error_dyn_types[i].vt == vt) return;
3941
+ }
3942
+ if (!scr_error_dyn_type_count) scr_atexit(scr_error_dyn_types_drop);
3943
+ scr_error_dyn_types = realloc(scr_error_dyn_types, (scr_error_dyn_type_count + 1) * sizeof *scr_error_dyn_types);
3944
+ if (!scr_error_dyn_types) scr_json_oom();
3945
+ scr_error_dyn_types[scr_error_dyn_type_count++] = (ScrErrorDynType){vt, box};
3946
+ }
3947
+
3418
3948
  static void scr_errdyn_teardown(void) {
3419
3949
  for (size_t i = 0; i < scr_errdyn_n; i++) {
3420
3950
  scr_error_release(scr_errdyn_cache[i].err);
@@ -3425,14 +3955,32 @@ static void scr_errdyn_teardown(void) {
3425
3955
  scr_errdyn_n = scr_errdyn_cap = 0;
3426
3956
  }
3427
3957
 
3428
- ScrDyn *scr_dyn_from_error(const ScrError *e) {
3429
- for (size_t i = 0; i < scr_errdyn_n; i++) {
3430
- if (scr_errdyn_cache[i].err == e) return scr_dyn_retain(scr_errdyn_cache[i].dyn);
3431
- }
3958
+ ScrDyn *scr_error_dyn_fields(const ScrError *e) {
3432
3959
  ScrDyn *d = scr_dyn_new_obj();
3433
3960
  scr_dyn_obj_set(d, "%error", 6, scr_dyn_new_bool(true)); /* the checked-dynamic tree's error marker */
3434
- scr_dyn_obj_set(d, "name", 4, scr_dyn_new_str(e->name));
3435
- scr_dyn_obj_set(d, "message", 7, scr_dyn_new_str(e->message));
3961
+ d->v.obj.entries[d->v.obj.len - 1].enumerable = false;
3962
+ if (e->name_present) {
3963
+ scr_dyn_obj_set(d, "name", 4, scr_dyn_new_str(e->name));
3964
+ d->v.obj.entries[d->v.obj.len - 1].enumerable = e->name_enumerable;
3965
+ }
3966
+ if (!e->name_present || !e->message_present) {
3967
+ ScrDyn *prototype = scr_dyn_new_obj();
3968
+ if (!e->name_present) {
3969
+ scr_dyn_obj_set(prototype, "name", 4, scr_dyn_new_str(e->name));
3970
+ prototype->v.obj.entries[prototype->v.obj.len - 1].enumerable = false;
3971
+ }
3972
+ if (!e->message_present) {
3973
+ scr_dyn_obj_set(prototype, "message", 7, scr_dyn_new_str(e->message));
3974
+ prototype->v.obj.entries[prototype->v.obj.len - 1].enumerable = false;
3975
+ }
3976
+ scr_dyn_release(scr_dyn_set_prototype(d, prototype));
3977
+ scr_dyn_release(prototype);
3978
+ }
3979
+ if (e->message_present) {
3980
+ scr_dyn_obj_set(d, "message", 7, scr_dyn_new_str(e->message));
3981
+ d->v.obj.entries[d->v.obj.len - 1].enumerable = e->message_enumerable;
3982
+ }
3983
+ if (e->stack) scr_dyn_obj_set(d, "stack", 5, scr_dyn_new_str(e->stack));
3436
3984
  if (e->code) scr_dyn_obj_set(d, "code", 4, scr_dyn_new_str(e->code));
3437
3985
  if (e->error_cause) {
3438
3986
  scr_dyn_obj_set(d, "cause", 5, scr_dyn_retain(e->error_cause));
@@ -3446,6 +3994,21 @@ ScrDyn *scr_dyn_from_error(const ScrError *e) {
3446
3994
  scr_dyn_obj_set(d, "cause", 5, scr_domex_cause((ScrError *)e));
3447
3995
  }
3448
3996
  }
3997
+ return d;
3998
+ }
3999
+
4000
+ ScrDyn *scr_dyn_from_error(const ScrError *e) {
4001
+ for (size_t i = 0; i < scr_errdyn_n; i++) {
4002
+ if (scr_errdyn_cache[i].err == e) return scr_dyn_retain(scr_errdyn_cache[i].dyn);
4003
+ }
4004
+ ScrDyn *d = NULL;
4005
+ for (size_t i = 0; i < scr_error_dyn_type_count; i++) {
4006
+ if (scr_error_dyn_types[i].vt == e->vt) {
4007
+ d = scr_error_dyn_types[i].box((void *)e);
4008
+ break;
4009
+ }
4010
+ }
4011
+ if (!d) d = scr_error_dyn_fields(e);
3449
4012
  if (scr_errdyn_n == scr_errdyn_cap) {
3450
4013
  scr_errdyn_cap = scr_errdyn_cap ? scr_errdyn_cap * 2 : 8;
3451
4014
  scr_errdyn_cache = realloc(scr_errdyn_cache, scr_errdyn_cap * sizeof *scr_errdyn_cache);
@@ -3474,6 +4037,54 @@ ScrDyn *scr_dyn_from_error(const ScrError *e) {
3474
4037
  * its next boxing answers the same dyn node. The dyn node is borrowed. */
3475
4038
  static void scr_error_cause_drop_impl(void *obj);
3476
4039
 
4040
+ void scr_error_commit_dyn(ScrError *e, const ScrDyn *view) {
4041
+ ScrDynEntry *name_entry = NULL;
4042
+ for (size_t i = 0; i < view->v.obj.len; i++) {
4043
+ ScrDynEntry *entry = &view->v.obj.entries[i];
4044
+ if (entry->key_len == 4 && memcmp(entry->key, "name", 4) == 0) { name_entry = entry; break; }
4045
+ }
4046
+ ScrDyn *name = name_entry ? name_entry->value : NULL;
4047
+ if (name && name->kind != SCR_DYN_STR) {
4048
+ scr_dyn_check_fail(NULL, "string", name);
4049
+ return;
4050
+ }
4051
+ ScrStr *next_name = name ? scr_str_retain(name->v.str) : scr_error_default_name(e);
4052
+ scr_str_release(e->name);
4053
+ e->name = next_name;
4054
+ e->name_present = name != NULL;
4055
+ e->name_enumerable = name_entry && name_entry->enumerable;
4056
+ ScrDyn *message = scr_dyn_obj_get(view, "message", 7);
4057
+ if (message && message->kind != SCR_DYN_STR) {
4058
+ scr_dyn_check_fail(NULL, "string", message);
4059
+ return;
4060
+ }
4061
+ ScrStr *next_message = message ? scr_str_retain(message->v.str) : scr_str_new("", 0);
4062
+ scr_str_release(e->message);
4063
+ e->message = next_message;
4064
+ e->message_present = message != NULL;
4065
+ e->message_enumerable = false;
4066
+ for (size_t i = 0; message && i < view->v.obj.len; i++) {
4067
+ const ScrDynEntry *entry = &view->v.obj.entries[i];
4068
+ if (entry->key_len == 7 && memcmp(entry->key, "message", 7) == 0) e->message_enumerable = entry->enumerable;
4069
+ }
4070
+ ScrDyn *stack = scr_dyn_obj_get(view, "stack", 5);
4071
+ if (stack && stack->kind == SCR_DYN_STR) {
4072
+ ScrStr *replacement = scr_str_retain(stack->v.str);
4073
+ scr_str_release(e->stack);
4074
+ e->stack = replacement;
4075
+ }
4076
+ ScrDyn *cause = scr_dyn_obj_get(view, "cause", 5);
4077
+ scr_error_install_cause_drop(&scr_error_cause_drop_impl);
4078
+ ScrDyn *replacement = cause ? scr_dyn_retain(cause) : NULL;
4079
+ scr_dyn_release(e->error_cause);
4080
+ e->error_cause = replacement;
4081
+ e->cause_enumerable = false;
4082
+ for (size_t i = 0; cause && i < view->v.obj.len; i++) {
4083
+ const ScrDynEntry *entry = &view->v.obj.entries[i];
4084
+ if (entry->key_len == 5 && memcmp(entry->key, "cause", 5) == 0) e->cause_enumerable = entry->enumerable;
4085
+ }
4086
+ }
4087
+
3477
4088
  ScrError *scr_error_from_dyn(const ScrDyn *d) {
3478
4089
  ScrError *hit = scr_errdyn_err_of(d);
3479
4090
  if (hit) return hit;
@@ -3494,6 +4105,8 @@ ScrError *scr_error_from_dyn(const ScrDyn *d) {
3494
4105
  if (en && en->kind == SCR_DYN_STR) {
3495
4106
  scr_str_release(e->name);
3496
4107
  e->name = scr_str_retain(en->v.str);
4108
+ e->name_present = true;
4109
+ e->name_enumerable = true;
3497
4110
  }
3498
4111
  if (ec && ec->kind == SCR_DYN_STR) e->code = scr_str_retain(ec->v.str);
3499
4112
  ScrDyn *cause = scr_dyn_obj_get(d, "cause", 5);
@@ -3539,11 +4152,20 @@ void scr_errdyn_put(ScrError *e, ScrDyn *d) {
3539
4152
  /* Error.cause has one live value even when the Error already crossed a
3540
4153
  * checked-value boundary. Reflective data-property edits update its slot. */
3541
4154
  static void scr_error_sync_cause(ScrDyn *view, const ScrStr *key) {
3542
- if (key->len != 5 || memcmp(key->data, "cause", 5) != 0) return;
4155
+ bool cause = key->len == 5 && memcmp(key->data, "cause", 5) == 0;
4156
+ bool stack = key->len == 5 && memcmp(key->data, "stack", 5) == 0;
4157
+ if (!cause && !stack) return;
3543
4158
  ScrDynEntry *entry = scr_dyn_entry(view, key);
3544
4159
  for (size_t i = 0; i < scr_errdyn_n; i++) {
3545
4160
  if (scr_errdyn_cache[i].dyn != view) continue;
3546
4161
  ScrError *e = scr_errdyn_cache[i].err;
4162
+ if (stack) {
4163
+ if (entry && entry->value->kind == SCR_DYN_STR) {
4164
+ scr_str_release(e->stack);
4165
+ e->stack = scr_str_retain(entry->value->v.str);
4166
+ }
4167
+ continue;
4168
+ }
3547
4169
  if (e->vt == &scr_error_vts[SCR_ERR_DOMEX]) continue;
3548
4170
  ScrDyn *replacement = entry ? scr_dyn_retain(entry->value) : NULL;
3549
4171
  scr_error_install_cause_drop(&scr_error_cause_drop_impl);
@@ -3687,20 +4309,7 @@ ScrStr *scr_dyn_to_string_argument(const ScrDyn *d, const ScrDyn *argument, cons
3687
4309
  scr_str_release(encoding);
3688
4310
  return result;
3689
4311
  }
3690
- if (d->kind == SCR_DYN_NUM && argument->kind != SCR_DYN_UNDEF) {
3691
- double radix;
3692
- if (!scr_dyn_number_coerce_js(argument, &radix)) return NULL;
3693
- if (!isfinite(radix) || trunc(radix) < 2 || trunc(radix) > 36) {
3694
- static const char message[] = "toString() radix argument must be between 2 and 36";
3695
- scr_throw_error_msg(SCR_ERR_RANGE, message, sizeof message - 1);
3696
- return NULL;
3697
- }
3698
- if (trunc(radix) != 10) {
3699
- static const char message[] = "Number.toString with a non-decimal radix has no native lowering";
3700
- scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
3701
- return NULL;
3702
- }
3703
- }
4312
+ if (d->kind == SCR_DYN_NUM) return scr_num_to_string_radix(d->v.num, argument);
3704
4313
  if (d->kind == SCR_DYN_OBJ && !scr_dyn_property_owner(d, "toString", 8) && !scr_dyn_has_object_prototype(d)) {
3705
4314
  ScrJsonBuf b;
3706
4315
  scr_jb_init(&b);
@@ -3709,7 +4318,7 @@ ScrStr *scr_dyn_to_string_argument(const ScrDyn *d, const ScrDyn *argument, cons
3709
4318
  scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&b));
3710
4319
  return scr_str_new("", 0);
3711
4320
  }
3712
- return scr_dyn_to_string(d, NULL);
4321
+ return scr_dyn_to_string_method(d, NULL, what);
3713
4322
  }
3714
4323
 
3715
4324
  /* JS String() over the dyn kind — the WebIDL ToString the web globals
@@ -3929,6 +4538,26 @@ double scr_dyn_number_constructor(const ScrDyn *d) {
3929
4538
  return result;
3930
4539
  }
3931
4540
 
4541
+ ScrBigInt *scr_dyn_bigint_constructor(const ScrDyn *d) {
4542
+ ScrDyn *primitive = scr_dyn_add_primitive(d);
4543
+ if (!primitive) return NULL;
4544
+ ScrBigInt *result = NULL;
4545
+ switch (primitive->kind) {
4546
+ case SCR_DYN_BIGINT: result = scr_bigint_retain(primitive->v.bigint); break;
4547
+ case SCR_DYN_STR: result = scr_bigint_parse(primitive->v.str); break;
4548
+ case SCR_DYN_NUM: result = scr_bigint_from_f64(primitive->v.num); break;
4549
+ case SCR_DYN_BOOL: result = scr_bigint_from_i64(primitive->v.b ? 1 : 0); break;
4550
+ default: {
4551
+ const char *message = primitive->kind == SCR_DYN_NULL ? "Cannot convert null to a BigInt"
4552
+ : primitive->kind == SCR_DYN_UNDEF ? "Cannot convert undefined to a BigInt" : "Cannot convert Symbol() to a BigInt";
4553
+ scr_throw_error_msg(SCR_ERR_TYPE, message, strlen(message));
4554
+ break;
4555
+ }
4556
+ }
4557
+ scr_dyn_release(primitive);
4558
+ return result;
4559
+ }
4560
+
3932
4561
  /* OrdinaryToPrimitive's default hint is numeric for the represented
3933
4562
  * ordinary objects. Retain the primitive itself: addition must choose
3934
4563
  * string concatenation before either side is converted to a number. */
@@ -4040,6 +4669,44 @@ ScrDyn *scr_dyn_increment(const ScrDyn *value, bool increment) {
4040
4669
  return scr_dyn_new_num(value->v.num + (increment ? 1 : -1));
4041
4670
  }
4042
4671
 
4672
+ bool scr_dyn_compare(const ScrDyn *left, const ScrDyn *right, const ScrStr *operation) {
4673
+ // ToPrimitive is observable and always visits the original left operand
4674
+ // first, including the > and <= spellings of relational comparison.
4675
+ ScrDyn *l = scr_dyn_add_primitive(left);
4676
+ if (!l) return false;
4677
+ ScrDyn *r = scr_dyn_add_primitive(right);
4678
+ if (!r) { scr_dyn_release(l); return false; }
4679
+ double order = 2;
4680
+ if (l->kind == SCR_DYN_STR && r->kind == SCR_DYN_STR) {
4681
+ int compared = scr_str_cmp_u16(l->v.str, r->v.str);
4682
+ order = compared < 0 ? -1 : compared > 0 ? 1 : 0;
4683
+ } else if (l->kind == SCR_DYN_BIGINT && r->kind == SCR_DYN_STR) {
4684
+ order = scr_bigint_cmp_string(l->v.bigint, r->v.str);
4685
+ } else if (l->kind == SCR_DYN_STR && r->kind == SCR_DYN_BIGINT) {
4686
+ double opposite = scr_bigint_cmp_string(r->v.bigint, l->v.str);
4687
+ order = opposite == 2 ? 2 : -opposite;
4688
+ } else if (l->kind == SCR_DYN_BIGINT && r->kind == SCR_DYN_BIGINT) {
4689
+ order = scr_bigint_cmp_f64(l->v.bigint, r->v.bigint);
4690
+ } else {
4691
+ double a = 0, b = 0;
4692
+ bool valid = (l->kind == SCR_DYN_BIGINT || scr_dyn_number_coerce_js(l, &a)) &&
4693
+ (r->kind == SCR_DYN_BIGINT || scr_dyn_number_coerce_js(r, &b));
4694
+ if (valid) {
4695
+ if (l->kind == SCR_DYN_BIGINT) order = scr_bigint_cmp_number(l->v.bigint, b);
4696
+ else if (r->kind == SCR_DYN_BIGINT) {
4697
+ double opposite = scr_bigint_cmp_number(r->v.bigint, a);
4698
+ order = opposite == 2 ? 2 : -opposite;
4699
+ } else if (!isnan(a) && !isnan(b)) order = a < b ? -1 : a > b ? 1 : 0;
4700
+ }
4701
+ }
4702
+ scr_dyn_release(l);
4703
+ scr_dyn_release(r);
4704
+ if (scr_exc_pending() || order == 2) return false;
4705
+ return operation->data[0] == '<'
4706
+ ? (operation->len == 2 ? order <= 0 : order < 0)
4707
+ : (operation->len == 2 ? order >= 0 : order > 0);
4708
+ }
4709
+
4043
4710
  ScrDyn *scr_dyn_arithmetic(const ScrDyn *left, const ScrDyn *right, const ScrStr *operation) {
4044
4711
  ScrDyn *l = scr_dyn_to_numeric(left);
4045
4712
  if (!l) return NULL;
@@ -4121,6 +4788,12 @@ static const char *scr_dyn_kind_name(const ScrDyn *d);
4121
4788
  * valid dense index, every other kind false (tsc admits `in` only on
4122
4789
  * object-typed operands). Proxy traps may throw. Borrows both. */
4123
4790
  bool scr_dyn_has_key(const ScrDyn *v, const ScrStr *key) {
4791
+ if (scr_dyn_generator(v)) {
4792
+ static const char *const inherited[] = { "next", "return", "throw", "constructor", "toString", "valueOf", "hasOwnProperty", "propertyIsEnumerable", "isPrototypeOf", "toLocaleString", "__proto__" };
4793
+ for (size_t i = 0; i < sizeof inherited / sizeof inherited[0]; i++)
4794
+ if (key->len == strlen(inherited[i]) && memcmp(key->data, inherited[i], key->len) == 0) return true;
4795
+ return false;
4796
+ }
4124
4797
  if (scr_dyn_class_reflection_fence(v)) return false;
4125
4798
  if (v->kind == SCR_DYN_PROXY) return scr_dyn_proxy_has(v, key);
4126
4799
  if (v->kind == SCR_DYN_JSVAL) return scr_dyn_isl_fence(v, "'in'");
@@ -4131,12 +4804,10 @@ bool scr_dyn_has_key(const ScrDyn *v, const ScrStr *key) {
4131
4804
  return out;
4132
4805
  }
4133
4806
  if (v->kind == SCR_DYN_OBJ) {
4134
- for (const ScrDyn *current = v; current && current->kind == SCR_DYN_OBJ; current = current->prototype) {
4135
- if (scr_dyn_obj_get(current, key->data, key->len)) return true;
4136
- }
4137
- return false;
4807
+ return scr_dyn_property_owner(v, key->data, key->len) != NULL;
4138
4808
  }
4139
4809
  if (v->kind == SCR_DYN_FUNC) {
4810
+ if (scr_dyn_property_owner(v, key->data, key->len)) return true;
4140
4811
  ScrDyn *descriptor = scr_dyn_own_descriptor(v, key);
4141
4812
  bool present = descriptor && descriptor->kind != SCR_DYN_UNDEF;
4142
4813
  scr_dyn_release(descriptor);
@@ -5151,6 +5822,14 @@ static void scr_json_delete_member(ScrDyn *object, const ScrStr *key) {
5151
5822
  void scr_dyn_key_delete(ScrDyn *recv, const ScrStr *key, bool strict) {
5152
5823
  if (scr_dyn_class_reflection_fence(recv)) return;
5153
5824
  if (recv->kind == SCR_DYN_PROXY) { scr_dyn_proxy_delete(recv, key); return; }
5825
+ if (recv->kind == SCR_DYN_TYPED_REF && recv->v.typed_ref.commit &&
5826
+ !strncmp(recv->v.typed_ref.type_key, "record:", 7)) {
5827
+ ScrDyn *materialized = scr_dyn_typed_ref_materialize(recv);
5828
+ if (!scr_exc_pending()) scr_dyn_key_delete(materialized, key, strict);
5829
+ if (!scr_exc_pending()) scr_dyn_typed_ref_commit(recv);
5830
+ scr_dyn_release(materialized);
5831
+ return;
5832
+ }
5154
5833
  if (recv->kind == SCR_DYN_FUNC) {
5155
5834
  if (scr_dyn_fn_property_fence(key)) return;
5156
5835
  ScrDyn *table = scr_dyn_fn_properties(recv);
@@ -5242,6 +5921,7 @@ static ScrDyn *scr_json_revive(ScrDyn *holder, const ScrStr *key,
5242
5921
  ScrDyn *scr_json_parse_reviver(ScrStr *text, const ScrDyn *reviver) {
5243
5922
  ScrDyn *parsed = scr_json_parse(text);
5244
5923
  if (!parsed) return NULL; /* No callback runs on invalid input. */
5924
+ if (reviver->kind != SCR_DYN_FUNC) return parsed;
5245
5925
  ScrDyn *holder = scr_dyn_new_obj();
5246
5926
  scr_dyn_obj_set(holder, "", 0, parsed);
5247
5927
  ScrStr *key = scr_str_new("", 0);
@@ -5461,7 +6141,7 @@ bool scr_dyn_strict_eq(const ScrDyn *a, const ScrDyn *b) {
5461
6141
  return a->v.handle.tag == b->v.handle.tag && a->v.handle.ptr == b->v.handle.ptr;
5462
6142
  case SCR_DYN_PROMISE:
5463
6143
  /* And the PROMISE: one promise crossing twice is one JS value. */
5464
- return a->v.promise == b->v.promise;
6144
+ return a->v.promise == b->v.promise || (scr_dyn_promise_identity_fn && scr_dyn_promise_identity_fn(a->v.promise, b->v.promise));
5465
6145
  case SCR_DYN_JSVAL:
5466
6146
  /* Identity is the ENGINE VALUE, not the box or even the cell: two
5467
6147
  * wraps of one engine value compare ===-equal (the engine's own
@@ -5511,6 +6191,8 @@ static ScrDyn *scr_function_constructor(uint32_t kind) {
5511
6191
  /* Keyed read on a FUNC node (see scr_runtime.h): own props first, then
5512
6192
  * the function-instance built-ins name/length. +1 or NULL. */
5513
6193
  ScrDyn *scr_dyn_fn_get(const ScrDyn *d, const char *key, size_t key_len) {
6194
+ if (d->v.fn.class_obj && d->v.fn.class_obj->static_data && !d->v.fn.clo->props)
6195
+ d->v.fn.clo->props = scr_box_retain(d->v.fn.class_obj->static_data);
5514
6196
  if (!d->v.fn.class_obj && key_len == 9 && !memcmp(key, "prototype", 9) && !d->v.fn.clo->props) {
5515
6197
  if (d->v.fn.clo->function_kind & 1) {
5516
6198
  static const char message[] = "Native generator function prototypes have no lowering";
@@ -5551,6 +6233,7 @@ ScrDyn *scr_dyn_fn_get(const ScrDyn *d, const char *key, size_t key_len) {
5551
6233
  if (key_len == 6 && memcmp(key, "length", 6) == 0) {
5552
6234
  return scr_dyn_new_num((double)d->v.fn.arity);
5553
6235
  }
6236
+ if (key_len == 5 && memcmp(key, "apply", 5) == 0) return scr_dyn_function_apply();
5554
6237
  if (d->v.fn.class_obj) {
5555
6238
  static const char message[] = "scriptc: class properties through unknown other than name and length are not supported";
5556
6239
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
@@ -5567,6 +6250,12 @@ ScrDyn *scr_dyn_fn_get(const ScrDyn *d, const char *key, size_t key_len) {
5567
6250
 
5568
6251
  void scr_sc_validate_options(const ScrDyn *options) {
5569
6252
  if (options == NULL || options->kind == SCR_DYN_UNDEF || options->kind == SCR_DYN_NULL) return;
6253
+ if (options->kind == SCR_DYN_TYPED_REF) {
6254
+ ScrDyn *view = scr_dyn_typed_ref_materialize(options);
6255
+ if (view && !scr_exc_pending()) scr_sc_validate_options(view);
6256
+ scr_dyn_release(view);
6257
+ return;
6258
+ }
5570
6259
  /* An engine-held options bag IS a dictionary to Node — the "cannot be
5571
6260
  * converted" TypeError would be a wrong claim. Loud fence. */
5572
6261
  if (options->kind == SCR_DYN_JSVAL) {
@@ -5581,10 +6270,14 @@ void scr_sc_validate_options(const ScrDyn *options) {
5581
6270
  }
5582
6271
  ScrDyn *tr = scr_dyn_obj_get(options, "transfer", 8); /* borrowed */
5583
6272
  if (tr == NULL || tr->kind == SCR_DYN_UNDEF) return;
6273
+ ScrDyn *transferView = tr->kind == SCR_DYN_TYPED_REF ? scr_dyn_typed_ref_materialize(tr) : NULL;
6274
+ if (scr_exc_pending()) { scr_dyn_release(transferView); return; }
6275
+ if (transferView) tr = transferView;
5584
6276
  if (tr->kind != SCR_DYN_ARR) {
5585
6277
  static const char msg[] =
5586
6278
  "Failed to execute 'structuredClone': transfer in Options can not be converted to sequence.";
5587
6279
  scr_throw_error_msg_code(SCR_ERR_TYPE, msg, sizeof msg - 1, "ERR_INVALID_ARG_TYPE");
6280
+ scr_dyn_release(transferView);
5588
6281
  return;
5589
6282
  }
5590
6283
  if (tr->v.arr.len > 0) {
@@ -5592,6 +6285,7 @@ void scr_sc_validate_options(const ScrDyn *options) {
5592
6285
  * a non-transferable list member. */
5593
6286
  scr_throw_domex("DataCloneError", "Found invalid value in transferList.");
5594
6287
  }
6288
+ scr_dyn_release(transferView);
5595
6289
  }
5596
6290
 
5597
6291
  /* The parent chain rides the C stack: a revisit is a cycle. */
@@ -5745,6 +6439,16 @@ bool scr_dyn_err_instanceof(const ScrDyn *d, double kind) {
5745
6439
 
5746
6440
  static ScrDyn *scr_dyn_obj_read_receiver(const ScrDyn *d, const char *key, size_t key_len, const ScrDyn *receiver) {
5747
6441
  for (const ScrDyn *current = d; current; current = current->prototype) {
6442
+ if (current == scr_builtin_object_prototype) {
6443
+ scr_dyn_class_reflection_fence(current);
6444
+ return NULL;
6445
+ }
6446
+ if (current->kind == SCR_DYN_FUNC) {
6447
+ ScrDyn *table = scr_dyn_fn_properties(current);
6448
+ ScrDyn *result = scr_dyn_obj_read_receiver(table, key, key_len, receiver);
6449
+ scr_dyn_release(table);
6450
+ return result;
6451
+ }
5748
6452
  if (current->kind == SCR_DYN_ARR) {
5749
6453
  if (key_len == 6 && memcmp(key, "length", 6) == 0) return scr_dyn_new_num((double)current->v.arr.len);
5750
6454
  double index;
@@ -5793,7 +6497,77 @@ static ScrDyn *scr_dyn_obj_read_receiver(const ScrDyn *d, const char *key, size_
5793
6497
  return scr_dyn_retain(scr_dyn_undefined());
5794
6498
  }
5795
6499
 
6500
+ static SCR_TL ScrDyn *scr_function_apply_value;
6501
+
6502
+ static void scr_function_apply_cleanup(void) {
6503
+ scr_dyn_release(scr_function_apply_value);
6504
+ scr_function_apply_value = NULL;
6505
+ }
6506
+
6507
+ ScrDyn *scr_dyn_apply_array_like(const ScrDyn *target, const ScrDyn *receiver, const ScrDyn *arguments, const char *what) {
6508
+ ScrDyn *list = scr_dyn_new_arr();
6509
+ if (arguments && arguments->kind != SCR_DYN_UNDEF && arguments->kind != SCR_DYN_NULL) {
6510
+ if (!scr_iterator_object(arguments)) {
6511
+ static const char message[] = "CreateListFromArrayLike called on non-object";
6512
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6513
+ } else {
6514
+ ScrDyn *length = scr_iterator_read(arguments, "length", 6);
6515
+ double count = 0;
6516
+ bool ok = length && scr_dyn_number_coerce_js(length, &count);
6517
+ scr_dyn_release(length);
6518
+ if (ok && count > 1000000) {
6519
+ static const char message[] = "Function.prototype.apply exceeds the native argument limit";
6520
+ scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
6521
+ } else if (ok) for (size_t i = 0; (double)i < floor(count); i++) {
6522
+ char key[32];
6523
+ int size = snprintf(key, sizeof key, "%zu", i);
6524
+ ScrDyn *value = scr_iterator_read(arguments, key, (size_t)size);
6525
+ if (!value) break;
6526
+ scr_dyn_arr_push(list, value);
6527
+ }
6528
+ }
6529
+ }
6530
+ ScrDyn *result = NULL;
6531
+ if (!scr_exc_pending()) {
6532
+ scr_dyn_this_push_dyn(receiver);
6533
+ result = scr_dyn_call(target, list->v.arr.items, list->v.arr.len, what);
6534
+ scr_dyn_this_pop();
6535
+ }
6536
+ scr_dyn_release(list);
6537
+ return result;
6538
+ }
6539
+
6540
+ static ScrDyn *scr_function_apply_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
6541
+ (void)closure;
6542
+ ScrDyn *receiver = scr_dyn_this_get();
6543
+ if (receiver->kind != SCR_DYN_FUNC) {
6544
+ scr_dyn_release(receiver);
6545
+ static const char message[] = "Function.prototype.apply was called on a non-callable value";
6546
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6547
+ return NULL;
6548
+ }
6549
+ ScrDyn *result = scr_dyn_apply_array_like(receiver, argc ? args[0] : scr_dyn_undefined(),
6550
+ argc > 1 ? args[1] : scr_dyn_undefined(), "Function.prototype.apply");
6551
+ scr_dyn_release(receiver);
6552
+ return result;
6553
+ }
6554
+
6555
+ ScrDyn *scr_dyn_function_apply(void) {
6556
+ if (!scr_function_apply_value) {
6557
+ scr_function_apply_value = scr_dyn_new_func(scr_closure_new(NULL, 0), scr_function_apply_call,
6558
+ 2, "native:Function.prototype.apply", "apply");
6559
+ scr_atexit(scr_function_apply_cleanup);
6560
+ }
6561
+ return scr_dyn_retain(scr_function_apply_value);
6562
+ }
6563
+
5796
6564
  ScrDyn *scr_dyn_obj_read(const ScrDyn *d, const char *key, size_t key_len) {
6565
+ if (d->kind == SCR_DYN_PROXY) {
6566
+ ScrStr *name = scr_str_new(key, key_len);
6567
+ ScrDyn *value = scr_dyn_proxy_get(d, name);
6568
+ scr_str_release(name);
6569
+ return value;
6570
+ }
5797
6571
  return scr_dyn_obj_read_receiver(d, key, key_len, d);
5798
6572
  }
5799
6573
 
@@ -5864,6 +6638,13 @@ ScrDyn *scr_dyn_obj_own_keys(const ScrDyn *v) {
5864
6638
  }
5865
6639
 
5866
6640
  ScrDyn *scr_dyn_get_own_property_names(const ScrDyn *value) {
6641
+ if (value->kind == SCR_DYN_TYPED_REF) {
6642
+ ScrDyn *view = scr_dyn_typed_ref_materialize(value);
6643
+ if (scr_exc_pending()) { scr_dyn_release(view); return NULL; }
6644
+ ScrDyn *result = scr_dyn_get_own_property_names(view);
6645
+ scr_dyn_release(view);
6646
+ return result;
6647
+ }
5867
6648
  if (value->kind == SCR_DYN_FUNC) {
5868
6649
  if (scr_dyn_class_reflection_fence(value)) return NULL;
5869
6650
  ScrDyn *table = scr_dyn_fn_properties(value);
@@ -5905,6 +6686,13 @@ ScrDyn *scr_dyn_get_own_property_names(const ScrDyn *value) {
5905
6686
  }
5906
6687
 
5907
6688
  ScrDyn *scr_dyn_get_own_property_symbols(const ScrDyn *value) {
6689
+ if (value->kind == SCR_DYN_TYPED_REF) {
6690
+ ScrDyn *view = scr_dyn_typed_ref_materialize(value);
6691
+ if (scr_exc_pending()) { scr_dyn_release(view); return NULL; }
6692
+ ScrDyn *result = scr_dyn_get_own_property_symbols(view);
6693
+ scr_dyn_release(view);
6694
+ return result;
6695
+ }
5908
6696
  if (value->kind == SCR_DYN_NULL || value->kind == SCR_DYN_UNDEF) {
5909
6697
  static const char message[] = "Cannot convert undefined or null to object";
5910
6698
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
@@ -5920,13 +6708,20 @@ ScrDyn *scr_dyn_get_own_property_symbols(const ScrDyn *value) {
5920
6708
  }
5921
6709
 
5922
6710
  ScrDyn *scr_dyn_get_own_property_descriptors(ScrDyn *object) {
6711
+ if (object->kind == SCR_DYN_TYPED_REF) {
6712
+ ScrDyn *view = scr_dyn_typed_ref_materialize(object);
6713
+ if (scr_exc_pending()) { scr_dyn_release(view); return NULL; }
6714
+ ScrDyn *result = scr_dyn_get_own_property_descriptors(view);
6715
+ scr_dyn_release(view);
6716
+ return result;
6717
+ }
5923
6718
  if (scr_dyn_class_reflection_fence(object)) return NULL;
5924
6719
  if (object->kind == SCR_DYN_UNDEF || object->kind == SCR_DYN_NULL) {
5925
6720
  static const char message[] = "Cannot convert undefined or null to object";
5926
6721
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
5927
6722
  return NULL;
5928
6723
  }
5929
- if (object->kind == SCR_DYN_PROXY || object->kind == SCR_DYN_TYPED_REF ||
6724
+ if (object->kind == SCR_DYN_PROXY ||
5930
6725
  object->kind == SCR_DYN_JSVAL || object->kind == SCR_DYN_HANDLE) {
5931
6726
  static const char message[] = "Object.getOwnPropertyDescriptors on this value is not supported yet";
5932
6727
  scr_throw_error_msg(SCR_ERR_ERROR, message, sizeof message - 1);
@@ -5957,6 +6752,21 @@ ScrDyn *scr_dyn_get_own_property_descriptors(ScrDyn *object) {
5957
6752
  return result;
5958
6753
  }
5959
6754
 
6755
+ ScrDyn *scr_dyn_own_keys(const ScrDyn *value) {
6756
+ if (!scr_dyn_to_primitive_result_is_object(value)) {
6757
+ static const char message[] = "Reflect.ownKeys called on non-object";
6758
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6759
+ return NULL;
6760
+ }
6761
+ ScrDyn *names = scr_dyn_get_own_property_names(value);
6762
+ if (!names) return NULL;
6763
+ ScrDyn *symbols = scr_dyn_get_own_property_symbols(value);
6764
+ if (!symbols) { scr_dyn_release(names); return NULL; }
6765
+ for (size_t i = 0; i < symbols->v.arr.len; i++) scr_dyn_arr_push(names, scr_dyn_retain(symbols->v.arr.items[i]));
6766
+ scr_dyn_release(symbols);
6767
+ return names;
6768
+ }
6769
+
5960
6770
  static void scr_dyn_objwalk_push(ScrDyn *out, ScrObjWalk mode, const char *key,
5961
6771
  size_t key_len, ScrDyn *value /* borrowed */) {
5962
6772
  switch (mode) {
@@ -6386,6 +7196,33 @@ ScrDyn *scr_dyn_copy_data_properties(ScrDyn *target, const ScrDyn *src) {
6386
7196
  return scr_exc_pending() ? NULL : scr_dyn_retain(target);
6387
7197
  }
6388
7198
 
7199
+ ScrDyn *scr_dyn_object_rest(const ScrDyn *source, const ScrDyn *excluded) {
7200
+ ScrDyn *out = scr_dyn_new_obj();
7201
+ ScrDyn *names = scr_dyn_get_own_property_names(source);
7202
+ if (!names) { scr_dyn_release(out); return NULL; }
7203
+ ScrDyn *symbols = scr_dyn_get_own_property_symbols(source);
7204
+ if (!symbols) { scr_dyn_release(names); scr_dyn_release(out); return NULL; }
7205
+ for (size_t i = 0; i < symbols->v.arr.len; i++) scr_dyn_arr_push(names, scr_dyn_retain(symbols->v.arr.items[i]));
7206
+ scr_dyn_release(symbols);
7207
+ for (size_t i = 0; i < names->v.arr.len && !scr_exc_pending(); i++) {
7208
+ ScrDyn *key = names->v.arr.items[i];
7209
+ bool skip = false;
7210
+ for (size_t j = 0; j < excluded->v.arr.len; j++) {
7211
+ if (scr_dyn_strict_eq(key, excluded->v.arr.items[j])) { skip = true; break; }
7212
+ }
7213
+ if (skip || !scr_dyn_key_probe_computed(source, key, 2)) continue;
7214
+ ScrDyn *value = key->kind == SCR_DYN_SYMBOL ? scr_dyn_symbol_key_get(source, key, false) : scr_iterator_read(source, key->v.str->data, key->v.str->len);
7215
+ if (!scr_exc_pending()) {
7216
+ if (key->kind == SCR_DYN_SYMBOL) scr_dyn_symbol_key_set(out, key, value);
7217
+ else scr_dyn_obj_set(out, key->v.str->data, key->v.str->len, scr_dyn_retain(value));
7218
+ }
7219
+ scr_dyn_release(value);
7220
+ }
7221
+ scr_dyn_release(names);
7222
+ if (scr_exc_pending()) { scr_dyn_release(out); return NULL; }
7223
+ return out;
7224
+ }
7225
+
6389
7226
  /* Compiler-owned native class views retain every property and its flags,
6390
7227
  * including nonenumerable data, without invoking accessors. */
6391
7228
  ScrDyn *scr_dyn_copy_property_descriptors(ScrDyn *target, const ScrDyn *src) {
@@ -6429,6 +7266,19 @@ void scr_dyn_pack_push_spread(ScrDyn *pack, const ScrDyn *src, const ScrStr *wha
6429
7266
  * Symbol(Symbol.iterator))". The compiler picks the variant by the
6430
7267
  * spread's syntactic position. MAY THROW (pending). Borrows src. */
6431
7268
  void scr_dyn_pack_push_spread_iter(ScrDyn *pack, const ScrDyn *src) {
7269
+ if (src->kind == SCR_DYN_TYPED_REF) {
7270
+ ScrDyn *view = scr_dyn_typed_ref_materialize(src);
7271
+ if (!scr_exc_pending()) scr_dyn_pack_push_spread_iter(pack, view);
7272
+ scr_dyn_release(view);
7273
+ return;
7274
+ }
7275
+ if (src->kind == SCR_DYN_HANDLE && scr_dyn_handle_ops_of(src)->iter_pack) {
7276
+ ScrDyn *items = scr_dyn_handle_ops_of(src)->iter_pack(src->v.handle.ptr);
7277
+ if (!items) return;
7278
+ scr_dyn_pack_push_spread_iter(pack, items);
7279
+ scr_dyn_release(items);
7280
+ return;
7281
+ }
6432
7282
  if (src->kind == SCR_DYN_ARR || src->kind == SCR_DYN_BYTES ||
6433
7283
  src->kind == SCR_DYN_STR) {
6434
7284
  scr_dyn_arr_push_spread(pack, src, ""); /* iterable kinds never throw */
@@ -6470,6 +7320,10 @@ void scr_dyn_pack_push_spread_iter(ScrDyn *pack, const ScrDyn *src) {
6470
7320
  * ToObject TypeError first (Node throws before looking at sources), then
6471
7321
  * each source's own-member copy left to right, answering the target
6472
7322
  * retained (+1) — identity, like JS. */
7323
+ ScrDyn *scr_dyn_reflect_apply(ScrDyn *target, ScrDyn *receiver, ScrDyn *arguments_list) {
7324
+ return scr_dyn_apply_array_like(target, receiver, arguments_list, "Reflect.apply");
7325
+ }
7326
+
6473
7327
  ScrDyn *scr_dyn_assign_all(ScrDyn *target, const ScrDyn *sources) {
6474
7328
  if (target->kind == SCR_DYN_UNDEF || target->kind == SCR_DYN_NULL) {
6475
7329
  const char *m = "Cannot convert undefined or null to object";
@@ -6598,6 +7452,12 @@ bool scr_dyn_has_own(const ScrDyn *v, const ScrStr *key) {
6598
7452
 
6599
7453
  bool scr_dyn_property_is_enumerable(const ScrDyn *value, const ScrStr *key) {
6600
7454
  if (scr_dyn_class_reflection_fence(value)) return false;
7455
+ if (value->kind == SCR_DYN_TYPED_REF) {
7456
+ ScrDyn *view = scr_dyn_typed_ref_materialize(value);
7457
+ bool result = !scr_exc_pending() && scr_dyn_property_is_enumerable(view, key);
7458
+ scr_dyn_release(view);
7459
+ return result;
7460
+ }
6601
7461
  if (value->kind == SCR_DYN_UNDEF || value->kind == SCR_DYN_NULL) {
6602
7462
  static const char message[] = "Cannot convert undefined or null to object";
6603
7463
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
@@ -6641,6 +7501,7 @@ void scr_error_init_options(void *obj, int kind, const ScrDyn *message, const Sc
6641
7501
  return;
6642
7502
  }
6643
7503
  scr_error_init(obj, kind, text);
7504
+ ((ScrError *)obj)->message_present = message && message->kind != SCR_DYN_UNDEF;
6644
7505
  scr_str_release(text);
6645
7506
  ScrDyn *view = options && options->kind == SCR_DYN_TYPED_REF
6646
7507
  ? scr_dyn_typed_ref_materialize(options) : NULL;
@@ -6673,7 +7534,15 @@ ScrError *scr_error_new_options(int kind, const ScrDyn *message, const ScrDyn *o
6673
7534
 
6674
7535
  ScrDyn *scr_error_cause(ScrError *e) {
6675
7536
  for (size_t i = 0; i < scr_errdyn_n; i++) {
6676
- if (scr_errdyn_cache[i].err == e) return scr_dyn_obj_read(scr_errdyn_cache[i].dyn, "cause", 5);
7537
+ if (scr_errdyn_cache[i].err != e) continue;
7538
+ ScrDyn *value = scr_errdyn_cache[i].dyn;
7539
+ if (value->kind == SCR_DYN_TYPED_REF) {
7540
+ ScrDyn *view = scr_dyn_typed_ref_materialize(value);
7541
+ ScrDyn *cause = scr_dyn_obj_read(view, "cause", 5);
7542
+ scr_dyn_release(view);
7543
+ return cause;
7544
+ }
7545
+ return scr_dyn_obj_read(value, "cause", 5);
6677
7546
  }
6678
7547
  return e->error_cause ? scr_dyn_retain(e->error_cause) : scr_dyn_undefined();
6679
7548
  }
@@ -6693,6 +7562,12 @@ void scr_error_set_cause(ScrError *e, ScrDyn *value) {
6693
7562
  e->error_cause = replacement;
6694
7563
  }
6695
7564
 
7565
+ void scr_error_define_cause(ScrError *e, ScrDyn *value) {
7566
+ scr_error_delete_cause(e);
7567
+ scr_error_set_cause(e, value);
7568
+ }
7569
+
7570
+
6696
7571
  void scr_error_delete_cause(ScrError *e) {
6697
7572
  for (size_t i = 0; i < scr_errdyn_n; i++) {
6698
7573
  if (scr_errdyn_cache[i].err != e) continue;
@@ -7337,7 +8212,7 @@ typedef struct ScrWeakEntry {
7337
8212
  } ScrWeakEntry;
7338
8213
 
7339
8214
  struct ScrWeakMap { size_t rc; ScrWeakEntry *entries; bool is_set; };
7340
- /* Weak observers borrow key identities. Values remain ordinary RC edges;
8215
+ /* Weak observers borrow key identities. Values are traced strong edges;
7341
8216
  * value-to-key cycles require explicit deletion or container disposal. */
7342
8217
  #define SCR_WEAK_BUCKETS 1024
7343
8218
  static SCR_TL ScrWeakEntry *scr_weak_entries[SCR_WEAK_BUCKETS];
@@ -7346,7 +8221,7 @@ static size_t scr_weak_bucket(void *key) {
7346
8221
  return ((bits >> 4) ^ (bits >> 14)) & (SCR_WEAK_BUCKETS - 1);
7347
8222
  }
7348
8223
 
7349
- static void scr_weak_remove(ScrWeakEntry *entry) {
8224
+ static void scr_weak_remove_impl(ScrWeakEntry *entry, bool collected) {
7350
8225
  ScrWeakEntry **slot = &entry->owner->entries;
7351
8226
  while (*slot != entry) slot = &(*slot)->next;
7352
8227
  *slot = entry->next;
@@ -7356,7 +8231,22 @@ static void scr_weak_remove(ScrWeakEntry *entry) {
7356
8231
  ScrDyn *value = entry->value;
7357
8232
  free(entry);
7358
8233
  /* Unlink before release: releasing a value can dispose another key. */
7359
- scr_dyn_release(value);
8234
+ if (!collected) scr_dyn_release(value);
8235
+ }
8236
+
8237
+ static void scr_weak_remove(ScrWeakEntry *entry) {
8238
+ scr_weak_remove_impl(entry, scr_cyc_hdr(entry->owner)->color == SCR_CYC_DOOMED);
8239
+ }
8240
+
8241
+ static void scr_weak_map_trace(void *ptr, ScrTraceVisit visit, void *ctx) {
8242
+ for (ScrWeakEntry *entry = ((ScrWeakMap *)ptr)->entries; entry; entry = entry->next)
8243
+ visit(entry->value, ctx);
8244
+ }
8245
+
8246
+ static void scr_weak_map_gcfree(void *ptr) {
8247
+ ScrWeakMap *map = ptr;
8248
+ while (map->entries) scr_weak_remove_impl(map->entries, true);
8249
+ scr_cyc_free(map);
7360
8250
  }
7361
8251
 
7362
8252
  static void scr_weak_disposed(void *key) {
@@ -7375,10 +8265,11 @@ static void *scr_weak_map_retain(void *ptr) {
7375
8265
 
7376
8266
  static void scr_weak_map_release(void *ptr) {
7377
8267
  ScrWeakMap *map = ptr;
7378
- if (--map->rc) return;
8268
+ if (--map->rc) { scr_cyc_on_release(map); return; }
8269
+ scr_cyc_on_dead(map);
7379
8270
  scr_weak_dispose(map);
7380
8271
  while (map->entries) scr_weak_remove(map->entries);
7381
- free(map);
8272
+ scr_cyc_free(map);
7382
8273
  }
7383
8274
 
7384
8275
  /* Return 1 for an observed identity, 0 for a primitive, and -1 for a
@@ -7399,9 +8290,16 @@ static int scr_weak_key(const ScrDyn *key, void **ptr, unsigned *kind) {
7399
8290
  *kind = key->v.fn.class_obj ? 3 : 2; return 1;
7400
8291
  case SCR_DYN_HANDLE:
7401
8292
  if (key->v.handle.tag != SCR_DYNH_ARRAY_BUFFER && key->v.handle.tag != SCR_DYNH_WEAK_MAP &&
7402
- key->v.handle.tag != SCR_DYNH_WEAK_SET && key->v.handle.tag != SCR_DYNH_STDIO) return -1;
8293
+ key->v.handle.tag != SCR_DYNH_WEAK_SET && key->v.handle.tag != SCR_DYNH_STDIO &&
8294
+ key->v.handle.tag != SCR_DYNH_FETCH_REQUEST && key->v.handle.tag != SCR_DYNH_FETCH_RESPONSE &&
8295
+ key->v.handle.tag != SCR_DYNH_MAP && key->v.handle.tag != SCR_DYNH_SET) return -1;
7403
8296
  *ptr = key->v.handle.ptr; *kind = 4 + key->v.handle.tag; return 1;
7404
- case SCR_DYN_TYPED_REF: case SCR_DYN_PROMISE: case SCR_DYN_JSVAL:
8297
+ case SCR_DYN_TYPED_REF:
8298
+ if (!key->v.typed_ref.observed) return -1;
8299
+ *ptr = key->v.typed_ref.ptr; *kind = 32; return 1;
8300
+ case SCR_DYN_PROMISE:
8301
+ *ptr = key->v.promise; *kind = 33; return 1;
8302
+ case SCR_DYN_JSVAL:
7405
8303
  return -1;
7406
8304
  default: return 0;
7407
8305
  }
@@ -7533,7 +8431,7 @@ static ScrDyn *scr_weak_collection_new(ScrDyn *seed, bool is_set) {
7533
8431
  ScrDynHandleTag tag = is_set ? SCR_DYNH_WEAK_SET : SCR_DYNH_WEAK_MAP;
7534
8432
  scr_weak_dispose_hook = &scr_weak_disposed;
7535
8433
  scr_dyn_handle_install(tag, is_set ? &set_ops : &map_ops);
7536
- ScrWeakMap *map = calloc(1, sizeof *map);
8434
+ ScrWeakMap *map = scr_cyc_alloc(sizeof *map, scr_weak_map_trace, scr_weak_map_gcfree);
7537
8435
  if (!map) scr_json_oom();
7538
8436
  map->rc = 1;
7539
8437
  map->is_set = is_set;
@@ -7720,12 +8618,15 @@ static ScrDyn *scr_native_set_invoke(void *ptr, ScrDyn *self, const char *method
7720
8618
  ScrMap *set = ptr;
7721
8619
  ScrDyn *value = argc ? args[0] : scr_dyn_undefined();
7722
8620
  if (strcmp(method, "add") == 0) {
7723
- scr_map_set_ref_f64(set, value, 1);
8621
+ scr_map_dyn_set(set, value, NULL, true);
8622
+ if (scr_exc_pending()) return NULL;
7724
8623
  return scr_dyn_retain(self);
7725
8624
  }
7726
- if (strcmp(method, "has") == 0) return scr_dyn_new_bool(scr_map_has_ref(set, value));
7727
- if (strcmp(method, "delete") == 0) return scr_dyn_new_bool(scr_map_delete_ref(set, value));
8625
+ if (strcmp(method, "has") == 0) return scr_dyn_new_bool(scr_map_dyn_has(set, value, false));
8626
+ if (strcmp(method, "delete") == 0) return scr_dyn_new_bool(scr_map_dyn_has(set, value, true));
7728
8627
  if (strcmp(method, "clear") == 0) { scr_map_clear(set); return scr_dyn_retain(scr_dyn_undefined()); }
8628
+ if (strcmp(method, "values") == 0 || strcmp(method, "keys") == 0) return scr_native_collection_iterator(self, 0);
8629
+ if (strcmp(method, "entries") == 0) return scr_native_collection_iterator(self, 2);
7729
8630
  if (strcmp(method, "forEach") == 0) {
7730
8631
  if (value->kind != SCR_DYN_FUNC &&
7731
8632
  !(value->kind == SCR_DYN_JSVAL && scr_dyn_isl_typeof_is(value, "function"))) {
@@ -7748,7 +8649,7 @@ static ScrDyn *scr_native_set_invoke(void *ptr, ScrDyn *self, const char *method
7748
8649
  scr_map_iter_enter(set);
7749
8650
  for (double i = 0; i < scr_map_iter_count(set); i++) {
7750
8651
  if (!scr_map_iter_live(set, i)) continue;
7751
- ScrDyn *entry = scr_map_iter_key_ref(set, i);
8652
+ ScrDyn *entry = scr_map_dyn_key(set, i);
7752
8653
  ScrDyn *callback_args[] = {entry, entry, self};
7753
8654
  scr_dyn_this_push_dyn(this_arg);
7754
8655
  ScrDyn *result = scr_dyn_call(value, callback_args, 3, "callback");
@@ -7766,10 +8667,21 @@ static ScrDyn *scr_native_set_invoke(void *ptr, ScrDyn *self, const char *method
7766
8667
  return NULL;
7767
8668
  }
7768
8669
 
8670
+ static ScrDyn *scr_native_set_pack(void *ptr) {
8671
+ ScrMap *set = ptr;
8672
+ ScrDyn *values = scr_dyn_new_arr();
8673
+ scr_map_iter_enter(set);
8674
+ for (double i = 0; i < scr_map_iter_count(set); i++) {
8675
+ if (scr_map_iter_live(set, i)) scr_dyn_arr_push(values, scr_map_dyn_key(set, i));
8676
+ }
8677
+ scr_map_iter_exit(set);
8678
+ return values;
8679
+ }
8680
+
7769
8681
  ScrDyn *scr_dyn_native_set(ScrMap *value) {
7770
8682
  static const ScrDynHandleOps ops = {
7771
8683
  "Set", &scr_map_retain_v, &scr_map_release_v, &scr_native_set_invoke,
7772
- &scr_native_set_get, &scr_weak_map_write, NULL, NULL,
8684
+ &scr_native_set_get, &scr_weak_map_write, NULL, &scr_native_set_pack,
7773
8685
  };
7774
8686
  scr_dyn_handle_install(SCR_DYNH_SET, &ops);
7775
8687
  return scr_dyn_new_handle(value, SCR_DYNH_SET);
@@ -7818,16 +8730,44 @@ static ScrDyn *scr_native_map_invoke(void *ptr, ScrDyn *self, const char *method
7818
8730
  ScrMap *map = ptr;
7819
8731
  ScrDyn *key = argc ? args[0] : scr_dyn_undefined();
7820
8732
  if (strcmp(method, "set") == 0) {
7821
- scr_map_set_ref_ref(map, key, scr_dyn_retain(argc > 1 ? args[1] : scr_dyn_undefined()));
8733
+ scr_map_dyn_set(map, key, argc > 1 ? args[1] : scr_dyn_undefined(), false);
8734
+ if (scr_exc_pending()) return NULL;
7822
8735
  return scr_dyn_retain(self);
7823
8736
  }
7824
8737
  if (strcmp(method, "get") == 0) {
7825
- ScrDyn *value = scr_map_get_ref_ref(map, key);
7826
- return value ? value : scr_dyn_retain(scr_dyn_undefined());
8738
+ return scr_map_dyn_get(map, key);
7827
8739
  }
7828
- if (strcmp(method, "has") == 0) return scr_dyn_new_bool(scr_map_has_ref(map, key));
7829
- if (strcmp(method, "delete") == 0) return scr_dyn_new_bool(scr_map_delete_ref(map, key));
8740
+ if (strcmp(method, "has") == 0) return scr_dyn_new_bool(scr_map_dyn_has(map, key, false));
8741
+ if (strcmp(method, "delete") == 0) return scr_dyn_new_bool(scr_map_dyn_has(map, key, true));
7830
8742
  if (strcmp(method, "clear") == 0) { scr_map_clear(map); return scr_dyn_retain(scr_dyn_undefined()); }
8743
+ if (strcmp(method, "values") == 0) return scr_native_collection_iterator(self, 0);
8744
+ if (strcmp(method, "keys") == 0) return scr_native_collection_iterator(self, 1);
8745
+ if (strcmp(method, "entries") == 0) return scr_native_collection_iterator(self, 2);
8746
+ if (strcmp(method, "forEach") == 0) {
8747
+ if (key->kind != SCR_DYN_FUNC && !(key->kind == SCR_DYN_JSVAL && scr_dyn_isl_typeof_is(key, "function"))) {
8748
+ /* Validate even when there are no entries to visit. */
8749
+ ScrDyn *result = scr_dyn_call(key, NULL, 0, "callback");
8750
+ scr_dyn_release(result);
8751
+ return NULL;
8752
+ }
8753
+ ScrDyn *this_arg = argc > 1 ? args[1] : scr_dyn_undefined();
8754
+ scr_map_iter_enter(map);
8755
+ for (double i = 0; i < scr_map_iter_count(map); i++) {
8756
+ if (!scr_map_iter_live(map, i)) continue;
8757
+ ScrDyn *entry_key = scr_map_dyn_key(map, i);
8758
+ ScrDyn *value = scr_map_dyn_value(map, i);
8759
+ ScrDyn *callback_args[] = {value, entry_key, self};
8760
+ scr_dyn_this_push_dyn(this_arg);
8761
+ ScrDyn *result = scr_dyn_call(key, callback_args, 3, "callback");
8762
+ scr_dyn_this_pop();
8763
+ scr_dyn_release(entry_key);
8764
+ scr_dyn_release(value);
8765
+ scr_dyn_release(result);
8766
+ if (scr_exc_pending()) break;
8767
+ }
8768
+ scr_map_iter_exit(map);
8769
+ return scr_exc_pending() ? NULL : scr_dyn_retain(scr_dyn_undefined());
8770
+ }
7831
8771
  (void)what;
7832
8772
  static const char message[] = "Native Map method has no lowering";
7833
8773
  scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
@@ -7841,8 +8781,8 @@ static ScrDyn *scr_native_map_pack(void *ptr) {
7841
8781
  for (double i = 0; i < scr_map_iter_count(map); i++) {
7842
8782
  if (!scr_map_iter_live(map, i)) continue;
7843
8783
  ScrDyn *pair = scr_dyn_new_arr();
7844
- scr_dyn_arr_push(pair, scr_map_iter_key_ref(map, i));
7845
- scr_dyn_arr_push(pair, scr_map_iter_val_ref(map, i));
8784
+ scr_dyn_arr_push(pair, scr_map_dyn_key(map, i));
8785
+ scr_dyn_arr_push(pair, scr_map_dyn_value(map, i));
7846
8786
  scr_dyn_arr_push(entries, pair);
7847
8787
  }
7848
8788
  scr_map_iter_exit(map);
@@ -7852,7 +8792,7 @@ static ScrDyn *scr_native_map_pack(void *ptr) {
7852
8792
  ScrDyn *scr_dyn_native_map(ScrMap *value) {
7853
8793
  static const ScrDynHandleOps ops = {
7854
8794
  "Map", &scr_map_retain_v, &scr_map_release_v, &scr_native_map_invoke,
7855
- &scr_native_map_get, &scr_weak_map_write, NULL, NULL,
8795
+ &scr_native_map_get, &scr_weak_map_write, NULL, &scr_native_map_pack,
7856
8796
  };
7857
8797
  scr_dyn_handle_install(SCR_DYNH_MAP, &ops);
7858
8798
  return scr_dyn_new_handle(value, SCR_DYNH_MAP);
@@ -7867,7 +8807,40 @@ ScrMap *scr_dyn_native_map_check(const ScrDyn *value, const ScrDynPath *path) {
7867
8807
  return scr_map_retain(value->v.handle.ptr);
7868
8808
  }
7869
8809
 
8810
+ bool scr_dyn_native_collection_is(const ScrDyn *value, int map, const char *type) {
8811
+ if (!(map ? scr_dyn_native_map_is(value) : scr_dyn_native_set_is(value))) return false;
8812
+ const ScrMap *storage = value->v.handle.ptr;
8813
+ return type ? storage->dyn_ops && strcmp(storage->dyn_ops->type, type) == 0 : !storage->dyn_ops;
8814
+ }
8815
+
8816
+ ScrMap *scr_dyn_native_collection_check(const ScrDyn *value, int map, const char *type, const ScrDynPath *path) {
8817
+ if (!scr_dyn_native_collection_is(value, map, type)) {
8818
+ scr_dyn_check_fail(path, type ? type : map ? "Map" : "Set", value);
8819
+ return NULL;
8820
+ }
8821
+ return scr_map_retain(value->v.handle.ptr);
8822
+ }
8823
+
7870
8824
  ScrStr *scr_dyn_to_string_method(const ScrDyn *d, const ScrStr *enc, const ScrStr *what) {
8825
+ /* Object.create receivers must run their inherited formatter before the
8826
+ * default object tag; Effect shard keys use it to produce distinct hashes. */
8827
+ const bool object_method = d->kind == SCR_DYN_OBJ && scr_dyn_property_owner(d, "toString", 8);
8828
+ if (d->kind == SCR_DYN_FUNC || object_method) {
8829
+ ScrDyn *member = object_method ? scr_dyn_obj_read(d, "toString", 8) : scr_dyn_fn_get(d, "toString", 8);
8830
+ if (scr_exc_pending()) { scr_dyn_release(member); return NULL; }
8831
+ if (member && (object_method || member->kind != SCR_DYN_UNDEF)) {
8832
+ scr_dyn_this_push_dyn(d);
8833
+ ScrDyn *value = scr_dyn_call(member, NULL, 0, what->data);
8834
+ scr_dyn_this_pop();
8835
+ scr_dyn_release(member);
8836
+ if (!value) return NULL;
8837
+ ScrStr *result = value->kind == SCR_DYN_STR ? scr_str_retain(value->v.str) : NULL;
8838
+ if (!result) scr_dyn_check_fail(NULL, "string", value);
8839
+ scr_dyn_release(value);
8840
+ return result;
8841
+ }
8842
+ scr_dyn_release(member);
8843
+ }
7871
8844
  if (d->kind == SCR_DYN_OBJ && !scr_dyn_property_owner(d, "toString", 8) && !scr_dyn_has_object_prototype(d)) {
7872
8845
  ScrJsonBuf b;
7873
8846
  scr_jb_init(&b);
@@ -7926,3 +8899,88 @@ bool scr_dyn_is_frozen(const ScrDyn *value) {
7926
8899
  scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
7927
8900
  return false;
7928
8901
  }
8902
+
8903
+ double scr_buffer_byte_length_dyn(ScrDyn *value, ScrStr *encoding) {
8904
+ if (value->kind == SCR_DYN_STR) return scr_bytes_byte_length_str(value->v.str, encoding);
8905
+ if (value->kind == SCR_DYN_BYTES) return scr_bytes_byte_len(value->v.bytes);
8906
+ if (scr_array_buffer_is(value)) return scr_bytes_byte_len(value->v.handle.ptr);
8907
+ static const char message[] = "The string argument must be of type string or an instance of Buffer or ArrayBuffer";
8908
+ scr_throw_error_msg_code(SCR_ERR_TYPE, message, sizeof message - 1, "ERR_INVALID_ARG_TYPE");
8909
+ return 0;
8910
+ }
8911
+
8912
+ /* Radix digit generation follows V8's DoubleToRadixStringView algorithm.
8913
+ * Copyright 2012 the V8 project authors. BSD license in
8914
+ * ../vendor/v8-number-radix/LICENSE. The decimal path retains Ryū. */
8915
+ ScrStr *scr_num_to_string_radix(double value, const ScrDyn *argument) {
8916
+ double requested = 10;
8917
+ if (argument && argument->kind != SCR_DYN_UNDEF &&
8918
+ !scr_dyn_number_coerce_js(argument, &requested)) return NULL;
8919
+ requested = isnan(requested) ? 0 : trunc(requested);
8920
+ if (requested < 2 || requested > 36 || !isfinite(requested)) {
8921
+ static const char message[] = "toString() radix argument must be between 2 and 36";
8922
+ scr_throw_error_msg(SCR_ERR_RANGE, message, sizeof message - 1);
8923
+ return NULL;
8924
+ }
8925
+ int radix = (int)requested;
8926
+ if (radix == 10 || !isfinite(value) || value == 0) return scr_f64_to_scrstr(value);
8927
+ static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
8928
+ char buffer[2200];
8929
+ const size_t middle = sizeof buffer / 2;
8930
+ size_t begin = middle, end = middle;
8931
+ bool negative = value < 0;
8932
+ value = fabs(value);
8933
+ double integer = floor(value), fraction = value - integer;
8934
+ double tolerance = 0.5 * (nextafter(value, INFINITY) - value);
8935
+ if (tolerance <= 0) tolerance = nextafter(0, INFINITY);
8936
+ if (fraction >= tolerance) {
8937
+ buffer[end++] = '.';
8938
+ do {
8939
+ fraction *= radix;
8940
+ tolerance *= radix;
8941
+ int digit = (int)fraction;
8942
+ buffer[end++] = digits[digit];
8943
+ fraction -= digit;
8944
+ if ((fraction > 0.5 || (fraction == 0.5 && (digit & 1))) && fraction + tolerance > 1) {
8945
+ for (;;) {
8946
+ end--;
8947
+ if (end == middle) { integer += 1; break; }
8948
+ char last = buffer[end];
8949
+ digit = last > '9' ? last - 'a' + 10 : last - '0';
8950
+ if (digit + 1 < radix) { buffer[end++] = digits[digit + 1]; break; }
8951
+ }
8952
+ break;
8953
+ }
8954
+ } while (fraction >= tolerance);
8955
+ }
8956
+ /* V8's Double::Exponent is the unbiased exponent minus 52. Beyond
8957
+ * that precision boundary, trailing digits are unrepresented zeros. */
8958
+ while (integer / radix >= 0x1p53) {
8959
+ integer /= radix;
8960
+ buffer[--begin] = '0';
8961
+ }
8962
+ do {
8963
+ double remainder = fmod(integer, radix);
8964
+ buffer[--begin] = digits[(int)remainder];
8965
+ integer = (integer - remainder) / radix;
8966
+ } while (integer > 0);
8967
+ if (negative) buffer[--begin] = '-';
8968
+ return scr_str_new(buffer + begin, end - begin);
8969
+ }
8970
+
8971
+ ScrDyn *scr_caught_to_dyn(const ScrCaught *c) {
8972
+ switch (c->kind) {
8973
+ case SCR_EXC_F64: return scr_dyn_new_num(c->f64);
8974
+ case SCR_EXC_BOOL: return scr_dyn_new_bool(c->b);
8975
+ case SCR_EXC_STR: return scr_dyn_new_str((ScrStr *)c->payload);
8976
+ case SCR_EXC_REF:
8977
+ case SCR_EXC_PRIMITIVE_REF:
8978
+ if (c->retain_fn == scr_dyn_retain_v) return scr_dyn_retain((ScrDyn *)c->payload);
8979
+ return scr_dyn_new_obj();
8980
+ case SCR_EXC_OBJ:
8981
+ if (scr_error_is(c->payload)) return scr_dyn_from_error((const ScrError *)c->payload);
8982
+ return scr_dyn_new_obj();
8983
+ default:
8984
+ return scr_dyn_new_obj();
8985
+ }
8986
+ }