1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

refactor(ops): Adding op2 macro and implementing in a couple of places (#19534)

This is a new op system that will eventually replace `#[op]`. 

Features
 - More maintainable, generally less-coupled code
 - More modern Rust proc-macro libraries
- Enforces correct `fast` labelling for fast ops, allowing for visual
scanning of fast ops
 - Explicit marking of `#[string]`, `#[serde]` and `#[smi]` parameters.

This first version of op2 supports integer and Option<integer>
parameters only, and allows us to start working on converting ops and
adding features.
This commit is contained in:
Matt Mastracci 2023-06-24 13:54:10 +02:00 committed by GitHub
parent 8d6dbda90e
commit 65d9bfb533
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 1798 additions and 112 deletions

View file

@ -5,7 +5,7 @@ import * as yaml from "https://deno.land/std@0.173.0/encoding/yaml.ts";
// Bump this number when you want to purge the cache.
// Note: the tools/release/01_bump_crate_versions.ts script will update this version
// automatically via regex, so ensure that this line maintains this format.
const cacheVersion = 40;
const cacheVersion = 41;
const Runners = (() => {
const ubuntuRunner = "ubuntu-22.04";

View file

@ -298,8 +298,8 @@ jobs:
path: |-
~/.cargo/registry/index
~/.cargo/registry/cache
key: '40-cargo-home-${{ matrix.os }}-${{ hashFiles(''Cargo.lock'') }}'
restore-keys: '40-cargo-home-${{ matrix.os }}'
key: '41-cargo-home-${{ matrix.os }}-${{ hashFiles(''Cargo.lock'') }}'
restore-keys: '41-cargo-home-${{ matrix.os }}'
if: '!(github.event_name == ''pull_request'' && matrix.skip_pr)'
- name: Restore cache build output (PR)
uses: actions/cache/restore@v3
@ -311,7 +311,7 @@ jobs:
!./target/*/*.zip
!./target/*/*.tar.gz
key: never_saved
restore-keys: '40-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-'
restore-keys: '41-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-'
- name: Apply and update mtime cache
if: '!(github.event_name == ''pull_request'' && matrix.skip_pr) && (!startsWith(github.ref, ''refs/tags/''))'
uses: ./.github/mtime_cache
@ -592,7 +592,7 @@ jobs:
!./target/*/gn_out
!./target/*/*.zip
!./target/*/*.tar.gz
key: '40-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
key: '41-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
publish-canary:
name: publish canary
runs-on: ubuntu-22.04

259
Cargo.lock generated
View file

@ -191,8 +191,8 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
"synstructure",
]
@ -203,8 +203,8 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -215,8 +215,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c704e2f6ee1a98223f5a7629a6ef0f3decb3b552ed282889dc957edff98ce1e6"
dependencies = [
"pmutil",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"swc_macros_common",
"syn 1.0.109",
]
@ -266,8 +266,8 @@ version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -277,9 +277,9 @@ version = "0.1.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"syn 2.0.13",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 2.0.18",
]
[[package]]
@ -300,8 +300,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7862e21c893d65a1650125d157eaeec691439379a1cee17ee49031b79236ada4"
dependencies = [
"proc-macro-error",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -716,7 +716,7 @@ version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
dependencies = [
"quote 1.0.26",
"quote 1.0.28",
"syn 1.0.109",
]
@ -871,6 +871,29 @@ dependencies = [
"zstd",
]
[[package]]
name = "deno-proc-macro-rules"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c65c2ffdafc1564565200967edc4851c7b55422d3913466688907efd05ea26f"
dependencies = [
"deno-proc-macro-rules-macros",
"proc-macro2 1.0.60",
"syn 2.0.18",
]
[[package]]
name = "deno-proc-macro-rules-macros"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3047b312b7451e3190865713a4dd6e1f821aed614ada219766ebc3024a690435"
dependencies = [
"once_cell",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 2.0.18",
]
[[package]]
name = "deno_ast"
version = "0.27.0"
@ -1317,18 +1340,24 @@ dependencies = [
name = "deno_ops"
version = "0.69.0"
dependencies = [
"deno-proc-macro-rules",
"lazy-regex",
"once_cell",
"pmutil",
"pretty_assertions",
"prettyplease",
"proc-macro-crate",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"regex",
"strum",
"strum_macros",
"syn 1.0.109",
"syn 2.0.18",
"testing_macros",
"thiserror",
"trybuild",
"v8",
]
[[package]]
@ -1537,8 +1566,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321"
dependencies = [
"convert_case",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"rustc_version 0.4.0",
"syn 1.0.109",
]
@ -1585,8 +1614,8 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -1727,8 +1756,8 @@ dependencies = [
"byteorder",
"lazy_static",
"proc-macro-error",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -1848,8 +1877,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116"
dependencies = [
"heck",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -2030,8 +2059,8 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "479cde5eb168cf5a056dd98f311cbfab7494c216394e4fb9eba0336827a8db93"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -2078,7 +2107,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d449976075322384507443937df2f1d5577afbf4282f12a5a66ef29fa3e6307"
dependencies = [
"pmutil",
"proc-macro2 1.0.56",
"proc-macro2 1.0.60",
"swc_macros_common",
"syn 1.0.109",
]
@ -2167,9 +2196,9 @@ version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"syn 2.0.13",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 2.0.18",
]
[[package]]
@ -2646,8 +2675,8 @@ checksum = "8a7d079e129b77477a49c5c4f1cfe9ce6c2c909ef52520693e8e811a714c7b20"
dependencies = [
"Inflector",
"pmutil",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -2761,8 +2790,8 @@ version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8edfc11b8f56ce85e207e62ea21557cfa09bb24a8f6b04ae181b086ff8611c22"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"regex",
"syn 1.0.109",
]
@ -3085,8 +3114,8 @@ dependencies = [
name = "napi_sym"
version = "0.39.0"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"serde",
"serde_json",
"syn 1.0.109",
@ -3511,8 +3540,8 @@ dependencies = [
"phf_generator",
"phf_shared",
"proc-macro-hack",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -3540,8 +3569,8 @@ version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -3601,8 +3630,8 @@ version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -3648,7 +3677,7 @@ version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.60",
"syn 1.0.109",
]
@ -3678,8 +3707,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
"version_check",
]
@ -3690,8 +3719,8 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"version_check",
]
@ -3712,9 +3741,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.56"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
dependencies = [
"unicode-ident",
]
@ -3766,11 +3795,11 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.26"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
dependencies = [
"proc-macro2 1.0.56",
"proc-macro2 1.0.60",
]
[[package]]
@ -4117,8 +4146,8 @@ version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "107c3d5d7f370ac09efa62a78375f94d94b8a33c61d8c278b96683fb4dbf2d8d"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -4314,9 +4343,9 @@ version = "1.0.157"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78997f4555c22a7971214540c4a661291970619afd56de19f77e0de86296e1e5"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"syn 2.0.13",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 2.0.18",
]
[[package]]
@ -4337,8 +4366,8 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fe39d9fbb0ebf5eb2c7cb7e2a47e4f462fad1379f1166b8ae49ad9eae89a7ca"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -4590,8 +4619,8 @@ checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
]
[[package]]
@ -4601,8 +4630,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0090512bdfee4b56d82480d66c0fd8a6f53f0fe0f97e075e949b252acdd482e0"
dependencies = [
"pmutil",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"swc_macros_common",
"syn 1.0.109",
]
@ -4613,6 +4642,28 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "strum"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
dependencies = [
"heck",
"proc-macro2 1.0.60",
"quote 1.0.28",
"rustversion",
"syn 1.0.109",
]
[[package]]
name = "subtle"
version = "2.4.1"
@ -4711,8 +4762,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dadb9998d4f5fc36ef558ed5a092579441579ee8c6fcce84a5228cca9df4004"
dependencies = [
"pmutil",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"swc_macros_common",
"syn 1.0.109",
]
@ -4760,8 +4811,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4ee0caee1018808d94ecd09490cb7affd3d504b19aa11c49238f5fc4b54901"
dependencies = [
"pmutil",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"swc_macros_common",
"syn 1.0.109",
]
@ -4856,8 +4907,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "984d5ac69b681fc5438f9abf82b0fda34fe04e119bc75f8213b7e01128c7c9a2"
dependencies = [
"pmutil",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"swc_macros_common",
"syn 1.0.109",
]
@ -4987,8 +5038,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c20468634668c2bbab581947bb8c75c97158d5a6959f4ba33df20983b20b4f6"
dependencies = [
"pmutil",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -5024,8 +5075,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e582c3e3c2269238524923781df5be49e011dbe29cf7683a2215d600a562ea6"
dependencies = [
"pmutil",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -5047,8 +5098,8 @@ checksum = "4cfc226380ba54a5feed2c12f3ccd33f1ae8e959160290e5d2d9b4e918b6472a"
dependencies = [
"Inflector",
"pmutil",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"swc_macros_common",
"syn 1.0.109",
]
@ -5070,19 +5121,19 @@ version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.13"
version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec"
checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"unicode-ident",
]
@ -5092,8 +5143,8 @@ version = "0.12.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
"unicode-xid 0.2.4",
]
@ -5195,8 +5246,8 @@ dependencies = [
"glob",
"once_cell",
"pmutil",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"regex",
"relative-path",
"syn 1.0.109",
@ -5232,9 +5283,9 @@ version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"syn 2.0.13",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 2.0.18",
]
[[package]]
@ -5304,9 +5355,9 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"syn 2.0.13",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 2.0.18",
]
[[package]]
@ -5443,8 +5494,8 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ebd99eec668d0a450c177acbc4d05e0d0d13b1f8d3db13cd706c52cbec4ac04"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -5472,8 +5523,8 @@ version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
]
@ -5840,8 +5891,8 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
]
[[package]]
@ -5896,8 +5947,8 @@ dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
"wasm-bindgen-shared",
]
@ -5920,7 +5971,7 @@ version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
dependencies = [
"quote 1.0.26",
"quote 1.0.28",
"wasm-bindgen-macro-support",
]
@ -5930,8 +5981,8 @@ version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
@ -6265,8 +6316,8 @@ version = "1.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44bf07cb3e50ea2003396695d58bf46bc9887a1f362260446fad6bc4e79bd36c"
dependencies = [
"proc-macro2 1.0.56",
"quote 1.0.26",
"proc-macro2 1.0.60",
"quote 1.0.28",
"syn 1.0.109",
"synstructure",
]

View file

@ -131,6 +131,8 @@ signature = "=1.6.4"
slab = "0.4"
smallvec = "1.8"
socket2 = "0.4.7"
strum = { version = "0.24", features = ["derive"] }
strum_macros = "0.24"
tar = "=0.4.38"
tempfile = "3.4.0"
thiserror = "1.0.40"
@ -155,6 +157,9 @@ hkdf = "0.12.3"
proc-macro2 = "1"
quote = "1"
syn = { version = "1", features = ["full", "extra-traits"] }
syn2 = { package = "syn", version = "=2.0.18", features = ["full", "extra-traits"] }
# Temporary fork while we wait for a more modern version to be published
deno-proc-macro-rules = "0.3.2"
# unix
nix = "=0.24.2"

View file

@ -41,6 +41,7 @@ pub use url;
pub use v8;
pub use deno_ops::op;
pub use deno_ops::op2;
pub use crate::async_cancel::CancelFuture;
pub use crate::async_cancel::CancelHandle;
@ -130,6 +131,7 @@ pub fn v8_version() -> &'static str {
pub mod _ops {
pub use super::error::throw_type_error;
pub use super::error_codes::get_error_code;
pub use super::extensions::OpDecl;
pub use super::ops::to_op_result;
pub use super::ops::OpCtx;
pub use super::ops::OpResult;
@ -139,10 +141,17 @@ pub mod _ops {
pub use super::runtime::ops::map_async_op4;
pub use super::runtime::ops::queue_async_op;
pub use super::runtime::ops::queue_fast_async_op;
pub use super::runtime::ops::to_i32;
pub use super::runtime::ops::to_u32;
pub use super::runtime::V8_WRAPPER_OBJECT_INDEX;
pub use super::runtime::V8_WRAPPER_TYPE_INDEX;
}
pub(crate) mod deno_core {
pub(crate) use crate::_ops;
pub(crate) use crate::v8;
}
// TODO(mmastrac): Temporary while we move code around
pub mod snapshot_util {
pub use crate::runtime::create_snapshot;

View file

@ -11,6 +11,7 @@ use crate::OpState;
use crate::Resource;
use anyhow::Error;
use deno_ops::op;
use deno_ops::op2;
use serde_v8::ToJsBuffer;
use std::cell::RefCell;
use std::io::stderr;
@ -95,7 +96,7 @@ pub fn op_resources(state: &mut OpState) -> Vec<(ResourceId, String)> {
.collect()
}
#[op(fast)]
#[op2(core, fast)]
fn op_add(a: i32, b: i32) -> i32 {
a + b
}

View file

@ -145,3 +145,140 @@ pub fn queue_async_op<'s>(
.spawn(unsafe { crate::task::MaskFutureAsSend::new(pinned) });
None
}
macro_rules! try_number {
($n:ident $type:ident $is:ident) => {
if $n.$is() {
// SAFETY: v8 handles can be transmuted
let n: &v8::Uint32 = unsafe { std::mem::transmute($n) };
return n.value() as _;
}
};
}
pub fn to_u32(number: &v8::Value) -> u32 {
try_number!(number Uint32 is_uint32);
try_number!(number Int32 is_int32);
try_number!(number Number is_number);
if number.is_big_int() {
// SAFETY: v8 handles can be transmuted
let n: &v8::BigInt = unsafe { std::mem::transmute(number) };
return n.u64_value().0 as _;
}
0
}
pub fn to_i32(number: &v8::Value) -> i32 {
try_number!(number Uint32 is_uint32);
try_number!(number Int32 is_int32);
try_number!(number Number is_number);
if number.is_big_int() {
// SAFETY: v8 handles can be transmuted
let n: &v8::BigInt = unsafe { std::mem::transmute(number) };
return n.i64_value().0 as _;
}
0
}
#[allow(unused)]
pub fn to_u64(number: &v8::Value) -> u32 {
try_number!(number Uint32 is_uint32);
try_number!(number Int32 is_int32);
try_number!(number Number is_number);
if number.is_big_int() {
// SAFETY: v8 handles can be transmuted
let n: &v8::BigInt = unsafe { std::mem::transmute(number) };
return n.u64_value().0 as _;
}
0
}
#[allow(unused)]
pub fn to_i64(number: &v8::Value) -> i32 {
try_number!(number Uint32 is_uint32);
try_number!(number Int32 is_int32);
try_number!(number Number is_number);
if number.is_big_int() {
// SAFETY: v8 handles can be transmuted
let n: &v8::BigInt = unsafe { std::mem::transmute(number) };
return n.i64_value().0 as _;
}
0
}
#[cfg(test)]
mod tests {
use crate::FastString;
use crate::JsRuntime;
use crate::RuntimeOptions;
use deno_ops::op2;
crate::extension!(testing, ops = [op_test_add, op_test_add_option]);
/// Run a test for a single op.
fn run_test(
op: &'static str,
test: &'static str,
f: impl FnOnce(Result<&v8::Value, anyhow::Error>, &mut v8::HandleScope),
) {
let mut runtime = JsRuntime::new(RuntimeOptions {
extensions: vec![testing::init_ops_and_esm()],
..Default::default()
});
let value: Result<v8::Global<v8::Value>, anyhow::Error> = runtime
.execute_script(
"",
FastString::Owned(
format!("const {{ {op} }} = Deno.core.ensureFastOps(); {test}")
.into(),
),
);
let mut scope: v8::HandleScope =
// SAFETY: transmute for test (this lifetime should be safe for this purpose)
unsafe { std::mem::transmute(runtime.handle_scope()) };
match value {
Ok(value) => {
let value = value.open(&mut scope);
f(Ok(value), &mut scope)
}
Err(err) => f(Err(err), &mut scope),
}
}
#[op2(core, fast)]
pub fn op_test_add(a: u32, b: u32) -> u32 {
a + b
}
#[tokio::test]
pub async fn test_op_add() -> Result<(), Box<dyn std::error::Error>> {
run_test("op_test_add", "op_test_add(1, 11)", |value, scope| {
assert_eq!(value.unwrap().int32_value(scope), Some(12));
});
Ok(())
}
#[op2(core)]
pub fn op_test_add_option(a: u32, b: Option<u32>) -> u32 {
a + b.unwrap_or(100)
}
#[tokio::test]
pub async fn test_op_add_option() -> Result<(), Box<dyn std::error::Error>> {
run_test(
"op_test_add_option",
"op_test_add_option(1, 11)",
|value, scope| {
assert_eq!(value.unwrap().int32_value(scope), Some(12));
},
);
run_test(
"op_test_add_option",
"op_test_add_option(1, null)",
|value, scope| {
assert_eq!(value.unwrap().int32_value(scope), Some(101));
},
);
Ok(())
}
}

View file

@ -20,6 +20,7 @@ use cache_control::CacheControl;
use deno_core::error::AnyError;
use deno_core::futures::TryFutureExt;
use deno_core::op;
use deno_core::op2;
use deno_core::serde_v8;
use deno_core::serde_v8::from_v8;
use deno_core::task::spawn;
@ -208,8 +209,8 @@ pub async fn op_http_upgrade_websocket_next(
ws_create_server_stream(&mut state.borrow_mut(), stream, bytes)
}
#[op(fast)]
pub fn op_http_set_promise_complete(slab_id: SlabId, status: u16) {
#[op2(fast)]
pub fn op_http_set_promise_complete(#[smi] slab_id: SlabId, status: u16) {
let mut http = slab_get(slab_id);
// The Javascript code will never provide a status that is invalid here (see 23_response.js)
*http.response().status_mut() = StatusCode::from_u16(status).unwrap();

View file

@ -15,6 +15,7 @@ path = "./lib.rs"
proc-macro = true
[dependencies]
deno-proc-macro-rules.workspace = true
lazy-regex.workspace = true
once_cell.workspace = true
pmutil = "0.5.3"
@ -22,7 +23,12 @@ proc-macro-crate = "1.1.3"
proc-macro2.workspace = true
quote.workspace = true
regex.workspace = true
strum.workspace = true
strum_macros.workspace = true
syn.workspace = true
syn2.workspace = true
thiserror.workspace = true
v8.workspace = true
[dev-dependencies]
pretty_assertions.workspace = true

View file

@ -8,6 +8,7 @@ use proc_macro2::Span;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use quote::ToTokens;
use std::error::Error;
use syn::parse;
use syn::parse_macro_input;
use syn::punctuated::Punctuated;
@ -22,6 +23,7 @@ use syn::LifetimeDef;
mod attrs;
mod deno;
mod fast_call;
mod op2;
mod optimizer;
const SCOPE_LIFETIME: &str = "'scope";
@ -235,6 +237,26 @@ pub fn op(attr: TokenStream, item: TokenStream) -> TokenStream {
op.gen().into()
}
#[proc_macro_attribute]
pub fn op2(attr: TokenStream, item: TokenStream) -> TokenStream {
match crate::op2::op2(attr.into(), item.into()) {
Ok(output) => output.into(),
Err(err) => {
let mut err: &dyn Error = &err;
let mut output = "Failed to parse #[op2]:\n".to_owned();
loop {
output += &format!(" - {err}\n");
if let Some(source) = err.source() {
err = source;
} else {
break;
}
}
panic!("{output}");
}
}
}
/// Generate the body of a v8 func for an async op
fn codegen_v8_async(
core: &TokenStream2,

193
ops/op2/dispatch_fast.rs Normal file
View file

@ -0,0 +1,193 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use super::generator_state::GeneratorState;
use super::signature::Arg;
use super::signature::NumericArg;
use super::signature::ParsedSignature;
use super::signature::RetVal;
use super::V8MappingError;
use proc_macro2::TokenStream;
use quote::format_ident;
use quote::quote;
#[allow(unused)]
#[derive(Debug, Default, PartialEq, Clone)]
pub(crate) enum FastValue {
#[default]
Void,
Bool,
U32,
I32,
U64,
I64,
F32,
F64,
Pointer,
V8Value,
Uint8Array,
Uint32Array,
Float64Array,
SeqOneByteString,
}
impl FastValue {
/// Quote fast value type.
fn quote_rust_type(&self) -> TokenStream {
match self {
FastValue::Void => quote!(()),
FastValue::Bool => quote!(bool),
FastValue::U32 => quote!(u32),
FastValue::I32 => quote!(i32),
FastValue::U64 => quote!(u64),
FastValue::I64 => quote!(i64),
FastValue::F32 => quote!(f32),
FastValue::F64 => quote!(f64),
FastValue::Pointer => quote!(*mut ::std::ffi::c_void),
FastValue::V8Value => unimplemented!("v8::Local<v8::Value>"),
FastValue::Uint8Array
| FastValue::Uint32Array
| FastValue::Float64Array
| FastValue::SeqOneByteString => unreachable!(),
}
}
/// Quote fast value type's variant.
fn quote_ctype(&self) -> TokenStream {
match &self {
FastValue::Void => quote!(CType::Void),
FastValue::Bool => quote!(CType::Bool),
FastValue::U32 => quote!(CType::Uint32),
FastValue::I32 => quote!(CType::Int32),
FastValue::U64 => quote!(CType::Uint64),
FastValue::I64 => quote!(CType::Int64),
FastValue::F32 => quote!(CType::Float32),
FastValue::F64 => quote!(CType::Float64),
FastValue::Pointer => quote!(CType::Pointer),
FastValue::V8Value => quote!(CType::V8Value),
FastValue::Uint8Array => unreachable!(),
FastValue::Uint32Array => unreachable!(),
FastValue::Float64Array => unreachable!(),
FastValue::SeqOneByteString => quote!(CType::SeqOneByteString),
}
}
/// Quote fast value type's variant.
fn quote_type(&self) -> TokenStream {
match &self {
FastValue::Void => quote!(Type::Void),
FastValue::Bool => quote!(Type::Bool),
FastValue::U32 => quote!(Type::Uint32),
FastValue::I32 => quote!(Type::Int32),
FastValue::U64 => quote!(Type::Uint64),
FastValue::I64 => quote!(Type::Int64),
FastValue::F32 => quote!(Type::Float32),
FastValue::F64 => quote!(Type::Float64),
FastValue::Pointer => quote!(Type::Pointer),
FastValue::V8Value => quote!(Type::V8Value),
FastValue::Uint8Array => quote!(Type::TypedArray(CType::Uint8)),
FastValue::Uint32Array => quote!(Type::TypedArray(CType::Uint32)),
FastValue::Float64Array => quote!(Type::TypedArray(CType::Float64)),
FastValue::SeqOneByteString => quote!(Type::SeqOneByteString),
}
}
}
pub fn generate_dispatch_fast(
generator_state: &mut GeneratorState,
signature: &ParsedSignature,
) -> Result<Option<(TokenStream, TokenStream)>, V8MappingError> {
let mut inputs = vec![];
for arg in &signature.args {
let fv = match arg {
Arg::OptionNumeric(_) | Arg::SerdeV8(_) => return Ok(None),
Arg::Numeric(NumericArg::bool) => FastValue::Bool,
Arg::Numeric(NumericArg::u32)
| Arg::Numeric(NumericArg::u16)
| Arg::Numeric(NumericArg::u8) => FastValue::U32,
Arg::Numeric(NumericArg::i32)
| Arg::Numeric(NumericArg::i16)
| Arg::Numeric(NumericArg::i8)
| Arg::Numeric(NumericArg::__SMI__) => FastValue::I32,
Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
FastValue::U64
}
Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
FastValue::I64
}
_ => {
return Err(V8MappingError::NoMapping("a fast argument", arg.clone()))
}
};
inputs.push(fv);
}
let ret_val = match &signature.ret_val {
RetVal::Infallible(arg) => arg,
RetVal::Result(arg) => arg,
};
let output = match ret_val {
Arg::OptionNumeric(_) | Arg::SerdeV8(_) => return Ok(None),
Arg::Void => FastValue::Void,
Arg::Numeric(NumericArg::bool) => FastValue::Bool,
Arg::Numeric(NumericArg::u32)
| Arg::Numeric(NumericArg::u16)
| Arg::Numeric(NumericArg::u8) => FastValue::U32,
Arg::Numeric(NumericArg::i32)
| Arg::Numeric(NumericArg::i16)
| Arg::Numeric(NumericArg::i8) => FastValue::I32,
Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
FastValue::U64
}
Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
FastValue::I64
}
Arg::Special(_) => return Ok(None),
_ => {
return Err(V8MappingError::NoMapping(
"a fast return value",
ret_val.clone(),
))
}
};
let GeneratorState {
fast_function,
deno_core,
..
} = &generator_state;
let input_types = inputs.iter().map(|fv| fv.quote_type());
let output_type = output.quote_ctype();
let fast_definition = quote! {
use #deno_core::v8::fast_api::Type;
use #deno_core::v8::fast_api::CType;
#deno_core::v8::fast_api::FastFunction::new(
&[ #( #input_types ),* ],
#output_type,
Self::#fast_function as *const ::std::ffi::c_void
)
};
let output_type = output.quote_rust_type();
let names = &inputs
.iter()
.enumerate()
.map(|(i, _)| format_ident!("arg{i}"))
.collect::<Vec<_>>();
let types = inputs.iter().map(|rv| rv.quote_rust_type());
let fast_fn = quote!(
fn #fast_function(
_: #deno_core::v8::Local<#deno_core::v8::Object>,
#( #names: #types, )*
) -> #output_type {
#(
let #names = #names as _;
)*
Self::call(#(#names),*)
}
);
Ok(Some((fast_definition, fast_fn)))
}

220
ops/op2/dispatch_slow.rs Normal file
View file

@ -0,0 +1,220 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use super::generator_state::GeneratorState;
use super::signature::Arg;
use super::signature::NumericArg;
use super::signature::ParsedSignature;
use super::signature::RetVal;
use super::signature::Special;
use super::V8MappingError;
use proc_macro2::TokenStream;
use quote::quote;
pub fn generate_dispatch_slow(
generator_state: &mut GeneratorState,
signature: &ParsedSignature,
) -> Result<TokenStream, V8MappingError> {
let mut output = TokenStream::new();
for (index, arg) in signature.args.iter().enumerate() {
output.extend(extract_arg(generator_state, index)?);
output.extend(from_arg(generator_state, index, arg)?);
}
output.extend(call(generator_state));
output.extend(return_value(generator_state, &signature.ret_val));
let GeneratorState {
deno_core,
scope,
fn_args,
retval,
info,
slow_function,
..
} = &generator_state;
let with_scope = if generator_state.needs_scope {
quote!(let #scope = &mut unsafe { #deno_core::v8::CallbackScope::new(&*#info) };)
} else {
quote!()
};
let with_retval = if generator_state.needs_retval {
quote!(let mut #retval = #deno_core::v8::ReturnValue::from_function_callback_info(unsafe { &*#info });)
} else {
quote!()
};
let with_args = if generator_state.needs_args {
quote!(let #fn_args = #deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe { &*#info });)
} else {
quote!()
};
Ok(quote! {
pub extern "C" fn #slow_function(#info: *const #deno_core::v8::FunctionCallbackInfo) {
#with_scope
#with_retval
#with_args
#output
}})
}
pub fn extract_arg(
generator_state: &mut GeneratorState,
index: usize,
) -> Result<TokenStream, V8MappingError> {
let GeneratorState { fn_args, .. } = &generator_state;
let arg_ident = generator_state.args.get(index);
Ok(quote!(
let #arg_ident = #fn_args.get(#index as i32);
))
}
pub fn from_arg(
mut generator_state: &mut GeneratorState,
index: usize,
arg: &Arg,
) -> Result<TokenStream, V8MappingError> {
let GeneratorState {
deno_core, args, ..
} = &mut generator_state;
let arg_ident = args.get_mut(index).expect("Argument at index was missing");
let res = match arg {
Arg::Numeric(NumericArg::bool) => quote! {
let #arg_ident = #arg_ident.is_true();
},
Arg::Numeric(NumericArg::u8)
| Arg::Numeric(NumericArg::u16)
| Arg::Numeric(NumericArg::u32) => {
quote! {
let #arg_ident = #deno_core::_ops::to_u32(&#arg_ident) as _;
}
}
Arg::Numeric(NumericArg::i8)
| Arg::Numeric(NumericArg::i16)
| Arg::Numeric(NumericArg::i32)
| Arg::Numeric(NumericArg::__SMI__) => {
quote! {
let #arg_ident = #deno_core::_ops::to_i32(&#arg_ident) as _;
}
}
Arg::Numeric(NumericArg::u64) | Arg::Numeric(NumericArg::usize) => {
quote! {
let #arg_ident = #deno_core::_ops::to_u64(&#arg_ident) as _;
}
}
Arg::Numeric(NumericArg::i64) | Arg::Numeric(NumericArg::isize) => {
quote! {
let #arg_ident = #deno_core::_ops::to_i64(&#arg_ident) as _;
}
}
Arg::OptionNumeric(numeric) => {
// Ends the borrow of generator_state
let arg_ident = arg_ident.clone();
let some = from_arg(generator_state, index, &Arg::Numeric(*numeric))?;
quote! {
let #arg_ident = if #arg_ident.is_null_or_undefined() {
None
} else {
#some
Some(#arg_ident)
};
}
}
Arg::Option(Special::String) => {
quote! {
let #arg_ident = #arg_ident.to_rust_string_lossy();
}
}
Arg::Special(Special::RefStr) => {
quote! {
let #arg_ident = #arg_ident.to_rust_string_lossy();
}
}
_ => return Err(V8MappingError::NoMapping("a slow argument", arg.clone())),
};
Ok(res)
}
pub fn call(
generator_state: &mut GeneratorState,
) -> Result<TokenStream, V8MappingError> {
let GeneratorState { result, .. } = &generator_state;
let mut tokens = TokenStream::new();
for arg in &generator_state.args {
tokens.extend(quote!( #arg , ));
}
Ok(quote! {
let #result = Self::call( #tokens );
})
}
pub fn return_value(
generator_state: &mut GeneratorState,
ret_type: &RetVal,
) -> Result<TokenStream, V8MappingError> {
match ret_type {
RetVal::Infallible(ret_type) => {
return_value_infallible(generator_state, ret_type)
}
RetVal::Result(ret_type) => return_value_result(generator_state, ret_type),
}
}
pub fn return_value_infallible(
generator_state: &mut GeneratorState,
ret_type: &Arg,
) -> Result<TokenStream, V8MappingError> {
let GeneratorState {
result,
retval,
needs_retval,
..
} = generator_state;
let res = match ret_type {
Arg::Numeric(NumericArg::u8)
| Arg::Numeric(NumericArg::u16)
| Arg::Numeric(NumericArg::u32) => {
*needs_retval = true;
quote!(#retval.set_uint32(#result as u32);)
}
Arg::Numeric(NumericArg::i8)
| Arg::Numeric(NumericArg::i16)
| Arg::Numeric(NumericArg::i32) => {
*needs_retval = true;
quote!(#retval.set_int32(#result as i32);)
}
_ => {
return Err(V8MappingError::NoMapping(
"a slow return value",
ret_type.clone(),
))
}
};
Ok(res)
}
pub fn return_value_result(
generator_state: &mut GeneratorState,
ret_type: &Arg,
) -> Result<TokenStream, V8MappingError> {
let infallible = return_value_infallible(generator_state, ret_type)?;
let GeneratorState { result, .. } = &generator_state;
let tokens = quote!(
let result = match ret_type {
Ok(#result) => {
#infallible,
}
Err(err) => {
return;
}
}
);
Ok(tokens)
}

View file

@ -0,0 +1,32 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use proc_macro2::Ident;
use proc_macro2::TokenStream;
pub struct GeneratorState {
/// The path to the `deno_core` crate (either `deno_core` or `crate`, the latter used if the op is `(core)`).
pub deno_core: TokenStream,
/// Identifiers for each of the arguments of the original function
pub args: Vec<Ident>,
/// The new identifier for the original function's contents.
pub call: Ident,
/// The result of the `call` function
pub result: Ident,
/// The `v8::CallbackScope` used if necessary for the function.
pub scope: Ident,
/// The `v8::FunctionCallbackInfo` used to pass args into the slow function.
pub info: Ident,
/// The `v8::FunctionCallbackArguments` used to pass args into the slow function.
pub fn_args: Ident,
/// The `v8::ReturnValue` used in the slow function
pub retval: Ident,
/// The "slow" function (ie: the one that isn't a fastcall)
pub slow_function: Ident,
/// The "fast" function (ie: a fastcall)
pub fast_function: Ident,
pub needs_args: bool,
pub needs_retval: bool,
pub needs_scope: bool,
}

287
ops/op2/mod.rs Normal file
View file

@ -0,0 +1,287 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use deno_proc_macro_rules::rules;
use proc_macro2::Ident;
use proc_macro2::Span;
use proc_macro2::TokenStream;
use quote::format_ident;
use quote::quote;
use quote::ToTokens;
use std::iter::zip;
use syn2::parse2;
use syn2::FnArg;
use syn2::ItemFn;
use syn2::Path;
use thiserror::Error;
use self::dispatch_fast::generate_dispatch_fast;
use self::dispatch_slow::generate_dispatch_slow;
use self::generator_state::GeneratorState;
use self::signature::parse_signature;
use self::signature::Arg;
use self::signature::SignatureError;
pub mod dispatch_fast;
pub mod dispatch_slow;
pub mod generator_state;
pub mod signature;
#[derive(Debug, Error)]
pub enum Op2Error {
#[error("Failed to match a pattern for '{0}': (input was '{1}')")]
PatternMatchFailed(&'static str, String),
#[error("Invalid attribute: '{0}'")]
InvalidAttribute(String),
#[error("Failed to parse syntax tree")]
ParseError(#[from] syn2::Error),
#[error("Failed to map a parsed signature to a V8 call")]
V8MappingError(#[from] V8MappingError),
#[error("Failed to parse signature")]
SignatureError(#[from] SignatureError),
#[error("This op is fast-compatible and should be marked as (fast)")]
ShouldBeFast,
#[error("This op is not fast-compatible and should not be marked as (fast)")]
ShouldNotBeFast,
}
#[derive(Debug, Error)]
pub enum V8MappingError {
#[error("Unable to map {1:?} to {0}")]
NoMapping(&'static str, Arg),
}
#[derive(Default)]
struct MacroConfig {
pub core: bool,
pub fast: bool,
}
impl MacroConfig {
pub fn from_flags(flags: Vec<Ident>) -> Result<Self, Op2Error> {
let mut config: MacroConfig = Self::default();
for flag in flags {
if flag == "core" {
config.core = true;
} else if flag == "fast" {
config.fast = true;
} else {
return Err(Op2Error::InvalidAttribute(flag.to_string()));
}
}
Ok(config)
}
pub fn from_tokens(tokens: TokenStream) -> Result<Self, Op2Error> {
let attr_string = tokens.to_string();
let config = std::panic::catch_unwind(|| {
rules!(tokens => {
() => {
Ok(MacroConfig::default())
}
($($flags:ident),+) => {
Self::from_flags(flags)
}
})
})
.map_err(|_| Op2Error::PatternMatchFailed("attribute", attr_string))??;
Ok(config)
}
}
pub fn op2(
attr: TokenStream,
item: TokenStream,
) -> Result<TokenStream, Op2Error> {
let func = parse2::<ItemFn>(item)?;
let config = MacroConfig::from_tokens(attr)?;
generate_op2(config, func)
}
fn generate_op2(
config: MacroConfig,
func: ItemFn,
) -> Result<TokenStream, Op2Error> {
// Create a copy of the original function, named "call"
let call = Ident::new("call", Span::call_site());
let mut op_fn = func.clone();
op_fn.attrs.clear();
op_fn.sig.ident = call.clone();
// Clear inert attributes
// TODO(mmastrac): This should limit itself to clearing ours only
for arg in op_fn.sig.inputs.iter_mut() {
match arg {
FnArg::Receiver(slf) => slf.attrs.clear(),
FnArg::Typed(ty) => ty.attrs.clear(),
}
}
let signature = parse_signature(func.attrs, func.sig.clone())?;
let processed_args =
zip(signature.args.iter(), &func.sig.inputs).collect::<Vec<_>>();
let mut args = vec![];
let mut needs_args = false;
for (index, _) in processed_args.iter().enumerate() {
let input = format_ident!("arg{index}");
args.push(input);
needs_args = true;
}
let retval = Ident::new("rv", Span::call_site());
let result = Ident::new("result", Span::call_site());
let fn_args = Ident::new("args", Span::call_site());
let scope = Ident::new("scope", Span::call_site());
let info = Ident::new("info", Span::call_site());
let slow_function = Ident::new("slow_function", Span::call_site());
let fast_function = Ident::new("fast_function", Span::call_site());
let deno_core = if config.core {
syn2::parse_str::<Path>("crate::deno_core")
} else {
syn2::parse_str::<Path>("deno_core")
}
.expect("Parsing crate should not fail")
.into_token_stream();
let mut generator_state = GeneratorState {
args,
fn_args,
call,
scope,
info,
deno_core,
result,
retval,
needs_args,
slow_function,
fast_function,
needs_retval: false,
needs_scope: false,
};
let name = func.sig.ident;
let slow_fn = generate_dispatch_slow(&mut generator_state, &signature)?;
let (fast_definition, fast_fn) =
match generate_dispatch_fast(&mut generator_state, &signature)? {
Some((fast_definition, fast_fn)) => {
if !config.fast {
return Err(Op2Error::ShouldBeFast);
}
(quote!(Some({#fast_definition})), fast_fn)
}
None => {
if config.fast {
return Err(Op2Error::ShouldNotBeFast);
}
(quote!(None), quote!())
}
};
let GeneratorState {
deno_core,
slow_function,
..
} = &generator_state;
let arg_count: usize = generator_state.args.len();
let vis = func.vis;
Ok(quote! {
#[allow(non_camel_case_types)]
#vis struct #name {
}
impl #name {
pub const fn name() -> &'static str {
stringify!(#name)
}
pub const fn decl() -> #deno_core::_ops::OpDecl {
#deno_core::_ops::OpDecl {
name: stringify!(#name),
v8_fn_ptr: Self::#slow_function as _,
enabled: true,
fast_fn: #fast_definition,
is_async: false,
is_unstable: false,
is_v8: false,
arg_count: #arg_count as u8,
}
}
#slow_fn
#fast_fn
#[inline(always)]
#op_fn
}
})
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
use std::path::PathBuf;
use syn2::parse_str;
use syn2::File;
use syn2::Item;
#[testing_macros::fixture("op2/test_cases/**/*.rs")]
fn test_signature_parser(input: PathBuf) {
let update_expected = std::env::var("UPDATE_EXPECTED").is_ok();
let source =
std::fs::read_to_string(&input).expect("Failed to read test file");
let file = parse_str::<File>(&source).expect("Failed to parse Rust file");
let mut expected_out = vec![];
for item in file.items {
if let Item::Fn(mut func) = item {
let mut config = None;
func.attrs.retain(|attr| {
let tokens = attr.into_token_stream();
let attr_string = attr.clone().into_token_stream().to_string();
println!("{}", attr_string);
use syn2 as syn;
if let Some(new_config) = rules!(tokens => {
(#[op2]) => {
Some(MacroConfig::default())
}
(#[op2( $($x:ident),* )]) => {
Some(MacroConfig::from_flags(x).expect("Failed to parse attribute"))
}
(#[$_attr:meta]) => {
None
}
}) {
config = Some(new_config);
false
} else {
true
}
});
let tokens =
generate_op2(config.unwrap(), func).expect("Failed to generate op");
println!("======== Raw tokens ========:\n{}", tokens.clone());
let tree = syn::parse2(tokens).unwrap();
let actual = prettyplease::unparse(&tree);
println!("======== Generated ========:\n{}", actual);
expected_out.push(actual);
}
}
let expected_out = expected_out.join("\n");
if update_expected {
std::fs::write(input.with_extension("out"), expected_out)
.expect("Failed to write expectation file");
} else {
let expected = std::fs::read_to_string(input.with_extension("out"))
.expect("Failed to read expectation file");
assert_eq!(
expected, expected_out,
"Failed to match expectation. Use UPDATE_EXPECTED=1."
);
}
}
}

516
ops/op2/signature.rs Normal file
View file

@ -0,0 +1,516 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use deno_proc_macro_rules::rules;
use proc_macro2::Ident;
use proc_macro2::Span;
use quote::quote;
use quote::ToTokens;
use strum::IntoEnumIterator;
use strum::IntoStaticStr;
use strum_macros::EnumIter;
use strum_macros::EnumString;
use syn2::Attribute;
use syn2::FnArg;
use syn2::Pat;
use syn2::ReturnType;
use syn2::Signature;
use syn2::Type;
use syn2::TypePath;
use thiserror::Error;
#[allow(non_camel_case_types)]
#[derive(
Copy, Clone, Debug, Eq, PartialEq, IntoStaticStr, EnumString, EnumIter,
)]
pub enum NumericArg {
/// A placeholder argument for arguments annotated with #[smi].
__SMI__,
/// A placeholder argument for void data.
__VOID__,
bool,
i8,
u8,
i16,
u16,
i32,
u32,
i64,
u64,
f32,
f64,
isize,
usize,
}
impl ToTokens for NumericArg {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let ident = Ident::new(self.into(), Span::call_site());
tokens.extend(quote! { #ident })
}
}
#[derive(
Copy, Clone, Debug, Eq, PartialEq, IntoStaticStr, EnumString, EnumIter,
)]
pub enum V8Arg {
External,
Object,
Array,
ArrayBuffer,
ArrayBufferView,
DataView,
TypedArray,
BigInt64Array,
BigUint64Array,
Float32Array,
Float64Array,
Int16Array,
Int32Array,
Int8Array,
Uint16Array,
Uint32Array,
Uint8Array,
Uint8ClampedArray,
BigIntObject,
BooleanObject,
Date,
Function,
Map,
NumberObject,
Promise,
PromiseResolver,
Proxy,
RegExp,
Set,
SharedArrayBuffer,
StringObject,
SymbolObject,
WasmMemoryObject,
WasmModuleObject,
Primitive,
BigInt,
Boolean,
Name,
String,
Symbol,
Number,
Integer,
Int32,
Uint32,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Special {
HandleScope,
OpState,
String,
RefStr,
FastApiCallbackOptions,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum RefType {
Ref,
Mut,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Arg {
Void,
Special(Special),
Ref(RefType, Special),
RcRefCell(Special),
Option(Special),
OptionNumeric(NumericArg),
Slice(RefType, NumericArg),
Ptr(RefType, NumericArg),
V8Local(V8Arg),
Numeric(NumericArg),
SerdeV8(String),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum RetVal {
Infallible(Arg),
Result(Arg),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ParsedSignature {
pub args: Vec<Arg>,
pub names: Vec<String>,
pub ret_val: RetVal,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum AttributeModifier {
/// #[serde], for serde_v8 types.
Serde,
/// #[smi], for small integers
Smi,
/// #[string], for strings.
String,
}
#[derive(Error, Debug)]
pub enum SignatureError {
#[error("Invalid argument: {0}")]
ArgError(String, #[source] ArgError),
#[error("Invalid return type")]
RetError(#[from] ArgError),
}
#[derive(Error, Debug)]
pub enum ArgError {
#[error("Invalid self argument")]
InvalidSelf,
#[error("Invalid argument type: {0}")]
InvalidType(String),
#[error(
"Invalid argument type path (should this be #[smi] or #[serde]?): {0}"
)]
InvalidTypePath(String),
#[error("Too many attributes")]
TooManyAttributes,
#[error("Invalid #[serde] type: {0}")]
InvalidSerdeType(String),
#[error("Cannot use #[serde] for type: {0}")]
InvalidSerdeAttributeType(String),
#[error("Invalid v8 type: {0}")]
InvalidV8Type(String),
#[error("Internal error: {0}")]
InternalError(String),
#[error("Missing a #[string] attribute")]
MissingStringAttribute,
}
#[derive(Copy, Clone, Default)]
struct Attributes {
primary: Option<AttributeModifier>,
}
fn stringify_token(tokens: impl ToTokens) -> String {
tokens
.into_token_stream()
.into_iter()
.map(|s| s.to_string())
.collect::<Vec<_>>()
.join("")
}
pub fn parse_signature(
attributes: Vec<Attribute>,
signature: Signature,
) -> Result<ParsedSignature, SignatureError> {
let mut args = vec![];
let mut names = vec![];
for input in signature.inputs {
let name = match &input {
FnArg::Receiver(_) => "self".to_owned(),
FnArg::Typed(ty) => match &*ty.pat {
Pat::Ident(ident) => ident.ident.to_string(),
_ => "(complex)".to_owned(),
},
};
names.push(name.clone());
args.push(
parse_arg(input).map_err(|err| SignatureError::ArgError(name, err))?,
);
}
Ok(ParsedSignature {
args,
names,
ret_val: parse_return(parse_attributes(&attributes)?, &signature.output)?,
})
}
fn parse_attributes(attributes: &[Attribute]) -> Result<Attributes, ArgError> {
let attrs = attributes
.iter()
.filter_map(parse_attribute)
.collect::<Vec<_>>();
if attrs.is_empty() {
return Ok(Attributes::default());
}
if attrs.len() > 1 {
return Err(ArgError::TooManyAttributes);
}
Ok(Attributes {
primary: Some(*attrs.get(0).unwrap()),
})
}
fn parse_attribute(attr: &Attribute) -> Option<AttributeModifier> {
let tokens = attr.into_token_stream();
use syn2 as syn;
std::panic::catch_unwind(|| {
rules!(tokens => {
(#[serde]) => Some(AttributeModifier::Serde),
(#[smi]) => Some(AttributeModifier::Smi),
(#[string]) => Some(AttributeModifier::String),
(#[$_attr:meta]) => None,
})
})
.expect("Failed to parse an attribute")
}
fn parse_return(
attrs: Attributes,
rt: &ReturnType,
) -> Result<RetVal, ArgError> {
match rt {
ReturnType::Default => Ok(RetVal::Infallible(Arg::Void)),
ReturnType::Type(_, ty) => {
let s = stringify_token(ty);
let tokens = ty.into_token_stream();
use syn2 as syn;
std::panic::catch_unwind(|| {
rules!(tokens => {
// x::y::Result<Value>, like io::Result and other specialty result types
($($_package:ident ::)* Result < $ty:ty >) => {
Ok(RetVal::Result(parse_type(attrs, &ty)?))
}
// x::y::Result<Value, Error>
($($_package:ident ::)* Result < $ty:ty, $_error:ty >) => {
Ok(RetVal::Result(parse_type(attrs, &ty)?))
}
($ty:ty) => {
Ok(RetVal::Infallible(parse_type(attrs, &ty)?))
}
})
})
.map_err(|e| {
ArgError::InternalError(format!(
"parse_return({}) {}",
s,
e.downcast::<&str>().unwrap_or_default()
))
})?
}
}
}
fn parse_type_path(attrs: Attributes, tp: &TypePath) -> Result<Arg, ArgError> {
if tp.path.segments.len() == 1 {
let segment = tp.path.segments.first().unwrap().ident.to_string();
for numeric in NumericArg::iter() {
if Into::<&'static str>::into(numeric) == segment.as_str() {
return Ok(Arg::Numeric(numeric));
}
}
}
use syn2 as syn;
let tokens = tp.clone().into_token_stream();
std::panic::catch_unwind(|| {
rules!(tokens => {
( $( std :: str :: )? String ) => {
if attrs.primary == Some(AttributeModifier::String) {
Ok(Arg::Special(Special::String))
} else {
Err(ArgError::MissingStringAttribute)
}
}
( $( std :: ffi :: )? c_void ) => Ok(Arg::Numeric(NumericArg::__VOID__)),
( OpState ) => Ok(Arg::Special(Special::OpState)),
( v8 :: HandleScope ) => Ok(Arg::Special(Special::HandleScope)),
( v8 :: FastApiCallbackOptions ) => Ok(Arg::Special(Special::FastApiCallbackOptions)),
( v8 :: Local < $( $_scope:lifetime , )? v8 :: $v8:ident >) => Ok(Arg::V8Local(parse_v8_type(&v8)?)),
( Rc < RefCell < $ty:ty > > ) => Ok(Arg::RcRefCell(parse_type_special(attrs, &ty)?)),
( Option < $ty:ty > ) => {
match parse_type(attrs, &ty)? {
Arg::Special(special) => Ok(Arg::Option(special)),
Arg::Numeric(numeric) => Ok(Arg::OptionNumeric(numeric)),
_ => Err(ArgError::InvalidType(stringify_token(ty)))
}
}
( $any:ty ) => Err(ArgError::InvalidTypePath(stringify_token(any))),
})
}).map_err(|e| ArgError::InternalError(format!("parse_type_path {e:?}")))?
}
fn parse_v8_type(v8: &Ident) -> Result<V8Arg, ArgError> {
let v8 = v8.to_string();
V8Arg::try_from(v8.as_str()).map_err(|_| ArgError::InvalidV8Type(v8))
}
fn parse_type_special(
attrs: Attributes,
ty: &Type,
) -> Result<Special, ArgError> {
match parse_type(attrs, ty)? {
Arg::Special(special) => Ok(special),
_ => Err(ArgError::InvalidType(stringify_token(ty))),
}
}
fn parse_type(attrs: Attributes, ty: &Type) -> Result<Arg, ArgError> {
if let Some(primary) = attrs.primary {
match primary {
AttributeModifier::Serde => match ty {
Type::Path(of) => {
// If this type will parse without #[serde], it is illegal to use this type with #[serde]
if parse_type_path(Attributes::default(), of).is_ok() {
return Err(ArgError::InvalidSerdeAttributeType(stringify_token(
ty,
)));
}
return Ok(Arg::SerdeV8(stringify_token(of.path.clone())));
}
_ => return Err(ArgError::InvalidSerdeType(stringify_token(ty))),
},
AttributeModifier::String => match ty {
Type::Path(of) => {
return parse_type_path(attrs, of);
}
Type::Reference(of) => {
let mut_type = if of.mutability.is_some() {
RefType::Mut
} else {
RefType::Ref
};
let tokens = of.elem.clone().into_token_stream();
use syn2 as syn;
return rules!(tokens => {
(str) => Ok(Arg::Special(Special::RefStr)),
($_ty:ty) => Ok(Arg::Ref(mut_type, parse_type_special(attrs, &of.elem)?)),
});
}
_ => return Err(ArgError::InvalidSerdeType(stringify_token(ty))),
},
AttributeModifier::Smi => {
return Ok(Arg::Numeric(NumericArg::__SMI__));
}
}
};
match ty {
Type::Tuple(of) => {
if of.elems.is_empty() {
Ok(Arg::Void)
} else {
Err(ArgError::InvalidType(stringify_token(ty)))
}
}
Type::Reference(of) => {
let mut_type = if of.mutability.is_some() {
RefType::Mut
} else {
RefType::Ref
};
match &*of.elem {
Type::Slice(of) => match parse_type(attrs, &of.elem)? {
Arg::Numeric(numeric) => Ok(Arg::Slice(mut_type, numeric)),
_ => Err(ArgError::InvalidType(stringify_token(ty))),
},
Type::Path(of) => match parse_type_path(attrs, of)? {
Arg::Special(special) => Ok(Arg::Ref(mut_type, special)),
_ => Err(ArgError::InvalidType(stringify_token(ty))),
},
_ => Err(ArgError::InvalidType(stringify_token(ty))),
}
}
Type::Ptr(of) => {
let mut_type = if of.mutability.is_some() {
RefType::Mut
} else {
RefType::Ref
};
match &*of.elem {
Type::Path(of) => match parse_type_path(attrs, of)? {
Arg::Numeric(numeric) => Ok(Arg::Ptr(mut_type, numeric)),
_ => Err(ArgError::InvalidType(stringify_token(ty))),
},
_ => Err(ArgError::InvalidType(stringify_token(ty))),
}
}
Type::Path(of) => parse_type_path(attrs, of),
_ => Err(ArgError::InvalidType(stringify_token(ty))),
}
}
fn parse_arg(arg: FnArg) -> Result<Arg, ArgError> {
let FnArg::Typed(typed) = arg else {
return Err(ArgError::InvalidSelf);
};
parse_type(parse_attributes(&typed.attrs)?, &typed.ty)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::op2::signature::parse_signature;
use syn2::parse_str;
use syn2::ItemFn;
// We can't test pattern args :/
// https://github.com/rust-lang/rfcs/issues/2688
macro_rules! test {
( $(# [ $fn_attr:ident ])? fn $name:ident ( $( $(# [ $attr:ident ])? $ident:ident : $ty:ty ),* ) $(-> $(# [ $ret_attr:ident ])? $ret:ty)?, ( $( $arg_res:expr ),* ) -> $ret_res:expr ) => {
#[test]
fn $name() {
test(
stringify!($( #[$fn_attr] )? fn op( $( $( #[$attr] )? $ident : $ty ),* ) $(-> $( #[$ret_attr] )? $ret)? {}),
stringify!($($arg_res),*),
stringify!($ret_res)
);
}
};
}
fn test(op: &str, args_expected: &str, return_expected: &str) {
let item_fn = parse_str::<ItemFn>(op)
.unwrap_or_else(|_| panic!("Failed to parse {op} as a ItemFn"));
let attrs = item_fn.attrs;
let sig = parse_signature(attrs, item_fn.sig).unwrap_or_else(|_| {
panic!("Failed to successfully parse signature from {op}")
});
assert_eq!(
args_expected,
format!("{:?}", sig.args).trim_matches(|c| c == '[' || c == ']')
);
assert_eq!(return_expected, format!("{:?}", sig.ret_val));
}
test!(
fn op_state_and_number(opstate: &mut OpState, a: u32) -> (),
(Ref(Mut, OpState), Numeric(u32)) -> Infallible(Void)
);
test!(
fn op_slices(r#in: &[u8], out: &mut [u8]),
(Slice(Ref, u8), Slice(Mut, u8)) -> Infallible(Void)
);
test!(
#[serde] fn op_serde(#[serde] input: package::SerdeInputType) -> Result<package::SerdeReturnType, Error>,
(SerdeV8("package::SerdeInputType")) -> Result(SerdeV8("package::SerdeReturnType"))
);
test!(
fn op_local(input: v8::Local<v8::String>) -> Result<v8::Local<v8::String>, Error>,
(V8Local(String)) -> Result(V8Local(String))
);
test!(
fn op_resource(#[smi] rid: ResourceId, buffer: &[u8]),
(Numeric(__SMI__), Slice(Ref, u8)) -> Infallible(Void)
);
test!(
fn op_option_numeric_result(state: &mut OpState) -> Result<Option<u32>, AnyError>,
(Ref(Mut, OpState)) -> Result(OptionNumeric(u32))
);
test!(
fn op_ffi_read_f64(state: &mut OpState, ptr: * mut c_void, offset: isize) -> Result <f64, AnyError>,
(Ref(Mut, OpState), Ptr(Mut, __VOID__), Numeric(isize)) -> Result(Numeric(f64))
);
test!(
fn op_print(#[string] msg: &str, is_err: bool) -> Result<(), Error>,
(Special(RefStr), Numeric(bool)) -> Result(Void)
);
#[test]
fn test_parse_result() {
let rt = parse_str::<ReturnType>("-> Result < (), Error >")
.expect("Failed to parse");
println!("{:?}", parse_return(Attributes::default(), &rt));
}
}

View file

@ -0,0 +1,54 @@
#[allow(non_camel_case_types)]
struct op_add {}
impl op_add {
pub const fn name() -> &'static str {
stringify!(op_add)
}
pub const fn decl() -> deno_core::_ops::OpDecl {
deno_core::_ops::OpDecl {
name: stringify!(op_add),
v8_fn_ptr: Self::slow_function as _,
enabled: true,
fast_fn: Some({
use deno_core::v8::fast_api::Type;
use deno_core::v8::fast_api::CType;
deno_core::v8::fast_api::FastFunction::new(
&[Type::Uint32, Type::Uint32],
CType::Uint32,
Self::fast_function as *const ::std::ffi::c_void,
)
}),
is_async: false,
is_unstable: false,
is_v8: false,
arg_count: 2usize as u8,
}
}
pub extern "C" fn slow_function(info: *const deno_core::v8::FunctionCallbackInfo) {
let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
&*info
});
let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
&*info
});
let arg0 = args.get(0usize as i32);
let arg0 = deno_core::_ops::to_u32(&arg0) as _;
let arg1 = args.get(1usize as i32);
let arg1 = deno_core::_ops::to_u32(&arg1) as _;
let result = Self::call(arg0, arg1);
rv.set_uint32(result as u32);
}
fn fast_function(
_: deno_core::v8::Local<deno_core::v8::Object>,
arg0: u32,
arg1: u32,
) -> u32 {
let arg0 = arg0 as _;
let arg1 = arg1 as _;
Self::call(arg0, arg1)
}
#[inline(always)]
fn call(a: u32, b: u32) -> u32 {
a + b
}
}

View file

@ -0,0 +1,6 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
#[op2(fast)]
fn op_add(a: u32, b: u32) -> u32 {
a + b
}

View file

@ -0,0 +1,44 @@
#[allow(non_camel_case_types)]
pub struct op_test_add_option {}
impl op_test_add_option {
pub const fn name() -> &'static str {
stringify!(op_test_add_option)
}
pub const fn decl() -> crate::deno_core::_ops::OpDecl {
crate::deno_core::_ops::OpDecl {
name: stringify!(op_test_add_option),
v8_fn_ptr: Self::slow_function as _,
enabled: true,
fast_fn: None,
is_async: false,
is_unstable: false,
is_v8: false,
arg_count: 2usize as u8,
}
}
pub extern "C" fn slow_function(
info: *const crate::deno_core::v8::FunctionCallbackInfo,
) {
let mut rv = crate::deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
&*info
});
let args = crate::deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
&*info
});
let arg0 = args.get(0usize as i32);
let arg0 = crate::deno_core::_ops::to_u32(&arg0) as _;
let arg1 = args.get(1usize as i32);
let arg1 = if arg1.is_null_or_undefined() {
None
} else {
let arg1 = crate::deno_core::_ops::to_u32(&arg1) as _;
Some(arg1)
};
let result = Self::call(arg0, arg1);
rv.set_uint32(result as u32);
}
#[inline(always)]
pub fn call(a: u32, b: Option<u32>) -> u32 {
a + b.unwrap_or(100)
}
}

View file

@ -0,0 +1,6 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
#[op2(core)]
pub fn op_test_add_option(a: u32, b: Option<u32>) -> u32 {
a + b.unwrap_or(100)
}

View file

@ -0,0 +1,35 @@
#[allow(non_camel_case_types)]
pub struct op_has_doc_comment {}
impl op_has_doc_comment {
pub const fn name() -> &'static str {
stringify!(op_has_doc_comment)
}
pub const fn decl() -> deno_core::_ops::OpDecl {
deno_core::_ops::OpDecl {
name: stringify!(op_has_doc_comment),
v8_fn_ptr: Self::slow_function as _,
enabled: true,
fast_fn: Some({
use deno_core::v8::fast_api::Type;
use deno_core::v8::fast_api::CType;
deno_core::v8::fast_api::FastFunction::new(
&[],
CType::Void,
Self::fast_function as *const ::std::ffi::c_void,
)
}),
is_async: false,
is_unstable: false,
is_v8: false,
arg_count: 0usize as u8,
}
}
pub extern "C" fn slow_function(info: *const deno_core::v8::FunctionCallbackInfo) {
let result = Self::call();
}
fn fast_function(_: deno_core::v8::Local<deno_core::v8::Object>) -> () {
Self::call()
}
#[inline(always)]
pub fn call() -> () {}
}

View file

@ -0,0 +1,5 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
/// This is a doc comment.
#[op2(fast)]
pub fn op_has_doc_comment() -> () {}

View file

@ -0,0 +1,52 @@
#[allow(non_camel_case_types)]
struct op_add {}
impl op_add {
pub const fn name() -> &'static str {
stringify!(op_add)
}
pub const fn decl() -> deno_core::_ops::OpDecl {
deno_core::_ops::OpDecl {
name: stringify!(op_add),
v8_fn_ptr: Self::slow_function as _,
enabled: true,
fast_fn: Some({
use deno_core::v8::fast_api::Type;
use deno_core::v8::fast_api::CType;
deno_core::v8::fast_api::FastFunction::new(
&[Type::Int32, Type::Uint32],
CType::Uint32,
Self::fast_function as *const ::std::ffi::c_void,
)
}),
is_async: false,
is_unstable: false,
is_v8: false,
arg_count: 2usize as u8,
}
}
pub extern "C" fn slow_function(info: *const deno_core::v8::FunctionCallbackInfo) {
let mut rv = deno_core::v8::ReturnValue::from_function_callback_info(unsafe {
&*info
});
let args = deno_core::v8::FunctionCallbackArguments::from_function_callback_info(unsafe {
&*info
});
let arg0 = args.get(0usize as i32);
let arg0 = deno_core::_ops::to_i32(&arg0) as _;
let arg1 = args.get(1usize as i32);
let arg1 = deno_core::_ops::to_u32(&arg1) as _;
let result = Self::call(arg0, arg1);
rv.set_uint32(result as u32);
}
fn fast_function(
_: deno_core::v8::Local<deno_core::v8::Object>,
arg0: i32,
arg1: u32,
) -> u32 {
let arg0 = arg0 as _;
let arg1 = arg1 as _;
Self::call(arg0, arg1)
}
#[inline(always)]
fn call(id: ResourceId, extra: u16) -> u32 {}
}

View file

@ -0,0 +1,4 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
#[op2(fast)]
fn op_add(#[smi] id: ResourceId, extra: u16) -> u32 {}