@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.
- package/dist/THIRD_PARTY_NOTICES +1 -1
- package/dist/bin/scriptc +0 -0
- package/dist/bin/scriptc.json +1 -1
- package/dist/lib/declarations/scriptc-node-fallback.d.ts +84 -19
- package/dist/lib/llvm/bin/scriptc-llvm-codegen +0 -0
- package/dist/lib/llvm/package.json +1 -1
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_child.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_console.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_console_native.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_error.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_events.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_fetch.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_grapheme.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_http.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_http2.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_net.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_object.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_stream.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_child.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_console.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_console_native.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_error.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_events.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_grapheme.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_http.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_http2.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_island.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_net.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_object.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_stream.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic/scr_web.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_console_native.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_error.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_grapheme.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_object.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_console_native.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_error.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_grapheme.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_object.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_console_native.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_error.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_grapheme.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_object.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-dev/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_console_native.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_error.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_grapheme.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_object.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/library-thread-release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/licenses/v8-number-radix.txt +61 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_child.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_console.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_console_native.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_error.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_events.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_fetch.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_grapheme.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_http.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_http2.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_net.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_object.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_stream.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/default/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_array.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_assert.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_async_dyn.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bigint.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_bytes_io.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_child.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_console.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_console_native.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_crypto_async.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_dyn_invoke.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_error.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_events.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_exception.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_file_handle.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_grapheme.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_http.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_http2.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_island.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_json.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_lib.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_map.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_net.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_node_builtin.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_object.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_qs.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_regex.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_stream.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_string.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_symbol.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_url.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic/scr_web.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/dynamic-text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/artifacts/release/runtime/text-decoder-legacy/scr_bytes.o +0 -0
- package/dist/lib/runtime-darwin-arm64/package.json +1 -1
- package/dist/lib/runtime-darwin-arm64/runtime-pack.json +549 -545
- package/dist/lib/runtime-sources/package.json +1 -1
- package/dist/lib/runtime-sources/src/scr_abort.c +5 -0
- package/dist/lib/runtime-sources/src/scr_array.c +16 -0
- package/dist/lib/runtime-sources/src/scr_assert.c +1 -0
- package/dist/lib/runtime-sources/src/scr_async.c +38 -5
- package/dist/lib/runtime-sources/src/scr_async_dyn.c +208 -40
- package/dist/lib/runtime-sources/src/scr_bigint.c +8 -0
- package/dist/lib/runtime-sources/src/scr_bytes.c +431 -41
- package/dist/lib/runtime-sources/src/scr_bytes_io.c +628 -12
- package/dist/lib/runtime-sources/src/scr_child.c +544 -17
- package/dist/lib/runtime-sources/src/scr_console.c +1 -1
- package/dist/lib/runtime-sources/src/scr_crypto_async.c +22 -2
- package/dist/lib/runtime-sources/src/scr_dyn_invoke.c +344 -73
- package/dist/lib/runtime-sources/src/scr_error.c +52 -5
- package/dist/lib/runtime-sources/src/scr_exception.c +21 -5
- package/dist/lib/runtime-sources/src/scr_fetch.c +311 -3
- package/dist/lib/runtime-sources/src/scr_file_handle.c +31 -0
- package/dist/lib/runtime-sources/src/scr_http.c +3 -0
- package/dist/lib/runtime-sources/src/scr_island.c +1226 -405
- package/dist/lib/runtime-sources/src/scr_island_manifest.h +11 -9
- package/dist/lib/runtime-sources/src/scr_json.c +1594 -139
- package/dist/lib/runtime-sources/src/scr_json.test.ts +1 -0
- package/dist/lib/runtime-sources/src/scr_lib.c +816 -34
- package/dist/lib/runtime-sources/src/scr_map.c +47 -0
- package/dist/lib/runtime-sources/src/scr_node_builtin.c +10 -0
- package/dist/lib/runtime-sources/src/scr_object.c +11 -0
- package/dist/lib/runtime-sources/src/scr_qs.c +10 -0
- package/dist/lib/runtime-sources/src/scr_regex.c +148 -72
- package/dist/lib/runtime-sources/src/scr_runtime.h +257 -41
- package/dist/lib/runtime-sources/src/scr_stream.c +197 -0
- package/dist/lib/runtime-sources/src/scr_string.c +16 -1
- package/dist/lib/runtime-sources/src/scr_symbol.c +5 -0
- package/dist/lib/runtime-sources/src/scr_text_decoder_labels.h +225 -0
- package/dist/lib/runtime-sources/src/scr_url.c +206 -10
- package/dist/lib/runtime-sources/src/scr_web.c +129 -26
- package/dist/lib/runtime-sources/vendor/v8-number-radix/LICENSE +61 -0
- 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 (
|
|
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
|
-
|
|
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
|
|
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 = ¤t->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
|
-
|
|
1172
|
-
|
|
1173
|
-
if (
|
|
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
|
|
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 *
|
|
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
|
|
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 *)
|
|
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
|
-
|
|
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
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
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
|
-
|
|
2375
|
+
scr_jb_putc(&shown, '\'');
|
|
2376
|
+
scr_jb_put_str(&shown, value);
|
|
2377
|
+
scr_jb_putc(&shown, '\'');
|
|
1941
2378
|
}
|
|
1942
|
-
|
|
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[
|
|
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[
|
|
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 =
|
|
2080
|
-
|
|
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 ==
|
|
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
|
-
|
|
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
|
|
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 <
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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)->
|
|
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 =
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
.
|
|
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
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
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
|
|
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 (
|
|
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", "
|
|
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 *
|
|
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
|
-
|
|
3435
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
4196
|
-
|
|
4197
|
-
|
|
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
|
|
4267
|
-
static const char message[] = "
|
|
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
|
-
|
|
4277
|
-
|
|
4278
|
-
|
|
4279
|
-
|
|
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
|
|
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
|
-
|
|
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 (
|
|
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) &&
|
|
5752
|
-
return
|
|
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 ||
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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:
|
|
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 =
|
|
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
|
-
|
|
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(
|
|
7727
|
-
if (strcmp(method, "delete") == 0) return scr_dyn_new_bool(
|
|
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 =
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
7829
|
-
if (strcmp(method, "delete") == 0) return scr_dyn_new_bool(
|
|
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,
|
|
7845
|
-
scr_dyn_arr_push(pair,
|
|
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,
|
|
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
|
+
}
|