mirror of
https://github.com/denoland/deno.git
synced 2025-02-07 23:06:50 -05:00
feat: first pass at native plugins (#3372)
This commit is contained in:
parent
214b3eb29a
commit
7c3b9b4f4f
26 changed files with 574 additions and 7 deletions
68
Cargo.lock
generated
68
Cargo.lock
generated
|
@ -293,6 +293,7 @@ dependencies = [
|
||||||
"deno 0.25.0",
|
"deno 0.25.0",
|
||||||
"deno_typescript 0.25.0",
|
"deno_typescript 0.25.0",
|
||||||
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"dlopen 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"fwdansi 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -357,6 +358,27 @@ dependencies = [
|
||||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dlopen"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"dlopen_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dlopen_derive"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "downcast-rs"
|
name = "downcast-rs"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
|
@ -969,6 +991,14 @@ name = "proc-macro-nested"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "0.4.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
|
@ -989,6 +1019,14 @@ dependencies = [
|
||||||
"url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "0.6.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
@ -1436,6 +1474,16 @@ name = "strsim"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "0.15.44"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
@ -1487,6 +1535,15 @@ dependencies = [
|
||||||
"wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "test_plugin"
|
||||||
|
version = "0.0.1"
|
||||||
|
dependencies = [
|
||||||
|
"deno 0.25.0",
|
||||||
|
"deno_cli 0.25.0",
|
||||||
|
"futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "textwrap"
|
name = "textwrap"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
|
@ -1786,6 +1843,11 @@ name = "unicode-width"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -2075,6 +2137,8 @@ dependencies = [
|
||||||
"checksum ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113"
|
"checksum ct-logs 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d3686f5fa27dbc1d76c751300376e167c5a43387f44bb451fd1c24776e49113"
|
||||||
"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
|
"checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
|
||||||
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
|
"checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b"
|
||||||
|
"checksum dlopen 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "71e80ad39f814a9abe68583cd50a2d45c8a67561c3361ab8da240587dda80937"
|
||||||
|
"checksum dlopen_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f236d9e1b1fbd81cea0f9cbdc8dcc7e8ebcd80e6659cd7cb2ad5f6c05946c581"
|
||||||
"checksum downcast-rs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6"
|
"checksum downcast-rs 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52ba6eb47c2131e784a38b726eb54c1e1484904f013e576a25354d0124161af6"
|
||||||
"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e"
|
"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e"
|
||||||
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
|
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
|
||||||
|
@ -2144,8 +2208,10 @@ dependencies = [
|
||||||
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
||||||
"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
|
"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5"
|
||||||
"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e"
|
"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e"
|
||||||
|
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||||
"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
|
"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
|
||||||
"checksum publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510"
|
"checksum publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510"
|
||||||
|
"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||||
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe"
|
||||||
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
||||||
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca"
|
||||||
|
@ -2194,6 +2260,7 @@ dependencies = [
|
||||||
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
|
"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
|
||||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
|
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||||
"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c"
|
"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c"
|
||||||
"checksum synstructure 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "575be94ccb86e8da37efb894a87e2b660be299b41d8ef347f9d6d79fbe61b1ba"
|
"checksum synstructure 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "575be94ccb86e8da37efb894a87e2b660be299b41d8ef347f9d6d79fbe61b1ba"
|
||||||
"checksum sys-info 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0079fe39cec2c8215e21b0bc4ccec9031004c160b88358f531b601e96b77f0df"
|
"checksum sys-info 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0079fe39cec2c8215e21b0bc4ccec9031004c160b88358f531b601e96b77f0df"
|
||||||
|
@ -2226,6 +2293,7 @@ dependencies = [
|
||||||
"checksum unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf"
|
"checksum unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf"
|
||||||
"checksum unicode-segmentation 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49f5526225fd8b77342d5986ab5f6055552e9c0776193b5b63fd53b46debfad7"
|
"checksum unicode-segmentation 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49f5526225fd8b77342d5986ab5f6055552e9c0776193b5b63fd53b46debfad7"
|
||||||
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
|
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
|
||||||
|
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||||
"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece"
|
"checksum untrusted 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60369ef7a31de49bcb3f6ca728d4ba7300d9a1658f94c727d4cab8c8d9f4aece"
|
||||||
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
|
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
|
||||||
|
|
|
@ -4,4 +4,5 @@ members = [
|
||||||
"core",
|
"core",
|
||||||
"tools/hyper_hello",
|
"tools/hyper_hello",
|
||||||
"deno_typescript",
|
"deno_typescript",
|
||||||
|
"test_plugin"
|
||||||
]
|
]
|
||||||
|
|
|
@ -31,6 +31,7 @@ base64 = "0.11.0"
|
||||||
byteorder = "1.3.2"
|
byteorder = "1.3.2"
|
||||||
clap = "2.33.0"
|
clap = "2.33.0"
|
||||||
dirs = "2.0.2"
|
dirs = "2.0.2"
|
||||||
|
dlopen = "0.1.8"
|
||||||
futures = { version = "0.3", features = [ "compat", "io-compat" ] }
|
futures = { version = "0.3", features = [ "compat", "io-compat" ] }
|
||||||
http = "0.1.19"
|
http = "0.1.19"
|
||||||
hyper = "0.12.35"
|
hyper = "0.12.35"
|
||||||
|
|
|
@ -6,6 +6,7 @@ pub use crate::msg::ErrorKind;
|
||||||
use deno::AnyError;
|
use deno::AnyError;
|
||||||
use deno::ErrBox;
|
use deno::ErrBox;
|
||||||
use deno::ModuleResolutionError;
|
use deno::ModuleResolutionError;
|
||||||
|
use dlopen::Error as DlopenError;
|
||||||
use http::uri;
|
use http::uri;
|
||||||
use hyper;
|
use hyper;
|
||||||
use reqwest;
|
use reqwest;
|
||||||
|
@ -292,6 +293,19 @@ mod unix {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl GetErrorKind for DlopenError {
|
||||||
|
fn kind(&self) -> ErrorKind {
|
||||||
|
use dlopen::Error::*;
|
||||||
|
match self {
|
||||||
|
NullCharacter(_) => ErrorKind::Other,
|
||||||
|
OpeningLibraryError(e) => GetErrorKind::kind(e),
|
||||||
|
SymbolGettingError(e) => GetErrorKind::kind(e),
|
||||||
|
NullSymbol => ErrorKind::Other,
|
||||||
|
AddrNotMatchingDll(e) => GetErrorKind::kind(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl GetErrorKind for dyn AnyError {
|
impl GetErrorKind for dyn AnyError {
|
||||||
fn kind(&self) -> ErrorKind {
|
fn kind(&self) -> ErrorKind {
|
||||||
use self::GetErrorKind as Get;
|
use self::GetErrorKind as Get;
|
||||||
|
@ -325,6 +339,7 @@ impl GetErrorKind for dyn AnyError {
|
||||||
.downcast_ref::<serde_json::error::Error>()
|
.downcast_ref::<serde_json::error::Error>()
|
||||||
.map(Get::kind)
|
.map(Get::kind)
|
||||||
})
|
})
|
||||||
|
.or_else(|| self.downcast_ref::<DlopenError>().map(Get::kind))
|
||||||
.or_else(|| unix_error_kind(self))
|
.or_else(|| unix_error_kind(self))
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
panic!("Can't get ErrorKind for {:?}", self);
|
panic!("Can't get ErrorKind for {:?}", self);
|
||||||
|
|
17
cli/flags.rs
17
cli/flags.rs
|
@ -82,6 +82,7 @@ pub struct DenoFlags {
|
||||||
pub net_whitelist: Vec<String>,
|
pub net_whitelist: Vec<String>,
|
||||||
pub allow_env: bool,
|
pub allow_env: bool,
|
||||||
pub allow_run: bool,
|
pub allow_run: bool,
|
||||||
|
pub allow_plugin: bool,
|
||||||
pub allow_hrtime: bool,
|
pub allow_hrtime: bool,
|
||||||
pub no_prompts: bool,
|
pub no_prompts: bool,
|
||||||
pub no_remote: bool,
|
pub no_remote: bool,
|
||||||
|
@ -346,6 +347,7 @@ fn xeval_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
||||||
flags.allow_run = true;
|
flags.allow_run = true;
|
||||||
flags.allow_read = true;
|
flags.allow_read = true;
|
||||||
flags.allow_write = true;
|
flags.allow_write = true;
|
||||||
|
flags.allow_plugin = true;
|
||||||
flags.allow_hrtime = true;
|
flags.allow_hrtime = true;
|
||||||
flags.argv.push(XEVAL_URL.to_string());
|
flags.argv.push(XEVAL_URL.to_string());
|
||||||
|
|
||||||
|
@ -373,6 +375,7 @@ fn repl_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
||||||
flags.allow_run = true;
|
flags.allow_run = true;
|
||||||
flags.allow_read = true;
|
flags.allow_read = true;
|
||||||
flags.allow_write = true;
|
flags.allow_write = true;
|
||||||
|
flags.allow_plugin = true;
|
||||||
flags.allow_hrtime = true;
|
flags.allow_hrtime = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,6 +386,7 @@ fn eval_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
||||||
flags.allow_run = true;
|
flags.allow_run = true;
|
||||||
flags.allow_read = true;
|
flags.allow_read = true;
|
||||||
flags.allow_write = true;
|
flags.allow_write = true;
|
||||||
|
flags.allow_plugin = true;
|
||||||
flags.allow_hrtime = true;
|
flags.allow_hrtime = true;
|
||||||
let code: &str = matches.value_of("code").unwrap();
|
let code: &str = matches.value_of("code").unwrap();
|
||||||
flags.argv.extend(vec![code.to_string()]);
|
flags.argv.extend(vec![code.to_string()]);
|
||||||
|
@ -465,6 +469,9 @@ fn run_test_args_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
||||||
if matches.is_present("allow-run") {
|
if matches.is_present("allow-run") {
|
||||||
flags.allow_run = true;
|
flags.allow_run = true;
|
||||||
}
|
}
|
||||||
|
if matches.is_present("allow-plugin") {
|
||||||
|
flags.allow_plugin = true;
|
||||||
|
}
|
||||||
if matches.is_present("allow-hrtime") {
|
if matches.is_present("allow-hrtime") {
|
||||||
flags.allow_hrtime = true;
|
flags.allow_hrtime = true;
|
||||||
}
|
}
|
||||||
|
@ -475,6 +482,7 @@ fn run_test_args_parse(flags: &mut DenoFlags, matches: &clap::ArgMatches) {
|
||||||
flags.allow_run = true;
|
flags.allow_run = true;
|
||||||
flags.allow_read = true;
|
flags.allow_read = true;
|
||||||
flags.allow_write = true;
|
flags.allow_write = true;
|
||||||
|
flags.allow_plugin = true;
|
||||||
flags.allow_hrtime = true;
|
flags.allow_hrtime = true;
|
||||||
}
|
}
|
||||||
if matches.is_present("cached-only") {
|
if matches.is_present("cached-only") {
|
||||||
|
@ -942,6 +950,11 @@ fn run_test_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
|
||||||
.long("allow-run")
|
.long("allow-run")
|
||||||
.help("Allow running subprocesses"),
|
.help("Allow running subprocesses"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("allow-plugin")
|
||||||
|
.long("allow-plugin")
|
||||||
|
.help("Allow loading plugins"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("allow-hrtime")
|
Arg::with_name("allow-hrtime")
|
||||||
.long("allow-hrtime")
|
.long("allow-hrtime")
|
||||||
|
@ -1408,6 +1421,7 @@ mod tests {
|
||||||
allow_run: true,
|
allow_run: true,
|
||||||
allow_read: true,
|
allow_read: true,
|
||||||
allow_write: true,
|
allow_write: true,
|
||||||
|
allow_plugin: true,
|
||||||
allow_hrtime: true,
|
allow_hrtime: true,
|
||||||
..DenoFlags::default()
|
..DenoFlags::default()
|
||||||
}
|
}
|
||||||
|
@ -1581,6 +1595,7 @@ mod tests {
|
||||||
allow_run: true,
|
allow_run: true,
|
||||||
allow_read: true,
|
allow_read: true,
|
||||||
allow_write: true,
|
allow_write: true,
|
||||||
|
allow_plugin: true,
|
||||||
allow_hrtime: true,
|
allow_hrtime: true,
|
||||||
..DenoFlags::default()
|
..DenoFlags::default()
|
||||||
}
|
}
|
||||||
|
@ -1600,6 +1615,7 @@ mod tests {
|
||||||
allow_run: true,
|
allow_run: true,
|
||||||
allow_read: true,
|
allow_read: true,
|
||||||
allow_write: true,
|
allow_write: true,
|
||||||
|
allow_plugin: true,
|
||||||
allow_hrtime: true,
|
allow_hrtime: true,
|
||||||
..DenoFlags::default()
|
..DenoFlags::default()
|
||||||
}
|
}
|
||||||
|
@ -1635,6 +1651,7 @@ mod tests {
|
||||||
allow_run: true,
|
allow_run: true,
|
||||||
allow_read: true,
|
allow_read: true,
|
||||||
allow_write: true,
|
allow_write: true,
|
||||||
|
allow_plugin: true,
|
||||||
allow_hrtime: true,
|
allow_hrtime: true,
|
||||||
..DenoFlags::default()
|
..DenoFlags::default()
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ export {
|
||||||
} from "./permissions.ts";
|
} from "./permissions.ts";
|
||||||
export { truncateSync, truncate } from "./truncate.ts";
|
export { truncateSync, truncate } from "./truncate.ts";
|
||||||
export { FileInfo } from "./file_info.ts";
|
export { FileInfo } from "./file_info.ts";
|
||||||
|
export { openPlugin } from "./plugins.ts";
|
||||||
export { connect, dial, listen, Listener, Conn } from "./net.ts";
|
export { connect, dial, listen, Listener, Conn } from "./net.ts";
|
||||||
export { dialTLS, listenTLS } from "./tls.ts";
|
export { dialTLS, listenTLS } from "./tls.ts";
|
||||||
export { metrics, Metrics } from "./metrics.ts";
|
export { metrics, Metrics } from "./metrics.ts";
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
|
||||||
import * as minimal from "./dispatch_minimal.ts";
|
import * as minimal from "./dispatch_minimal.ts";
|
||||||
import * as json from "./dispatch_json.ts";
|
import * as json from "./dispatch_json.ts";
|
||||||
|
import { AsyncHandler } from "./plugins.ts";
|
||||||
|
|
||||||
// These consts are shared with Rust. Update with care.
|
// These consts are shared with Rust. Update with care.
|
||||||
export let OP_READ: number;
|
export let OP_READ: number;
|
||||||
|
@ -67,6 +68,16 @@ export let OP_CWD: number;
|
||||||
export let OP_FETCH_ASSET: number;
|
export let OP_FETCH_ASSET: number;
|
||||||
export let OP_DIAL_TLS: number;
|
export let OP_DIAL_TLS: number;
|
||||||
export let OP_HOSTNAME: number;
|
export let OP_HOSTNAME: number;
|
||||||
|
export let OP_OPEN_PLUGIN: number;
|
||||||
|
|
||||||
|
const PLUGIN_ASYNC_HANDLER_MAP: Map<number, AsyncHandler> = new Map();
|
||||||
|
|
||||||
|
export function setPluginAsyncHandler(
|
||||||
|
opId: number,
|
||||||
|
handler: AsyncHandler
|
||||||
|
): void {
|
||||||
|
PLUGIN_ASYNC_HANDLER_MAP.set(opId, handler);
|
||||||
|
}
|
||||||
|
|
||||||
export function asyncMsgFromRust(opId: number, ui8: Uint8Array): void {
|
export function asyncMsgFromRust(opId: number, ui8: Uint8Array): void {
|
||||||
switch (opId) {
|
switch (opId) {
|
||||||
|
@ -111,6 +122,11 @@ export function asyncMsgFromRust(opId: number, ui8: Uint8Array): void {
|
||||||
json.asyncMsgFromRust(opId, ui8);
|
json.asyncMsgFromRust(opId, ui8);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw Error("bad async opId");
|
const handler = PLUGIN_ASYNC_HANDLER_MAP.get(opId);
|
||||||
|
if (handler) {
|
||||||
|
handler(ui8);
|
||||||
|
} else {
|
||||||
|
throw Error("bad async opId");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
35
cli/js/lib.deno_runtime.d.ts
vendored
35
cli/js/lib.deno_runtime.d.ts
vendored
|
@ -907,6 +907,7 @@ declare namespace Deno {
|
||||||
| "write"
|
| "write"
|
||||||
| "net"
|
| "net"
|
||||||
| "env"
|
| "env"
|
||||||
|
| "plugin"
|
||||||
| "hrtime";
|
| "hrtime";
|
||||||
/** https://w3c.github.io/permissions/#status-of-a-permission */
|
/** https://w3c.github.io/permissions/#status-of-a-permission */
|
||||||
export type PermissionState = "granted" | "denied" | "prompt";
|
export type PermissionState = "granted" | "denied" | "prompt";
|
||||||
|
@ -924,6 +925,9 @@ declare namespace Deno {
|
||||||
interface EnvPermissionDescriptor {
|
interface EnvPermissionDescriptor {
|
||||||
name: "env";
|
name: "env";
|
||||||
}
|
}
|
||||||
|
interface PluginPermissionDescriptor {
|
||||||
|
name: "plugin";
|
||||||
|
}
|
||||||
interface HrtimePermissionDescriptor {
|
interface HrtimePermissionDescriptor {
|
||||||
name: "hrtime";
|
name: "hrtime";
|
||||||
}
|
}
|
||||||
|
@ -933,6 +937,7 @@ declare namespace Deno {
|
||||||
| ReadWritePermissionDescriptor
|
| ReadWritePermissionDescriptor
|
||||||
| NetPermissionDescriptor
|
| NetPermissionDescriptor
|
||||||
| EnvPermissionDescriptor
|
| EnvPermissionDescriptor
|
||||||
|
| PluginPermissionDescriptor
|
||||||
| HrtimePermissionDescriptor;
|
| HrtimePermissionDescriptor;
|
||||||
|
|
||||||
export class Permissions {
|
export class Permissions {
|
||||||
|
@ -982,6 +987,36 @@ declare namespace Deno {
|
||||||
*/
|
*/
|
||||||
export function truncate(name: string, len?: number): Promise<void>;
|
export function truncate(name: string, len?: number): Promise<void>;
|
||||||
|
|
||||||
|
// @url js/plugins.d.ts
|
||||||
|
|
||||||
|
export interface AsyncHandler {
|
||||||
|
(msg: Uint8Array): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PluginOp {
|
||||||
|
dispatch(
|
||||||
|
control: Uint8Array,
|
||||||
|
zeroCopy?: ArrayBufferView | null
|
||||||
|
): Uint8Array | null;
|
||||||
|
setAsyncHandler(handler: AsyncHandler): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Plugin {
|
||||||
|
ops: {
|
||||||
|
[name: string]: PluginOp;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Open and initalize a plugin.
|
||||||
|
* Requires the `--allow-plugin` flag.
|
||||||
|
*
|
||||||
|
* const plugin = Deno.openPlugin("./path/to/some/plugin.so");
|
||||||
|
* const some_op = plugin.ops.some_op;
|
||||||
|
* const response = some_op.dispatch(new Uint8Array([1,2,3,4]));
|
||||||
|
* console.log(`Response from plugin ${response}`);
|
||||||
|
*/
|
||||||
|
export function openPlugin(filename: string): Plugin;
|
||||||
|
|
||||||
// @url js/net.d.ts
|
// @url js/net.d.ts
|
||||||
|
|
||||||
type Transport = "tcp";
|
type Transport = "tcp";
|
||||||
|
|
|
@ -11,6 +11,7 @@ export type PermissionName =
|
||||||
| "net"
|
| "net"
|
||||||
| "env"
|
| "env"
|
||||||
| "run"
|
| "run"
|
||||||
|
| "plugin"
|
||||||
| "hrtime";
|
| "hrtime";
|
||||||
// NOTE: Keep in sync with cli/permissions.rs
|
// NOTE: Keep in sync with cli/permissions.rs
|
||||||
|
|
||||||
|
@ -31,6 +32,9 @@ interface NetPermissionDescriptor {
|
||||||
interface EnvPermissionDescriptor {
|
interface EnvPermissionDescriptor {
|
||||||
name: "env";
|
name: "env";
|
||||||
}
|
}
|
||||||
|
interface PluginPermissionDescriptor {
|
||||||
|
name: "plugin";
|
||||||
|
}
|
||||||
interface HrtimePermissionDescriptor {
|
interface HrtimePermissionDescriptor {
|
||||||
name: "hrtime";
|
name: "hrtime";
|
||||||
}
|
}
|
||||||
|
@ -40,6 +44,7 @@ type PermissionDescriptor =
|
||||||
| ReadWritePermissionDescriptor
|
| ReadWritePermissionDescriptor
|
||||||
| NetPermissionDescriptor
|
| NetPermissionDescriptor
|
||||||
| EnvPermissionDescriptor
|
| EnvPermissionDescriptor
|
||||||
|
| PluginPermissionDescriptor
|
||||||
| HrtimePermissionDescriptor;
|
| HrtimePermissionDescriptor;
|
||||||
|
|
||||||
/** https://w3c.github.io/permissions/#permissionstatus */
|
/** https://w3c.github.io/permissions/#permissionstatus */
|
||||||
|
|
|
@ -7,11 +7,12 @@ const knownPermissions: Deno.PermissionName[] = [
|
||||||
"write",
|
"write",
|
||||||
"net",
|
"net",
|
||||||
"env",
|
"env",
|
||||||
|
"plugin",
|
||||||
"hrtime"
|
"hrtime"
|
||||||
];
|
];
|
||||||
|
|
||||||
for (const grant of knownPermissions) {
|
function genFunc(grant: Deno.PermissionName): () => Promise<void> {
|
||||||
testPerm({ [grant]: true }, async function envGranted(): Promise<void> {
|
const gen: () => Promise<void> = async function Granted(): Promise<void> {
|
||||||
const status0 = await Deno.permissions.query({ name: grant });
|
const status0 = await Deno.permissions.query({ name: grant });
|
||||||
assert(status0 != null);
|
assert(status0 != null);
|
||||||
assertEquals(status0.state, "granted");
|
assertEquals(status0.state, "granted");
|
||||||
|
@ -19,7 +20,14 @@ for (const grant of knownPermissions) {
|
||||||
const status1 = await Deno.permissions.revoke({ name: grant });
|
const status1 = await Deno.permissions.revoke({ name: grant });
|
||||||
assert(status1 != null);
|
assert(status1 != null);
|
||||||
assertEquals(status1.state, "prompt");
|
assertEquals(status1.state, "prompt");
|
||||||
});
|
};
|
||||||
|
// Properly name these generated functions.
|
||||||
|
Object.defineProperty(gen, "name", { value: grant + "Granted" });
|
||||||
|
return gen;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const grant of knownPermissions) {
|
||||||
|
testPerm({ [grant]: true }, genFunc(grant));
|
||||||
}
|
}
|
||||||
|
|
||||||
test(async function permissionInvalidName(): Promise<void> {
|
test(async function permissionInvalidName(): Promise<void> {
|
||||||
|
|
66
cli/js/plugins.ts
Normal file
66
cli/js/plugins.ts
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import { sendSync } from "./dispatch_json.ts";
|
||||||
|
import { OP_OPEN_PLUGIN, setPluginAsyncHandler } from "./dispatch.ts";
|
||||||
|
import { core } from "./core.ts";
|
||||||
|
|
||||||
|
export interface AsyncHandler {
|
||||||
|
(msg: Uint8Array): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PluginOp {
|
||||||
|
dispatch(
|
||||||
|
control: Uint8Array,
|
||||||
|
zeroCopy?: ArrayBufferView | null
|
||||||
|
): Uint8Array | null;
|
||||||
|
setAsyncHandler(handler: AsyncHandler): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginOpImpl implements PluginOp {
|
||||||
|
constructor(private readonly opId: number) {}
|
||||||
|
|
||||||
|
dispatch(
|
||||||
|
control: Uint8Array,
|
||||||
|
zeroCopy?: ArrayBufferView | null
|
||||||
|
): Uint8Array | null {
|
||||||
|
return core.dispatch(this.opId, control, zeroCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
setAsyncHandler(handler: AsyncHandler): void {
|
||||||
|
setPluginAsyncHandler(this.opId, handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(afinch7): add close method.
|
||||||
|
|
||||||
|
interface Plugin {
|
||||||
|
ops: {
|
||||||
|
[name: string]: PluginOp;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class PluginImpl implements Plugin {
|
||||||
|
private _ops: { [name: string]: PluginOp } = {};
|
||||||
|
|
||||||
|
constructor(private readonly rid: number, ops: { [name: string]: number }) {
|
||||||
|
for (const op in ops) {
|
||||||
|
this._ops[op] = new PluginOpImpl(ops[op]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get ops(): { [name: string]: PluginOp } {
|
||||||
|
return Object.assign({}, this._ops);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OpenPluginResponse {
|
||||||
|
rid: number;
|
||||||
|
ops: {
|
||||||
|
[name: string]: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function openPlugin(filename: string): Plugin {
|
||||||
|
const response: OpenPluginResponse = sendSync(OP_OPEN_PLUGIN, {
|
||||||
|
filename
|
||||||
|
});
|
||||||
|
return new PluginImpl(response.rid, response.ops);
|
||||||
|
}
|
|
@ -26,6 +26,7 @@ interface TestPermissions {
|
||||||
net?: boolean;
|
net?: boolean;
|
||||||
env?: boolean;
|
env?: boolean;
|
||||||
run?: boolean;
|
run?: boolean;
|
||||||
|
plugin?: boolean;
|
||||||
hrtime?: boolean;
|
hrtime?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ export interface Permissions {
|
||||||
net: boolean;
|
net: boolean;
|
||||||
env: boolean;
|
env: boolean;
|
||||||
run: boolean;
|
run: boolean;
|
||||||
|
plugin: boolean;
|
||||||
hrtime: boolean;
|
hrtime: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +50,7 @@ async function getProcessPermissions(): Promise<Permissions> {
|
||||||
write: await isGranted("write"),
|
write: await isGranted("write"),
|
||||||
net: await isGranted("net"),
|
net: await isGranted("net"),
|
||||||
env: await isGranted("env"),
|
env: await isGranted("env"),
|
||||||
|
plugin: await isGranted("plugin"),
|
||||||
hrtime: await isGranted("hrtime")
|
hrtime: await isGranted("hrtime")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -75,8 +78,9 @@ function permToString(perms: Permissions): string {
|
||||||
const n = perms.net ? 1 : 0;
|
const n = perms.net ? 1 : 0;
|
||||||
const e = perms.env ? 1 : 0;
|
const e = perms.env ? 1 : 0;
|
||||||
const u = perms.run ? 1 : 0;
|
const u = perms.run ? 1 : 0;
|
||||||
|
const p = perms.plugin ? 1 : 0;
|
||||||
const h = perms.hrtime ? 1 : 0;
|
const h = perms.hrtime ? 1 : 0;
|
||||||
return `permR${r}W${w}N${n}E${e}U${u}H${h}`;
|
return `permR${r}W${w}N${n}E${e}U${u}P${p}H${h}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function registerPermCombination(perms: Permissions): void {
|
function registerPermCombination(perms: Permissions): void {
|
||||||
|
@ -93,6 +97,7 @@ function normalizeTestPermissions(perms: TestPermissions): Permissions {
|
||||||
net: !!perms.net,
|
net: !!perms.net,
|
||||||
run: !!perms.run,
|
run: !!perms.run,
|
||||||
env: !!perms.env,
|
env: !!perms.env,
|
||||||
|
plugin: !!perms.plugin,
|
||||||
hrtime: !!perms.hrtime
|
hrtime: !!perms.hrtime
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -120,6 +125,7 @@ export function test(fn: testing.TestFunction): void {
|
||||||
net: false,
|
net: false,
|
||||||
env: false,
|
env: false,
|
||||||
run: false,
|
run: false,
|
||||||
|
plugin: false,
|
||||||
hrtime: false
|
hrtime: false
|
||||||
},
|
},
|
||||||
fn
|
fn
|
||||||
|
@ -176,6 +182,7 @@ test(function permissionsMatches(): void {
|
||||||
net: false,
|
net: false,
|
||||||
env: false,
|
env: false,
|
||||||
run: false,
|
run: false,
|
||||||
|
plugin: false,
|
||||||
hrtime: false
|
hrtime: false
|
||||||
},
|
},
|
||||||
normalizeTestPermissions({ read: true })
|
normalizeTestPermissions({ read: true })
|
||||||
|
@ -190,6 +197,7 @@ test(function permissionsMatches(): void {
|
||||||
net: false,
|
net: false,
|
||||||
env: false,
|
env: false,
|
||||||
run: false,
|
run: false,
|
||||||
|
plugin: false,
|
||||||
hrtime: false
|
hrtime: false
|
||||||
},
|
},
|
||||||
normalizeTestPermissions({})
|
normalizeTestPermissions({})
|
||||||
|
@ -204,6 +212,7 @@ test(function permissionsMatches(): void {
|
||||||
net: true,
|
net: true,
|
||||||
env: true,
|
env: true,
|
||||||
run: true,
|
run: true,
|
||||||
|
plugin: true,
|
||||||
hrtime: true
|
hrtime: true
|
||||||
},
|
},
|
||||||
normalizeTestPermissions({ read: true })
|
normalizeTestPermissions({ read: true })
|
||||||
|
@ -219,6 +228,7 @@ test(function permissionsMatches(): void {
|
||||||
net: true,
|
net: true,
|
||||||
env: false,
|
env: false,
|
||||||
run: false,
|
run: false,
|
||||||
|
plugin: false,
|
||||||
hrtime: false
|
hrtime: false
|
||||||
},
|
},
|
||||||
normalizeTestPermissions({ read: true })
|
normalizeTestPermissions({ read: true })
|
||||||
|
@ -234,6 +244,7 @@ test(function permissionsMatches(): void {
|
||||||
net: true,
|
net: true,
|
||||||
env: true,
|
env: true,
|
||||||
run: true,
|
run: true,
|
||||||
|
plugin: true,
|
||||||
hrtime: true
|
hrtime: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -242,6 +253,7 @@ test(function permissionsMatches(): void {
|
||||||
net: true,
|
net: true,
|
||||||
env: true,
|
env: true,
|
||||||
run: true,
|
run: true,
|
||||||
|
plugin: true,
|
||||||
hrtime: true
|
hrtime: true
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,6 +16,7 @@ pub mod io;
|
||||||
pub mod net;
|
pub mod net;
|
||||||
pub mod os;
|
pub mod os;
|
||||||
pub mod permissions;
|
pub mod permissions;
|
||||||
|
pub mod plugins;
|
||||||
pub mod process;
|
pub mod process;
|
||||||
pub mod random;
|
pub mod random;
|
||||||
pub mod repl;
|
pub mod repl;
|
||||||
|
|
|
@ -55,6 +55,7 @@ pub fn op_revoke_permission(
|
||||||
"write" => permissions.allow_write.revoke(),
|
"write" => permissions.allow_write.revoke(),
|
||||||
"net" => permissions.allow_net.revoke(),
|
"net" => permissions.allow_net.revoke(),
|
||||||
"env" => permissions.allow_env.revoke(),
|
"env" => permissions.allow_env.revoke(),
|
||||||
|
"plugin" => permissions.allow_plugin.revoke(),
|
||||||
"hrtime" => permissions.allow_hrtime.revoke(),
|
"hrtime" => permissions.allow_hrtime.revoke(),
|
||||||
_ => {}
|
_ => {}
|
||||||
};
|
};
|
||||||
|
@ -83,6 +84,7 @@ pub fn op_request_permission(
|
||||||
}
|
}
|
||||||
"net" => permissions.request_net(&args.url.as_ref().map(String::as_str)),
|
"net" => permissions.request_net(&args.url.as_ref().map(String::as_str)),
|
||||||
"env" => Ok(permissions.request_env()),
|
"env" => Ok(permissions.request_env()),
|
||||||
|
"plugin" => Ok(permissions.request_plugin()),
|
||||||
"hrtime" => Ok(permissions.request_hrtime()),
|
"hrtime" => Ok(permissions.request_hrtime()),
|
||||||
n => Err(type_error(format!("No such permission name: {}", n))),
|
n => Err(type_error(format!("No such permission name: {}", n))),
|
||||||
}?;
|
}?;
|
||||||
|
|
96
cli/ops/plugins.rs
Normal file
96
cli/ops/plugins.rs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
use super::dispatch_json::{Deserialize, JsonOp, Value};
|
||||||
|
use crate::fs as deno_fs;
|
||||||
|
use crate::ops::json_op;
|
||||||
|
use crate::state::ThreadSafeState;
|
||||||
|
use deno::*;
|
||||||
|
use dlopen::symbor::Library;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::ffi::OsStr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
pub fn init(i: &mut Isolate, s: &ThreadSafeState, r: Arc<deno::OpRegistry>) {
|
||||||
|
let r_ = r.clone();
|
||||||
|
i.register_op(
|
||||||
|
"open_plugin",
|
||||||
|
s.core_op(json_op(s.stateful_op(move |state, args, zero_copy| {
|
||||||
|
op_open_plugin(&r_, state, args, zero_copy)
|
||||||
|
}))),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn open_plugin<P: AsRef<OsStr>>(lib_path: P) -> Result<Library, ErrBox> {
|
||||||
|
debug!("Loading Plugin: {:#?}", lib_path.as_ref());
|
||||||
|
|
||||||
|
Library::open(lib_path).map_err(ErrBox::from)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PluginResource {
|
||||||
|
lib: Library,
|
||||||
|
ops: HashMap<String, OpId>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Resource for PluginResource {}
|
||||||
|
|
||||||
|
struct InitContext {
|
||||||
|
ops: HashMap<String, Box<OpDispatcher>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PluginInitContext for InitContext {
|
||||||
|
fn register_op(&mut self, name: &str, op: Box<OpDispatcher>) {
|
||||||
|
let existing = self.ops.insert(name.to_string(), op);
|
||||||
|
assert!(
|
||||||
|
existing.is_none(),
|
||||||
|
format!("Op already registered: {}", name)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
struct OpenPluginArgs {
|
||||||
|
filename: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn op_open_plugin(
|
||||||
|
registry: &Arc<deno::OpRegistry>,
|
||||||
|
state: &ThreadSafeState,
|
||||||
|
args: Value,
|
||||||
|
_zero_copy: Option<PinnedBuf>,
|
||||||
|
) -> Result<JsonOp, ErrBox> {
|
||||||
|
let args: OpenPluginArgs = serde_json::from_value(args)?;
|
||||||
|
let (filename, filename_) = deno_fs::resolve_from_cwd(&args.filename)?;
|
||||||
|
|
||||||
|
state.check_plugin(&filename_)?;
|
||||||
|
|
||||||
|
let lib = open_plugin(filename)?;
|
||||||
|
let plugin_resource = PluginResource {
|
||||||
|
lib,
|
||||||
|
ops: HashMap::new(),
|
||||||
|
};
|
||||||
|
let mut table = state.lock_resource_table();
|
||||||
|
let rid = table.add("plugin", Box::new(plugin_resource));
|
||||||
|
let plugin_resource = table.get_mut::<PluginResource>(rid).unwrap();
|
||||||
|
|
||||||
|
let init_fn = *unsafe {
|
||||||
|
plugin_resource
|
||||||
|
.lib
|
||||||
|
.symbol::<PluginInitFn>("deno_plugin_init")
|
||||||
|
}?;
|
||||||
|
let mut init_context = InitContext {
|
||||||
|
ops: HashMap::new(),
|
||||||
|
};
|
||||||
|
init_fn(&mut init_context);
|
||||||
|
for op in init_context.ops {
|
||||||
|
// Register each plugin op in the `OpRegistry` with the name
|
||||||
|
// formated like this `plugin_{plugin_rid}_{name}`.
|
||||||
|
// The inclusion of prefix and rid is designed to avoid any
|
||||||
|
// op name collision beyond the bound of a single loaded
|
||||||
|
// plugin instance.
|
||||||
|
let op_id = registry.register(&format!("plugin_{}_{}", rid, op.0), op.1);
|
||||||
|
plugin_resource.ops.insert(op.0, op_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(JsonOp::Sync(
|
||||||
|
json!({ "rid": rid, "ops": plugin_resource.ops }),
|
||||||
|
))
|
||||||
|
}
|
|
@ -227,7 +227,12 @@ fn op_host_get_worker_closed(
|
||||||
};
|
};
|
||||||
let op = future.then(move |_result| {
|
let op = future.then(move |_result| {
|
||||||
let mut workers_table = state_.workers.lock().unwrap();
|
let mut workers_table = state_.workers.lock().unwrap();
|
||||||
workers_table.remove(&id);
|
let maybe_worker = workers_table.remove(&id);
|
||||||
|
if let Some(worker) = maybe_worker {
|
||||||
|
let mut channels = worker.state.worker_channels.lock().unwrap();
|
||||||
|
channels.sender.close_channel();
|
||||||
|
channels.receiver.close();
|
||||||
|
};
|
||||||
futures::future::ok(json!({}))
|
futures::future::ok(json!({}))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -108,6 +108,7 @@ pub struct DenoPermissions {
|
||||||
pub net_whitelist: HashSet<String>,
|
pub net_whitelist: HashSet<String>,
|
||||||
pub allow_env: PermissionState,
|
pub allow_env: PermissionState,
|
||||||
pub allow_run: PermissionState,
|
pub allow_run: PermissionState,
|
||||||
|
pub allow_plugin: PermissionState,
|
||||||
pub allow_hrtime: PermissionState,
|
pub allow_hrtime: PermissionState,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,6 +123,7 @@ impl DenoPermissions {
|
||||||
net_whitelist: flags.net_whitelist.iter().cloned().collect(),
|
net_whitelist: flags.net_whitelist.iter().cloned().collect(),
|
||||||
allow_env: PermissionState::from(flags.allow_env),
|
allow_env: PermissionState::from(flags.allow_env),
|
||||||
allow_run: PermissionState::from(flags.allow_run),
|
allow_run: PermissionState::from(flags.allow_run),
|
||||||
|
allow_plugin: PermissionState::from(flags.allow_plugin),
|
||||||
allow_hrtime: PermissionState::from(flags.allow_hrtime),
|
allow_hrtime: PermissionState::from(flags.allow_hrtime),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,6 +209,13 @@ impl DenoPermissions {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_plugin(&self, filename: &str) -> Result<(), ErrBox> {
|
||||||
|
self.allow_plugin.check(
|
||||||
|
&format!("access to open a plugin: {}", filename),
|
||||||
|
"run again with the --allow-plugin flag",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn request_run(&mut self) -> PermissionState {
|
pub fn request_run(&mut self) -> PermissionState {
|
||||||
self
|
self
|
||||||
.allow_run
|
.allow_run
|
||||||
|
@ -258,6 +267,10 @@ impl DenoPermissions {
|
||||||
.request("Deno requests to access to high precision time.")
|
.request("Deno requests to access to high precision time.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn request_plugin(&mut self) -> PermissionState {
|
||||||
|
self.allow_plugin.request("Deno requests to open plugins.")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_permission_state(
|
pub fn get_permission_state(
|
||||||
&self,
|
&self,
|
||||||
name: &str,
|
name: &str,
|
||||||
|
@ -270,6 +283,7 @@ impl DenoPermissions {
|
||||||
"write" => Ok(self.get_state_write(path)),
|
"write" => Ok(self.get_state_write(path)),
|
||||||
"net" => self.get_state_net_url(url),
|
"net" => self.get_state_net_url(url),
|
||||||
"env" => Ok(self.allow_env),
|
"env" => Ok(self.allow_env),
|
||||||
|
"plugin" => Ok(self.allow_plugin),
|
||||||
"hrtime" => Ok(self.allow_hrtime),
|
"hrtime" => Ok(self.allow_hrtime),
|
||||||
n => Err(type_error(format!("No such permission name: {}", n))),
|
n => Err(type_error(format!("No such permission name: {}", n))),
|
||||||
}
|
}
|
||||||
|
@ -652,6 +666,21 @@ mod tests {
|
||||||
assert_eq!(perms1.request_env(), PermissionState::Deny);
|
assert_eq!(perms1.request_env(), PermissionState::Deny);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_permissions_request_plugin() {
|
||||||
|
let mut perms0 = DenoPermissions::from_flags(&DenoFlags {
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
set_prompt_result(true);
|
||||||
|
assert_eq!(perms0.request_plugin(), PermissionState::Allow);
|
||||||
|
|
||||||
|
let mut perms1 = DenoPermissions::from_flags(&DenoFlags {
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
set_prompt_result(false);
|
||||||
|
assert_eq!(perms1.request_plugin(), PermissionState::Deny);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_permissions_request_hrtime() {
|
fn test_permissions_request_hrtime() {
|
||||||
let mut perms0 = DenoPermissions::from_flags(&DenoFlags {
|
let mut perms0 = DenoPermissions::from_flags(&DenoFlags {
|
||||||
|
|
|
@ -295,6 +295,11 @@ impl ThreadSafeState {
|
||||||
self.permissions.lock().unwrap().check_run()
|
self.permissions.lock().unwrap().check_run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn check_plugin(&self, filename: &str) -> Result<(), ErrBox> {
|
||||||
|
self.permissions.lock().unwrap().check_plugin(filename)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn check_dyn_import(
|
pub fn check_dyn_import(
|
||||||
self: &Self,
|
self: &Self,
|
||||||
module_specifier: &ModuleSpecifier,
|
module_specifier: &ModuleSpecifier,
|
||||||
|
|
|
@ -50,6 +50,7 @@ impl Worker {
|
||||||
let isolate = Arc::new(Mutex::new(deno::Isolate::new(startup_data, false)));
|
let isolate = Arc::new(Mutex::new(deno::Isolate::new(startup_data, false)));
|
||||||
{
|
{
|
||||||
let mut i = isolate.lock().unwrap();
|
let mut i = isolate.lock().unwrap();
|
||||||
|
let op_registry = i.op_registry.clone();
|
||||||
|
|
||||||
ops::compiler::init(&mut i, &state);
|
ops::compiler::init(&mut i, &state);
|
||||||
ops::errors::init(&mut i, &state);
|
ops::errors::init(&mut i, &state);
|
||||||
|
@ -57,6 +58,7 @@ impl Worker {
|
||||||
ops::files::init(&mut i, &state);
|
ops::files::init(&mut i, &state);
|
||||||
ops::fs::init(&mut i, &state);
|
ops::fs::init(&mut i, &state);
|
||||||
ops::io::init(&mut i, &state);
|
ops::io::init(&mut i, &state);
|
||||||
|
ops::plugins::init(&mut i, &state, op_registry);
|
||||||
ops::net::init(&mut i, &state);
|
ops::net::init(&mut i, &state);
|
||||||
ops::tls::init(&mut i, &state);
|
ops::tls::init(&mut i, &state);
|
||||||
ops::os::init(&mut i, &state);
|
ops::os::init(&mut i, &state);
|
||||||
|
|
|
@ -14,6 +14,7 @@ mod libdeno;
|
||||||
mod module_specifier;
|
mod module_specifier;
|
||||||
mod modules;
|
mod modules;
|
||||||
mod ops;
|
mod ops;
|
||||||
|
mod plugins;
|
||||||
mod resources;
|
mod resources;
|
||||||
mod shared_queue;
|
mod shared_queue;
|
||||||
|
|
||||||
|
@ -27,6 +28,7 @@ pub use crate::libdeno::PinnedBuf;
|
||||||
pub use crate::module_specifier::*;
|
pub use crate::module_specifier::*;
|
||||||
pub use crate::modules::*;
|
pub use crate::modules::*;
|
||||||
pub use crate::ops::*;
|
pub use crate::ops::*;
|
||||||
|
pub use crate::plugins::*;
|
||||||
pub use crate::resources::*;
|
pub use crate::resources::*;
|
||||||
|
|
||||||
pub fn v8_version() -> &'static str {
|
pub fn v8_version() -> &'static str {
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub type CoreError = ();
|
||||||
pub type CoreOp = Op<CoreError>;
|
pub type CoreOp = Op<CoreError>;
|
||||||
|
|
||||||
/// Main type describing op
|
/// Main type describing op
|
||||||
type OpDispatcher =
|
pub type OpDispatcher =
|
||||||
dyn Fn(&[u8], Option<PinnedBuf>) -> CoreOp + Send + Sync + 'static;
|
dyn Fn(&[u8], Option<PinnedBuf>) -> CoreOp + Send + Sync + 'static;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|
22
core/plugins.rs
Normal file
22
core/plugins.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
use crate::libdeno::PinnedBuf;
|
||||||
|
use crate::ops::CoreOp;
|
||||||
|
|
||||||
|
pub type PluginInitFn = fn(context: &mut dyn PluginInitContext);
|
||||||
|
|
||||||
|
pub trait PluginInitContext {
|
||||||
|
fn register_op(
|
||||||
|
&mut self,
|
||||||
|
name: &str,
|
||||||
|
op: Box<dyn Fn(&[u8], Option<PinnedBuf>) -> CoreOp + Send + Sync + 'static>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! init_fn {
|
||||||
|
($fn:path) => {
|
||||||
|
#[no_mangle]
|
||||||
|
pub fn deno_plugin_init(context: &mut dyn PluginInitContext) {
|
||||||
|
$fn(context)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
14
test_plugin/Cargo.toml
Normal file
14
test_plugin/Cargo.toml
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[package]
|
||||||
|
name = "test_plugin"
|
||||||
|
version = "0.0.1"
|
||||||
|
authors = ["the deno authors"]
|
||||||
|
edition = "2018"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
futures = "0.3"
|
||||||
|
deno = { path = "../core" }
|
||||||
|
deno_cli = { path = "../cli" }
|
53
test_plugin/src/lib.rs
Normal file
53
test_plugin/src/lib.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
#[macro_use]
|
||||||
|
extern crate deno;
|
||||||
|
extern crate futures;
|
||||||
|
|
||||||
|
use deno::CoreOp;
|
||||||
|
use deno::Op;
|
||||||
|
use deno::PluginInitContext;
|
||||||
|
use deno::{Buf, PinnedBuf};
|
||||||
|
use futures::future::FutureExt;
|
||||||
|
|
||||||
|
fn init(context: &mut dyn PluginInitContext) {
|
||||||
|
context.register_op("testSync", Box::new(op_test_sync));
|
||||||
|
context.register_op("testAsync", Box::new(op_test_async));
|
||||||
|
}
|
||||||
|
init_fn!(init);
|
||||||
|
|
||||||
|
pub fn op_test_sync(data: &[u8], zero_copy: Option<PinnedBuf>) -> CoreOp {
|
||||||
|
if let Some(buf) = zero_copy {
|
||||||
|
let data_str = std::str::from_utf8(&data[..]).unwrap();
|
||||||
|
let buf_str = std::str::from_utf8(&buf[..]).unwrap();
|
||||||
|
println!(
|
||||||
|
"Hello from plugin. data: {} | zero_copy: {}",
|
||||||
|
data_str, buf_str
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let result = b"test";
|
||||||
|
let result_box: Buf = Box::new(*result);
|
||||||
|
Op::Sync(result_box)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn op_test_async(data: &[u8], zero_copy: Option<PinnedBuf>) -> CoreOp {
|
||||||
|
let data_str = std::str::from_utf8(&data[..]).unwrap().to_string();
|
||||||
|
let fut = async move {
|
||||||
|
if let Some(buf) = zero_copy {
|
||||||
|
let buf_str = std::str::from_utf8(&buf[..]).unwrap();
|
||||||
|
println!(
|
||||||
|
"Hello from plugin. data: {} | zero_copy: {}",
|
||||||
|
data_str, buf_str
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let (tx, rx) = futures::channel::oneshot::channel::<Result<(), ()>>();
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
std::thread::sleep(std::time::Duration::from_secs(1));
|
||||||
|
tx.send(Ok(())).unwrap();
|
||||||
|
});
|
||||||
|
assert!(rx.await.is_ok());
|
||||||
|
let result = b"test";
|
||||||
|
let result_box: Buf = Box::new(*result);
|
||||||
|
Ok(result_box)
|
||||||
|
};
|
||||||
|
|
||||||
|
Op::Async(fut.boxed())
|
||||||
|
}
|
44
test_plugin/tests/integration_tests.rs
Normal file
44
test_plugin/tests/integration_tests.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
use deno_cli::test_util::*;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
fn deno_cmd() -> Command {
|
||||||
|
assert!(deno_exe_path().exists());
|
||||||
|
Command::new(deno_exe_path())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
const BUILD_VARIANT: &str = "debug";
|
||||||
|
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
const BUILD_VARIANT: &str = "release";
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn basic() {
|
||||||
|
let mut build_plugin_base = Command::new("cargo");
|
||||||
|
let mut build_plugin =
|
||||||
|
build_plugin_base.arg("build").arg("-p").arg("test_plugin");
|
||||||
|
if BUILD_VARIANT == "release" {
|
||||||
|
build_plugin = build_plugin.arg("--release");
|
||||||
|
}
|
||||||
|
let _build_plugin_output = build_plugin.output().unwrap();
|
||||||
|
let output = deno_cmd()
|
||||||
|
.arg("--allow-plugin")
|
||||||
|
.arg("tests/test.js")
|
||||||
|
.arg(BUILD_VARIANT)
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
let stdout = std::str::from_utf8(&output.stdout).unwrap();
|
||||||
|
let stderr = std::str::from_utf8(&output.stderr).unwrap();
|
||||||
|
if !output.status.success() {
|
||||||
|
println!("stdout {}", stdout);
|
||||||
|
println!("stderr {}", stderr);
|
||||||
|
}
|
||||||
|
assert!(output.status.success());
|
||||||
|
let expected = if cfg!(target_os = "windows") {
|
||||||
|
"Hello from plugin. data: test | zero_copy: test\nPlugin Sync Response: test\r\nHello from plugin. data: test | zero_copy: test\nPlugin Async Response: test\r\n"
|
||||||
|
} else {
|
||||||
|
"Hello from plugin. data: test | zero_copy: test\nPlugin Sync Response: test\nHello from plugin. data: test | zero_copy: test\nPlugin Async Response: test\n"
|
||||||
|
};
|
||||||
|
assert_eq!(stdout, expected);
|
||||||
|
assert_eq!(stderr, "");
|
||||||
|
}
|
47
test_plugin/tests/test.js
Normal file
47
test_plugin/tests/test.js
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
const filenameBase = "test_plugin";
|
||||||
|
|
||||||
|
let filenameSuffix = ".so";
|
||||||
|
let filenamePrefix = "lib";
|
||||||
|
|
||||||
|
if (Deno.build.os === "win") {
|
||||||
|
filenameSuffix = ".dll";
|
||||||
|
filenamePrefix = "";
|
||||||
|
}
|
||||||
|
if (Deno.build.os === "mac") {
|
||||||
|
filenameSuffix = ".dylib";
|
||||||
|
}
|
||||||
|
|
||||||
|
const filename = `../target/${Deno.args[1]}/${filenamePrefix}${filenameBase}${filenameSuffix}`;
|
||||||
|
|
||||||
|
const plugin = Deno.openPlugin(filename);
|
||||||
|
|
||||||
|
const { testSync, testAsync } = plugin.ops;
|
||||||
|
|
||||||
|
const textDecoder = new TextDecoder();
|
||||||
|
|
||||||
|
function runTestSync() {
|
||||||
|
const response = testSync.dispatch(
|
||||||
|
new Uint8Array([116, 101, 115, 116]),
|
||||||
|
new Uint8Array([116, 101, 115, 116])
|
||||||
|
);
|
||||||
|
|
||||||
|
console.log(`Plugin Sync Response: ${textDecoder.decode(response)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
testAsync.setAsyncHandler(response => {
|
||||||
|
console.log(`Plugin Async Response: ${textDecoder.decode(response)}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
function runTestAsync() {
|
||||||
|
const response = testAsync.dispatch(
|
||||||
|
new Uint8Array([116, 101, 115, 116]),
|
||||||
|
new Uint8Array([116, 101, 115, 116])
|
||||||
|
);
|
||||||
|
|
||||||
|
if (response != null || response != undefined) {
|
||||||
|
throw new Error("Expected null response!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runTestSync();
|
||||||
|
runTestAsync();
|
Loading…
Add table
Reference in a new issue