├── .dprint.json ├── .gitattributes ├── .github ├── HOW_CI_WORKS.md └── workflows │ ├── ci-coverage │ └── action.yml │ ├── ci-job.yml │ ├── ci-lint-deps │ └── action.yml │ ├── ci-lint │ └── action.yml │ ├── ci-nop │ └── action.yml │ ├── ci-publish │ └── action.yml │ ├── ci-test-miri │ └── action.yml │ ├── ci-test-ops │ └── action.yml │ ├── ci-test-publish │ └── action.yml │ ├── ci-test-valgrind │ ├── action.yml │ └── suppressions.txt │ ├── ci-test │ └── action.yml │ ├── ci.yml │ └── version_bump.yml ├── .gitignore ├── .rustfmt.toml ├── ARCHITECTURE.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE.md ├── README.md ├── core ├── 00_infra.js ├── 00_primordials.js ├── 01_core.js ├── Cargo.toml ├── README.md ├── arena │ ├── mod.rs │ ├── raw_arena.rs │ ├── shared_arena.rs │ ├── shared_atomic_arena.rs │ └── unique_arena.rs ├── async_cancel.rs ├── async_cell.rs ├── benches │ ├── infra │ │ └── arena.rs │ ├── ops │ │ ├── async.rs │ │ ├── async_harness.js │ │ ├── opset.rs │ │ ├── sync.rs │ │ └── sync_harness.js │ └── snapshot │ │ ├── file.js │ │ ├── file2.js │ │ └── snapshot.rs ├── convert.rs ├── core.d.ts ├── cppgc.rs ├── error.rs ├── examples │ ├── disable_ops.rs │ ├── eval_js_value.rs │ ├── hello_world.rs │ ├── op2.js │ ├── op2.rs │ ├── snapshot │ │ ├── Cargo.toml │ │ ├── README.md │ │ ├── build.rs │ │ ├── example.js │ │ ├── src │ │ │ ├── main.rs │ │ │ └── runtime.js │ │ └── tests │ │ │ └── output.rs │ ├── ts_module_loader.rs │ ├── wasm.js │ ├── wasm.ts │ └── wasm.wasm ├── extension_set.rs ├── extensions.rs ├── external.rs ├── fast_string.rs ├── flags.rs ├── gotham_state.rs ├── inspector.rs ├── io │ ├── buffer_strategy.rs │ ├── buffers.rs │ ├── mod.rs │ ├── resource.rs │ ├── resource_handle.rs │ └── resource_table.rs ├── lib.rs ├── mod.js ├── module_specifier.rs ├── modules │ ├── loaders.rs │ ├── map.rs │ ├── mod.rs │ ├── module_map_data.rs │ ├── recursive_load.rs │ ├── testdata │ │ └── lazy_loaded.js │ └── tests.rs ├── ops.rs ├── ops_builtin.rs ├── ops_builtin_types.rs ├── ops_builtin_v8.rs ├── ops_metrics.rs ├── rebuild_async_stubs.js ├── runtime │ ├── bindings.rs │ ├── exception_state.rs │ ├── jsrealm.rs │ ├── jsruntime.rs │ ├── mod.rs │ ├── op_driver │ │ ├── erased_future.rs │ │ ├── future_arena.rs │ │ ├── futures_unordered_driver.rs │ │ ├── mod.rs │ │ └── op_results.rs │ ├── ops.rs │ ├── ops_rust_to_v8.rs │ ├── setup.rs │ ├── snapshot.rs │ ├── stats.rs │ ├── tests │ │ ├── error.rs │ │ ├── error_builder_test.js │ │ ├── jsrealm.rs │ │ ├── misc.rs │ │ ├── mod.rs │ │ ├── ops.rs │ │ └── snapshot.rs │ └── v8_static_strings.rs ├── source_map.rs ├── tasks.rs ├── web_timeout.rs └── webidl.rs ├── dcore ├── Cargo.toml ├── build.rs └── src │ ├── inspector_server.rs │ ├── main.rs │ └── metrics.rs ├── ops ├── Cargo.toml ├── README.md ├── compile_test_runner │ ├── Cargo.toml │ └── lib.rs ├── lib.rs ├── op2 │ ├── README.md │ ├── config.rs │ ├── dispatch_async.rs │ ├── dispatch_fast.rs │ ├── dispatch_shared.rs │ ├── dispatch_slow.rs │ ├── generator_state.rs │ ├── mod.rs │ ├── object_wrap.rs │ ├── signature.rs │ ├── signature_retval.rs │ ├── test_cases │ │ ├── async │ │ │ ├── async_arg_return.out │ │ │ ├── async_arg_return.rs │ │ │ ├── async_arg_return_result.out │ │ │ ├── async_arg_return_result.rs │ │ │ ├── async_cppgc.out │ │ │ ├── async_cppgc.rs │ │ │ ├── async_deferred.out │ │ │ ├── async_deferred.rs │ │ │ ├── async_jsbuffer.out │ │ │ ├── async_jsbuffer.rs │ │ │ ├── async_lazy.out │ │ │ ├── async_lazy.rs │ │ │ ├── async_op_metadata.out │ │ │ ├── async_op_metadata.rs │ │ │ ├── async_opstate.out │ │ │ ├── async_opstate.rs │ │ │ ├── async_precise_capture.out │ │ │ ├── async_precise_capture.rs │ │ │ ├── async_result.out │ │ │ ├── async_result.rs │ │ │ ├── async_result_impl.out │ │ │ ├── async_result_impl.rs │ │ │ ├── async_result_smi.out │ │ │ ├── async_result_smi.rs │ │ │ ├── async_stack_trace.out │ │ │ ├── async_stack_trace.rs │ │ │ ├── async_v8_global.out │ │ │ ├── async_v8_global.rs │ │ │ ├── async_void.out │ │ │ └── async_void.rs │ │ ├── compiler_pass │ │ │ ├── async.rs │ │ │ └── sync.rs │ │ └── sync │ │ │ ├── add.out │ │ │ ├── add.rs │ │ │ ├── add_options.out │ │ │ ├── add_options.rs │ │ │ ├── bigint.out │ │ │ ├── bigint.rs │ │ │ ├── bool.out │ │ │ ├── bool.rs │ │ │ ├── bool_result.out │ │ │ ├── bool_result.rs │ │ │ ├── buffers.out │ │ │ ├── buffers.rs │ │ │ ├── buffers_copy.out │ │ │ ├── buffers_copy.rs │ │ │ ├── buffers_out.out │ │ │ ├── buffers_out.rs │ │ │ ├── cfg.out │ │ │ ├── cfg.rs │ │ │ ├── clippy_allow.out │ │ │ ├── clippy_allow.rs │ │ │ ├── cppgc_resource.out │ │ │ ├── cppgc_resource.rs │ │ │ ├── doc_comment.out │ │ │ ├── doc_comment.rs │ │ │ ├── fast_alternative.out │ │ │ ├── fast_alternative.rs │ │ │ ├── from_v8.out │ │ │ ├── from_v8.rs │ │ │ ├── generics.out │ │ │ ├── generics.rs │ │ │ ├── nofast.out │ │ │ ├── nofast.rs │ │ │ ├── object_wrap.out │ │ │ ├── object_wrap.rs │ │ │ ├── op_state_attr.out │ │ │ ├── op_state_attr.rs │ │ │ ├── op_state_rc.out │ │ │ ├── op_state_rc.rs │ │ │ ├── op_state_ref.out │ │ │ ├── op_state_ref.rs │ │ │ ├── result_external.out │ │ │ ├── result_external.rs │ │ │ ├── result_primitive.out │ │ │ ├── result_primitive.rs │ │ │ ├── result_scope.out │ │ │ ├── result_scope.rs │ │ │ ├── result_void.out │ │ │ ├── result_void.rs │ │ │ ├── serde_v8.out │ │ │ ├── serde_v8.rs │ │ │ ├── smi.out │ │ │ ├── smi.rs │ │ │ ├── stack_trace.out │ │ │ ├── stack_trace.rs │ │ │ ├── stack_trace_scope.out │ │ │ ├── stack_trace_scope.rs │ │ │ ├── string_cow.out │ │ │ ├── string_cow.rs │ │ │ ├── string_onebyte.out │ │ │ ├── string_onebyte.rs │ │ │ ├── string_option_return.out │ │ │ ├── string_option_return.rs │ │ │ ├── string_owned.out │ │ │ ├── string_owned.rs │ │ │ ├── string_ref.out │ │ │ ├── string_ref.rs │ │ │ ├── string_return.out │ │ │ ├── string_return.rs │ │ │ ├── to_v8.out │ │ │ ├── to_v8.rs │ │ │ ├── v8_global.out │ │ │ ├── v8_global.rs │ │ │ ├── v8_handlescope.out │ │ │ ├── v8_handlescope.rs │ │ │ ├── v8_lifetime.out │ │ │ ├── v8_lifetime.rs │ │ │ ├── v8_ref_option.out │ │ │ ├── v8_ref_option.rs │ │ │ ├── v8_string.out │ │ │ ├── v8_string.rs │ │ │ ├── webidl.out │ │ │ └── webidl.rs │ ├── test_cases_fail │ │ ├── lifetimes.rs │ │ └── lifetimes.stderr │ ├── valid_args.md │ └── valid_retvals.md └── webidl │ ├── dictionary.rs │ ├── enum.rs │ ├── mod.rs │ ├── test_cases │ ├── dict.out │ ├── dict.rs │ ├── dict_and_enum.out │ ├── dict_and_enum.rs │ ├── enum.out │ └── enum.rs │ └── test_cases_fail │ ├── enum_fields.rs │ └── enum_fields.stderr ├── rust-toolchain.toml ├── serde_v8 ├── Cargo.toml ├── README.md ├── de.rs ├── error.rs ├── examples │ └── basic.rs ├── keys.rs ├── lib.rs ├── magic │ ├── any_value.rs │ ├── bigint.rs │ ├── buffer.rs │ ├── bytestring.rs │ ├── detached_buffer.rs │ ├── external_pointer.rs │ ├── global_value.rs │ ├── mod.rs │ ├── string_or_buffer.rs │ ├── transl8.rs │ ├── u16string.rs │ ├── v8slice.rs │ └── value.rs ├── payload.rs ├── ser.rs ├── tests │ ├── de.rs │ ├── magic.rs │ └── ser.rs └── utilities │ ├── Cargo.toml │ └── lib.rs ├── testing ├── Cargo.toml ├── README.md ├── checkin.d.ts ├── checkin │ ├── mod.rs │ ├── runner │ │ ├── extensions.rs │ │ ├── mod.rs │ │ ├── ops.rs │ │ ├── ops_async.rs │ │ ├── ops_buffer.rs │ │ ├── ops_error.rs │ │ ├── ops_io.rs │ │ ├── ops_worker.rs │ │ ├── snapshot.rs │ │ ├── testing.rs │ │ └── ts_module_loader.rs │ └── runtime │ │ ├── __init.js │ │ ├── async.ts │ │ ├── console.ts │ │ ├── error.ts │ │ ├── object.ts │ │ ├── testing.ts │ │ ├── throw.ts │ │ ├── timers.ts │ │ └── worker.ts ├── docs │ └── logo.png ├── integration │ ├── builtin_console_test │ │ ├── builtin_console_test.out │ │ └── builtin_console_test.ts │ ├── dyn_import_circular │ │ ├── a.js │ │ ├── b.js │ │ ├── c.js │ │ ├── d.js │ │ ├── dyn_import_circular.out │ │ └── dyn_import_circular.ts │ ├── dyn_import_no_hang │ │ ├── dyn_import_no_hang.js │ │ ├── dyn_import_no_hang.out │ │ └── dynamic.js │ ├── dyn_import_op │ │ ├── dyn_import_op.js │ │ ├── dyn_import_op.out │ │ ├── dynamic.js │ │ └── main.js │ ├── error_async_stack │ │ ├── error_async_stack.js │ │ └── error_async_stack.out │ ├── error_callsite │ │ ├── error_callsite.out │ │ └── error_callsite.ts │ ├── error_eval_stack │ │ ├── error_eval_stack.out │ │ └── error_eval_stack.ts │ ├── error_ext_stack │ │ ├── error_ext_stack.out │ │ └── error_ext_stack.ts │ ├── error_get_file_name │ │ ├── error_get_file_name.out │ │ └── error_get_file_name.ts │ ├── error_get_file_name_to_string │ │ ├── error_get_file_name_to_string.out │ │ └── error_get_file_name_to_string.ts │ ├── error_get_script_name_or_source_url │ │ ├── error_get_script_name_or_source_url.out │ │ └── error_get_script_name_or_source_url.ts │ ├── error_non_existent_eval_source │ │ ├── error_non_existent_eval_source.out │ │ └── error_non_existent_eval_source.ts │ ├── error_prepare_stack_trace │ │ ├── error_prepare_stack_trace.out │ │ └── error_prepare_stack_trace.ts │ ├── error_prepare_stack_trace_crash │ │ ├── error_prepare_stack_trace_crash.js │ │ └── error_prepare_stack_trace_crash.out │ ├── error_rejection_catch │ │ ├── error_rejection_catch.out │ │ └── error_rejection_catch.ts │ ├── error_rejection_order │ │ ├── error_rejection_order.out │ │ └── error_rejection_order.ts │ ├── error_source_maps_with_prepare_stack_trace │ │ ├── error_source_maps_with_prepare_stack_trace.out │ │ └── error_source_maps_with_prepare_stack_trace.ts │ ├── error_with_stack │ │ ├── error_with_stack.out │ │ └── error_with_stack.ts │ ├── error_without_stack │ │ ├── error_without_stack.js │ │ └── error_without_stack.out │ ├── import_sync │ │ ├── async.js │ │ ├── import_sync.out │ │ ├── import_sync.ts │ │ └── sync.js │ ├── import_sync_existing │ │ ├── import_sync_existing.out │ │ ├── import_sync_existing.ts │ │ └── sync.js │ ├── main_module_handler │ │ ├── main_module_handler.js │ │ └── main_module_handler.out │ ├── module_types │ │ ├── module_types.out │ │ ├── module_types.ts │ │ ├── test.bin │ │ ├── test.bin.ts │ │ ├── test.json │ │ ├── test.txt │ │ └── test.txt.ts │ ├── pending_unref_op_tla │ │ ├── pending_unref_op_tla.out │ │ └── pending_unref_op_tla.ts │ ├── smoke_test │ │ ├── smoke_test.out │ │ └── smoke_test.ts │ ├── timer_many │ │ ├── timer_many.out │ │ └── timer_many.ts │ ├── timer_ref │ │ ├── timer_ref.out │ │ └── timer_ref.ts │ ├── timer_ref_and_cancel │ │ ├── timer_ref_and_cancel.out │ │ └── timer_ref_and_cancel.ts │ ├── ts_types │ │ ├── decorator.ts │ │ ├── ts_types.out │ │ ├── ts_types.ts │ │ └── which.ts │ ├── user_breaks_promise_constructor │ │ ├── user_breaks_promise_constructor.out │ │ └── user_breaks_promise_constructor.ts │ ├── user_breaks_promise_species │ │ ├── user_breaks_promise_species.out │ │ └── user_breaks_promise_species.ts │ ├── wasm_imports │ │ ├── add.wasm │ │ ├── add.wat │ │ ├── import_from_wasm.mjs │ │ ├── lib.mjs │ │ ├── wasm_imports.js │ │ └── wasm_imports.out │ ├── worker_spawn │ │ ├── worker.ts │ │ ├── worker_spawn.out │ │ └── worker_spawn.ts │ ├── worker_terminate │ │ ├── worker.ts │ │ ├── worker_terminate.out │ │ └── worker_terminate.ts │ └── worker_terminate_op │ │ ├── worker.ts │ │ ├── worker_terminate_op.out │ │ └── worker_terminate_op.ts ├── lib.rs ├── ops.d.ts ├── tsconfig.json └── unit │ ├── encode_decode_test.ts │ ├── error_test.ts │ ├── microtask_test.ts │ ├── ops_async_test.ts │ ├── ops_buffer_test.ts │ ├── ops_error_test.ts │ ├── resource_test.ts │ ├── serialize_deserialize_test.ts │ ├── stats_test.ts │ ├── task_test.ts │ ├── tc39_test.ts │ ├── test_test.ts │ ├── timer_test.ts │ └── type_test.ts └── tools ├── check.ts ├── copyright_checker.js ├── create_pr_for_release.ts ├── deno_core_workspace.ts ├── deps.ts ├── format.ts ├── import_map.json ├── lint.ts ├── publish_dry_run.ts └── util.js /.dprint.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript": { 3 | "deno": true 4 | }, 5 | "markdown": { 6 | "deno": true 7 | }, 8 | "json": { 9 | "deno": true 10 | }, 11 | "exec": { 12 | "cwd": "${configDir}", 13 | "commands": [{ 14 | "command": "rustfmt", 15 | "exts": ["rs"] 16 | }] 17 | }, 18 | "excludes": [ 19 | ".cargo_home", 20 | ".git", 21 | "target" 22 | ], 23 | "plugins": [ 24 | "https://plugins.dprint.dev/typescript-0.93.3.wasm", 25 | "https://plugins.dprint.dev/json-0.19.4.wasm", 26 | "https://plugins.dprint.dev/markdown-0.17.8.wasm", 27 | "https://plugins.dprint.dev/toml-0.6.3.wasm", 28 | "https://plugins.dprint.dev/exec-0.5.1.json@492414e39dea4dccc07b4af796d2f4efdb89e84bae2bd4e1e924c0cc050855bf" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Use Unix line endings in all text files. 2 | * text=auto eol=lf 3 | *.png -text 4 | *.out linguist-generated=true 5 | -------------------------------------------------------------------------------- /.github/workflows/ci-coverage/action.yml: -------------------------------------------------------------------------------- 1 | name: Coverage 2 | runs: 3 | using: "composite" 4 | steps: 5 | - name: Install cargo-llvm-cov 6 | uses: taiki-e/install-action@cargo-llvm-cov 7 | - name: Generate code coverage 8 | shell: bash 9 | run: | 10 | cargo llvm-cov --workspace --release --features "deno_core/default deno_core/include_js_files_for_snapshotting deno_core/unsafe_runtime_options deno_core/unsafe_use_unprotected_platform" --bins --tests --examples --exclude deno_ops_compile_test_runner --lcov --output-path lcov.info 11 | - name: Upload coverage to Codecov 12 | uses: codecov/codecov-action@v4 13 | with: 14 | files: lcov.info 15 | fail_ci_if_error: false 16 | token: ${{ inputs.codecov_token }} 17 | -------------------------------------------------------------------------------- /.github/workflows/ci-lint-deps/action.yml: -------------------------------------------------------------------------------- 1 | name: Lint Dependencies 2 | runs: 3 | using: "composite" 4 | steps: 5 | - name: Install Rust (nightly) 6 | uses: dtolnay/rust-toolchain@master 7 | with: 8 | toolchain: nightly-2025-02-25 9 | - name: Lint deps 10 | shell: bash 11 | run: | 12 | cargo install cargo-machete --locked 13 | cargo machete 14 | cargo install cargo-udeps@0.1.55 --locked 15 | cargo +nightly-2025-02-25 udeps 16 | -------------------------------------------------------------------------------- /.github/workflows/ci-lint/action.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | runs: 3 | using: "composite" 4 | steps: 5 | - name: Format 6 | shell: bash 7 | run: | 8 | tools/check.ts format --check 9 | - name: Lint 10 | shell: bash 11 | run: | 12 | tools/check.ts lint --check 13 | -------------------------------------------------------------------------------- /.github/workflows/ci-nop/action.yml: -------------------------------------------------------------------------------- 1 | name: No-op 2 | runs: 3 | using: "composite" 4 | steps: 5 | - name: No-op 6 | shell: bash 7 | run: echo 'Doing nothing (intentionally)!' 8 | -------------------------------------------------------------------------------- /.github/workflows/ci-publish/action.yml: -------------------------------------------------------------------------------- 1 | name: Publish workflow 2 | runs: 3 | using: "composite" 4 | steps: 5 | - name: Cargo publish 6 | shell: bash 7 | run: | 8 | for package in serde_v8 deno_ops deno_core; do 9 | cargo publish -p $package 10 | done 11 | - name: Get tag version 12 | shell: bash 13 | id: get_tag_version 14 | run: echo TAG_VERSION=${GITHUB_REF/refs\/tags\//} >> "$GITHUB_OUTPUT" 15 | -------------------------------------------------------------------------------- /.github/workflows/ci-test-miri/action.yml: -------------------------------------------------------------------------------- 1 | name: Test workflow 2 | runs: 3 | using: "composite" 4 | steps: 5 | - name: Install Rust (nightly) 6 | uses: dtolnay/rust-toolchain@master 7 | with: 8 | toolchain: nightly-2025-01-02 9 | - name: Cargo test (miri) 10 | shell: bash 11 | run: | 12 | # Install and run miri tests 13 | cargo clean 14 | rustup component add --toolchain nightly-2025-01-02 miri 15 | # This somehow prints errors in CI that don't show up locally 16 | RUSTFLAGS=-Awarnings cargo +nightly-2025-01-02 miri test -p deno_core 17 | -------------------------------------------------------------------------------- /.github/workflows/ci-test-ops/action.yml: -------------------------------------------------------------------------------- 1 | name: Test workflow 2 | runs: 3 | using: "composite" 4 | steps: 5 | - name: Cargo test (ops) 6 | shell: bash 7 | run: |- 8 | cargo nextest run --workspace --release -p deno_ops_compile_test_runner 9 | -------------------------------------------------------------------------------- /.github/workflows/ci-test-publish/action.yml: -------------------------------------------------------------------------------- 1 | name: Test publish 2 | runs: 3 | using: "composite" 4 | steps: 5 | - name: Cargo publish (dry-run) 6 | shell: bash 7 | env: 8 | CARGO_REGISTRIES_UPSTREAM_INDEX: sparse+http://localhost:8000/api/v1/crates/ 9 | CARGO_REGISTRIES_UPSTREAM_TOKEN: Zy9HhJ02RJmg0GCrgLfaCVfU6IwDfhXD 10 | # This should match our bumped-up crates.io limits 11 | KELLNR_REGISTRY__MAX_CRATE_SIZE: 10 12 | run: | 13 | curl -L --output kellnr-latest.zip "https://github.com/kellnr/kellnr/releases/download/v5.1.1/kellnr-x86_64-unknown-linux-gnu.zip" 14 | unzip kellnr-latest.zip -d ./kellnr 15 | (cd ./kellnr && ./kellnr) & 16 | sleep 1 17 | tools/publish_dry_run.ts 18 | -------------------------------------------------------------------------------- /.github/workflows/ci-test-valgrind/action.yml: -------------------------------------------------------------------------------- 1 | name: Test workflow 2 | runs: 3 | using: "composite" 4 | steps: 5 | - name: Install valgrind 6 | shell: bash 7 | run: | 8 | # Installing packages 9 | sudo rm /var/lib/man-db/auto-update || true 10 | sudo apt-get update && sudo apt-get install -y --no-install-recommends valgrind 11 | - name: Cargo test (valgrind) 12 | shell: bash 13 | run: | 14 | CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER=" 15 | valgrind --error-exitcode=1 --leak-check=no 16 | --suppressions=/home/runner/work/deno_core/deno_core/.github/workflows/ci-test-valgrind/suppressions.txt 17 | --gen-suppressions=all" \ 18 | cargo nextest run -p deno_core -p deno_core_testing -p serde_v8 --release 19 | -------------------------------------------------------------------------------- /.github/workflows/ci-test/action.yml: -------------------------------------------------------------------------------- 1 | name: Test workflow 2 | runs: 3 | using: "composite" 4 | steps: 5 | - name: Cargo test 6 | shell: bash 7 | run: |- 8 | cargo nextest run --workspace --release --features "deno_core/default deno_core/include_js_files_for_snapshotting deno_core/unsafe_runtime_options deno_core/unsafe_use_unprotected_platform" --tests --examples --exclude deno_ops_compile_test_runner 9 | cargo test --doc 10 | 11 | - name: Run examples 12 | shell: bash 13 | # Only regression tests here for now. 14 | # Regression test for https://github.com/denoland/deno/pull/19615. 15 | run: |- 16 | cargo run -p deno_core --example op2 17 | cargo run -p deno_core --example op2 --features include_js_files_for_snapshotting 18 | -------------------------------------------------------------------------------- /.github/workflows/version_bump.yml: -------------------------------------------------------------------------------- 1 | name: version_bump 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | releaseKind: 7 | description: "Kind of release" 8 | default: "minor" 9 | type: choice 10 | options: 11 | - minor 12 | required: true 13 | 14 | jobs: 15 | build: 16 | name: version bump 17 | runs-on: ubuntu-22.04 18 | timeout-minutes: 30 19 | 20 | env: 21 | CARGO_TERM_COLOR: always 22 | RUST_BACKTRACE: full 23 | RUSTC_FORCE_INCREMENTAL: 1 24 | 25 | steps: 26 | - name: Configure git 27 | run: | 28 | git config --global core.symlinks true 29 | git config --global fetch.parallel 32 30 | 31 | - name: Clone repository 32 | uses: actions/checkout@v4 33 | with: 34 | token: ${{ secrets.DENOBOT_PAT }} 35 | submodules: recursive 36 | 37 | - uses: denoland/setup-deno@v1 38 | - uses: dsherret/rust-toolchain-file@v1 39 | 40 | - name: Create PR for release 41 | env: 42 | GITHUB_TOKEN: ${{ secrets.DENOBOT_PAT }} 43 | GH_WORKFLOW_ACTOR: ${{ github.actor }} 44 | run: | 45 | git remote add upstream https://github.com/denoland/deno 46 | git config user.email "${{ github.actor }}@users.noreply.github.com" 47 | git config user.name "${{ github.actor }}" 48 | deno run -A ./tools/create_pr_for_release.ts 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.orig 2 | *.pyc 3 | *.swp 4 | .env 5 | 6 | /.cargo_home/ 7 | /.idea/ 8 | /.vs/ 9 | /.vscode/ 10 | gclient_config.py_entries 11 | /target/ 12 | /std/hash/_wasm/target 13 | /tools/wpt/manifest.json 14 | /test_napi/node_modules 15 | /test_napi/build 16 | /test_napi/third_party_tests/node_modules 17 | 18 | # MacOS generated files 19 | .DS_Store 20 | .DS_Store? 21 | 22 | # Flamegraphs & profiles 23 | /flamebench*.svg 24 | /flamegraph*.svg 25 | profile.json 26 | 27 | # WPT generated cert files 28 | /tools/wpt/certs/index.txt* 29 | /tools/wpt/certs/serial* 30 | 31 | /ext/websocket/autobahn/reports 32 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | max_width = 80 2 | tab_spaces = 2 3 | edition = "2024" 4 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | [workspace] 4 | resolver = "2" 5 | members = [ 6 | "core", 7 | "core/examples/snapshot", 8 | "dcore", 9 | "ops", 10 | "ops/compile_test_runner", 11 | "serde_v8", 12 | "testing", 13 | ] 14 | 15 | [workspace.package] 16 | authors = ["the Deno authors"] 17 | edition = "2024" 18 | license = "MIT" 19 | repository = "https://github.com/denoland/deno_core" 20 | 21 | [workspace.dependencies] 22 | # Local dependencies 23 | deno_ast = { version = "=0.48.0", features = ["transpiling"] } 24 | deno_core = { version = "0.350.0", path = "./core" } 25 | deno_core_icudata = "0.74.0" 26 | deno_core_testing = { path = "./testing" } 27 | deno_error = { version = "0.6.0", features = ["serde_json", "serde", "url", "tokio"] } 28 | deno_ops = { version = "0.226.0", path = "./ops" } 29 | deno_unsync = "0.4.2" 30 | serde_v8 = { version = "0.259.0", path = "./serde_v8" } 31 | v8 = { version = "137.1.0", default-features = false } 32 | 33 | anyhow = "1" 34 | bencher = "0.1" 35 | bincode = "1" 36 | bit-set = "0.8.0" 37 | bit-vec = "0.8.0" 38 | bytes = ">=1.6.0" 39 | cooked-waker = "5" 40 | criterion = "0.5" 41 | deno_path_util = "0.4.0" 42 | fastrand = "2" 43 | futures = "0.3.31" 44 | indexmap = "2.8.0" 45 | libc = "0.2.171" 46 | num-bigint = { version = "0.4", features = ["rand"] } 47 | parking_lot = "0.12.3" 48 | paste = "1.0" 49 | percent-encoding = "2.3.1" 50 | pin-project = "1" 51 | pretty_assertions = "1.4.1" 52 | prettyplease = "0.2.31" 53 | rand = "0.8.5" 54 | rstest = "0" 55 | serde = { version = "1", features = ["derive"] } 56 | serde_bytes = "0.11" 57 | serde_json = "1" 58 | smallvec = "1.14" 59 | sourcemap = "9.1.2" 60 | static_assertions = "1" 61 | strum = { version = "0.27.1", features = ["derive"] } 62 | strum_macros = "0.27.1" 63 | testing_macros = "1.0.0" 64 | thiserror = "2" 65 | tokio = { version = "1", features = ["full"] } 66 | twox-hash = { version = "2.1.0", default-features = false, features = ["xxhash64"] } 67 | url = { version = "2", features = ["serde", "expose_internals"] } 68 | 69 | # macros 70 | proc-macro-rules = "0.4.0" 71 | proc-macro2 = "1" 72 | quote = "1" 73 | syn = { version = "2", features = ["full", "extra-traits"] } 74 | 75 | [profile.dev.package.v8] 76 | # v8 miscompiles at opt-level=0 77 | opt-level = 1 78 | 79 | # NB: the `bench` and `release` profiles must remain EXACTLY the same. 80 | [profile.release] 81 | codegen-units = 1 82 | incremental = true 83 | lto = true 84 | opt-level = 'z' # Optimize for size 85 | 86 | # Build release with debug symbols: cargo build --profile=release-with-debug 87 | [profile.release-with-debug] 88 | inherits = "release" 89 | debug = true 90 | 91 | # NB: the `bench` and `release` profiles must remain EXACTLY the same. 92 | [profile.bench] 93 | codegen-units = 1 94 | incremental = true 95 | lto = true 96 | opt-level = 'z' # Optimize for size 97 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright 2018-2025 the Deno authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deno Core 2 | 3 | [![Twitter badge][]][Twitter link] [![Discord badge][]][Discord link] 4 | [![YouTube badge][]][Youtube link] 5 | 6 | the Deno mascot dinosaur standing in the rain 7 | 8 | The core engine at the heart of [Deno](https://deno.com/runtime). 9 | 10 | ### Contributing 11 | 12 | We appreciate your help! 13 | 14 | To contribute, please read our 15 | [contributing instructions](https://docs.deno.com/runtime/manual/references/contributing). 16 | 17 | [Twitter badge]: https://img.shields.io/twitter/follow/deno_land.svg?style=social&label=Follow 18 | [Twitter link]: https://twitter.com/intent/follow?screen_name=deno_land 19 | [YouTube badge]: https://img.shields.io/youtube/channel/subscribers/UCqC2G2M-rg4fzg1esKFLFIw?style=social 20 | [YouTube link]: https://www.youtube.com/@deno_land 21 | [Discord badge]: https://img.shields.io/discord/684898665143206084?logo=discord&style=social 22 | [Discord link]: https://discord.gg/deno 23 | -------------------------------------------------------------------------------- /core/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | [package] 4 | name = "deno_core" 5 | version = "0.350.0" 6 | authors.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme = "README.md" 10 | repository.workspace = true 11 | description = "A modern JavaScript/TypeScript runtime built with V8, Rust, and Tokio" 12 | 13 | [lib] 14 | path = "lib.rs" 15 | 16 | [features] 17 | default = ["include_icu_data", "v8_use_custom_libcxx"] 18 | include_icu_data = ["deno_core_icudata"] 19 | v8_use_custom_libcxx = ["v8/use_custom_libcxx"] 20 | v8_enable_pointer_compression = ["v8/v8_enable_pointer_compression"] 21 | include_js_files_for_snapshotting = [] 22 | unsafe_runtime_options = [] 23 | unsafe_use_unprotected_platform = [] 24 | snapshot_flags_eager_parse = [] 25 | 26 | [dependencies] 27 | anyhow.workspace = true 28 | az = "1.2.1" 29 | bincode.workspace = true 30 | bit-set.workspace = true 31 | bit-vec.workspace = true 32 | bytes.workspace = true 33 | capacity_builder = "0.5.0" 34 | cooked-waker.workspace = true 35 | deno_core_icudata = { workspace = true, optional = true } 36 | deno_error.workspace = true 37 | deno_ops.workspace = true 38 | deno_path_util.workspace = true 39 | deno_unsync.workspace = true 40 | futures.workspace = true 41 | indexmap.workspace = true 42 | libc.workspace = true 43 | parking_lot.workspace = true 44 | percent-encoding.workspace = true 45 | pin-project.workspace = true 46 | serde.workspace = true 47 | serde_json = { workspace = true, features = ["preserve_order"] } 48 | serde_v8.workspace = true 49 | smallvec.workspace = true 50 | sourcemap.workspace = true 51 | static_assertions.workspace = true 52 | thiserror.workspace = true 53 | tokio.workspace = true 54 | url.workspace = true 55 | v8.workspace = true 56 | wasm_dep_analyzer = "0.3.0" 57 | 58 | [dev-dependencies] 59 | bencher.workspace = true 60 | criterion.workspace = true 61 | deno_ast.workspace = true 62 | fastrand.workspace = true 63 | paste.workspace = true 64 | pretty_assertions.workspace = true 65 | rstest.workspace = true 66 | twox-hash.workspace = true 67 | unicycle = "0.10.2" 68 | 69 | [[bench]] 70 | name = "ops_sync" 71 | path = "benches/ops/sync.rs" 72 | harness = false 73 | required-features = ["unsafe_runtime_options"] 74 | 75 | [[bench]] 76 | name = "ops_async" 77 | path = "benches/ops/async.rs" 78 | harness = false 79 | required-features = ["unsafe_runtime_options"] 80 | 81 | [[bench]] 82 | name = "opset" 83 | path = "benches/ops/opset.rs" 84 | harness = false 85 | 86 | [[bench]] 87 | name = "arena" 88 | path = "benches/infra/arena.rs" 89 | harness = false 90 | 91 | [[bench]] 92 | name = "snapshot" 93 | path = "benches/snapshot/snapshot.rs" 94 | harness = false 95 | -------------------------------------------------------------------------------- /core/README.md: -------------------------------------------------------------------------------- 1 | # Deno Core Crate 2 | 3 | [![crates](https://img.shields.io/crates/v/deno_core.svg)](https://crates.io/crates/deno_core) 4 | [![docs](https://docs.rs/deno_core/badge.svg)](https://docs.rs/deno_core) 5 | 6 | The main dependency of this crate is 7 | [rusty_v8](https://github.com/denoland/rusty_v8), which provides the V8-Rust 8 | bindings. 9 | 10 | This Rust crate contains the essential V8 bindings for Deno's command-line 11 | interface (Deno CLI). The main abstraction here is the JsRuntime which provides 12 | a way to execute JavaScript. 13 | 14 | The JsRuntime implements an event loop abstraction for the executed code that 15 | keeps track of all pending tasks (async ops, dynamic module loads). It is user's 16 | responsibility to drive that loop by using `JsRuntime::run_event_loop` method - 17 | it must be executed in the context of Rust's future executor (eg. tokio, smol). 18 | 19 | Rust functions can be registered in JavaScript using the `deno_core::extension!` 20 | macro. A conventional way to write ops is using the 21 | [`deno_ops`](../ops/README.md) crate. 22 | 23 | Documentation for this crate is thin at the moment. Please see 24 | [hello_world.rs](./examples/hello_world.rs) and 25 | [eval_js_value.rs](./examples/eval_js_value.rs) as examples of usage. 26 | 27 | TypeScript support and lots of other functionality are not available at this 28 | layer. See the [CLI](https://github.com/denoland/deno/tree/main/cli) for that. 29 | -------------------------------------------------------------------------------- /core/arena/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | mod raw_arena; 4 | mod shared_arena; 5 | mod shared_atomic_arena; 6 | mod unique_arena; 7 | 8 | use std::alloc::Layout; 9 | use std::alloc::handle_alloc_error; 10 | use std::ptr::NonNull; 11 | 12 | pub use raw_arena::*; 13 | pub use shared_arena::*; 14 | pub use shared_atomic_arena::*; 15 | pub use unique_arena::*; 16 | 17 | const unsafe fn ptr_byte_add( 18 | ptr: NonNull, 19 | offset: usize, 20 | ) -> NonNull { 21 | unsafe { NonNull::new_unchecked((ptr.as_ptr() as *mut u8).add(offset) as _) } 22 | } 23 | 24 | const unsafe fn ptr_byte_sub( 25 | ptr: NonNull, 26 | offset: usize, 27 | ) -> NonNull { 28 | unsafe { NonNull::new_unchecked((ptr.as_ptr() as *mut u8).sub(offset) as _) } 29 | } 30 | 31 | #[inline(always)] 32 | fn alloc_layout(layout: Layout) -> NonNull { 33 | // Layout of size zero is UB 34 | assert!(std::mem::size_of::() > 0); 35 | let alloc = unsafe { std::alloc::alloc(layout) } as *mut _; 36 | let Some(alloc) = NonNull::new(alloc) else { 37 | handle_alloc_error(layout); 38 | }; 39 | alloc 40 | } 41 | 42 | #[inline(always)] 43 | fn alloc() -> NonNull { 44 | // Layout of size zero is UB 45 | assert!(std::mem::size_of::() > 0); 46 | let alloc = unsafe { std::alloc::alloc(Layout::new::()) } as *mut _; 47 | let Some(alloc) = NonNull::new(alloc) else { 48 | handle_alloc_error(Layout::new::()); 49 | }; 50 | alloc 51 | } 52 | -------------------------------------------------------------------------------- /core/benches/ops/async_harness.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // deno-lint-ignore-file no-unused-vars, prefer-const, require-await 3 | 4 | // This harness is dynamically generated for each individual bench run. 5 | async function run() { 6 | const LARGE_STRING_1000000 = "*".repeat(1000000); 7 | const LARGE_STRING_1000 = "*".repeat(1000); 8 | const LARGE_STRING_UTF8_1000000 = "\u1000".repeat(1000000); 9 | const LARGE_STRING_UTF8_1000 = "\u1000".repeat(1000); 10 | const BUFFER = new Uint8Array(1024); 11 | const ARRAYBUFFER = new ArrayBuffer(1024); 12 | const { __OP__: op } = Deno.core.ops; 13 | const { op_make_external } = Deno.core.ops; 14 | const EXTERNAL = op_make_external(); 15 | 16 | // TODO(mmastrac): Because of current v8 limitations, these ops are not always fast unless we do this. 17 | // The reason is not entirely clear. 18 | function __OP__(__ARGS__) { 19 | return op(__ARGS__); 20 | } 21 | 22 | let accum = 0; 23 | let __index__ = 0; 24 | __PERCENT__PrepareFunctionForOptimization(__OP__); 25 | __CALL__; 26 | __PERCENT__OptimizeFunctionOnNextCall(__OP__); 27 | __CALL__; 28 | 29 | async function bench() { 30 | let accum = 0; 31 | for (let __index__ = 0; __index__ < __COUNT__; __index__++) __CALL__; 32 | return accum; 33 | } 34 | 35 | __PERCENT__PrepareFunctionForOptimization(bench); 36 | await bench(); 37 | __PERCENT__OptimizeFunctionOnNextCall(bench); 38 | await bench(); 39 | 40 | return bench; 41 | } 42 | -------------------------------------------------------------------------------- /core/benches/ops/sync_harness.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // deno-lint-ignore-file no-unused-vars, prefer-const 3 | 4 | // This harness is dynamically generated for each individual bench run. 5 | const LARGE_STRING_1000000 = "*".repeat(1000000); 6 | const LARGE_STRING_1000 = "*".repeat(1000); 7 | const LARGE_STRING_UTF8_1000000 = "\u1000".repeat(1000000); 8 | const LARGE_STRING_UTF8_1000 = "\u1000".repeat(1000); 9 | const BUFFER = new Uint8Array(1024); 10 | const ARRAYBUFFER = new ArrayBuffer(1024); 11 | const { __OP__: op } = Deno.core.ops; 12 | const { op_make_external } = Deno.core.ops; 13 | const EXTERNAL = op_make_external(); 14 | 15 | // TODO(mmastrac): Because of current v8 limitations, these ops are not always fast unless we do this. 16 | // The reason is not entirely clear. 17 | function __OP__(__ARGS__) { 18 | return op(__ARGS__); 19 | } 20 | 21 | let accum = __INIT__; 22 | let __index__ = 0; 23 | __PERCENT__PrepareFunctionForOptimization(__OP__); 24 | __CALL__; 25 | __PERCENT__OptimizeFunctionOnNextCall(__OP__); 26 | __CALL__; 27 | 28 | function bench() { 29 | let accum = __INIT__; 30 | for (let __index__ = 0; __index__ < __COUNT__; __index__++) __CALL__; 31 | return accum; 32 | } 33 | __PERCENT__PrepareFunctionForOptimization(bench); 34 | bench(); 35 | __PERCENT__OptimizeFunctionOnNextCall(bench); 36 | bench(); 37 | -------------------------------------------------------------------------------- /core/benches/snapshot/file.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import * as ops from "ext:core/ops"; 3 | 4 | export function unused() { 5 | return "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; 6 | } 7 | 8 | export function unused2() { 9 | return Object.keys(ops).length; 10 | } 11 | -------------------------------------------------------------------------------- /core/benches/snapshot/file2.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | export function ok() {} 3 | -------------------------------------------------------------------------------- /core/examples/disable_ops.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | //! This example shows you how to define ops in Rust and then call them from 3 | //! JavaScript. 4 | 5 | use deno_core::Extension; 6 | use deno_core::JsRuntime; 7 | use deno_core::RuntimeOptions; 8 | 9 | fn main() { 10 | let my_ext = Extension { 11 | name: "my_ext", 12 | middleware_fn: Some(Box::new(|op| match op.name { 13 | "op_print" => op.disable(), 14 | _ => op, 15 | })), 16 | ..Default::default() 17 | }; 18 | 19 | // Initialize a runtime instance 20 | let mut runtime = JsRuntime::new(RuntimeOptions { 21 | extensions: vec![my_ext], 22 | ..Default::default() 23 | }); 24 | 25 | // Deno.core.print() will now be a NOP 26 | runtime 27 | .execute_script("", r#"Deno.core.print("I'm broken")"#) 28 | .unwrap(); 29 | } 30 | -------------------------------------------------------------------------------- /core/examples/eval_js_value.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | //! This example shows you how to evaluate JavaScript expression and deserialize 3 | //! return value into a Rust object. 4 | 5 | // NOTE: 6 | // Here we are deserializing to `serde_json::Value` but you can 7 | // deserialize to any other type that implements the `Deserialize` trait. 8 | 9 | use deno_core::JsRuntime; 10 | use deno_core::RuntimeOptions; 11 | use deno_core::v8; 12 | 13 | fn main() { 14 | let mut runtime = JsRuntime::new(RuntimeOptions::default()); 15 | 16 | // Evaluate some code 17 | let code = "let a = 1+4; a*2"; 18 | let output: serde_json::Value = 19 | eval(&mut runtime, code).expect("Eval failed"); 20 | 21 | println!("Output: {output:?}"); 22 | 23 | let expected_output = serde_json::json!(10); 24 | assert_eq!(expected_output, output); 25 | } 26 | 27 | fn eval( 28 | context: &mut JsRuntime, 29 | code: &'static str, 30 | ) -> Result { 31 | let res = context.execute_script("", code); 32 | match res { 33 | Ok(global) => { 34 | let scope = &mut context.handle_scope(); 35 | let local = v8::Local::new(scope, global); 36 | // Deserialize a `v8` object into a Rust type using `serde_v8`, 37 | // in this case deserialize to a JSON `Value`. 38 | let deserialized_value = 39 | serde_v8::from_v8::(scope, local); 40 | 41 | match deserialized_value { 42 | Ok(value) => Ok(value), 43 | Err(err) => Err(format!("Cannot deserialize value: {err:?}")), 44 | } 45 | } 46 | Err(err) => Err(format!("Evaling error: {err:?}")), 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /core/examples/hello_world.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | //! This example shows you how to define ops in Rust and then call them from 3 | //! JavaScript. 4 | 5 | use deno_core::*; 6 | 7 | /// An op for summing an array of numbers. The op-layer automatically 8 | /// deserializes inputs and serializes the returned Result & value. 9 | #[op2] 10 | fn op_sum(#[serde] nums: Vec) -> Result { 11 | // Sum inputs 12 | let sum = nums.iter().fold(0.0, |a, v| a + v); 13 | // return as a Result 14 | Ok(sum) 15 | } 16 | 17 | fn main() { 18 | // Build a deno_core::Extension providing custom ops 19 | const DECL: OpDecl = op_sum(); 20 | let ext = Extension { 21 | name: "my_ext", 22 | ops: std::borrow::Cow::Borrowed(&[DECL]), 23 | ..Default::default() 24 | }; 25 | 26 | // Initialize a runtime instance 27 | let mut runtime = JsRuntime::new(RuntimeOptions { 28 | extensions: vec![ext], 29 | ..Default::default() 30 | }); 31 | 32 | // Now we see how to invoke the op we just defined. The runtime automatically 33 | // contains a Deno.core object with several functions for interacting with it. 34 | // You can find its definition in core.js. 35 | runtime 36 | .execute_script( 37 | "", 38 | r#" 39 | // Print helper function, calling Deno.core.print() 40 | function print(value) { 41 | Deno.core.print(value.toString()+"\n"); 42 | } 43 | 44 | const arr = [1, 2, 3]; 45 | print("The sum of"); 46 | print(arr); 47 | print("is"); 48 | print(Deno.core.ops.op_sum(arr)); 49 | 50 | // And incorrect usage 51 | try { 52 | print(Deno.core.ops.op_sum(0)); 53 | } catch(e) { 54 | print('Exception:'); 55 | print(e); 56 | } 57 | "#, 58 | ) 59 | .unwrap(); 60 | } 61 | -------------------------------------------------------------------------------- /core/examples/op2.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | globalThis.op2_sample = { 4 | "use_state": (f) => Deno.core.ops.op_use_state(f), 5 | }; 6 | -------------------------------------------------------------------------------- /core/examples/op2.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use anyhow::Context; 4 | use deno_core::*; 5 | use std::rc::Rc; 6 | 7 | #[op2] 8 | fn op_use_state( 9 | state: &mut OpState, 10 | #[global] callback: v8::Global, 11 | ) -> Result<(), deno_error::JsErrorBox> { 12 | state.put(callback); 13 | Ok(()) 14 | } 15 | 16 | extension!( 17 | op2_sample, 18 | ops = [op_use_state], 19 | esm_entry_point = "ext:op2_sample/op2.js", 20 | esm = [ dir "examples", "op2.js" ], 21 | docs = "A small example demonstrating op2 usage.", "Contains one op." 22 | ); 23 | 24 | fn main() -> Result<(), anyhow::Error> { 25 | let module_name = "test.js"; 26 | let module_code = " 27 | op2_sample.use_state(() => { 28 | console.log('Hello World'); 29 | }); 30 | " 31 | .to_string(); 32 | 33 | let mut js_runtime = JsRuntime::new(deno_core::RuntimeOptions { 34 | module_loader: Some(Rc::new(FsModuleLoader)), 35 | extensions: vec![op2_sample::init()], 36 | ..Default::default() 37 | }); 38 | 39 | let main_module = resolve_path( 40 | module_name, 41 | &std::env::current_dir() 42 | .context("Unable to get current working directory")?, 43 | )?; 44 | 45 | let future = async move { 46 | let mod_id = js_runtime 47 | .load_main_es_module_from_code(&main_module, module_code) 48 | .await?; 49 | 50 | let result = js_runtime.mod_evaluate(mod_id); 51 | js_runtime.run_event_loop(Default::default()).await?; 52 | result.await?; 53 | Ok::<(), anyhow::Error>(()) 54 | }; 55 | 56 | tokio::runtime::Builder::new_current_thread() 57 | .enable_all() 58 | .build() 59 | .unwrap() 60 | .block_on(future) 61 | } 62 | -------------------------------------------------------------------------------- /core/examples/snapshot/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2018-2025 the Deno authors. MIT license. 2 | # Note: Since Cargo "example" targets don't discover/use `build.rs` files, this 3 | # example is a member of the root `deno_core` workspace. That means it will 4 | # compile with `cargo build` in the root, so that this example/documentation 5 | # stays in-sync with development. 6 | 7 | [package] 8 | name = "build-your-own-js-snapshot" 9 | version = "0.1.0" 10 | build = "build.rs" 11 | edition = "2024" 12 | 13 | [dependencies] 14 | deno_core.workspace = true 15 | tokio.workspace = true 16 | 17 | [build-dependencies] 18 | deno_core.workspace = true 19 | -------------------------------------------------------------------------------- /core/examples/snapshot/README.md: -------------------------------------------------------------------------------- 1 | # Snapshot Example 2 | 3 | This example roughly follows the blog post 4 | [Roll Your Own JavaScript Runtime: Part 3][blog] to create a `JsRuntime` with an 5 | embedded startup snapshot. 6 | 7 | That blog post and the two that preceded it were no longer accurate. By 8 | including this example in the repository, it will continually be built, so it 9 | will hopefully stay up-to-date. 10 | 11 | ## Running 12 | 13 | The example can be run by changing to the `core/examples/snapshot` directory and 14 | running `cargo run`. 15 | 16 | ## Differences 17 | 18 | Differences from those blog posts: 19 | 20 | - The `create_snapshot()` API has changed in various ways. 21 | - New API features for extensions: 22 | - `#[op2]` ([read more][op2]) 23 | - `extension!(...)` macro replaces `Extension::builder()` 24 | - ESM-based extensions. 25 | 26 | Missing features vs. those blog posts: 27 | 28 | - Does not implement [TsModuleLoader], to keep this example more concise. 29 | 30 | [blog]: https://deno.com/blog/roll-your-own-javascript-runtime-pt3#creating-a-snapshot-in-buildrs 31 | [op2]: https://github.com/denoland/deno_core/tree/main/ops/op2#readme 32 | [TsModuleLoader]: https://deno.com/blog/roll-your-own-javascript-runtime-pt2#supporting-typescript 33 | -------------------------------------------------------------------------------- /core/examples/snapshot/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use deno_core::extension; 4 | use deno_core::snapshot::CreateSnapshotOptions; 5 | use deno_core::snapshot::create_snapshot; 6 | use std::env; 7 | use std::fs; 8 | use std::path::PathBuf; 9 | 10 | fn main() { 11 | extension!( 12 | runjs_extension, 13 | // Must specify an entrypoint so that our module gets loaded while snapshotting: 14 | esm_entry_point = "my:runtime", 15 | esm = [ 16 | dir "src", 17 | "my:runtime" = "runtime.js", 18 | ], 19 | ); 20 | 21 | let options = CreateSnapshotOptions { 22 | cargo_manifest_dir: env!("CARGO_MANIFEST_DIR"), 23 | startup_snapshot: None, 24 | extensions: vec![runjs_extension::init()], 25 | with_runtime_cb: None, 26 | skip_op_registration: false, 27 | extension_transpiler: None, 28 | }; 29 | let warmup_script = None; 30 | 31 | let snapshot = 32 | create_snapshot(options, warmup_script).expect("Error creating snapshot"); 33 | 34 | // Save the snapshot for use by our source code: 35 | let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); 36 | let file_path = out_dir.join("RUNJS_SNAPSHOT.bin"); 37 | fs::write(file_path, snapshot.output).expect("Failed to write snapshot"); 38 | 39 | // Let cargo know that builds depend on these files: 40 | for path in snapshot.files_loaded_during_snapshot { 41 | println!("cargo:rerun-if-changed={}", path.display()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /core/examples/snapshot/example.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // Run this script with `cargo run`. 3 | 4 | import { callRust } from "my:runtime"; 5 | 6 | callRust("Hello from example.js"); 7 | -------------------------------------------------------------------------------- /core/examples/snapshot/src/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use std::env::current_dir; 4 | use std::rc::Rc; 5 | 6 | use deno_core::FsModuleLoader; 7 | use deno_core::JsRuntime; 8 | use deno_core::PollEventLoopOptions; 9 | use deno_core::RuntimeOptions; 10 | use deno_core::anyhow; 11 | use deno_core::extension; 12 | use deno_core::op2; 13 | 14 | fn main() { 15 | let runtime = tokio::runtime::Builder::new_current_thread() 16 | .enable_all() 17 | .build() 18 | .unwrap(); 19 | if let Err(error) = runtime.block_on(run_js("./example.js")) { 20 | eprintln!("error: {}", error); 21 | } 22 | } 23 | 24 | #[op2(fast)] 25 | fn op_call_rust(#[string] value: String) { 26 | println!("Received this value from JS: {value}"); 27 | } 28 | 29 | extension!(runjs_extension, ops = [op_call_rust,],); 30 | 31 | async fn run_js(file_path: &str) -> Result<(), anyhow::Error> { 32 | let cwd = current_dir()?; 33 | let main_module = deno_core::resolve_path(file_path, &cwd)?; 34 | 35 | let mut js_runtime = JsRuntime::new(RuntimeOptions { 36 | module_loader: Some(Rc::new(FsModuleLoader)), 37 | startup_snapshot: Some(RUNTIME_SNAPSHOT), 38 | extensions: vec![runjs_extension::init()], 39 | ..Default::default() 40 | }); 41 | 42 | let mod_id = js_runtime.load_main_es_module(&main_module).await?; 43 | let result = js_runtime.mod_evaluate(mod_id); 44 | js_runtime 45 | .run_event_loop(PollEventLoopOptions::default()) 46 | .await?; 47 | result.await?; 48 | Ok(()) 49 | } 50 | 51 | // Load the snapshot generated by build.rs: 52 | static RUNTIME_SNAPSHOT: &[u8] = 53 | include_bytes!(concat!(env!("OUT_DIR"), "/RUNJS_SNAPSHOT.bin")); 54 | -------------------------------------------------------------------------------- /core/examples/snapshot/src/runtime.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | /** 3 | * This module provides the JavaScript interface atop calls to the Rust ops. 4 | */ 5 | 6 | // Minimal example, just passes arguments through to Rust: 7 | export function callRust(stringValue) { 8 | const { op_call_rust } = Deno.core.ops; 9 | op_call_rust(stringValue); 10 | } 11 | -------------------------------------------------------------------------------- /core/examples/snapshot/tests/output.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use core::str; 4 | use std::process::Command; 5 | use std::process::Output; 6 | 7 | #[test] 8 | fn check_output() -> Result<(), Box> { 9 | let output = capture_output()?; 10 | 11 | let err = str::from_utf8(&output.stderr)?; 12 | assert_eq!(err, ""); 13 | assert!(output.status.success()); 14 | 15 | let out = str::from_utf8(&output.stdout)?; 16 | assert_eq!(out, "Received this value from JS: Hello from example.js\n"); 17 | 18 | Ok(()) 19 | } 20 | 21 | /// NOTE!: This is NOT the preferred pattern to follow for testing binary crates! 22 | /// See: 23 | /// 24 | /// However, we want to keep this example simple, so we're not going to create separate main.rs & lib.rs, or 25 | /// add injectable outputs. We'll just run the binary and then capture its output. 26 | fn capture_output() -> Result { 27 | Command::new("cargo") 28 | .args([ 29 | "run", 30 | "--release", // CI runs in --release mode, so re-use its cache. 31 | "--quiet", // only capture the command's output. 32 | ]) 33 | .output() 34 | } 35 | -------------------------------------------------------------------------------- /core/examples/wasm.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | const { ops } = Deno.core; 4 | 5 | // The Wasm module is generated using assemblyscript@0.24.1 6 | // asc core/examples/wasm.ts --exportStart --initialMemory 6400 -O -o core/examples/wasm.wasm 7 | 8 | const bytes = ops.op_get_wasm_module(); 9 | 10 | const module = new WebAssembly.Module(bytes); 11 | const instance = new WebAssembly.Instance(module, { wasm: ops }); 12 | ops.op_set_wasm_mem(instance.exports.memory); 13 | 14 | instance.exports.call(); 15 | 16 | const memory = instance.exports.memory; 17 | const view = new Uint8Array(memory.buffer); 18 | 19 | if (view[0] !== 69) { 20 | throw new Error("Expected first byte to be 69"); 21 | } 22 | 23 | instance.exports.call_mem(instance.exports.memory); 24 | 25 | if (view[0] !== 68) { 26 | throw new Error("Expected first byte to be 68"); 27 | } 28 | -------------------------------------------------------------------------------- /core/examples/wasm.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | export declare function op_wasm(): void; 4 | export declare function op_wasm_mem(memory: externref): void; 5 | 6 | export function call(): void { 7 | op_wasm(); 8 | } 9 | 10 | export function call_mem(memory: externref): void { 11 | op_wasm_mem(memory); 12 | } 13 | -------------------------------------------------------------------------------- /core/examples/wasm.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/denoland/deno_core/fc1ef37491950e82d2fb2e5e426a55723e730ce1/core/examples/wasm.wasm -------------------------------------------------------------------------------- /core/flags.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | /// Pass the command line arguments to v8. 4 | /// The first element of args (which usually corresponds to the binary name) is 5 | /// ignored. 6 | /// Returns a vector of command line arguments that V8 did not understand. 7 | pub fn v8_set_flags(args: Vec) -> Vec { 8 | v8::V8::set_flags_from_command_line(args) 9 | } 10 | -------------------------------------------------------------------------------- /core/io/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | // Think of Resources as File Descriptors. They are integers that are allocated 4 | // by the privileged side of Deno which refer to various rust objects that need 5 | // to be persisted between various ops. For example, network sockets are 6 | // resources. Resources may or may not correspond to a real operating system 7 | // file descriptor (hence the different name). 8 | 9 | use std::future::Future; 10 | use std::pin::Pin; 11 | 12 | mod buffer_strategy; 13 | mod buffers; 14 | mod resource; 15 | mod resource_handle; 16 | mod resource_table; 17 | 18 | pub use buffer_strategy::AdaptiveBufferStrategy; 19 | pub use buffers::BufMutView; 20 | pub use buffers::BufView; 21 | pub use resource::Resource; 22 | pub use resource_handle::ResourceHandle; 23 | pub use resource_handle::ResourceHandleFd; 24 | pub use resource_handle::ResourceHandleSocket; 25 | pub use resource_table::ResourceError; 26 | pub use resource_table::ResourceId; 27 | pub use resource_table::ResourceTable; 28 | 29 | /// Returned by resource shutdown methods 30 | pub type AsyncResult = 31 | Pin>>>; 32 | 33 | pub enum WriteOutcome { 34 | Partial { nwritten: usize, view: BufView }, 35 | Full { nwritten: usize }, 36 | } 37 | 38 | impl WriteOutcome { 39 | pub fn nwritten(&self) -> usize { 40 | match self { 41 | WriteOutcome::Partial { nwritten, .. } => *nwritten, 42 | WriteOutcome::Full { nwritten } => *nwritten, 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /core/mod.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // Re-export fields from `globalThis.__bootstrap` so that embedders using 3 | // ES modules can import these symbols instead of capturing the bootstrap ns. 4 | const bootstrap = globalThis.__bootstrap; 5 | const { core, internals, primordials } = bootstrap; 6 | 7 | export { core, internals, primordials }; 8 | -------------------------------------------------------------------------------- /core/modules/testdata/lazy_loaded.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | export const foo = "foo"; 3 | export const bar = 123; 4 | export function blah(a) { 5 | Deno.core.print(a); 6 | } 7 | export default { foo, bar, blah }; 8 | -------------------------------------------------------------------------------- /core/rebuild_async_stubs.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env deno run --allow-read --allow-write 2 | // Copyright 2018-2025 the Deno authors. MIT license. 3 | 4 | const doNotModify = 5 | "/* DO NOT MODIFY: use rebuild_async_stubs.js to regenerate */\n"; 6 | 7 | // The template function we build op_async_N functions from 8 | function __TEMPLATE__(__ARGS_PARAM__) { 9 | const id = nextPromiseId; 10 | try { 11 | // deno-fmt-ignore 12 | const maybeResult = __OP__.call(this, __ARGS__); 13 | if (maybeResult !== undefined) { 14 | return PromiseResolve(maybeResult); 15 | } 16 | } catch (err) { 17 | __ERR__; 18 | ErrorCaptureStackTrace(err, __TEMPLATE__); 19 | return PromiseReject(err); 20 | } 21 | if (isLeakTracingEnabled) { 22 | submitLeakTrace(id); 23 | } 24 | nextPromiseId = (id + 1) & 0xffffffff; 25 | return setPromise(id); 26 | } 27 | 28 | const infraJsPath = new URL("00_infra.js", import.meta.url); 29 | const infraJs = Deno.readTextFileSync(infraJsPath); 30 | 31 | const infraPristine = infraJs.replaceAll( 32 | /\/\* BEGIN TEMPLATE ([^ ]+) \*\/.*?\/\* END TEMPLATE \*\//smg, 33 | "TEMPLATE-$1", 34 | ); 35 | const templateString = __TEMPLATE__.toString(); 36 | let asyncStubCases = "/* BEGIN TEMPLATE setUpAsyncStub */\n"; 37 | asyncStubCases += doNotModify; 38 | const vars = "abcdefghijklm"; 39 | for (let i = 0; i < 10; i++) { 40 | let args = "id"; 41 | for (let j = 0; j < i; j++) { 42 | args += `, ${vars[j]}`; 43 | } 44 | const name = `async_op_${i}`; 45 | // Replace the name and args, and add a two-space indent 46 | const func = `fn = ${templateString}` 47 | .replaceAll(/__TEMPLATE__/g, name) 48 | .replaceAll(/__ARGS__/g, args) 49 | .replaceAll(/__ARGS_PARAM__/g, args.replace(/id(, )?/, "")) 50 | .replaceAll(/__OP__/g, "originalOp") 51 | .replaceAll(/[\s]*__ERR__;/g, "") 52 | .replaceAll(/^/gm, " "); 53 | asyncStubCases += ` 54 | case ${i}: 55 | ${func}; 56 | break; 57 | `.trim() + "\n"; 58 | } 59 | asyncStubCases += "/* END TEMPLATE */"; 60 | 61 | const asyncStubIndent = 62 | infraPristine.match(/^([\t ]+)(?=TEMPLATE-setUpAsyncStub)/m)[0]; 63 | 64 | const infraOutput = infraPristine 65 | .replace( 66 | /[\t ]+TEMPLATE-setUpAsyncStub/, 67 | asyncStubCases.replaceAll(/^/gm, asyncStubIndent), 68 | ); 69 | 70 | if (Deno.args[0] === "--check") { 71 | if (infraOutput !== infraJs) { 72 | Deno.writeTextFileSync("/tmp/mismatch.txt", infraOutput); 73 | throw new Error( 74 | "Mismatch between pristine and updated source (wrote mismatch to /tmp/mismatch.txt)", 75 | ); 76 | } else { 77 | console.log("✅ Templated sections would not change"); 78 | } 79 | } else { 80 | Deno.writeTextFileSync(infraJsPath, infraOutput); 81 | } 82 | -------------------------------------------------------------------------------- /core/runtime/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | pub(crate) mod bindings; 4 | pub(crate) mod exception_state; 5 | mod jsrealm; 6 | mod jsruntime; 7 | pub mod op_driver; 8 | #[doc(hidden)] 9 | pub mod ops; 10 | pub mod ops_rust_to_v8; 11 | mod setup; 12 | mod snapshot; 13 | pub mod stats; 14 | pub mod v8_static_strings; 15 | 16 | #[cfg(all(test, not(miri)))] 17 | mod tests; 18 | 19 | pub const V8_WRAPPER_TYPE_INDEX: i32 = 0; 20 | pub const V8_WRAPPER_OBJECT_INDEX: i32 = 1; 21 | 22 | pub use jsrealm::CONTEXT_STATE_SLOT_INDEX; 23 | pub use jsrealm::ContextState; 24 | pub(crate) use jsrealm::JsRealm; 25 | pub use jsrealm::MODULE_MAP_SLOT_INDEX; 26 | pub(crate) use jsrealm::OpDriverImpl; 27 | pub(crate) use jsrealm::UnrefedOps; 28 | pub use jsruntime::CompiledWasmModuleStore; 29 | pub use jsruntime::CreateRealmOptions; 30 | pub use jsruntime::CrossIsolateStore; 31 | pub use jsruntime::ExtensionTranspiler; 32 | pub use jsruntime::ImportAssertionsSupport; 33 | pub use jsruntime::ImportAssertionsSupportCustomCallbackArgs; 34 | pub(crate) use jsruntime::InitMode; 35 | pub use jsruntime::JsRuntime; 36 | pub use jsruntime::JsRuntimeForSnapshot; 37 | pub use jsruntime::JsRuntimeState; 38 | #[cfg(test)] 39 | pub(crate) use jsruntime::NO_OF_BUILTIN_MODULES; 40 | pub use jsruntime::PollEventLoopOptions; 41 | pub use jsruntime::RuntimeOptions; 42 | pub use jsruntime::SharedArrayBufferStore; 43 | pub use snapshot::CreateSnapshotOptions; 44 | pub use snapshot::CreateSnapshotOutput; 45 | pub use snapshot::FilterFn; 46 | pub(crate) use snapshot::SnapshotDataId; 47 | pub(crate) use snapshot::SnapshotLoadDataStore; 48 | pub(crate) use snapshot::SnapshotStoreDataStore; 49 | pub(crate) use snapshot::SnapshottedData; 50 | pub use snapshot::create_snapshot; 51 | pub use snapshot::get_js_files; 52 | -------------------------------------------------------------------------------- /core/runtime/tests/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use crate::JsRuntime; 4 | use crate::RuntimeOptions; 5 | use crate::error::CoreError; 6 | use crate::op2; 7 | use deno_error::JsErrorBox; 8 | use std::future::poll_fn; 9 | use std::task::Poll; 10 | 11 | #[tokio::test] 12 | async fn test_error_builder() { 13 | #[op2(fast)] 14 | fn op_err() -> Result<(), JsErrorBox> { 15 | Err(JsErrorBox::new("DOMExceptionOperationError", "abc")) 16 | } 17 | 18 | deno_core::extension!(test_ext, ops = [op_err]); 19 | let mut runtime = JsRuntime::new(RuntimeOptions { 20 | extensions: vec![test_ext::init()], 21 | ..Default::default() 22 | }); 23 | poll_fn(move |cx| { 24 | runtime 25 | .execute_script( 26 | "error_builder_test.js", 27 | include_str!("error_builder_test.js"), 28 | ) 29 | .unwrap(); 30 | if let Poll::Ready(Err(_)) = runtime.poll_event_loop(cx, Default::default()) 31 | { 32 | unreachable!(); 33 | } 34 | Poll::Ready(()) 35 | }) 36 | .await; 37 | } 38 | 39 | #[test] 40 | fn syntax_error() { 41 | let mut runtime = JsRuntime::new(Default::default()); 42 | let src = "hocuspocus("; 43 | let r = runtime.execute_script("i.js", src); 44 | let CoreError::Js(js_error) = r.unwrap_err() else { 45 | unreachable!() 46 | }; 47 | let frame = js_error.frames.first().unwrap(); 48 | assert_eq!(frame.column_number, Some(12)); 49 | } 50 | -------------------------------------------------------------------------------- /core/runtime/tests/error_builder_test.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | const { core } = Deno; 3 | const { ops } = core; 4 | 5 | class DOMException { 6 | constructor(message, code) { 7 | this.msg = message; 8 | this.code = code; 9 | } 10 | } 11 | 12 | core.registerErrorBuilder( 13 | "DOMExceptionOperationError", 14 | function DOMExceptionOperationError(msg) { 15 | return new DOMException(msg, "OperationError"); 16 | }, 17 | ); 18 | 19 | try { 20 | ops.op_err(); 21 | throw new Error("op_err didn't throw!"); 22 | } catch (err) { 23 | if (!(err instanceof DOMException)) { 24 | throw new Error("err not DOMException"); 25 | } 26 | if (err.msg !== "abc") { 27 | throw new Error("err.message is incorrect"); 28 | } 29 | if (err.code !== "OperationError") { 30 | throw new Error("err.code is incorrect"); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/runtime/tests/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use crate::CrossIsolateStore; 4 | use crate::JsRuntime; 5 | use crate::OpState; 6 | use crate::RuntimeOptions; 7 | use crate::op2; 8 | use deno_error::JsErrorBox; 9 | use serde_v8::JsBuffer; 10 | use std::cell::RefCell; 11 | use std::rc::Rc; 12 | use std::sync::Arc; 13 | use std::sync::atomic::AtomicUsize; 14 | use std::sync::atomic::Ordering; 15 | 16 | mod error; 17 | mod jsrealm; 18 | mod misc; 19 | mod ops; 20 | mod snapshot; 21 | 22 | #[derive(Copy, Clone)] 23 | pub enum Mode { 24 | Async, 25 | AsyncDeferred, 26 | AsyncZeroCopy(bool), 27 | } 28 | 29 | struct TestState { 30 | mode: Mode, 31 | dispatch_count: Arc, 32 | } 33 | 34 | #[allow(clippy::await_holding_refcell_ref)] // False positive. 35 | #[op2(async)] 36 | async fn op_test( 37 | rc_op_state: Rc>, 38 | control: u8, 39 | #[buffer] buf: Option, 40 | ) -> Result { 41 | let op_state_ = rc_op_state.borrow(); 42 | let test_state = op_state_.borrow::(); 43 | test_state.dispatch_count.fetch_add(1, Ordering::Relaxed); 44 | let mode = test_state.mode; 45 | drop(op_state_); 46 | match mode { 47 | Mode::Async => { 48 | assert_eq!(control, 42); 49 | Ok(43) 50 | } 51 | Mode::AsyncDeferred => { 52 | tokio::task::yield_now().await; 53 | assert_eq!(control, 42); 54 | Ok(43) 55 | } 56 | Mode::AsyncZeroCopy(has_buffer) => { 57 | assert_eq!(buf.is_some(), has_buffer); 58 | if let Some(buf) = buf { 59 | assert_eq!(buf.len(), 1); 60 | } 61 | Ok(43) 62 | } 63 | } 64 | } 65 | 66 | fn setup(mode: Mode) -> (JsRuntime, Arc) { 67 | let dispatch_count = Arc::new(AtomicUsize::new(0)); 68 | deno_core::extension!( 69 | test_ext, 70 | ops = [op_test], 71 | options = { 72 | mode: Mode, 73 | dispatch_count: Arc, 74 | }, 75 | state = |state, options| { 76 | state.put(TestState { 77 | mode: options.mode, 78 | dispatch_count: options.dispatch_count 79 | }) 80 | } 81 | ); 82 | let mut runtime = JsRuntime::new(RuntimeOptions { 83 | extensions: vec![test_ext::init(mode, dispatch_count.clone())], 84 | shared_array_buffer_store: Some(CrossIsolateStore::default()), 85 | ..Default::default() 86 | }); 87 | 88 | runtime 89 | .execute_script( 90 | "setup.js", 91 | r#" 92 | function assert(cond) { 93 | if (!cond) { 94 | throw Error("assert"); 95 | } 96 | } 97 | "#, 98 | ) 99 | .unwrap(); 100 | assert_eq!(dispatch_count.load(Ordering::Relaxed), 0); 101 | (runtime, dispatch_count) 102 | } 103 | -------------------------------------------------------------------------------- /core/runtime/v8_static_strings.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #[macro_export] 4 | macro_rules! v8_static_strings { 5 | ($($ident:ident = $str:literal),* $(,)?) => { 6 | $( 7 | pub static $ident: $crate::FastStaticString = $crate::ascii_str!($str); 8 | )* 9 | }; 10 | } 11 | 12 | pub use v8_static_strings; 13 | 14 | v8_static_strings!( 15 | BUILD_CUSTOM_ERROR = "buildCustomError", 16 | CALL_CONSOLE = "callConsole", 17 | CALL_SITE_EVALS = "deno_core::call_site_evals", 18 | CAUSE = "cause", 19 | CODE = "code", 20 | CONSOLE = "console", 21 | CONSTRUCTOR = "constructor", 22 | CORE = "core", 23 | DENO = "Deno", 24 | DEFAULT = "default", 25 | DIRNAME = "dirname", 26 | ERR_MODULE_NOT_FOUND = "ERR_MODULE_NOT_FOUND", 27 | ERRORS = "errors", 28 | EVENT_LOOP_TICK = "eventLoopTick", 29 | FILENAME = "filename", 30 | INSTANCE = "Instance", 31 | MAIN = "main", 32 | MESSAGE = "message", 33 | NAME = "name", 34 | OPS = "ops", 35 | RESOLVE = "resolve", 36 | SET_UP_ASYNC_STUB = "setUpAsyncStub", 37 | STACK = "stack", 38 | URL = "url", 39 | WASM_INSTANCE = "WasmInstance", 40 | WEBASSEMBLY = "WebAssembly", 41 | ESMODULE = "__esModule", 42 | ); 43 | -------------------------------------------------------------------------------- /dcore/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | [package] 4 | name = "dcore" 5 | version = "0.1.0" 6 | authors.workspace = true 7 | default-run = "dcore" 8 | edition.workspace = true 9 | license.workspace = true 10 | publish = false 11 | readme = "README.md" 12 | repository.workspace = true 13 | description = "A simple binary that builds on deno_core" 14 | 15 | [[bin]] 16 | name = "dcore" 17 | 18 | [build-dependencies] 19 | deno_core_testing.workspace = true 20 | 21 | [dependencies] 22 | anyhow.workspace = true 23 | clap = "4.5.32" 24 | deno_core.workspace = true 25 | deno_core_testing.workspace = true 26 | fastwebsockets = { version = "0.10.0", features = ["upgrade", "unstable-split"] } 27 | http = { version = "1.3" } 28 | http-body-util = { version = "0.1.3" } 29 | hyper = { version = "=1.6.0", features = ["full"] } 30 | hyper-util = { version = "=0.1.10", features = ["tokio", "server", "server-auto"] } 31 | serde_json = { workspace = true, features = ["preserve_order"] } 32 | tokio.workspace = true 33 | uuid = { version = "1.16.0", features = ["v4"] } 34 | -------------------------------------------------------------------------------- /dcore/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use std::env; 4 | use std::fs; 5 | use std::path::Path; 6 | 7 | fn main() { 8 | let out_dir = env::var_os("OUT_DIR").unwrap(); 9 | let snapshot = deno_core_testing::create_snapshot(); 10 | let dest_path = Path::new(&out_dir).join("SNAPSHOT.bin"); 11 | fs::write(dest_path, snapshot).expect("Failed to write snapshot"); 12 | } 13 | -------------------------------------------------------------------------------- /ops/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | [package] 4 | name = "deno_ops" 5 | version = "0.226.0" 6 | authors.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme = "README.md" 10 | repository.workspace = true 11 | description = "Proc macro for writing Deno Ops" 12 | 13 | [lib] 14 | path = "./lib.rs" 15 | proc-macro = true 16 | 17 | [dependencies] 18 | indexmap.workspace = true 19 | proc-macro-rules.workspace = true 20 | proc-macro2.workspace = true 21 | quote.workspace = true 22 | stringcase = "0.4.0" 23 | strum.workspace = true 24 | strum_macros.workspace = true 25 | syn.workspace = true 26 | thiserror.workspace = true 27 | 28 | [dev-dependencies] 29 | pretty_assertions.workspace = true 30 | prettyplease.workspace = true 31 | testing_macros.workspace = true 32 | -------------------------------------------------------------------------------- /ops/README.md: -------------------------------------------------------------------------------- 1 | # deno_ops 2 | 3 | `proc_macro` for generating highly optimized V8 functions from Rust functions. 4 | 5 | ```rust,ignore 6 | use deno_core::{op2, extension}; 7 | 8 | // Declare an op. 9 | #[op2(fast)] 10 | pub fn op_add(a: i32, b: i32) -> i32 { 11 | a + b 12 | } 13 | 14 | // Register with an extension. 15 | extension!( 16 | math, 17 | ops = [op_add] 18 | ) 19 | ``` 20 | -------------------------------------------------------------------------------- /ops/compile_test_runner/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2018-2025 the Deno authors. MIT license. 2 | [package] 3 | name = "deno_ops_compile_test_runner" 4 | version = "0.2.0" 5 | authors.workspace = true 6 | edition.workspace = true 7 | license.workspace = true 8 | publish = false 9 | repository.workspace = true 10 | description = "Compile-test runner for deno_ops" 11 | 12 | [lib] 13 | path = "lib.rs" 14 | 15 | [dev-dependencies] 16 | bytes.workspace = true 17 | deno_core.workspace = true 18 | deno_error.workspace = true 19 | deno_ops.workspace = true 20 | serde.workspace = true 21 | trybuild = "1.0.104" 22 | -------------------------------------------------------------------------------- /ops/compile_test_runner/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #[macro_export] 4 | macro_rules! prelude { 5 | () => { 6 | #[allow(unused_imports)] 7 | use deno_ops::WebIDL; 8 | #[allow(unused_imports)] 9 | use deno_ops::op2; 10 | 11 | pub fn main() {} 12 | }; 13 | } 14 | 15 | #[cfg(test)] 16 | mod compile_tests { 17 | #[test] 18 | fn op2() { 19 | let t = trybuild::TestCases::new(); 20 | t.pass("../op2/test_cases/**/*.rs"); 21 | t.pass("../op2/test_cases/compiler_pass/*.rs"); 22 | t.compile_fail("../op2/test_cases_fail/**/*.rs"); 23 | } 24 | 25 | #[test] 26 | fn webidl() { 27 | let t = trybuild::TestCases::new(); 28 | t.pass("../webidl/test_cases/*.rs"); 29 | t.compile_fail("../webidl/test_cases_fail/*.rs"); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_arg_return.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(async)] 7 | pub async fn op_async(x: i32) -> i32 { 8 | x 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_arg_return_result.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(async)] 7 | pub async fn op_async(x: i32) -> std::io::Result { 8 | Ok(x) 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_cppgc.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | use deno_core::GarbageCollected; 6 | 7 | struct Wrap; 8 | 9 | impl GarbageCollected for Wrap { 10 | fn get_name(&self) -> &'static std::ffi::CStr { 11 | c"Wrap" 12 | } 13 | } 14 | 15 | #[op2(async)] 16 | #[cppgc] 17 | async fn op_make_cppgc_object() -> Wrap { 18 | Wrap 19 | } 20 | 21 | #[op2(async)] 22 | async fn op_use_cppgc_object(#[cppgc] _wrap: &Wrap) {} 23 | 24 | #[op2(async)] 25 | async fn op_use_optional_cppgc_object(#[cppgc] _wrap: Option<&Wrap>) {} 26 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_deferred.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(async(deferred), fast)] 7 | pub async fn op_async_deferred() -> std::io::Result { 8 | Ok(0) 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_jsbuffer.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::JsBuffer; 7 | 8 | #[op2(async)] 9 | #[buffer] 10 | pub async fn op_async_v8_buffer(#[buffer] buf: JsBuffer) -> JsBuffer { 11 | buf 12 | } 13 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_lazy.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(async(lazy), fast)] 7 | pub async fn op_async_lazy() -> std::io::Result { 8 | Ok(0) 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_op_metadata.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(async)] 7 | #[meta(sanitizer_details = "read from a Blob or File")] 8 | #[meta(sanitizer_fix = "awaiting the result of a Blob or File read")] 9 | async fn op_blob_read_part() { 10 | return; 11 | } 12 | 13 | #[op2(async)] 14 | #[meta( 15 | sanitizer_details = "receive a message from a BroadcastChannel", 16 | sanitizer_fix = "closing the BroadcastChannel" 17 | )] 18 | async fn op_broadcast_recv() { 19 | return; 20 | } 21 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_opstate.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::OpState; 7 | use std::cell::RefCell; 8 | use std::rc::Rc; 9 | 10 | #[op2(async)] 11 | pub async fn op_async_opstate( 12 | state: Rc>, 13 | ) -> std::io::Result { 14 | Ok(*state.borrow().borrow::()) 15 | } 16 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_precise_capture.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use std::future::Future; 7 | 8 | #[op2(async)] 9 | pub fn op_async_impl_use( 10 | x: i32, 11 | ) -> impl Future> + use<> { 12 | async move { Ok(x) } 13 | } 14 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_result.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(async)] 7 | pub async fn op_async() -> std::io::Result { 8 | Ok(0) 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_result_impl.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_error::JsErrorBox; 7 | use std::future::Future; 8 | 9 | #[op2(async)] 10 | pub fn op_async_result_impl( 11 | x: i32, 12 | ) -> Result>, JsErrorBox> { 13 | Ok(async move { Ok(x) }) 14 | } 15 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_result_smi.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | pub type ResourceId = i16; 7 | 8 | #[op2(async)] 9 | #[smi] 10 | pub async fn op_async(#[smi] rid: ResourceId) -> std::io::Result { 11 | Ok(rid as _) 12 | } 13 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_stack_trace.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(async, stack_trace)] 7 | pub async fn op_async_stack_trace() {} 8 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_v8_global.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::v8; 7 | 8 | #[op2(async)] 9 | pub async fn op_async_v8_global(#[global] _s: v8::Global) {} 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/async/async_void.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(async)] 7 | pub async fn op_async() {} 8 | -------------------------------------------------------------------------------- /ops/op2/test_cases/compiler_pass/async.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::JsBuffer; 7 | use deno_core::OpState; 8 | use deno_error::JsErrorBox; 9 | use std::cell::RefCell; 10 | use std::future::Future; 11 | use std::rc::Rc; 12 | 13 | // Collect a few examples that we'll smoke test when not running on the CI. 14 | 15 | #[op2(async)] 16 | pub async fn op_async1() {} 17 | 18 | #[op2(async)] 19 | pub async fn op_async2(x: i32) -> i32 { 20 | x 21 | } 22 | 23 | #[op2(async)] 24 | pub async fn op_async3(x: i32) -> std::io::Result { 25 | Ok(x) 26 | } 27 | 28 | #[op2(async)] 29 | pub fn op_async4(x: i32) -> Result, JsErrorBox> { 30 | Ok(async move { x }) 31 | } 32 | 33 | #[op2(async)] 34 | pub fn op_async5( 35 | x: i32, 36 | ) -> Result>, JsErrorBox> { 37 | Ok(async move { Ok(x) }) 38 | } 39 | 40 | #[op2(async)] 41 | pub async fn op_async6(x: f32) -> f32 { 42 | x 43 | } 44 | 45 | #[op2(async)] 46 | pub async fn op_async_opstate( 47 | state: Rc>, 48 | ) -> std::io::Result { 49 | Ok(*state.borrow().borrow::()) 50 | } 51 | 52 | #[op2(async)] 53 | #[buffer] 54 | pub async fn op_async_buffer(#[buffer] buf: JsBuffer) -> JsBuffer { 55 | buf 56 | } 57 | 58 | #[op2(async)] 59 | #[string] 60 | pub async fn op_async_string(#[string] s: String) -> String { 61 | s 62 | } 63 | -------------------------------------------------------------------------------- /ops/op2/test_cases/compiler_pass/sync.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::v8; 7 | 8 | // Collect a few examples that we'll smoke test when not running on the CI. 9 | 10 | #[op2(fast)] 11 | pub fn op_fast(x: u32) -> u32 { 12 | x 13 | } 14 | 15 | #[op2(fast)] 16 | fn op_buffers(#[buffer] _a: &[u8], #[buffer(copy)] _b: Vec) {} 17 | 18 | struct Something {} 19 | 20 | #[op2(fast)] 21 | fn op_state_rc( 22 | #[state] _arg: &Something, 23 | #[state] _arg_opt: Option<&Something>, 24 | ) { 25 | } 26 | 27 | #[op2(fast)] 28 | fn op_v8_1(_s: v8::Local) {} 29 | 30 | #[op2(fast)] 31 | fn op_v8_2(_s: &v8::String) {} 32 | 33 | #[op2] 34 | fn op_v8_3(#[global] _s: v8::Global) {} 35 | 36 | pub type Int16 = i16; 37 | pub type Int32 = i32; 38 | pub type Uint16 = u16; 39 | pub type Uint32 = u32; 40 | 41 | #[op2(fast)] 42 | #[smi] 43 | fn op_smi_unsigned_return( 44 | #[smi] a: Int16, 45 | #[smi] b: Int32, 46 | #[smi] c: Uint16, 47 | #[smi] d: Uint32, 48 | ) -> Uint32 { 49 | a as Uint32 + b as Uint32 + c as Uint32 + d as Uint32 50 | } 51 | 52 | #[op2(fast)] 53 | #[smi] 54 | fn op_smi_signed_return( 55 | #[smi] a: Int16, 56 | #[smi] b: Int32, 57 | #[smi] c: Uint16, 58 | #[smi] d: Uint32, 59 | ) -> Int32 { 60 | a as Int32 + b as Int32 + c as Int32 + d as Int32 61 | } 62 | 63 | #[op2(fast, stack_trace)] 64 | fn op_stack_trace(#[string] _: String) {} 65 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/add.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(fast)] 7 | fn op_add(a: u32, b: u32) -> u32 { 8 | a + b 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/add_options.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2] 7 | pub fn op_test_add_option(a: u32, b: Option) -> u32 { 8 | a + b.unwrap_or(100) 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/bigint.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(fast)] 7 | #[bigint] 8 | pub fn op_bigint() -> u64 { 9 | 0 10 | } 11 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/bool.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(fast)] 7 | pub fn op_bool(arg: bool) -> bool { 8 | arg 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/bool_result.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_error::JsErrorBox; 7 | 8 | #[op2(fast)] 9 | pub fn op_bool(arg: bool) -> Result { 10 | Ok(arg) 11 | } 12 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/buffers.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::JsBuffer; 7 | 8 | #[op2(fast)] 9 | fn op_buffers( 10 | #[buffer] _a: &[u8], 11 | #[buffer] _b: &mut [u8], 12 | #[buffer] _c: *const u8, 13 | #[buffer] _d: *mut u8, 14 | ) { 15 | } 16 | 17 | #[op2(fast)] 18 | fn op_buffers_32( 19 | #[buffer] _a: &[u32], 20 | #[buffer] _b: &mut [u32], 21 | #[buffer] _c: *const u32, 22 | #[buffer] _d: *mut u32, 23 | ) { 24 | } 25 | 26 | #[op2] 27 | fn op_buffers_option( 28 | #[buffer] _a: Option<&[u8]>, 29 | #[buffer] _b: Option, 30 | ) { 31 | } 32 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/buffers_copy.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(fast)] 7 | fn op_buffers( 8 | #[buffer(copy)] _a: Vec, 9 | #[buffer(copy)] _b: Box<[u8]>, 10 | #[buffer(copy)] _c: bytes::Bytes, 11 | ) { 12 | } 13 | 14 | #[op2(fast)] 15 | fn op_buffers_32(#[buffer(copy)] _a: Vec, #[buffer(copy)] _b: Box<[u32]>) { 16 | } 17 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/buffers_out.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::JsBuffer; 7 | 8 | #[op2] 9 | #[buffer] 10 | fn op_buffers(#[buffer] buffer: JsBuffer) -> JsBuffer { 11 | buffer 12 | } 13 | 14 | #[op2] 15 | #[buffer] 16 | fn op_buffers_option(#[buffer] buffer: Option) -> Option { 17 | buffer 18 | } 19 | 20 | #[op2] 21 | #[arraybuffer] 22 | fn op_arraybuffers(#[arraybuffer] buffer: JsBuffer) -> JsBuffer { 23 | buffer 24 | } 25 | 26 | // TODO(mmastrac): Option + Marker doesn't work yet 27 | 28 | // #[op2] 29 | // #[arraybuffer] 30 | // fn op_arraybuffers_option(#[arraybuffer] buffer: Option) -> Option { 31 | // buffer 32 | // } 33 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/cfg.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | /// This is a doc comment. 7 | #[op2(fast)] 8 | #[cfg(windows)] 9 | pub fn op_maybe_windows() -> () {} 10 | 11 | /// This is a doc comment. 12 | #[op2(fast)] 13 | #[cfg(not(windows))] 14 | pub fn op_maybe_windows() -> () {} 15 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/clippy_allow.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | /// This is a doc comment. 7 | #[op2(fast)] 8 | #[allow(clippy::some_annotation)] 9 | pub fn op_extra_annotation() -> () {} 10 | 11 | #[op2(fast)] 12 | pub fn op_clippy_internal() -> () { 13 | { 14 | #![allow(clippy::await_holding_refcell_ref)] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/cppgc_resource.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | use deno_core::GarbageCollected; 6 | 7 | struct Wrap; 8 | 9 | impl GarbageCollected for Wrap { 10 | fn get_name(&self) -> &'static std::ffi::CStr { 11 | c"Wrap" 12 | } 13 | } 14 | 15 | #[op2(fast)] 16 | fn op_cppgc_object(#[cppgc] _resource: &Wrap) {} 17 | 18 | #[op2(fast)] 19 | fn op_option_cppgc_object(#[cppgc] _resource: Option<&Wrap>) {} 20 | 21 | #[op2] 22 | #[cppgc] 23 | fn op_make_cppgc_object() -> Wrap { 24 | Wrap 25 | } 26 | 27 | #[op2(fast)] 28 | fn op_use_cppgc_object(#[cppgc] _wrap: &Wrap) {} 29 | 30 | #[op2] 31 | #[cppgc] 32 | fn op_make_cppgc_object_option() -> Option { 33 | Some(Wrap) 34 | } 35 | 36 | #[op2(fast)] 37 | fn op_use_cppgc_object_option(#[cppgc] _wrap: &Wrap) {} 38 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/doc_comment.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | /// This is a doc comment. 7 | #[op2(fast)] 8 | pub fn op_has_doc_comment() -> () {} 9 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/fast_alternative.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::v8; 7 | 8 | // Unused scope would normally make this a slow-only op 9 | #[op2(fast(op_fast))] 10 | fn op_slow(_scope: &v8::HandleScope, a: u32, b: u32) -> u32 { 11 | a + b 12 | } 13 | 14 | #[op2(fast)] 15 | fn op_fast(a: u32, b: u32) -> u32 { 16 | a + b 17 | } 18 | 19 | pub trait Trait {} 20 | 21 | // Unused scope would normally make this a slow-only op 22 | #[op2(fast(op_fast_generic::))] 23 | fn op_slow_generic(_scope: &v8::HandleScope, a: u32, b: u32) -> u32 { 24 | a + b 25 | } 26 | 27 | #[op2(fast)] 28 | fn op_fast_generic(a: u32, b: u32) -> u32 { 29 | a + b 30 | } 31 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/from_v8.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | use deno_core::FromV8; 6 | use deno_core::v8; 7 | 8 | struct Foo; 9 | 10 | impl<'a> FromV8<'a> for Foo { 11 | type Error = std::convert::Infallible; 12 | fn from_v8( 13 | _scope: &mut v8::HandleScope<'a>, 14 | _value: v8::Local<'a, v8::Value>, 15 | ) -> Result { 16 | Ok(Foo) 17 | } 18 | } 19 | 20 | #[op2] 21 | #[from_v8] 22 | pub fn op_from_v8_arg(#[from_v8] foo: Foo) { 23 | let _ = foo; 24 | } 25 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/generics.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | pub trait Trait {} 7 | 8 | #[op2(fast)] 9 | pub fn op_generics() {} 10 | 11 | #[op2(fast)] 12 | pub fn op_generics_static() {} 13 | 14 | #[op2(fast)] 15 | pub fn op_generics_static_where() 16 | where 17 | T: Trait + 'static, 18 | { 19 | } 20 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/nofast.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(nofast)] 7 | fn op_nofast(a: u32, b: u32) -> u32 { 8 | a + b 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/object_wrap.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | use deno_core::cppgc::GarbageCollected; 6 | use deno_core::v8; 7 | use deno_error::JsErrorBox; 8 | use std::cell::Cell; 9 | 10 | pub struct Foo { 11 | x: Cell, 12 | } 13 | 14 | impl GarbageCollected for Foo { 15 | fn get_name(&self) -> &'static std::ffi::CStr { 16 | c"Foo" 17 | } 18 | } 19 | 20 | fn f( 21 | _: &mut v8::HandleScope, 22 | _: &v8::FunctionCallbackArguments, 23 | ) -> Result<(), JsErrorBox> { 24 | Ok(()) 25 | } 26 | 27 | #[op2] 28 | impl Foo { 29 | #[constructor] 30 | #[cppgc] 31 | pub fn constructor(x: Option) -> Foo { 32 | Foo { 33 | x: Cell::new(x.unwrap_or_default()), 34 | } 35 | } 36 | 37 | #[fast] 38 | #[getter] 39 | pub fn x(&self) -> u32 { 40 | self.x.get() 41 | } 42 | 43 | #[fast] 44 | #[setter] 45 | pub fn x(&self, x: u32) { 46 | self.x.set(x); 47 | } 48 | 49 | #[nofast] 50 | #[required(1)] 51 | pub fn bar(&self, _v: u32) {} 52 | 53 | #[fast] 54 | pub fn zzz(&self) {} 55 | 56 | #[nofast] 57 | fn with_varargs( 58 | &self, 59 | #[varargs] _args: Option<&v8::FunctionCallbackArguments>, 60 | ) { 61 | } 62 | 63 | #[nofast] 64 | #[rename("with_RENAME")] 65 | fn with_rename(&self) {} 66 | 67 | #[nofast] 68 | #[static_method] 69 | fn do_thing() {} 70 | 71 | #[nofast] 72 | fn do_thing(&self) {} 73 | 74 | #[fast] 75 | #[validate(f)] 76 | fn validate(&self) {} 77 | } 78 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/op_state_attr.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | // Test w/ import pollution 7 | #[allow(unused)] 8 | use std::borrow::Borrow; 9 | #[allow(unused)] 10 | use std::borrow::BorrowMut; 11 | 12 | struct Something {} 13 | 14 | #[op2(fast)] 15 | fn op_state_rc( 16 | #[state] _arg: &Something, 17 | #[state] _arg_opt: Option<&Something>, 18 | ) { 19 | } 20 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/op_state_rc.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::OpState; 7 | use std::cell::RefCell; 8 | use std::rc::Rc; 9 | 10 | #[op2(fast)] 11 | fn op_state_rc(_state: Rc>) {} 12 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/op_state_ref.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::OpState; 7 | use deno_core::v8; 8 | 9 | // Test w/ import pollution 10 | #[allow(unused)] 11 | use std::borrow::Borrow; 12 | #[allow(unused)] 13 | use std::borrow::BorrowMut; 14 | 15 | #[op2(fast)] 16 | fn op_state_ref(_state: &OpState) {} 17 | 18 | #[op2(fast)] 19 | fn op_state_mut(_state: &mut OpState) {} 20 | 21 | #[op2] 22 | fn op_state_and_v8( 23 | _state: &mut OpState, 24 | #[global] _callback: v8::Global, 25 | ) { 26 | } 27 | 28 | #[op2(fast)] 29 | fn op_state_and_v8_local( 30 | _state: &mut OpState, 31 | _callback: v8::Local, 32 | ) { 33 | } 34 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/result_external.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_error::JsErrorBox; 7 | 8 | #[op2(fast)] 9 | pub fn op_external_with_result() -> Result<*mut std::ffi::c_void, JsErrorBox> { 10 | Ok(0 as _) 11 | } 12 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/result_primitive.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_error::JsErrorBox; 7 | 8 | #[op2(fast)] 9 | pub fn op_u32_with_result() -> Result { 10 | Ok(0) 11 | } 12 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/result_scope.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::v8; 7 | use deno_error::JsErrorBox; 8 | 9 | #[op2(fast)] 10 | pub fn op_void_with_result( 11 | _scope: &mut v8::HandleScope, 12 | ) -> Result<(), JsErrorBox> { 13 | Ok(()) 14 | } 15 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/result_void.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(fast)] 7 | pub fn op_void_with_result() -> std::io::Result<()> { 8 | Ok(()) 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/serde_v8.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use serde::Deserialize; 7 | use serde::Serialize; 8 | 9 | #[derive(Serialize, Deserialize)] 10 | pub struct Input {} 11 | #[derive(Serialize, Deserialize)] 12 | pub struct Output {} 13 | 14 | #[op2] 15 | #[serde] 16 | pub fn op_serde_v8(#[serde] _input: Input) -> Output { 17 | Output {} 18 | } 19 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/smi.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | pub type Int16 = i16; 7 | pub type Int32 = i32; 8 | pub type Uint16 = u16; 9 | pub type Uint32 = u32; 10 | 11 | #[op2(fast)] 12 | #[smi] 13 | fn op_smi_unsigned_return( 14 | #[smi] a: Int16, 15 | #[smi] b: Int32, 16 | #[smi] c: Uint16, 17 | #[smi] d: Uint32, 18 | ) -> Uint32 { 19 | a as Uint32 + b as Uint32 + c as Uint32 + d as Uint32 20 | } 21 | 22 | #[op2(fast)] 23 | #[smi] 24 | fn op_smi_signed_return( 25 | #[smi] a: Int16, 26 | #[smi] b: Int32, 27 | #[smi] c: Uint16, 28 | #[smi] d: Uint32, 29 | ) -> Int32 { 30 | a as Int32 + b as Int32 + c as Int32 + d as Int32 31 | } 32 | 33 | #[op2] 34 | #[smi] 35 | fn op_smi_option(#[smi] a: Option) -> Option { 36 | a 37 | } 38 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/stack_trace.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(fast, stack_trace)] 7 | fn op_stack_trace() {} 8 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/stack_trace_scope.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(fast, stack_trace)] 7 | fn op_stack_trace(#[string] _: String) {} 8 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/string_cow.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use std::borrow::Cow; 7 | 8 | #[op2(fast)] 9 | fn op_string_cow(#[string] s: Cow) -> u32 { 10 | s.len() as _ 11 | } 12 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/string_onebyte.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use std::borrow::Cow; 7 | 8 | #[op2(fast)] 9 | fn op_string_onebyte(#[string(onebyte)] s: Cow<[u8]>) -> u32 { 10 | s.len() as _ 11 | } 12 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/string_option_return.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2] 7 | #[string] 8 | pub fn op_string_return(#[string] s: Option) -> Option { 9 | s 10 | } 11 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/string_owned.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(fast)] 7 | fn op_string_owned(#[string] s: String) -> u32 { 8 | s.len() as _ 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/string_ref.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2(fast)] 7 | fn op_string_owned(#[string] s: &str) -> u32 { 8 | s.len() as _ 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/string_return.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | use std::borrow::Cow; 6 | 7 | #[op2] 8 | #[string] 9 | pub fn op_string_return() -> String { 10 | "".into() 11 | } 12 | 13 | #[op2] 14 | #[string] 15 | pub fn op_string_return_ref() -> &'static str { 16 | "" 17 | } 18 | 19 | #[op2] 20 | #[string] 21 | pub fn op_string_return_cow<'a>() -> Cow<'a, str> { 22 | "".into() 23 | } 24 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/to_v8.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | use deno_core::ToV8; 6 | use deno_core::v8; 7 | 8 | struct Foo; 9 | 10 | impl<'a> ToV8<'a> for Foo { 11 | type Error = std::convert::Infallible; 12 | fn to_v8( 13 | self, 14 | scope: &mut v8::HandleScope<'a>, 15 | ) -> Result, Self::Error> { 16 | Ok(v8::null(scope).into()) 17 | } 18 | } 19 | 20 | #[op2] 21 | #[to_v8] 22 | pub fn op_to_v8_return() -> Foo { 23 | Foo 24 | } 25 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/v8_global.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::v8; 7 | 8 | #[op2] 9 | #[global] 10 | pub fn op_global( 11 | #[global] g: v8::Global, 12 | ) -> v8::Global { 13 | g 14 | } 15 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/v8_handlescope.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::v8; 7 | 8 | #[op2] 9 | fn op_handlescope<'a>( 10 | _scope: &v8::HandleScope<'a>, 11 | _str2: v8::Local, 12 | ) -> v8::Local<'a, v8::String> { 13 | unimplemented!() 14 | } 15 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/v8_lifetime.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::v8; 7 | 8 | #[op2] 9 | pub fn op_v8_lifetime<'s>( 10 | _s: v8::Local<'s, v8::String>, 11 | ) -> v8::Local<'s, v8::String> { 12 | unimplemented!() 13 | } 14 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/v8_ref_option.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::v8; 7 | 8 | #[op2(fast)] 9 | pub fn op_v8_lifetime<'s>(_s: Option<&v8::String>, _s2: Option<&v8::String>) {} 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/v8_string.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | use deno_core::v8; 7 | 8 | #[op2] 9 | fn op_v8_string<'a>( 10 | _str1: &v8::String, 11 | _str2: v8::Local, 12 | ) -> v8::Local<'a, v8::String> { 13 | unimplemented!() 14 | } 15 | -------------------------------------------------------------------------------- /ops/op2/test_cases/sync/webidl.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[op2] 7 | fn op_webidl(#[webidl] s: String, #[webidl] _n: u32) -> u32 { 8 | s.len() as _ 9 | } 10 | -------------------------------------------------------------------------------- /ops/op2/test_cases_fail/lifetimes.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | #![deny(warnings)] 3 | deno_ops_compile_test_runner::prelude!(); 4 | use deno_core::GarbageCollected; 5 | 6 | struct Wrap; 7 | 8 | impl GarbageCollected for Wrap { 9 | fn get_name(&self) -> &'static std::ffi::CStr { 10 | c"Wrap" 11 | } 12 | } 13 | 14 | #[op2(fast)] 15 | fn op_use_cppgc_object(#[cppgc] _wrap: &'static Wrap) {} 16 | 17 | #[op2(fast)] 18 | fn op_use_buffer(#[buffer] _buffer: &'static [u8]) {} 19 | -------------------------------------------------------------------------------- /ops/op2/test_cases_fail/lifetimes.stderr: -------------------------------------------------------------------------------- 1 | error[E0597]: `arg0` does not live long enough 2 | --> $WORKSPACE/ops/op2/test_cases_fail/lifetimes.rs 3 | | 4 | | #[op2(fast)] 5 | | ^^^^^^^^^^^- 6 | | | | 7 | | | `arg0` dropped here while still borrowed 8 | | borrowed value does not live long enough 9 | | argument requires that `arg0` is borrowed for `'static` 10 | | 11 | = note: this error originates in the attribute macro `op2` (in Nightly builds, run with -Z macro-backtrace for more info) 12 | 13 | error[E0521]: borrowed data escapes outside of associated function 14 | --> $WORKSPACE/ops/op2/test_cases_fail/lifetimes.rs 15 | | 16 | | #[op2(fast)] 17 | | ^^^^^^^^^^^^ 18 | | | 19 | | `fast_api_callback_options` is a reference that is only valid in the associated function body 20 | | `fast_api_callback_options` escapes the associated function body here 21 | | lifetime `'s` defined here 22 | | argument requires that `'s` must outlive `'static` 23 | | 24 | = note: this error originates in the attribute macro `op2` (in Nightly builds, run with -Z macro-backtrace for more info) 25 | 26 | error[E0597]: `arg0_temp` does not live long enough 27 | --> $WORKSPACE/ops/op2/test_cases_fail/lifetimes.rs 28 | | 29 | | #[op2(fast)] 30 | | ^^^^^^^^^^^- 31 | | | | 32 | | | `arg0_temp` dropped here while still borrowed 33 | | borrowed value does not live long enough 34 | | argument requires that `arg0_temp` is borrowed for `'static` 35 | | 36 | = note: this error originates in the attribute macro `op2` (in Nightly builds, run with -Z macro-backtrace for more info) 37 | -------------------------------------------------------------------------------- /ops/webidl/test_cases/dict.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[derive(WebIDL)] 7 | #[webidl(dictionary)] 8 | pub struct Dict { 9 | a: u8, 10 | #[options(clamp = true)] 11 | b: Vec, 12 | #[webidl(default = Some(3))] 13 | c: Option, 14 | #[webidl(rename = "e")] 15 | d: u64, 16 | f: Option, 17 | } 18 | -------------------------------------------------------------------------------- /ops/webidl/test_cases/dict_and_enum.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[derive(WebIDL)] 7 | #[webidl(dictionary)] 8 | pub(crate) struct GPURequestAdapterOptions { 9 | pub power_preference: Option, 10 | #[webidl(default = false)] 11 | pub force_fallback_adapter: bool, 12 | } 13 | 14 | #[derive(WebIDL)] 15 | #[webidl(enum)] 16 | pub(crate) enum GPUPowerPreference { 17 | LowPower, 18 | HighPerformance, 19 | } 20 | -------------------------------------------------------------------------------- /ops/webidl/test_cases/enum.out: -------------------------------------------------------------------------------- 1 | impl<'a> ::deno_core::webidl::WebIdlConverter<'a> for Enumeration { 2 | type Options = (); 3 | fn convert<'b>( 4 | __scope: &mut ::deno_core::v8::HandleScope<'a>, 5 | __value: ::deno_core::v8::Local<'a, ::deno_core::v8::Value>, 6 | __prefix: std::borrow::Cow<'static, str>, 7 | __context: ::deno_core::webidl::ContextFn<'b>, 8 | __options: &Self::Options, 9 | ) -> Result { 10 | let Ok(str) = __value.try_cast::<::deno_core::v8::String>() else { 11 | return Err( 12 | ::deno_core::webidl::WebIdlError::new( 13 | __prefix, 14 | __context, 15 | ::deno_core::webidl::WebIdlErrorKind::ConvertToConverterType("enum"), 16 | ), 17 | ); 18 | }; 19 | match str.to_rust_string_lossy(__scope).as_str() { 20 | "foo-bar" => Ok(Self::FooBar), 21 | "baz" => Ok(Self::Baz), 22 | "hello" => Ok(Self::World), 23 | s => { 24 | Err( 25 | ::deno_core::webidl::WebIdlError::new( 26 | __prefix, 27 | __context, 28 | ::deno_core::webidl::WebIdlErrorKind::InvalidEnumVariant { 29 | converter: "Enumeration", 30 | variant: s.to_string(), 31 | }, 32 | ), 33 | ) 34 | } 35 | } 36 | } 37 | } 38 | impl Enumeration { 39 | pub fn as_str(&self) -> &'static str { 40 | match self { 41 | Self::FooBar => "foo-bar", 42 | Self::Baz => "baz", 43 | Self::World => "hello", 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ops/webidl/test_cases/enum.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[derive(WebIDL)] 7 | #[webidl(enum)] 8 | pub enum Enumeration { 9 | FooBar, 10 | Baz, 11 | #[webidl(rename = "hello")] 12 | World, 13 | } 14 | -------------------------------------------------------------------------------- /ops/webidl/test_cases_fail/enum_fields.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | #![deny(warnings)] 4 | deno_ops_compile_test_runner::prelude!(); 5 | 6 | #[derive(WebIDL)] 7 | #[webidl(enum)] 8 | pub enum Enumeration { 9 | FooBar(u32), 10 | Baz, 11 | } 12 | -------------------------------------------------------------------------------- /ops/webidl/test_cases_fail/enum_fields.stderr: -------------------------------------------------------------------------------- 1 | error: variants with fields are not allowed for enum converters 2 | --> $WORKSPACE/ops/webidl/test_cases_fail/enum_fields.rs 3 | | 4 | | FooBar(u32), 5 | | ^^^^^ 6 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.85.0" 3 | components = ["rustfmt", "clippy"] 4 | -------------------------------------------------------------------------------- /serde_v8/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | [package] 4 | name = "serde_v8" 5 | version = "0.259.0" 6 | authors.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | readme = "README.md" 10 | repository.workspace = true 11 | description = "Rust to V8 serialization and deserialization" 12 | 13 | [lib] 14 | path = "lib.rs" 15 | 16 | [dependencies] 17 | deno_error.workspace = true 18 | num-bigint.workspace = true 19 | serde.workspace = true 20 | smallvec = { workspace = true, features = ["union"] } 21 | thiserror.workspace = true 22 | v8.workspace = true 23 | 24 | [dev-dependencies] 25 | bencher.workspace = true 26 | serde_bytes.workspace = true 27 | serde_json.workspace = true 28 | serde_v8_utilities = { path = "./utilities" } 29 | 30 | [[example]] 31 | name = "basic" 32 | -------------------------------------------------------------------------------- /serde_v8/README.md: -------------------------------------------------------------------------------- 1 | # serde_v8 2 | 3 | Author: Aaron O'Mullan 4 | 5 | Serde support for encoding/decoding (rusty_)v8 values. 6 | 7 | Broadly `serde_v8` aims to provide an expressive but ~maximally efficient 8 | encoding layer to biject rust & v8/js values. It's a core component of deno's 9 | op-layer and is used to encode/decode all non-buffer values. 10 | 11 | **Original issue:** 12 | [denoland/deno#9540](https://github.com/denoland/deno/issues/9540) 13 | 14 | ## Quickstart 15 | 16 | `serde_v8` fits naturally into the serde ecosystem, so if you've already used 17 | `serde` or `serde_json`, `serde_v8`'s API should be very familiar. 18 | 19 | `serde_v8` exposes two key-functions: 20 | 21 | - `to_v8`: maps `rust->v8`, similar to `serde_json::to_string`, ... 22 | - `from_v8`: maps `v8->rust`, similar to `serde_json::from_str`, ... 23 | 24 | ## Best practices 25 | 26 | Whilst `serde_v8` is compatible with `serde_json::Value` it's important to keep 27 | in mind that `serde_json::Value` is essentially a loosely-typed value (think 28 | nested HashMaps), so when writing ops we recommend directly using rust 29 | structs/tuples or primitives, since mapping to `serde_json::Value` will add 30 | extra overhead and result in slower ops. 31 | 32 | I also recommend avoiding unnecessary "wrappers", if your op takes a 33 | single-keyed struct, consider unwrapping that as a plain value unless you plan 34 | to add fields in the near-future. 35 | 36 | Instead of returning "nothing" via `Ok(json!({}))`, change your return type to 37 | rust's unit type `()` and returning `Ok(())`, `serde_v8` will efficiently encode 38 | that as a JS `null`. 39 | 40 | ## TODO 41 | 42 | - [ ] Experiment with KeyCache to optimize struct keys 43 | - [ ] Experiment with external v8 strings 44 | - [ ] Explore using 45 | [json-stringifier.cc](https://chromium.googlesource.com/v8/v8/+/refs/heads/master/src/json/json-stringifier.cc)'s 46 | fast-paths for arrays 47 | - [ ] Improve tests to test parity with `serde_json` (should be mostly 48 | interchangeable) 49 | - [ ] Consider a `Payload` type that's deserializable by itself (holds scope & 50 | value) 51 | - [ ] Ensure we return errors instead of panicking on `.unwrap()`s 52 | -------------------------------------------------------------------------------- /serde_v8/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use std::fmt::Display; 4 | 5 | pub type Result = std::result::Result; 6 | 7 | #[derive(Debug, thiserror::Error, deno_error::JsError)] 8 | #[class(type)] 9 | #[non_exhaustive] 10 | pub enum Error { 11 | #[error("{0}")] 12 | Message(String), 13 | 14 | #[error("serde_v8 error: invalid type; expected: boolean, got: {0}")] 15 | ExpectedBoolean(&'static str), 16 | 17 | #[error("serde_v8 error: invalid type; expected: integer, got: {0}")] 18 | ExpectedInteger(&'static str), 19 | 20 | #[error("serde_v8 error: invalid type; expected: number, got: {0}")] 21 | ExpectedNumber(&'static str), 22 | 23 | #[error("serde_v8 error: invalid type; expected: string, got: {0}")] 24 | ExpectedString(&'static str), 25 | 26 | #[error("serde_v8 error: invalid type; expected: array, got: {0}")] 27 | ExpectedArray(&'static str), 28 | 29 | #[error("serde_v8 error: invalid type; expected: map, got: {0}")] 30 | ExpectedMap(&'static str), 31 | 32 | #[error("serde_v8 error: invalid type; expected: enum, got: {0}")] 33 | ExpectedEnum(&'static str), 34 | 35 | #[error("serde_v8 error: invalid type; expected: object, got: {0}")] 36 | ExpectedObject(&'static str), 37 | 38 | #[error("serde_v8 error: invalid type; expected: buffer, got: {0}")] 39 | ExpectedBuffer(&'static str), 40 | 41 | #[error("serde_v8 error: invalid type; expected: detachable, got: {0}")] 42 | ExpectedDetachable(&'static str), 43 | 44 | #[error("serde_v8 error: invalid type; expected: external, got: {0}")] 45 | ExpectedExternal(&'static str), 46 | 47 | #[error("serde_v8 error: invalid type; expected: bigint, got: {0}")] 48 | ExpectedBigInt(&'static str), 49 | 50 | #[error("serde_v8 error: invalid type, expected: utf8")] 51 | ExpectedUtf8, 52 | #[error("serde_v8 error: invalid type, expected: latin1")] 53 | ExpectedLatin1, 54 | 55 | #[error("serde_v8 error: unsupported type")] 56 | UnsupportedType, 57 | 58 | #[error("serde_v8 error: length mismatch, got: {0}, expected: {1}")] 59 | LengthMismatch(usize, usize), 60 | 61 | #[error("serde_v8 error: can't create slice from resizable ArrayBuffer")] 62 | ResizableBackingStoreNotSupported, 63 | 64 | #[error("{0}")] 65 | Custom(Box), 66 | } 67 | 68 | impl serde::ser::Error for Error { 69 | fn custom(msg: T) -> Self { 70 | Error::Message(msg.to_string()) 71 | } 72 | } 73 | 74 | impl serde::de::Error for Error { 75 | fn custom(msg: T) -> Self { 76 | Error::Message(msg.to_string()) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /serde_v8/examples/basic.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use serde::Deserialize; 4 | 5 | #[derive(Debug, Deserialize)] 6 | struct MathOp { 7 | pub a: u64, 8 | pub b: u64, 9 | pub operator: Option, 10 | } 11 | 12 | fn main() { 13 | let platform = v8::new_default_platform(0, false).make_shared(); 14 | v8::V8::initialize_platform(platform); 15 | v8::V8::initialize(); 16 | 17 | { 18 | let isolate = &mut v8::Isolate::new(v8::CreateParams::default()); 19 | let handle_scope = &mut v8::HandleScope::new(isolate); 20 | let context = v8::Context::new(handle_scope, Default::default()); 21 | let scope = &mut v8::ContextScope::new(handle_scope, context); 22 | 23 | fn exec<'s>( 24 | scope: &mut v8::HandleScope<'s>, 25 | src: &str, 26 | ) -> v8::Local<'s, v8::Value> { 27 | let code = v8::String::new(scope, src).unwrap(); 28 | let script = v8::Script::compile(scope, code, None).unwrap(); 29 | script.run(scope).unwrap() 30 | } 31 | 32 | let v = exec(scope, "32"); 33 | let x32: u64 = serde_v8::from_v8(scope, v).unwrap(); 34 | println!("x32 = {x32}"); 35 | 36 | let v = exec(scope, "({a: 1, b: 3, c: 'ignored'})"); 37 | let mop: MathOp = serde_v8::from_v8(scope, v).unwrap(); 38 | println!( 39 | "mop = {{ a: {}, b: {}, operator: {:?} }}", 40 | mop.a, mop.b, mop.operator 41 | ); 42 | 43 | let v = exec(scope, "[1,2,3,4,5]"); 44 | let arr: Vec = serde_v8::from_v8(scope, v).unwrap(); 45 | println!("arr = {arr:?}"); 46 | 47 | let v = exec(scope, "['hello', 'world']"); 48 | let hi: Vec = serde_v8::from_v8(scope, v).unwrap(); 49 | println!("hi = {hi:?}"); 50 | 51 | let v: v8::Local = v8::Number::new(scope, 12345.0).into(); 52 | let x: f64 = serde_v8::from_v8(scope, v).unwrap(); 53 | println!("x = {x}"); 54 | } 55 | 56 | // SAFETY: all isolates have been destroyed, so we can now safely let V8 clean 57 | // up its resources. 58 | unsafe { 59 | v8::V8::dispose(); 60 | } 61 | v8::V8::dispose_platform(); 62 | } 63 | -------------------------------------------------------------------------------- /serde_v8/keys.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use std::collections::HashMap; 4 | 5 | // KeyCache stores a pool struct keys mapped to v8, 6 | // to minimize allocs and speed up decoding/encoding `v8::Object`s 7 | // TODO: experiment with in from_v8/to_v8 8 | // TODO: this is unused 9 | #[allow(dead_code)] 10 | pub struct KeyCache(HashMap<&'static str, v8::Global>); 11 | 12 | // creates an optimized v8::String for a struct field 13 | // TODO: experiment with external strings 14 | // TODO: evaluate if own KeyCache is better than v8's dedupe 15 | pub fn v8_struct_key<'s>( 16 | scope: &mut v8::HandleScope<'s>, 17 | field: &'static str, 18 | ) -> v8::Local<'s, v8::String> { 19 | // Internalized v8 strings are significantly faster than "normal" v8 strings 20 | // since v8 deduplicates re-used strings minimizing new allocations 21 | // see: https://github.com/v8/v8/blob/14ac92e02cc3db38131a57e75e2392529f405f2f/include/v8.h#L3165-L3171 22 | v8::String::new_from_utf8( 23 | scope, 24 | field.as_ref(), 25 | v8::NewStringType::Internalized, 26 | ) 27 | .unwrap() 28 | 29 | // TODO: consider external strings later 30 | // right now non-deduped external strings (without KeyCache) 31 | // are slower than the deduped internalized strings by ~2.5x 32 | // since they're a new string in v8's eyes and needs to be hashed, etc... 33 | // v8::String::new_external_onebyte_static(scope, field).unwrap() 34 | } 35 | -------------------------------------------------------------------------------- /serde_v8/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | mod de; 4 | mod error; 5 | mod keys; 6 | mod magic; 7 | mod payload; 8 | mod ser; 9 | 10 | pub use de::Deserializer; 11 | pub use de::from_v8; 12 | pub use de::from_v8_cached; 13 | pub use de::to_utf8; 14 | pub use error::Error; 15 | pub use error::Result; 16 | pub use keys::KeyCache; 17 | pub use magic::ExternalPointer; 18 | pub use magic::GlobalValue; 19 | pub use magic::Value; 20 | pub use magic::any_value::AnyValue; 21 | pub use magic::bigint::BigInt; 22 | pub use magic::buffer::JsBuffer; 23 | pub use magic::buffer::ToJsBuffer; 24 | pub use magic::bytestring::ByteString; 25 | pub use magic::detached_buffer::DetachedBuffer; 26 | pub use magic::string_or_buffer::StringOrBuffer; 27 | pub use magic::u16string::U16String; 28 | pub use magic::v8slice::V8Slice; 29 | pub use magic::v8slice::V8Sliceable; 30 | pub use ser::Serializer; 31 | pub use ser::to_v8; 32 | -------------------------------------------------------------------------------- /serde_v8/magic/any_value.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use super::buffer::JsBuffer; 4 | use super::transl8::FromV8; 5 | use super::transl8::ToV8; 6 | use crate::Error; 7 | use crate::ToJsBuffer; 8 | use crate::magic::transl8::impl_magic; 9 | use num_bigint::BigInt; 10 | 11 | /// An untagged enum type that can be any of number, string, bool, bigint, or 12 | /// buffer. 13 | #[derive(Debug)] 14 | pub enum AnyValue { 15 | RustBuffer(ToJsBuffer), 16 | V8Buffer(JsBuffer), 17 | String(String), 18 | Number(f64), 19 | BigInt(BigInt), 20 | Bool(bool), 21 | } 22 | 23 | impl_magic!(AnyValue); 24 | 25 | impl ToV8 for AnyValue { 26 | fn to_v8<'a>( 27 | &self, 28 | scope: &mut v8::HandleScope<'a>, 29 | ) -> Result, crate::Error> { 30 | match self { 31 | Self::RustBuffer(buf) => crate::to_v8(scope, buf), 32 | Self::V8Buffer(_) => unreachable!(), 33 | Self::String(s) => crate::to_v8(scope, s), 34 | Self::Number(num) => crate::to_v8(scope, num), 35 | Self::BigInt(bigint) => { 36 | crate::to_v8(scope, crate::BigInt::from(bigint.clone())) 37 | } 38 | Self::Bool(b) => crate::to_v8(scope, b), 39 | } 40 | } 41 | } 42 | 43 | impl FromV8 for AnyValue { 44 | fn from_v8( 45 | scope: &mut v8::HandleScope, 46 | value: v8::Local, 47 | ) -> Result { 48 | if value.is_string() { 49 | let string = crate::from_v8(scope, value)?; 50 | Ok(AnyValue::String(string)) 51 | } else if value.is_number() { 52 | let string = crate::from_v8(scope, value)?; 53 | Ok(AnyValue::Number(string)) 54 | } else if value.is_big_int() { 55 | let bigint = crate::BigInt::from_v8(scope, value)?; 56 | Ok(AnyValue::BigInt(bigint.into())) 57 | } else if value.is_array_buffer_view() { 58 | let buf = JsBuffer::from_v8(scope, value)?; 59 | Ok(AnyValue::V8Buffer(buf)) 60 | } else if value.is_boolean() { 61 | let string = crate::from_v8(scope, value)?; 62 | Ok(AnyValue::Bool(string)) 63 | } else { 64 | Err(Error::Message( 65 | "expected string, number, bigint, ArrayBufferView, boolean".into(), 66 | )) 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /serde_v8/magic/bigint.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use std::ops::Deref; 4 | use std::ops::DerefMut; 5 | 6 | use smallvec::SmallVec; 7 | use smallvec::smallvec; 8 | 9 | use super::transl8::FromV8; 10 | use super::transl8::ToV8; 11 | use crate::Error; 12 | use crate::magic::transl8::impl_magic; 13 | 14 | #[derive(PartialEq, Eq, Clone, Debug, Default)] 15 | pub struct BigInt(num_bigint::BigInt); 16 | impl_magic!(BigInt); 17 | 18 | impl Deref for BigInt { 19 | type Target = num_bigint::BigInt; 20 | 21 | fn deref(&self) -> &Self::Target { 22 | &self.0 23 | } 24 | } 25 | 26 | impl DerefMut for BigInt { 27 | fn deref_mut(&mut self) -> &mut Self::Target { 28 | &mut self.0 29 | } 30 | } 31 | 32 | impl ToV8 for BigInt { 33 | fn to_v8<'a>( 34 | &self, 35 | scope: &mut v8::HandleScope<'a>, 36 | ) -> Result, crate::Error> { 37 | let (sign, words) = self.0.to_u64_digits(); 38 | let sign_bit = sign == num_bigint::Sign::Minus; 39 | let v = v8::BigInt::new_from_words(scope, sign_bit, &words).unwrap(); 40 | Ok(v.into()) 41 | } 42 | } 43 | 44 | impl FromV8 for BigInt { 45 | fn from_v8( 46 | _scope: &mut v8::HandleScope, 47 | value: v8::Local, 48 | ) -> Result { 49 | let v8bigint = v8::Local::::try_from(value) 50 | .map_err(|_| Error::ExpectedBigInt(value.type_repr()))?; 51 | let word_count = v8bigint.word_count(); 52 | let mut words: SmallVec<[u64; 1]> = smallvec![0u64; word_count]; 53 | let (sign_bit, _words) = v8bigint.to_words_array(&mut words); 54 | let sign = match sign_bit { 55 | true => num_bigint::Sign::Minus, 56 | false => num_bigint::Sign::Plus, 57 | }; 58 | // SAFETY: Because the alignment of u64 is 8, the alignment of u32 is 4, and 59 | // the size of u64 is 8, the size of u32 is 4, the alignment of u32 is a 60 | // factor of the alignment of u64, and the size of u32 is a factor of the 61 | // size of u64, we can safely transmute the slice of u64 to a slice of u32. 62 | let (prefix, slice, suffix) = unsafe { words.align_to::() }; 63 | assert!(prefix.is_empty()); 64 | assert!(suffix.is_empty()); 65 | assert_eq!(slice.len(), words.len() * 2); 66 | let big_int = num_bigint::BigInt::from_slice(sign, slice); 67 | Ok(Self(big_int)) 68 | } 69 | } 70 | 71 | impl From for BigInt { 72 | fn from(big_int: num_bigint::BigInt) -> Self { 73 | Self(big_int) 74 | } 75 | } 76 | 77 | impl From for num_bigint::BigInt { 78 | fn from(big_int: BigInt) -> Self { 79 | big_int.0 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /serde_v8/magic/detached_buffer.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use core::ops::Range; 4 | use std::ops::Deref; 5 | use std::ops::DerefMut; 6 | 7 | use super::transl8::FromV8; 8 | use super::transl8::ToV8; 9 | use super::v8slice::V8Slice; 10 | use super::v8slice::to_ranged_buffer; 11 | use crate::magic::transl8::impl_magic; 12 | 13 | // A buffer that detaches when deserialized from JS 14 | pub struct DetachedBuffer(V8Slice); 15 | impl_magic!(DetachedBuffer); 16 | 17 | impl AsRef<[u8]> for DetachedBuffer { 18 | fn as_ref(&self) -> &[u8] { 19 | self.0.as_ref() 20 | } 21 | } 22 | 23 | impl AsMut<[u8]> for DetachedBuffer { 24 | fn as_mut(&mut self) -> &mut [u8] { 25 | self.0.as_mut() 26 | } 27 | } 28 | 29 | impl Deref for DetachedBuffer { 30 | type Target = [u8]; 31 | fn deref(&self) -> &[u8] { 32 | self.0.deref() 33 | } 34 | } 35 | 36 | impl DerefMut for DetachedBuffer { 37 | fn deref_mut(&mut self) -> &mut [u8] { 38 | self.0.deref_mut() 39 | } 40 | } 41 | 42 | impl ToV8 for DetachedBuffer { 43 | fn to_v8<'a>( 44 | &self, 45 | scope: &mut v8::HandleScope<'a>, 46 | ) -> Result, crate::Error> { 47 | let buffer = v8::ArrayBuffer::with_backing_store(scope, &self.0.store); 48 | let Range { start, end } = self.0.range; 49 | let (off, len) = (start, end - start); 50 | let v = v8::Uint8Array::new(scope, buffer, off, len).unwrap(); 51 | Ok(v.into()) 52 | } 53 | } 54 | 55 | impl FromV8 for DetachedBuffer { 56 | fn from_v8( 57 | scope: &mut v8::HandleScope, 58 | value: v8::Local, 59 | ) -> Result { 60 | let (b, range) = to_ranged_buffer(scope, value) 61 | .map_err(|_| crate::Error::ExpectedBuffer(value.type_repr()))?; 62 | if !b.is_detachable() { 63 | return Err(crate::Error::ExpectedDetachable(value.type_repr())); 64 | } 65 | let store = b.get_backing_store(); 66 | b.detach(None); // Detach 67 | // SAFETY: We got these values from to_ranged_buffer 68 | Ok(Self(unsafe { V8Slice::from_parts(store, range) })) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /serde_v8/magic/external_pointer.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use std::ffi::c_void; 4 | 5 | use super::transl8::FromV8; 6 | use super::transl8::ToV8; 7 | use super::transl8::impl_magic; 8 | 9 | #[repr(transparent)] 10 | pub struct ExternalPointer(*mut c_void); 11 | 12 | // SAFETY: Nonblocking FFI is user controller and we must trust user to have it right. 13 | unsafe impl Send for ExternalPointer {} 14 | // SAFETY: Nonblocking FFI is user controller and we must trust user to have it right. 15 | unsafe impl Sync for ExternalPointer {} 16 | 17 | impl_magic!(ExternalPointer); 18 | 19 | impl ToV8 for ExternalPointer { 20 | fn to_v8<'a>( 21 | &self, 22 | scope: &mut v8::HandleScope<'a>, 23 | ) -> Result, crate::Error> { 24 | if self.0.is_null() { 25 | Ok(v8::null(scope).into()) 26 | } else { 27 | Ok(v8::External::new(scope, self.0).into()) 28 | } 29 | } 30 | } 31 | 32 | impl FromV8 for ExternalPointer { 33 | fn from_v8( 34 | _scope: &mut v8::HandleScope, 35 | value: v8::Local, 36 | ) -> Result { 37 | if value.is_null() { 38 | Ok(ExternalPointer(std::ptr::null_mut())) 39 | } else if let Ok(external) = v8::Local::::try_from(value) { 40 | Ok(ExternalPointer(external.value())) 41 | } else { 42 | Err(crate::Error::ExpectedExternal(value.type_repr())) 43 | } 44 | } 45 | } 46 | 47 | impl From<*mut c_void> for ExternalPointer { 48 | fn from(value: *mut c_void) -> Self { 49 | ExternalPointer(value) 50 | } 51 | } 52 | 53 | impl From<*const c_void> for ExternalPointer { 54 | fn from(value: *const c_void) -> Self { 55 | ExternalPointer(value as *mut c_void) 56 | } 57 | } 58 | 59 | impl From for *mut c_void { 60 | fn from(value: ExternalPointer) -> Self { 61 | value.0 62 | } 63 | } 64 | 65 | impl From for *const c_void { 66 | fn from(value: ExternalPointer) -> Self { 67 | value.0 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /serde_v8/magic/global_value.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use crate::magic::transl8::FromV8; 4 | use crate::magic::transl8::ToV8; 5 | use crate::magic::transl8::impl_magic; 6 | 7 | /// A wrapper around `v8::Global` to allow for passing globals transparently through a serde boundary. 8 | /// 9 | /// Serializing a `GlobalValue` creates a `v8::Local` from the global value, and deserializing creates a `v8::Global` from the local value. 10 | pub struct GlobalValue { 11 | pub v8_value: v8::Global, 12 | } 13 | impl_magic!(GlobalValue); 14 | 15 | impl From> for GlobalValue 16 | where 17 | v8::Global: Into>, 18 | { 19 | fn from(v: v8::Global) -> Self { 20 | Self { v8_value: v.into() } 21 | } 22 | } 23 | 24 | impl From for v8::Global { 25 | fn from(value: GlobalValue) -> Self { 26 | value.v8_value 27 | } 28 | } 29 | 30 | impl ToV8 for GlobalValue { 31 | fn to_v8<'a>( 32 | &self, 33 | scope: &mut v8::HandleScope<'a>, 34 | ) -> Result, crate::Error> { 35 | Ok(v8::Local::new(scope, self.v8_value.clone())) 36 | } 37 | } 38 | 39 | impl FromV8 for GlobalValue { 40 | fn from_v8( 41 | scope: &mut v8::HandleScope, 42 | value: v8::Local, 43 | ) -> Result { 44 | Ok(Self { 45 | v8_value: v8::Global::new(scope, value), 46 | }) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /serde_v8/magic/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | pub mod any_value; 4 | pub mod bigint; 5 | pub mod buffer; 6 | pub mod bytestring; 7 | pub mod detached_buffer; 8 | mod external_pointer; 9 | mod global_value; 10 | pub mod string_or_buffer; 11 | pub mod transl8; 12 | pub mod u16string; 13 | pub mod v8slice; 14 | mod value; 15 | pub use external_pointer::ExternalPointer; 16 | pub use global_value::GlobalValue; 17 | pub use value::Value; 18 | -------------------------------------------------------------------------------- /serde_v8/magic/string_or_buffer.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use super::buffer::JsBuffer; 4 | use super::transl8::FromV8; 5 | use crate::Error; 6 | use crate::magic::transl8::impl_magic; 7 | use std::ops::Deref; 8 | 9 | #[derive(Debug)] 10 | pub enum StringOrBuffer { 11 | Buffer(JsBuffer), 12 | String(String), 13 | } 14 | 15 | impl_magic!(StringOrBuffer); 16 | 17 | impl Deref for StringOrBuffer { 18 | type Target = [u8]; 19 | fn deref(&self) -> &Self::Target { 20 | match self { 21 | Self::Buffer(b) => b.as_ref(), 22 | Self::String(s) => s.as_bytes(), 23 | } 24 | } 25 | } 26 | 27 | impl<'a> TryFrom<&'a StringOrBuffer> for &'a str { 28 | type Error = std::str::Utf8Error; 29 | fn try_from(value: &'a StringOrBuffer) -> Result { 30 | match value { 31 | StringOrBuffer::String(s) => Ok(s.as_str()), 32 | StringOrBuffer::Buffer(b) => std::str::from_utf8(b.as_ref()), 33 | } 34 | } 35 | } 36 | 37 | impl FromV8 for StringOrBuffer { 38 | fn from_v8( 39 | scope: &mut v8::HandleScope, 40 | value: v8::Local, 41 | ) -> Result { 42 | match JsBuffer::from_v8(scope, value) { 43 | Ok(buf) => { 44 | return Ok(Self::Buffer(buf)); 45 | } 46 | _ => { 47 | if let Ok(s) = crate::from_v8(scope, value) { 48 | return Ok(Self::String(s)); 49 | } 50 | } 51 | } 52 | Err(Error::ExpectedBuffer(value.type_repr())) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /serde_v8/magic/u16string.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use std::ops::Deref; 4 | use std::ops::DerefMut; 5 | 6 | use crate::Error; 7 | 8 | use super::transl8::FromV8; 9 | use super::transl8::ToV8; 10 | use super::transl8::impl_magic; 11 | 12 | #[derive(PartialEq, Eq, Clone, Debug, Default)] 13 | pub struct U16String(Vec); 14 | impl_magic!(U16String); 15 | 16 | impl Deref for U16String { 17 | type Target = Vec; 18 | 19 | fn deref(&self) -> &Self::Target { 20 | &self.0 21 | } 22 | } 23 | 24 | impl DerefMut for U16String { 25 | fn deref_mut(&mut self) -> &mut Self::Target { 26 | &mut self.0 27 | } 28 | } 29 | 30 | impl AsRef<[u16]> for U16String { 31 | fn as_ref(&self) -> &[u16] { 32 | &self.0 33 | } 34 | } 35 | 36 | impl AsMut<[u16]> for U16String { 37 | fn as_mut(&mut self) -> &mut [u16] { 38 | &mut self.0 39 | } 40 | } 41 | 42 | impl From<[u16; N]> for U16String { 43 | fn from(value: [u16; N]) -> Self { 44 | Self(value.into()) 45 | } 46 | } 47 | 48 | impl From<&[u16; N]> for U16String { 49 | fn from(value: &[u16; N]) -> Self { 50 | Self(value.into()) 51 | } 52 | } 53 | 54 | impl From<&[u16]> for U16String { 55 | fn from(value: &[u16]) -> Self { 56 | Self(value.into()) 57 | } 58 | } 59 | 60 | impl From> for U16String { 61 | fn from(value: Vec) -> Self { 62 | Self(value) 63 | } 64 | } 65 | 66 | impl ToV8 for U16String { 67 | fn to_v8<'a>( 68 | &self, 69 | scope: &mut v8::HandleScope<'a>, 70 | ) -> Result, crate::Error> { 71 | let maybe_v = 72 | v8::String::new_from_two_byte(scope, self, v8::NewStringType::Normal); 73 | 74 | // 'new_from_two_byte' can return 'None' if buffer length > kMaxLength. 75 | if let Some(v) = maybe_v { 76 | Ok(v.into()) 77 | } else { 78 | Err(Error::Message(String::from( 79 | "Cannot allocate String from UTF-16: buffer exceeds maximum length.", 80 | ))) 81 | } 82 | } 83 | } 84 | 85 | impl FromV8 for U16String { 86 | fn from_v8( 87 | scope: &mut v8::HandleScope, 88 | value: v8::Local, 89 | ) -> Result { 90 | let v8str = v8::Local::::try_from(value) 91 | .map_err(|_| Error::ExpectedString(value.type_repr()))?; 92 | let len = v8str.length(); 93 | let mut buffer = Vec::with_capacity(len); 94 | #[allow(clippy::uninit_vec)] 95 | // SAFETY: we set length == capacity (see previous line), 96 | // before immediately writing into that buffer and sanity check with an assert 97 | unsafe { 98 | buffer.set_len(len); 99 | v8str.write_v2(scope, 0, &mut buffer, v8::WriteFlags::empty()); 100 | } 101 | Ok(buffer.into()) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /serde_v8/magic/value.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use crate::magic::transl8::FromV8; 4 | use crate::magic::transl8::ToV8; 5 | use crate::magic::transl8::impl_magic; 6 | use std::mem::transmute; 7 | 8 | /// serde_v8::Value is used internally to serialize/deserialize values in 9 | /// objects and arrays. This struct was exposed to user code in the past, but 10 | /// we don't want to do that anymore as it leads to inefficient usages - eg. wrapping 11 | /// a V8 object in `serde_v8::Value` and then immediately unwrapping it. 12 | // 13 | // SAFETY: caveat emptor, the rust-compiler can no longer link lifetimes to their 14 | // original scope, you must take special care in ensuring your handles don't 15 | // outlive their scope. 16 | pub struct Value<'s> { 17 | pub v8_value: v8::Local<'s, v8::Value>, 18 | } 19 | impl_magic!(Value<'_>); 20 | 21 | impl<'s, T> From> for Value<'s> 22 | where 23 | v8::Local<'s, T>: Into>, 24 | { 25 | fn from(v: v8::Local<'s, T>) -> Self { 26 | Self { v8_value: v.into() } 27 | } 28 | } 29 | 30 | impl<'s> From> for v8::Local<'s, v8::Value> { 31 | fn from(value: Value<'s>) -> Self { 32 | value.v8_value 33 | } 34 | } 35 | 36 | impl ToV8 for Value<'_> { 37 | fn to_v8<'a>( 38 | &self, 39 | _scope: &mut v8::HandleScope<'a>, 40 | ) -> Result, crate::Error> { 41 | // SAFETY: not fully safe, since lifetimes are detached from original scope 42 | Ok(unsafe { 43 | transmute::, v8::Local>(self.v8_value) 44 | }) 45 | } 46 | } 47 | 48 | impl FromV8 for Value<'_> { 49 | fn from_v8( 50 | _scope: &mut v8::HandleScope, 51 | value: v8::Local, 52 | ) -> Result { 53 | // SAFETY: not fully safe, since lifetimes are detached from original scope 54 | Ok(unsafe { transmute::(value.into()) }) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /serde_v8/payload.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | // TODO: maybe add a Payload type that holds scope & v8::Value 4 | // so it can implement Deserialize by itself 5 | 6 | // Classifies v8::Values into sub-types 7 | #[derive(Debug)] 8 | pub enum ValueType { 9 | Null, 10 | Bool, 11 | Number, 12 | BigInt, 13 | String, 14 | Array, 15 | ArrayBuffer, 16 | ArrayBufferView, 17 | Object, 18 | } 19 | 20 | impl ValueType { 21 | pub fn from_v8(v: v8::Local) -> ValueType { 22 | if v.is_boolean() { 23 | return Self::Bool; 24 | } else if v.is_number() { 25 | return Self::Number; 26 | } else if v.is_string() { 27 | return Self::String; 28 | } else if v.is_array() { 29 | return Self::Array; 30 | } else if v.is_big_int() { 31 | return Self::BigInt; 32 | } else if v.is_array_buffer() { 33 | return Self::ArrayBuffer; 34 | } else if v.is_array_buffer_view() { 35 | return Self::ArrayBufferView; 36 | } else if v.is_object() { 37 | return Self::Object; 38 | } else if v.is_null_or_undefined() { 39 | return Self::Null; 40 | } 41 | panic!("serde_v8: unknown ValueType for v8::Value") 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /serde_v8/utilities/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | [package] 4 | name = "serde_v8_utilities" 5 | version = "0.3.0" 6 | edition = "2024" 7 | publish = false 8 | 9 | [lib] 10 | path = "lib.rs" 11 | 12 | [dependencies] 13 | v8.workspace = true 14 | -------------------------------------------------------------------------------- /serde_v8/utilities/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use std::sync::Once; 4 | 5 | pub fn js_exec<'s>( 6 | scope: &mut v8::HandleScope<'s>, 7 | src: &str, 8 | ) -> v8::Local<'s, v8::Value> { 9 | let code = v8::String::new(scope, src).unwrap(); 10 | let script = v8::Script::compile(scope, code, None).unwrap(); 11 | script.run(scope).unwrap() 12 | } 13 | 14 | pub fn v8_init() { 15 | let platform = v8::new_unprotected_default_platform(0, false).make_shared(); 16 | v8::V8::initialize_platform(platform); 17 | v8::V8::initialize(); 18 | } 19 | 20 | pub fn v8_shutdown() { 21 | // SAFETY: this is safe, because all isolates have been shut down already. 22 | unsafe { 23 | v8::V8::dispose(); 24 | } 25 | v8::V8::dispose_platform(); 26 | } 27 | 28 | pub fn v8_do(f: impl FnOnce()) { 29 | static V8_INIT: Once = Once::new(); 30 | V8_INIT.call_once(|| { 31 | v8_init(); 32 | }); 33 | f(); 34 | // v8_shutdown(); 35 | } 36 | -------------------------------------------------------------------------------- /testing/Cargo.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | [package] 4 | name = "deno_core_testing" 5 | version = "0.0.0" 6 | authors.workspace = true 7 | edition.workspace = true 8 | license.workspace = true 9 | publish = false 10 | readme = "README.md" 11 | repository.workspace = true 12 | 13 | [lib] 14 | path = "./lib.rs" 15 | 16 | [dependencies] 17 | anyhow.workspace = true 18 | deno_ast.workspace = true 19 | deno_core.workspace = true 20 | deno_core.features = ["unsafe_use_unprotected_platform", "snapshot_flags_eager_parse"] 21 | deno_error.workspace = true 22 | futures.workspace = true 23 | thiserror.workspace = true 24 | tokio.workspace = true 25 | url.workspace = true 26 | 27 | [dev-dependencies] 28 | anyhow.workspace = true 29 | deno_ast.workspace = true 30 | deno_core.workspace = true 31 | deno_core.features = ["unsafe_use_unprotected_platform"] 32 | futures.workspace = true 33 | pretty_assertions.workspace = true 34 | prettyplease.workspace = true 35 | testing_macros.workspace = true 36 | tokio.workspace = true 37 | -------------------------------------------------------------------------------- /testing/README.md: -------------------------------------------------------------------------------- 1 | # Checkin: A Tiny Testing Tool for `deno_core` 2 | 3 | 4 | 5 | ## Why Checkin? 6 | 7 | Dino : _Deno_ :: Chicken : _Checkin_ 8 | 9 | Also because it _checks_ how deno_core works. Yuk yuk. 10 | 11 | ## Overview 12 | 13 | _Checkin_ is a tiny testing tool designed to exercise the functionality of 14 | `deno_core`. It implements a very small standard library which is just enough to 15 | exercise all of the components that we expose to 16 | [Deno](https://github.com/denoland/deno) without reinventing the wheel. 17 | 18 | ## Modules 19 | 20 | Modules in _Checkin_ are written in TypeScript and transpiled before loading. 21 | -------------------------------------------------------------------------------- /testing/checkin.d.ts: -------------------------------------------------------------------------------- 1 | // deno-lint-ignore-file no-explicit-any 2 | // Copyright 2018-2025 the Deno authors. MIT license. 3 | 4 | /// 5 | 6 | export type * from "../core/core.d.ts"; 7 | 8 | declare global { 9 | // Types and method unavailable in TypeScript by default. 10 | interface PromiseConstructor { 11 | withResolvers(): { 12 | promise: Promise; 13 | resolve: (value: T | PromiseLike) => void; 14 | reject: (reason?: any) => void; 15 | }; 16 | } 17 | 18 | interface ArrayBuffer { 19 | transfer(size: number): ArrayBuffer; 20 | } 21 | 22 | interface SharedArrayBuffer { 23 | transfer(size: number): SharedArrayBuffer; 24 | } 25 | 26 | namespace Deno { 27 | export function refTimer(id: number): void; 28 | export function unrefTimer(id: number): void; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /testing/checkin/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | pub(super) mod runner; 4 | -------------------------------------------------------------------------------- /testing/checkin/runner/extensions.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use crate::checkin::runner::Output; 4 | use crate::checkin::runner::TestData; 5 | use crate::checkin::runner::ops; 6 | use crate::checkin::runner::ops_async; 7 | use crate::checkin::runner::ops_buffer; 8 | use crate::checkin::runner::ops_error; 9 | use crate::checkin::runner::ops_io; 10 | use crate::checkin::runner::ops_worker; 11 | 12 | pub trait SomeType {} 13 | 14 | impl SomeType for () {} 15 | 16 | deno_core::extension!( 17 | checkin_runtime, 18 | parameters = [P: SomeType], 19 | ops = [ 20 | ops::op_log_debug, 21 | ops::op_log_info, 22 | ops::op_stats_capture, 23 | ops::op_stats_diff, 24 | ops::op_stats_dump, 25 | ops::op_stats_delete, 26 | ops::op_nop_generic

, 27 | ops_io::op_pipe_create, 28 | ops_io::op_file_open, 29 | ops_io::op_path_to_url, 30 | ops_async::op_task_submit, 31 | ops_async::op_async_yield, 32 | ops_async::op_async_barrier_create, 33 | ops_async::op_async_barrier_await, 34 | ops_async::op_async_spin_on_state, 35 | ops_async::op_async_make_cppgc_resource, 36 | ops_async::op_async_get_cppgc_resource, 37 | ops_async::op_async_never_resolves, 38 | ops_async::op_async_fake, 39 | ops_async::op_async_promise_id, 40 | ops_error::op_async_throw_error_eager, 41 | ops_error::op_async_throw_error_lazy, 42 | ops_error::op_async_throw_error_deferred, 43 | ops_error::op_error_custom_sync, 44 | ops_error::op_error_custom_with_code_sync, 45 | ops_buffer::op_v8slice_store, 46 | ops_buffer::op_v8slice_clone, 47 | ops_worker::op_worker_spawn, 48 | ops_worker::op_worker_send, 49 | ops_worker::op_worker_recv, 50 | ops_worker::op_worker_parent, 51 | ops_worker::op_worker_await_close, 52 | ops_worker::op_worker_terminate, 53 | ], 54 | objects = [ 55 | ops::DOMPointReadOnly, 56 | ops::DOMPoint, 57 | ops::TestObjectWrap, 58 | ops::TestEnumWrap 59 | ], 60 | esm_entry_point = "ext:checkin_runtime/__init.js", 61 | esm = [ 62 | dir "checkin/runtime", 63 | "__init.js", 64 | "checkin:async" = "async.ts", 65 | "checkin:console" = "console.ts", 66 | "checkin:object" = "object.ts", 67 | "checkin:error" = "error.ts", 68 | "checkin:timers" = "timers.ts", 69 | "checkin:worker" = "worker.ts", 70 | "checkin:throw" = "throw.ts", 71 | ], 72 | state = |state| { 73 | state.put(TestData::default()); 74 | state.put(Output::default()); 75 | } 76 | ); 77 | -------------------------------------------------------------------------------- /testing/checkin/runner/ops_async.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use super::Output; 4 | use super::TestData; 5 | use deno_core::GarbageCollected; 6 | use deno_core::OpState; 7 | use deno_core::V8TaskSpawner; 8 | use deno_core::op2; 9 | use deno_core::v8; 10 | use deno_error::JsErrorBox; 11 | use std::cell::RefCell; 12 | use std::future::Future; 13 | use std::future::poll_fn; 14 | use std::rc::Rc; 15 | 16 | #[op2] 17 | pub fn op_task_submit( 18 | state: &mut OpState, 19 | #[global] f: v8::Global, 20 | ) { 21 | state.borrow_mut::().spawn(move |scope| { 22 | let f = v8::Local::new(scope, f); 23 | let recv = v8::undefined(scope); 24 | f.call(scope, recv.into(), &[]); 25 | }); 26 | } 27 | 28 | #[op2(async)] 29 | pub async fn op_async_yield() { 30 | tokio::task::yield_now().await 31 | } 32 | 33 | #[op2(fast)] 34 | pub fn op_async_barrier_create( 35 | #[state] test_data: &mut TestData, 36 | #[string] name: String, 37 | count: u32, 38 | ) { 39 | let barrier = Rc::new(tokio::sync::Barrier::new(count as _)); 40 | test_data.insert(name, barrier); 41 | } 42 | 43 | #[op2(async)] 44 | pub fn op_async_barrier_await( 45 | #[state] test_data: &TestData, 46 | #[string] name: String, 47 | ) -> impl Future + use<> { 48 | let barrier: &Rc = test_data.get(name); 49 | let barrier = barrier.clone(); 50 | async move { 51 | barrier.wait().await; 52 | } 53 | } 54 | 55 | #[op2(async)] 56 | pub async fn op_async_spin_on_state(state: Rc>) { 57 | poll_fn(|cx| { 58 | // Ensure that we never get polled when the state has been emptied 59 | state.borrow().borrow::(); 60 | cx.waker().wake_by_ref(); 61 | std::task::Poll::Pending 62 | }) 63 | .await 64 | } 65 | 66 | pub struct TestResource { 67 | value: u32, 68 | } 69 | 70 | impl GarbageCollected for TestResource { 71 | fn get_name(&self) -> &'static std::ffi::CStr { 72 | c"TestResource" 73 | } 74 | } 75 | 76 | #[op2(async)] 77 | #[cppgc] 78 | pub async fn op_async_make_cppgc_resource() -> TestResource { 79 | TestResource { value: 42 } 80 | } 81 | 82 | #[op2(async)] 83 | #[smi] 84 | pub async fn op_async_get_cppgc_resource( 85 | #[cppgc] resource: &TestResource, 86 | ) -> u32 { 87 | resource.value 88 | } 89 | 90 | #[op2(async)] 91 | pub fn op_async_never_resolves() -> impl Future { 92 | std::future::pending::<()>() 93 | } 94 | 95 | #[op2(async(fake))] 96 | pub fn op_async_fake() -> Result { 97 | Ok(1) 98 | } 99 | 100 | #[op2(async, promise_id)] 101 | pub async fn op_async_promise_id(#[smi] promise_id: u32) -> u32 { 102 | promise_id 103 | } 104 | -------------------------------------------------------------------------------- /testing/checkin/runner/ops_buffer.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use deno_core::JsBuffer; 4 | use deno_core::op2; 5 | 6 | use super::TestData; 7 | 8 | #[op2] 9 | pub fn op_v8slice_store( 10 | #[state] test_data: &mut TestData, 11 | #[string] name: String, 12 | #[buffer] data: JsBuffer, 13 | ) { 14 | test_data.insert(name, data); 15 | } 16 | 17 | #[op2] 18 | #[buffer] 19 | pub fn op_v8slice_clone( 20 | #[state] test_data: &mut TestData, 21 | #[string] name: String, 22 | ) -> Vec { 23 | test_data.get::(name).to_vec() 24 | } 25 | -------------------------------------------------------------------------------- /testing/checkin/runner/ops_error.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use deno_core::op2; 4 | use deno_error::JsErrorBox; 5 | 6 | #[op2(async)] 7 | pub async fn op_async_throw_error_eager() -> Result<(), JsErrorBox> { 8 | Err(JsErrorBox::type_error("Error")) 9 | } 10 | 11 | #[op2(async(deferred), fast)] 12 | pub async fn op_async_throw_error_deferred() -> Result<(), JsErrorBox> { 13 | Err(JsErrorBox::type_error("Error")) 14 | } 15 | 16 | #[op2(async(lazy), fast)] 17 | pub async fn op_async_throw_error_lazy() -> Result<(), JsErrorBox> { 18 | Err(JsErrorBox::type_error("Error")) 19 | } 20 | 21 | #[op2(fast)] 22 | pub fn op_error_custom_sync( 23 | #[string] message: String, 24 | ) -> Result<(), JsErrorBox> { 25 | Err(JsErrorBox::new("BadResource", message)) 26 | } 27 | 28 | #[derive(Debug, thiserror::Error, deno_error::JsError)] 29 | #[class(type)] 30 | #[error("{message}")] 31 | struct MyError { 32 | message: String, 33 | #[property] 34 | code: u32, 35 | } 36 | 37 | #[op2(fast)] 38 | pub fn op_error_custom_with_code_sync( 39 | #[string] message: String, 40 | code: u32, 41 | ) -> Result<(), MyError> { 42 | Err(MyError { message, code }) 43 | } 44 | -------------------------------------------------------------------------------- /testing/checkin/runner/snapshot.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | use std::rc::Rc; 4 | 5 | use deno_core::JsRuntimeForSnapshot; 6 | use deno_core::RuntimeOptions; 7 | 8 | use super::extensions; 9 | use super::ts_module_loader::maybe_transpile_source; 10 | 11 | pub fn create_snapshot() -> Box<[u8]> { 12 | let extensions_for_snapshot = vec![extensions::checkin_runtime::init::<()>()]; 13 | 14 | let runtime_for_snapshot = JsRuntimeForSnapshot::new(RuntimeOptions { 15 | extensions: extensions_for_snapshot, 16 | extension_transpiler: Some(Rc::new(|specifier, source| { 17 | maybe_transpile_source(specifier, source) 18 | })), 19 | ..Default::default() 20 | }); 21 | 22 | runtime_for_snapshot.snapshot() 23 | } 24 | -------------------------------------------------------------------------------- /testing/checkin/runtime/__init.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import * as async from "checkin:async"; 3 | import * as console from "checkin:console"; 4 | import * as error from "checkin:error"; 5 | import * as timers from "checkin:timers"; 6 | import * as worker from "checkin:worker"; 7 | import * as throw_ from "checkin:throw"; 8 | import * as object from "checkin:object"; 9 | async; 10 | error; 11 | throw_; 12 | object; 13 | 14 | globalThis.console = console.console; 15 | globalThis.setTimeout = timers.setTimeout; 16 | globalThis.setInterval = timers.setInterval; 17 | globalThis.clearTimeout = timers.clearTimeout; 18 | globalThis.clearInterval = timers.clearInterval; 19 | globalThis.Worker = worker.Worker; 20 | Deno.core.addMainModuleHandler((module) => { 21 | if (onMainModuleCb) onMainModuleCb(module); 22 | }); 23 | let onMainModuleCb = () => {}; 24 | Reflect.defineProperty(globalThis, "onmainmodule", { 25 | set: (cb) => { 26 | onMainModuleCb = cb; 27 | }, 28 | }); 29 | Reflect.defineProperty(globalThis, "onerror", { 30 | set: (cb) => { 31 | if (cb) { 32 | Deno.core.setReportExceptionCallback((error) => { 33 | let defaultPrevented = false; 34 | cb({ 35 | error, 36 | preventDefault: () => defaultPrevented = true, 37 | }); 38 | if (!defaultPrevented) { 39 | Deno.core.reportUnhandledException(error); 40 | } 41 | }); 42 | } else { 43 | Deno.core.setReportExceptionCallback(null); 44 | } 45 | }, 46 | }); 47 | Reflect.defineProperty(globalThis, "onunhandledrejection", { 48 | set: (cb) => { 49 | if (cb) { 50 | Deno.core.setUnhandledPromiseRejectionHandler((promise, reason) => { 51 | let defaultPrevented = false; 52 | cb({ 53 | promise, 54 | reason, 55 | preventDefault: () => defaultPrevented = true, 56 | }); 57 | return defaultPrevented; 58 | }); 59 | } else { 60 | Deno.core.setUnhandledPromiseRejectionHandler(null); 61 | } 62 | }, 63 | }); 64 | Reflect.defineProperty(globalThis, "onrejectionhandled", { 65 | set: (cb) => { 66 | if (cb) { 67 | Deno.core.setHandledPromiseRejectionHandler((promise, reason) => { 68 | cb({ 69 | promise, 70 | reason, 71 | }); 72 | }); 73 | } else { 74 | Deno.core.setHandledPromiseRejectionHandler(null); 75 | } 76 | }, 77 | }); 78 | Deno.unrefTimer = timers.unrefTimer; 79 | Deno.refTimer = timers.refTimer; 80 | -------------------------------------------------------------------------------- /testing/checkin/runtime/console.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | import { op_log_debug, op_log_info } from "ext:core/ops"; 4 | import { core } from "ext:core/mod.js"; 5 | 6 | export const console = { 7 | debug(...args: string[]) { 8 | op_log_debug(core.consoleStringify(...args)); 9 | }, 10 | 11 | log(...args: string[]) { 12 | op_log_info(core.consoleStringify(...args)); 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /testing/checkin/runtime/error.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { 3 | op_async_throw_error_deferred, 4 | op_async_throw_error_eager, 5 | op_async_throw_error_lazy, 6 | op_error_custom_sync, 7 | op_error_custom_with_code_sync, 8 | } from "ext:core/ops"; 9 | 10 | export async function asyncThrow(kind: "lazy" | "eager" | "deferred") { 11 | const op = { 12 | lazy: op_async_throw_error_lazy, 13 | eager: op_async_throw_error_eager, 14 | deferred: op_async_throw_error_deferred, 15 | }[kind]; 16 | return await op(); 17 | } 18 | 19 | export function throwCustomError(message: string) { 20 | op_error_custom_sync(message); 21 | } 22 | 23 | export function throwCustomErrorWithCode(message: string, code: number) { 24 | op_error_custom_with_code_sync(message, code); 25 | } 26 | -------------------------------------------------------------------------------- /testing/checkin/runtime/object.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | import { 4 | DOMPoint, 5 | DOMPointReadOnly, 6 | TestEnumWrap, 7 | TestObjectWrap, 8 | } from "ext:core/ops"; 9 | 10 | export { DOMPoint, DOMPointReadOnly, TestEnumWrap, TestObjectWrap }; 11 | -------------------------------------------------------------------------------- /testing/checkin/runtime/testing.ts: -------------------------------------------------------------------------------- 1 | // deno-lint-ignore-file no-explicit-any 2 | // Copyright 2018-2025 the Deno authors. MIT license. 3 | 4 | const { op_test_register } = Deno.core.ops; 5 | 6 | /** 7 | * Define a sync or async test function. 8 | */ 9 | export function test(test: () => void | Promise) { 10 | op_test_register(test.name, test); 11 | } 12 | 13 | /** 14 | * Assert a value is truthy. 15 | */ 16 | export function assert(value: any, message?: string | undefined) { 17 | if (!value) { 18 | const assertion = "Failed assertion" + (message ? `: ${message}` : ""); 19 | console.debug(assertion); 20 | throw new Error(assertion); 21 | } 22 | } 23 | 24 | export function assertThrows( 25 | fn: () => void, 26 | errorClass: any, 27 | message?: string | undefined, 28 | ) { 29 | try { 30 | fn(); 31 | } catch (e) { 32 | if (e instanceof errorClass) { 33 | if (message) { 34 | assert( 35 | e.message.includes(message), 36 | `Expected message to include ${message}`, 37 | ); 38 | } 39 | return; 40 | } 41 | throw e; 42 | } 43 | throw new Error("Expected function to throw"); 44 | } 45 | 46 | /** 47 | * Fails a test. 48 | */ 49 | export function fail(reason: string) { 50 | console.debug("Failed: " + reason); 51 | throw new Error("Failed: " + reason); 52 | } 53 | 54 | /** 55 | * Assert two values match (==). 56 | */ 57 | export function assertEquals(a1: any, a2: any) { 58 | assert(a1 == a2, `${a1} != ${a2}`); 59 | } 60 | 61 | /** 62 | * Assert two arrays match (==). 63 | */ 64 | export function assertArrayEquals(a1: ArrayLike, a2: ArrayLike) { 65 | assertEquals(a1.length, a2.length); 66 | 67 | for (const index in a1) { 68 | assertEquals(a1[index], a2[index]); 69 | } 70 | } 71 | 72 | /** 73 | * Assert that two stack traces match, minus the line numbers. 74 | */ 75 | export function assertStackTraceEquals(stack1: string, stack2: string) { 76 | function normalize(s: string) { 77 | return s.replace(/[ ]+/g, " ") 78 | .replace(/^ /g, "") 79 | .replace(/\d+:\d+/g, "line:col") 80 | .trim(); 81 | } 82 | 83 | assertEquals(normalize(stack1), normalize(stack2)); 84 | } 85 | -------------------------------------------------------------------------------- /testing/checkin/runtime/throw.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | /** 4 | * This is needed to test that stack traces in extensions are correct. 5 | */ 6 | export function throwExceptionFromExtension() { 7 | innerThrowInExt(); 8 | } 9 | 10 | function innerThrowInExt() { 11 | throw new Error("Failed"); 12 | } 13 | -------------------------------------------------------------------------------- /testing/checkin/runtime/timers.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | /** 4 | * Call a callback function after a delay. 5 | */ 6 | export function setTimeout(callback: () => void, delay = 0) { 7 | return Deno.core.queueUserTimer( 8 | Deno.core.getTimerDepth() + 1, 9 | false, 10 | delay, 11 | callback, 12 | ); 13 | } 14 | 15 | /** 16 | * Call a callback function after a delay. 17 | */ 18 | export function setInterval(callback: () => void, delay = 0) { 19 | return Deno.core.queueUserTimer( 20 | Deno.core.getTimerDepth() + 1, 21 | true, 22 | delay, 23 | callback, 24 | ); 25 | } 26 | 27 | /** 28 | * Clear a timeout or interval. 29 | */ 30 | export function clearTimeout(id: number) { 31 | Deno.core.cancelTimer(id); 32 | } 33 | 34 | /** 35 | * Clear a timeout or interval. 36 | */ 37 | export function clearInterval(id: number) { 38 | Deno.core.cancelTimer(id); 39 | } 40 | 41 | /** 42 | * Mark a timer as not blocking event loop exit. 43 | */ 44 | export function unrefTimer(id: number) { 45 | Deno.core.unrefTimer(id); 46 | } 47 | 48 | /** 49 | * Mark a timer as blocking event loop exit. 50 | */ 51 | export function refTimer(id: number) { 52 | Deno.core.refTimer(id); 53 | } 54 | -------------------------------------------------------------------------------- /testing/checkin/runtime/worker.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { 3 | op_worker_await_close, 4 | op_worker_parent, 5 | op_worker_recv, 6 | op_worker_send, 7 | op_worker_spawn, 8 | op_worker_terminate, 9 | } from "ext:core/ops"; 10 | 11 | const privateConstructor = Symbol(); 12 | let parentWorker: Worker | null = null; 13 | 14 | export class Worker { 15 | // deno-lint-ignore no-explicit-any 16 | #worker: any; 17 | 18 | // deno-lint-ignore no-explicit-any 19 | constructor(privateParent: symbol, worker: any); 20 | constructor(baseUrl: string, url: string); 21 | constructor(arg1: unknown, arg2: unknown) { 22 | if (arg1 == privateConstructor) { 23 | this.#worker = arg2; 24 | } else { 25 | this.#worker = op_worker_spawn(arg1, arg2); 26 | } 27 | } 28 | 29 | sendMessage(message: string) { 30 | op_worker_send(this.#worker, message); 31 | } 32 | 33 | async receiveMessage(): Promise { 34 | return await op_worker_recv(this.#worker); 35 | } 36 | 37 | terminate() { 38 | op_worker_terminate(this.#worker); 39 | } 40 | 41 | get closed(): Promise { 42 | return op_worker_await_close(this.#worker); 43 | } 44 | 45 | static get parent(): Worker { 46 | if (parentWorker === null) { 47 | parentWorker = new Worker(privateConstructor, op_worker_parent()); 48 | } 49 | return parentWorker; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /testing/docs/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/denoland/deno_core/fc1ef37491950e82d2fb2e5e426a55723e730ce1/testing/docs/logo.png -------------------------------------------------------------------------------- /testing/integration/builtin_console_test/builtin_console_test.out: -------------------------------------------------------------------------------- 1 | Hello, world 2 | [ 3 | 1, 4 | 2, 5 | 3 6 | ] 7 | { 8 | "foo": "bar" 9 | } 10 | Uint8Array(3) [1, 2, 3] 11 | Uint8Array(1024) [0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 12 | Uint32Array(3) [1, 2, 3] 13 | -------------------------------------------------------------------------------- /testing/integration/builtin_console_test/builtin_console_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | console.log("Hello, world"); 3 | console.log([1, 2, 3]); 4 | console.log({ "foo": "bar" }); 5 | console.log(new Uint8Array([1, 2, 3])); 6 | console.log(new Uint8Array(1024)); 7 | console.log(new Uint32Array([1, 2, 3])); 8 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_circular/a.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import "./b.js"; 3 | console.log("a complete"); 4 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_circular/b.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import "./c.js"; 3 | import "./a.js"; 4 | console.log("b complete"); 5 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_circular/c.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import "./d.js"; 3 | console.log("c complete"); 4 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_circular/d.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | console.log("d"); 3 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_circular/dyn_import_circular.out: -------------------------------------------------------------------------------- 1 | d 2 | c complete 3 | b complete 4 | a complete 5 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_circular/dyn_import_circular.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | // Regression test for https://github.com/denoland/deno/issues/3736. 4 | import("./b.js"); 5 | import("./a.js"); 6 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_no_hang/dyn_import_no_hang.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { asyncNeverResolves } from "checkin:async"; 3 | 4 | // make a promise that never resolves so we have 5 | // a pending op outstanding 6 | const prom = asyncNeverResolves(); 7 | 8 | // import a module, with the key being that 9 | // this module promise doesn't resolve until a later 10 | // tick of the event loop 11 | await import("./dynamic.js"); 12 | console.log("module imported"); 13 | 14 | // unref to let the event loop exit 15 | Deno.core.unrefOpPromise(prom); 16 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_no_hang/dyn_import_no_hang.out: -------------------------------------------------------------------------------- 1 | module executed 2 | module imported 3 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_no_hang/dynamic.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | await new Promise((resolve) => { 3 | // Resolve the promise after one tick of the event loop. 4 | setTimeout(() => { 5 | resolve(); 6 | }, 0); 7 | }); 8 | console.log("module executed"); 9 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_op/dyn_import_op.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import "./main.js"; 3 | import { barrierAwait } from "checkin:async"; 4 | await barrierAwait("barrier"); 5 | console.log("done"); 6 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_op/dyn_import_op.out: -------------------------------------------------------------------------------- 1 | done 2 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_op/dynamic.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { asyncYield } from "checkin:async"; 3 | 4 | await asyncYield(); 5 | -------------------------------------------------------------------------------- /testing/integration/dyn_import_op/main.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { barrierAwait, barrierCreate } from "checkin:async"; 3 | 4 | barrierCreate("barrier", 2); 5 | (async () => { 6 | await import("./dynamic.js"); 7 | await barrierAwait("barrier"); 8 | })(); 9 | -------------------------------------------------------------------------------- /testing/integration/error_async_stack/error_async_stack.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | (async () => { 3 | const p = (async () => { 4 | await Promise.resolve().then(() => { 5 | throw new Error("async"); 6 | }); 7 | })(); 8 | try { 9 | await p; 10 | } catch (error) { 11 | console.log(error.stack); 12 | throw error; 13 | } 14 | })(); 15 | -------------------------------------------------------------------------------- /testing/integration/error_async_stack/error_async_stack.out: -------------------------------------------------------------------------------- 1 | Error: async 2 | at test:///integration/error_async_stack/error_async_stack.js:5:13 3 | at async test:///integration/error_async_stack/error_async_stack.js:4:5 4 | at async test:///integration/error_async_stack/error_async_stack.js:9:5 5 | [ERR] Error: async 6 | [ERR] at test:///integration/error_async_stack/error_async_stack.js:5:13 7 | [ERR] at async test:///integration/error_async_stack/error_async_stack.js:4:5 8 | [ERR] at async test:///integration/error_async_stack/error_async_stack.js:9:5 9 | -------------------------------------------------------------------------------- /testing/integration/error_callsite/error_callsite.out: -------------------------------------------------------------------------------- 1 | { 2 | "getTypeName": null, 3 | "getFunctionName": "Foo", 4 | "getMethodName": null, 5 | "getFileName": "test:///integration/error_callsite/error_callsite.ts", 6 | "getLineNumber": 34, 7 | "getColumnNumber": 5, 8 | "isToplevel": false, 9 | "isEval": false, 10 | "isNative": false, 11 | "isConstructor": true, 12 | "isAsync": false, 13 | "isPromiseAll": false, 14 | "getPromiseIndex": null 15 | } 16 | new Foo (test:///integration/error_callsite/error_callsite.ts:34:5) 17 | { 18 | "getTypeName": null, 19 | "getFunctionName": null, 20 | "getMethodName": null, 21 | "getFileName": "test:///integration/error_callsite/error_callsite.ts", 22 | "getLineNumber": 38, 23 | "getColumnNumber": 1, 24 | "isToplevel": true, 25 | "isEval": false, 26 | "isNative": false, 27 | "isConstructor": false, 28 | "isAsync": false, 29 | "isPromiseAll": false, 30 | "getPromiseIndex": null 31 | } 32 | test:///integration/error_callsite/error_callsite.ts:38:1 33 | -------------------------------------------------------------------------------- /testing/integration/error_callsite/error_callsite.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // deno-lint-ignore-file no-explicit-any 3 | function toObj(callsite: any) { 4 | const keys = [ 5 | "getThis", 6 | "getTypeName", 7 | "getFunction", 8 | "getFunctionName", 9 | "getMethodName", 10 | "getFileName", 11 | "getLineNumber", 12 | "getColumnNumber", 13 | "getEvalOrigin", 14 | "isToplevel", 15 | "isEval", 16 | "isNative", 17 | "isConstructor", 18 | "isAsync", 19 | "isPromiseAll", 20 | "getPromiseIndex", 21 | ]; 22 | return Object.fromEntries(keys.map((key) => [key, callsite[key]()])); 23 | } 24 | (Error as any).prepareStackTrace = function (_: any, callsites: any) { 25 | callsites.forEach((callsite: any) => { 26 | console.log(toObj(callsite)); 27 | console.log(callsite.toString()); 28 | }); 29 | return callsites; 30 | }; 31 | 32 | class Foo { 33 | constructor() { 34 | new Error().stack; 35 | } 36 | } 37 | 38 | new Foo(); 39 | -------------------------------------------------------------------------------- /testing/integration/error_eval_stack/error_eval_stack.out: -------------------------------------------------------------------------------- 1 | [ERR] Error 2 | [ERR] at eval (eval at (eval at (eval at foo (test:///integration/error_eval_stack/error_eval_stack.ts:5:3))), :1:7) 3 | [ERR] at eval (eval at (eval at foo (test:///integration/error_eval_stack/error_eval_stack.ts:5:3)), :1:1) 4 | [ERR] at eval (eval at foo (test:///integration/error_eval_stack/error_eval_stack.ts:5:3), :1:1) 5 | [ERR] at foo (test:///integration/error_eval_stack/error_eval_stack.ts:5:3) 6 | [ERR] at test:///integration/error_eval_stack/error_eval_stack.ts:8:1 7 | -------------------------------------------------------------------------------- /testing/integration/error_eval_stack/error_eval_stack.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // FAIL 3 | 4 | function foo() { 5 | eval(`eval("eval('throw new Error()')")`); 6 | } 7 | 8 | foo(); 9 | -------------------------------------------------------------------------------- /testing/integration/error_ext_stack/error_ext_stack.out: -------------------------------------------------------------------------------- 1 | [ERR] Error: Failed 2 | [ERR] at innerThrowInExt (checkin:throw:11:9) 3 | [ERR] at throwExceptionFromExtension (checkin:throw:7:3) 4 | [ERR] at test:///integration/error_ext_stack/error_ext_stack.ts:5:1 5 | -------------------------------------------------------------------------------- /testing/integration/error_ext_stack/error_ext_stack.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // FAIL 3 | import { throwExceptionFromExtension } from "checkin:throw"; 4 | 5 | throwExceptionFromExtension(); 6 | -------------------------------------------------------------------------------- /testing/integration/error_get_file_name/error_get_file_name.out: -------------------------------------------------------------------------------- 1 | [ 2 | "test:///integration/error_get_file_name/error_get_file_name.ts", 3 | null, 4 | "test:///integration/error_get_file_name/error_get_file_name.ts" 5 | ] 6 | -------------------------------------------------------------------------------- /testing/integration/error_get_file_name/error_get_file_name.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | // deno-lint-ignore no-explicit-any 4 | (Error as any).prepareStackTrace = (_err: unknown, frames: any[]) => { 5 | return frames.map((frame) => frame.getFileName()); 6 | }; 7 | 8 | new Promise((_, reject) => { 9 | reject(new Error("fail").stack); 10 | }).catch((err) => { 11 | console.log(err); 12 | }); 13 | -------------------------------------------------------------------------------- /testing/integration/error_get_file_name_to_string/error_get_file_name_to_string.out: -------------------------------------------------------------------------------- 1 | [ 2 | "test:///integration/error_get_file_name_to_string/error_get_file_name_to_string.ts:9:10", 3 | "new Promise ()", 4 | "test:///integration/error_get_file_name_to_string/error_get_file_name_to_string.ts:8:1" 5 | ] 6 | -------------------------------------------------------------------------------- /testing/integration/error_get_file_name_to_string/error_get_file_name_to_string.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | // deno-lint-ignore no-explicit-any 4 | (Error as any).prepareStackTrace = (_err: unknown, frames: any[]) => { 5 | return frames.map((frame) => frame.toString()); 6 | }; 7 | 8 | new Promise((_, reject) => { 9 | reject(new Error("fail").stack); 10 | }).catch((err) => { 11 | console.log(err); 12 | }); 13 | -------------------------------------------------------------------------------- /testing/integration/error_get_script_name_or_source_url/error_get_script_name_or_source_url.out: -------------------------------------------------------------------------------- 1 | [ 2 | "test:///integration/error_get_script_name_or_source_url/error_get_script_name_or_source_url.ts", 3 | null, 4 | "test:///integration/error_get_script_name_or_source_url/error_get_script_name_or_source_url.ts" 5 | ] 6 | -------------------------------------------------------------------------------- /testing/integration/error_get_script_name_or_source_url/error_get_script_name_or_source_url.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | // deno-lint-ignore no-explicit-any 4 | (Error as any).prepareStackTrace = (_err: unknown, frames: any[]) => { 5 | return frames.map((frame) => frame.getScriptNameOrSourceURL()); 6 | }; 7 | 8 | new Promise((_, reject) => { 9 | reject(new Error("fail").stack); 10 | }).catch((err) => { 11 | console.log(err); 12 | }); 13 | -------------------------------------------------------------------------------- /testing/integration/error_non_existent_eval_source/error_non_existent_eval_source.out: -------------------------------------------------------------------------------- 1 | [ERR] ReferenceError: doesNotExist is not defined 2 | [ERR] at Object.eval (empty.eval, :3:1) 3 | [ERR] at test:///integration/error_non_existent_eval_source/error_non_existent_eval_source.ts:11:6 4 | -------------------------------------------------------------------------------- /testing/integration/error_non_existent_eval_source/error_non_existent_eval_source.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | const AsyncFunction = Object.getPrototypeOf(async function () { 3 | // empty 4 | }).constructor; 5 | 6 | const func = new AsyncFunction( 7 | `return doesNotExist(); 8 | //# sourceURL=empty.eval`, 9 | ); 10 | 11 | func.call({}); 12 | -------------------------------------------------------------------------------- /testing/integration/error_prepare_stack_trace/error_prepare_stack_trace.out: -------------------------------------------------------------------------------- 1 | [ 2 | "getThis", 3 | "getTypeName", 4 | "getFunction", 5 | "getFunctionName", 6 | "getMethodName", 7 | "getFileName", 8 | "getLineNumber", 9 | "getColumnNumber", 10 | "getEvalOrigin", 11 | "isToplevel", 12 | "isEval", 13 | "isNative", 14 | "isConstructor", 15 | "isAsync", 16 | "isPromiseAll", 17 | "getPromiseIndex", 18 | "getScriptNameOrSourceURL", 19 | "toString" 20 | ] 21 | [] 22 | [ 23 | "test:///integration/error_prepare_stack_trace/error_prepare_stack_trace.ts:13:13" 24 | ] 25 | getThis() threw an error: The receiver is not a valid callsite object. 26 | getTypeName() threw an error: The receiver is not a valid callsite object. 27 | getFunction() threw an error: The receiver is not a valid callsite object. 28 | getFunctionName() threw an error: The receiver is not a valid callsite object. 29 | getMethodName() threw an error: The receiver is not a valid callsite object. 30 | getFileName() threw an error: The receiver is not a valid callsite object. 31 | getLineNumber() threw an error: The receiver is not a valid callsite object. 32 | getColumnNumber() threw an error: The receiver is not a valid callsite object. 33 | getEvalOrigin() threw an error: The receiver is not a valid callsite object. 34 | isToplevel() threw an error: The receiver is not a valid callsite object. 35 | isEval() threw an error: The receiver is not a valid callsite object. 36 | isNative() threw an error: The receiver is not a valid callsite object. 37 | isConstructor() threw an error: The receiver is not a valid callsite object. 38 | isAsync() threw an error: The receiver is not a valid callsite object. 39 | isPromiseAll() threw an error: The receiver is not a valid callsite object. 40 | getPromiseIndex() threw an error: The receiver is not a valid callsite object. 41 | getScriptNameOrSourceURL() threw an error: The receiver is not a valid callsite object. 42 | toString() threw an error: The receiver is not a valid callsite object. 43 | -------------------------------------------------------------------------------- /testing/integration/error_prepare_stack_trace/error_prepare_stack_trace.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | let errorCallsitePrototype; 3 | // deno-lint-ignore no-explicit-any 4 | (Error as any).prepareStackTrace = (_err, frames) => { 5 | return frames.map((frame) => { 6 | errorCallsitePrototype = Object.getPrototypeOf(frame); 7 | console.log(Object.getOwnPropertyNames(Object.getPrototypeOf(frame))); 8 | console.log(Object.getOwnPropertyNames(frame)); 9 | return frame.toString(); 10 | }); 11 | }; 12 | 13 | console.log(new Error("fail").stack); 14 | 15 | for (const prop of Object.getOwnPropertyNames(errorCallsitePrototype)) { 16 | if (typeof errorCallsitePrototype[prop] === "function") { 17 | let error; 18 | try { 19 | errorCallsitePrototype[prop](); 20 | } catch (e) { 21 | error = e; 22 | } 23 | if (error) { 24 | console.log(`${prop}() threw an error: ${error.message}`); 25 | } else { 26 | console.log(`${prop}() did not throw an error`); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /testing/integration/error_prepare_stack_trace_crash/error_prepare_stack_trace_crash.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | delete globalThis.Error; 3 | 4 | const e = new TypeError("e"); 5 | e.stack; 6 | -------------------------------------------------------------------------------- /testing/integration/error_prepare_stack_trace_crash/error_prepare_stack_trace_crash.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/denoland/deno_core/fc1ef37491950e82d2fb2e5e426a55723e730ce1/testing/integration/error_prepare_stack_trace_crash/error_prepare_stack_trace_crash.out -------------------------------------------------------------------------------- /testing/integration/error_rejection_catch/error_rejection_catch.out: -------------------------------------------------------------------------------- 1 | ok 1 2 | caught 1 3 | --- 4 | unhandled: rejected 2 5 | ok 2 6 | caught 2 7 | --- 8 | handled: rejected 2 9 | unhandled: rejected 3 10 | -------------------------------------------------------------------------------- /testing/integration/error_rejection_catch/error_rejection_catch.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | // This test should return the same output on a browser. 4 | 5 | globalThis.onunhandledrejection = (event) => { 6 | console.log("unhandled: " + event.reason); 7 | event.preventDefault(); 8 | }; 9 | 10 | globalThis.onrejectionhandled = ({ reason }) => { 11 | console.log("handled: " + reason); 12 | }; 13 | 14 | // catch handler added before event loop spins, not unhandled 15 | const p1 = Promise.reject("rejected 1"); 16 | const p1a = p1.catch(() => { 17 | console.log("caught 1"); 18 | }); 19 | console.log("ok 1"); 20 | await p1a; 21 | 22 | console.log("---"); 23 | 24 | // catch handler added after event loop spins, unhandled 25 | const p2 = Promise.reject("rejected 2"); 26 | await new Promise((r) => setTimeout(r, 1)); 27 | const p2a = p2.catch(() => { 28 | console.log("caught 2"); 29 | }); 30 | console.log("ok 2"); 31 | await p2a; 32 | 33 | console.log("---"); 34 | 35 | const p3 = Promise.reject("rejected 3"); 36 | await p3; 37 | -------------------------------------------------------------------------------- /testing/integration/error_rejection_order/error_rejection_order.out: -------------------------------------------------------------------------------- 1 | [ERR] Uncaught (in promise) 0 2 | -------------------------------------------------------------------------------- /testing/integration/error_rejection_order/error_rejection_order.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | for (let i = 0; i < 100; i++) { 3 | Promise.reject(i); 4 | } 5 | -------------------------------------------------------------------------------- /testing/integration/error_source_maps_with_prepare_stack_trace/error_source_maps_with_prepare_stack_trace.out: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "filename": "test:///integration/error_source_maps_with_prepare_stack_trace/error_source_maps_with_prepare_stack_trace.ts", 4 | "methodName": null, 5 | "functionName": null, 6 | "lineNumber": 9, 7 | "columnNumber": 9 8 | } 9 | ] 10 | -------------------------------------------------------------------------------- /testing/integration/error_source_maps_with_prepare_stack_trace/error_source_maps_with_prepare_stack_trace.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | // deno-lint-ignore-file no-explicit-any 4 | type Thing = { 5 | name: string; 6 | }; 7 | 8 | try { 9 | throw new Error("This is an error"); 10 | } catch (e) { 11 | (Error as any).prepareStackTrace = (_: any, stack: any) => { 12 | return stack.map((s: any) => ({ 13 | filename: s.getFileName(), 14 | methodName: s.getMethodName(), 15 | functionName: s.getFunctionName(), 16 | lineNumber: s.getLineNumber(), 17 | columnNumber: s.getColumnNumber(), 18 | })); 19 | }; 20 | console.log((e as Error).stack); 21 | } 22 | -------------------------------------------------------------------------------- /testing/integration/error_with_stack/error_with_stack.out: -------------------------------------------------------------------------------- 1 | [ERR] Error: assert 2 | [ERR] at assert (test:///integration/error_with_stack/error_with_stack.ts:6:11) 3 | [ERR] at main (test:///integration/error_with_stack/error_with_stack.ts:10:3) 4 | [ERR] at test:///integration/error_with_stack/error_with_stack.ts:12:1 5 | -------------------------------------------------------------------------------- /testing/integration/error_with_stack/error_with_stack.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // FAIL 3 | 4 | function assert(cond) { 5 | if (!cond) { 6 | throw Error("assert"); 7 | } 8 | } 9 | function main() { 10 | assert(false); 11 | } 12 | main(); 13 | -------------------------------------------------------------------------------- /testing/integration/error_without_stack/error_without_stack.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | eval(`function main() { 3 | console.log("asdf); 4 | } 5 | main();`); 6 | -------------------------------------------------------------------------------- /testing/integration/error_without_stack/error_without_stack.out: -------------------------------------------------------------------------------- 1 | [ERR] SyntaxError: Invalid or unexpected token 2 | [ERR] at test:///integration/error_without_stack/error_without_stack.js:2:1 3 | -------------------------------------------------------------------------------- /testing/integration/import_sync/async.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | await {}; 4 | export const a = 1; 5 | -------------------------------------------------------------------------------- /testing/integration/import_sync/import_sync.out: -------------------------------------------------------------------------------- 1 | { 2 | "a": 1 3 | } 4 | [ERR] Error: Top-level await is not allowed in synchronous evaluation 5 | [ERR] at test:///integration/import_sync/import_sync.ts:8:1 6 | -------------------------------------------------------------------------------- /testing/integration/import_sync/import_sync.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | const { op_import_sync, op_path_to_url } = Deno.core.ops; 4 | 5 | const resolve = (p: string) => op_path_to_url(p); 6 | 7 | console.log(op_import_sync(resolve("./integration/import_sync/sync.js"))); 8 | op_import_sync(resolve("./integration/import_sync/async.js")); 9 | -------------------------------------------------------------------------------- /testing/integration/import_sync/sync.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | export const a = 1; 4 | -------------------------------------------------------------------------------- /testing/integration/import_sync_existing/import_sync_existing.out: -------------------------------------------------------------------------------- 1 | { 2 | "a": 1 3 | } 4 | -------------------------------------------------------------------------------- /testing/integration/import_sync_existing/import_sync_existing.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | const { op_import_sync, op_path_to_url } = Deno.core.ops; 4 | 5 | const resolve = (p: string) => op_path_to_url(p); 6 | 7 | await import(resolve("./integration/import_sync/sync.js")); 8 | console.log(op_import_sync(resolve("./integration/import_sync/sync.js"))); 9 | -------------------------------------------------------------------------------- /testing/integration/import_sync_existing/sync.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | export const a = 1; 4 | -------------------------------------------------------------------------------- /testing/integration/main_module_handler/main_module_handler.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // The handler is set up before this main module is executed 3 | globalThis.onmainmodule = (main) => { 4 | console.log(main); 5 | }; 6 | 7 | export const b = 2; 8 | 9 | export default { 10 | a: 1, 11 | }; 12 | -------------------------------------------------------------------------------- /testing/integration/main_module_handler/main_module_handler.out: -------------------------------------------------------------------------------- 1 | { 2 | "b": 2, 3 | "default": { 4 | "a": 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /testing/integration/module_types/module_types.out: -------------------------------------------------------------------------------- 1 | Uint8Array(3) [1, 2, 3] 2 | "🦕" 3 | {} 4 | -------------------------------------------------------------------------------- /testing/integration/module_types/module_types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import bin from "./test.bin" with { type: "bytes" }; 3 | import txt from "./test.txt" with { type: "text" }; 4 | import json from "./test.json" with { type: "json" }; 5 | 6 | console.log(bin); 7 | console.log(JSON.stringify(txt)); 8 | console.log(JSON.stringify(json)); 9 | -------------------------------------------------------------------------------- /testing/integration/module_types/test.bin: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /testing/integration/module_types/test.bin.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // Make tsc happy 3 | export default {}; 4 | -------------------------------------------------------------------------------- /testing/integration/module_types/test.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /testing/integration/module_types/test.txt: -------------------------------------------------------------------------------- 1 | 🦕 -------------------------------------------------------------------------------- /testing/integration/module_types/test.txt.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // Make tsc happy 3 | export default {}; 4 | -------------------------------------------------------------------------------- /testing/integration/pending_unref_op_tla/pending_unref_op_tla.out: -------------------------------------------------------------------------------- 1 | should not panic 2 | didn't panic! 3 | -------------------------------------------------------------------------------- /testing/integration/pending_unref_op_tla/pending_unref_op_tla.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | console.log("should not panic"); 3 | await new Promise((r) => { 4 | const id = setTimeout(r, 1000); 5 | Deno.unrefTimer(id); 6 | }); 7 | console.log("didn't panic!"); 8 | -------------------------------------------------------------------------------- /testing/integration/smoke_test/smoke_test.out: -------------------------------------------------------------------------------- 1 | Hello, world 2 | -------------------------------------------------------------------------------- /testing/integration/smoke_test/smoke_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | console.log("Hello, world"); 3 | -------------------------------------------------------------------------------- /testing/integration/timer_many/timer_many.out: -------------------------------------------------------------------------------- 1 | 1000000 2 | -------------------------------------------------------------------------------- /testing/integration/timer_many/timer_many.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | let n = 0; 3 | for (let i = 0; i < 1e6; i++) setTimeout(() => n++, 1); 4 | setTimeout(() => console.log(n), 2); 5 | -------------------------------------------------------------------------------- /testing/integration/timer_ref/timer_ref.out: -------------------------------------------------------------------------------- 1 | a 2 | b 3 | -------------------------------------------------------------------------------- /testing/integration/timer_ref/timer_ref.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | setTimeout(() => console.log("a"), 1000); 3 | setTimeout(() => console.log("b"), 2000); 4 | // Make this long enough that we'll never hit it 5 | const c = setTimeout(() => console.log("c"), 120_000); 6 | Deno.core.unrefTimer(c); 7 | -------------------------------------------------------------------------------- /testing/integration/timer_ref_and_cancel/timer_ref_and_cancel.out: -------------------------------------------------------------------------------- 1 | a 2 | b 3 | -------------------------------------------------------------------------------- /testing/integration/timer_ref_and_cancel/timer_ref_and_cancel.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | setTimeout(() => console.log("a"), 1000); 3 | setTimeout(() => console.log("b"), 2000); 4 | // Make these long enough that we'll never hit them 5 | const c = setTimeout(() => console.log("c"), 120_000); 6 | const d = setTimeout(() => console.log("d"), 150_000); 7 | // c should not run, if d is cancelled 8 | Deno.unrefTimer(c); 9 | clearTimeout(d); 10 | -------------------------------------------------------------------------------- /testing/integration/ts_types/decorator.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | function logged(value, { kind, name }) { 3 | if (kind === "method" || kind === "getter" || kind === "setter") { 4 | return function (...args) { 5 | console.log(`starting ${name} with arguments ${args.join(", ")}`); 6 | const ret = value.call(this, ...args); 7 | console.log(`ending ${name}`); 8 | return ret; 9 | }; 10 | } 11 | } 12 | 13 | class C { 14 | @logged 15 | set x(arg) {} 16 | } 17 | 18 | new C().x = 1; 19 | -------------------------------------------------------------------------------- /testing/integration/ts_types/ts_types.out: -------------------------------------------------------------------------------- 1 | starting x with arguments 1 2 | ending x 3 | {} 4 | {} 5 | -------------------------------------------------------------------------------- /testing/integration/ts_types/ts_types.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import * as which from "./which.ts"; 3 | import * as decorator from "./decorator.ts"; 4 | console.log(which); 5 | console.log(decorator); 6 | -------------------------------------------------------------------------------- /testing/integration/user_breaks_promise_constructor/user_breaks_promise_constructor.out: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | [ERR] Uncaught (in promise) x 4 | -------------------------------------------------------------------------------- /testing/integration/user_breaks_promise_constructor/user_breaks_promise_constructor.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // https://github.com/denoland/deno_core/issues/743 3 | console.log("1"); 4 | Object.defineProperty(Promise.prototype, "constructor", { 5 | get() { 6 | throw "x"; 7 | }, 8 | }); 9 | console.log("2"); 10 | -------------------------------------------------------------------------------- /testing/integration/user_breaks_promise_species/user_breaks_promise_species.out: -------------------------------------------------------------------------------- 1 | 1 2 | 2 3 | [ERR] TypeError: object.constructor[Symbol.species] is not a constructor 4 | [ERR] at Promise.then () 5 | -------------------------------------------------------------------------------- /testing/integration/user_breaks_promise_species/user_breaks_promise_species.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | // https://github.com/denoland/deno_core/issues/742 3 | console.log("1"); 4 | Object.defineProperty(Promise, Symbol.species, { value: 0 }); 5 | console.log("2"); 6 | -------------------------------------------------------------------------------- /testing/integration/wasm_imports/add.wasm: -------------------------------------------------------------------------------- 1 | asm ``./import_from_wasm.mjsadd exported_add 2 | 3 | AA nameadd -------------------------------------------------------------------------------- /testing/integration/wasm_imports/add.wat: -------------------------------------------------------------------------------- 1 | (module 2 | (func $add (import "./import_from_wasm.mjs" "add") (param i32) (param i32) (result i32)) 3 | (func (export "exported_add") (result i32) 4 | i32.const 21 5 | i32.const 21 6 | call $add 7 | ) 8 | ) -------------------------------------------------------------------------------- /testing/integration/wasm_imports/import_from_wasm.mjs: -------------------------------------------------------------------------------- 1 | import { sleep } from "./lib.mjs"; 2 | export { add } from "./lib.mjs"; 3 | 4 | console.log("import_inner.js before"); 5 | 6 | await sleep(100); 7 | 8 | console.log("import_inner.js after"); 9 | -------------------------------------------------------------------------------- /testing/integration/wasm_imports/lib.mjs: -------------------------------------------------------------------------------- 1 | console.log("lib.js before"); 2 | 3 | export function sleep(timeout) { 4 | return new Promise((resolve) => { 5 | Deno.core.queueUserTimer( 6 | Deno.core.getTimerDepth() + 1, 7 | false, 8 | timeout, 9 | resolve, 10 | ); 11 | }); 12 | } 13 | await sleep(100); 14 | 15 | console.log("lib.js after"); 16 | 17 | const abc = 1 + 2; 18 | export function add(a, b) { 19 | console.log(`abc: ${abc}`); 20 | return a + b; 21 | } 22 | -------------------------------------------------------------------------------- /testing/integration/wasm_imports/wasm_imports.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { exported_add } from "./add.wasm"; 3 | 4 | // To regenerate Wasm file use: 5 | // npx -p wabt wat2wasm ./testing/integration/wasm_imports/add.wat -o ./testing/integration/wasm_imports/add.wasm 6 | 7 | console.log(`exported_add: ${exported_add(4, 5)}`); 8 | -------------------------------------------------------------------------------- /testing/integration/wasm_imports/wasm_imports.out: -------------------------------------------------------------------------------- 1 | lib.js before 2 | lib.js after 3 | import_inner.js before 4 | import_inner.js after 5 | abc: 3 6 | exported_add: 42 7 | -------------------------------------------------------------------------------- /testing/integration/worker_spawn/worker.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { Worker } from "checkin:worker"; 3 | Worker.parent.sendMessage("hello from client"); 4 | const message = await Worker.parent.receiveMessage(); 5 | console.log(`worker got from main "${message}"`); 6 | -------------------------------------------------------------------------------- /testing/integration/worker_spawn/worker_spawn.out: -------------------------------------------------------------------------------- 1 | main started 2 | main worker booted 3 | main got from worker "hello from client" 4 | worker got from main "ok from main" 5 | main exiting 6 | -------------------------------------------------------------------------------- /testing/integration/worker_spawn/worker_spawn.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { Worker } from "checkin:worker"; 3 | console.log("main started"); 4 | const worker = new Worker(import.meta.url, "./worker.ts"); 5 | console.log("main worker booted"); 6 | const message = await worker.receiveMessage(); 7 | console.log(`main got from worker "${message}"`); 8 | worker.sendMessage("ok from main"); 9 | await worker.closed; 10 | console.log("main exiting"); 11 | -------------------------------------------------------------------------------- /testing/integration/worker_terminate/worker.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { Worker } from "checkin:worker"; 3 | Worker.parent.sendMessage("hello from client"); 4 | const message = await Worker.parent.receiveMessage(); 5 | console.log(`worker got from main "${message}"`); 6 | -------------------------------------------------------------------------------- /testing/integration/worker_terminate/worker_terminate.out: -------------------------------------------------------------------------------- 1 | main started 2 | main worker booted 3 | main got from worker "hello from client" 4 | [ERR] Uncaught Error: execution terminated 5 | main exiting 6 | -------------------------------------------------------------------------------- /testing/integration/worker_terminate/worker_terminate.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { Worker } from "checkin:worker"; 3 | console.log("main started"); 4 | const worker = new Worker(import.meta.url, "./worker.ts"); 5 | console.log("main worker booted"); 6 | const message = await worker.receiveMessage(); 7 | console.log(`main got from worker "${message}"`); 8 | worker.terminate(); 9 | await worker.closed; 10 | console.log("main exiting"); 11 | -------------------------------------------------------------------------------- /testing/integration/worker_terminate_op/worker.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { asyncSpin, asyncYield } from "checkin:async"; 3 | import { Worker } from "checkin:worker"; 4 | const p = asyncSpin(); 5 | await asyncYield(); 6 | Worker.parent.sendMessage("hello from client"); 7 | await p; 8 | console.log("worker shouldn't get here!"); 9 | -------------------------------------------------------------------------------- /testing/integration/worker_terminate_op/worker_terminate_op.out: -------------------------------------------------------------------------------- 1 | main started 2 | main worker booted 3 | main got from worker "hello from client" 4 | [ERR] Uncaught Error: execution terminated 5 | main exiting 6 | -------------------------------------------------------------------------------- /testing/integration/worker_terminate_op/worker_terminate_op.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { setTimeout } from "checkin:timers"; 3 | import { Worker } from "checkin:worker"; 4 | console.log("main started"); 5 | const worker = new Worker(import.meta.url, "./worker.ts"); 6 | console.log("main worker booted"); 7 | const message = await worker.receiveMessage(); 8 | console.log(`main got from worker "${message}"`); 9 | worker.terminate(); 10 | await worker.closed; 11 | console.log("main exiting"); 12 | await new Promise((r) => setTimeout(r, 100)); 13 | -------------------------------------------------------------------------------- /testing/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | mod checkin; 4 | 5 | pub use checkin::runner::create_runtime_from_snapshot; 6 | pub use checkin::runner::create_runtime_from_snapshot_with_options; 7 | pub use checkin::runner::snapshot::create_snapshot; 8 | 9 | macro_rules! unit_test { 10 | ($($id:ident,)*) => { 11 | #[cfg(test)] 12 | mod unit { 13 | $( 14 | #[test] 15 | fn $id() { 16 | $crate::checkin::runner::testing::run_unit_test(stringify!($id)); 17 | } 18 | )* 19 | } 20 | }; 21 | } 22 | 23 | macro_rules! integration_test { 24 | ($($id:ident,)*) => { 25 | #[cfg(test)] 26 | mod integration { 27 | $( 28 | #[test] 29 | fn $id() { 30 | $crate::checkin::runner::testing::run_integration_test(stringify!($id)); 31 | } 32 | )* 33 | } 34 | }; 35 | } 36 | 37 | // Test individual bits of functionality. These files are loaded from the unit/ dir. 38 | unit_test!( 39 | encode_decode_test, 40 | error_test, 41 | microtask_test, 42 | ops_async_test, 43 | ops_buffer_test, 44 | ops_error_test, 45 | resource_test, 46 | serialize_deserialize_test, 47 | stats_test, 48 | task_test, 49 | tc39_test, 50 | timer_test, 51 | type_test, 52 | ); 53 | 54 | // Test the load and run of an entire file within the `checkin` infrastructure. 55 | // These files are loaded from the integration/ dir. 56 | integration_test!( 57 | builtin_console_test, 58 | dyn_import_circular, 59 | dyn_import_op, 60 | dyn_import_no_hang, 61 | error_async_stack, 62 | error_callsite, 63 | error_non_existent_eval_source, 64 | error_rejection_catch, 65 | error_rejection_order, 66 | error_eval_stack, 67 | error_ext_stack, 68 | error_prepare_stack_trace, 69 | error_prepare_stack_trace_crash, 70 | error_source_maps_with_prepare_stack_trace, 71 | error_with_stack, 72 | error_without_stack, 73 | error_get_file_name, 74 | error_get_file_name_to_string, 75 | error_get_script_name_or_source_url, 76 | import_sync, 77 | import_sync_existing, 78 | main_module_handler, 79 | module_types, 80 | pending_unref_op_tla, 81 | smoke_test, 82 | timer_ref, 83 | timer_ref_and_cancel, 84 | timer_many, 85 | ts_types, 86 | user_breaks_promise_constructor, 87 | user_breaks_promise_species, 88 | wasm_imports, 89 | worker_spawn, 90 | worker_terminate, 91 | worker_terminate_op, 92 | ); 93 | -------------------------------------------------------------------------------- /testing/ops.d.ts: -------------------------------------------------------------------------------- 1 | // deno-lint-ignore-file no-explicit-any 2 | // Copyright 2018-2025 the Deno authors. MIT license. 3 | 4 | export function op_log_debug(...any: any[]): any; 5 | export function op_log_info(...any: any[]): any; 6 | 7 | export function op_test_register(...any: any[]): any; 8 | 9 | export function op_async_throw_error_deferred(...any: any[]): any; 10 | export function op_async_throw_error_eager(...any: any[]): any; 11 | export function op_async_throw_error_lazy(...any: any[]): any; 12 | export function op_error_context_async(...any: any[]): any; 13 | export function op_error_context_sync(...any: any[]): any; 14 | export function op_error_custom_sync(...any: any[]): any; 15 | export function op_error_custom_with_code_sync(...any: any[]): any; 16 | 17 | export function op_worker_await_close(...any: any[]): any; 18 | export function op_worker_parent(...any: any[]): any; 19 | export function op_worker_recv(...any: any[]): any; 20 | export function op_worker_send(...any: any[]): any; 21 | export function op_worker_spawn(...any: any[]): any; 22 | export function op_worker_terminate(...any: any[]): any; 23 | 24 | export class DOMPointReadOnly {} 25 | 26 | export class DOMPoint { 27 | constructor(x?: number, y?: number, z?: number, w?: number); 28 | static fromPoint( 29 | other: { x?: number; y?: number; z?: number; w?: number }, 30 | ): DOMPoint; 31 | fromPoint( 32 | other: { x?: number; y?: number; z?: number; w?: number }, 33 | ): DOMPoint; 34 | get x(): number; 35 | get y(): number; 36 | get z(): number; 37 | get w(): number; 38 | wrappingSmi(value: number): number; 39 | } 40 | 41 | export class TestObjectWrap { 42 | constructor(); 43 | withVarargs(...args: any[]): number; 44 | with_RENAME(): void; 45 | withAsyncFn(ms: number): Promise; 46 | withThis(): void; 47 | withScopeFast(): void; 48 | undefinedResult(): undefined; 49 | withValidateInt(value: number): void; 50 | } 51 | 52 | export class TestEnumWrap {} 53 | -------------------------------------------------------------------------------- /testing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "baseUrl": ".", 5 | "paths": { 6 | "ext:core/mod.js": ["../core/core.d.ts"], 7 | "ext:core/ops": ["ops.d.ts"], 8 | "checkin:async": ["checkin/runtime/async.ts"], 9 | "checkin:console": ["checkin/runtime/console.ts"], 10 | "checkin:error": ["checkin/runtime/error.ts"], 11 | "checkin:testing": ["checkin/runtime/testing.ts"], 12 | "checkin:throw": ["checkin/runtime/throw.ts"], 13 | "checkin:timers": ["checkin/runtime/timers.ts"], 14 | "checkin:worker": ["checkin/runtime/worker.ts"], 15 | "checkin:object": ["checkin/runtime/object.ts"] 16 | }, 17 | "lib": ["ESNext", "DOM", "ES2023.Array"], 18 | "module": "ESNext", 19 | "moduleDetection": "force", 20 | "moduleResolution": "Bundler", 21 | "noEmit": true, 22 | "allowImportingTsExtensions": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /testing/unit/encode_decode_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { assert, assertArrayEquals, assertEquals, test } from "checkin:testing"; 3 | 4 | test(function testEmptyEncode() { 5 | const empty = Deno.core.encode(""); 6 | assertEquals(empty.length, 0); 7 | }); 8 | 9 | test(function testEmptyDecode() { 10 | const emptyBuf = Deno.core.decode(new Uint8Array(0)); 11 | assertEquals(emptyBuf, ""); 12 | }); 13 | 14 | test(function testFixture1() { 15 | // deno-fmt-ignore 16 | const fixture1 = [ 17 | 0xf0, 0x9d, 0x93, 0xbd, 18 | 0xf0, 0x9d, 0x93, 0xae, 19 | 0xf0, 0x9d, 0x94, 0x81, 20 | 0xf0, 0x9d, 0x93, 0xbd 21 | ]; 22 | assertArrayEquals( 23 | Array.from(Deno.core.encode("𝓽𝓮𝔁𝓽")), 24 | fixture1, 25 | ); 26 | assertEquals(Deno.core.decode(new Uint8Array(fixture1)), "𝓽𝓮𝔁𝓽"); 27 | }); 28 | 29 | test(function testFixture2() { 30 | // deno-fmt-ignore 31 | const fixture2 = [ 32 | 72, 101, 108, 108, 33 | 111, 32, 239, 191, 34 | 189, 239, 191, 189, 35 | 32, 87, 111, 114, 36 | 108, 100 37 | ]; 38 | assertArrayEquals( 39 | Array.from(Deno.core.encode("Hello \udc12\ud834 World")), 40 | fixture2, 41 | ); 42 | assertEquals( 43 | Deno.core.decode(new Uint8Array(fixture2)), 44 | "Hello �� World", 45 | ); 46 | }); 47 | 48 | test(function testStringTooLarge() { 49 | // See https://github.com/denoland/deno/issues/6649 50 | let thrown = false; 51 | try { 52 | Deno.core.decode(new Uint8Array(2 ** 29)); 53 | } catch (e) { 54 | thrown = true; 55 | assert(e instanceof RangeError); 56 | assertEquals(e.message, "string too long"); 57 | } 58 | assert(thrown); 59 | }); 60 | 61 | test(function binaryEncode() { 62 | function asBinaryString(bytes: Uint8Array): string { 63 | return Array.from(bytes).map( 64 | (v: number) => String.fromCodePoint(v), 65 | ).join(""); 66 | } 67 | 68 | function decodeBinary(binaryString: string) { 69 | const chars: string[] = Array.from(binaryString); 70 | return chars.map((v: string): number | undefined => v.codePointAt(0)); 71 | } 72 | 73 | // invalid utf-8 code points 74 | const invalid = new Uint8Array([0xC0]); 75 | assertEquals( 76 | Deno.core.encodeBinaryString(invalid), 77 | asBinaryString(invalid), 78 | ); 79 | 80 | const invalid2 = new Uint8Array([0xC1]); 81 | assertEquals( 82 | Deno.core.encodeBinaryString(invalid2), 83 | asBinaryString(invalid2), 84 | ); 85 | 86 | for (let i = 0, j = 255; i <= 255; i++, j--) { 87 | const bytes = new Uint8Array([i, j]); 88 | const binaryString = Deno.core.encodeBinaryString(bytes); 89 | assertEquals( 90 | binaryString, 91 | asBinaryString(bytes), 92 | ); 93 | assertArrayEquals(Array.from(bytes), decodeBinary(binaryString)); 94 | } 95 | }); 96 | -------------------------------------------------------------------------------- /testing/unit/error_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { throwCustomError } from "checkin:error"; 3 | import { assert, assertEquals, test } from "checkin:testing"; 4 | 5 | test(function testCustomError() { 6 | try { 7 | throwCustomError("uh oh"); 8 | } catch (e) { 9 | assertEquals(e.message, "uh oh"); 10 | assert(e instanceof Deno.core.BadResource); 11 | } 12 | }); 13 | 14 | test(function testJsErrorConstructors() { 15 | const error = new Error("message"); 16 | const badResource = new Deno.core.BadResource("bad resource", { 17 | cause: error, 18 | }); 19 | assertEquals(badResource.message, "bad resource"); 20 | assertEquals(badResource.cause, error); 21 | 22 | const Interrupted = new Deno.core.Interrupted("interrupted", { 23 | cause: error, 24 | }); 25 | assertEquals(Interrupted.message, "interrupted"); 26 | assertEquals(Interrupted.cause, error); 27 | 28 | const notCapable = new Deno.core.NotCapable("not capable", { cause: error }); 29 | assertEquals(notCapable.message, "not capable"); 30 | assertEquals(notCapable.cause, error); 31 | }); 32 | -------------------------------------------------------------------------------- /testing/unit/microtask_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { test } from "checkin:testing"; 3 | 4 | test(async function testQueueMicrotask() { 5 | await new Promise((r) => 6 | queueMicrotask(() => { 7 | console.log("In microtask!"); 8 | r(null); 9 | }) 10 | ); 11 | }); 12 | -------------------------------------------------------------------------------- /testing/unit/ops_async_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { assert, assertStackTraceEquals, test } from "checkin:testing"; 3 | import { 4 | asyncPromiseId, 5 | asyncYield, 6 | barrierAwait, 7 | barrierCreate, 8 | } from "checkin:async"; 9 | import { asyncThrow } from "checkin:error"; 10 | 11 | // Test that stack traces from async ops are all sane 12 | test(async function testAsyncThrow() { 13 | try { 14 | await asyncThrow("eager"); 15 | } catch (e) { 16 | assertStackTraceEquals( 17 | e.stack, 18 | `TypeError: Error 19 | at asyncThrow (checkin:error:line:col) 20 | at testAsyncThrow (test:///unit/ops_async_test.ts:line:col) 21 | `, 22 | ); 23 | } 24 | try { 25 | await asyncThrow("lazy"); 26 | } catch (e) { 27 | assertStackTraceEquals( 28 | e.stack, 29 | `TypeError: Error 30 | at async asyncThrow (checkin:error:line:col) 31 | at async testAsyncThrow (test:///unit/ops_async_test.ts:line:col) 32 | `, 33 | ); 34 | } 35 | try { 36 | await asyncThrow("deferred"); 37 | } catch (e) { 38 | assertStackTraceEquals( 39 | e.stack, 40 | `TypeError: Error 41 | at async asyncThrow (checkin:error:line:col) 42 | at async testAsyncThrow (test:///unit/ops_async_test.ts:line:col)`, 43 | ); 44 | } 45 | }); 46 | 47 | test(async function testAsyncOp() { 48 | await asyncYield(); 49 | }); 50 | 51 | // Test a large number of async ops resolving at the same time. This stress-tests both 52 | // large-batch op dispatch and the JS-side promise-tracking implementation. 53 | test(async function testAsyncBarrier() { 54 | const count = 1e6; 55 | barrierCreate("barrier", count); 56 | const promises = []; 57 | for (let i = 0; i < count; i++) { 58 | promises.push(barrierAwait("barrier")); 59 | } 60 | await Promise.all(promises); 61 | }); 62 | 63 | test(async function promiseId() { 64 | const id = await asyncPromiseId(); 65 | 66 | assert(typeof id === "number"); 67 | assert(id > 0); 68 | }); 69 | -------------------------------------------------------------------------------- /testing/unit/ops_buffer_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { assertArrayEquals, test } from "checkin:testing"; 3 | const { 4 | op_v8slice_store, 5 | op_v8slice_clone, 6 | } = Deno.core.ops; 7 | 8 | // Cloning a buffer should result in the same buffer being returned 9 | test(function testBufferStore() { 10 | const data = new Uint8Array(1024 * 1024); 11 | op_v8slice_store("buffer", data); 12 | const output = op_v8slice_clone("buffer"); 13 | assertArrayEquals(output, new Uint8Array(1024 * 1024)); 14 | }); 15 | 16 | // Ensure that the returned buffer size is correct when a buffer is resized 17 | // externally via `ArrayBuffer.transfer`. 18 | test(function testBufferTransfer() { 19 | const data = new Uint8Array(1024 * 1024); 20 | const buffer = data.buffer; 21 | op_v8slice_store("buffer", data); 22 | buffer.transfer(100); 23 | const output = op_v8slice_clone("buffer"); 24 | // Note: after https://chromium-review.googlesource.com/c/v8/v8/+/5394731 landed, the underlying 25 | // AB backingstore is no longer resized. 26 | assertArrayEquals(output, new Uint8Array(1024 * 1024)); 27 | }); 28 | -------------------------------------------------------------------------------- /testing/unit/ops_error_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { assertEquals, test } from "checkin:testing"; 3 | import { throwCustomErrorWithCode } from "checkin:error"; 4 | 5 | test(function additionalPropertyIsWritable() { 6 | try { 7 | throwCustomErrorWithCode("foo", 1); 8 | } catch (e) { 9 | assertEquals(e.message, "foo"); 10 | assertEquals(e.code, 1); 11 | e.code = 2; 12 | } 13 | }); 14 | -------------------------------------------------------------------------------- /testing/unit/serialize_deserialize_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { assertArrayEquals, assertEquals, test } from "checkin:testing"; 3 | 4 | test(function testIssue20727() { 5 | // https://github.com/denoland/deno/issues/20727 6 | const ab = new ArrayBuffer(10); 7 | const transferList = [ab]; 8 | Deno.core.serialize( 9 | { ab }, 10 | { transferredArrayBuffers: transferList }, 11 | ); 12 | 13 | // The shared_array_buffer_store replaces this with a number 14 | assertEquals(typeof transferList[0], "number"); 15 | }); 16 | 17 | test(function testIssue20727b() { 18 | const data = { 19 | array1: new Uint32Array([]), 20 | array2: new Float32Array([]), 21 | }; 22 | const transferList = [ 23 | data.array1.buffer, 24 | data.array2.buffer, 25 | ]; 26 | const serializedMultipleTransferredBuffers = Deno.core.serialize( 27 | { id: 2, data }, 28 | { transferredArrayBuffers: transferList }, 29 | ); 30 | 31 | // The shared_array_buffer_store replaces these with a number 32 | assertEquals(typeof transferList[0], "number"); 33 | assertEquals(typeof transferList[1], "number"); 34 | 35 | // should not throw 36 | Deno.core.deserialize( 37 | serializedMultipleTransferredBuffers, 38 | { transferredArrayBuffers: transferList }, 39 | ); 40 | }); 41 | 42 | test(function testEmptyString() { 43 | const emptyString = ""; 44 | const emptyStringSerialized = [255, 15, 34, 0]; 45 | assertArrayEquals( 46 | Deno.core.serialize(emptyString), 47 | emptyStringSerialized, 48 | ); 49 | assertEquals( 50 | Deno.core.deserialize( 51 | new Uint8Array(emptyStringSerialized), 52 | ), 53 | emptyString, 54 | ); 55 | }); 56 | 57 | test(function testPrimitiveArray() { 58 | const primitiveValueArray = ["test", "a", null, undefined]; 59 | // deno-fmt-ignore 60 | const primitiveValueArraySerialized = [ 61 | 255, 15, 65, 4, 34, 4, 116, 101, 115, 116, 62 | 34, 1, 97, 48, 95, 36, 0, 4, 63 | ]; 64 | assertArrayEquals( 65 | Deno.core.serialize(primitiveValueArray), 66 | primitiveValueArraySerialized, 67 | ); 68 | assertArrayEquals( 69 | Deno.core.deserialize( 70 | new Uint8Array(primitiveValueArraySerialized), 71 | ), 72 | primitiveValueArray, 73 | ); 74 | }); 75 | 76 | test(function testCircularObject() { 77 | const circularObject = { test: null as unknown, test2: "dd", test3: "aa" }; 78 | circularObject.test = circularObject; 79 | // deno-fmt-ignore 80 | const circularObjectSerialized = [ 81 | 255, 15, 111, 34, 4, 116, 101, 115, 82 | 116, 94, 0, 34, 5, 116, 101, 115, 83 | 116, 50, 34, 2, 100, 100, 34, 5, 84 | 116, 101, 115, 116, 51, 34, 2, 97, 85 | 97, 123, 3, 86 | ]; 87 | assertArrayEquals( 88 | Deno.core.serialize(circularObject), 89 | circularObjectSerialized, 90 | ); 91 | 92 | const deserializedCircularObject = Deno.core.deserialize( 93 | new Uint8Array(circularObjectSerialized), 94 | ); 95 | assertEquals(deserializedCircularObject.test, deserializedCircularObject); 96 | }); 97 | -------------------------------------------------------------------------------- /testing/unit/task_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { test } from "checkin:testing"; 3 | 4 | const { op_task_submit } = Deno.core.ops; 5 | 6 | test(async function testTaskSubmit1() { 7 | const { promise, resolve } = Promise.withResolvers(); 8 | op_task_submit(() => { 9 | resolve(undefined); 10 | }); 11 | await promise; 12 | }); 13 | 14 | test(async function testTaskSubmit2() { 15 | for (let i = 0; i < 2; i++) { 16 | const { promise, resolve } = Promise.withResolvers(); 17 | op_task_submit(() => { 18 | resolve(undefined); 19 | }); 20 | await promise; 21 | } 22 | }); 23 | 24 | test(async function testTaskSubmit3() { 25 | for (let i = 0; i < 3; i++) { 26 | const { promise, resolve } = Promise.withResolvers(); 27 | op_task_submit(() => { 28 | resolve(undefined); 29 | }); 30 | await promise; 31 | } 32 | }); 33 | 34 | test(async function testTaskSubmit100() { 35 | for (let i = 0; i < 100; i++) { 36 | const { promise, resolve } = Promise.withResolvers(); 37 | op_task_submit(() => { 38 | resolve(undefined); 39 | }); 40 | await promise; 41 | } 42 | }); 43 | -------------------------------------------------------------------------------- /testing/unit/tc39_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { assert, fail, test } from "checkin:testing"; 3 | 4 | // Verify that "array by copy" proposal is enabled (https://github.com/tc39/proposal-change-array-by-copy) 5 | test(function testArrayByCopy() { 6 | const a = [1, 2, 3]; 7 | const b = a.toReversed(); 8 | if (!(a[0] === 1 && a[1] === 2 && a[2] === 3)) { 9 | fail("Expected a to be intact"); 10 | } 11 | if (!(b[0] === 3 && b[1] === 2 && b[2] === 1)) { 12 | fail("Expected b to be reversed"); 13 | } 14 | }); 15 | 16 | // Verify that "Array.fromAsync" proposal is enabled (https://github.com/tc39/proposal-array-from-async) 17 | test(async function testArrayFromAsync() { 18 | const b = await Array.fromAsync(new Map([[1, 2], [3, 4]])); 19 | if (b[0][0] !== 1 || b[0][1] !== 2 || b[1][0] !== 3 || b[1][1] !== 4) { 20 | fail("failed"); 21 | } 22 | }); 23 | 24 | // Verify that "Iterator helpers" proposal is enabled (https://github.com/tc39/proposal-iterator-helpers) 25 | test(function testIteratorHelpers() { 26 | function* naturals() { 27 | let i = 0; 28 | while (true) { 29 | yield i; 30 | i += 1; 31 | } 32 | } 33 | 34 | // @ts-expect-error: Not available in TypeScript yet 35 | const a = naturals().take(5).toArray(); 36 | if (a[0] !== 0 || a[1] !== 1 || a[2] !== 2 || a[3] !== 3 || a[4] !== 4) { 37 | fail("failed"); 38 | } 39 | }); 40 | 41 | // Verify that "Set methods" proposal is enabled (https://github.com/tc39/proposal-set-methods) 42 | test(function testSetMethods() { 43 | const a: Set = new Set([1, 2, 3]).intersection(new Set([3, 4, 5])); 44 | if (a.size !== 1 && !a.has(3)) { 45 | fail("failed"); 46 | } 47 | }); 48 | 49 | // Verify that the "Temporal" proposal is enabled (https://github.com/tc39/proposal-temporal) 50 | test(function testTemporal() { 51 | // @ts-expect-error: Not available in TypeScript yet 52 | assert(typeof Temporal !== "undefined"); 53 | }); 54 | 55 | // Verify that the "Float16Array" proposal is enabled (https://github.com/tc39/proposal-float16array) 56 | test(function testFloat16Array() { 57 | // @ts-expect-error: Not available in TypeScript yet 58 | const a = new Float16Array([Math.PI]); 59 | assert(a[0] === 3.140625); 60 | // @ts-expect-error: Not available in TypeScript yet 61 | assert(typeof DataView.prototype.getFloat16 !== "undefined"); 62 | // @ts-expect-error: Not available in TypeScript yet 63 | assert(typeof DataView.prototype.setFloat16 !== "undefined"); 64 | }); 65 | -------------------------------------------------------------------------------- /testing/unit/test_test.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | import { assert, test } from "checkin:testing"; 3 | 4 | test(function testAssert() { 5 | assert(true); 6 | }); 7 | -------------------------------------------------------------------------------- /tools/create_pr_for_release.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S deno run -A --lock=tools/deno.lock.json 2 | // Copyright 2018-2025 the Deno authors. MIT license. 3 | import { DenoWorkspace } from "./deno_core_workspace.ts"; 4 | import { $, createOctoKit, getGitHubRepository } from "./deps.ts"; 5 | 6 | const octoKit = createOctoKit(); 7 | const workspace = await DenoWorkspace.load(); 8 | const repo = workspace.repo; 9 | const denoCoreCrate = workspace.getDenoCoreCrate(); 10 | 11 | // increment the core version 12 | await denoCoreCrate.increment("minor"); 13 | 14 | // increment the dependency crate versions 15 | for (const crate of workspace.getDenoCoreDependencyCrates()) { 16 | await crate.increment("minor"); 17 | } 18 | 19 | // update the lock file 20 | await workspace.getDenoCoreCrate().cargoUpdate("--workspace"); 21 | 22 | const originalBranch = await repo.gitCurrentBranch(); 23 | const newBranchName = `release_${denoCoreCrate.version.replace(/\./, "_")}`; 24 | 25 | // Create and push branch 26 | $.logStep(`Creating branch ${newBranchName}...`); 27 | await repo.gitBranch(newBranchName); 28 | await repo.gitAdd(); 29 | await repo.gitCommit(denoCoreCrate.version); 30 | $.logStep("Pushing branch..."); 31 | await repo.gitPush("-u", "origin", "HEAD"); 32 | 33 | // Open PR 34 | $.logStep("Opening PR..."); 35 | const openedPr = await octoKit.request("POST /repos/{owner}/{repo}/pulls", { 36 | ...getGitHubRepository(), 37 | base: originalBranch, 38 | head: newBranchName, 39 | draft: false, 40 | title: denoCoreCrate.version, 41 | body: getPrBody(), 42 | }); 43 | $.log(`Opened PR at ${openedPr.data.url}`); 44 | 45 | function getPrBody() { 46 | let text = `Bumped versions for ${denoCoreCrate.version}\n\n` + 47 | `Please ensure:\n` + 48 | `- [ ] Crate versions are bumped correctly\n` + 49 | `To make edits to this PR:\n` + 50 | "```shell\n" + 51 | `git fetch upstream ${newBranchName} && git checkout -b ${newBranchName} upstream/${newBranchName}\n` + 52 | "```\n"; 53 | 54 | const actor = Deno.env.get("GH_WORKFLOW_ACTOR"); 55 | if (actor != null) { 56 | text += `\ncc @${actor}`; 57 | } 58 | 59 | return text; 60 | } 61 | -------------------------------------------------------------------------------- /tools/deno_core_workspace.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | import { $, Crate, Repo } from "./deps.ts"; 4 | 5 | export { Crate }; 6 | 7 | export class DenoWorkspace { 8 | #repo: Repo; 9 | 10 | static get rootDirPath() { 11 | return $.path(import.meta).join("../../").resolve().toString(); 12 | } 13 | 14 | static async load(): Promise { 15 | return new DenoWorkspace( 16 | await Repo.load({ 17 | name: "deno_core", 18 | path: DenoWorkspace.rootDirPath, 19 | }), 20 | ); 21 | } 22 | 23 | private constructor(repo: Repo) { 24 | this.#repo = repo; 25 | } 26 | 27 | get repo() { 28 | return this.#repo; 29 | } 30 | 31 | static get manifest() { 32 | return $.path.join(this.rootDirPath, "Cargo.toml"); 33 | } 34 | 35 | get crates() { 36 | return this.#repo.crates; 37 | } 38 | 39 | /** Gets the deno_core dependency crates that should be published. */ 40 | getDenoCoreDependencyCrates() { 41 | return this.getDenoCoreCrate() 42 | .immediateDependenciesInRepo().map((c) => c.crate); 43 | } 44 | 45 | getDenoCoreCrate() { 46 | return this.getCrate("deno_core"); 47 | } 48 | 49 | getCrate(name: string) { 50 | return this.#repo.getCrate(name); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /tools/deps.ts: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | 3 | export * from "https://raw.githubusercontent.com/denoland/automation/0.19.0/mod.ts"; 4 | export * from "https://raw.githubusercontent.com/denoland/automation/0.19.0/github_actions.ts"; 5 | -------------------------------------------------------------------------------- /tools/format.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S deno run --quiet --allow-read --allow-write --allow-run --allow-env 2 | // Copyright 2018-2025 the Deno authors. MIT license. 3 | import { main } from "./check.ts"; 4 | 5 | await main("format", Deno.args[0]); 6 | -------------------------------------------------------------------------------- /tools/import_map.json: -------------------------------------------------------------------------------- 1 | { 2 | "imports": { 3 | "ext:core/mod.js": "../testing/checkin.d.ts", 4 | "ext:core/ops": "../testing/ops.d.ts", 5 | "checkin:async": "../testing/checkin/runtime/async.ts", 6 | "checkin:console": "../testing/checkin/runtime/console.ts", 7 | "checkin:error": "../testing/checkin/runtime/error.ts", 8 | "checkin:testing": "../testing/checkin/runtime/testing.ts", 9 | "checkin:throw": "../testing/checkin/runtime/throw.ts", 10 | "checkin:timers": "../testing/checkin/runtime/timers.ts", 11 | "checkin:worker": "../testing/checkin/runtime/worker.ts" 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tools/lint.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S deno run --quiet --allow-read --allow-write --allow-run --allow-env 2 | // Copyright 2018-2025 the Deno authors. MIT license. 3 | import { main } from "./check.ts"; 4 | 5 | await main("lint", Deno.args[0]); 6 | -------------------------------------------------------------------------------- /tools/publish_dry_run.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env -S deno run -A --lock=tools/deno.lock.json 2 | // Copyright 2018-2025 the Deno authors. MIT license. 3 | import { Crate, DenoWorkspace } from "./deno_core_workspace.ts"; 4 | 5 | const workspace = await DenoWorkspace.load(); 6 | const repo = workspace.repo; 7 | const denoCoreCrate = workspace.getDenoCoreCrate(); 8 | 9 | const allCrates: { [key: string]: Crate } = {}; 10 | allCrates[denoCoreCrate.name] = denoCoreCrate; 11 | 12 | for (const crate of workspace.getDenoCoreDependencyCrates()) { 13 | allCrates[crate.name] = crate; 14 | } 15 | 16 | // We have the crates in the correct publish order here 17 | const cratesInOrder = repo.getCratesPublishOrder().map((c) => allCrates[c.name]) 18 | .filter((c) => !!c); 19 | 20 | for (const crate of cratesInOrder) { 21 | await crate.increment("minor"); 22 | } 23 | 24 | const originalManifest = Deno.readTextFileSync(DenoWorkspace.manifest); 25 | let manifest = originalManifest; 26 | for (const crate of cratesInOrder) { 27 | const re = new RegExp(`^(\\b${crate.name}\\b\\s=.*)}$`, "gm"); 28 | manifest = manifest.replace(re, '$1, registry = "upstream" }'); 29 | } 30 | 31 | Deno.writeTextFileSync(DenoWorkspace.manifest, manifest); 32 | 33 | for (const crate of cratesInOrder) { 34 | await crate.publish( 35 | "-p", 36 | crate.name, 37 | "--allow-dirty", 38 | "--registry", 39 | "upstream", 40 | "--token", 41 | "Zy9HhJ02RJmg0GCrgLfaCVfU6IwDfhXD", 42 | "--config", 43 | 'registries.upstream.index="sparse+http://localhost:8000/api/v1/crates/"', 44 | ); 45 | } 46 | -------------------------------------------------------------------------------- /tools/util.js: -------------------------------------------------------------------------------- 1 | // Copyright 2018-2025 the Deno authors. MIT license. 2 | export const ROOT_PATH = Deno.realPathSync(new URL("..", import.meta.url)); 3 | 4 | async function getFilesFromGit(baseDir, args) { 5 | const { success, stdout } = await new Deno.Command("git", { 6 | stderr: "inherit", 7 | args, 8 | }).output(); 9 | const output = new TextDecoder().decode(stdout); 10 | if (!success) { 11 | throw new Error("gitLsFiles failed"); 12 | } 13 | 14 | const files = output 15 | .split("\0") 16 | .filter((line) => line.length > 0) 17 | .map( 18 | (filePath) => { 19 | try { 20 | return Deno.realPathSync(baseDir + "/" + filePath); 21 | } catch { 22 | return null; 23 | } 24 | }, 25 | ) 26 | .filter((x) => !!x); 27 | 28 | return files; 29 | } 30 | 31 | function gitLsFiles(baseDir, patterns) { 32 | baseDir = Deno.realPathSync(baseDir); 33 | const cmd = [ 34 | "-C", 35 | baseDir, 36 | "ls-files", 37 | "-z", 38 | "--exclude-standard", 39 | "--cached", 40 | "--modified", 41 | "--others", 42 | "--", 43 | ...patterns, 44 | ]; 45 | return getFilesFromGit(baseDir, cmd); 46 | } 47 | 48 | /** List all files staged for commit */ 49 | function gitStaged(baseDir, patterns) { 50 | baseDir = Deno.realPathSync(baseDir); 51 | const cmd = [ 52 | "-C", 53 | baseDir, 54 | "diff", 55 | "--staged", 56 | "--diff-filter=ACMR", 57 | "--name-only", 58 | "-z", 59 | "--", 60 | ...patterns, 61 | ]; 62 | return getFilesFromGit(baseDir, cmd); 63 | } 64 | 65 | /** 66 | * Recursively list all files in (a subdirectory of) a git worktree. 67 | * * Optionally, glob patterns may be specified to e.g. only list files with a 68 | * certain extension. 69 | * * Untracked files are included, unless they're listed in .gitignore. 70 | * * Directory names themselves are not listed (but the files inside are). 71 | * * Submodules and their contents are ignored entirely. 72 | * * This function fails if the query matches no files. 73 | * 74 | * If --staged argument was provided when program is run 75 | * only staged sources will be returned. 76 | */ 77 | export async function getSources(baseDir, patterns) { 78 | const stagedOnly = Deno.args.includes("--staged"); 79 | 80 | if (stagedOnly) { 81 | return await gitStaged(baseDir, patterns); 82 | } else { 83 | return await gitLsFiles(baseDir, patterns); 84 | } 85 | } 86 | --------------------------------------------------------------------------------