@scriptc/runtime 0.0.0 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (416) hide show
  1. package/LICENSE +202 -0
  2. package/package.json +16 -6
  3. package/src/scr_array.c +488 -0
  4. package/src/scr_assert.c +1393 -0
  5. package/src/scr_async.c +2593 -0
  6. package/src/scr_async_dyn.c +607 -0
  7. package/src/scr_bytes.c +1425 -0
  8. package/src/scr_bytes_io.c +161 -0
  9. package/src/scr_child.c +3587 -0
  10. package/src/scr_closure.c +214 -0
  11. package/src/scr_console.c +143 -0
  12. package/src/scr_cycle.c +218 -0
  13. package/src/scr_dc.c +805 -0
  14. package/src/scr_dgram.c +1007 -0
  15. package/src/scr_dyn_handle.c +154 -0
  16. package/src/scr_dyn_invoke.c +644 -0
  17. package/src/scr_error.c +332 -0
  18. package/src/scr_events.c +714 -0
  19. package/src/scr_events_emitter.c +699 -0
  20. package/src/scr_exception.c +242 -0
  21. package/src/scr_fetch.c +1130 -0
  22. package/src/scr_fetch_curl.c +654 -0
  23. package/src/scr_http.c +3482 -0
  24. package/src/scr_http2.c +3030 -0
  25. package/src/scr_inspect.c +803 -0
  26. package/src/scr_inspect_island.c +51 -0
  27. package/src/scr_island.c +9363 -0
  28. package/src/scr_json.c +2151 -0
  29. package/src/scr_lib.c +3612 -0
  30. package/src/scr_loop_epoll.c +241 -0
  31. package/src/scr_loop_kqueue.c +121 -0
  32. package/src/scr_loop_wsapoll.c +208 -0
  33. package/src/scr_map.c +591 -0
  34. package/src/scr_net.c +3017 -0
  35. package/src/scr_net_island.c +458 -0
  36. package/src/scr_number.c +115 -0
  37. package/src/scr_object.c +25 -0
  38. package/src/scr_path.c +1266 -0
  39. package/src/scr_platform.h +119 -0
  40. package/src/scr_readline.c +287 -0
  41. package/src/scr_regex.c +1080 -0
  42. package/src/scr_runtime.h +5036 -0
  43. package/src/scr_stream.c +2877 -0
  44. package/src/scr_string.c +1176 -0
  45. package/src/scr_symbol.c +132 -0
  46. package/src/scr_test.c +662 -0
  47. package/src/scr_tls.c +1520 -0
  48. package/src/scr_union.c +105 -0
  49. package/src/scr_url.c +911 -0
  50. package/src/scr_url_internal.h +29 -0
  51. package/src/scr_url_params.c +561 -0
  52. package/src/scr_watch.c +568 -0
  53. package/src/scr_web.c +1778 -0
  54. package/src/scr_win.c +76 -0
  55. package/src/scr_zlib.c +197 -0
  56. package/src/scr_zlib_island.c +15 -0
  57. package/vendor/README.md +52 -0
  58. package/vendor/curl/COPYRIGHT +534 -0
  59. package/vendor/curl/include/curl/curl.h +3214 -0
  60. package/vendor/curl/include/curl/curlver.h +79 -0
  61. package/vendor/curl/include/curl/easy.h +125 -0
  62. package/vendor/curl/include/curl/header.h +74 -0
  63. package/vendor/curl/include/curl/mprintf.h +52 -0
  64. package/vendor/curl/include/curl/multi.h +460 -0
  65. package/vendor/curl/include/curl/options.h +70 -0
  66. package/vendor/curl/include/curl/stdcheaders.h +35 -0
  67. package/vendor/curl/include/curl/system.h +508 -0
  68. package/vendor/curl/include/curl/typecheck-gcc.h +716 -0
  69. package/vendor/curl/include/curl/urlapi.h +149 -0
  70. package/vendor/curl/include/curl/websockets.h +84 -0
  71. package/vendor/mbedtls/LICENSE +553 -0
  72. package/vendor/mbedtls/include/CMakeLists.txt +22 -0
  73. package/vendor/mbedtls/include/mbedtls/aes.h +631 -0
  74. package/vendor/mbedtls/include/mbedtls/aria.h +343 -0
  75. package/vendor/mbedtls/include/mbedtls/asn1.h +642 -0
  76. package/vendor/mbedtls/include/mbedtls/asn1write.h +390 -0
  77. package/vendor/mbedtls/include/mbedtls/base64.h +82 -0
  78. package/vendor/mbedtls/include/mbedtls/bignum.h +1088 -0
  79. package/vendor/mbedtls/include/mbedtls/block_cipher.h +76 -0
  80. package/vendor/mbedtls/include/mbedtls/build_info.h +194 -0
  81. package/vendor/mbedtls/include/mbedtls/camellia.h +305 -0
  82. package/vendor/mbedtls/include/mbedtls/ccm.h +526 -0
  83. package/vendor/mbedtls/include/mbedtls/chacha20.h +209 -0
  84. package/vendor/mbedtls/include/mbedtls/chachapoly.h +351 -0
  85. package/vendor/mbedtls/include/mbedtls/check_config.h +1149 -0
  86. package/vendor/mbedtls/include/mbedtls/cipher.h +1250 -0
  87. package/vendor/mbedtls/include/mbedtls/cmac.h +246 -0
  88. package/vendor/mbedtls/include/mbedtls/compat-2.x.h +46 -0
  89. package/vendor/mbedtls/include/mbedtls/config_adjust_legacy_crypto.h +578 -0
  90. package/vendor/mbedtls/include/mbedtls/config_adjust_legacy_from_psa.h +873 -0
  91. package/vendor/mbedtls/include/mbedtls/config_adjust_psa_from_legacy.h +359 -0
  92. package/vendor/mbedtls/include/mbedtls/config_adjust_psa_superset_legacy.h +145 -0
  93. package/vendor/mbedtls/include/mbedtls/config_adjust_ssl.h +91 -0
  94. package/vendor/mbedtls/include/mbedtls/config_adjust_x509.h +35 -0
  95. package/vendor/mbedtls/include/mbedtls/config_psa.h +61 -0
  96. package/vendor/mbedtls/include/mbedtls/constant_time.h +36 -0
  97. package/vendor/mbedtls/include/mbedtls/ctr_drbg.h +596 -0
  98. package/vendor/mbedtls/include/mbedtls/debug.h +156 -0
  99. package/vendor/mbedtls/include/mbedtls/des.h +385 -0
  100. package/vendor/mbedtls/include/mbedtls/dhm.h +972 -0
  101. package/vendor/mbedtls/include/mbedtls/ecdh.h +455 -0
  102. package/vendor/mbedtls/include/mbedtls/ecdsa.h +674 -0
  103. package/vendor/mbedtls/include/mbedtls/ecjpake.h +298 -0
  104. package/vendor/mbedtls/include/mbedtls/ecp.h +1517 -0
  105. package/vendor/mbedtls/include/mbedtls/entropy.h +274 -0
  106. package/vendor/mbedtls/include/mbedtls/error.h +201 -0
  107. package/vendor/mbedtls/include/mbedtls/gcm.h +387 -0
  108. package/vendor/mbedtls/include/mbedtls/hkdf.h +124 -0
  109. package/vendor/mbedtls/include/mbedtls/hmac_drbg.h +434 -0
  110. package/vendor/mbedtls/include/mbedtls/lms.h +440 -0
  111. package/vendor/mbedtls/include/mbedtls/mbedtls_config.h +4446 -0
  112. package/vendor/mbedtls/include/mbedtls/md.h +526 -0
  113. package/vendor/mbedtls/include/mbedtls/md5.h +190 -0
  114. package/vendor/mbedtls/include/mbedtls/memory_buffer_alloc.h +142 -0
  115. package/vendor/mbedtls/include/mbedtls/net_sockets.h +299 -0
  116. package/vendor/mbedtls/include/mbedtls/nist_kw.h +166 -0
  117. package/vendor/mbedtls/include/mbedtls/oid.h +727 -0
  118. package/vendor/mbedtls/include/mbedtls/pem.h +160 -0
  119. package/vendor/mbedtls/include/mbedtls/pk.h +1303 -0
  120. package/vendor/mbedtls/include/mbedtls/pkcs12.h +186 -0
  121. package/vendor/mbedtls/include/mbedtls/pkcs5.h +198 -0
  122. package/vendor/mbedtls/include/mbedtls/pkcs7.h +252 -0
  123. package/vendor/mbedtls/include/mbedtls/platform.h +516 -0
  124. package/vendor/mbedtls/include/mbedtls/platform_time.h +79 -0
  125. package/vendor/mbedtls/include/mbedtls/platform_util.h +247 -0
  126. package/vendor/mbedtls/include/mbedtls/poly1305.h +168 -0
  127. package/vendor/mbedtls/include/mbedtls/private_access.h +20 -0
  128. package/vendor/mbedtls/include/mbedtls/psa_util.h +207 -0
  129. package/vendor/mbedtls/include/mbedtls/ripemd160.h +136 -0
  130. package/vendor/mbedtls/include/mbedtls/rsa.h +1170 -0
  131. package/vendor/mbedtls/include/mbedtls/sha1.h +219 -0
  132. package/vendor/mbedtls/include/mbedtls/sha256.h +200 -0
  133. package/vendor/mbedtls/include/mbedtls/sha3.h +172 -0
  134. package/vendor/mbedtls/include/mbedtls/sha512.h +208 -0
  135. package/vendor/mbedtls/include/mbedtls/ssl.h +5887 -0
  136. package/vendor/mbedtls/include/mbedtls/ssl_cache.h +187 -0
  137. package/vendor/mbedtls/include/mbedtls/ssl_ciphersuites.h +482 -0
  138. package/vendor/mbedtls/include/mbedtls/ssl_cookie.h +106 -0
  139. package/vendor/mbedtls/include/mbedtls/ssl_ticket.h +199 -0
  140. package/vendor/mbedtls/include/mbedtls/threading.h +167 -0
  141. package/vendor/mbedtls/include/mbedtls/timing.h +94 -0
  142. package/vendor/mbedtls/include/mbedtls/version.h +78 -0
  143. package/vendor/mbedtls/include/mbedtls/x509.h +500 -0
  144. package/vendor/mbedtls/include/mbedtls/x509_crl.h +184 -0
  145. package/vendor/mbedtls/include/mbedtls/x509_crt.h +1208 -0
  146. package/vendor/mbedtls/include/mbedtls/x509_csr.h +382 -0
  147. package/vendor/mbedtls/include/psa/build_info.h +20 -0
  148. package/vendor/mbedtls/include/psa/crypto.h +4998 -0
  149. package/vendor/mbedtls/include/psa/crypto_adjust_auto_enabled.h +31 -0
  150. package/vendor/mbedtls/include/psa/crypto_adjust_config_dependencies.h +51 -0
  151. package/vendor/mbedtls/include/psa/crypto_adjust_config_key_pair_types.h +101 -0
  152. package/vendor/mbedtls/include/psa/crypto_adjust_config_synonyms.h +49 -0
  153. package/vendor/mbedtls/include/psa/crypto_builtin_composites.h +214 -0
  154. package/vendor/mbedtls/include/psa/crypto_builtin_key_derivation.h +118 -0
  155. package/vendor/mbedtls/include/psa/crypto_builtin_primitives.h +114 -0
  156. package/vendor/mbedtls/include/psa/crypto_compat.h +230 -0
  157. package/vendor/mbedtls/include/psa/crypto_config.h +145 -0
  158. package/vendor/mbedtls/include/psa/crypto_driver_common.h +44 -0
  159. package/vendor/mbedtls/include/psa/crypto_driver_contexts_composites.h +151 -0
  160. package/vendor/mbedtls/include/psa/crypto_driver_contexts_key_derivation.h +52 -0
  161. package/vendor/mbedtls/include/psa/crypto_driver_contexts_primitives.h +105 -0
  162. package/vendor/mbedtls/include/psa/crypto_extra.h +2145 -0
  163. package/vendor/mbedtls/include/psa/crypto_legacy.h +88 -0
  164. package/vendor/mbedtls/include/psa/crypto_platform.h +102 -0
  165. package/vendor/mbedtls/include/psa/crypto_se_driver.h +1383 -0
  166. package/vendor/mbedtls/include/psa/crypto_sizes.h +1319 -0
  167. package/vendor/mbedtls/include/psa/crypto_struct.h +527 -0
  168. package/vendor/mbedtls/include/psa/crypto_types.h +508 -0
  169. package/vendor/mbedtls/include/psa/crypto_values.h +2782 -0
  170. package/vendor/mbedtls/library/aes.c +2294 -0
  171. package/vendor/mbedtls/library/aesce.c +624 -0
  172. package/vendor/mbedtls/library/aesce.h +136 -0
  173. package/vendor/mbedtls/library/aesni.c +846 -0
  174. package/vendor/mbedtls/library/aesni.h +162 -0
  175. package/vendor/mbedtls/library/alignment.h +704 -0
  176. package/vendor/mbedtls/library/aria.c +969 -0
  177. package/vendor/mbedtls/library/asn1parse.c +468 -0
  178. package/vendor/mbedtls/library/asn1write.c +440 -0
  179. package/vendor/mbedtls/library/base64.c +322 -0
  180. package/vendor/mbedtls/library/base64_internal.h +45 -0
  181. package/vendor/mbedtls/library/bignum.c +2583 -0
  182. package/vendor/mbedtls/library/bignum_core.c +1240 -0
  183. package/vendor/mbedtls/library/bignum_core.h +872 -0
  184. package/vendor/mbedtls/library/bignum_core_invasive.h +38 -0
  185. package/vendor/mbedtls/library/bignum_internal.h +122 -0
  186. package/vendor/mbedtls/library/bignum_mod.c +394 -0
  187. package/vendor/mbedtls/library/bignum_mod.h +452 -0
  188. package/vendor/mbedtls/library/bignum_mod_raw.c +276 -0
  189. package/vendor/mbedtls/library/bignum_mod_raw.h +416 -0
  190. package/vendor/mbedtls/library/bignum_mod_raw_invasive.h +34 -0
  191. package/vendor/mbedtls/library/block_cipher.c +207 -0
  192. package/vendor/mbedtls/library/block_cipher_internal.h +99 -0
  193. package/vendor/mbedtls/library/bn_mul.h +1094 -0
  194. package/vendor/mbedtls/library/camellia.c +1058 -0
  195. package/vendor/mbedtls/library/ccm.c +777 -0
  196. package/vendor/mbedtls/library/chacha20.c +563 -0
  197. package/vendor/mbedtls/library/chacha20_internal.h +23 -0
  198. package/vendor/mbedtls/library/chachapoly.c +487 -0
  199. package/vendor/mbedtls/library/check_crypto_config.h +136 -0
  200. package/vendor/mbedtls/library/cipher.c +1712 -0
  201. package/vendor/mbedtls/library/cipher_invasive.h +28 -0
  202. package/vendor/mbedtls/library/cipher_wrap.c +2482 -0
  203. package/vendor/mbedtls/library/cipher_wrap.h +178 -0
  204. package/vendor/mbedtls/library/cmac.c +1067 -0
  205. package/vendor/mbedtls/library/common.h +487 -0
  206. package/vendor/mbedtls/library/constant_time.c +247 -0
  207. package/vendor/mbedtls/library/constant_time_impl.h +541 -0
  208. package/vendor/mbedtls/library/constant_time_internal.h +579 -0
  209. package/vendor/mbedtls/library/ctr.h +35 -0
  210. package/vendor/mbedtls/library/ctr_drbg.c +1016 -0
  211. package/vendor/mbedtls/library/debug.c +475 -0
  212. package/vendor/mbedtls/library/debug_internal.h +185 -0
  213. package/vendor/mbedtls/library/des.c +1042 -0
  214. package/vendor/mbedtls/library/dhm.c +700 -0
  215. package/vendor/mbedtls/library/ecdh.c +696 -0
  216. package/vendor/mbedtls/library/ecdsa.c +858 -0
  217. package/vendor/mbedtls/library/ecjpake.c +1216 -0
  218. package/vendor/mbedtls/library/ecp.c +3674 -0
  219. package/vendor/mbedtls/library/ecp_curves.c +6125 -0
  220. package/vendor/mbedtls/library/ecp_curves_new.c +9 -0
  221. package/vendor/mbedtls/library/ecp_internal_alt.h +287 -0
  222. package/vendor/mbedtls/library/ecp_invasive.h +305 -0
  223. package/vendor/mbedtls/library/entropy.c +680 -0
  224. package/vendor/mbedtls/library/entropy_poll.c +233 -0
  225. package/vendor/mbedtls/library/entropy_poll.h +64 -0
  226. package/vendor/mbedtls/library/error.c +878 -0
  227. package/vendor/mbedtls/library/gcm.c +1330 -0
  228. package/vendor/mbedtls/library/hkdf.c +161 -0
  229. package/vendor/mbedtls/library/hmac_drbg.c +633 -0
  230. package/vendor/mbedtls/library/lmots.c +789 -0
  231. package/vendor/mbedtls/library/lmots.h +288 -0
  232. package/vendor/mbedtls/library/lms.c +778 -0
  233. package/vendor/mbedtls/library/md.c +1108 -0
  234. package/vendor/mbedtls/library/md5.c +426 -0
  235. package/vendor/mbedtls/library/md_psa.h +26 -0
  236. package/vendor/mbedtls/library/md_wrap.h +46 -0
  237. package/vendor/mbedtls/library/memory_buffer_alloc.c +751 -0
  238. package/vendor/mbedtls/library/mps_common.h +181 -0
  239. package/vendor/mbedtls/library/mps_error.h +89 -0
  240. package/vendor/mbedtls/library/mps_reader.c +538 -0
  241. package/vendor/mbedtls/library/mps_reader.h +366 -0
  242. package/vendor/mbedtls/library/mps_trace.c +112 -0
  243. package/vendor/mbedtls/library/mps_trace.h +154 -0
  244. package/vendor/mbedtls/library/net_sockets.c +694 -0
  245. package/vendor/mbedtls/library/nist_kw.c +729 -0
  246. package/vendor/mbedtls/library/oid.c +1166 -0
  247. package/vendor/mbedtls/library/padlock.c +157 -0
  248. package/vendor/mbedtls/library/padlock.h +111 -0
  249. package/vendor/mbedtls/library/pem.c +554 -0
  250. package/vendor/mbedtls/library/pk.c +1602 -0
  251. package/vendor/mbedtls/library/pk_ecc.c +261 -0
  252. package/vendor/mbedtls/library/pk_internal.h +241 -0
  253. package/vendor/mbedtls/library/pk_wrap.c +1618 -0
  254. package/vendor/mbedtls/library/pk_wrap.h +138 -0
  255. package/vendor/mbedtls/library/pkcs12.c +437 -0
  256. package/vendor/mbedtls/library/pkcs5.c +500 -0
  257. package/vendor/mbedtls/library/pkcs7.c +787 -0
  258. package/vendor/mbedtls/library/pkparse.c +1392 -0
  259. package/vendor/mbedtls/library/pkwrite.c +631 -0
  260. package/vendor/mbedtls/library/pkwrite.h +121 -0
  261. package/vendor/mbedtls/library/platform.c +402 -0
  262. package/vendor/mbedtls/library/platform_util.c +258 -0
  263. package/vendor/mbedtls/library/poly1305.c +492 -0
  264. package/vendor/mbedtls/library/psa_crypto.c +9532 -0
  265. package/vendor/mbedtls/library/psa_crypto_aead.c +646 -0
  266. package/vendor/mbedtls/library/psa_crypto_aead.h +499 -0
  267. package/vendor/mbedtls/library/psa_crypto_cipher.c +747 -0
  268. package/vendor/mbedtls/library/psa_crypto_cipher.h +316 -0
  269. package/vendor/mbedtls/library/psa_crypto_client.c +22 -0
  270. package/vendor/mbedtls/library/psa_crypto_core.h +983 -0
  271. package/vendor/mbedtls/library/psa_crypto_core_common.h +52 -0
  272. package/vendor/mbedtls/library/psa_crypto_driver_wrappers.h +2896 -0
  273. package/vendor/mbedtls/library/psa_crypto_driver_wrappers_no_static.c +256 -0
  274. package/vendor/mbedtls/library/psa_crypto_driver_wrappers_no_static.h +31 -0
  275. package/vendor/mbedtls/library/psa_crypto_ecp.c +594 -0
  276. package/vendor/mbedtls/library/psa_crypto_ecp.h +267 -0
  277. package/vendor/mbedtls/library/psa_crypto_ffdh.c +361 -0
  278. package/vendor/mbedtls/library/psa_crypto_ffdh.h +131 -0
  279. package/vendor/mbedtls/library/psa_crypto_hash.c +470 -0
  280. package/vendor/mbedtls/library/psa_crypto_hash.h +211 -0
  281. package/vendor/mbedtls/library/psa_crypto_invasive.h +92 -0
  282. package/vendor/mbedtls/library/psa_crypto_its.h +131 -0
  283. package/vendor/mbedtls/library/psa_crypto_mac.c +505 -0
  284. package/vendor/mbedtls/library/psa_crypto_mac.h +264 -0
  285. package/vendor/mbedtls/library/psa_crypto_pake.c +571 -0
  286. package/vendor/mbedtls/library/psa_crypto_pake.h +159 -0
  287. package/vendor/mbedtls/library/psa_crypto_random.c +181 -0
  288. package/vendor/mbedtls/library/psa_crypto_random.h +72 -0
  289. package/vendor/mbedtls/library/psa_crypto_random_impl.h +200 -0
  290. package/vendor/mbedtls/library/psa_crypto_rsa.c +714 -0
  291. package/vendor/mbedtls/library/psa_crypto_rsa.h +321 -0
  292. package/vendor/mbedtls/library/psa_crypto_se.c +373 -0
  293. package/vendor/mbedtls/library/psa_crypto_se.h +192 -0
  294. package/vendor/mbedtls/library/psa_crypto_slot_management.c +1137 -0
  295. package/vendor/mbedtls/library/psa_crypto_slot_management.h +344 -0
  296. package/vendor/mbedtls/library/psa_crypto_storage.c +481 -0
  297. package/vendor/mbedtls/library/psa_crypto_storage.h +392 -0
  298. package/vendor/mbedtls/library/psa_its_file.c +254 -0
  299. package/vendor/mbedtls/library/psa_util.c +614 -0
  300. package/vendor/mbedtls/library/psa_util_internal.h +100 -0
  301. package/vendor/mbedtls/library/ripemd160.c +490 -0
  302. package/vendor/mbedtls/library/rsa.c +3121 -0
  303. package/vendor/mbedtls/library/rsa_alt_helpers.c +455 -0
  304. package/vendor/mbedtls/library/rsa_alt_helpers.h +209 -0
  305. package/vendor/mbedtls/library/rsa_internal.h +188 -0
  306. package/vendor/mbedtls/library/sha1.c +480 -0
  307. package/vendor/mbedtls/library/sha256.c +983 -0
  308. package/vendor/mbedtls/library/sha3.c +721 -0
  309. package/vendor/mbedtls/library/sha512.c +1115 -0
  310. package/vendor/mbedtls/library/ssl_cache.c +410 -0
  311. package/vendor/mbedtls/library/ssl_ciphersuites.c +2050 -0
  312. package/vendor/mbedtls/library/ssl_ciphersuites_internal.h +154 -0
  313. package/vendor/mbedtls/library/ssl_client.c +1023 -0
  314. package/vendor/mbedtls/library/ssl_client.h +22 -0
  315. package/vendor/mbedtls/library/ssl_cookie.c +384 -0
  316. package/vendor/mbedtls/library/ssl_debug_helpers.h +85 -0
  317. package/vendor/mbedtls/library/ssl_debug_helpers_generated.c +251 -0
  318. package/vendor/mbedtls/library/ssl_misc.h +3198 -0
  319. package/vendor/mbedtls/library/ssl_msg.c +6619 -0
  320. package/vendor/mbedtls/library/ssl_ticket.c +556 -0
  321. package/vendor/mbedtls/library/ssl_tls.c +10234 -0
  322. package/vendor/mbedtls/library/ssl_tls12_client.c +3688 -0
  323. package/vendor/mbedtls/library/ssl_tls12_server.c +4311 -0
  324. package/vendor/mbedtls/library/ssl_tls13_client.c +3208 -0
  325. package/vendor/mbedtls/library/ssl_tls13_generic.c +1793 -0
  326. package/vendor/mbedtls/library/ssl_tls13_invasive.h +23 -0
  327. package/vendor/mbedtls/library/ssl_tls13_keys.c +1918 -0
  328. package/vendor/mbedtls/library/ssl_tls13_keys.h +668 -0
  329. package/vendor/mbedtls/library/ssl_tls13_server.c +3624 -0
  330. package/vendor/mbedtls/library/threading.c +193 -0
  331. package/vendor/mbedtls/library/threading_internal.h +28 -0
  332. package/vendor/mbedtls/library/timing.c +152 -0
  333. package/vendor/mbedtls/library/version.c +32 -0
  334. package/vendor/mbedtls/library/version_features.c +856 -0
  335. package/vendor/mbedtls/library/x509.c +1776 -0
  336. package/vendor/mbedtls/library/x509_create.c +570 -0
  337. package/vendor/mbedtls/library/x509_crl.c +708 -0
  338. package/vendor/mbedtls/library/x509_crt.c +3311 -0
  339. package/vendor/mbedtls/library/x509_csr.c +648 -0
  340. package/vendor/mbedtls/library/x509_internal.h +101 -0
  341. package/vendor/mbedtls/library/x509write.c +174 -0
  342. package/vendor/mbedtls/library/x509write_crt.c +688 -0
  343. package/vendor/mbedtls/library/x509write_csr.c +336 -0
  344. package/vendor/quickjs-ng/CMakeLists.txt +566 -0
  345. package/vendor/quickjs-ng/LICENSE +24 -0
  346. package/vendor/quickjs-ng/README.md +24 -0
  347. package/vendor/quickjs-ng/api-test.c +1195 -0
  348. package/vendor/quickjs-ng/builtin-array-fromasync.h +119 -0
  349. package/vendor/quickjs-ng/builtin-iterator-zip-keyed.h +332 -0
  350. package/vendor/quickjs-ng/builtin-iterator-zip.h +337 -0
  351. package/vendor/quickjs-ng/cutils.h +1998 -0
  352. package/vendor/quickjs-ng/dtoa.c +1619 -0
  353. package/vendor/quickjs-ng/dtoa.h +87 -0
  354. package/vendor/quickjs-ng/gen/function_source.c +81 -0
  355. package/vendor/quickjs-ng/gen/hello.c +53 -0
  356. package/vendor/quickjs-ng/gen/hello_module.c +106 -0
  357. package/vendor/quickjs-ng/gen/repl.c +3036 -0
  358. package/vendor/quickjs-ng/gen/standalone.c +323 -0
  359. package/vendor/quickjs-ng/gen/test_fib.c +81 -0
  360. package/vendor/quickjs-ng/libregexp-opcode.h +73 -0
  361. package/vendor/quickjs-ng/libregexp.c +3474 -0
  362. package/vendor/quickjs-ng/libregexp.h +101 -0
  363. package/vendor/quickjs-ng/libunicode-table.h +5173 -0
  364. package/vendor/quickjs-ng/libunicode.c +2069 -0
  365. package/vendor/quickjs-ng/libunicode.h +172 -0
  366. package/vendor/quickjs-ng/list.h +107 -0
  367. package/vendor/quickjs-ng/lre-test.c +52 -0
  368. package/vendor/quickjs-ng/qjs.c +762 -0
  369. package/vendor/quickjs-ng/qjsc.c +673 -0
  370. package/vendor/quickjs-ng/quickjs-atom.h +280 -0
  371. package/vendor/quickjs-ng/quickjs-c-atomics.h +54 -0
  372. package/vendor/quickjs-ng/quickjs-libc.c +5037 -0
  373. package/vendor/quickjs-ng/quickjs-libc.h +87 -0
  374. package/vendor/quickjs-ng/quickjs-opcode.h +377 -0
  375. package/vendor/quickjs-ng/quickjs.c +64041 -0
  376. package/vendor/quickjs-ng/quickjs.h +1447 -0
  377. package/vendor/quickjs-ng/run-test262.c +2374 -0
  378. package/vendor/quickjs-ng/unicode_gen.c +3121 -0
  379. package/vendor/quickjs-ng/unicode_gen_def.h +310 -0
  380. package/vendor/ryu/LICENSE-Boost +23 -0
  381. package/vendor/ryu/common.h +114 -0
  382. package/vendor/ryu/d2s.c +509 -0
  383. package/vendor/ryu/d2s_full_table.h +367 -0
  384. package/vendor/ryu/d2s_intrinsics.h +357 -0
  385. package/vendor/ryu/d2s_small_table.h +186 -0
  386. package/vendor/ryu/digit_table.h +35 -0
  387. package/vendor/ryu/ryu.h +46 -0
  388. package/vendor/zlib/LICENSE +22 -0
  389. package/vendor/zlib/adler32.c +164 -0
  390. package/vendor/zlib/compress.c +75 -0
  391. package/vendor/zlib/crc32.c +1049 -0
  392. package/vendor/zlib/crc32.h +9446 -0
  393. package/vendor/zlib/deflate.c +2139 -0
  394. package/vendor/zlib/deflate.h +377 -0
  395. package/vendor/zlib/gzclose.c +23 -0
  396. package/vendor/zlib/gzguts.h +214 -0
  397. package/vendor/zlib/gzlib.c +582 -0
  398. package/vendor/zlib/gzread.c +602 -0
  399. package/vendor/zlib/gzwrite.c +631 -0
  400. package/vendor/zlib/infback.c +628 -0
  401. package/vendor/zlib/inffast.c +320 -0
  402. package/vendor/zlib/inffast.h +11 -0
  403. package/vendor/zlib/inffixed.h +94 -0
  404. package/vendor/zlib/inflate.c +1526 -0
  405. package/vendor/zlib/inflate.h +126 -0
  406. package/vendor/zlib/inftrees.c +299 -0
  407. package/vendor/zlib/inftrees.h +62 -0
  408. package/vendor/zlib/trees.c +1117 -0
  409. package/vendor/zlib/trees.h +128 -0
  410. package/vendor/zlib/uncompr.c +85 -0
  411. package/vendor/zlib/zconf.h +543 -0
  412. package/vendor/zlib/zlib.h +1938 -0
  413. package/vendor/zlib/zutil.c +299 -0
  414. package/vendor/zlib/zutil.h +254 -0
  415. package/README.md +0 -3
  416. package/index.js +0 -2
@@ -0,0 +1,1393 @@
1
+ /* node:assert — the static assertion surface. Every failure throws a
2
+ * catchable AssertionError: a runtime %Error instance whose name is
3
+ * "AssertionError" and whose code slot is "ERR_ASSERTION" (Node's
4
+ * ERR_ASSERTION), so catch-side `instanceof Error`, `.name`, `.message`,
5
+ * and `.code` reads all answer exactly like Node's.
6
+ *
7
+ * Generated messages reproduce Node's assertion_error.js for the SCALAR
8
+ * comparisons this file receives (numbers, strings, booleans): the short
9
+ * `a !== b` form under the 12-character budget (string quotes excluded),
10
+ * the stacked `+ actual - expected` diff above it — including the `^`
11
+ * first-difference indicator for string pairs — and the inline-vs-block
12
+ * split of the not-equal operators (single-line inspect over 5 chars goes
13
+ * on its own block). One deliberate divergence (SEMANTICS.md 103): Node
14
+ * renders a COLORED character diff for string pairs when stderr is a
15
+ * color TTY; this runtime always emits the plain stacked form (the
16
+ * message text itself would be terminal-dependent in Node).
17
+ * Deep-equality over composite values compares honestly in
18
+ * compiler-synthesized helpers; their generated failure messages carry
19
+ * Node's header line WITHOUT the rendered value diff (a full
20
+ * util.inspect has no static lowering — SEMANTICS.md 102).
21
+ *
22
+ * Ownership: all ScrStr arguments are BORROWED; the throw helpers that
23
+ * take ownership say so. Value inspection follows util.inspect's default
24
+ * quoting (single quotes, then double, then backtick; C0 controls and
25
+ * DEL escaped) — exotic C1/Unicode escapes are out of scope
26
+ * (SEMANTICS.md 106). */
27
+ #include "scr_runtime.h"
28
+
29
+ #include <math.h>
30
+ #include <stdio.h>
31
+ #include <stdlib.h>
32
+ #include <string.h>
33
+
34
+ static void scr_assert_oom(void) {
35
+ fputs("scriptc: out of memory\n", stderr);
36
+ abort();
37
+ }
38
+
39
+ /* ── a tiny append-only byte buffer for message assembly ─────────────── */
40
+
41
+ typedef struct {
42
+ char *data;
43
+ size_t len;
44
+ size_t cap;
45
+ } ScrAssertBuf;
46
+
47
+ static void ab_grow(ScrAssertBuf *b, size_t need) {
48
+ if (b->len + need <= b->cap) return;
49
+ size_t cap = b->cap ? b->cap * 2 : 64;
50
+ while (cap < b->len + need) cap *= 2;
51
+ char *data = realloc(b->data, cap);
52
+ if (!data) scr_assert_oom();
53
+ b->data = data;
54
+ b->cap = cap;
55
+ }
56
+
57
+ static void ab_bytes(ScrAssertBuf *b, const char *s, size_t len) {
58
+ ab_grow(b, len);
59
+ memcpy(b->data + b->len, s, len);
60
+ b->len += len;
61
+ }
62
+
63
+ static void ab_cstr(ScrAssertBuf *b, const char *s) { ab_bytes(b, s, strlen(s)); }
64
+
65
+ static void ab_char(ScrAssertBuf *b, char c) { ab_bytes(b, &c, 1); }
66
+
67
+ static void ab_str(ScrAssertBuf *b, const ScrStr *s) { ab_bytes(b, s->data, s->len); }
68
+
69
+ static ScrStr *ab_take(ScrAssertBuf *b) {
70
+ ScrStr *out = scr_str_new(b->data ? b->data : "", b->len);
71
+ free(b->data);
72
+ return out;
73
+ }
74
+
75
+ /* ── value inspection (util.inspect's scalar slice) ──────────────────── */
76
+
77
+ /* Number inspection: JS ToString EXCEPT that inspect distinguishes -0. */
78
+ static size_t scr_assert_inspect_f64(double x, char *buf /* >= 33 */) {
79
+ if (x == 0.0 && signbit(x)) {
80
+ memcpy(buf, "-0", 3);
81
+ return 2;
82
+ }
83
+ return scr_f64_to_str(x, buf);
84
+ }
85
+
86
+ /* String inspection: util.inspect's quoting — single quotes by default,
87
+ * double quotes when the text contains ' but no ", backticks when it
88
+ * contains both; backslash/quote/C0/DEL escaped (\b \t \n \f \r named,
89
+ * \x0B and the rest as \xNN — inspect's own table). +1. */
90
+ ScrStr *scr_assert_inspect_str(const ScrStr *s) {
91
+ char quote = '\'';
92
+ bool hasSingle = false, hasDouble = false;
93
+ for (size_t i = 0; i < s->len; i++) {
94
+ if (s->data[i] == '\'') hasSingle = true;
95
+ if (s->data[i] == '"') hasDouble = true;
96
+ }
97
+ if (hasSingle) quote = hasDouble ? '`' : '"';
98
+ ScrAssertBuf b = {0};
99
+ ab_char(&b, quote);
100
+ for (size_t i = 0; i < s->len; i++) {
101
+ unsigned char c = (unsigned char)s->data[i];
102
+ if (c == (unsigned char)quote || c == '\\') {
103
+ ab_char(&b, '\\');
104
+ ab_char(&b, (char)c);
105
+ } else if (c == '\b') {
106
+ ab_cstr(&b, "\\b");
107
+ } else if (c == '\t') {
108
+ ab_cstr(&b, "\\t");
109
+ } else if (c == '\n') {
110
+ ab_cstr(&b, "\\n");
111
+ } else if (c == '\f') {
112
+ ab_cstr(&b, "\\f");
113
+ } else if (c == '\r') {
114
+ ab_cstr(&b, "\\r");
115
+ } else if (c < 0x20 || c == 0x7f) {
116
+ char esc[5];
117
+ snprintf(esc, sizeof esc, "\\x%02X", c);
118
+ ab_cstr(&b, esc);
119
+ } else {
120
+ ab_char(&b, (char)c);
121
+ }
122
+ }
123
+ ab_char(&b, quote);
124
+ return ab_take(&b);
125
+ }
126
+
127
+ /* ── the AssertionError throw ─────────────────────────────────────────── */
128
+
129
+ /* Throws an AssertionError with `message` (ownership MOVES in): a runtime
130
+ * %Error whose name/code are Node's. The exception is pending on return —
131
+ * callers return through the emitter's pending check like every other
132
+ * throwing libCall. */
133
+ void scr_assert_fail_msg(ScrStr *message) {
134
+ ScrError *e = scr_error_new(SCR_ERR_ERROR, message);
135
+ scr_str_release(message); /* scr_error_new retained its copy */
136
+ scr_str_release(e->name);
137
+ e->name = scr_str_new("AssertionError", 14);
138
+ scr_error_set_code(e, "ERR_ASSERTION");
139
+ scr_throw_obj(e, &scr_error_retain_v, &scr_error_release_v, scr_error_trace_arg());
140
+ }
141
+
142
+ /* assert(value) / assert.ok(value[, message]) / assert.fail([message]):
143
+ * the frontend computed the truthiness and the FULL message (the user's
144
+ * string, or the compile-time "The expression evaluated to a falsy
145
+ * value:\n\n <source text>\n" — the source is a compile-time constant
146
+ * where Node re-reads the file). */
147
+ void scr_assert_ok(bool pass, ScrStr *message) {
148
+ if (pass) return;
149
+ scr_assert_fail_msg(scr_str_retain(message));
150
+ }
151
+
152
+ /* SameValue over doubles — Object.is, the comparison of strictEqual AND
153
+ * deepStrictEqual for numbers (NaN equals NaN; +0 and -0 differ). */
154
+ bool scr_assert_same_value_f64(double a, double b) {
155
+ if (a == b) return a != 0.0 || signbit(a) == signbit(b);
156
+ return isnan(a) && isnan(b);
157
+ }
158
+
159
+ /* ── generated equality messages (assertion_error.js, scalar slice) ──── */
160
+
161
+ static const char *scr_assert_eq_header(bool deep) {
162
+ return deep ? "Expected values to be strictly deep-equal:"
163
+ : "Expected values to be strictly equal:";
164
+ }
165
+
166
+ static const char *scr_assert_neq_header(bool deep) {
167
+ return deep ? "Expected \"actual\" not to be strictly deep-equal to:"
168
+ : "Expected \"actual\" to be strictly unequal to:";
169
+ }
170
+
171
+ /* The failing NOT-equal operators (values compared equal): the custom
172
+ * message stands alone; the generated one inlines a short single-line
173
+ * inspect after the header (<= 5 chars), block form otherwise. `insp` is
174
+ * the inspected actual value (borrowed bytes). Exported for the spoke
175
+ * files that carry their own inspection (scr_symbol.c). */
176
+ void scr_assert_neq_fail(const char *insp, size_t ilen, bool deep,
177
+ ScrStr *msg, bool has_msg) {
178
+ if (has_msg) {
179
+ scr_assert_fail_msg(scr_str_retain(msg));
180
+ return;
181
+ }
182
+ ScrAssertBuf b = {0};
183
+ ab_cstr(&b, scr_assert_neq_header(deep));
184
+ ab_cstr(&b, ilen > 5 ? "\n\n" : " ");
185
+ ab_bytes(&b, insp, ilen);
186
+ scr_assert_fail_msg(ab_take(&b));
187
+ }
188
+
189
+ /* The failing EQUAL operators: createErrDiff's scalar paths — a custom
190
+ * message replaces the HEADER (Node appends the diff below it; the empty
191
+ * string falls back to the default header, `message ||` in Node).
192
+ * `quotes` counts the string-typed sides (each contributes 2 quote
193
+ * characters excluded from the short-form budget); `both_zero` is the
194
+ * ±0-vs-±0 special case (never short); `strings` enables the stacked
195
+ * form's first-difference `^` indicator (string pairs only, combined
196
+ * inspected length within the 80-column non-TTY default). Exported for
197
+ * scr_symbol.c's symbol comparison. */
198
+ void scr_assert_eq_fail(const char *ia, size_t la, const char *ib, size_t lb,
199
+ int quotes, bool both_zero, bool strings, bool deep,
200
+ ScrStr *msg, bool has_msg) {
201
+ ScrAssertBuf b = {0};
202
+ if (has_msg && msg->len > 0) {
203
+ ab_str(&b, msg);
204
+ } else {
205
+ ab_cstr(&b, scr_assert_eq_header(deep));
206
+ }
207
+ size_t stringsLen = la + lb - (size_t)(2 * quotes);
208
+ if (stringsLen <= 12 && !both_zero) {
209
+ ab_cstr(&b, "\n\n");
210
+ ab_bytes(&b, ia, la);
211
+ ab_cstr(&b, " !== ");
212
+ ab_bytes(&b, ib, lb);
213
+ ab_cstr(&b, "\n");
214
+ } else {
215
+ ab_cstr(&b, "\n+ actual - expected\n\n+ ");
216
+ ab_bytes(&b, ia, la);
217
+ ab_cstr(&b, "\n- ");
218
+ ab_bytes(&b, ib, lb);
219
+ if (strings && la + lb <= 80) {
220
+ /* The first-difference indicator (getStackedDiff): the first index
221
+ * where actual's characters stop matching expected's — skipped when
222
+ * that lands within the first two content characters (i < 3 over the
223
+ * quoted text) or when actual is a prefix of expected. Node computes
224
+ * this over the INSPECTED text of every simple stacked diff (numbers
225
+ * and symbols included — getSimpleDiff hands getStackedDiff the
226
+ * rendered strings, so its typeof-string test is always true), so
227
+ * every scalar caller passes `strings` true. */
228
+ size_t i = 0;
229
+ while (i < la && i < lb && ia[i] == ib[i]) i++;
230
+ if (i < la && i >= 3) {
231
+ ab_char(&b, '\n');
232
+ for (size_t k = 0; k < i + 2; k++) ab_char(&b, ' ');
233
+ ab_char(&b, '^');
234
+ }
235
+ }
236
+ ab_cstr(&b, "\n");
237
+ }
238
+ scr_assert_fail_msg(ab_take(&b));
239
+ }
240
+
241
+ /* strictEqual / notStrictEqual / deepStrictEqual / notDeepStrictEqual over
242
+ * numbers: Object.is comparison, inspect distinguishes -0. */
243
+ void scr_assert_eq_f64(double a, double b, bool negated, bool deep,
244
+ ScrStr *msg, bool has_msg) {
245
+ bool same = scr_assert_same_value_f64(a, b);
246
+ if ((negated && !same) || (!negated && same)) return;
247
+ char ia[40], ib[40];
248
+ size_t la = scr_assert_inspect_f64(a, ia);
249
+ if (negated) {
250
+ scr_assert_neq_fail(ia, la, deep, msg, has_msg);
251
+ return;
252
+ }
253
+ size_t lb = scr_assert_inspect_f64(b, ib);
254
+ scr_assert_eq_fail(ia, la, ib, lb, 0, a == 0.0 && b == 0.0, true, deep, msg, has_msg);
255
+ }
256
+
257
+ /* The string forms: byte equality IS SameValue for well-formed UTF-8. */
258
+ void scr_assert_eq_str(ScrStr *a, ScrStr *b, bool negated, bool deep,
259
+ ScrStr *msg, bool has_msg) {
260
+ bool same = a->len == b->len && memcmp(a->data, b->data, a->len) == 0;
261
+ if ((negated && !same) || (!negated && same)) return;
262
+ ScrStr *ia = scr_assert_inspect_str(a);
263
+ if (negated) {
264
+ scr_assert_neq_fail(ia->data, ia->len, deep, msg, has_msg);
265
+ scr_str_release(ia);
266
+ return;
267
+ }
268
+ ScrStr *ib = scr_assert_inspect_str(b);
269
+ scr_assert_eq_fail(ia->data, ia->len, ib->data, ib->len, 2, false, true, deep,
270
+ msg, has_msg);
271
+ scr_str_release(ia);
272
+ scr_str_release(ib);
273
+ }
274
+
275
+ /* The boolean forms. */
276
+ void scr_assert_eq_bool(bool a, bool b, bool negated, bool deep,
277
+ ScrStr *msg, bool has_msg) {
278
+ bool same = a == b;
279
+ if ((negated && !same) || (!negated && same)) return;
280
+ const char *ia = a ? "true" : "false";
281
+ if (negated) {
282
+ scr_assert_neq_fail(ia, strlen(ia), deep, msg, has_msg);
283
+ return;
284
+ }
285
+ const char *ib = b ? "true" : "false";
286
+ scr_assert_eq_fail(ia, strlen(ia), ib, strlen(ib), 0, false, true, deep, msg,
287
+ has_msg);
288
+ }
289
+
290
+ /* deepStrictEqual / notDeepStrictEqual over COMPOSITE values: the frontend
291
+ * synthesized the honest structural comparison; this only turns its verdict
292
+ * into Node's throw. The generated message is the header line alone —
293
+ * rendering the value diff needs util.inspect, which has no static
294
+ * lowering (SEMANTICS.md 102). */
295
+ void scr_assert_deep_result(bool equal, bool negated, ScrStr *msg, bool has_msg) {
296
+ if ((negated && !equal) || (!negated && equal)) return;
297
+ if (has_msg && (negated || msg->len > 0)) {
298
+ /* Node: the not-equal operators use the message ALONE (even empty);
299
+ * the equal operators use it as the diff HEADER when non-empty —
300
+ * without a rendered diff below it the two collapse to the same
301
+ * shape here. */
302
+ scr_assert_fail_msg(scr_str_retain(msg));
303
+ return;
304
+ }
305
+ const char *base = negated ? scr_assert_neq_header(true) : scr_assert_eq_header(true);
306
+ scr_assert_fail_msg(scr_str_new(base, strlen(base)));
307
+ }
308
+
309
+ /* deepStrictEqual's content comparison over bytes values (the brand is
310
+ * the frontend's compile-time question — see the header). One elem kind
311
+ * by construction (the frontend's same-static-type gate), but the elem
312
+ * check stays: a defensive answer beats a miscompare. */
313
+ static bool scr_assert_bytes_content_eq(const ScrBytes *a, const ScrBytes *b) {
314
+ if (a->elem != b->elem || a->len != b->len) return false;
315
+ size_t nbytes = a->len * scr_bytes_elem_size(a->elem);
316
+ return nbytes == 0 || memcmp(a->data, b->data, nbytes) == 0;
317
+ }
318
+
319
+ bool scr_assert_bytes_deep_eq(const ScrBytes *a, const ScrBytes *b, bool brands_eq) {
320
+ return brands_eq && scr_assert_bytes_content_eq(a, b);
321
+ }
322
+
323
+ /* strictEqual / notStrictEqual over bytes values: reference identity.
324
+ * The generated messages are Node's OBJECT-comparison headers (createErrDiff
325
+ * routes objects through the reference-equality wording, not the scalar
326
+ * "strictly equal" one); the value renderings below them need the
327
+ * assert-style diff engine, so the header stands alone — the composite
328
+ * stance (SEMANTICS.md 102). */
329
+ void scr_assert_ref_eq_bytes(const ScrBytes *a, const ScrBytes *b, bool negated,
330
+ bool brands_eq, ScrStr *msg, bool has_msg) {
331
+ bool same = a == b;
332
+ if ((negated && !same) || (!negated && same)) return;
333
+ if (has_msg && (negated || msg->len > 0)) {
334
+ /* The deepResult message stance: not-equal operators use it alone
335
+ * (even empty); the equal operators use a non-empty one as the diff
336
+ * header — headerless diffs collapse both to the message itself. */
337
+ scr_assert_fail_msg(scr_str_retain(msg));
338
+ return;
339
+ }
340
+ const char *h;
341
+ if (negated) {
342
+ h = "Expected \"actual\" not to be reference-equal to \"expected\":";
343
+ } else if (brands_eq && scr_assert_bytes_content_eq(a, b)) {
344
+ h = "Values have same structure but are not reference-equal:";
345
+ } else {
346
+ h = "Expected \"actual\" to be reference-equal to \"expected\":";
347
+ }
348
+ scr_assert_fail_msg(scr_str_new(h, strlen(h)));
349
+ }
350
+
351
+ /* strictEqual / notStrictEqual over function values: reference identity.
352
+ * Two distinct functions are never deep-equal, so the failing equal form
353
+ * always takes the reference-equality expectation header. */
354
+ void scr_assert_ref_eq_fn(const ScrClosure *a, const ScrClosure *b, bool negated,
355
+ ScrStr *msg, bool has_msg) {
356
+ bool same = a == b;
357
+ if ((negated && !same) || (!negated && same)) return;
358
+ if (has_msg && (negated || msg->len > 0)) {
359
+ scr_assert_fail_msg(scr_str_retain(msg));
360
+ return;
361
+ }
362
+ const char *h = negated
363
+ ? "Expected \"actual\" not to be reference-equal to \"expected\":"
364
+ : "Expected \"actual\" to be reference-equal to \"expected\":";
365
+ scr_assert_fail_msg(scr_str_new(h, strlen(h)));
366
+ }
367
+
368
+ /* ── strictEqual / deepStrictEqual over CHECKED-DYNAMIC (dyn) operands ──
369
+ * The DOM carries the value's kind at runtime, so one entry point serves
370
+ * the whole quartet: SameValue for the strict pair (numbers by Object.is,
371
+ * strings by bytes, units by kind, arrays/objects/bytes by node identity,
372
+ * functions by the BOXED CLOSURE — two dyn crossings of one function are
373
+ * the same JS function), a structural DOM walk for the deep pair.
374
+ *
375
+ * Failure messages reproduce Node's assertion_error.js against the v24
376
+ * sources: inspectValue is a compact:false / sorted:true / depth-1000
377
+ * rendering of the DOM (each entry on its own line, entries sorted by
378
+ * their RENDERED text — Node's `sorted: true` sorts formatted entries),
379
+ * the simple/stacked scalar forms match the static paths byte-for-byte,
380
+ * and composite diffs run the real myers line diff with Node's printer
381
+ * (5 context lines, then "..." and the "... Skipped lines" banner, comma
382
+ * disparity between object lines treated as equal). Known divergences:
383
+ * key sorting is UTF-8 byte order where Node sorts UTF-16 code units
384
+ * (identical for ASCII keys), dyn function props are not rendered after
385
+ * the [Function: name] form, and values rendering past ~4096 lines fall
386
+ * back to the whole-value +/- form without context collapsing. */
387
+
388
+ /* JS SameValue over two DOM values (Object.is — the strictEqual and
389
+ * notStrictEqual comparison). Functions compare by boxed closure: the
390
+ * ScrDyn box is a boundary artifact, the closure IS the JS identity. */
391
+ static bool scr_assert_dyn_same_value(const ScrDyn *a, const ScrDyn *b) {
392
+ if (a->kind != b->kind) return false;
393
+ switch (a->kind) {
394
+ case SCR_DYN_UNDEF:
395
+ case SCR_DYN_NULL:
396
+ return true;
397
+ case SCR_DYN_BOOL:
398
+ return a->v.b == b->v.b;
399
+ case SCR_DYN_NUM:
400
+ return scr_assert_same_value_f64(a->v.num, b->v.num);
401
+ case SCR_DYN_STR:
402
+ return a->v.str->len == b->v.str->len &&
403
+ memcmp(a->v.str->data, b->v.str->data, a->v.str->len) == 0;
404
+ case SCR_DYN_FUNC:
405
+ return a == b || a->v.fn.clo == b->v.fn.clo;
406
+ case SCR_DYN_HANDLE:
407
+ /* Identity is the HANDLE (the strict_eq stance). */
408
+ return a->v.handle.tag == b->v.handle.tag && a->v.handle.ptr == b->v.handle.ptr;
409
+ case SCR_DYN_PROMISE:
410
+ /* Identity is the PROMISE (the strict_eq stance). */
411
+ return a->v.promise == b->v.promise;
412
+ default:
413
+ return a == b; /* ARR/OBJ/BYTES: node identity */
414
+ }
415
+ }
416
+
417
+ /* Node's strict deep equality over two DOM values: kind-wise — Object.is
418
+ * numbers, byte-equal strings, units by kind, per-element arrays,
419
+ * key-set-plus-values objects (DOM keys are unique, so equal lengths and
420
+ * an a⊆b value walk prove the bijection), brand-aware bytes (the buffer
421
+ * flavor bit IS the Buffer-vs-Uint8Array prototype Node compares first),
422
+ * reference identity for functions (boxed closure). Plain recursion:
423
+ * JSON-origin DOMs are trees; a keyed-write cycle (h.self = h) has no
424
+ * memo here where Node carries one (documented divergence). */
425
+ static bool scr_assert_dyn_deep_eq(const ScrDyn *a, const ScrDyn *b) {
426
+ if (a == b) return true;
427
+ if (a->kind != b->kind) return false;
428
+ switch (a->kind) {
429
+ case SCR_DYN_UNDEF:
430
+ case SCR_DYN_NULL:
431
+ return true;
432
+ case SCR_DYN_BOOL:
433
+ return a->v.b == b->v.b;
434
+ case SCR_DYN_NUM:
435
+ return scr_assert_same_value_f64(a->v.num, b->v.num);
436
+ case SCR_DYN_STR:
437
+ return a->v.str->len == b->v.str->len &&
438
+ memcmp(a->v.str->data, b->v.str->data, a->v.str->len) == 0;
439
+ case SCR_DYN_FUNC:
440
+ return a->v.fn.clo == b->v.fn.clo;
441
+ case SCR_DYN_HANDLE:
442
+ /* Node's deepStrictEqual over two distinct live handles walks own
443
+ * enumerable props we do not model; same-handle is the only case a
444
+ * compiled test can honestly answer (documented). */
445
+ return a->v.handle.tag == b->v.handle.tag && a->v.handle.ptr == b->v.handle.ptr;
446
+ case SCR_DYN_PROMISE:
447
+ /* Node compares promises structurally (no own props → equal); the
448
+ * honest arm here is identity — two distinct promises with equal
449
+ * settlements would diverge (documented with the handle stance). */
450
+ return a->v.promise == b->v.promise;
451
+ case SCR_DYN_BYTES: {
452
+ if (a->buffer != b->buffer) return false; /* the prototype gate */
453
+ const ScrBytes *x = a->v.bytes, *y = b->v.bytes;
454
+ if (x->elem != y->elem || x->len != y->len) return false;
455
+ size_t nbytes = x->len * scr_bytes_elem_size(x->elem);
456
+ return nbytes == 0 || memcmp(x->data, y->data, nbytes) == 0;
457
+ }
458
+ case SCR_DYN_ARR: {
459
+ if (a->v.arr.len != b->v.arr.len) return false;
460
+ for (size_t i = 0; i < a->v.arr.len; i++) {
461
+ if (!scr_assert_dyn_deep_eq(a->v.arr.items[i], b->v.arr.items[i])) return false;
462
+ }
463
+ return true;
464
+ }
465
+ case SCR_DYN_OBJ: {
466
+ if (a->v.obj.len != b->v.obj.len) return false;
467
+ for (size_t i = 0; i < a->v.obj.len; i++) {
468
+ const ScrDynEntry *ent = &a->v.obj.entries[i];
469
+ ScrDyn *bv = scr_dyn_obj_get(b, ent->key, ent->key_len);
470
+ if (!bv || !scr_assert_dyn_deep_eq(ent->value, bv)) return false;
471
+ }
472
+ return true;
473
+ }
474
+ }
475
+ return false; /* unreachable */
476
+ }
477
+
478
+ /* ── inspectValue over the DOM (assertion_error.js's inspect options:
479
+ * compact:false, sorted:true, depth 1000, maxArrayLength Infinity) ───── */
480
+
481
+ #define SCR_ASSERT_CF_DEPTH 1000
482
+
483
+ static void scr_assert_cf_pad(ScrAssertBuf *b, size_t n) {
484
+ ab_grow(b, n);
485
+ memset(b->data + b->len, ' ', n);
486
+ b->len += n;
487
+ }
488
+
489
+ /* Property-key rendering: __proto__ bracketed, identifier-shaped keys
490
+ * bare (the scr_inspect.c ladder), everything else inspect-quoted. */
491
+ static void scr_assert_cf_key(ScrAssertBuf *b, const char *key, size_t len) {
492
+ if (len == 9 && memcmp(key, "__proto__", 9) == 0) {
493
+ ab_cstr(b, "['__proto__']");
494
+ return;
495
+ }
496
+ bool bare = len > 0;
497
+ for (size_t i = 0; bare && i < len; i++) {
498
+ char c = key[i];
499
+ bool head_ok = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';
500
+ bool tail_ok = head_ok || (c >= '0' && c <= '9');
501
+ bare = i == 0 ? head_ok : tail_ok;
502
+ }
503
+ if (bare) {
504
+ ab_bytes(b, key, len);
505
+ return;
506
+ }
507
+ ScrStr *raw = scr_str_new(key, len);
508
+ ScrStr *q = scr_assert_inspect_str(raw);
509
+ ab_str(b, q);
510
+ scr_str_release(q);
511
+ scr_str_release(raw);
512
+ }
513
+
514
+ /* One rendered object entry, for sorting before emission. */
515
+ typedef struct {
516
+ char *text;
517
+ size_t len;
518
+ } ScrCfEntry;
519
+
520
+ static int scr_assert_cf_entry_cmp(const void *pa, const void *pb) {
521
+ const ScrCfEntry *a = pa, *b = pb;
522
+ size_t n = a->len < b->len ? a->len : b->len;
523
+ int c = n ? memcmp(a->text, b->text, n) : 0;
524
+ if (c) return c;
525
+ return a->len < b->len ? -1 : (a->len > b->len ? 1 : 0);
526
+ }
527
+
528
+ /* Renders `d` at `indent` (the column its CONTINUATION lines start at);
529
+ * the first line is appended in place. */
530
+ static void scr_assert_cf_value(ScrAssertBuf *b, const ScrDyn *d, size_t indent,
531
+ size_t depth) {
532
+ switch (d->kind) {
533
+ case SCR_DYN_UNDEF:
534
+ ab_cstr(b, "undefined");
535
+ return;
536
+ case SCR_DYN_NULL:
537
+ ab_cstr(b, "null");
538
+ return;
539
+ case SCR_DYN_BOOL:
540
+ ab_cstr(b, d->v.b ? "true" : "false");
541
+ return;
542
+ case SCR_DYN_NUM: {
543
+ char tmp[40];
544
+ size_t n = scr_assert_inspect_f64(d->v.num, tmp);
545
+ ab_bytes(b, tmp, n);
546
+ return;
547
+ }
548
+ case SCR_DYN_STR: {
549
+ ScrStr *q = scr_assert_inspect_str(d->v.str);
550
+ ab_str(b, q);
551
+ scr_str_release(q);
552
+ return;
553
+ }
554
+ case SCR_DYN_FUNC: {
555
+ const char *name = d->v.fn.name;
556
+ if (name && name[0]) {
557
+ ab_cstr(b, "[Function: ");
558
+ ab_cstr(b, name);
559
+ ab_char(b, ']');
560
+ } else {
561
+ ab_cstr(b, "[Function (anonymous)]");
562
+ }
563
+ return;
564
+ }
565
+ case SCR_DYN_HANDLE: {
566
+ /* The depth-elided class form ([ServerResponse]) — the full own-
567
+ * property dump Node renders is internals we do not model; this
568
+ * text only appears inside FAILURE diffs, which already diverge in
569
+ * report format. */
570
+ ab_char(b, '[');
571
+ ab_cstr(b, scr_dyn_handle_cls(d));
572
+ ab_char(b, ']');
573
+ return;
574
+ }
575
+ case SCR_DYN_PROMISE: {
576
+ /* The depth-elided form (Node renders Promise { <state> }; failure
577
+ * diffs already diverge in report format — the handle stance). */
578
+ ab_cstr(b, "[Promise]");
579
+ return;
580
+ }
581
+ case SCR_DYN_BYTES: {
582
+ const ScrBytes *bs = d->v.bytes;
583
+ char prefix[64];
584
+ int pn = snprintf(prefix, sizeof prefix, "%s(%zu) %s[",
585
+ d->buffer ? "Buffer" : "Uint8Array", bs->len,
586
+ d->buffer ? "[Uint8Array] " : "");
587
+ ab_bytes(b, prefix, (size_t)pn);
588
+ if (bs->len == 0) {
589
+ ab_char(b, ']');
590
+ return;
591
+ }
592
+ for (size_t i = 0; i < bs->len; i++) {
593
+ ab_char(b, '\n');
594
+ scr_assert_cf_pad(b, indent + 2);
595
+ char tmp[40];
596
+ size_t n = scr_assert_inspect_f64((double)((const unsigned char *)bs->data)[i], tmp);
597
+ ab_bytes(b, tmp, n);
598
+ if (i + 1 < bs->len) ab_char(b, ',');
599
+ }
600
+ ab_char(b, '\n');
601
+ scr_assert_cf_pad(b, indent);
602
+ ab_char(b, ']');
603
+ return;
604
+ }
605
+ case SCR_DYN_ARR: {
606
+ if (d->v.arr.len == 0) {
607
+ ab_cstr(b, "[]");
608
+ return;
609
+ }
610
+ if (depth == 0) {
611
+ ab_cstr(b, "[Array]");
612
+ return;
613
+ }
614
+ ab_char(b, '[');
615
+ for (size_t i = 0; i < d->v.arr.len; i++) {
616
+ ab_char(b, '\n');
617
+ scr_assert_cf_pad(b, indent + 2);
618
+ scr_assert_cf_value(b, d->v.arr.items[i], indent + 2, depth - 1);
619
+ if (i + 1 < d->v.arr.len) ab_char(b, ',');
620
+ }
621
+ ab_char(b, '\n');
622
+ scr_assert_cf_pad(b, indent);
623
+ ab_char(b, ']');
624
+ return;
625
+ }
626
+ case SCR_DYN_OBJ: {
627
+ if (d->v.obj.len == 0) {
628
+ ab_cstr(b, "{}");
629
+ return;
630
+ }
631
+ if (depth == 0) {
632
+ ab_cstr(b, "[Object]");
633
+ return;
634
+ }
635
+ /* Render every entry, then sort the RENDERED texts (Node's
636
+ * sorted:true sorts formatted entries, quotes included). */
637
+ ScrCfEntry *ents = malloc(d->v.obj.len * sizeof *ents);
638
+ if (!ents) scr_assert_oom();
639
+ for (size_t i = 0; i < d->v.obj.len; i++) {
640
+ const ScrDynEntry *ent = &d->v.obj.entries[i];
641
+ ScrAssertBuf eb = {0};
642
+ scr_assert_cf_key(&eb, ent->key, ent->key_len);
643
+ ab_cstr(&eb, ": ");
644
+ scr_assert_cf_value(&eb, ent->value, indent + 2, depth - 1);
645
+ ents[i].text = eb.data ? eb.data : malloc(1);
646
+ if (!ents[i].text) scr_assert_oom();
647
+ ents[i].len = eb.len;
648
+ }
649
+ qsort(ents, d->v.obj.len, sizeof *ents, scr_assert_cf_entry_cmp);
650
+ ab_char(b, '{');
651
+ for (size_t i = 0; i < d->v.obj.len; i++) {
652
+ ab_char(b, '\n');
653
+ scr_assert_cf_pad(b, indent + 2);
654
+ ab_bytes(b, ents[i].text, ents[i].len);
655
+ if (i + 1 < d->v.obj.len) ab_char(b, ',');
656
+ free(ents[i].text);
657
+ }
658
+ free(ents);
659
+ ab_char(b, '\n');
660
+ scr_assert_cf_pad(b, indent);
661
+ ab_char(b, '}');
662
+ return;
663
+ }
664
+ }
665
+ }
666
+
667
+ static ScrStr *scr_assert_cf_inspect(const ScrDyn *d) {
668
+ ScrAssertBuf b = {0};
669
+ scr_assert_cf_value(&b, d, 0, SCR_ASSERT_CF_DEPTH);
670
+ return ab_take(&b);
671
+ }
672
+
673
+ /* ── the myers line diff (internal/assert/myers_diff.js) ─────────────── */
674
+
675
+ typedef struct {
676
+ const char *s;
677
+ size_t len;
678
+ } ScrLine;
679
+
680
+ /* Splits rendered text into lines (no trailing-newline convention: the
681
+ * renderer never emits a final \n, matching String.prototype.split). */
682
+ static ScrLine *scr_assert_split_lines(const ScrStr *text, size_t *out_n) {
683
+ size_t n = 1;
684
+ for (size_t i = 0; i < text->len; i++) {
685
+ if (text->data[i] == '\n') n++;
686
+ }
687
+ ScrLine *lines = malloc(n * sizeof *lines);
688
+ if (!lines) scr_assert_oom();
689
+ size_t li = 0, start = 0;
690
+ for (size_t i = 0; i <= text->len; i++) {
691
+ if (i == text->len || text->data[i] == '\n') {
692
+ lines[li].s = text->data + start;
693
+ lines[li].len = i - start;
694
+ li++;
695
+ start = i + 1;
696
+ }
697
+ }
698
+ *out_n = n;
699
+ return lines;
700
+ }
701
+
702
+ /* areLinesEqual with the comma-disparity rule: object lines differing
703
+ * only by a trailing comma count as equal. */
704
+ static bool scr_assert_lines_eq(ScrLine a, ScrLine b, bool comma) {
705
+ if (a.len == b.len && (a.len == 0 || memcmp(a.s, b.s, a.len) == 0)) return true;
706
+ if (!comma) return false;
707
+ if (a.len + 1 == b.len && b.s[b.len - 1] == ',' &&
708
+ (a.len == 0 || memcmp(a.s, b.s, a.len) == 0))
709
+ return true;
710
+ if (b.len + 1 == a.len && a.s[a.len - 1] == ',' &&
711
+ (b.len == 0 || memcmp(a.s, b.s, b.len) == 0))
712
+ return true;
713
+ return false;
714
+ }
715
+
716
+ typedef struct {
717
+ int8_t op; /* 1 INSERT (actual), -1 DELETE (expected), 0 NOP */
718
+ ScrLine line;
719
+ } ScrDiffOp;
720
+
721
+ /* The greedy O((N+M)·D) forward walk plus backtrack — a straight port of
722
+ * myersDiff/backtrack. The result array is in REVERSE document order
723
+ * (built back-to-front, like Node's), so the printer walks it from the
724
+ * end. Returns NULL when the inputs exceed the line cap (the caller falls
725
+ * back to the whole-value form). */
726
+ #define SCR_ASSERT_MYERS_CAP 4096
727
+
728
+ static ScrDiffOp *scr_assert_myers(ScrLine *a, size_t an, ScrLine *b, size_t bn,
729
+ bool comma, size_t *out_n) {
730
+ size_t max = an + bn;
731
+ if (max == 0 || max > SCR_ASSERT_MYERS_CAP) return NULL;
732
+ size_t width = 2 * max + 1;
733
+ int32_t *v = calloc(width, sizeof *v);
734
+ int32_t **trace = malloc((max + 1) * sizeof *trace);
735
+ if (!v || !trace) scr_assert_oom();
736
+ size_t traceN = 0;
737
+ size_t foundLevel = 0;
738
+ bool found = false;
739
+ for (size_t d = 0; d <= max && !found; d++) {
740
+ int32_t *snap = malloc(width * sizeof *snap);
741
+ if (!snap) scr_assert_oom();
742
+ memcpy(snap, v, width * sizeof *snap);
743
+ trace[traceN++] = snap;
744
+ for (long k = -(long)d; k <= (long)d; k += 2) {
745
+ size_t off = (size_t)(k + (long)max);
746
+ long x;
747
+ if (k == -(long)d || (k != (long)d && v[off - 1] < v[off + 1])) {
748
+ x = v[off + 1];
749
+ } else {
750
+ x = v[off - 1] + 1;
751
+ }
752
+ long y = x - k;
753
+ while (x < (long)an && y < (long)bn && scr_assert_lines_eq(a[x], b[y], comma)) {
754
+ x++;
755
+ y++;
756
+ }
757
+ v[off] = (int32_t)x;
758
+ if (x >= (long)an && y >= (long)bn) {
759
+ foundLevel = d;
760
+ found = true;
761
+ break;
762
+ }
763
+ }
764
+ }
765
+ free(v);
766
+ if (!found) { /* unreachable: D <= max always terminates */
767
+ for (size_t i = 0; i < traceN; i++) free(trace[i]);
768
+ free(trace);
769
+ return NULL;
770
+ }
771
+ ScrDiffOp *result = malloc((an + bn + 1) * sizeof *result);
772
+ if (!result) scr_assert_oom();
773
+ size_t rn = 0;
774
+ long x = (long)an, y = (long)bn;
775
+ for (long level = (long)foundLevel; level >= 0; level--) {
776
+ int32_t *vv = trace[level];
777
+ long k = x - y;
778
+ long prevK;
779
+ if (k == -level || (k != level && vv[k + (long)max - 1] < vv[k + (long)max + 1])) {
780
+ prevK = k + 1;
781
+ } else {
782
+ prevK = k - 1;
783
+ }
784
+ long prevX = vv[prevK + (long)max];
785
+ long prevY = prevX - prevK;
786
+ while (x > prevX && y > prevY) {
787
+ ScrLine ai = a[x - 1];
788
+ bool aComma = ai.len > 0 && ai.s[ai.len - 1] == ',';
789
+ result[rn].op = 0;
790
+ result[rn].line = (comma && !aComma) ? b[y - 1] : ai;
791
+ rn++;
792
+ x--;
793
+ y--;
794
+ }
795
+ if (level > 0) {
796
+ if (x > prevX) {
797
+ x--;
798
+ result[rn].op = 1;
799
+ result[rn].line = a[x];
800
+ } else {
801
+ y--;
802
+ result[rn].op = -1;
803
+ result[rn].line = b[y];
804
+ }
805
+ rn++;
806
+ }
807
+ }
808
+ for (size_t i = 0; i < traceN; i++) free(trace[i]);
809
+ free(trace);
810
+ *out_n = rn;
811
+ return result;
812
+ }
813
+
814
+ static void scr_assert_line_out(ScrAssertBuf *b, const char *prefix, ScrLine l) {
815
+ ab_cstr(b, prefix);
816
+ ab_bytes(b, l.s, l.len);
817
+ ab_char(b, '\n');
818
+ }
819
+
820
+ /* printMyersDiff: document order (the diff array reversed), 5 context
821
+ * lines per common run, then "..." plus the run's last line and the
822
+ * skipped flag. Trailing common lines past the window drop silently —
823
+ * Node's printer does the same. The message lands WITHOUT its leading
824
+ * newline (the caller places it); trailing whitespace trimmed. */
825
+ static bool scr_assert_print_myers(ScrAssertBuf *b, const ScrDiffOp *diff, size_t n) {
826
+ bool skipped = false;
827
+ size_t nopCount = 0;
828
+ size_t startLen = b->len;
829
+ for (size_t i = n; i-- > 0;) {
830
+ int8_t op = diff[i].op;
831
+ bool hasPrev = i + 1 < n;
832
+ if (hasPrev && diff[i + 1].op == 0 && op != 0) {
833
+ if (nopCount == 6) {
834
+ scr_assert_line_out(b, " ", diff[i + 1].line);
835
+ } else if (nopCount == 7) {
836
+ scr_assert_line_out(b, " ", diff[i + 2].line);
837
+ scr_assert_line_out(b, " ", diff[i + 1].line);
838
+ } else if (nopCount >= 8) {
839
+ ab_cstr(b, "...\n");
840
+ scr_assert_line_out(b, " ", diff[i + 1].line);
841
+ skipped = true;
842
+ }
843
+ nopCount = 0;
844
+ }
845
+ if (op == 1) {
846
+ scr_assert_line_out(b, "+ ", diff[i].line);
847
+ } else if (op == -1) {
848
+ scr_assert_line_out(b, "- ", diff[i].line);
849
+ } else {
850
+ if (nopCount < 5) scr_assert_line_out(b, " ", diff[i].line);
851
+ nopCount++;
852
+ }
853
+ }
854
+ while (b->len > startLen &&
855
+ (b->data[b->len - 1] == '\n' || b->data[b->len - 1] == ' ')) {
856
+ b->len--; /* trimEnd */
857
+ }
858
+ return skipped;
859
+ }
860
+
861
+ /* ── the dyn entry point ─────────────────────────────────────────────── */
862
+
863
+ /* Is this DOM kind `typeof == "object" && != null` to assertion_error.js? */
864
+ static bool scr_assert_dyn_is_object(const ScrDyn *d) {
865
+ return d->kind == SCR_DYN_ARR || d->kind == SCR_DYN_OBJ || d->kind == SCR_DYN_BYTES ||
866
+ d->kind == SCR_DYN_HANDLE || d->kind == SCR_DYN_PROMISE;
867
+ }
868
+
869
+ /* The failing EQUAL operators over dyn operands — createErrDiff. */
870
+ static void scr_assert_dyn_eq_fail(ScrDyn *a, ScrDyn *b, bool deep,
871
+ ScrStr *msg, bool has_msg) {
872
+ /* checkOperator: strictEqual over two objects (or two functions)
873
+ * reports the reference-equality expectation. */
874
+ bool objOp = !deep && ((scr_assert_dyn_is_object(a) && scr_assert_dyn_is_object(b)) ||
875
+ (a->kind == SCR_DYN_FUNC && b->kind == SCR_DYN_FUNC));
876
+ const char *header =
877
+ deep ? "Expected values to be strictly deep-equal:"
878
+ : (objOp ? "Expected \"actual\" to be reference-equal to \"expected\":"
879
+ : "Expected values to be strictly equal:");
880
+ ScrStr *ia = scr_assert_cf_inspect(a);
881
+ ScrStr *ib = scr_assert_cf_inspect(b);
882
+ size_t an, en;
883
+ ScrLine *alines = scr_assert_split_lines(ia, &an);
884
+ ScrLine *elines = scr_assert_split_lines(ib, &en);
885
+ ScrAssertBuf out = {0};
886
+ const char *customOrHeader = header; /* resolved after operator morphing */
887
+ bool simple = an == 1 && en == 1 &&
888
+ (!scr_assert_dyn_is_object(a) || !scr_assert_dyn_is_object(b));
889
+ bool inspEq = ia->len == ib->len && memcmp(ia->data, ib->data, ia->len) == 0;
890
+
891
+ if (simple) {
892
+ if (has_msg && msg->len > 0) {
893
+ ab_str(&out, msg);
894
+ } else {
895
+ ab_cstr(&out, customOrHeader);
896
+ }
897
+ size_t la = ia->len, lb = ib->len;
898
+ size_t stringsLen = la + lb;
899
+ if (a->kind == SCR_DYN_STR) stringsLen -= 2;
900
+ if (b->kind == SCR_DYN_STR) stringsLen -= 2;
901
+ bool bothZero = a->kind == SCR_DYN_NUM && b->kind == SCR_DYN_NUM &&
902
+ a->v.num == 0.0 && b->v.num == 0.0;
903
+ if (stringsLen <= 12 && !bothZero) {
904
+ ab_cstr(&out, "\n\n");
905
+ ab_str(&out, ia);
906
+ ab_cstr(&out, " !== ");
907
+ ab_str(&out, ib);
908
+ ab_cstr(&out, "\n");
909
+ } else {
910
+ ab_cstr(&out, "\n+ actual - expected\n\n+ ");
911
+ ab_str(&out, ia);
912
+ ab_cstr(&out, "\n- ");
913
+ ab_str(&out, ib);
914
+ /* getStackedDiff's ^ indicator runs over the INSPECTED text of
915
+ * every simple stacked diff (its typeof-string test sees the
916
+ * rendered strings), all kinds included. */
917
+ if (la + lb <= 80) {
918
+ size_t i = 0;
919
+ while (i < la && i < lb && ia->data[i] == ib->data[i]) i++;
920
+ if (i < la && i >= 3) {
921
+ ab_char(&out, '\n');
922
+ for (size_t k = 0; k < i + 2; k++) ab_char(&out, ' ');
923
+ ab_char(&out, '^');
924
+ }
925
+ }
926
+ ab_cstr(&out, "\n");
927
+ }
928
+ } else if (inspEq) {
929
+ /* Structurally identical renderings that are not the same reference:
930
+ * the notIdentical banner over the single rendering. */
931
+ const char *ident = "Values have same structure but are not reference-equal:";
932
+ if (has_msg && msg->len > 0) {
933
+ ab_str(&out, msg);
934
+ } else {
935
+ ab_cstr(&out, ident);
936
+ }
937
+ ab_cstr(&out, "\n");
938
+ if (an > 50) {
939
+ ab_cstr(&out, "\n... Skipped lines");
940
+ ab_cstr(&out, "\n");
941
+ for (size_t i = 0; i < 50; i++) {
942
+ ab_bytes(&out, alines[i].s, alines[i].len);
943
+ ab_char(&out, '\n');
944
+ }
945
+ ab_cstr(&out, "...}\n");
946
+ } else {
947
+ ab_cstr(&out, "\n");
948
+ ab_str(&out, ia);
949
+ ab_cstr(&out, "\n");
950
+ }
951
+ } else {
952
+ /* The myers line diff with Node's printer. checkCommaDisparity is
953
+ * Node's `actual != null && typeof actual === 'object'`. */
954
+ bool comma = scr_assert_dyn_is_object(a);
955
+ size_t dn = 0;
956
+ ScrDiffOp *diff = scr_assert_myers(alines, an, elines, en, comma, &dn);
957
+ if (has_msg && msg->len > 0) {
958
+ ab_str(&out, msg);
959
+ } else {
960
+ ab_cstr(&out, customOrHeader);
961
+ }
962
+ ab_cstr(&out, "\n+ actual - expected");
963
+ if (diff) {
964
+ ScrAssertBuf body = {0};
965
+ bool skipped = scr_assert_print_myers(&body, diff, dn);
966
+ if (skipped) ab_cstr(&out, "\n... Skipped lines");
967
+ ab_cstr(&out, "\n\n");
968
+ ab_bytes(&out, body.data ? body.data : "", body.len);
969
+ ab_cstr(&out, "\n");
970
+ free(body.data);
971
+ free(diff);
972
+ } else {
973
+ /* Past the line cap: the whole-value fallback (documented). */
974
+ ab_cstr(&out, "\n\n");
975
+ for (size_t i = 0; i < an; i++) scr_assert_line_out(&out, "+ ", alines[i]);
976
+ for (size_t i = 0; i < en; i++) {
977
+ ab_cstr(&out, "- ");
978
+ ab_bytes(&out, elines[i].s, elines[i].len);
979
+ if (i + 1 < en) ab_char(&out, '\n');
980
+ }
981
+ ab_cstr(&out, "\n");
982
+ }
983
+ }
984
+ free(alines);
985
+ free(elines);
986
+ scr_str_release(ia);
987
+ scr_str_release(ib);
988
+ scr_assert_fail_msg(ab_take(&out));
989
+ }
990
+
991
+ /* The failing NOT-equal operators over dyn operands (values compared
992
+ * same): a custom message stands alone; the generated one renders the
993
+ * actual value under the operator's banner (the object banner for
994
+ * notStrictEqual over objects/functions), inline when a single short
995
+ * line, block form otherwise, >50-line renderings collapsed. */
996
+ static void scr_assert_dyn_neq_fail(ScrDyn *a, bool deep, ScrStr *msg, bool has_msg) {
997
+ if (has_msg) {
998
+ scr_assert_fail_msg(scr_str_retain(msg));
999
+ return;
1000
+ }
1001
+ const char *base =
1002
+ deep ? "Expected \"actual\" not to be strictly deep-equal to:"
1003
+ : ((scr_assert_dyn_is_object(a) || a->kind == SCR_DYN_FUNC)
1004
+ ? "Expected \"actual\" not to be reference-equal to \"expected\":"
1005
+ : "Expected \"actual\" to be strictly unequal to:");
1006
+ ScrStr *ia = scr_assert_cf_inspect(a);
1007
+ size_t an;
1008
+ ScrLine *lines = scr_assert_split_lines(ia, &an);
1009
+ ScrAssertBuf out = {0};
1010
+ ab_cstr(&out, base);
1011
+ if (an == 1) {
1012
+ ab_cstr(&out, lines[0].len > 5 ? "\n\n" : " ");
1013
+ ab_str(&out, ia);
1014
+ } else {
1015
+ ab_cstr(&out, "\n\n");
1016
+ /* res.length > 50: line 47 becomes "..." and the rest drop. */
1017
+ size_t shown = an > 50 ? 47 : an;
1018
+ for (size_t i = 0; i < shown; i++) {
1019
+ if (an > 50 && i == 46) {
1020
+ ab_cstr(&out, "...");
1021
+ } else {
1022
+ ab_bytes(&out, lines[i].s, lines[i].len);
1023
+ }
1024
+ ab_char(&out, '\n');
1025
+ }
1026
+ }
1027
+ free(lines);
1028
+ scr_str_release(ia);
1029
+ scr_assert_fail_msg(ab_take(&out));
1030
+ }
1031
+
1032
+ /* strictEqual / notStrictEqual / deepStrictEqual / notDeepStrictEqual
1033
+ * where either operand is a checked-dynamic value (both arrive as DOM
1034
+ * values — the frontend boxes a static side). Borrows everything. */
1035
+ void scr_assert_eq_dyn(ScrDyn *a, ScrDyn *b, bool negated, bool deep,
1036
+ ScrStr *msg, bool has_msg) {
1037
+ bool same = deep ? scr_assert_dyn_deep_eq(a, b) : scr_assert_dyn_same_value(a, b);
1038
+ if ((negated && !same) || (!negated && same)) return;
1039
+ if (negated) {
1040
+ scr_assert_dyn_neq_fail(a, deep, msg, has_msg);
1041
+ } else {
1042
+ scr_assert_dyn_eq_fail(a, b, deep, msg, has_msg);
1043
+ }
1044
+ }
1045
+
1046
+ /* Node's expectsError over an error-INSTANCE expected (assert.throws/
1047
+ * rejects second argument): every key of the expected DOM error (the
1048
+ * %error marker skipped; name/message/code is the encoding's surface)
1049
+ * must deep-strict-equal the caught value's — extra ACTUAL keys are fine
1050
+ * (Node walks the expected's keys only). A mismatch fails through the
1051
+ * deep-equal report (a mismatched key implies the full comparison
1052
+ * differs, so the diff is honest); a non-object pair falls back to the
1053
+ * full deep comparison outright. */
1054
+ void scr_assert_expects_err_dyn(ScrDyn *actual, ScrDyn *expected, ScrStr *msg, bool has_msg) {
1055
+ if (actual->kind == SCR_DYN_OBJ && expected->kind == SCR_DYN_OBJ) {
1056
+ bool ok = true;
1057
+ for (size_t i = 0; i < expected->v.obj.len && ok; i++) {
1058
+ const ScrDynEntry *e = &expected->v.obj.entries[i];
1059
+ if (e->key_len == 6 && memcmp(e->key, "%error", 6) == 0) continue;
1060
+ ScrDyn *av = scr_dyn_obj_get(actual, e->key, e->key_len);
1061
+ if (av == NULL || !scr_assert_dyn_deep_eq(av, e->value)) ok = false;
1062
+ }
1063
+ if (ok) return;
1064
+ }
1065
+ scr_assert_eq_dyn(actual, expected, false, true, msg, has_msg);
1066
+ }
1067
+
1068
+ /* assert.throws(fn) that did NOT throw / assert.rejects whose promise
1069
+ * fulfilled: "Missing expected exception|rejection" with Node's details —
1070
+ * ` (${expected.name})` when the expected class or shape carries a name,
1071
+ * then `: message` or `.` (expectsError's NO_EXCEPTION_SENTINEL arm). */
1072
+ void scr_assert_throws_none(bool rejection, ScrStr *ename, bool has_ename,
1073
+ ScrStr *msg, bool has_msg) {
1074
+ ScrAssertBuf b = {0};
1075
+ ab_cstr(&b, rejection ? "Missing expected rejection" : "Missing expected exception");
1076
+ if (has_ename) {
1077
+ ab_cstr(&b, " (");
1078
+ ab_str(&b, ename);
1079
+ ab_char(&b, ')');
1080
+ }
1081
+ if (has_msg) {
1082
+ ab_cstr(&b, ": ");
1083
+ ab_str(&b, msg);
1084
+ } else {
1085
+ ab_cstr(&b, ".");
1086
+ }
1087
+ scr_assert_fail_msg(ab_take(&b));
1088
+ }
1089
+
1090
+ /* assert.throws(fn, ErrorClass) where the thrown Error is NOT an instance
1091
+ * of the expected class: Node's mismatch AssertionError, built from the
1092
+ * received error's name and message. (Node prefers constructor.name; this
1093
+ * runtime carries the `name` slot — identical for the builtin hierarchy,
1094
+ * SEMANTICS.md 105 for subclasses whose constructor name differs.)
1095
+ * Borrows both. */
1096
+ void scr_assert_throws_mismatch(ScrStr *expected_name, ScrError *err,
1097
+ ScrStr *msg, bool has_msg) {
1098
+ if (has_msg) {
1099
+ /* A custom message stands alone (Node's innerFail with the user's
1100
+ * message — the instance-of text is the generated form only). */
1101
+ scr_assert_fail_msg(scr_str_retain(msg));
1102
+ return;
1103
+ }
1104
+ ScrAssertBuf b = {0};
1105
+ ab_cstr(&b, "The error is expected to be an instance of \"");
1106
+ ab_str(&b, expected_name);
1107
+ ab_cstr(&b, "\". Received \"");
1108
+ if (err->name) ab_str(&b, err->name);
1109
+ ab_char(&b, '"');
1110
+ if (err->message && err->message->len > 0) {
1111
+ ab_cstr(&b, "\n\nError message:\n\n");
1112
+ ab_str(&b, err->message);
1113
+ }
1114
+ scr_assert_fail_msg(ab_take(&b));
1115
+ }
1116
+
1117
+ /* ── assert.throws(fn, <object shape>) — expectedException over the
1118
+ * static error surface ─────────────────────────────────────────────────
1119
+ * Node compares each own key of the expected object against the thrown
1120
+ * error: strings by deep-equal (byte equality here), regex values by
1121
+ * test against the actual string. The bounded key set (name/message/
1122
+ * code — everything the static surface carries) makes Node's generated
1123
+ * failure message — a deep-equal diff of two `Comparison` placeholder
1124
+ * objects, keys in inspect's SORTED order (code < message < name), a
1125
+ * regex-valued key that MATCHED rendering as the actual's own value on
1126
+ * both sides — fully enumerable, so the rendering is byte-exact, not
1127
+ * header-only. The accumulator is a static: the begin/slot/end calls are
1128
+ * straight-line inside one synthesized helper, no suspension between. */
1129
+
1130
+ enum { SHAPE_CODE = 0, SHAPE_MESSAGE = 1, SHAPE_NAME = 2 };
1131
+
1132
+ typedef struct {
1133
+ bool present;
1134
+ bool is_re;
1135
+ bool re_matched;
1136
+ ScrStr *val; /* owned: the string value, or the regex's /source/flags */
1137
+ } ScrShapeSlot;
1138
+
1139
+ static struct {
1140
+ ScrError *err; /* borrowed — alive across the straight-line sequence */
1141
+ ScrShapeSlot slots[3];
1142
+ } scr_shape;
1143
+
1144
+ static void scr_shape_clear(void) {
1145
+ for (int k = 0; k < 3; k++) {
1146
+ if (scr_shape.slots[k].val) scr_str_release(scr_shape.slots[k].val);
1147
+ scr_shape.slots[k] = (ScrShapeSlot){0};
1148
+ }
1149
+ scr_shape.err = NULL;
1150
+ }
1151
+
1152
+ void scr_assert_shape_begin(ScrError *err) {
1153
+ scr_shape_clear();
1154
+ scr_shape.err = err;
1155
+ }
1156
+
1157
+ void scr_assert_shape_str(int key, ScrStr *v) {
1158
+ scr_shape.slots[key] = (ScrShapeSlot){
1159
+ .present = true, .is_re = false, .re_matched = false, .val = scr_str_retain(v)};
1160
+ }
1161
+
1162
+ /* The regex slot's storage half — scr_regex.c tested the actual value
1163
+ * already and rendered the /source/flags form (moves in). */
1164
+ void scr_assert_shape_slot_re(int key, bool matched, ScrStr *rendered) {
1165
+ scr_shape.slots[key] = (ScrShapeSlot){
1166
+ .present = true, .is_re = true, .re_matched = matched, .val = rendered};
1167
+ }
1168
+
1169
+ /* The actual error's key value, borrowed; NULL = absent (a NULL code
1170
+ * slot — Node's `!(key in actual)`). name/message are always present. */
1171
+ ScrStr *scr_assert_shape_actual(int key) {
1172
+ switch (key) {
1173
+ case SHAPE_CODE:
1174
+ return scr_shape.err->code;
1175
+ case SHAPE_MESSAGE:
1176
+ return scr_shape.err->message;
1177
+ default:
1178
+ return scr_shape.err->name;
1179
+ }
1180
+ }
1181
+
1182
+ static bool scr_shape_str_eq(const ScrStr *a, const ScrStr *b) {
1183
+ return a->len == b->len && memcmp(a->data, b->data, a->len) == 0;
1184
+ }
1185
+
1186
+ /* Does every expected key match the caught error? (The pass check and
1187
+ * doesNotReject's predicate.) */
1188
+ static bool scr_shape_matches(void) {
1189
+ for (int k = 0; k < 3; k++) {
1190
+ const ScrShapeSlot *s = &scr_shape.slots[k];
1191
+ if (!s->present) continue;
1192
+ ScrStr *actual = scr_assert_shape_actual(k);
1193
+ if (!actual) return false;
1194
+ if (s->is_re ? !s->re_matched : !scr_shape_str_eq(actual, s->val)) return false;
1195
+ }
1196
+ return true;
1197
+ }
1198
+
1199
+ /* One rendered Comparison line: " <key>: <value>" (+ "," unless last).
1200
+ * The value is util.inspect of a string, or the regex's own rendering. */
1201
+ static ScrStr *scr_shape_line(int key, ScrStr *value, bool inspect, bool last) {
1202
+ static const char *names[3] = {"code", "message", "name"};
1203
+ ScrAssertBuf b = {0};
1204
+ ab_cstr(&b, " ");
1205
+ ab_cstr(&b, names[key]);
1206
+ ab_cstr(&b, ": ");
1207
+ if (inspect) {
1208
+ ScrStr *q = scr_assert_inspect_str(value);
1209
+ ab_str(&b, q);
1210
+ scr_str_release(q);
1211
+ } else {
1212
+ ab_str(&b, value);
1213
+ }
1214
+ if (!last) ab_char(&b, ',');
1215
+ return ab_take(&b);
1216
+ }
1217
+
1218
+ /* The failing shape comparison's generated message: Node's deep-equal
1219
+ * diff of the two Comparison renderings. A line diff over two tiny
1220
+ * arrays (<= 5 lines): common lines print with a two-space margin; each
1221
+ * maximal differing gap prints its actual lines (+) then its expected
1222
+ * lines (-) — the myers printer's grouping, verified against v24 across
1223
+ * the enumerable case space. */
1224
+ static void scr_shape_diff_fail(void) {
1225
+ ScrStr *alines[5], *elines[5];
1226
+ size_t an = 0, en = 0;
1227
+ /* Actual Comparison: the expected keys present on the error, sorted
1228
+ * render order (code < message < name); zero keys collapse to the
1229
+ * one-line "Comparison {}". */
1230
+ int akeys[3], ekeys[3];
1231
+ int ank = 0, enk = 0;
1232
+ for (int k = 0; k < 3; k++) {
1233
+ if (!scr_shape.slots[k].present) continue;
1234
+ ekeys[enk++] = k;
1235
+ if (scr_assert_shape_actual(k)) akeys[ank++] = k;
1236
+ }
1237
+ if (ank == 0) {
1238
+ alines[an++] = scr_str_new("Comparison {}", 13);
1239
+ } else {
1240
+ alines[an++] = scr_str_new("Comparison {", 12);
1241
+ for (int i = 0; i < ank; i++) {
1242
+ alines[an++] =
1243
+ scr_shape_line(akeys[i], scr_assert_shape_actual(akeys[i]), true, i == ank - 1);
1244
+ }
1245
+ alines[an++] = scr_str_new("}", 1);
1246
+ }
1247
+ elines[en++] = scr_str_new("Comparison {", 12);
1248
+ for (int i = 0; i < enk; i++) {
1249
+ const ScrShapeSlot *s = &scr_shape.slots[ekeys[i]];
1250
+ /* A regex value that MATCHED renders as the actual's own value on
1251
+ * the expected side too (Node's Comparison constructor), making the
1252
+ * two lines identical. */
1253
+ ScrStr *v = s->is_re && s->re_matched ? scr_assert_shape_actual(ekeys[i]) : s->val;
1254
+ bool inspect = !s->is_re || s->re_matched;
1255
+ elines[en++] = scr_shape_line(ekeys[i], v, inspect, i == enk - 1);
1256
+ }
1257
+ elines[en++] = scr_str_new("}", 1);
1258
+
1259
+ /* LCS table over the two line arrays (byte-equal lines), then the
1260
+ * matched pairs — unique here: distinct keys never render equal lines,
1261
+ * so ambiguity cannot arise. */
1262
+ size_t L[6][6] = {{0}};
1263
+ for (size_t i = an; i-- > 0;) {
1264
+ for (size_t j = en; j-- > 0;) {
1265
+ L[i][j] = scr_shape_str_eq(alines[i], elines[j])
1266
+ ? L[i + 1][j + 1] + 1
1267
+ : (L[i + 1][j] > L[i][j + 1] ? L[i + 1][j] : L[i][j + 1]);
1268
+ }
1269
+ }
1270
+ /* The walk: common lines print with a two-space margin; inside a gap
1271
+ * the >= tie-break prefers actual, so each maximal differing run
1272
+ * groups its + lines before its - lines — the myers printer's
1273
+ * grouping, verified against v24 across the enumerable case space
1274
+ * (the first "\n" doubles as the blank line under the banner). */
1275
+ ScrAssertBuf b = {0};
1276
+ ab_cstr(&b, "Expected values to be strictly deep-equal:\n+ actual - expected\n");
1277
+ size_t i = 0, j = 0;
1278
+ while (i < an && j < en) {
1279
+ if (scr_shape_str_eq(alines[i], elines[j])) {
1280
+ ab_cstr(&b, "\n ");
1281
+ ab_str(&b, alines[i]);
1282
+ i++;
1283
+ j++;
1284
+ } else if (L[i + 1][j] >= L[i][j + 1]) {
1285
+ ab_cstr(&b, "\n+ ");
1286
+ ab_str(&b, alines[i]);
1287
+ i++;
1288
+ } else {
1289
+ ab_cstr(&b, "\n- ");
1290
+ ab_str(&b, elines[j]);
1291
+ j++;
1292
+ }
1293
+ }
1294
+ for (; i < an; i++) {
1295
+ ab_cstr(&b, "\n+ ");
1296
+ ab_str(&b, alines[i]);
1297
+ }
1298
+ for (; j < en; j++) {
1299
+ ab_cstr(&b, "\n- ");
1300
+ ab_str(&b, elines[j]);
1301
+ }
1302
+ ab_cstr(&b, "\n");
1303
+ for (size_t k = 0; k < an; k++) scr_str_release(alines[k]);
1304
+ for (size_t k = 0; k < en; k++) scr_str_release(elines[k]);
1305
+ scr_assert_fail_msg(ab_take(&b));
1306
+ }
1307
+
1308
+ void scr_assert_shape_end(ScrStr *msg, bool has_msg) {
1309
+ if (scr_shape_matches()) {
1310
+ scr_shape_clear();
1311
+ return;
1312
+ }
1313
+ if (has_msg) {
1314
+ scr_shape_clear();
1315
+ scr_assert_fail_msg(scr_str_retain(msg));
1316
+ return;
1317
+ }
1318
+ scr_shape_diff_fail();
1319
+ scr_shape_clear();
1320
+ }
1321
+
1322
+ /* assert.doesNotReject whose rejection matched the expectation (or had
1323
+ * none): expectsNoError's generated message. */
1324
+ void scr_assert_unwanted_rejection(ScrError *err, ScrStr *msg, bool has_msg) {
1325
+ ScrAssertBuf b = {0};
1326
+ ab_cstr(&b, "Got unwanted rejection");
1327
+ if (has_msg) {
1328
+ ab_cstr(&b, ": ");
1329
+ ab_str(&b, msg);
1330
+ } else {
1331
+ ab_char(&b, '.');
1332
+ }
1333
+ ab_cstr(&b, "\nActual message: \"");
1334
+ if (err->message) ab_str(&b, err->message);
1335
+ ab_char(&b, '"');
1336
+ scr_assert_fail_msg(ab_take(&b));
1337
+ }
1338
+
1339
+ /* ── assert.ifError ───────────────────────────────────────────────────
1340
+ * Node throws for ANY value but null/undefined (falsy included); the
1341
+ * frontend routes null/undefined to a no-op and everything else here.
1342
+ * The detail is the error's message (its name when the message is
1343
+ * empty — Node reads constructor.name, identical for the builtin
1344
+ * hierarchy) or the value's inspection. */
1345
+
1346
+ static void scr_assert_iferror_fail(const char *detail, size_t len) {
1347
+ ScrAssertBuf b = {0};
1348
+ ab_cstr(&b, "ifError got unwanted exception: ");
1349
+ ab_bytes(&b, detail, len);
1350
+ scr_assert_fail_msg(ab_take(&b));
1351
+ }
1352
+
1353
+ void scr_assert_iferror_err(ScrError *err) {
1354
+ const ScrStr *d = err->message && err->message->len > 0 ? err->message : err->name;
1355
+ scr_assert_iferror_fail(d ? d->data : "", d ? d->len : 0);
1356
+ }
1357
+
1358
+ void scr_assert_iferror_f64(double x) {
1359
+ char buf[40];
1360
+ size_t n = scr_assert_inspect_f64(x, buf);
1361
+ scr_assert_iferror_fail(buf, n);
1362
+ }
1363
+
1364
+ void scr_assert_iferror_str(ScrStr *s) {
1365
+ ScrStr *q = scr_assert_inspect_str(s);
1366
+ scr_assert_iferror_fail(q->data, q->len);
1367
+ scr_str_release(q);
1368
+ }
1369
+
1370
+ void scr_assert_iferror_bool(bool v) {
1371
+ scr_assert_iferror_fail(v ? "true" : "false", v ? 4 : 5);
1372
+ }
1373
+
1374
+ /* The checked-dynamic argument (test/common's mustSucceed wrapper): the
1375
+ * DOM kind dispatches — units pass quietly, %error-marked objects (the
1376
+ * caughtToDyn encoding) throw with the error's message (its name when
1377
+ * the message is empty, Node's rule), everything else throws with the
1378
+ * value's inspection. */
1379
+ void scr_assert_iferror_dyn(const ScrDyn *v) {
1380
+ if (v->kind == SCR_DYN_UNDEF || v->kind == SCR_DYN_NULL) return;
1381
+ if (v->kind == SCR_DYN_OBJ && scr_dyn_obj_get(v, "%error", 6) != NULL) {
1382
+ const ScrDyn *msg = scr_dyn_obj_get(v, "message", 7);
1383
+ const ScrDyn *name = scr_dyn_obj_get(v, "name", 4);
1384
+ const ScrDyn *d = msg != NULL && msg->kind == SCR_DYN_STR && msg->v.str->len > 0 ? msg : name;
1385
+ if (d != NULL && d->kind == SCR_DYN_STR) {
1386
+ scr_assert_iferror_fail(d->v.str->data, d->v.str->len);
1387
+ return;
1388
+ }
1389
+ }
1390
+ ScrStr *q = scr_assert_cf_inspect(v);
1391
+ scr_assert_iferror_fail(q->data, q->len);
1392
+ scr_str_release(q);
1393
+ }