@scriptc/cli-darwin-arm64 0.2.0 → 0.2.2

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 (260) 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 +84 -19
  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_crypto_async.o +0 -0
  18. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_dyn_invoke.o +0 -0
  19. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_error.o +0 -0
  20. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_events.o +0 -0
  21. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_exception.o +0 -0
  22. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_fetch.o +0 -0
  23. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_file_handle.o +0 -0
  24. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_grapheme.o +0 -0
  25. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_http.o +0 -0
  26. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_http2.o +0 -0
  27. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_json.o +0 -0
  28. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_lib.o +0 -0
  29. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_map.o +0 -0
  30. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_net.o +0 -0
  31. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_node_builtin.o +0 -0
  32. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_object.o +0 -0
  33. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_qs.o +0 -0
  34. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_regex.o +0 -0
  35. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_stream.o +0 -0
  36. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_string.o +0 -0
  37. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_symbol.o +0 -0
  38. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_url.o +0 -0
  39. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_array.o +0 -0
  40. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_assert.o +0 -0
  41. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_async.o +0 -0
  42. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_async_dyn.o +0 -0
  43. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bigint.o +0 -0
  44. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
  45. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
  46. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_child.o +0 -0
  47. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_console.o +0 -0
  48. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_console_native.o +0 -0
  49. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_crypto_async.o +0 -0
  50. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_dyn_invoke.o +0 -0
  51. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_error.o +0 -0
  52. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_events.o +0 -0
  53. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_exception.o +0 -0
  54. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_file_handle.o +0 -0
  55. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_grapheme.o +0 -0
  56. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_http.o +0 -0
  57. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_http2.o +0 -0
  58. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_island.o +0 -0
  59. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
  60. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
  61. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_map.o +0 -0
  62. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_net.o +0 -0
  63. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_node_builtin.o +0 -0
  64. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_object.o +0 -0
  65. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_qs.o +0 -0
  66. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
  67. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_stream.o +0 -0
  68. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_string.o +0 -0
  69. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_symbol.o +0 -0
  70. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_url.o +0 -0
  71. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_web.o +0 -0
  72. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  73. package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  74. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_array.o +0 -0
  75. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_assert.o +0 -0
  76. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bigint.o +0 -0
  77. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
  78. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
  79. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_console_native.o +0 -0
  80. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_dyn_invoke.o +0 -0
  81. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_error.o +0 -0
  82. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_exception.o +0 -0
  83. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_grapheme.o +0 -0
  84. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
  85. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
  86. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_map.o +0 -0
  87. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_node_builtin.o +0 -0
  88. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_object.o +0 -0
  89. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
  90. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_string.o +0 -0
  91. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_symbol.o +0 -0
  92. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_url.o +0 -0
  93. package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  94. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_array.o +0 -0
  95. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_assert.o +0 -0
  96. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bigint.o +0 -0
  97. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
  98. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
  99. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_console_native.o +0 -0
  100. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_dyn_invoke.o +0 -0
  101. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_error.o +0 -0
  102. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_exception.o +0 -0
  103. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_grapheme.o +0 -0
  104. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_json.o +0 -0
  105. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
  106. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_map.o +0 -0
  107. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_node_builtin.o +0 -0
  108. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_object.o +0 -0
  109. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
  110. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_string.o +0 -0
  111. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_symbol.o +0 -0
  112. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_url.o +0 -0
  113. package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  114. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_array.o +0 -0
  115. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_assert.o +0 -0
  116. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bigint.o +0 -0
  117. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
  118. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
  119. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_console_native.o +0 -0
  120. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_dyn_invoke.o +0 -0
  121. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_error.o +0 -0
  122. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_exception.o +0 -0
  123. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_grapheme.o +0 -0
  124. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
  125. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
  126. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_map.o +0 -0
  127. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_node_builtin.o +0 -0
  128. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_object.o +0 -0
  129. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
  130. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_string.o +0 -0
  131. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_symbol.o +0 -0
  132. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_url.o +0 -0
  133. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  134. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_array.o +0 -0
  135. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_assert.o +0 -0
  136. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bigint.o +0 -0
  137. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
  138. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
  139. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_console_native.o +0 -0
  140. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_dyn_invoke.o +0 -0
  141. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_error.o +0 -0
  142. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_exception.o +0 -0
  143. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_grapheme.o +0 -0
  144. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
  145. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
  146. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_map.o +0 -0
  147. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_node_builtin.o +0 -0
  148. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_object.o +0 -0
  149. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
  150. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_string.o +0 -0
  151. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_symbol.o +0 -0
  152. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_url.o +0 -0
  153. package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  154. package/dist/lib/runtime-darwin-arm64/artifacts/licenses/v8-number-radix.txt +61 -0
  155. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_array.o +0 -0
  156. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_assert.o +0 -0
  157. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_async.o +0 -0
  158. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_async_dyn.o +0 -0
  159. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bigint.o +0 -0
  160. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes.o +0 -0
  161. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
  162. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_child.o +0 -0
  163. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_console.o +0 -0
  164. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_console_native.o +0 -0
  165. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_crypto_async.o +0 -0
  166. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_dyn_invoke.o +0 -0
  167. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_error.o +0 -0
  168. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_events.o +0 -0
  169. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_exception.o +0 -0
  170. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_fetch.o +0 -0
  171. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_file_handle.o +0 -0
  172. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_grapheme.o +0 -0
  173. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_http.o +0 -0
  174. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_http2.o +0 -0
  175. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_json.o +0 -0
  176. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_lib.o +0 -0
  177. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_map.o +0 -0
  178. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_net.o +0 -0
  179. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_node_builtin.o +0 -0
  180. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_object.o +0 -0
  181. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_qs.o +0 -0
  182. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_regex.o +0 -0
  183. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_stream.o +0 -0
  184. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_string.o +0 -0
  185. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_symbol.o +0 -0
  186. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_url.o +0 -0
  187. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_array.o +0 -0
  188. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_assert.o +0 -0
  189. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_async.o +0 -0
  190. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_async_dyn.o +0 -0
  191. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bigint.o +0 -0
  192. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
  193. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
  194. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_child.o +0 -0
  195. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_console.o +0 -0
  196. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_console_native.o +0 -0
  197. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_crypto_async.o +0 -0
  198. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_dyn_invoke.o +0 -0
  199. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_error.o +0 -0
  200. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_events.o +0 -0
  201. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_exception.o +0 -0
  202. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_file_handle.o +0 -0
  203. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_grapheme.o +0 -0
  204. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_http.o +0 -0
  205. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_http2.o +0 -0
  206. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_island.o +0 -0
  207. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
  208. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
  209. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_map.o +0 -0
  210. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_net.o +0 -0
  211. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_node_builtin.o +0 -0
  212. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_object.o +0 -0
  213. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_qs.o +0 -0
  214. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
  215. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_stream.o +0 -0
  216. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_string.o +0 -0
  217. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_symbol.o +0 -0
  218. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_url.o +0 -0
  219. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_web.o +0 -0
  220. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
  221. package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
  222. package/dist/lib/runtime-darwin-arm64/package.json +1 -1
  223. package/dist/lib/runtime-darwin-arm64/runtime-pack.json +549 -545
  224. package/dist/lib/runtime-sources/package.json +1 -1
  225. package/dist/lib/runtime-sources/src/scr_abort.c +5 -0
  226. package/dist/lib/runtime-sources/src/scr_array.c +16 -0
  227. package/dist/lib/runtime-sources/src/scr_assert.c +1 -0
  228. package/dist/lib/runtime-sources/src/scr_async.c +38 -5
  229. package/dist/lib/runtime-sources/src/scr_async_dyn.c +208 -40
  230. package/dist/lib/runtime-sources/src/scr_bigint.c +8 -0
  231. package/dist/lib/runtime-sources/src/scr_bytes.c +431 -41
  232. package/dist/lib/runtime-sources/src/scr_bytes_io.c +628 -12
  233. package/dist/lib/runtime-sources/src/scr_child.c +544 -17
  234. package/dist/lib/runtime-sources/src/scr_console.c +1 -1
  235. package/dist/lib/runtime-sources/src/scr_crypto_async.c +22 -2
  236. package/dist/lib/runtime-sources/src/scr_dyn_invoke.c +344 -73
  237. package/dist/lib/runtime-sources/src/scr_error.c +52 -5
  238. package/dist/lib/runtime-sources/src/scr_exception.c +21 -5
  239. package/dist/lib/runtime-sources/src/scr_fetch.c +311 -3
  240. package/dist/lib/runtime-sources/src/scr_file_handle.c +31 -0
  241. package/dist/lib/runtime-sources/src/scr_http.c +3 -0
  242. package/dist/lib/runtime-sources/src/scr_island.c +1226 -405
  243. package/dist/lib/runtime-sources/src/scr_island_manifest.h +11 -9
  244. package/dist/lib/runtime-sources/src/scr_json.c +1594 -139
  245. package/dist/lib/runtime-sources/src/scr_json.test.ts +1 -0
  246. package/dist/lib/runtime-sources/src/scr_lib.c +816 -34
  247. package/dist/lib/runtime-sources/src/scr_map.c +47 -0
  248. package/dist/lib/runtime-sources/src/scr_node_builtin.c +10 -0
  249. package/dist/lib/runtime-sources/src/scr_object.c +11 -0
  250. package/dist/lib/runtime-sources/src/scr_qs.c +10 -0
  251. package/dist/lib/runtime-sources/src/scr_regex.c +148 -72
  252. package/dist/lib/runtime-sources/src/scr_runtime.h +257 -41
  253. package/dist/lib/runtime-sources/src/scr_stream.c +197 -0
  254. package/dist/lib/runtime-sources/src/scr_string.c +16 -1
  255. package/dist/lib/runtime-sources/src/scr_symbol.c +5 -0
  256. package/dist/lib/runtime-sources/src/scr_text_decoder_labels.h +225 -0
  257. package/dist/lib/runtime-sources/src/scr_url.c +206 -10
  258. package/dist/lib/runtime-sources/src/scr_web.c +129 -26
  259. package/dist/lib/runtime-sources/vendor/v8-number-radix/LICENSE +61 -0
  260. 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) {
@@ -444,6 +524,7 @@ static ScrDyn *scr_dyn_alloc(ScrDynKind kind) {
444
524
  d->v.arr.properties = NULL;
445
525
  d->v.arr.sealed = false;
446
526
  d->v.arr.frozen = false;
527
+ d->v.arr.presence = NULL;
447
528
  } else if (kind == SCR_DYN_OBJ) {
448
529
  d->v.obj.len = 0; /* cap/entries preserved */
449
530
  d->v.obj.source_identity = NULL;
@@ -490,6 +571,8 @@ static void scr_dyn_dispose(ScrDyn *d, bool collected) {
490
571
  scr_bytes_release(d->v.bytes);
491
572
  break;
492
573
  case SCR_DYN_ARR:
574
+ free(d->v.arr.presence);
575
+ d->v.arr.presence = NULL;
493
576
  if (!collected) {
494
577
  for (size_t i = 0; i < d->v.arr.len; i++) scr_dyn_release(d->v.arr.items[i]);
495
578
  scr_dyn_release(d->v.arr.properties);
@@ -527,11 +610,12 @@ static void scr_dyn_dispose(ScrDyn *d, bool collected) {
527
610
  scr_dyn_jsval_ops()->release(d->v.jsval.cell);
528
611
  break;
529
612
  case SCR_DYN_TYPED_REF:
613
+ scr_typed_ref_forget(d);
530
614
  if (!collected) scr_dyn_release(d->v.typed_ref.materialized);
531
615
  while (d->v.typed_ref.casts) {
532
616
  ScrDynTypedCast *cast = d->v.typed_ref.casts;
533
617
  d->v.typed_ref.casts = cast->next;
534
- cast->release(cast->ptr);
618
+ if (!collected || !cast->traced) cast->release(cast->ptr);
535
619
  free(cast);
536
620
  }
537
621
  if (!collected || !d->v.typed_ref.traced) d->v.typed_ref.release(d->v.typed_ref.ptr);
@@ -652,11 +736,31 @@ void scr_dyn_arr_push(ScrDyn *arr, ScrDyn *item) {
652
736
  ScrDyn **items = realloc(arr->v.arr.items, cap * sizeof *items);
653
737
  if (!items) scr_json_oom();
654
738
  arr->v.arr.items = items;
739
+ if (arr->v.arr.presence) {
740
+ unsigned char *presence = realloc(arr->v.arr.presence, cap);
741
+ if (!presence) scr_json_oom();
742
+ arr->v.arr.presence = presence;
743
+ }
655
744
  arr->v.arr.cap = cap;
656
745
  }
746
+ if (arr->v.arr.presence) arr->v.arr.presence[arr->v.arr.len] = 1;
657
747
  arr->v.arr.items[arr->v.arr.len++] = item; /* ownership moves in */
658
748
  }
659
749
 
750
+ bool scr_dyn_arr_has_index(const ScrDyn *arr, size_t index) {
751
+ return index < arr->v.arr.len && (!arr->v.arr.presence || arr->v.arr.presence[index]);
752
+ }
753
+
754
+ void scr_dyn_arr_push_hole(ScrDyn *arr) {
755
+ scr_dyn_arr_push(arr, scr_dyn_retain(scr_dyn_undefined()));
756
+ if (!arr->v.arr.presence) {
757
+ arr->v.arr.presence = malloc(arr->v.arr.cap);
758
+ if (!arr->v.arr.presence) scr_json_oom();
759
+ memset(arr->v.arr.presence, 1, arr->v.arr.len);
760
+ }
761
+ arr->v.arr.presence[arr->v.arr.len - 1] = 0;
762
+ }
763
+
660
764
  /* Spread completion for a runtime-arity argument list (`f(...xs)` in the
661
765
  * checked-dynamic tier): JS's spread over the checked-dynamic tree's iterable kinds —
662
766
  * arrays element-by-element (retained), strings by code POINT (the string
@@ -793,6 +897,10 @@ ScrDyn *scr_dyn_iter_pack(const ScrDyn *src, const ScrStr *msg) {
793
897
  return scr_dyn_not_iterable(src, msg);
794
898
  }
795
899
 
900
+ ScrDyn *scr_dyn_jsval_iter_n(const ScrDyn *src, double count) {
901
+ return scr_dyn_jsval_ops()->iter_n(src->v.jsval.cell, count);
902
+ }
903
+
796
904
  /* The for-of-over-dyn pack accessors: the emitted index loop drives them
797
905
  * over a scr_dyn_iter_pack result (ARR by construction — the defensive
798
906
  * arms cover nothing reachable from that lowering). Never throw. */
@@ -840,7 +948,13 @@ ScrDyn *scr_dyn_arr_at(const ScrDyn *d, double i) {
840
948
  if (d->kind != SCR_DYN_ARR || i < 0 || i >= (double)d->v.arr.len) {
841
949
  return scr_dyn_retain(scr_dyn_undefined());
842
950
  }
843
- return scr_dyn_retain(d->v.arr.items[(size_t)i]);
951
+ if (scr_dyn_arr_has_index(d, (size_t)i)) return scr_dyn_retain(d->v.arr.items[(size_t)i]);
952
+ char text[32];
953
+ int length = snprintf(text, sizeof text, "%zu", (size_t)i);
954
+ ScrStr *key = scr_str_new(text, (size_t)length);
955
+ ScrDyn *result = scr_dyn_arr_named_get(d, key);
956
+ scr_str_release(key);
957
+ return result;
844
958
  }
845
959
 
846
960
  ScrDyn *scr_dyn_arr_named_get(const ScrDyn *d, const ScrStr *key) {
@@ -848,8 +962,13 @@ ScrDyn *scr_dyn_arr_named_get(const ScrDyn *d, const ScrStr *key) {
848
962
  return scr_dyn_obj_read_receiver(d->v.arr.properties, key->data, key->len, d);
849
963
  const ScrDyn *prototype = d->prototype ? d->prototype :
850
964
  d != scr_builtin_array_prototype ? scr_builtin_array_prototype : NULL;
851
- return prototype ? scr_dyn_obj_read_receiver(prototype, key->data, key->len, d)
965
+ ScrDyn *value = prototype ? scr_dyn_obj_read_receiver(prototype, key->data, key->len, d)
852
966
  : scr_dyn_retain(scr_dyn_undefined());
967
+ if (value && value->kind == SCR_DYN_UNDEF && !d->null_proto && key->len == 11 && !memcmp(key->data, "constructor", 11)) {
968
+ scr_dyn_release(value);
969
+ return scr_dyn_array_constructor();
970
+ }
971
+ return value;
853
972
  }
854
973
 
855
974
  /* Takes ownership of key (malloc'd) and value. Duplicate keys: the LATER
@@ -966,6 +1085,21 @@ static void scr_builtin_array_prototype_cleanup(void) {
966
1085
  scr_dyn_release(prototype);
967
1086
  }
968
1087
 
1088
+ static void scr_builtin_object_prototype_cleanup(void) {
1089
+ ScrDyn *prototype = scr_builtin_object_prototype;
1090
+ scr_builtin_object_prototype = NULL;
1091
+ scr_dyn_release(prototype);
1092
+ }
1093
+
1094
+ ScrDyn *scr_dyn_object_prototype(void) {
1095
+ if (!scr_builtin_object_prototype) {
1096
+ scr_builtin_object_prototype = scr_dyn_alloc(SCR_DYN_OBJ);
1097
+ scr_builtin_object_prototype->null_proto = true;
1098
+ scr_atexit(scr_builtin_object_prototype_cleanup);
1099
+ }
1100
+ return scr_dyn_retain(scr_builtin_object_prototype);
1101
+ }
1102
+
969
1103
  ScrDyn *scr_dyn_array_prototype_base(void) {
970
1104
  if (!scr_builtin_array_prototype) {
971
1105
  scr_builtin_array_prototype = scr_dyn_alloc(SCR_DYN_ARR);
@@ -1005,7 +1139,7 @@ ScrDyn *scr_dyn_new_obj_null_proto(void) {
1005
1139
  }
1006
1140
 
1007
1141
  ScrDyn *scr_dyn_obj_create(ScrDyn *prototype) {
1008
- if (scr_dyn_class_reflection_fence(prototype)) return NULL;
1142
+ if (prototype != scr_builtin_object_prototype && scr_dyn_class_reflection_fence(prototype)) return NULL;
1009
1143
  if (prototype->kind != SCR_DYN_OBJ && prototype->kind != SCR_DYN_ARR && prototype->kind != SCR_DYN_NULL) {
1010
1144
  static const char message[] = "Object prototype may only be an Object or null";
1011
1145
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
@@ -1017,7 +1151,15 @@ ScrDyn *scr_dyn_obj_create(ScrDyn *prototype) {
1017
1151
  }
1018
1152
 
1019
1153
  ScrDyn *scr_dyn_get_prototype(ScrDyn *object) {
1154
+ if (object == scr_builtin_object_prototype) return scr_dyn_new_null();
1020
1155
  if (scr_dyn_class_reflection_fence(object)) return NULL;
1156
+ if (object->kind == SCR_DYN_TYPED_REF && strncmp(object->v.typed_ref.type_key, "object:", 7)) {
1157
+ ScrDyn *view = scr_dyn_typed_ref_materialize(object);
1158
+ if (!view) return NULL;
1159
+ ScrDyn *result = scr_dyn_get_prototype(view);
1160
+ scr_dyn_release(view);
1161
+ return result;
1162
+ }
1021
1163
  if (object->kind == SCR_DYN_FUNC && object->v.fn.clo->props) {
1022
1164
  ScrDyn *table = scr_dyn_fn_properties(object);
1023
1165
  ScrDyn *result = table->prototype ? scr_dyn_retain(table->prototype)
@@ -1032,7 +1174,9 @@ ScrDyn *scr_dyn_get_prototype(ScrDyn *object) {
1032
1174
  if (object->kind == SCR_DYN_OBJ) {
1033
1175
  if (object->prototype) return scr_dyn_retain(object->prototype);
1034
1176
  if (object->null_proto) return scr_dyn_new_null();
1177
+ return scr_dyn_object_prototype();
1035
1178
  }
1179
+ if (object == scr_builtin_array_prototype) return scr_dyn_object_prototype();
1036
1180
  if (object->kind == SCR_DYN_NULL || object->kind == SCR_DYN_UNDEF) {
1037
1181
  static const char message[] = "Cannot convert undefined or null to object";
1038
1182
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
@@ -1045,6 +1189,15 @@ ScrDyn *scr_dyn_get_prototype(ScrDyn *object) {
1045
1189
 
1046
1190
  ScrDyn *scr_dyn_set_prototype(ScrDyn *object, ScrDyn *prototype) {
1047
1191
  if (scr_dyn_class_reflection_fence(object) || scr_dyn_class_reflection_fence(prototype)) return NULL;
1192
+ if (object->kind == SCR_DYN_TYPED_REF) {
1193
+ ScrDyn *view = scr_dyn_typed_ref_materialize(object);
1194
+ if (scr_exc_pending()) { scr_dyn_release(view); return NULL; }
1195
+ ScrDyn *result = scr_dyn_set_prototype(view, prototype);
1196
+ scr_dyn_release(view);
1197
+ if (!result) return NULL;
1198
+ scr_dyn_release(result);
1199
+ return scr_dyn_retain(object);
1200
+ }
1048
1201
  if (object->kind == SCR_DYN_FUNC) {
1049
1202
  if (prototype->kind == SCR_DYN_FUNC && object->v.fn.clo == prototype->v.fn.clo) {
1050
1203
  static const char message[] = "Cyclic __proto__ value";
@@ -1058,18 +1211,24 @@ ScrDyn *scr_dyn_set_prototype(ScrDyn *object, ScrDyn *prototype) {
1058
1211
  scr_dyn_release(result);
1059
1212
  return scr_dyn_retain(object);
1060
1213
  }
1061
- if (object->kind != SCR_DYN_OBJ ||
1062
- (prototype->kind != SCR_DYN_OBJ && prototype->kind != SCR_DYN_NULL)) {
1214
+ if ((object->kind != SCR_DYN_OBJ && object->kind != SCR_DYN_ARR) ||
1215
+ (prototype->kind != SCR_DYN_OBJ && prototype->kind != SCR_DYN_ARR && prototype->kind != SCR_DYN_FUNC && prototype->kind != SCR_DYN_NULL)) {
1063
1216
  static const char message[] = "Object prototype may only be an Object or null";
1064
1217
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
1065
1218
  return NULL;
1066
1219
  }
1067
- for (ScrDyn *current = prototype; current && current->kind == SCR_DYN_OBJ; current = current->prototype) {
1220
+ for (ScrDyn *current = prototype; current;) {
1221
+ if (current->kind == SCR_DYN_FUNC) {
1222
+ ScrDyn *table = scr_dyn_fn_properties(current);
1223
+ current = table;
1224
+ scr_dyn_release(table); /* the function owns the table */
1225
+ }
1068
1226
  if (current == object) {
1069
1227
  static const char message[] = "Cyclic __proto__ value";
1070
1228
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
1071
1229
  return NULL;
1072
1230
  }
1231
+ current = current->prototype;
1073
1232
  }
1074
1233
  if (object->non_extensible && (prototype->kind == SCR_DYN_NULL ? object->prototype != NULL || !object->null_proto : object->prototype != prototype)) {
1075
1234
  static const char message[] = "Cannot set prototype of a non-extensible object";
@@ -1131,6 +1290,12 @@ bool scr_dyn_is_sealed(const ScrDyn *object) {
1131
1290
 
1132
1291
  static const ScrDyn *scr_dyn_property_owner(const ScrDyn *object, const char *key, size_t length) {
1133
1292
  for (const ScrDyn *current = object; current; current = current->prototype) {
1293
+ if (current->kind == SCR_DYN_FUNC) {
1294
+ ScrDyn *table = scr_dyn_fn_properties(current);
1295
+ const ScrDyn *owner = scr_dyn_property_owner(table, key, length);
1296
+ scr_dyn_release(table);
1297
+ return owner;
1298
+ }
1134
1299
  if (current->kind != SCR_DYN_OBJ) continue;
1135
1300
  for (size_t i = 0; i < current->v.obj.len; i++) {
1136
1301
  const ScrDynEntry *entry = &current->v.obj.entries[i];
@@ -1143,7 +1308,7 @@ static const ScrDyn *scr_dyn_property_owner(const ScrDyn *object, const char *ke
1143
1308
  static bool scr_dyn_has_object_prototype(const ScrDyn *object) {
1144
1309
  const ScrDyn *current = object;
1145
1310
  while (current->prototype) current = current->prototype;
1146
- return !current->null_proto;
1311
+ return current == scr_builtin_object_prototype || !current->null_proto;
1147
1312
  }
1148
1313
 
1149
1314
  void scr_dyn_proxy_unsupported(const char *operation) {
@@ -1168,9 +1333,20 @@ ScrDyn *scr_dyn_proxy_new(const ScrDyn *target, const ScrDyn *handler) {
1168
1333
  scr_throw_error_msg(SCR_ERR_TYPE, msg, sizeof msg - 1);
1169
1334
  return NULL;
1170
1335
  }
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) {
1336
+ bool native_record = target->kind == SCR_DYN_TYPED_REF &&
1337
+ strncmp(target->v.typed_ref.type_key, "record:", 7) == 0;
1338
+ if (native_record) {
1339
+ ScrDyn *view = scr_dyn_typed_ref_materialize(target);
1340
+ bool plain = view && view->kind == SCR_DYN_OBJ;
1341
+ if (plain) for (size_t i = 0; i < view->v.obj.len; i++) {
1342
+ ScrDynEntry *entry = &view->v.obj.entries[i];
1343
+ if (entry->accessor || !entry->configurable || !entry->writable) plain = false;
1344
+ }
1345
+ scr_dyn_release(view);
1346
+ if (scr_exc_pending()) return NULL;
1347
+ native_record = plain;
1348
+ }
1349
+ if ((target->kind != SCR_DYN_OBJ && target->kind != SCR_DYN_FUNC && !native_record) || handler->kind != SCR_DYN_OBJ) {
1174
1350
  scr_dyn_proxy_unsupported("non-plain targets or handlers");
1175
1351
  return NULL;
1176
1352
  }
@@ -1188,7 +1364,7 @@ static ScrDyn *scr_dyn_proxy_trap(const ScrDyn *proxy, const char *name) {
1188
1364
  scr_dyn_release(method);
1189
1365
  return NULL;
1190
1366
  }
1191
- if (method->kind != SCR_DYN_FUNC) {
1367
+ if (!scr_dyn_is_callable(method)) {
1192
1368
  ScrJsonBuf msg;
1193
1369
  scr_jb_init(&msg);
1194
1370
  scr_jb_puts(&msg, "Proxy handler '");
@@ -1198,6 +1374,11 @@ static ScrDyn *scr_dyn_proxy_trap(const ScrDyn *proxy, const char *name) {
1198
1374
  scr_dyn_release(method);
1199
1375
  return NULL;
1200
1376
  }
1377
+ if (proxy->v.proxy.target->kind == SCR_DYN_TYPED_REF) {
1378
+ scr_dyn_release(method);
1379
+ scr_dyn_proxy_unsupported("traps over typed native targets");
1380
+ return NULL;
1381
+ }
1201
1382
  return method;
1202
1383
  }
1203
1384
 
@@ -1222,19 +1403,25 @@ static bool scr_dyn_object_proto_key(const ScrDyn *target, const ScrStr *key) {
1222
1403
  return false;
1223
1404
  }
1224
1405
 
1225
- ScrDyn *scr_dyn_proxy_get(const ScrDyn *proxy, const ScrStr *key) {
1406
+ static ScrDyn *scr_dyn_proxy_get_receiver(const ScrDyn *proxy, const ScrStr *key, const ScrDyn *receiver) {
1226
1407
  ScrDyn *trap = scr_dyn_proxy_trap(proxy, "get");
1227
1408
  if (scr_exc_pending()) return NULL;
1228
1409
  if (!trap) {
1229
1410
  ScrDyn *target = proxy->v.proxy.target;
1411
+ if (target->kind == SCR_DYN_TYPED_REF) {
1412
+ ScrDyn *view = scr_dyn_typed_ref_materialize(target);
1413
+ ScrDyn *result = scr_exc_pending() ? NULL : scr_dyn_obj_read_receiver(view, key->data, key->len, receiver);
1414
+ scr_dyn_release(view);
1415
+ return result;
1416
+ }
1230
1417
  if (!scr_dyn_obj_get(target, key->data, key->len) && scr_dyn_object_proto_key(target, key)) {
1231
1418
  scr_dyn_proxy_unsupported("inherited Object.prototype member reads");
1232
1419
  return NULL;
1233
1420
  }
1234
- return scr_dyn_obj_read(target, key->data, key->len);
1421
+ return scr_dyn_obj_read_receiver(target, key->data, key->len, receiver);
1235
1422
  }
1236
1423
  ScrDyn *property = scr_dyn_new_str((ScrStr *)key);
1237
- ScrDyn *args[] = { proxy->v.proxy.target, property, (ScrDyn *)proxy };
1424
+ ScrDyn *args[] = { proxy->v.proxy.target, property, (ScrDyn *)receiver };
1238
1425
  ScrDyn *result = scr_dyn_proxy_call(proxy, trap, args, 3);
1239
1426
  scr_dyn_release(property);
1240
1427
  ScrDynEntry *entry = scr_dyn_entry(proxy->v.proxy.target, key);
@@ -1248,6 +1435,10 @@ ScrDyn *scr_dyn_proxy_get(const ScrDyn *proxy, const ScrStr *key) {
1248
1435
  return result;
1249
1436
  }
1250
1437
 
1438
+ ScrDyn *scr_dyn_proxy_get(const ScrDyn *proxy, const ScrStr *key) {
1439
+ return scr_dyn_proxy_get_receiver(proxy, key, proxy);
1440
+ }
1441
+
1251
1442
  bool scr_dyn_proxy_has(const ScrDyn *proxy, const ScrStr *key) {
1252
1443
  ScrDyn *trap = scr_dyn_proxy_trap(proxy, "has");
1253
1444
  if (scr_exc_pending()) return false;
@@ -1306,6 +1497,7 @@ ScrDyn *scr_dyn_own_descriptor(const ScrDyn *value, const ScrStr *key) {
1306
1497
  if (scr_dyn_canonical_own_index(key, value->v.arr.len)) {
1307
1498
  size_t index = 0;
1308
1499
  for (size_t i = 0; i < key->len; i++) index = index * 10 + (size_t)(key->data[i] - '0');
1500
+ if (!scr_dyn_arr_has_index(value, index)) return scr_dyn_retain(scr_dyn_undefined());
1309
1501
  ScrDyn *out = scr_dyn_new_obj();
1310
1502
  scr_dyn_obj_set(out, "value", 5, scr_dyn_retain(value->v.arr.items[index]));
1311
1503
  scr_dyn_obj_set(out, "writable", 8, scr_dyn_new_bool(!value->v.arr.frozen));
@@ -1432,6 +1624,10 @@ void scr_dyn_proxy_set(ScrDyn *proxy, ScrStr *key, ScrDyn *value) {
1432
1624
  ScrDyn *trap = scr_dyn_proxy_trap(proxy, "set");
1433
1625
  if (scr_exc_pending()) return;
1434
1626
  if (!trap) {
1627
+ if (proxy->v.proxy.target->kind == SCR_DYN_TYPED_REF) {
1628
+ scr_dyn_key_set(proxy->v.proxy.target, key, value);
1629
+ return;
1630
+ }
1435
1631
  /* OrdinarySet uses the Proxy receiver's [[GetOwnProperty]] and
1436
1632
  * [[DefineOwnProperty]]. Keep that boundary explicit for now. */
1437
1633
  scr_dyn_proxy_unsupported("assignment without a set trap");
@@ -1498,6 +1694,15 @@ ScrDyn *scr_dyn_new_typed_ref(
1498
1694
  const char *type_key, size_t type_key_len,
1499
1695
  ScrDyn *(*materialize)(void *),
1500
1696
  void (*commit)(void *, const ScrDyn *)) {
1697
+ scr_typed_ref_reserve();
1698
+ size_t bucket = scr_typed_ref_bucket(ptr);
1699
+ for (ScrTypedRefIdentity *entry = scr_typed_ref_identities[bucket]; entry; entry = entry->next) {
1700
+ ScrDyn *value = entry->value;
1701
+ if (value->v.typed_ref.ptr == ptr && value->v.typed_ref.retain == retain &&
1702
+ value->v.typed_ref.materialize == materialize && value->v.typed_ref.commit == commit &&
1703
+ value->v.typed_ref.type_key_len == type_key_len && !memcmp(value->v.typed_ref.type_key, type_key, type_key_len))
1704
+ return scr_dyn_retain(value);
1705
+ }
1501
1706
  ScrDyn *d = scr_dyn_alloc(SCR_DYN_TYPED_REF);
1502
1707
  d->v.typed_ref.ptr = retain(ptr);
1503
1708
  d->v.typed_ref.retain = retain;
@@ -1509,6 +1714,12 @@ ScrDyn *scr_dyn_new_typed_ref(
1509
1714
  d->v.typed_ref.materialized = NULL;
1510
1715
  d->v.typed_ref.casts = NULL;
1511
1716
  d->v.typed_ref.traced = false;
1717
+ d->v.typed_ref.observed = false;
1718
+ ScrTypedRefIdentity *identity = malloc(sizeof *identity);
1719
+ if (!identity) scr_json_oom();
1720
+ identity->value = d; identity->next = scr_typed_ref_identities[bucket];
1721
+ scr_typed_ref_identities[bucket] = identity;
1722
+ scr_typed_ref_count++;
1512
1723
  return d;
1513
1724
  }
1514
1725
 
@@ -1520,6 +1731,16 @@ ScrDyn *scr_dyn_new_typed_ref_traced(
1520
1731
  ScrDyn *value = scr_dyn_new_typed_ref(ptr, retain, release, type_key,
1521
1732
  type_key_len, materialize, commit);
1522
1733
  value->v.typed_ref.traced = true;
1734
+ value->v.typed_ref.observed = true;
1735
+ return value;
1736
+ }
1737
+
1738
+ ScrDyn *scr_dyn_new_typed_ref_observed(
1739
+ void *ptr, void *(*retain)(void *), void (*release)(void *),
1740
+ const char *type_key, size_t type_key_len,
1741
+ ScrDyn *(*materialize)(void *), void (*commit)(void *, const ScrDyn *)) {
1742
+ ScrDyn *value = scr_dyn_new_typed_ref(ptr, retain, release, type_key, type_key_len, materialize, commit);
1743
+ value->v.typed_ref.observed = true;
1523
1744
  return value;
1524
1745
  }
1525
1746
 
@@ -1601,6 +1822,34 @@ ScrDyn *scr_dyn_typed_ref_materialize(const ScrDyn *d) {
1601
1822
  * detached contents without changing the cached node's address. */
1602
1823
  scr_dyn_typed_ref_preserve_children(
1603
1824
  capsule->v.typed_ref.materialized, fresh);
1825
+ /* Record layouts cannot store properties added through a checked
1826
+ * view. Keep those descriptors in the view across native refreshes. */
1827
+ ScrDyn *cached = capsule->v.typed_ref.materialized;
1828
+ if (fresh->kind == SCR_DYN_OBJ && cached->kind == SCR_DYN_OBJ &&
1829
+ capsule->v.typed_ref.type_key_len >= 7 &&
1830
+ memcmp(capsule->v.typed_ref.type_key, "record:", 7) == 0) {
1831
+ for (size_t i = 0; i < cached->v.obj.len; i++) {
1832
+ ScrDynEntry *entry = &cached->v.obj.entries[i];
1833
+ if (scr_dyn_obj_get(fresh, entry->key, entry->key_len)) continue;
1834
+ ScrStr *name = scr_str_new(entry->key, entry->key_len);
1835
+ ScrDyn *key = scr_dyn_new_str(name);
1836
+ ScrDyn *descriptor = scr_dyn_own_descriptor(cached, name);
1837
+ ScrDyn *defined = scr_dyn_define_property(fresh, key, descriptor);
1838
+ scr_dyn_release(defined);
1839
+ scr_dyn_release(descriptor);
1840
+ scr_dyn_release(key);
1841
+ scr_str_release(name);
1842
+ }
1843
+ }
1844
+ /* A native record stores its own fields, while its checked view owns
1845
+ * prototype changes. Refreshing fields must preserve that prototype. */
1846
+ scr_dyn_release(fresh->prototype);
1847
+ fresh->prototype = capsule->v.typed_ref.materialized->prototype ? scr_dyn_retain(capsule->v.typed_ref.materialized->prototype) : NULL;
1848
+ fresh->null_proto = capsule->v.typed_ref.materialized->null_proto;
1849
+ scr_dyn_release(fresh->symbol_properties);
1850
+ scr_dyn_release(fresh->symbol_keys);
1851
+ fresh->symbol_properties = capsule->v.typed_ref.materialized->symbol_properties ? scr_dyn_retain(capsule->v.typed_ref.materialized->symbol_properties) : NULL;
1852
+ fresh->symbol_keys = capsule->v.typed_ref.materialized->symbol_keys ? scr_dyn_retain(capsule->v.typed_ref.materialized->symbol_keys) : NULL;
1604
1853
  size_t cached_rc = capsule->v.typed_ref.materialized->rc;
1605
1854
  size_t fresh_rc = fresh->rc;
1606
1855
  ScrDyn old = *capsule->v.typed_ref.materialized;
@@ -1635,7 +1884,7 @@ void *scr_dyn_typed_ref_cached_cast(
1635
1884
 
1636
1885
  void scr_dyn_typed_ref_cache_cast(
1637
1886
  ScrDyn *d, const char *type_key, size_t type_key_len, void *ptr,
1638
- void *(*retain)(void *), void (*release)(void *)) {
1887
+ void *(*retain)(void *), void (*release)(void *), bool traced) {
1639
1888
  if (!ptr) return;
1640
1889
  ScrDynTypedCast *cast = malloc(sizeof *cast);
1641
1890
  if (!cast) scr_trap("scriptc: out of memory\n");
@@ -1644,10 +1893,15 @@ void scr_dyn_typed_ref_cache_cast(
1644
1893
  cast->ptr = retain(ptr);
1645
1894
  cast->retain = retain;
1646
1895
  cast->release = release;
1896
+ cast->traced = traced;
1647
1897
  cast->next = d->v.typed_ref.casts;
1648
1898
  d->v.typed_ref.casts = cast;
1649
1899
  }
1650
1900
 
1901
+ bool scr_dyn_typed_array_is(const ScrDyn *d, int elem) {
1902
+ return d && d->kind == SCR_DYN_BYTES && !d->v.bytes->is_data_view && d->v.bytes->elem == (ScrBytesElem)elem;
1903
+ }
1904
+
1651
1905
  bool scr_dyn_bytes_is(const ScrDyn *d, int elem) {
1652
1906
  return d && d->kind == SCR_DYN_BYTES && d->v.bytes->elem == (ScrBytesElem)elem;
1653
1907
  }
@@ -1656,6 +1910,146 @@ ScrBytes *scr_dyn_bytes_unbox(const ScrDyn *d) {
1656
1910
  return scr_bytes_retain(d->v.bytes);
1657
1911
  }
1658
1912
 
1913
+ /* Numeric typed-array constructor values share native function identity.
1914
+ * The cache owns one reference until runtime cleanup; arbitrary strings or
1915
+ * functions cannot impersonate one of these constructors. */
1916
+ static SCR_TL ScrDyn *scr_bytes_ctors[9];
1917
+ static void scr_bytes_ctors_cleanup(void) {
1918
+ for (size_t i = 0; i < 9; i++) {
1919
+ scr_dyn_release(scr_bytes_ctors[i]);
1920
+ scr_bytes_ctors[i] = NULL;
1921
+ }
1922
+ }
1923
+ static ScrDyn *scr_bytes_ctor_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
1924
+ (void)args; (void)argc;
1925
+ for (size_t i = 0; i < 9; i++) {
1926
+ if (!scr_bytes_ctors[i] || scr_bytes_ctors[i]->v.fn.clo != closure) continue;
1927
+ ScrJsonBuf message;
1928
+ scr_jb_init(&message);
1929
+ scr_jb_puts(&message, "Constructor ");
1930
+ scr_jb_puts(&message, scr_bytes_elem_name((ScrBytesElem)i));
1931
+ scr_jb_puts(&message, " requires 'new'");
1932
+ scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&message));
1933
+ return NULL;
1934
+ }
1935
+ scr_trap("scriptc: invalid typed array constructor\n");
1936
+ }
1937
+ static ScrDyn *scr_dyn_fn_properties(const ScrDyn *function);
1938
+ static ScrDyn *scr_bytes_constructor_for(ScrBytesElem elem) {
1939
+ if (!scr_bytes_ctors[elem]) {
1940
+ bool initialized = false;
1941
+ for (size_t i = 0; i < 9; i++) if (scr_bytes_ctors[i]) initialized = true;
1942
+ if (!initialized) scr_atexit(scr_bytes_ctors_cleanup);
1943
+ scr_bytes_ctors[elem] = scr_dyn_new_func(scr_closure_new(NULL, 0),
1944
+ scr_bytes_ctor_call, 3, "typed-array-constructor", scr_bytes_elem_name(elem));
1945
+ ScrDyn *properties = scr_dyn_fn_properties(scr_bytes_ctors[elem]);
1946
+ scr_dyn_obj_set(properties, "BYTES_PER_ELEMENT", 17, scr_dyn_new_num((double)scr_bytes_elem_size(elem)));
1947
+ ScrDynEntry *entry = &properties->v.obj.entries[properties->v.obj.len - 1];
1948
+ entry->writable = entry->enumerable = entry->configurable = false;
1949
+ scr_dyn_release(properties);
1950
+ }
1951
+ return scr_dyn_retain(scr_bytes_ctors[elem]);
1952
+ }
1953
+ ScrDyn *scr_bytes_constructor(const ScrStr *name) {
1954
+ for (size_t i = 0; i < 9; i++) {
1955
+ const char *candidate = scr_bytes_elem_name((ScrBytesElem)i);
1956
+ if (strlen(candidate) == name->len && memcmp(candidate, name->data, name->len) == 0)
1957
+ return scr_bytes_constructor_for((ScrBytesElem)i);
1958
+ }
1959
+ scr_trap("scriptc: invalid typed array constructor name\n");
1960
+ }
1961
+ static SCR_TL ScrDyn *scr_array_buffer_ctor;
1962
+ static SCR_TL ScrDyn *scr_array_ctor;
1963
+ static void scr_array_ctor_cleanup(void) {
1964
+ scr_dyn_release(scr_array_ctor);
1965
+ scr_array_ctor = NULL;
1966
+ }
1967
+ static ScrDyn *scr_array_ctor_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
1968
+ (void)closure;
1969
+ ScrDyn *result = scr_dyn_new_arr();
1970
+ if (argc == 1 && args[0]->kind == SCR_DYN_NUM) {
1971
+ double length = args[0]->v.num;
1972
+ if (!isfinite(length) || length < 0 || length > 4294967295.0 || trunc(length) != length) {
1973
+ scr_dyn_release(result);
1974
+ static const char message[] = "Invalid array length";
1975
+ scr_throw_error_msg(SCR_ERR_RANGE, message, sizeof message - 1);
1976
+ return NULL;
1977
+ }
1978
+ if (length > 1000000) {
1979
+ scr_dyn_release(result);
1980
+ static const char message[] = "Checked array construction exceeds the native allocation limit";
1981
+ scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
1982
+ return NULL;
1983
+ }
1984
+ for (size_t i = 0; i < (size_t)length; i++) scr_dyn_arr_push_hole(result);
1985
+ } else for (size_t i = 0; i < argc; i++) scr_dyn_arr_push(result, scr_dyn_retain(args[i]));
1986
+ return result;
1987
+ }
1988
+ ScrDyn *scr_dyn_array_constructor(void) {
1989
+ if (!scr_array_ctor) {
1990
+ scr_array_ctor = scr_dyn_new_func(scr_closure_new(NULL, 0), scr_array_ctor_call, 1, "native:Array", "Array");
1991
+ scr_atexit(scr_array_ctor_cleanup);
1992
+ }
1993
+ return scr_dyn_retain(scr_array_ctor);
1994
+ }
1995
+ static void scr_array_buffer_ctor_cleanup(void) {
1996
+ scr_dyn_release(scr_array_buffer_ctor);
1997
+ scr_array_buffer_ctor = NULL;
1998
+ }
1999
+ static ScrDyn *scr_array_buffer_ctor_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
2000
+ (void)closure; (void)args; (void)argc;
2001
+ static const char message[] = "Constructor ArrayBuffer requires 'new'";
2002
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
2003
+ return NULL;
2004
+ }
2005
+ ScrDyn *scr_array_buffer_constructor(void) {
2006
+ if (!scr_array_buffer_ctor) {
2007
+ scr_array_buffer_ctor = scr_dyn_new_func(scr_closure_new(NULL, 0), scr_array_buffer_ctor_call, 1, "native:ArrayBuffer", "ArrayBuffer");
2008
+ scr_atexit(scr_array_buffer_ctor_cleanup);
2009
+ }
2010
+ return scr_dyn_retain(scr_array_buffer_ctor);
2011
+ }
2012
+
2013
+ bool scr_bytes_instanceof(const ScrDyn *value, const ScrDyn *callee) {
2014
+ if (!callee || callee->kind != SCR_DYN_FUNC) {
2015
+ static const char message[] = "Right-hand side of 'instanceof' is not callable";
2016
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
2017
+ return false;
2018
+ }
2019
+ if (scr_array_buffer_ctor && callee->v.fn.clo == scr_array_buffer_ctor->v.fn.clo) return scr_array_buffer_is(value);
2020
+ if (scr_array_ctor && callee->v.fn.clo == scr_array_ctor->v.fn.clo) return value->kind == SCR_DYN_ARR || scr_dyn_isl_is_array(value);
2021
+ for (size_t i = 0; i < 9; i++) {
2022
+ if (scr_bytes_ctors[i] && callee->v.fn.clo == scr_bytes_ctors[i]->v.fn.clo)
2023
+ return scr_dyn_typed_array_is(value, (int)i);
2024
+ }
2025
+ static const char message[] = "instanceof against this native constructor is not supported yet";
2026
+ scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC1090");
2027
+ return false;
2028
+ }
2029
+ ScrDyn *scr_bytes_construct(const ScrDyn *callee, const ScrDyn *args, const ScrStr *what) {
2030
+ if (callee->kind == SCR_DYN_FUNC && scr_array_ctor && callee->v.fn.clo == scr_array_ctor->v.fn.clo)
2031
+ return scr_array_ctor_call(callee->v.fn.clo, args->v.arr.items, args->v.arr.len);
2032
+ if (callee->kind == SCR_DYN_FUNC && scr_array_buffer_ctor && callee->v.fn.clo == scr_array_buffer_ctor->v.fn.clo)
2033
+ return scr_array_buffer_new(args->v.arr.len ? args->v.arr.items[0] : scr_dyn_undefined());
2034
+ for (size_t i = 0; i < 9; i++) {
2035
+ if (callee->kind != SCR_DYN_FUNC || !scr_bytes_ctors[i] || callee->v.fn.clo != scr_bytes_ctors[i]->v.fn.clo) continue;
2036
+ const ScrDyn *input = args->v.arr.len > 0 ? args->v.arr.items[0] : scr_dyn_undefined();
2037
+ const ScrDyn *offset = args->v.arr.len > 1 ? args->v.arr.items[1] : scr_dyn_undefined();
2038
+ const ScrDyn *length = args->v.arr.len > 2 ? args->v.arr.items[2] : scr_dyn_undefined();
2039
+ ScrBytes *bytes = scr_array_buffer_view((ScrBytesElem)i, input, offset, length);
2040
+ if (!bytes) return NULL;
2041
+ ScrDyn *result = scr_dyn_new_bytes(bytes);
2042
+ scr_bytes_release(bytes);
2043
+ return result;
2044
+ }
2045
+ ScrJsonBuf message;
2046
+ scr_jb_init(&message);
2047
+ scr_jb_write(&message, what->data, what->len);
2048
+ scr_jb_puts(&message, " is not a supported native constructor");
2049
+ scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&message));
2050
+ return NULL;
2051
+ }
2052
+
1659
2053
  /* Shared view metadata and indexed reads for both compiler backends. */
1660
2054
  ScrDyn *scr_dyn_bytes_key_get(const ScrDyn *value, const ScrStr *key) {
1661
2055
  ScrBytes *bytes = value->v.bytes;
@@ -1664,7 +2058,8 @@ ScrDyn *scr_dyn_bytes_key_get(const ScrDyn *value, const ScrStr *key) {
1664
2058
  if (key->len == 10 && memcmp(key->data, "byteOffset", 10) == 0) return scr_dyn_new_num(scr_bytes_byte_offset(bytes));
1665
2059
  if (key->len == 6 && memcmp(key->data, "buffer", 6) == 0) return scr_array_buffer_from_bytes(bytes);
1666
2060
  if (key->len == 11 && memcmp(key->data, "constructor", 11) == 0) {
1667
- /* Match the compiler's opaque JS builtin identity values. */
2061
+ if (!value->buffer) return scr_bytes_constructor_for(bytes->elem);
2062
+ /* Buffer retains its separate builtin identity. */
1668
2063
  char token[64];
1669
2064
  int length = snprintf(token, sizeof token, "[builtin %s]", value->buffer ? "Buffer" : scr_bytes_elem_name(bytes->elem));
1670
2065
  ScrStr *name = scr_str_new(token, (size_t)length);
@@ -1711,6 +2106,11 @@ ScrDyn *scr_dyn_new_chunk(const ScrBytes *b) {
1711
2106
  /* A boxed static function value (the compiler's static→dyn converters).
1712
2107
  * Ownership of the closure MOVES in; sig/name are static literals. */
1713
2108
  ScrDyn *scr_dyn_new_func(ScrClosure *clo, ScrDynThunk thunk, uint32_t arity, const char *sig, const char *name) {
2109
+ if (clo->function_kind & 8) {
2110
+ ScrDyn *original = scr_box_get_ref(clo->caps[0]);
2111
+ scr_closure_release(clo);
2112
+ return original;
2113
+ }
1714
2114
  ScrDyn *d = scr_dyn_alloc(SCR_DYN_FUNC);
1715
2115
  d->v.fn.clo = clo;
1716
2116
  d->v.fn.thunk = thunk;
@@ -1739,6 +2139,7 @@ static ScrDyn *scr_dyn_class_call(ScrClosure *closure, ScrDyn *const *args, size
1739
2139
 
1740
2140
  ScrDyn *scr_dyn_new_class(ScrClassObj *cls, const char *type_key) {
1741
2141
  ScrClosure *closure = scr_closure_new(NULL, 1);
2142
+ if (cls->static_data) closure->props = scr_box_retain(cls->static_data);
1742
2143
  closure->caps[0] = scr_box_new_obj(scr_classobj_retain_v, scr_classobj_release_v, scr_classobj_trace_v);
1743
2144
  scr_box_set_ref(closure->caps[0], scr_classobj_retain(cls));
1744
2145
  ScrDyn *value = scr_dyn_new_func(closure, scr_dyn_class_call, (uint32_t)cls->length, type_key, cls->name->data);
@@ -1751,6 +2152,10 @@ bool scr_dyn_class_is(const ScrDyn *value, const char *type_key) {
1751
2152
  strcmp(value->v.fn.sig, type_key) == 0;
1752
2153
  }
1753
2154
 
2155
+ bool scr_dyn_class_is_key(const ScrDyn *value, const ScrStr *type_key) {
2156
+ return scr_dyn_class_is(value, type_key->data);
2157
+ }
2158
+
1754
2159
  ScrClassObj *scr_dyn_class_check(const ScrDyn *value, const char *type_key, const ScrDynPath *path) {
1755
2160
  if (!scr_dyn_class_is(value, type_key)) {
1756
2161
  scr_dyn_check_fail(path, "class constructor", value);
@@ -1783,6 +2188,19 @@ ScrDyn *scr_dyn_class_prototype(ScrDyn *value, ScrDyn *base) {
1783
2188
  * compiled per signature). Args borrowed; result owned (+1) or NULL with
1784
2189
  * the exception pending. */
1785
2190
  ScrDyn *scr_dyn_call(const ScrDyn *d, ScrDyn *const *args, size_t argc, const char *what) {
2191
+ if (d->kind == SCR_DYN_PROXY && scr_dyn_is_callable(d->v.proxy.target)) {
2192
+ ScrDyn *trap = scr_dyn_proxy_trap(d, "apply");
2193
+ if (scr_exc_pending()) return NULL;
2194
+ if (!trap) return scr_dyn_call(d->v.proxy.target, args, argc, what);
2195
+ ScrDyn *receiver = scr_dyn_this_get();
2196
+ ScrDyn *arguments = scr_dyn_new_arr();
2197
+ for (size_t i = 0; i < argc; i++) scr_dyn_arr_push(arguments, scr_dyn_retain(args[i]));
2198
+ ScrDyn *trap_args[] = { d->v.proxy.target, receiver, arguments };
2199
+ ScrDyn *result = scr_dyn_proxy_call(d, trap, trap_args, 3);
2200
+ scr_dyn_release(arguments);
2201
+ scr_dyn_release(receiver);
2202
+ return result;
2203
+ }
1786
2204
  if (d->kind == SCR_DYN_JSVAL) {
1787
2205
  /* An ENGINE callee: the call routes through scr_jsval_call with the
1788
2206
  * uniform argument conversion (wrapped cells by reference, dyn data
@@ -1893,7 +2311,7 @@ const char *scr_dyn_specific_type(const ScrDyn *cb, char *detail, size_t cap) {
1893
2311
  case SCR_DYN_OBJ: d = "an instance of Object"; break;
1894
2312
  case SCR_DYN_ARR: d = "an instance of Array"; break;
1895
2313
  case SCR_DYN_BYTES:
1896
- snprintf(detail, cap, "an instance of %s", cb->buffer ? "Buffer" : scr_bytes_elem_name(cb->v.bytes->elem));
2314
+ snprintf(detail, cap, "an instance of %s", cb->buffer ? "Buffer" : cb->v.bytes->is_data_view ? "DataView" : scr_bytes_elem_name(cb->v.bytes->elem));
1897
2315
  break;
1898
2316
  case SCR_DYN_FUNC:
1899
2317
  /* determineSpecificType: `function ${value.name}` — anonymous
@@ -1920,6 +2338,18 @@ const char *scr_dyn_specific_type(const ScrDyn *cb, char *detail, size_t cap) {
1920
2338
  case SCR_DYN_BOOL:
1921
2339
  snprintf(detail, cap, "type boolean (%s)", cb->v.b ? "true" : "false");
1922
2340
  break;
2341
+ case SCR_DYN_BIGINT: {
2342
+ ScrStr *value = scr_bigint_inspect(cb->v.bigint);
2343
+ snprintf(detail, cap, "type bigint (%.*s)", (int)value->len, value->data);
2344
+ scr_str_release(value);
2345
+ break;
2346
+ }
2347
+ case SCR_DYN_SYMBOL: {
2348
+ ScrStr *value = cb->v.symbol.render(cb->v.symbol.value);
2349
+ snprintf(detail, cap, "type symbol (%.*s)", (int)value->len, value->data);
2350
+ scr_str_release(value);
2351
+ break;
2352
+ }
1923
2353
  case SCR_DYN_NUM: {
1924
2354
  char num[32];
1925
2355
  size_t n = scr_f64_to_str(cb->v.num, num);
@@ -1927,19 +2357,30 @@ const char *scr_dyn_specific_type(const ScrDyn *cb, char *detail, size_t cap) {
1927
2357
  break;
1928
2358
  }
1929
2359
  case SCR_DYN_STR: {
1930
- const ScrStr *sv = cb->v.str;
1931
- char insp[32];
1932
- size_t n = 0;
1933
- insp[n++] = '\'';
1934
- for (size_t i = 0; i < sv->len && n < 28; i++) insp[n++] = sv->data[i];
1935
- if (sv->len + 2 > 28) {
1936
- n = 25;
1937
- memcpy(insp + n, "...", 3);
1938
- n += 3;
2360
+ ScrStr *value = scr_str_retain(cb->v.str);
2361
+ if (scr_str_utf16_len(value) > 28) {
2362
+ ScrStr *prefix = scr_str_slice(value, 0, 25);
2363
+ ScrStr *dots = scr_str_new("...", 3);
2364
+ scr_str_release(value);
2365
+ value = scr_str_concat(prefix, dots);
2366
+ scr_str_release(prefix);
2367
+ scr_str_release(dots);
2368
+ }
2369
+ ScrJsonBuf shown;
2370
+ scr_jb_init(&shown);
2371
+ scr_jb_puts(&shown, "type string (");
2372
+ if (memchr(value->data, '\'', value->len)) {
2373
+ scr_jb_put_json_str(&shown, value);
1939
2374
  } else {
1940
- insp[n++] = '\'';
2375
+ scr_jb_putc(&shown, '\'');
2376
+ scr_jb_put_str(&shown, value);
2377
+ scr_jb_putc(&shown, '\'');
1941
2378
  }
1942
- snprintf(detail, cap, "type string (%.*s)", (int)n, insp);
2379
+ scr_jb_putc(&shown, ')');
2380
+ ScrStr *text = scr_jb_finish(&shown);
2381
+ snprintf(detail, cap, "%.*s", (int)text->len, text->data);
2382
+ scr_str_release(text);
2383
+ scr_str_release(value);
1943
2384
  break;
1944
2385
  }
1945
2386
  default: d = "an instance of Object"; break;
@@ -1961,7 +2402,7 @@ void scr_throw_arg_type(const ScrStr *argname, const ScrStr *expected, const Scr
1961
2402
  }
1962
2403
 
1963
2404
  void scr_dyn_arg_type_fail(const char *argname, const char *expected, const ScrDyn *got) {
1964
- char detail[64];
2405
+ char detail[256];
1965
2406
  const char *d = scr_dyn_specific_type(got, detail, sizeof detail);
1966
2407
  ScrJsonBuf b;
1967
2408
  scr_jb_init(&b);
@@ -1982,7 +2423,7 @@ void scr_dyn_arg_type_fail(const char *argname, const char *expected, const ScrD
1982
2423
  * wording on the name, but every property-path caller here knows it is
1983
2424
  * one). Same runtime-rendered Received tail; always throws catchably. */
1984
2425
  void scr_dyn_prop_type_fail(const char *name, const char *expected, const ScrDyn *got) {
1985
- char detail[64];
2426
+ char detail[256];
1986
2427
  const char *d = scr_dyn_specific_type(got, detail, sizeof detail);
1987
2428
  ScrJsonBuf b;
1988
2429
  scr_jb_init(&b);
@@ -2076,8 +2517,9 @@ ScrDyn *scr_dyn_new_handle(void *h, ScrDynHandleTag tag) {
2076
2517
  ScrDyn *d = scr_dyn_alloc(SCR_DYN_HANDLE);
2077
2518
  d->v.handle.ptr = scr_dyn_handle_ops(tag)->retain(h);
2078
2519
  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);
2520
+ d->v.handle.traced = tag == SCR_DYNH_WEAK_MAP || tag == SCR_DYNH_WEAK_SET ||
2521
+ ((tag == SCR_DYNH_SET || tag == SCR_DYNH_MAP) &&
2522
+ (((ScrMap *)h)->key_trace != NULL || ((ScrMap *)h)->val_trace != NULL));
2081
2523
  return d;
2082
2524
  }
2083
2525
 
@@ -2086,6 +2528,7 @@ ScrDyn *scr_dyn_new_handle(void *h, ScrDynHandleTag tag) {
2086
2528
  * scr_promise_release edge installs HERE — a promise-free link never
2087
2529
  * references the fiber machinery (the unit-test subset links). */
2088
2530
  void (*scr_dyn_promise_release_fn)(ScrPromise *p) = NULL;
2531
+ bool (*scr_dyn_promise_identity_fn)(ScrPromise *a, ScrPromise *b) = NULL;
2089
2532
 
2090
2533
  ScrDyn *scr_dyn_alloc_promise(void (*release_fn)(ScrPromise *p)) {
2091
2534
  scr_dyn_promise_release_fn = release_fn;
@@ -2114,6 +2557,7 @@ const ScrDynJsvalOps *scr_dyn_jsval_ops(void) {
2114
2557
  }
2115
2558
 
2116
2559
  bool scr_dyn_isl_typeof_is(const ScrDyn *d, const char *name) {
2560
+ if (scr_dyn_generator(d)) return strcmp(name, "object") == 0;
2117
2561
  if (d->kind == SCR_DYN_TYPED_REF) {
2118
2562
  if (d->v.typed_ref.type_key_len >= 7 &&
2119
2563
  memcmp(d->v.typed_ref.type_key, "object:", 7) == 0)
@@ -2144,10 +2588,12 @@ bool scr_dyn_isl_typeof_is(const ScrDyn *d, const char *name) {
2144
2588
  }
2145
2589
 
2146
2590
  bool scr_dyn_isl_is_array(const ScrDyn *d) {
2591
+ if (scr_dyn_generator(d)) return false;
2147
2592
  if (d->kind == SCR_DYN_TYPED_REF) {
2148
2593
  if (d->v.typed_ref.type_key_len >= 7 &&
2149
2594
  memcmp(d->v.typed_ref.type_key, "object:", 7) == 0) return false;
2150
2595
  ScrDyn *materialized = scr_dyn_typed_ref_materialize(d);
2596
+ if (!materialized) return false;
2151
2597
  bool out = materialized->kind == SCR_DYN_ARR ||
2152
2598
  scr_dyn_isl_is_array(materialized);
2153
2599
  scr_dyn_release(materialized);
@@ -2157,6 +2603,14 @@ bool scr_dyn_isl_is_array(const ScrDyn *d) {
2157
2603
  }
2158
2604
 
2159
2605
  bool scr_dyn_isl_is_error(const ScrDyn *d) {
2606
+ if (scr_dyn_generator(d)) return false;
2607
+ /* Registered native Error capsules retain their brand even when their
2608
+ * public property view omits the internal error marker. */
2609
+ ScrError *error = scr_errdyn_err_of(d);
2610
+ if (error) {
2611
+ scr_error_release(error);
2612
+ return true;
2613
+ }
2160
2614
  if (d->kind == SCR_DYN_TYPED_REF) {
2161
2615
  ScrDyn *materialized = scr_dyn_typed_ref_materialize(d);
2162
2616
  bool out =
@@ -2316,6 +2770,7 @@ static ScrStr *scr_dyn_property_key(const ScrDyn *key) {
2316
2770
  }
2317
2771
 
2318
2772
  static ScrDynEntry *scr_dyn_entry(ScrDyn *obj, const ScrStr *key) {
2773
+ if (obj->kind != SCR_DYN_OBJ) return NULL;
2319
2774
  for (size_t i = 0; i < obj->v.obj.len; i++) {
2320
2775
  ScrDynEntry *entry = &obj->v.obj.entries[i];
2321
2776
  if (entry->key_len == key->len && memcmp(entry->key, key->data, key->len) == 0) return entry;
@@ -2334,6 +2789,10 @@ static bool scr_dyn_property_same_value(const ScrDyn *a, const ScrDyn *b) {
2334
2789
  return scr_dyn_strict_eq(a, b);
2335
2790
  }
2336
2791
 
2792
+ bool scr_dyn_same_value(const ScrDyn *left, const ScrDyn *right) {
2793
+ return scr_dyn_property_same_value(left, right);
2794
+ }
2795
+
2337
2796
  static void scr_dyn_descriptor_fields_drop(ScrDyn **fields) {
2338
2797
  for (size_t i = 0; i < 6; i++) scr_dyn_release(fields[i]);
2339
2798
  }
@@ -2344,6 +2803,8 @@ static void scr_error_sync_cause(ScrDyn *view, const ScrStr *key);
2344
2803
  * the configurable, non-writable builtin members once so redefinitions and
2345
2804
  * deletions retain the same behavior through every alias. Returns +1. */
2346
2805
  static ScrDyn *scr_dyn_fn_properties(const ScrDyn *function) {
2806
+ if (!function->v.fn.clo->props && function->v.fn.class_obj && function->v.fn.class_obj->static_data)
2807
+ function->v.fn.clo->props = scr_box_retain(function->v.fn.class_obj->static_data);
2347
2808
  if (!function->v.fn.clo->props) {
2348
2809
  ScrDyn *table = scr_dyn_new_obj();
2349
2810
  const char *name = function->v.fn.name ? function->v.fn.name : "";
@@ -2358,6 +2819,7 @@ static ScrDyn *scr_dyn_fn_properties(const ScrDyn *function) {
2358
2819
  ScrBox *box = scr_box_new_obj(&scr_dyn_retain_v, &scr_dyn_release_v, &scr_dyn_trace_v);
2359
2820
  scr_box_set_ref(box, table);
2360
2821
  function->v.fn.clo->props = box;
2822
+ if (function->v.fn.class_obj) function->v.fn.class_obj->static_data = scr_box_retain(box);
2361
2823
  if (function->v.fn.clo->function_kind & 4) {
2362
2824
  ScrDyn *prototype = scr_dyn_new_obj();
2363
2825
  scr_dyn_obj_set(prototype, "constructor", 11, scr_dyn_retain((ScrDyn *)function));
@@ -2371,6 +2833,22 @@ static ScrDyn *scr_dyn_fn_properties(const ScrDyn *function) {
2371
2833
  return (ScrDyn *)scr_box_get_ref(function->v.fn.clo->props);
2372
2834
  }
2373
2835
 
2836
+ ScrDyn *scr_dyn_class_inherit(ScrDyn *constructor, ScrDyn *base) {
2837
+ if (constructor->kind != SCR_DYN_FUNC || !constructor->v.fn.class_obj || (base->kind != SCR_DYN_FUNC && base->kind != SCR_DYN_UNDEF)) {
2838
+ static const char message[] = "Class inheritance requires native constructors";
2839
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
2840
+ return NULL;
2841
+ }
2842
+ ScrDyn *table = scr_dyn_fn_properties(constructor);
2843
+ if (base->kind == SCR_DYN_FUNC) scr_dyn_release(scr_dyn_fn_properties(base));
2844
+ ScrClassObj *cls = constructor->v.fn.class_obj;
2845
+ if (!cls->static_data) cls->static_data = scr_box_retain(constructor->v.fn.clo->props);
2846
+ ScrDyn *result = base->kind == SCR_DYN_UNDEF ? NULL : scr_dyn_set_prototype(table, base);
2847
+ scr_dyn_release(table);
2848
+ scr_dyn_release(result);
2849
+ return scr_exc_pending() ? NULL : scr_dyn_retain(constructor);
2850
+ }
2851
+
2374
2852
  ScrDyn *scr_dyn_class_base_prototype(ScrDyn *constructor) {
2375
2853
  if (constructor->kind != SCR_DYN_FUNC || constructor->v.fn.class_obj ||
2376
2854
  constructor->v.fn.clo->function_kind != 4) {
@@ -2399,6 +2877,35 @@ void scr_dyn_class_super(ScrDyn *constructor, ScrDyn *receiver, ScrDyn *argument
2399
2877
  scr_dyn_release(result);
2400
2878
  }
2401
2879
 
2880
+ bool scr_dyn_data_view_is(const ScrDyn *value) {
2881
+ return value->kind == SCR_DYN_BYTES && value->v.bytes->is_data_view;
2882
+ }
2883
+
2884
+ /* Ordinary native function constructors retain their live prototype table.
2885
+ * A constructor may replace the fresh receiver with another object. */
2886
+ ScrDyn *scr_dyn_construct(const ScrDyn *callee, const ScrDyn *args, const ScrStr *what) {
2887
+ if (callee->kind != SCR_DYN_FUNC || callee->v.fn.class_obj || callee->v.fn.clo->function_kind != 4)
2888
+ return scr_bytes_construct(callee, args, what);
2889
+ ScrDyn *prototype = scr_dyn_fn_get(callee, "prototype", 9);
2890
+ if (!prototype) return NULL;
2891
+ ScrDyn *receiver = scr_iterator_object(prototype) ? scr_dyn_obj_create(prototype) : scr_dyn_new_obj();
2892
+ scr_dyn_release(prototype);
2893
+ if (!receiver) return NULL;
2894
+ scr_dyn_this_push_dyn(receiver);
2895
+ ScrDyn *result = scr_dyn_call(callee, args->v.arr.items, args->v.arr.len, what->data);
2896
+ scr_dyn_this_pop();
2897
+ if (!result) {
2898
+ scr_dyn_release(receiver);
2899
+ return NULL;
2900
+ }
2901
+ if (scr_iterator_object(result)) {
2902
+ scr_dyn_release(receiver);
2903
+ return result;
2904
+ }
2905
+ scr_dyn_release(result);
2906
+ return receiver;
2907
+ }
2908
+
2402
2909
  /* Symbol descriptors use the ordinary descriptor implementation in an
2403
2910
  * inaccessible table. Keep a retained key list so identities cannot be
2404
2911
  * recycled while properties exist, and reflection returns real symbols. */
@@ -2409,11 +2916,11 @@ static ScrStr *scr_dyn_symbol_storage_key(const ScrDyn *key) {
2409
2916
  }
2410
2917
 
2411
2918
  static ScrDyn *scr_dyn_symbol_receiver(const ScrDyn *value) {
2919
+ if (value->kind == SCR_DYN_TYPED_REF) return scr_dyn_typed_ref_materialize(value);
2412
2920
  if (value->kind == SCR_DYN_FUNC) return scr_dyn_fn_properties(value);
2413
- if (value->kind == SCR_DYN_OBJ || value->kind == SCR_DYN_ARR)
2921
+ if (value->kind == SCR_DYN_OBJ || value->kind == SCR_DYN_ARR || value->kind == SCR_DYN_HANDLE)
2414
2922
  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) {
2923
+ if (value->kind == SCR_DYN_PROXY || value->kind == SCR_DYN_JSVAL) {
2417
2924
  static const char message[] = "Symbol properties on this native value have no lowering";
2418
2925
  scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
2419
2926
  }
@@ -2425,6 +2932,12 @@ static ScrDynEntry *scr_dyn_symbol_entry(const ScrDyn *receiver, const ScrDyn *k
2425
2932
  ScrDynEntry *entry = NULL;
2426
2933
  for (const ScrDyn *current = receiver; current; current = own ? NULL : current->prototype ? current->prototype
2427
2934
  : current->kind == SCR_DYN_ARR && current != scr_builtin_array_prototype && !current->null_proto ? scr_builtin_array_prototype : NULL) {
2935
+ if (current->kind == SCR_DYN_FUNC) {
2936
+ ScrDyn *table = scr_dyn_fn_properties(current);
2937
+ entry = scr_dyn_symbol_entry(table, key, own);
2938
+ scr_dyn_release(table);
2939
+ break;
2940
+ }
2428
2941
  if (current->symbol_properties) entry = scr_dyn_entry(current->symbol_properties, name);
2429
2942
  if (entry) break;
2430
2943
  }
@@ -2442,14 +2955,19 @@ typedef struct {
2442
2955
  size_t rc;
2443
2956
  ScrDyn *source;
2444
2957
  double index;
2445
- bool string_iterator;
2958
+ unsigned kind; /* 0: array, 1: string, 2: Map, 3: Set */
2959
+ unsigned selection; /* 0: values, 1: keys, 2: entries */
2960
+ bool array_like;
2961
+ double limit;
2446
2962
  } ScrNativeIterator;
2447
2963
 
2448
- static SCR_TL ScrDyn *scr_iterator_functions[7];
2964
+ static ScrDyn *scr_iterator_read(const ScrDyn *value, const char *key, size_t len);
2965
+
2966
+ static SCR_TL ScrDyn *scr_iterator_functions[11];
2449
2967
  static SCR_TL bool scr_iterator_functions_registered;
2450
2968
 
2451
2969
  static void scr_iterator_functions_cleanup(void) {
2452
- for (size_t i = 0; i < 7; i++) {
2970
+ for (size_t i = 0; i < 11; i++) {
2453
2971
  ScrDyn *function = scr_iterator_functions[i];
2454
2972
  scr_iterator_functions[i] = NULL;
2455
2973
  scr_dyn_release(function);
@@ -2475,27 +2993,63 @@ static void *scr_native_iterator_retain(void *ptr) {
2475
2993
  static void scr_native_iterator_release(void *ptr) {
2476
2994
  ScrNativeIterator *iterator = ptr;
2477
2995
  if (--iterator->rc) return;
2996
+ scr_weak_dispose(iterator);
2997
+ if (iterator->source && (iterator->kind == 2 || iterator->kind == 3)) scr_map_iter_exit(iterator->source->v.handle.ptr);
2478
2998
  scr_dyn_release(iterator->source);
2479
2999
  free(iterator);
2480
3000
  }
2481
3001
 
2482
3002
  static ScrDyn *scr_native_iterator_next(ScrNativeIterator *iterator) {
2483
3003
  ScrDyn *source = iterator->source;
3004
+ if (source && iterator->kind == 4) {
3005
+ ScrDyn *result = scr_dyn_handle_ops_of(source)->iter_step(source->v.handle.ptr, &iterator->index, iterator->selection);
3006
+ if (!result) return NULL;
3007
+ if (scr_dyn_truthy(scr_dyn_obj_get(result, "done", 4))) {
3008
+ iterator->source = NULL;
3009
+ scr_dyn_release(source);
3010
+ }
3011
+ return result;
3012
+ }
2484
3013
  /* Native array capsules retain the live array, so refresh its view at each
2485
3014
  * step rather than iterating a snapshot taken when the iterator opened. */
2486
3015
  ScrDyn *view = source && source->kind == SCR_DYN_TYPED_REF ? scr_dyn_typed_ref_materialize(source) : NULL;
2487
3016
  if (scr_exc_pending()) { scr_dyn_release(view); return NULL; }
2488
3017
  ScrDyn *items = view ? view : source;
2489
- double length = !items ? 0 : items->kind == SCR_DYN_ARR ? (double)items->v.arr.len
3018
+ ScrMap *map = source && (iterator->kind == 2 || iterator->kind == 3) ? source->v.handle.ptr : NULL;
3019
+ if (map) while (iterator->index < scr_map_iter_count(map) && !scr_map_iter_live(map, iterator->index)) iterator->index++;
3020
+ 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
3021
  : items->kind == SCR_DYN_BYTES ? (double)items->v.bytes->len : scr_str_utf16_len(items->v.str);
2491
3022
  bool done = !source || iterator->index >= length;
2492
3023
  ScrDyn *value;
2493
3024
  if (done) {
2494
3025
  value = scr_dyn_retain(scr_dyn_undefined());
2495
3026
  iterator->source = NULL;
3027
+ if (map) scr_map_iter_exit(map);
2496
3028
  scr_dyn_release(source);
3029
+ } else if (iterator->array_like) {
3030
+ char key[32];
3031
+ int size = snprintf(key, sizeof key, "%.0f", iterator->index++);
3032
+ value = scr_iterator_read(items, key, (size_t)size);
3033
+ } else if (map) {
3034
+ double index = iterator->index++;
3035
+ if (iterator->selection == 2) {
3036
+ value = scr_dyn_new_arr();
3037
+ scr_dyn_arr_push(value, scr_map_dyn_key(map, index));
3038
+ scr_dyn_arr_push(value, iterator->kind == 3 ? scr_map_dyn_key(map, index) : scr_map_dyn_value(map, index));
3039
+ } else value = iterator->selection == 1 || iterator->kind == 3
3040
+ ? scr_map_dyn_key(map, index) : scr_map_dyn_value(map, index);
2497
3041
  } else if (items->kind == SCR_DYN_ARR) {
2498
- value = scr_dyn_arr_at(items, iterator->index++);
3042
+ double index = iterator->index++;
3043
+ if (iterator->selection == 1) value = scr_dyn_new_num(index);
3044
+ else {
3045
+ value = scr_dyn_arr_at(items, index);
3046
+ if (value && iterator->selection == 2) {
3047
+ ScrDyn *entry = scr_dyn_new_arr();
3048
+ scr_dyn_arr_push(entry, scr_dyn_new_num(index));
3049
+ scr_dyn_arr_push(entry, value);
3050
+ value = entry;
3051
+ }
3052
+ }
2499
3053
  } else if (items->kind == SCR_DYN_BYTES) {
2500
3054
  value = scr_dyn_new_num(scr_bytes_get(items->v.bytes, iterator->index++));
2501
3055
  } else {
@@ -2512,14 +3066,15 @@ static ScrDyn *scr_native_iterator_next(ScrNativeIterator *iterator) {
2512
3066
  return result;
2513
3067
  }
2514
3068
 
2515
- static ScrDyn *scr_native_iterator_next_checked(bool string_iterator) {
3069
+ static ScrDyn *scr_native_iterator_next_checked(unsigned kind) {
2516
3070
  ScrDyn *self = scr_dyn_this_get();
2517
3071
  ScrDyn *result = NULL;
2518
3072
  if (self->kind == SCR_DYN_HANDLE && self->v.handle.tag == SCR_DYNH_ITERATOR &&
2519
- ((ScrNativeIterator *)self->v.handle.ptr)->string_iterator == string_iterator)
3073
+ ((ScrNativeIterator *)self->v.handle.ptr)->kind == kind)
2520
3074
  result = scr_native_iterator_next(self->v.handle.ptr);
2521
3075
  else {
2522
- const char *message = string_iterator
3076
+ const char *message = kind == 3 ? "Method Set Iterator.prototype.next called on incompatible receiver"
3077
+ : kind == 2 ? "Method Map Iterator.prototype.next called on incompatible receiver" : kind == 1
2523
3078
  ? "Method String Iterator.prototype.next called on incompatible receiver"
2524
3079
  : "Method Array Iterator.prototype.next called on incompatible receiver";
2525
3080
  scr_throw_error_msg(SCR_ERR_TYPE, message, strlen(message));
@@ -2530,17 +3085,35 @@ static ScrDyn *scr_native_iterator_next_checked(bool string_iterator) {
2530
3085
 
2531
3086
  static ScrDyn *scr_native_array_iterator_next_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
2532
3087
  (void)closure; (void)args; (void)argc;
2533
- return scr_native_iterator_next_checked(false);
3088
+ return scr_native_iterator_next_checked(0);
2534
3089
  }
2535
3090
 
2536
3091
  static ScrDyn *scr_native_string_iterator_next_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
2537
3092
  (void)closure; (void)args; (void)argc;
2538
- return scr_native_iterator_next_checked(true);
3093
+ return scr_native_iterator_next_checked(1);
3094
+ }
3095
+
3096
+ static ScrDyn *scr_native_map_iterator_next_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
3097
+ (void)closure; (void)args; (void)argc;
3098
+ return scr_native_iterator_next_checked(2);
3099
+ }
3100
+
3101
+ static ScrDyn *scr_native_set_iterator_next_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
3102
+ (void)closure; (void)args; (void)argc;
3103
+ return scr_native_iterator_next_checked(3);
3104
+ }
3105
+
3106
+ static ScrDyn *scr_native_handle_iterator_next_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
3107
+ (void)closure; (void)args; (void)argc;
3108
+ return scr_native_iterator_next_checked(4);
2539
3109
  }
2540
3110
 
2541
3111
  static ScrDyn *scr_native_iterator_get(void *ptr, const char *key, size_t len) {
2542
3112
  if (len != 4 || memcmp(key, "next", 4)) return NULL;
2543
- return ((ScrNativeIterator *)ptr)->string_iterator
3113
+ unsigned kind = ((ScrNativeIterator *)ptr)->kind;
3114
+ if (kind == 4) return scr_iterator_function(10, &scr_native_handle_iterator_next_call, "next");
3115
+ return kind == 3 ? scr_iterator_function(8, &scr_native_set_iterator_next_call, "next")
3116
+ : kind == 2 ? scr_iterator_function(7, &scr_native_map_iterator_next_call, "next") : kind == 1
2544
3117
  ? scr_iterator_function(5, &scr_native_string_iterator_next_call, "next")
2545
3118
  : scr_iterator_function(0, &scr_native_array_iterator_next_call, "next");
2546
3119
  }
@@ -2562,12 +3135,26 @@ static ScrDyn *scr_native_iterator_new(ScrDyn *source) {
2562
3135
  ScrNativeIterator *iterator = malloc(sizeof *iterator);
2563
3136
  if (!iterator) scr_json_oom();
2564
3137
  *iterator = (ScrNativeIterator){ .rc = 1, .source = scr_dyn_retain(source), .index = 0,
2565
- .string_iterator = source->kind == SCR_DYN_STR };
3138
+ .kind = source->kind == SCR_DYN_STR ? 1 : source->kind == SCR_DYN_HANDLE && source->v.handle.tag == SCR_DYNH_MAP ? 2
3139
+ : source->kind == SCR_DYN_HANDLE && source->v.handle.tag == SCR_DYNH_SET ? 3
3140
+ : source->kind == SCR_DYN_HANDLE && scr_dyn_handle_ops_of(source)->iter_step ? 4 : 0,
3141
+ .selection = source->kind == SCR_DYN_HANDLE && (source->v.handle.tag == SCR_DYNH_MAP || scr_dyn_handle_ops_of(source)->iter_step) ? 2 : 0 };
3142
+ if (iterator->kind == 2 || iterator->kind == 3) scr_map_iter_enter(source->v.handle.ptr);
2566
3143
  ScrDyn *result = scr_dyn_new_handle(iterator, SCR_DYNH_ITERATOR);
2567
3144
  scr_native_iterator_release(iterator);
2568
3145
  return result;
2569
3146
  }
2570
3147
 
3148
+ static ScrDyn *scr_native_collection_iterator(ScrDyn *source, unsigned selection) {
3149
+ ScrDyn *result = scr_native_iterator_new(source);
3150
+ ((ScrNativeIterator *)result->v.handle.ptr)->selection = selection;
3151
+ return result;
3152
+ }
3153
+
3154
+ ScrDyn *scr_dyn_native_handle_iterator(ScrDyn *source, unsigned selection) {
3155
+ return scr_native_collection_iterator(source, selection);
3156
+ }
3157
+
2571
3158
  static ScrDyn *scr_builtin_iterator_checked(int kind) {
2572
3159
  ScrDyn *self = scr_dyn_this_get();
2573
3160
  ScrDyn *result = NULL;
@@ -2604,6 +3191,11 @@ static ScrDyn *scr_iterator_self_call(ScrClosure *closure, ScrDyn *const *args,
2604
3191
  static ScrDyn *scr_handle_iterator_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
2605
3192
  (void)closure; (void)args; (void)argc;
2606
3193
  ScrDyn *self = scr_dyn_this_get();
3194
+ 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)) {
3195
+ ScrDyn *result = scr_native_iterator_new(self);
3196
+ scr_dyn_release(self);
3197
+ return result;
3198
+ }
2607
3199
  ScrDyn *items = scr_dyn_iter_pack(self, NULL);
2608
3200
  ScrDyn *result = items ? scr_native_iterator_new(items) : NULL;
2609
3201
  scr_dyn_release(items);
@@ -2616,10 +3208,11 @@ ScrDyn *scr_dyn_array_values_function(void) {
2616
3208
  }
2617
3209
 
2618
3210
  static ScrDyn *scr_builtin_iterator_method(const ScrDyn *value) {
3211
+ if (scr_dyn_generator(value)) return scr_iterator_function(4, &scr_iterator_self_call, "[Symbol.iterator]");
2619
3212
  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
3213
  if (value->kind == SCR_DYN_BYTES) return scr_iterator_function(2, &scr_builtin_bytes_iterator_call, "values");
2621
3214
  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)
3215
+ 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
3216
  return scr_iterator_function(6, &scr_handle_iterator_call, "[Symbol.iterator]");
2624
3217
  return scr_iterator_function(4, &scr_iterator_self_call, "[Symbol.iterator]");
2625
3218
  }
@@ -2644,6 +3237,21 @@ static ScrDyn *scr_iterator_method(const ScrDyn *source) {
2644
3237
  }
2645
3238
 
2646
3239
  /* Compiled class methods are dispatched before this checked-object path. */
3240
+ ScrDyn *scr_dyn_iterator_optional(const ScrDyn *source) {
3241
+ ScrDyn *method = scr_iterator_method(source);
3242
+ if (!method) return NULL;
3243
+ if (method->kind == SCR_DYN_UNDEF || method->kind == SCR_DYN_NULL) {
3244
+ scr_dyn_release(method);
3245
+ return NULL;
3246
+ }
3247
+ ScrDyn *iterator = scr_iterator_call(method, source, "value[Symbol.iterator]");
3248
+ scr_dyn_release(method);
3249
+ if (!iterator) return NULL;
3250
+ ScrDyn *checked = scr_dyn_iterator_result(iterator);
3251
+ scr_dyn_release(iterator);
3252
+ return checked;
3253
+ }
3254
+
2647
3255
  ScrDyn *scr_dyn_iterator(const ScrDyn *source, const ScrStr *spell) {
2648
3256
  if (source->kind == SCR_DYN_JSVAL) return scr_dyn_jsval_ops()->iterator(source->v.jsval.cell, spell, false);
2649
3257
  if (source->kind == SCR_DYN_NULL || source->kind == SCR_DYN_UNDEF) return scr_dyn_not_iterable(source, spell);
@@ -2662,6 +3270,14 @@ ScrDyn *scr_dyn_iterator(const ScrDyn *source, const ScrStr *spell) {
2662
3270
  }
2663
3271
 
2664
3272
  static ScrDyn *scr_iterator_read(const ScrDyn *value, const char *key, size_t len) {
3273
+ if (value->kind == SCR_DYN_TYPED_REF) {
3274
+ ScrDyn *view = scr_dyn_typed_ref_materialize(value);
3275
+ if (!view) return NULL;
3276
+ ScrDyn *result = scr_iterator_read(view, key, len);
3277
+ scr_dyn_release(view);
3278
+ return result;
3279
+ }
3280
+ if (value->kind == SCR_DYN_PROXY) return scr_dyn_obj_read(value, key, len);
2665
3281
  if (value->kind == SCR_DYN_HANDLE) {
2666
3282
  ScrStr *name = scr_str_new(key, len);
2667
3283
  ScrDyn *result = scr_dyn_handle_key_get(value, name);
@@ -2701,14 +3317,10 @@ ScrDyn *scr_dyn_array_from_iterator(const ScrDyn *source) {
2701
3317
  numeric = false;
2702
3318
  }
2703
3319
  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);
3320
+ ScrDyn *iterator = scr_native_iterator_new((ScrDyn *)source);
3321
+ ScrNativeIterator *state = iterator->v.handle.ptr;
3322
+ state->array_like = true;
3323
+ state->limit = isnan(n) || n < 0 ? 0 : floor(n);
2712
3324
  scr_dyn_release(out);
2713
3325
  return iterator;
2714
3326
  }
@@ -2722,7 +3334,9 @@ ScrDyn *scr_dyn_array_from_iterator(const ScrDyn *source) {
2722
3334
  }
2723
3335
 
2724
3336
  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)) {
3337
+ if (scr_dyn_generator(value)) return scr_dyn_generator_symbol(value, key)
3338
+ ? scr_iterator_function(4, &scr_iterator_self_call, "[Symbol.iterator]") : scr_dyn_retain(scr_dyn_undefined());
3339
+ if (value->kind == SCR_DYN_TYPED_REF) {
2726
3340
  ScrDyn *view = scr_dyn_typed_ref_materialize(value);
2727
3341
  ScrDyn *result = scr_exc_pending() ? NULL : scr_dyn_symbol_key_get(view, key, optional);
2728
3342
  scr_dyn_release(view);
@@ -2760,6 +3374,15 @@ ScrDyn *scr_dyn_symbol_key_get(const ScrDyn *value, const ScrDyn *key, bool opti
2760
3374
  return out;
2761
3375
  }
2762
3376
 
3377
+ /* Native field tables retain presence and attributes without owning a second
3378
+ * copy of the field's value. This internal update bypasses writable flags. */
3379
+ void scr_dyn_symbol_key_placeholder(ScrDyn *value, ScrDyn *key) {
3380
+ ScrDynEntry *entry = scr_dyn_symbol_entry(value, key, true);
3381
+ if (!entry || entry->accessor) return;
3382
+ scr_dyn_release(entry->value);
3383
+ entry->value = scr_dyn_retain(scr_dyn_undefined());
3384
+ }
3385
+
2763
3386
  void scr_dyn_symbol_key_set(ScrDyn *value, ScrDyn *key, ScrDyn *stored) {
2764
3387
  ScrDyn *receiver = scr_dyn_symbol_receiver(value);
2765
3388
  if (!receiver) {
@@ -2823,7 +3446,12 @@ static bool scr_dyn_key_probe_computed(const ScrDyn *value, const ScrDyn *raw_ke
2823
3446
  scr_dyn_release(key);
2824
3447
  return out;
2825
3448
  }
2826
- if (value->kind == SCR_DYN_TYPED_REF && scr_dyn_isl_is_array(value)) {
3449
+ if (scr_dyn_generator(value)) {
3450
+ bool found = mode == 0 && scr_dyn_generator_symbol(value, key);
3451
+ scr_dyn_release(key);
3452
+ return found;
3453
+ }
3454
+ if (value->kind == SCR_DYN_TYPED_REF) {
2827
3455
  ScrDyn *view = scr_dyn_typed_ref_materialize(value);
2828
3456
  bool out = !scr_exc_pending() && scr_dyn_key_probe_computed(view, key, mode);
2829
3457
  scr_dyn_release(view);
@@ -2892,7 +3520,7 @@ void scr_dyn_key_delete_computed(ScrDyn *value, const ScrDyn *raw_key, bool stri
2892
3520
  * Refuse overrides until every typed call site observes the property table. */
2893
3521
  static bool scr_dyn_fn_property_fence(const ScrStr *key) {
2894
3522
  static const char *const reserved[] = {
2895
- "call", "apply", "bind", "toString", "valueOf", "toLocaleString",
3523
+ "call", "apply", "bind", "valueOf", "toLocaleString",
2896
3524
  "hasOwnProperty", "propertyIsEnumerable", "isPrototypeOf",
2897
3525
  "constructor", "caller", "arguments", "__proto__",
2898
3526
  };
@@ -2906,6 +3534,20 @@ static bool scr_dyn_fn_property_fence(const ScrStr *key) {
2906
3534
  }
2907
3535
 
2908
3536
  ScrDyn *scr_dyn_define_property(ScrDyn *target, ScrDyn *key, ScrDyn *descriptor) {
3537
+ if (target->kind == SCR_DYN_TYPED_REF) {
3538
+ ScrDyn *view = scr_dyn_typed_ref_materialize(target);
3539
+ ScrDyn *defined = scr_exc_pending() ? NULL : scr_dyn_define_property(view, key, descriptor);
3540
+ if (!scr_exc_pending()) scr_dyn_typed_ref_commit(target);
3541
+ scr_dyn_release(defined);
3542
+ scr_dyn_release(view);
3543
+ return scr_exc_pending() ? NULL : scr_dyn_retain(target);
3544
+ }
3545
+ if (descriptor->kind == SCR_DYN_TYPED_REF) {
3546
+ ScrDyn *view = scr_dyn_typed_ref_materialize(descriptor);
3547
+ ScrDyn *result = scr_exc_pending() ? NULL : scr_dyn_define_property(target, key, view);
3548
+ scr_dyn_release(view);
3549
+ return result;
3550
+ }
2909
3551
  if (key->kind == SCR_DYN_SYMBOL) return scr_dyn_define_symbol(target, key, descriptor);
2910
3552
  if (target->kind == SCR_DYN_PROXY || descriptor->kind == SCR_DYN_PROXY) {
2911
3553
  scr_dyn_proxy_unsupported("Object.defineProperty");
@@ -3136,6 +3778,7 @@ bool scr_dyn_truthy(const ScrDyn *d) {
3136
3778
  * null answers "object" — JS's oldest wart, preserved. */
3137
3779
  ScrStr *scr_dyn_typeof(const ScrDyn *d) {
3138
3780
  const char *s;
3781
+ if (d->kind == SCR_DYN_PROXY) return scr_dyn_typeof(d->v.proxy.target);
3139
3782
  if (d->kind == SCR_DYN_TYPED_REF) {
3140
3783
  if (d->v.typed_ref.type_key_len >= 7 &&
3141
3784
  memcmp(d->v.typed_ref.type_key, "object:", 7) == 0)
@@ -3170,6 +3813,16 @@ ScrStr *scr_dyn_typeof(const ScrDyn *d) {
3170
3813
  return scr_str_new(s, strlen(s));
3171
3814
  }
3172
3815
 
3816
+ bool scr_dyn_is_callable(const ScrDyn *value) {
3817
+ while (value->kind == SCR_DYN_PROXY) value = value->v.proxy.target;
3818
+ return value->kind == SCR_DYN_FUNC || scr_dyn_isl_typeof_is(value, "function");
3819
+ }
3820
+
3821
+ int scr_dyn_function_kind(const ScrDyn *value) {
3822
+ while (value->kind == SCR_DYN_PROXY) value = value->v.proxy.target;
3823
+ return value->kind == SCR_DYN_FUNC ? value->v.fn.clo->function_kind : 0;
3824
+ }
3825
+
3173
3826
  bool scr_dyn_is_object(const ScrDyn *d) {
3174
3827
  ScrStr *type = scr_dyn_typeof(d);
3175
3828
  bool object = type->len == 6 && memcmp(type->data, "object", 6) == 0;
@@ -3415,6 +4068,29 @@ static SCR_TL ScrErrDynEnt *scr_errdyn_cache = NULL;
3415
4068
  static SCR_TL size_t scr_errdyn_n = 0, scr_errdyn_cap = 0;
3416
4069
  static SCR_TL bool scr_errdyn_teardown_registered = false;
3417
4070
 
4071
+ typedef struct {
4072
+ const ScrVt *vt;
4073
+ ScrDyn *(*box)(void *);
4074
+ } ScrErrorDynType;
4075
+ static SCR_TL ScrErrorDynType *scr_error_dyn_types = NULL;
4076
+ static SCR_TL size_t scr_error_dyn_type_count = 0;
4077
+
4078
+ static void scr_error_dyn_types_drop(void) {
4079
+ free(scr_error_dyn_types);
4080
+ scr_error_dyn_types = NULL;
4081
+ scr_error_dyn_type_count = 0;
4082
+ }
4083
+
4084
+ void scr_error_register_dyn(const ScrVt *vt, ScrDyn *(*box)(void *)) {
4085
+ for (size_t i = 0; i < scr_error_dyn_type_count; i++) {
4086
+ if (scr_error_dyn_types[i].vt == vt) return;
4087
+ }
4088
+ if (!scr_error_dyn_type_count) scr_atexit(scr_error_dyn_types_drop);
4089
+ scr_error_dyn_types = realloc(scr_error_dyn_types, (scr_error_dyn_type_count + 1) * sizeof *scr_error_dyn_types);
4090
+ if (!scr_error_dyn_types) scr_json_oom();
4091
+ scr_error_dyn_types[scr_error_dyn_type_count++] = (ScrErrorDynType){vt, box};
4092
+ }
4093
+
3418
4094
  static void scr_errdyn_teardown(void) {
3419
4095
  for (size_t i = 0; i < scr_errdyn_n; i++) {
3420
4096
  scr_error_release(scr_errdyn_cache[i].err);
@@ -3425,14 +4101,32 @@ static void scr_errdyn_teardown(void) {
3425
4101
  scr_errdyn_n = scr_errdyn_cap = 0;
3426
4102
  }
3427
4103
 
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
- }
4104
+ ScrDyn *scr_error_dyn_fields(const ScrError *e) {
3432
4105
  ScrDyn *d = scr_dyn_new_obj();
3433
4106
  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));
4107
+ d->v.obj.entries[d->v.obj.len - 1].enumerable = false;
4108
+ if (e->name_present) {
4109
+ scr_dyn_obj_set(d, "name", 4, scr_dyn_new_str(e->name));
4110
+ d->v.obj.entries[d->v.obj.len - 1].enumerable = e->name_enumerable;
4111
+ }
4112
+ if (!e->name_present || !e->message_present) {
4113
+ ScrDyn *prototype = scr_dyn_new_obj();
4114
+ if (!e->name_present) {
4115
+ scr_dyn_obj_set(prototype, "name", 4, scr_dyn_new_str(e->name));
4116
+ prototype->v.obj.entries[prototype->v.obj.len - 1].enumerable = false;
4117
+ }
4118
+ if (!e->message_present) {
4119
+ scr_dyn_obj_set(prototype, "message", 7, scr_dyn_new_str(e->message));
4120
+ prototype->v.obj.entries[prototype->v.obj.len - 1].enumerable = false;
4121
+ }
4122
+ scr_dyn_release(scr_dyn_set_prototype(d, prototype));
4123
+ scr_dyn_release(prototype);
4124
+ }
4125
+ if (e->message_present) {
4126
+ scr_dyn_obj_set(d, "message", 7, scr_dyn_new_str(e->message));
4127
+ d->v.obj.entries[d->v.obj.len - 1].enumerable = e->message_enumerable;
4128
+ }
4129
+ if (e->stack) scr_dyn_obj_set(d, "stack", 5, scr_dyn_new_str(e->stack));
3436
4130
  if (e->code) scr_dyn_obj_set(d, "code", 4, scr_dyn_new_str(e->code));
3437
4131
  if (e->error_cause) {
3438
4132
  scr_dyn_obj_set(d, "cause", 5, scr_dyn_retain(e->error_cause));
@@ -3446,6 +4140,21 @@ ScrDyn *scr_dyn_from_error(const ScrError *e) {
3446
4140
  scr_dyn_obj_set(d, "cause", 5, scr_domex_cause((ScrError *)e));
3447
4141
  }
3448
4142
  }
4143
+ return d;
4144
+ }
4145
+
4146
+ ScrDyn *scr_dyn_from_error(const ScrError *e) {
4147
+ for (size_t i = 0; i < scr_errdyn_n; i++) {
4148
+ if (scr_errdyn_cache[i].err == e) return scr_dyn_retain(scr_errdyn_cache[i].dyn);
4149
+ }
4150
+ ScrDyn *d = NULL;
4151
+ for (size_t i = 0; i < scr_error_dyn_type_count; i++) {
4152
+ if (scr_error_dyn_types[i].vt == e->vt) {
4153
+ d = scr_error_dyn_types[i].box((void *)e);
4154
+ break;
4155
+ }
4156
+ }
4157
+ if (!d) d = scr_error_dyn_fields(e);
3449
4158
  if (scr_errdyn_n == scr_errdyn_cap) {
3450
4159
  scr_errdyn_cap = scr_errdyn_cap ? scr_errdyn_cap * 2 : 8;
3451
4160
  scr_errdyn_cache = realloc(scr_errdyn_cache, scr_errdyn_cap * sizeof *scr_errdyn_cache);
@@ -3474,6 +4183,54 @@ ScrDyn *scr_dyn_from_error(const ScrError *e) {
3474
4183
  * its next boxing answers the same dyn node. The dyn node is borrowed. */
3475
4184
  static void scr_error_cause_drop_impl(void *obj);
3476
4185
 
4186
+ void scr_error_commit_dyn(ScrError *e, const ScrDyn *view) {
4187
+ ScrDynEntry *name_entry = NULL;
4188
+ for (size_t i = 0; i < view->v.obj.len; i++) {
4189
+ ScrDynEntry *entry = &view->v.obj.entries[i];
4190
+ if (entry->key_len == 4 && memcmp(entry->key, "name", 4) == 0) { name_entry = entry; break; }
4191
+ }
4192
+ ScrDyn *name = name_entry ? name_entry->value : NULL;
4193
+ if (name && name->kind != SCR_DYN_STR) {
4194
+ scr_dyn_check_fail(NULL, "string", name);
4195
+ return;
4196
+ }
4197
+ ScrStr *next_name = name ? scr_str_retain(name->v.str) : scr_error_default_name(e);
4198
+ scr_str_release(e->name);
4199
+ e->name = next_name;
4200
+ e->name_present = name != NULL;
4201
+ e->name_enumerable = name_entry && name_entry->enumerable;
4202
+ ScrDyn *message = scr_dyn_obj_get(view, "message", 7);
4203
+ if (message && message->kind != SCR_DYN_STR) {
4204
+ scr_dyn_check_fail(NULL, "string", message);
4205
+ return;
4206
+ }
4207
+ ScrStr *next_message = message ? scr_str_retain(message->v.str) : scr_str_new("", 0);
4208
+ scr_str_release(e->message);
4209
+ e->message = next_message;
4210
+ e->message_present = message != NULL;
4211
+ e->message_enumerable = false;
4212
+ for (size_t i = 0; message && i < view->v.obj.len; i++) {
4213
+ const ScrDynEntry *entry = &view->v.obj.entries[i];
4214
+ if (entry->key_len == 7 && memcmp(entry->key, "message", 7) == 0) e->message_enumerable = entry->enumerable;
4215
+ }
4216
+ ScrDyn *stack = scr_dyn_obj_get(view, "stack", 5);
4217
+ if (stack && stack->kind == SCR_DYN_STR) {
4218
+ ScrStr *replacement = scr_str_retain(stack->v.str);
4219
+ scr_str_release(e->stack);
4220
+ e->stack = replacement;
4221
+ }
4222
+ ScrDyn *cause = scr_dyn_obj_get(view, "cause", 5);
4223
+ scr_error_install_cause_drop(&scr_error_cause_drop_impl);
4224
+ ScrDyn *replacement = cause ? scr_dyn_retain(cause) : NULL;
4225
+ scr_dyn_release(e->error_cause);
4226
+ e->error_cause = replacement;
4227
+ e->cause_enumerable = false;
4228
+ for (size_t i = 0; cause && i < view->v.obj.len; i++) {
4229
+ const ScrDynEntry *entry = &view->v.obj.entries[i];
4230
+ if (entry->key_len == 5 && memcmp(entry->key, "cause", 5) == 0) e->cause_enumerable = entry->enumerable;
4231
+ }
4232
+ }
4233
+
3477
4234
  ScrError *scr_error_from_dyn(const ScrDyn *d) {
3478
4235
  ScrError *hit = scr_errdyn_err_of(d);
3479
4236
  if (hit) return hit;
@@ -3494,6 +4251,8 @@ ScrError *scr_error_from_dyn(const ScrDyn *d) {
3494
4251
  if (en && en->kind == SCR_DYN_STR) {
3495
4252
  scr_str_release(e->name);
3496
4253
  e->name = scr_str_retain(en->v.str);
4254
+ e->name_present = true;
4255
+ e->name_enumerable = true;
3497
4256
  }
3498
4257
  if (ec && ec->kind == SCR_DYN_STR) e->code = scr_str_retain(ec->v.str);
3499
4258
  ScrDyn *cause = scr_dyn_obj_get(d, "cause", 5);
@@ -3539,11 +4298,20 @@ void scr_errdyn_put(ScrError *e, ScrDyn *d) {
3539
4298
  /* Error.cause has one live value even when the Error already crossed a
3540
4299
  * checked-value boundary. Reflective data-property edits update its slot. */
3541
4300
  static void scr_error_sync_cause(ScrDyn *view, const ScrStr *key) {
3542
- if (key->len != 5 || memcmp(key->data, "cause", 5) != 0) return;
4301
+ bool cause = key->len == 5 && memcmp(key->data, "cause", 5) == 0;
4302
+ bool stack = key->len == 5 && memcmp(key->data, "stack", 5) == 0;
4303
+ if (!cause && !stack) return;
3543
4304
  ScrDynEntry *entry = scr_dyn_entry(view, key);
3544
4305
  for (size_t i = 0; i < scr_errdyn_n; i++) {
3545
4306
  if (scr_errdyn_cache[i].dyn != view) continue;
3546
4307
  ScrError *e = scr_errdyn_cache[i].err;
4308
+ if (stack) {
4309
+ if (entry && entry->value->kind == SCR_DYN_STR) {
4310
+ scr_str_release(e->stack);
4311
+ e->stack = scr_str_retain(entry->value->v.str);
4312
+ }
4313
+ continue;
4314
+ }
3547
4315
  if (e->vt == &scr_error_vts[SCR_ERR_DOMEX]) continue;
3548
4316
  ScrDyn *replacement = entry ? scr_dyn_retain(entry->value) : NULL;
3549
4317
  scr_error_install_cause_drop(&scr_error_cause_drop_impl);
@@ -3687,20 +4455,7 @@ ScrStr *scr_dyn_to_string_argument(const ScrDyn *d, const ScrDyn *argument, cons
3687
4455
  scr_str_release(encoding);
3688
4456
  return result;
3689
4457
  }
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
- }
4458
+ if (d->kind == SCR_DYN_NUM) return scr_num_to_string_radix(d->v.num, argument);
3704
4459
  if (d->kind == SCR_DYN_OBJ && !scr_dyn_property_owner(d, "toString", 8) && !scr_dyn_has_object_prototype(d)) {
3705
4460
  ScrJsonBuf b;
3706
4461
  scr_jb_init(&b);
@@ -3709,7 +4464,7 @@ ScrStr *scr_dyn_to_string_argument(const ScrDyn *d, const ScrDyn *argument, cons
3709
4464
  scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&b));
3710
4465
  return scr_str_new("", 0);
3711
4466
  }
3712
- return scr_dyn_to_string(d, NULL);
4467
+ return scr_dyn_to_string_method(d, NULL, what);
3713
4468
  }
3714
4469
 
3715
4470
  /* JS String() over the dyn kind — the WebIDL ToString the web globals
@@ -3929,6 +4684,46 @@ double scr_dyn_number_constructor(const ScrDyn *d) {
3929
4684
  return result;
3930
4685
  }
3931
4686
 
4687
+ static ScrBigInt *scr_dyn_bigint_convert(const ScrDyn *d, bool allow_number) {
4688
+ ScrDyn *primitive = scr_dyn_add_primitive(d);
4689
+ if (!primitive) return NULL;
4690
+ ScrBigInt *result = NULL;
4691
+ switch (primitive->kind) {
4692
+ case SCR_DYN_BIGINT: result = scr_bigint_retain(primitive->v.bigint); break;
4693
+ case SCR_DYN_STR: result = scr_bigint_parse(primitive->v.str); break;
4694
+ case SCR_DYN_NUM:
4695
+ if (allow_number) result = scr_bigint_from_f64(primitive->v.num);
4696
+ else {
4697
+ ScrStr *text = scr_dyn_string_coerce_js(primitive);
4698
+ ScrJsonBuf message;
4699
+ scr_jb_init(&message);
4700
+ scr_jb_puts(&message, "Cannot convert ");
4701
+ for (size_t i = 0; i < text->len; i++) scr_jb_putc(&message, text->data[i]);
4702
+ scr_jb_puts(&message, " to a BigInt");
4703
+ scr_str_release(text);
4704
+ scr_throw_error(SCR_ERR_TYPE, scr_jb_finish(&message));
4705
+ }
4706
+ break;
4707
+ case SCR_DYN_BOOL: result = scr_bigint_from_i64(primitive->v.b ? 1 : 0); break;
4708
+ default: {
4709
+ const char *message = primitive->kind == SCR_DYN_NULL ? "Cannot convert null to a BigInt"
4710
+ : primitive->kind == SCR_DYN_UNDEF ? "Cannot convert undefined to a BigInt" : "Cannot convert Symbol() to a BigInt";
4711
+ scr_throw_error_msg(SCR_ERR_TYPE, message, strlen(message));
4712
+ break;
4713
+ }
4714
+ }
4715
+ scr_dyn_release(primitive);
4716
+ return result;
4717
+ }
4718
+
4719
+ ScrBigInt *scr_dyn_bigint_constructor(const ScrDyn *d) {
4720
+ return scr_dyn_bigint_convert(d, true);
4721
+ }
4722
+
4723
+ ScrBigInt *scr_dyn_bigint_coerce(const ScrDyn *d) {
4724
+ return scr_dyn_bigint_convert(d, false);
4725
+ }
4726
+
3932
4727
  /* OrdinaryToPrimitive's default hint is numeric for the represented
3933
4728
  * ordinary objects. Retain the primitive itself: addition must choose
3934
4729
  * string concatenation before either side is converted to a number. */
@@ -4037,7 +4832,45 @@ ScrDyn *scr_dyn_increment(const ScrDyn *value, bool increment) {
4037
4832
  scr_bigint_release(one);
4038
4833
  return out;
4039
4834
  }
4040
- return scr_dyn_new_num(value->v.num + (increment ? 1 : -1));
4835
+ return scr_dyn_new_num(value->v.num + (increment ? 1 : -1));
4836
+ }
4837
+
4838
+ bool scr_dyn_compare(const ScrDyn *left, const ScrDyn *right, const ScrStr *operation) {
4839
+ // ToPrimitive is observable and always visits the original left operand
4840
+ // first, including the > and <= spellings of relational comparison.
4841
+ ScrDyn *l = scr_dyn_add_primitive(left);
4842
+ if (!l) return false;
4843
+ ScrDyn *r = scr_dyn_add_primitive(right);
4844
+ if (!r) { scr_dyn_release(l); return false; }
4845
+ double order = 2;
4846
+ if (l->kind == SCR_DYN_STR && r->kind == SCR_DYN_STR) {
4847
+ int compared = scr_str_cmp_u16(l->v.str, r->v.str);
4848
+ order = compared < 0 ? -1 : compared > 0 ? 1 : 0;
4849
+ } else if (l->kind == SCR_DYN_BIGINT && r->kind == SCR_DYN_STR) {
4850
+ order = scr_bigint_cmp_string(l->v.bigint, r->v.str);
4851
+ } else if (l->kind == SCR_DYN_STR && r->kind == SCR_DYN_BIGINT) {
4852
+ double opposite = scr_bigint_cmp_string(r->v.bigint, l->v.str);
4853
+ order = opposite == 2 ? 2 : -opposite;
4854
+ } else if (l->kind == SCR_DYN_BIGINT && r->kind == SCR_DYN_BIGINT) {
4855
+ order = scr_bigint_cmp_f64(l->v.bigint, r->v.bigint);
4856
+ } else {
4857
+ double a = 0, b = 0;
4858
+ bool valid = (l->kind == SCR_DYN_BIGINT || scr_dyn_number_coerce_js(l, &a)) &&
4859
+ (r->kind == SCR_DYN_BIGINT || scr_dyn_number_coerce_js(r, &b));
4860
+ if (valid) {
4861
+ if (l->kind == SCR_DYN_BIGINT) order = scr_bigint_cmp_number(l->v.bigint, b);
4862
+ else if (r->kind == SCR_DYN_BIGINT) {
4863
+ double opposite = scr_bigint_cmp_number(r->v.bigint, a);
4864
+ order = opposite == 2 ? 2 : -opposite;
4865
+ } else if (!isnan(a) && !isnan(b)) order = a < b ? -1 : a > b ? 1 : 0;
4866
+ }
4867
+ }
4868
+ scr_dyn_release(l);
4869
+ scr_dyn_release(r);
4870
+ if (scr_exc_pending() || order == 2) return false;
4871
+ return operation->data[0] == '<'
4872
+ ? (operation->len == 2 ? order <= 0 : order < 0)
4873
+ : (operation->len == 2 ? order >= 0 : order > 0);
4041
4874
  }
4042
4875
 
4043
4876
  ScrDyn *scr_dyn_arithmetic(const ScrDyn *left, const ScrDyn *right, const ScrStr *operation) {
@@ -4121,6 +4954,12 @@ static const char *scr_dyn_kind_name(const ScrDyn *d);
4121
4954
  * valid dense index, every other kind false (tsc admits `in` only on
4122
4955
  * object-typed operands). Proxy traps may throw. Borrows both. */
4123
4956
  bool scr_dyn_has_key(const ScrDyn *v, const ScrStr *key) {
4957
+ if (scr_dyn_generator(v)) {
4958
+ static const char *const inherited[] = { "next", "return", "throw", "constructor", "toString", "valueOf", "hasOwnProperty", "propertyIsEnumerable", "isPrototypeOf", "toLocaleString", "__proto__" };
4959
+ for (size_t i = 0; i < sizeof inherited / sizeof inherited[0]; i++)
4960
+ if (key->len == strlen(inherited[i]) && memcmp(key->data, inherited[i], key->len) == 0) return true;
4961
+ return false;
4962
+ }
4124
4963
  if (scr_dyn_class_reflection_fence(v)) return false;
4125
4964
  if (v->kind == SCR_DYN_PROXY) return scr_dyn_proxy_has(v, key);
4126
4965
  if (v->kind == SCR_DYN_JSVAL) return scr_dyn_isl_fence(v, "'in'");
@@ -4131,12 +4970,10 @@ bool scr_dyn_has_key(const ScrDyn *v, const ScrStr *key) {
4131
4970
  return out;
4132
4971
  }
4133
4972
  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;
4973
+ return scr_dyn_property_owner(v, key->data, key->len) != NULL;
4138
4974
  }
4139
4975
  if (v->kind == SCR_DYN_FUNC) {
4976
+ if (scr_dyn_property_owner(v, key->data, key->len)) return true;
4140
4977
  ScrDyn *descriptor = scr_dyn_own_descriptor(v, key);
4141
4978
  bool present = descriptor && descriptor->kind != SCR_DYN_UNDEF;
4142
4979
  scr_dyn_release(descriptor);
@@ -4155,6 +4992,8 @@ bool scr_dyn_has_key(const ScrDyn *v, const ScrStr *key) {
4155
4992
  if (v->kind == SCR_DYN_ARR) {
4156
4993
  if (key->len == 6 && memcmp(key->data, "length", 6) == 0) return true;
4157
4994
  if (v->v.arr.properties && scr_dyn_obj_get(v->v.arr.properties, key->data, key->len)) return true;
4995
+ const ScrDyn *prototype = v->prototype ? v->prototype : !v->null_proto && v != scr_builtin_array_prototype ? scr_builtin_array_prototype : NULL;
4996
+ if (prototype && scr_dyn_has_key(prototype, key)) return true;
4158
4997
  if (key->len == 0 || key->len > 10) return false;
4159
4998
  size_t idx = 0;
4160
4999
  for (size_t i = 0; i < key->len; i++) {
@@ -4164,7 +5003,7 @@ bool scr_dyn_has_key(const ScrDyn *v, const ScrStr *key) {
4164
5003
  if (idx > (4294967294ULL - (size_t)(c - '0')) / 10) return false;
4165
5004
  idx = idx * 10 + (size_t)(c - '0');
4166
5005
  }
4167
- return idx < v->v.arr.len;
5006
+ return scr_dyn_arr_has_index(v, idx);
4168
5007
  }
4169
5008
  if (v->kind == SCR_DYN_STR)
4170
5009
  return scr_dyn_canonical_own_index(key, (size_t)scr_str_utf16_len(v->v.str));
@@ -4192,9 +5031,16 @@ static void scr_dyn_object_key_set(ScrDyn *recv, ScrStr *key, ScrDyn *value, con
4192
5031
  }
4193
5032
  }
4194
5033
  if (!scr_dyn_entry(recv, key)) {
4195
- for (const ScrDyn *current = recv->prototype; current && current->kind == SCR_DYN_OBJ; current = current->prototype) {
4196
- ScrDynEntry *inherited = scr_dyn_entry((ScrDyn *)current, key);
4197
- if (!inherited) continue;
5034
+ for (const ScrDyn *current = recv->prototype; current;) {
5035
+ ScrDyn *table = current->kind == SCR_DYN_FUNC ? scr_dyn_fn_properties(current) : NULL;
5036
+ const ScrDyn *object = table ? table : current;
5037
+ if (object->kind != SCR_DYN_OBJ) { scr_dyn_release(table); break; }
5038
+ ScrDynEntry *inherited = scr_dyn_entry((ScrDyn *)object, key);
5039
+ if (!inherited) {
5040
+ current = object->prototype;
5041
+ scr_dyn_release(table);
5042
+ continue;
5043
+ }
4198
5044
  if (inherited->accessor && inherited->setter) {
4199
5045
  ScrDyn *args[] = {value};
4200
5046
  ScrDyn *setter = scr_dyn_retain(inherited->setter);
@@ -4203,13 +5049,16 @@ static void scr_dyn_object_key_set(ScrDyn *recv, ScrStr *key, ScrDyn *value, con
4203
5049
  scr_dyn_this_pop();
4204
5050
  scr_dyn_release(setter);
4205
5051
  scr_dyn_release(result);
5052
+ scr_dyn_release(table);
4206
5053
  return;
4207
5054
  }
4208
5055
  if (inherited->accessor || !inherited->writable) {
4209
5056
  static const char message[] = "Cannot assign to read only property";
4210
5057
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
5058
+ scr_dyn_release(table);
4211
5059
  return;
4212
5060
  }
5061
+ scr_dyn_release(table);
4213
5062
  break;
4214
5063
  }
4215
5064
  }
@@ -4263,22 +5112,20 @@ void scr_dyn_key_set(ScrDyn *recv, ScrStr *key, ScrDyn *value) {
4263
5112
  return;
4264
5113
  }
4265
5114
  size_t length = (size_t)number;
4266
- if (length > recv->v.arr.len && recv->non_extensible) {
4267
- static const char message[] = "Cannot add property, object is not extensible";
4268
- scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
4269
- return;
4270
- }
4271
- if (length > recv->v.arr.len) {
4272
- static const char message[] = "Sparse array lengths are not supported yet";
5115
+ if (length > recv->v.arr.len + 1000000) {
5116
+ static const char message[] = "Checked array growth exceeds the native allocation limit";
4273
5117
  scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
4274
5118
  return;
4275
5119
  }
4276
- if (length < recv->v.arr.len && recv->v.arr.sealed) {
4277
- static const char message[] = "Cannot delete non-configurable property";
4278
- scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
4279
- return;
5120
+ while (recv->v.arr.len < length) scr_dyn_arr_push_hole(recv);
5121
+ while (recv->v.arr.len > length) {
5122
+ if (recv->v.arr.sealed && scr_dyn_arr_has_index(recv, recv->v.arr.len - 1)) {
5123
+ static const char message[] = "Cannot delete non-configurable property";
5124
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
5125
+ return;
5126
+ }
5127
+ scr_dyn_release(recv->v.arr.items[--recv->v.arr.len]);
4280
5128
  }
4281
- while (recv->v.arr.len > length) scr_dyn_release(recv->v.arr.items[--recv->v.arr.len]);
4282
5129
  return;
4283
5130
  }
4284
5131
  /* Canonical indexes extend the dense portion; other names live in the
@@ -4296,7 +5143,7 @@ void scr_dyn_key_set(ScrDyn *recv, ScrStr *key, ScrDyn *value) {
4296
5143
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
4297
5144
  return;
4298
5145
  }
4299
- if (recv->non_extensible && idx >= recv->v.arr.len) {
5146
+ if (recv->non_extensible && !scr_dyn_arr_has_index(recv, idx)) {
4300
5147
  static const char message[] = "Cannot add property, object is not extensible";
4301
5148
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
4302
5149
  return;
@@ -4307,10 +5154,11 @@ void scr_dyn_key_set(ScrDyn *recv, ScrStr *key, ScrDyn *value) {
4307
5154
  return;
4308
5155
  }
4309
5156
  while (recv->v.arr.len <= idx) {
4310
- scr_dyn_arr_push(recv, scr_dyn_retain(scr_dyn_undefined()));
5157
+ scr_dyn_arr_push_hole(recv);
4311
5158
  }
4312
5159
  ScrDyn *old = recv->v.arr.items[idx];
4313
5160
  recv->v.arr.items[idx] = scr_dyn_retain(value);
5161
+ if (recv->v.arr.presence) recv->v.arr.presence[idx] = 1;
4314
5162
  scr_dyn_release(old);
4315
5163
  return;
4316
5164
  }
@@ -5151,6 +5999,14 @@ static void scr_json_delete_member(ScrDyn *object, const ScrStr *key) {
5151
5999
  void scr_dyn_key_delete(ScrDyn *recv, const ScrStr *key, bool strict) {
5152
6000
  if (scr_dyn_class_reflection_fence(recv)) return;
5153
6001
  if (recv->kind == SCR_DYN_PROXY) { scr_dyn_proxy_delete(recv, key); return; }
6002
+ if (recv->kind == SCR_DYN_TYPED_REF && recv->v.typed_ref.commit &&
6003
+ !strncmp(recv->v.typed_ref.type_key, "record:", 7)) {
6004
+ ScrDyn *materialized = scr_dyn_typed_ref_materialize(recv);
6005
+ if (!scr_exc_pending()) scr_dyn_key_delete(materialized, key, strict);
6006
+ if (!scr_exc_pending()) scr_dyn_typed_ref_commit(recv);
6007
+ scr_dyn_release(materialized);
6008
+ return;
6009
+ }
5154
6010
  if (recv->kind == SCR_DYN_FUNC) {
5155
6011
  if (scr_dyn_fn_property_fence(key)) return;
5156
6012
  ScrDyn *table = scr_dyn_fn_properties(recv);
@@ -5171,6 +6027,27 @@ void scr_dyn_key_delete(ScrDyn *recv, const ScrStr *key, bool strict) {
5171
6027
  scr_error_sync_cause(recv, key);
5172
6028
  return;
5173
6029
  }
6030
+ if (recv->kind == SCR_DYN_ARR && scr_dyn_canonical_own_index(key, recv->v.arr.len)) {
6031
+ size_t index = 0;
6032
+ for (size_t i = 0; i < key->len; i++) index = index * 10 + (size_t)(key->data[i] - '0');
6033
+ if (!scr_dyn_arr_has_index(recv, index)) return;
6034
+ if (recv->v.arr.sealed) {
6035
+ if (strict) {
6036
+ static const char message[] = "Cannot delete non-configurable property";
6037
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6038
+ }
6039
+ return;
6040
+ }
6041
+ if (!recv->v.arr.presence) {
6042
+ recv->v.arr.presence = malloc(recv->v.arr.cap);
6043
+ if (!recv->v.arr.presence) scr_json_oom();
6044
+ memset(recv->v.arr.presence, 1, recv->v.arr.len);
6045
+ }
6046
+ recv->v.arr.presence[index] = 0;
6047
+ scr_dyn_release(recv->v.arr.items[index]);
6048
+ recv->v.arr.items[index] = scr_dyn_retain(scr_dyn_undefined());
6049
+ return;
6050
+ }
5174
6051
  if (recv->kind == SCR_DYN_ARR && recv->v.arr.properties &&
5175
6052
  scr_dyn_obj_get(recv->v.arr.properties, key->data, key->len)) {
5176
6053
  scr_dyn_key_delete(recv->v.arr.properties, key, strict);
@@ -5242,6 +6119,7 @@ static ScrDyn *scr_json_revive(ScrDyn *holder, const ScrStr *key,
5242
6119
  ScrDyn *scr_json_parse_reviver(ScrStr *text, const ScrDyn *reviver) {
5243
6120
  ScrDyn *parsed = scr_json_parse(text);
5244
6121
  if (!parsed) return NULL; /* No callback runs on invalid input. */
6122
+ if (reviver->kind != SCR_DYN_FUNC) return parsed;
5245
6123
  ScrDyn *holder = scr_dyn_new_obj();
5246
6124
  scr_dyn_obj_set(holder, "", 0, parsed);
5247
6125
  ScrStr *key = scr_str_new("", 0);
@@ -5273,7 +6151,7 @@ static ScrDyn *scr_json_replace(const ScrDyn *holder, const ScrStr *key, const S
5273
6151
  ScrDyn *view = value->kind == SCR_DYN_TYPED_REF ? scr_dyn_typed_ref_materialize(value) : NULL;
5274
6152
  const ScrDyn *inspected = view ? view : value;
5275
6153
  if (scr_exc_pending()) { scr_dyn_release(view); scr_dyn_release(value); return NULL; }
5276
- if (inspected->kind == SCR_DYN_HANDLE && inspected->v.handle.tag == SCR_DYNH_DATE) {
6154
+ if (inspected->kind == SCR_DYN_HANDLE && (inspected->v.handle.tag == SCR_DYNH_DATE || inspected->v.handle.tag == SCR_DYNH_URL)) {
5277
6155
  const ScrDynHandleOps *ops = scr_dyn_handle_ops_of(inspected);
5278
6156
  ScrDyn *converted = ops->invoke(inspected->v.handle.ptr, value, "toJSON", NULL, 0, "toJSON");
5279
6157
  scr_dyn_release(value);
@@ -5461,7 +6339,7 @@ bool scr_dyn_strict_eq(const ScrDyn *a, const ScrDyn *b) {
5461
6339
  return a->v.handle.tag == b->v.handle.tag && a->v.handle.ptr == b->v.handle.ptr;
5462
6340
  case SCR_DYN_PROMISE:
5463
6341
  /* And the PROMISE: one promise crossing twice is one JS value. */
5464
- return a->v.promise == b->v.promise;
6342
+ return a->v.promise == b->v.promise || (scr_dyn_promise_identity_fn && scr_dyn_promise_identity_fn(a->v.promise, b->v.promise));
5465
6343
  case SCR_DYN_JSVAL:
5466
6344
  /* Identity is the ENGINE VALUE, not the box or even the cell: two
5467
6345
  * wraps of one engine value compare ===-equal (the engine's own
@@ -5476,6 +6354,36 @@ bool scr_dyn_strict_eq(const ScrDyn *a, const ScrDyn *b) {
5476
6354
  }
5477
6355
  }
5478
6356
 
6357
+ bool scr_dyn_abstract_eq(const ScrDyn *a, const ScrDyn *b) {
6358
+ if (a->kind == b->kind) return scr_dyn_strict_eq(a, b);
6359
+ bool an = a->kind == SCR_DYN_NULL || a->kind == SCR_DYN_UNDEF;
6360
+ bool bn = b->kind == SCR_DYN_NULL || b->kind == SCR_DYN_UNDEF;
6361
+ if (an || bn) return an && bn;
6362
+ if (a->kind == SCR_DYN_BOOL || b->kind == SCR_DYN_BOOL) {
6363
+ ScrDyn *numeric = scr_dyn_new_num(a->kind == SCR_DYN_BOOL ? (a->v.b ? 1 : 0) : (b->v.b ? 1 : 0));
6364
+ bool equal = a->kind == SCR_DYN_BOOL ? scr_dyn_abstract_eq(numeric, b) : scr_dyn_abstract_eq(a, numeric);
6365
+ scr_dyn_release(numeric);
6366
+ return equal;
6367
+ }
6368
+ if (scr_dyn_to_primitive_result_is_object(a) || scr_dyn_to_primitive_result_is_object(b)) {
6369
+ if (scr_dyn_to_primitive_result_is_object(a) && scr_dyn_to_primitive_result_is_object(b)) return scr_dyn_strict_eq(a, b);
6370
+ const ScrDyn *object = scr_dyn_to_primitive_result_is_object(a) ? a : b;
6371
+ ScrDyn *primitive = scr_dyn_add_primitive(object);
6372
+ bool equal = primitive && (object == a ? scr_dyn_abstract_eq(primitive, b) : scr_dyn_abstract_eq(a, primitive));
6373
+ scr_dyn_release(primitive);
6374
+ return equal;
6375
+ }
6376
+ if (a->kind == SCR_DYN_SYMBOL || b->kind == SCR_DYN_SYMBOL) return false;
6377
+ if (a->kind == SCR_DYN_BIGINT || b->kind == SCR_DYN_BIGINT) {
6378
+ const ScrDyn *integer = a->kind == SCR_DYN_BIGINT ? a : b;
6379
+ const ScrDyn *other = integer == a ? b : a;
6380
+ return other->kind == SCR_DYN_STR ? scr_bigint_eq_string(integer->v.bigint, other->v.str)
6381
+ : other->kind == SCR_DYN_NUM && scr_bigint_cmp_number(integer->v.bigint, other->v.num) == 0;
6382
+ }
6383
+ double left, right;
6384
+ return scr_dyn_number_coerce_js(a, &left) && scr_dyn_number_coerce_js(b, &right) && left == right;
6385
+ }
6386
+
5479
6387
  static SCR_TL ScrDyn *scr_function_constructors[4];
5480
6388
  static SCR_TL bool scr_function_constructors_registered;
5481
6389
 
@@ -5511,6 +6419,8 @@ static ScrDyn *scr_function_constructor(uint32_t kind) {
5511
6419
  /* Keyed read on a FUNC node (see scr_runtime.h): own props first, then
5512
6420
  * the function-instance built-ins name/length. +1 or NULL. */
5513
6421
  ScrDyn *scr_dyn_fn_get(const ScrDyn *d, const char *key, size_t key_len) {
6422
+ if (d->v.fn.class_obj && d->v.fn.class_obj->static_data && !d->v.fn.clo->props)
6423
+ d->v.fn.clo->props = scr_box_retain(d->v.fn.class_obj->static_data);
5514
6424
  if (!d->v.fn.class_obj && key_len == 9 && !memcmp(key, "prototype", 9) && !d->v.fn.clo->props) {
5515
6425
  if (d->v.fn.clo->function_kind & 1) {
5516
6426
  static const char message[] = "Native generator function prototypes have no lowering";
@@ -5551,7 +6461,8 @@ ScrDyn *scr_dyn_fn_get(const ScrDyn *d, const char *key, size_t key_len) {
5551
6461
  if (key_len == 6 && memcmp(key, "length", 6) == 0) {
5552
6462
  return scr_dyn_new_num((double)d->v.fn.arity);
5553
6463
  }
5554
- if (d->v.fn.class_obj) {
6464
+ if (key_len == 5 && memcmp(key, "apply", 5) == 0) return scr_dyn_function_apply();
6465
+ if (d->v.fn.class_obj && !d->v.fn.class_obj->static_data) {
5555
6466
  static const char message[] = "scriptc: class properties through unknown other than name and length are not supported";
5556
6467
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
5557
6468
  }
@@ -5567,6 +6478,12 @@ ScrDyn *scr_dyn_fn_get(const ScrDyn *d, const char *key, size_t key_len) {
5567
6478
 
5568
6479
  void scr_sc_validate_options(const ScrDyn *options) {
5569
6480
  if (options == NULL || options->kind == SCR_DYN_UNDEF || options->kind == SCR_DYN_NULL) return;
6481
+ if (options->kind == SCR_DYN_TYPED_REF) {
6482
+ ScrDyn *view = scr_dyn_typed_ref_materialize(options);
6483
+ if (view && !scr_exc_pending()) scr_sc_validate_options(view);
6484
+ scr_dyn_release(view);
6485
+ return;
6486
+ }
5570
6487
  /* An engine-held options bag IS a dictionary to Node — the "cannot be
5571
6488
  * converted" TypeError would be a wrong claim. Loud fence. */
5572
6489
  if (options->kind == SCR_DYN_JSVAL) {
@@ -5581,10 +6498,14 @@ void scr_sc_validate_options(const ScrDyn *options) {
5581
6498
  }
5582
6499
  ScrDyn *tr = scr_dyn_obj_get(options, "transfer", 8); /* borrowed */
5583
6500
  if (tr == NULL || tr->kind == SCR_DYN_UNDEF) return;
6501
+ ScrDyn *transferView = tr->kind == SCR_DYN_TYPED_REF ? scr_dyn_typed_ref_materialize(tr) : NULL;
6502
+ if (scr_exc_pending()) { scr_dyn_release(transferView); return; }
6503
+ if (transferView) tr = transferView;
5584
6504
  if (tr->kind != SCR_DYN_ARR) {
5585
6505
  static const char msg[] =
5586
6506
  "Failed to execute 'structuredClone': transfer in Options can not be converted to sequence.";
5587
6507
  scr_throw_error_msg_code(SCR_ERR_TYPE, msg, sizeof msg - 1, "ERR_INVALID_ARG_TYPE");
6508
+ scr_dyn_release(transferView);
5588
6509
  return;
5589
6510
  }
5590
6511
  if (tr->v.arr.len > 0) {
@@ -5592,6 +6513,7 @@ void scr_sc_validate_options(const ScrDyn *options) {
5592
6513
  * a non-transferable list member. */
5593
6514
  scr_throw_domex("DataCloneError", "Found invalid value in transferList.");
5594
6515
  }
6516
+ scr_dyn_release(transferView);
5595
6517
  }
5596
6518
 
5597
6519
  /* The parent chain rides the C stack: a revisit is a cycle. */
@@ -5651,6 +6573,7 @@ static ScrDyn *scr_sc_clone(const ScrDyn *v, const ScrScParent *up) {
5651
6573
  if (v->kind == SCR_DYN_ARR) {
5652
6574
  ScrDyn *out = scr_dyn_new_arr();
5653
6575
  for (size_t i = 0; i < v->v.arr.len; i++) {
6576
+ if (!scr_dyn_arr_has_index(v, i)) { scr_dyn_arr_push_hole(out); continue; }
5654
6577
  ScrDyn *c = scr_sc_clone(v->v.arr.items[i], &self);
5655
6578
  if (c == NULL) { /* threw */
5656
6579
  scr_dyn_release(out);
@@ -5745,11 +6668,21 @@ bool scr_dyn_err_instanceof(const ScrDyn *d, double kind) {
5745
6668
 
5746
6669
  static ScrDyn *scr_dyn_obj_read_receiver(const ScrDyn *d, const char *key, size_t key_len, const ScrDyn *receiver) {
5747
6670
  for (const ScrDyn *current = d; current; current = current->prototype) {
6671
+ if (current == scr_builtin_object_prototype) {
6672
+ scr_dyn_class_reflection_fence(current);
6673
+ return NULL;
6674
+ }
6675
+ if (current->kind == SCR_DYN_FUNC) {
6676
+ ScrDyn *table = scr_dyn_fn_properties(current);
6677
+ ScrDyn *result = scr_dyn_obj_read_receiver(table, key, key_len, receiver);
6678
+ scr_dyn_release(table);
6679
+ return result;
6680
+ }
5748
6681
  if (current->kind == SCR_DYN_ARR) {
5749
6682
  if (key_len == 6 && memcmp(key, "length", 6) == 0) return scr_dyn_new_num((double)current->v.arr.len);
5750
6683
  double index;
5751
- if (scr_dyn_key_is_index(key, key_len, &index) && index < (double)current->v.arr.len)
5752
- return scr_dyn_arr_at(current, index);
6684
+ if (scr_dyn_key_is_index(key, key_len, &index) && scr_dyn_arr_has_index(current, (size_t)index))
6685
+ return scr_dyn_retain(current->v.arr.items[(size_t)index]);
5753
6686
  if (current->v.arr.properties && scr_dyn_obj_get(current->v.arr.properties, key, key_len))
5754
6687
  return scr_dyn_obj_read_receiver(current->v.arr.properties, key, key_len, receiver);
5755
6688
  continue;
@@ -5793,10 +6726,229 @@ static ScrDyn *scr_dyn_obj_read_receiver(const ScrDyn *d, const char *key, size_
5793
6726
  return scr_dyn_retain(scr_dyn_undefined());
5794
6727
  }
5795
6728
 
6729
+ static SCR_TL ScrDyn *scr_function_apply_value;
6730
+
6731
+ static void scr_function_apply_cleanup(void) {
6732
+ scr_dyn_release(scr_function_apply_value);
6733
+ scr_function_apply_value = NULL;
6734
+ }
6735
+
6736
+ ScrDyn *scr_dyn_apply_array_like(const ScrDyn *target, const ScrDyn *receiver, const ScrDyn *arguments, const char *what) {
6737
+ ScrDyn *list = scr_dyn_new_arr();
6738
+ if (arguments && arguments->kind != SCR_DYN_UNDEF && arguments->kind != SCR_DYN_NULL) {
6739
+ if (!scr_iterator_object(arguments)) {
6740
+ static const char message[] = "CreateListFromArrayLike called on non-object";
6741
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6742
+ } else {
6743
+ ScrDyn *length = scr_iterator_read(arguments, "length", 6);
6744
+ double count = 0;
6745
+ bool ok = length && scr_dyn_number_coerce_js(length, &count);
6746
+ scr_dyn_release(length);
6747
+ if (ok && count > 1000000) {
6748
+ static const char message[] = "Function.prototype.apply exceeds the native argument limit";
6749
+ scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
6750
+ } else if (ok) for (size_t i = 0; (double)i < floor(count); i++) {
6751
+ char key[32];
6752
+ int size = snprintf(key, sizeof key, "%zu", i);
6753
+ ScrDyn *value = scr_iterator_read(arguments, key, (size_t)size);
6754
+ if (!value) break;
6755
+ scr_dyn_arr_push(list, value);
6756
+ }
6757
+ }
6758
+ }
6759
+ ScrDyn *result = NULL;
6760
+ if (!scr_exc_pending()) {
6761
+ scr_dyn_this_push_dyn(receiver);
6762
+ result = scr_dyn_call(target, list->v.arr.items, list->v.arr.len, what);
6763
+ scr_dyn_this_pop();
6764
+ }
6765
+ scr_dyn_release(list);
6766
+ return result;
6767
+ }
6768
+
6769
+ static ScrDyn *scr_function_apply_call(ScrClosure *closure, ScrDyn *const *args, size_t argc) {
6770
+ (void)closure;
6771
+ ScrDyn *receiver = scr_dyn_this_get();
6772
+ if (receiver->kind != SCR_DYN_FUNC) {
6773
+ scr_dyn_release(receiver);
6774
+ static const char message[] = "Function.prototype.apply was called on a non-callable value";
6775
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6776
+ return NULL;
6777
+ }
6778
+ ScrDyn *result = scr_dyn_apply_array_like(receiver, argc ? args[0] : scr_dyn_undefined(),
6779
+ argc > 1 ? args[1] : scr_dyn_undefined(), "Function.prototype.apply");
6780
+ scr_dyn_release(receiver);
6781
+ return result;
6782
+ }
6783
+
6784
+ ScrDyn *scr_dyn_function_apply(void) {
6785
+ if (!scr_function_apply_value) {
6786
+ scr_function_apply_value = scr_dyn_new_func(scr_closure_new(NULL, 0), scr_function_apply_call,
6787
+ 2, "native:Function.prototype.apply", "apply");
6788
+ scr_atexit(scr_function_apply_cleanup);
6789
+ }
6790
+ return scr_dyn_retain(scr_function_apply_value);
6791
+ }
6792
+
5796
6793
  ScrDyn *scr_dyn_obj_read(const ScrDyn *d, const char *key, size_t key_len) {
6794
+ if (d->kind == SCR_DYN_PROXY) {
6795
+ ScrStr *name = scr_str_new(key, key_len);
6796
+ ScrDyn *value = scr_dyn_proxy_get(d, name);
6797
+ scr_str_release(name);
6798
+ return value;
6799
+ }
5797
6800
  return scr_dyn_obj_read_receiver(d, key, key_len, d);
5798
6801
  }
5799
6802
 
6803
+ /* Compiler-owned class property tables use their native instance as the
6804
+ * receiver of inherited accessors, retaining field updates on that instance. */
6805
+ ScrDyn *scr_dyn_bag_get(ScrDyn *bag, ScrStr *key, ScrDyn *receiver) {
6806
+ return scr_dyn_obj_read_receiver(bag, key->data, key->len, receiver);
6807
+ }
6808
+
6809
+ void scr_dyn_bag_set(ScrDyn *bag, ScrStr *key, ScrDyn *value, ScrDyn *receiver) {
6810
+ scr_dyn_object_key_set(bag, key, value, receiver);
6811
+ }
6812
+
6813
+ /* Reflect uses OrdinaryGet/OrdinarySet with an independently supplied
6814
+ * receiver. Failed descriptor writes return false; user callbacks still
6815
+ * propagate their exceptions. Keys are converted once before dispatch. */
6816
+ ScrDyn *scr_dyn_reflect_get(ScrDyn *target, ScrDyn *raw_key, ScrDyn *receiver) {
6817
+ if (!scr_dyn_to_primitive_result_is_object(target)) {
6818
+ static const char message[] = "Reflect.get called on non-object";
6819
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6820
+ return NULL;
6821
+ }
6822
+ ScrDyn *key = scr_dyn_property_key_value(raw_key);
6823
+ if (!key) return NULL;
6824
+ ScrDyn *result = NULL;
6825
+ if (target->kind == SCR_DYN_TYPED_REF) {
6826
+ ScrDyn *view = scr_dyn_typed_ref_materialize(target);
6827
+ if (!scr_exc_pending()) result = scr_dyn_reflect_get(view, key, receiver);
6828
+ scr_dyn_release(view);
6829
+ } else if (key->kind == SCR_DYN_SYMBOL) {
6830
+ ScrDyn *symbols = scr_dyn_symbol_receiver(target);
6831
+ ScrDynEntry *entry = symbols ? scr_dyn_symbol_entry(symbols, key, false) : NULL;
6832
+ if (entry && entry->accessor && entry->getter) {
6833
+ ScrDyn *getter = scr_dyn_retain(entry->getter);
6834
+ scr_dyn_this_push_dyn(receiver);
6835
+ result = scr_dyn_call(getter, NULL, 0, "getter");
6836
+ scr_dyn_this_pop();
6837
+ scr_dyn_release(getter);
6838
+ } else result = scr_dyn_symbol_key_get(target, key, false);
6839
+ scr_dyn_release(symbols);
6840
+ } else if (target->kind == SCR_DYN_PROXY) result = scr_dyn_proxy_get_receiver(target, key->v.str, receiver);
6841
+ else result = scr_dyn_obj_read_receiver(target, key->v.str->data, key->v.str->len, receiver);
6842
+ scr_dyn_release(key);
6843
+ return result;
6844
+ }
6845
+
6846
+ bool scr_dyn_reflect_define(ScrDyn *receiver, ScrDyn *raw_key, ScrDyn *value) {
6847
+ if (!scr_dyn_to_primitive_result_is_object(receiver)) return false;
6848
+ ScrDyn *key = scr_dyn_property_key_value(raw_key);
6849
+ if (!key) return false;
6850
+ bool ok = false;
6851
+ if (receiver->kind == SCR_DYN_TYPED_REF) {
6852
+ ScrDyn *view = scr_dyn_typed_ref_materialize(receiver);
6853
+ if (!scr_exc_pending()) ok = scr_dyn_reflect_define(view, key, value);
6854
+ if (ok) scr_dyn_typed_ref_commit(receiver);
6855
+ scr_dyn_release(view);
6856
+ } else if (receiver->kind == SCR_DYN_PROXY) {
6857
+ scr_dyn_proxy_unsupported("Reflect.set receiver definition");
6858
+ } else if (receiver->kind == SCR_DYN_FUNC) {
6859
+ ScrDyn *table = scr_dyn_fn_properties(receiver);
6860
+ ok = scr_dyn_reflect_define(table, key, value);
6861
+ scr_dyn_release(table);
6862
+ } else {
6863
+ ScrDyn *symbols = key->kind == SCR_DYN_SYMBOL ? scr_dyn_symbol_receiver(receiver) : NULL;
6864
+ ScrDynEntry *entry = key->kind == SCR_DYN_SYMBOL ? (symbols ? scr_dyn_symbol_entry(symbols, key, true) : NULL)
6865
+ : receiver->kind == SCR_DYN_OBJ ? scr_dyn_entry(receiver, key->v.str)
6866
+ : receiver->kind == SCR_DYN_ARR && receiver->v.arr.properties ? scr_dyn_entry(receiver->v.arr.properties, key->v.str) : NULL;
6867
+ if (!(entry && (entry->accessor || !entry->writable)) && !(receiver->non_extensible && !scr_dyn_has_own_computed(receiver, key))) {
6868
+ if (entry) {
6869
+ ScrDyn *old = entry->value;
6870
+ entry->value = scr_dyn_retain(value);
6871
+ scr_dyn_release(old);
6872
+ ok = true;
6873
+ } else if (key->kind == SCR_DYN_SYMBOL && symbols) {
6874
+ ScrDyn *descriptor = scr_dyn_new_obj();
6875
+ scr_dyn_obj_set(descriptor, "value", 5, scr_dyn_retain(value));
6876
+ scr_dyn_obj_set(descriptor, "writable", 8, scr_dyn_new_bool(true));
6877
+ scr_dyn_obj_set(descriptor, "enumerable", 10, scr_dyn_new_bool(true));
6878
+ scr_dyn_obj_set(descriptor, "configurable", 12, scr_dyn_new_bool(true));
6879
+ ScrDyn *defined = scr_dyn_define_symbol(receiver, key, descriptor);
6880
+ scr_dyn_release(defined);
6881
+ scr_dyn_release(descriptor);
6882
+ ok = !scr_exc_pending();
6883
+ } else if (receiver->kind == SCR_DYN_OBJ) {
6884
+ scr_dyn_obj_set(receiver, key->v.str->data, key->v.str->len, scr_dyn_retain(value));
6885
+ ok = true;
6886
+ } else if (receiver->kind == SCR_DYN_ARR) {
6887
+ if (!receiver->v.arr.frozen) {
6888
+ scr_dyn_key_set(receiver, key->v.str, value);
6889
+ ok = !scr_exc_pending();
6890
+ }
6891
+ }
6892
+ }
6893
+ scr_dyn_release(symbols);
6894
+ }
6895
+ scr_dyn_release(key);
6896
+ return ok && !scr_exc_pending();
6897
+ }
6898
+
6899
+ bool scr_dyn_reflect_set(ScrDyn *target, ScrDyn *raw_key, ScrDyn *value, ScrDyn *receiver) {
6900
+ if (!scr_dyn_to_primitive_result_is_object(target)) {
6901
+ static const char message[] = "Reflect.set called on non-object";
6902
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
6903
+ return false;
6904
+ }
6905
+ ScrDyn *key = scr_dyn_property_key_value(raw_key);
6906
+ if (!key) return false;
6907
+ bool ok = false;
6908
+ if (target->kind == SCR_DYN_TYPED_REF) {
6909
+ ScrDyn *view = scr_dyn_typed_ref_materialize(target);
6910
+ if (!scr_exc_pending()) ok = scr_dyn_reflect_set(view, key, value, receiver);
6911
+ scr_dyn_release(view);
6912
+ } else if (target->kind == SCR_DYN_PROXY) {
6913
+ ScrDyn *trap = scr_dyn_proxy_trap(target, "set");
6914
+ if (!scr_exc_pending() && !trap) ok = scr_dyn_reflect_set(target->v.proxy.target, key, value, receiver);
6915
+ else if (trap) {
6916
+ ScrDyn *args[] = {target->v.proxy.target, key, value, receiver};
6917
+ ScrDyn *result = scr_dyn_proxy_call(target, trap, args, 4);
6918
+ ok = result && scr_dyn_truthy(result);
6919
+ scr_dyn_release(result);
6920
+ ScrDynEntry *entry = key->kind == SCR_DYN_STR ? scr_dyn_entry(target->v.proxy.target, key->v.str) : NULL;
6921
+ if (ok && entry && !entry->configurable && ((entry->accessor && !entry->setter) || (!entry->accessor && !entry->writable && !scr_dyn_property_same_value(entry->value, value)))) scr_dyn_proxy_invariant();
6922
+ }
6923
+ } else if (target->kind == SCR_DYN_FUNC) {
6924
+ ScrDyn *table = scr_dyn_fn_properties(target);
6925
+ ok = scr_dyn_reflect_set(table, key, value, receiver);
6926
+ scr_dyn_release(table);
6927
+ } else {
6928
+ ScrDyn *symbols = key->kind == SCR_DYN_SYMBOL ? scr_dyn_symbol_receiver(target) : NULL;
6929
+ ScrDynEntry *entry = symbols ? scr_dyn_symbol_entry(symbols, key, false) : NULL;
6930
+ if (key->kind == SCR_DYN_STR) for (ScrDyn *current = target; current; current = current->prototype) {
6931
+ if (current->kind == SCR_DYN_OBJ) entry = scr_dyn_entry(current, key->v.str);
6932
+ else if (current->kind == SCR_DYN_ARR && current->v.arr.properties) entry = scr_dyn_entry(current->v.arr.properties, key->v.str);
6933
+ if (entry) break;
6934
+ }
6935
+ if (entry && entry->accessor) {
6936
+ if (entry->setter) {
6937
+ ScrDyn *setter = scr_dyn_retain(entry->setter);
6938
+ scr_dyn_this_push_dyn(receiver);
6939
+ ScrDyn *result = scr_dyn_call(setter, &value, 1, "setter");
6940
+ scr_dyn_this_pop();
6941
+ scr_dyn_release(result);
6942
+ scr_dyn_release(setter);
6943
+ ok = !scr_exc_pending();
6944
+ }
6945
+ } else if (!entry || entry->writable) ok = scr_dyn_reflect_define(receiver, key, value);
6946
+ scr_dyn_release(symbols);
6947
+ }
6948
+ scr_dyn_release(key);
6949
+ return ok && !scr_exc_pending();
6950
+ }
6951
+
5800
6952
  /* ── Object.keys/values/entries over the checked-dynamic tree ──────────────────────────
5801
6953
  * JS own-key order: array-index keys ascending first, then the rest in
5802
6954
  * insertion order. entries answers [key, value] pairs; values RETAIN
@@ -5864,6 +7016,13 @@ ScrDyn *scr_dyn_obj_own_keys(const ScrDyn *v) {
5864
7016
  }
5865
7017
 
5866
7018
  ScrDyn *scr_dyn_get_own_property_names(const ScrDyn *value) {
7019
+ if (value->kind == SCR_DYN_TYPED_REF) {
7020
+ ScrDyn *view = scr_dyn_typed_ref_materialize(value);
7021
+ if (scr_exc_pending()) { scr_dyn_release(view); return NULL; }
7022
+ ScrDyn *result = scr_dyn_get_own_property_names(view);
7023
+ scr_dyn_release(view);
7024
+ return result;
7025
+ }
5867
7026
  if (value->kind == SCR_DYN_FUNC) {
5868
7027
  if (scr_dyn_class_reflection_fence(value)) return NULL;
5869
7028
  ScrDyn *table = scr_dyn_fn_properties(value);
@@ -5878,6 +7037,7 @@ ScrDyn *scr_dyn_get_own_property_names(const ScrDyn *value) {
5878
7037
  value->kind == SCR_DYN_BYTES ? value->v.bytes->len :
5879
7038
  (size_t)scr_str_utf16_len(value->v.str);
5880
7039
  for (size_t i = 0; i < length; i++) {
7040
+ if (value->kind == SCR_DYN_ARR && !scr_dyn_arr_has_index(value, i)) continue;
5881
7041
  char name[24];
5882
7042
  int size = snprintf(name, sizeof name, "%zu", i);
5883
7043
  scr_dyn_arr_push(keys, scr_dyn_objwalk_key(name, (size_t)size));
@@ -5905,6 +7065,13 @@ ScrDyn *scr_dyn_get_own_property_names(const ScrDyn *value) {
5905
7065
  }
5906
7066
 
5907
7067
  ScrDyn *scr_dyn_get_own_property_symbols(const ScrDyn *value) {
7068
+ if (value->kind == SCR_DYN_TYPED_REF) {
7069
+ ScrDyn *view = scr_dyn_typed_ref_materialize(value);
7070
+ if (scr_exc_pending()) { scr_dyn_release(view); return NULL; }
7071
+ ScrDyn *result = scr_dyn_get_own_property_symbols(view);
7072
+ scr_dyn_release(view);
7073
+ return result;
7074
+ }
5908
7075
  if (value->kind == SCR_DYN_NULL || value->kind == SCR_DYN_UNDEF) {
5909
7076
  static const char message[] = "Cannot convert undefined or null to object";
5910
7077
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
@@ -5920,13 +7087,20 @@ ScrDyn *scr_dyn_get_own_property_symbols(const ScrDyn *value) {
5920
7087
  }
5921
7088
 
5922
7089
  ScrDyn *scr_dyn_get_own_property_descriptors(ScrDyn *object) {
7090
+ if (object->kind == SCR_DYN_TYPED_REF) {
7091
+ ScrDyn *view = scr_dyn_typed_ref_materialize(object);
7092
+ if (scr_exc_pending()) { scr_dyn_release(view); return NULL; }
7093
+ ScrDyn *result = scr_dyn_get_own_property_descriptors(view);
7094
+ scr_dyn_release(view);
7095
+ return result;
7096
+ }
5923
7097
  if (scr_dyn_class_reflection_fence(object)) return NULL;
5924
7098
  if (object->kind == SCR_DYN_UNDEF || object->kind == SCR_DYN_NULL) {
5925
7099
  static const char message[] = "Cannot convert undefined or null to object";
5926
7100
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
5927
7101
  return NULL;
5928
7102
  }
5929
- if (object->kind == SCR_DYN_PROXY || object->kind == SCR_DYN_TYPED_REF ||
7103
+ if (object->kind == SCR_DYN_PROXY ||
5930
7104
  object->kind == SCR_DYN_JSVAL || object->kind == SCR_DYN_HANDLE) {
5931
7105
  static const char message[] = "Object.getOwnPropertyDescriptors on this value is not supported yet";
5932
7106
  scr_throw_error_msg(SCR_ERR_ERROR, message, sizeof message - 1);
@@ -5957,6 +7131,21 @@ ScrDyn *scr_dyn_get_own_property_descriptors(ScrDyn *object) {
5957
7131
  return result;
5958
7132
  }
5959
7133
 
7134
+ ScrDyn *scr_dyn_own_keys(const ScrDyn *value) {
7135
+ if (!scr_dyn_to_primitive_result_is_object(value)) {
7136
+ static const char message[] = "Reflect.ownKeys called on non-object";
7137
+ scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
7138
+ return NULL;
7139
+ }
7140
+ ScrDyn *names = scr_dyn_get_own_property_names(value);
7141
+ if (!names) return NULL;
7142
+ ScrDyn *symbols = scr_dyn_get_own_property_symbols(value);
7143
+ if (!symbols) { scr_dyn_release(names); return NULL; }
7144
+ for (size_t i = 0; i < symbols->v.arr.len; i++) scr_dyn_arr_push(names, scr_dyn_retain(symbols->v.arr.items[i]));
7145
+ scr_dyn_release(symbols);
7146
+ return names;
7147
+ }
7148
+
5960
7149
  static void scr_dyn_objwalk_push(ScrDyn *out, ScrObjWalk mode, const char *key,
5961
7150
  size_t key_len, ScrDyn *value /* borrowed */) {
5962
7151
  switch (mode) {
@@ -6106,6 +7295,7 @@ static ScrDyn *scr_dyn_objwalk(const ScrDyn *v, ScrObjWalk mode) {
6106
7295
  if (v->kind == SCR_DYN_ARR || v->kind == SCR_DYN_BYTES) {
6107
7296
  size_t n = v->kind == SCR_DYN_ARR ? v->v.arr.len : v->v.bytes->len;
6108
7297
  for (size_t i = 0; i < n; i++) {
7298
+ if (v->kind == SCR_DYN_ARR && !scr_dyn_arr_has_index(v, i)) continue;
6109
7299
  char key[24];
6110
7300
  int klen = snprintf(key, sizeof key, "%zu", i);
6111
7301
  ScrDyn *val = NULL;
@@ -6171,7 +7361,8 @@ ScrDyn *scr_dyn_obj_keys(const ScrDyn *v) { return scr_dyn_objwalk(v, SCR_OBJWAL
6171
7361
  * Non-enumerable own names shadow names farther up the chain. */
6172
7362
  ScrDyn *scr_dyn_for_in_keys(const ScrDyn *v) {
6173
7363
  if (scr_dyn_class_reflection_fence(v)) return NULL;
6174
- if (v->kind == SCR_DYN_TYPED_REF && scr_dyn_isl_is_array(v)) {
7364
+ if (v->kind == SCR_DYN_TYPED_REF && (scr_dyn_isl_is_array(v) ||
7365
+ !strncmp(v->v.typed_ref.type_key, "record:", 7))) {
6175
7366
  ScrDyn *view = scr_dyn_typed_ref_materialize(v);
6176
7367
  ScrDyn *keys = scr_exc_pending() ? NULL : scr_dyn_for_in_keys(view);
6177
7368
  scr_dyn_release(view);
@@ -6386,6 +7577,33 @@ ScrDyn *scr_dyn_copy_data_properties(ScrDyn *target, const ScrDyn *src) {
6386
7577
  return scr_exc_pending() ? NULL : scr_dyn_retain(target);
6387
7578
  }
6388
7579
 
7580
+ ScrDyn *scr_dyn_object_rest(const ScrDyn *source, const ScrDyn *excluded) {
7581
+ ScrDyn *out = scr_dyn_new_obj();
7582
+ ScrDyn *names = scr_dyn_get_own_property_names(source);
7583
+ if (!names) { scr_dyn_release(out); return NULL; }
7584
+ ScrDyn *symbols = scr_dyn_get_own_property_symbols(source);
7585
+ if (!symbols) { scr_dyn_release(names); scr_dyn_release(out); return NULL; }
7586
+ for (size_t i = 0; i < symbols->v.arr.len; i++) scr_dyn_arr_push(names, scr_dyn_retain(symbols->v.arr.items[i]));
7587
+ scr_dyn_release(symbols);
7588
+ for (size_t i = 0; i < names->v.arr.len && !scr_exc_pending(); i++) {
7589
+ ScrDyn *key = names->v.arr.items[i];
7590
+ bool skip = false;
7591
+ for (size_t j = 0; j < excluded->v.arr.len; j++) {
7592
+ if (scr_dyn_strict_eq(key, excluded->v.arr.items[j])) { skip = true; break; }
7593
+ }
7594
+ if (skip || !scr_dyn_key_probe_computed(source, key, 2)) continue;
7595
+ 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);
7596
+ if (!scr_exc_pending()) {
7597
+ if (key->kind == SCR_DYN_SYMBOL) scr_dyn_symbol_key_set(out, key, value);
7598
+ else scr_dyn_obj_set(out, key->v.str->data, key->v.str->len, scr_dyn_retain(value));
7599
+ }
7600
+ scr_dyn_release(value);
7601
+ }
7602
+ scr_dyn_release(names);
7603
+ if (scr_exc_pending()) { scr_dyn_release(out); return NULL; }
7604
+ return out;
7605
+ }
7606
+
6389
7607
  /* Compiler-owned native class views retain every property and its flags,
6390
7608
  * including nonenumerable data, without invoking accessors. */
6391
7609
  ScrDyn *scr_dyn_copy_property_descriptors(ScrDyn *target, const ScrDyn *src) {
@@ -6401,6 +7619,19 @@ ScrDyn *scr_dyn_copy_property_descriptors(ScrDyn *target, const ScrDyn *src) {
6401
7619
  if (scr_exc_pending()) break;
6402
7620
  }
6403
7621
  scr_dyn_release(keys);
7622
+ if (!scr_exc_pending()) {
7623
+ ScrDyn *symbols = scr_dyn_get_own_property_symbols(src);
7624
+ if (!symbols) return NULL;
7625
+ for (size_t i = 0; i < symbols->v.arr.len; i++) {
7626
+ ScrDyn *key = symbols->v.arr.items[i];
7627
+ ScrDyn *descriptor = scr_dyn_get_own_property_descriptor((ScrDyn *)src, key);
7628
+ ScrDyn *result = descriptor ? scr_dyn_define_property(target, key, descriptor) : NULL;
7629
+ scr_dyn_release(descriptor);
7630
+ scr_dyn_release(result);
7631
+ if (scr_exc_pending()) break;
7632
+ }
7633
+ scr_dyn_release(symbols);
7634
+ }
6404
7635
  return scr_exc_pending() ? NULL : scr_dyn_retain(target);
6405
7636
  }
6406
7637
 
@@ -6429,6 +7660,19 @@ void scr_dyn_pack_push_spread(ScrDyn *pack, const ScrDyn *src, const ScrStr *wha
6429
7660
  * Symbol(Symbol.iterator))". The compiler picks the variant by the
6430
7661
  * spread's syntactic position. MAY THROW (pending). Borrows src. */
6431
7662
  void scr_dyn_pack_push_spread_iter(ScrDyn *pack, const ScrDyn *src) {
7663
+ if (src->kind == SCR_DYN_TYPED_REF) {
7664
+ ScrDyn *view = scr_dyn_typed_ref_materialize(src);
7665
+ if (!scr_exc_pending()) scr_dyn_pack_push_spread_iter(pack, view);
7666
+ scr_dyn_release(view);
7667
+ return;
7668
+ }
7669
+ if (src->kind == SCR_DYN_HANDLE && scr_dyn_handle_ops_of(src)->iter_pack) {
7670
+ ScrDyn *items = scr_dyn_handle_ops_of(src)->iter_pack(src->v.handle.ptr);
7671
+ if (!items) return;
7672
+ scr_dyn_pack_push_spread_iter(pack, items);
7673
+ scr_dyn_release(items);
7674
+ return;
7675
+ }
6432
7676
  if (src->kind == SCR_DYN_ARR || src->kind == SCR_DYN_BYTES ||
6433
7677
  src->kind == SCR_DYN_STR) {
6434
7678
  scr_dyn_arr_push_spread(pack, src, ""); /* iterable kinds never throw */
@@ -6470,6 +7714,10 @@ void scr_dyn_pack_push_spread_iter(ScrDyn *pack, const ScrDyn *src) {
6470
7714
  * ToObject TypeError first (Node throws before looking at sources), then
6471
7715
  * each source's own-member copy left to right, answering the target
6472
7716
  * retained (+1) — identity, like JS. */
7717
+ ScrDyn *scr_dyn_reflect_apply(ScrDyn *target, ScrDyn *receiver, ScrDyn *arguments_list) {
7718
+ return scr_dyn_apply_array_like(target, receiver, arguments_list, "Reflect.apply");
7719
+ }
7720
+
6473
7721
  ScrDyn *scr_dyn_assign_all(ScrDyn *target, const ScrDyn *sources) {
6474
7722
  if (target->kind == SCR_DYN_UNDEF || target->kind == SCR_DYN_NULL) {
6475
7723
  const char *m = "Cannot convert undefined or null to object";
@@ -6573,7 +7821,10 @@ bool scr_dyn_has_own(const ScrDyn *v, const ScrStr *key) {
6573
7821
  if (v->kind == SCR_DYN_ARR) {
6574
7822
  if (key->len == 6 && memcmp(key->data, "length", 6) == 0) return true;
6575
7823
  if (v->v.arr.properties && scr_dyn_obj_get(v->v.arr.properties, key->data, key->len)) return true;
6576
- return scr_dyn_canonical_own_index(key, v->v.arr.len);
7824
+ if (!scr_dyn_canonical_own_index(key, v->v.arr.len)) return false;
7825
+ size_t index = 0;
7826
+ for (size_t i = 0; i < key->len; i++) index = index * 10 + (size_t)(key->data[i] - '0');
7827
+ return scr_dyn_arr_has_index(v, index);
6577
7828
  }
6578
7829
  if (v->kind == SCR_DYN_STR) {
6579
7830
  if (key->len == 6 && memcmp(key->data, "length", 6) == 0) return true;
@@ -6598,6 +7849,12 @@ bool scr_dyn_has_own(const ScrDyn *v, const ScrStr *key) {
6598
7849
 
6599
7850
  bool scr_dyn_property_is_enumerable(const ScrDyn *value, const ScrStr *key) {
6600
7851
  if (scr_dyn_class_reflection_fence(value)) return false;
7852
+ if (value->kind == SCR_DYN_TYPED_REF) {
7853
+ ScrDyn *view = scr_dyn_typed_ref_materialize(value);
7854
+ bool result = !scr_exc_pending() && scr_dyn_property_is_enumerable(view, key);
7855
+ scr_dyn_release(view);
7856
+ return result;
7857
+ }
6601
7858
  if (value->kind == SCR_DYN_UNDEF || value->kind == SCR_DYN_NULL) {
6602
7859
  static const char message[] = "Cannot convert undefined or null to object";
6603
7860
  scr_throw_error_msg(SCR_ERR_TYPE, message, sizeof message - 1);
@@ -6608,7 +7865,7 @@ bool scr_dyn_property_is_enumerable(const ScrDyn *value, const ScrStr *key) {
6608
7865
  if (value->kind == SCR_DYN_STR)
6609
7866
  return scr_dyn_canonical_own_index(key, (size_t)scr_str_utf16_len(value->v.str));
6610
7867
  if (value->kind == SCR_DYN_ARR)
6611
- return scr_dyn_canonical_own_index(key, value->v.arr.len) ||
7868
+ return (scr_dyn_canonical_own_index(key, value->v.arr.len) && scr_dyn_has_own(value, key)) ||
6612
7869
  (value->v.arr.properties && scr_dyn_obj_enumerable(value->v.arr.properties, key->data, key->len));
6613
7870
  if (value->kind == SCR_DYN_BYTES)
6614
7871
  return scr_dyn_canonical_own_index(key, value->v.bytes->len);
@@ -6641,6 +7898,7 @@ void scr_error_init_options(void *obj, int kind, const ScrDyn *message, const Sc
6641
7898
  return;
6642
7899
  }
6643
7900
  scr_error_init(obj, kind, text);
7901
+ ((ScrError *)obj)->message_present = message && message->kind != SCR_DYN_UNDEF;
6644
7902
  scr_str_release(text);
6645
7903
  ScrDyn *view = options && options->kind == SCR_DYN_TYPED_REF
6646
7904
  ? scr_dyn_typed_ref_materialize(options) : NULL;
@@ -6673,7 +7931,15 @@ ScrError *scr_error_new_options(int kind, const ScrDyn *message, const ScrDyn *o
6673
7931
 
6674
7932
  ScrDyn *scr_error_cause(ScrError *e) {
6675
7933
  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);
7934
+ if (scr_errdyn_cache[i].err != e) continue;
7935
+ ScrDyn *value = scr_errdyn_cache[i].dyn;
7936
+ if (value->kind == SCR_DYN_TYPED_REF) {
7937
+ ScrDyn *view = scr_dyn_typed_ref_materialize(value);
7938
+ ScrDyn *cause = scr_dyn_obj_read(view, "cause", 5);
7939
+ scr_dyn_release(view);
7940
+ return cause;
7941
+ }
7942
+ return scr_dyn_obj_read(value, "cause", 5);
6677
7943
  }
6678
7944
  return e->error_cause ? scr_dyn_retain(e->error_cause) : scr_dyn_undefined();
6679
7945
  }
@@ -6693,6 +7959,12 @@ void scr_error_set_cause(ScrError *e, ScrDyn *value) {
6693
7959
  e->error_cause = replacement;
6694
7960
  }
6695
7961
 
7962
+ void scr_error_define_cause(ScrError *e, ScrDyn *value) {
7963
+ scr_error_delete_cause(e);
7964
+ scr_error_set_cause(e, value);
7965
+ }
7966
+
7967
+
6696
7968
  void scr_error_delete_cause(ScrError *e) {
6697
7969
  for (size_t i = 0; i < scr_errdyn_n; i++) {
6698
7970
  if (scr_errdyn_cache[i].err != e) continue;
@@ -7337,7 +8609,7 @@ typedef struct ScrWeakEntry {
7337
8609
  } ScrWeakEntry;
7338
8610
 
7339
8611
  struct ScrWeakMap { size_t rc; ScrWeakEntry *entries; bool is_set; };
7340
- /* Weak observers borrow key identities. Values remain ordinary RC edges;
8612
+ /* Weak observers borrow key identities. Values are traced strong edges;
7341
8613
  * value-to-key cycles require explicit deletion or container disposal. */
7342
8614
  #define SCR_WEAK_BUCKETS 1024
7343
8615
  static SCR_TL ScrWeakEntry *scr_weak_entries[SCR_WEAK_BUCKETS];
@@ -7346,7 +8618,7 @@ static size_t scr_weak_bucket(void *key) {
7346
8618
  return ((bits >> 4) ^ (bits >> 14)) & (SCR_WEAK_BUCKETS - 1);
7347
8619
  }
7348
8620
 
7349
- static void scr_weak_remove(ScrWeakEntry *entry) {
8621
+ static void scr_weak_remove_impl(ScrWeakEntry *entry, bool collected) {
7350
8622
  ScrWeakEntry **slot = &entry->owner->entries;
7351
8623
  while (*slot != entry) slot = &(*slot)->next;
7352
8624
  *slot = entry->next;
@@ -7356,7 +8628,22 @@ static void scr_weak_remove(ScrWeakEntry *entry) {
7356
8628
  ScrDyn *value = entry->value;
7357
8629
  free(entry);
7358
8630
  /* Unlink before release: releasing a value can dispose another key. */
7359
- scr_dyn_release(value);
8631
+ if (!collected) scr_dyn_release(value);
8632
+ }
8633
+
8634
+ static void scr_weak_remove(ScrWeakEntry *entry) {
8635
+ scr_weak_remove_impl(entry, scr_cyc_hdr(entry->owner)->color == SCR_CYC_DOOMED);
8636
+ }
8637
+
8638
+ static void scr_weak_map_trace(void *ptr, ScrTraceVisit visit, void *ctx) {
8639
+ for (ScrWeakEntry *entry = ((ScrWeakMap *)ptr)->entries; entry; entry = entry->next)
8640
+ visit(entry->value, ctx);
8641
+ }
8642
+
8643
+ static void scr_weak_map_gcfree(void *ptr) {
8644
+ ScrWeakMap *map = ptr;
8645
+ while (map->entries) scr_weak_remove_impl(map->entries, true);
8646
+ scr_cyc_free(map);
7360
8647
  }
7361
8648
 
7362
8649
  static void scr_weak_disposed(void *key) {
@@ -7375,10 +8662,11 @@ static void *scr_weak_map_retain(void *ptr) {
7375
8662
 
7376
8663
  static void scr_weak_map_release(void *ptr) {
7377
8664
  ScrWeakMap *map = ptr;
7378
- if (--map->rc) return;
8665
+ if (--map->rc) { scr_cyc_on_release(map); return; }
8666
+ scr_cyc_on_dead(map);
7379
8667
  scr_weak_dispose(map);
7380
8668
  while (map->entries) scr_weak_remove(map->entries);
7381
- free(map);
8669
+ scr_cyc_free(map);
7382
8670
  }
7383
8671
 
7384
8672
  /* Return 1 for an observed identity, 0 for a primitive, and -1 for a
@@ -7399,9 +8687,16 @@ static int scr_weak_key(const ScrDyn *key, void **ptr, unsigned *kind) {
7399
8687
  *kind = key->v.fn.class_obj ? 3 : 2; return 1;
7400
8688
  case SCR_DYN_HANDLE:
7401
8689
  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;
8690
+ key->v.handle.tag != SCR_DYNH_WEAK_SET && key->v.handle.tag != SCR_DYNH_STDIO &&
8691
+ key->v.handle.tag != SCR_DYNH_FETCH_REQUEST && key->v.handle.tag != SCR_DYNH_FETCH_RESPONSE &&
8692
+ key->v.handle.tag != SCR_DYNH_MAP && key->v.handle.tag != SCR_DYNH_SET) return -1;
7403
8693
  *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:
8694
+ case SCR_DYN_TYPED_REF:
8695
+ if (!key->v.typed_ref.observed) return -1;
8696
+ *ptr = key->v.typed_ref.ptr; *kind = 32; return 1;
8697
+ case SCR_DYN_PROMISE:
8698
+ *ptr = key->v.promise; *kind = 33; return 1;
8699
+ case SCR_DYN_JSVAL:
7405
8700
  return -1;
7406
8701
  default: return 0;
7407
8702
  }
@@ -7533,7 +8828,7 @@ static ScrDyn *scr_weak_collection_new(ScrDyn *seed, bool is_set) {
7533
8828
  ScrDynHandleTag tag = is_set ? SCR_DYNH_WEAK_SET : SCR_DYNH_WEAK_MAP;
7534
8829
  scr_weak_dispose_hook = &scr_weak_disposed;
7535
8830
  scr_dyn_handle_install(tag, is_set ? &set_ops : &map_ops);
7536
- ScrWeakMap *map = calloc(1, sizeof *map);
8831
+ ScrWeakMap *map = scr_cyc_alloc(sizeof *map, scr_weak_map_trace, scr_weak_map_gcfree);
7537
8832
  if (!map) scr_json_oom();
7538
8833
  map->rc = 1;
7539
8834
  map->is_set = is_set;
@@ -7720,12 +9015,15 @@ static ScrDyn *scr_native_set_invoke(void *ptr, ScrDyn *self, const char *method
7720
9015
  ScrMap *set = ptr;
7721
9016
  ScrDyn *value = argc ? args[0] : scr_dyn_undefined();
7722
9017
  if (strcmp(method, "add") == 0) {
7723
- scr_map_set_ref_f64(set, value, 1);
9018
+ scr_map_dyn_set(set, value, NULL, true);
9019
+ if (scr_exc_pending()) return NULL;
7724
9020
  return scr_dyn_retain(self);
7725
9021
  }
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));
9022
+ if (strcmp(method, "has") == 0) return scr_dyn_new_bool(scr_map_dyn_has(set, value, false));
9023
+ if (strcmp(method, "delete") == 0) return scr_dyn_new_bool(scr_map_dyn_has(set, value, true));
7728
9024
  if (strcmp(method, "clear") == 0) { scr_map_clear(set); return scr_dyn_retain(scr_dyn_undefined()); }
9025
+ if (strcmp(method, "values") == 0 || strcmp(method, "keys") == 0) return scr_native_collection_iterator(self, 0);
9026
+ if (strcmp(method, "entries") == 0) return scr_native_collection_iterator(self, 2);
7729
9027
  if (strcmp(method, "forEach") == 0) {
7730
9028
  if (value->kind != SCR_DYN_FUNC &&
7731
9029
  !(value->kind == SCR_DYN_JSVAL && scr_dyn_isl_typeof_is(value, "function"))) {
@@ -7748,7 +9046,7 @@ static ScrDyn *scr_native_set_invoke(void *ptr, ScrDyn *self, const char *method
7748
9046
  scr_map_iter_enter(set);
7749
9047
  for (double i = 0; i < scr_map_iter_count(set); i++) {
7750
9048
  if (!scr_map_iter_live(set, i)) continue;
7751
- ScrDyn *entry = scr_map_iter_key_ref(set, i);
9049
+ ScrDyn *entry = scr_map_dyn_key(set, i);
7752
9050
  ScrDyn *callback_args[] = {entry, entry, self};
7753
9051
  scr_dyn_this_push_dyn(this_arg);
7754
9052
  ScrDyn *result = scr_dyn_call(value, callback_args, 3, "callback");
@@ -7766,10 +9064,21 @@ static ScrDyn *scr_native_set_invoke(void *ptr, ScrDyn *self, const char *method
7766
9064
  return NULL;
7767
9065
  }
7768
9066
 
9067
+ static ScrDyn *scr_native_set_pack(void *ptr) {
9068
+ ScrMap *set = ptr;
9069
+ ScrDyn *values = scr_dyn_new_arr();
9070
+ scr_map_iter_enter(set);
9071
+ for (double i = 0; i < scr_map_iter_count(set); i++) {
9072
+ if (scr_map_iter_live(set, i)) scr_dyn_arr_push(values, scr_map_dyn_key(set, i));
9073
+ }
9074
+ scr_map_iter_exit(set);
9075
+ return values;
9076
+ }
9077
+
7769
9078
  ScrDyn *scr_dyn_native_set(ScrMap *value) {
7770
9079
  static const ScrDynHandleOps ops = {
7771
9080
  "Set", &scr_map_retain_v, &scr_map_release_v, &scr_native_set_invoke,
7772
- &scr_native_set_get, &scr_weak_map_write, NULL, NULL,
9081
+ &scr_native_set_get, &scr_weak_map_write, NULL, &scr_native_set_pack,
7773
9082
  };
7774
9083
  scr_dyn_handle_install(SCR_DYNH_SET, &ops);
7775
9084
  return scr_dyn_new_handle(value, SCR_DYNH_SET);
@@ -7818,16 +9127,44 @@ static ScrDyn *scr_native_map_invoke(void *ptr, ScrDyn *self, const char *method
7818
9127
  ScrMap *map = ptr;
7819
9128
  ScrDyn *key = argc ? args[0] : scr_dyn_undefined();
7820
9129
  if (strcmp(method, "set") == 0) {
7821
- scr_map_set_ref_ref(map, key, scr_dyn_retain(argc > 1 ? args[1] : scr_dyn_undefined()));
9130
+ scr_map_dyn_set(map, key, argc > 1 ? args[1] : scr_dyn_undefined(), false);
9131
+ if (scr_exc_pending()) return NULL;
7822
9132
  return scr_dyn_retain(self);
7823
9133
  }
7824
9134
  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());
9135
+ return scr_map_dyn_get(map, key);
7827
9136
  }
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));
9137
+ if (strcmp(method, "has") == 0) return scr_dyn_new_bool(scr_map_dyn_has(map, key, false));
9138
+ if (strcmp(method, "delete") == 0) return scr_dyn_new_bool(scr_map_dyn_has(map, key, true));
7830
9139
  if (strcmp(method, "clear") == 0) { scr_map_clear(map); return scr_dyn_retain(scr_dyn_undefined()); }
9140
+ if (strcmp(method, "values") == 0) return scr_native_collection_iterator(self, 0);
9141
+ if (strcmp(method, "keys") == 0) return scr_native_collection_iterator(self, 1);
9142
+ if (strcmp(method, "entries") == 0) return scr_native_collection_iterator(self, 2);
9143
+ if (strcmp(method, "forEach") == 0) {
9144
+ if (key->kind != SCR_DYN_FUNC && !(key->kind == SCR_DYN_JSVAL && scr_dyn_isl_typeof_is(key, "function"))) {
9145
+ /* Validate even when there are no entries to visit. */
9146
+ ScrDyn *result = scr_dyn_call(key, NULL, 0, "callback");
9147
+ scr_dyn_release(result);
9148
+ return NULL;
9149
+ }
9150
+ ScrDyn *this_arg = argc > 1 ? args[1] : scr_dyn_undefined();
9151
+ scr_map_iter_enter(map);
9152
+ for (double i = 0; i < scr_map_iter_count(map); i++) {
9153
+ if (!scr_map_iter_live(map, i)) continue;
9154
+ ScrDyn *entry_key = scr_map_dyn_key(map, i);
9155
+ ScrDyn *value = scr_map_dyn_value(map, i);
9156
+ ScrDyn *callback_args[] = {value, entry_key, self};
9157
+ scr_dyn_this_push_dyn(this_arg);
9158
+ ScrDyn *result = scr_dyn_call(key, callback_args, 3, "callback");
9159
+ scr_dyn_this_pop();
9160
+ scr_dyn_release(entry_key);
9161
+ scr_dyn_release(value);
9162
+ scr_dyn_release(result);
9163
+ if (scr_exc_pending()) break;
9164
+ }
9165
+ scr_map_iter_exit(map);
9166
+ return scr_exc_pending() ? NULL : scr_dyn_retain(scr_dyn_undefined());
9167
+ }
7831
9168
  (void)what;
7832
9169
  static const char message[] = "Native Map method has no lowering";
7833
9170
  scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
@@ -7841,8 +9178,8 @@ static ScrDyn *scr_native_map_pack(void *ptr) {
7841
9178
  for (double i = 0; i < scr_map_iter_count(map); i++) {
7842
9179
  if (!scr_map_iter_live(map, i)) continue;
7843
9180
  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));
9181
+ scr_dyn_arr_push(pair, scr_map_dyn_key(map, i));
9182
+ scr_dyn_arr_push(pair, scr_map_dyn_value(map, i));
7846
9183
  scr_dyn_arr_push(entries, pair);
7847
9184
  }
7848
9185
  scr_map_iter_exit(map);
@@ -7852,7 +9189,7 @@ static ScrDyn *scr_native_map_pack(void *ptr) {
7852
9189
  ScrDyn *scr_dyn_native_map(ScrMap *value) {
7853
9190
  static const ScrDynHandleOps ops = {
7854
9191
  "Map", &scr_map_retain_v, &scr_map_release_v, &scr_native_map_invoke,
7855
- &scr_native_map_get, &scr_weak_map_write, NULL, NULL,
9192
+ &scr_native_map_get, &scr_weak_map_write, NULL, &scr_native_map_pack,
7856
9193
  };
7857
9194
  scr_dyn_handle_install(SCR_DYNH_MAP, &ops);
7858
9195
  return scr_dyn_new_handle(value, SCR_DYNH_MAP);
@@ -7867,7 +9204,40 @@ ScrMap *scr_dyn_native_map_check(const ScrDyn *value, const ScrDynPath *path) {
7867
9204
  return scr_map_retain(value->v.handle.ptr);
7868
9205
  }
7869
9206
 
9207
+ bool scr_dyn_native_collection_is(const ScrDyn *value, int map, const char *type) {
9208
+ if (!(map ? scr_dyn_native_map_is(value) : scr_dyn_native_set_is(value))) return false;
9209
+ const ScrMap *storage = value->v.handle.ptr;
9210
+ return type ? storage->dyn_ops && strcmp(storage->dyn_ops->type, type) == 0 : !storage->dyn_ops;
9211
+ }
9212
+
9213
+ ScrMap *scr_dyn_native_collection_check(const ScrDyn *value, int map, const char *type, const ScrDynPath *path) {
9214
+ if (!scr_dyn_native_collection_is(value, map, type)) {
9215
+ scr_dyn_check_fail(path, type ? type : map ? "Map" : "Set", value);
9216
+ return NULL;
9217
+ }
9218
+ return scr_map_retain(value->v.handle.ptr);
9219
+ }
9220
+
7870
9221
  ScrStr *scr_dyn_to_string_method(const ScrDyn *d, const ScrStr *enc, const ScrStr *what) {
9222
+ /* Object.create receivers must run their inherited formatter before the
9223
+ * default object tag; Effect shard keys use it to produce distinct hashes. */
9224
+ const bool object_method = d->kind == SCR_DYN_OBJ && scr_dyn_property_owner(d, "toString", 8);
9225
+ if (d->kind == SCR_DYN_FUNC || object_method) {
9226
+ ScrDyn *member = object_method ? scr_dyn_obj_read(d, "toString", 8) : scr_dyn_fn_get(d, "toString", 8);
9227
+ if (scr_exc_pending()) { scr_dyn_release(member); return NULL; }
9228
+ if (member && (object_method || member->kind != SCR_DYN_UNDEF)) {
9229
+ scr_dyn_this_push_dyn(d);
9230
+ ScrDyn *value = scr_dyn_call(member, NULL, 0, what->data);
9231
+ scr_dyn_this_pop();
9232
+ scr_dyn_release(member);
9233
+ if (!value) return NULL;
9234
+ ScrStr *result = value->kind == SCR_DYN_STR ? scr_str_retain(value->v.str) : NULL;
9235
+ if (!result) scr_dyn_check_fail(NULL, "string", value);
9236
+ scr_dyn_release(value);
9237
+ return result;
9238
+ }
9239
+ scr_dyn_release(member);
9240
+ }
7871
9241
  if (d->kind == SCR_DYN_OBJ && !scr_dyn_property_owner(d, "toString", 8) && !scr_dyn_has_object_prototype(d)) {
7872
9242
  ScrJsonBuf b;
7873
9243
  scr_jb_init(&b);
@@ -7926,3 +9296,88 @@ bool scr_dyn_is_frozen(const ScrDyn *value) {
7926
9296
  scr_throw_error_msg_code(SCR_ERR_ERROR, message, sizeof message - 1, "SC2020");
7927
9297
  return false;
7928
9298
  }
9299
+
9300
+ double scr_buffer_byte_length_dyn(ScrDyn *value, ScrStr *encoding) {
9301
+ if (value->kind == SCR_DYN_STR) return scr_bytes_byte_length_str(value->v.str, encoding);
9302
+ if (value->kind == SCR_DYN_BYTES) return scr_bytes_byte_len(value->v.bytes);
9303
+ if (scr_array_buffer_is(value)) return scr_bytes_byte_len(value->v.handle.ptr);
9304
+ static const char message[] = "The string argument must be of type string or an instance of Buffer or ArrayBuffer";
9305
+ scr_throw_error_msg_code(SCR_ERR_TYPE, message, sizeof message - 1, "ERR_INVALID_ARG_TYPE");
9306
+ return 0;
9307
+ }
9308
+
9309
+ /* Radix digit generation follows V8's DoubleToRadixStringView algorithm.
9310
+ * Copyright 2012 the V8 project authors. BSD license in
9311
+ * ../vendor/v8-number-radix/LICENSE. The decimal path retains Ryū. */
9312
+ ScrStr *scr_num_to_string_radix(double value, const ScrDyn *argument) {
9313
+ double requested = 10;
9314
+ if (argument && argument->kind != SCR_DYN_UNDEF &&
9315
+ !scr_dyn_number_coerce_js(argument, &requested)) return NULL;
9316
+ requested = isnan(requested) ? 0 : trunc(requested);
9317
+ if (requested < 2 || requested > 36 || !isfinite(requested)) {
9318
+ static const char message[] = "toString() radix argument must be between 2 and 36";
9319
+ scr_throw_error_msg(SCR_ERR_RANGE, message, sizeof message - 1);
9320
+ return NULL;
9321
+ }
9322
+ int radix = (int)requested;
9323
+ if (radix == 10 || !isfinite(value) || value == 0) return scr_f64_to_scrstr(value);
9324
+ static const char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
9325
+ char buffer[2200];
9326
+ const size_t middle = sizeof buffer / 2;
9327
+ size_t begin = middle, end = middle;
9328
+ bool negative = value < 0;
9329
+ value = fabs(value);
9330
+ double integer = floor(value), fraction = value - integer;
9331
+ double tolerance = 0.5 * (nextafter(value, INFINITY) - value);
9332
+ if (tolerance <= 0) tolerance = nextafter(0, INFINITY);
9333
+ if (fraction >= tolerance) {
9334
+ buffer[end++] = '.';
9335
+ do {
9336
+ fraction *= radix;
9337
+ tolerance *= radix;
9338
+ int digit = (int)fraction;
9339
+ buffer[end++] = digits[digit];
9340
+ fraction -= digit;
9341
+ if ((fraction > 0.5 || (fraction == 0.5 && (digit & 1))) && fraction + tolerance > 1) {
9342
+ for (;;) {
9343
+ end--;
9344
+ if (end == middle) { integer += 1; break; }
9345
+ char last = buffer[end];
9346
+ digit = last > '9' ? last - 'a' + 10 : last - '0';
9347
+ if (digit + 1 < radix) { buffer[end++] = digits[digit + 1]; break; }
9348
+ }
9349
+ break;
9350
+ }
9351
+ } while (fraction >= tolerance);
9352
+ }
9353
+ /* V8's Double::Exponent is the unbiased exponent minus 52. Beyond
9354
+ * that precision boundary, trailing digits are unrepresented zeros. */
9355
+ while (integer / radix >= 0x1p53) {
9356
+ integer /= radix;
9357
+ buffer[--begin] = '0';
9358
+ }
9359
+ do {
9360
+ double remainder = fmod(integer, radix);
9361
+ buffer[--begin] = digits[(int)remainder];
9362
+ integer = (integer - remainder) / radix;
9363
+ } while (integer > 0);
9364
+ if (negative) buffer[--begin] = '-';
9365
+ return scr_str_new(buffer + begin, end - begin);
9366
+ }
9367
+
9368
+ ScrDyn *scr_caught_to_dyn(const ScrCaught *c) {
9369
+ switch (c->kind) {
9370
+ case SCR_EXC_F64: return scr_dyn_new_num(c->f64);
9371
+ case SCR_EXC_BOOL: return scr_dyn_new_bool(c->b);
9372
+ case SCR_EXC_STR: return scr_dyn_new_str((ScrStr *)c->payload);
9373
+ case SCR_EXC_REF:
9374
+ case SCR_EXC_PRIMITIVE_REF:
9375
+ if (c->retain_fn == scr_dyn_retain_v) return scr_dyn_retain((ScrDyn *)c->payload);
9376
+ return scr_dyn_new_obj();
9377
+ case SCR_EXC_OBJ:
9378
+ if (scr_error_is(c->payload)) return scr_dyn_from_error((const ScrError *)c->payload);
9379
+ return scr_dyn_new_obj();
9380
+ default:
9381
+ return scr_dyn_new_obj();
9382
+ }
9383
+ }