mirror of
https://github.com/denoland/deno.git
synced 2025-03-04 01:44:26 -05:00
feat: Support Inspector / Chrome Devtools (#4484)
This is a first pass implementation which is still missing several important features: - support for --inspect-brk (#4503) - support for source maps (#4501) - support for piping console.log to devtools console (#4502) Co-authored-by: Bert Belder <bertbelder@gmail.com> Co-authored-by: Matt Harrison <mt.harrison86@gmail.com> Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com>
This commit is contained in:
parent
8bcdb422e3
commit
2874664e91
12 changed files with 1153 additions and 37 deletions
390
Cargo.lock
generated
390
Cargo.lock
generated
|
@ -169,6 +169,12 @@ version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d5ca2cd0adc3f48f9e9ea5a6bbdf9ccc0bfade884847e484d452414c7ccffb3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
@ -186,6 +192,27 @@ dependencies = [
|
||||||
"constant_time_eq",
|
"constant_time_eq",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
|
||||||
|
dependencies = [
|
||||||
|
"block-padding",
|
||||||
|
"byte-tools",
|
||||||
|
"byteorder",
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-padding"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5"
|
||||||
|
dependencies = [
|
||||||
|
"byte-tools",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "brotli"
|
name = "brotli"
|
||||||
version = "3.3.0"
|
version = "3.3.0"
|
||||||
|
@ -207,12 +234,28 @@ dependencies = [
|
||||||
"alloc-stdlib",
|
"alloc-stdlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "buf_redux"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
"safemem",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.2.0"
|
version = "3.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742"
|
checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byte-tools"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
version = "1.3.4"
|
version = "1.3.4"
|
||||||
|
@ -435,7 +478,7 @@ dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"nix",
|
"nix",
|
||||||
"notify",
|
"notify",
|
||||||
"os_pipe",
|
"os_pipe",
|
||||||
|
@ -455,9 +498,12 @@ dependencies = [
|
||||||
"termcolor",
|
"termcolor",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-rustls",
|
"tokio-rustls",
|
||||||
|
"tokio-tungstenite",
|
||||||
"url 2.1.1",
|
"url 2.1.1",
|
||||||
"utime",
|
"utime",
|
||||||
|
"uuid",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
|
"warp",
|
||||||
"webpki",
|
"webpki",
|
||||||
"webpki-roots 0.19.0",
|
"webpki-roots 0.19.0",
|
||||||
"winapi 0.3.8",
|
"winapi 0.3.8",
|
||||||
|
@ -472,7 +518,7 @@ dependencies = [
|
||||||
"futures 0.3.4",
|
"futures 0.3.4",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"rusty_v8",
|
"rusty_v8",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -499,6 +545,15 @@ dependencies = [
|
||||||
"syn 0.15.44",
|
"syn 0.15.44",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs"
|
name = "dirs"
|
||||||
version = "2.0.2"
|
version = "2.0.2"
|
||||||
|
@ -626,6 +681,12 @@ dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fake-simd"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "filetime"
|
name = "filetime"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
@ -828,6 +889,15 @@ dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.14"
|
version = "0.1.14"
|
||||||
|
@ -858,7 +928,7 @@ dependencies = [
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"slab",
|
"slab",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
|
@ -874,6 +944,31 @@ dependencies = [
|
||||||
"autocfg 0.1.7",
|
"autocfg 0.1.7",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "headers"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed18eb2459bf1a09ad2d6b1547840c3e5e62882fa09b9a6a20b1de8e3228848f"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.12.0",
|
||||||
|
"bitflags",
|
||||||
|
"bytes 0.5.4",
|
||||||
|
"headers-core",
|
||||||
|
"http",
|
||||||
|
"mime 0.3.16",
|
||||||
|
"sha-1",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "headers-core"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
|
||||||
|
dependencies = [
|
||||||
|
"http",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.1.8"
|
version = "0.1.8"
|
||||||
|
@ -925,7 +1020,7 @@ dependencies = [
|
||||||
"http-body",
|
"http-body",
|
||||||
"httparse",
|
"httparse",
|
||||||
"itoa",
|
"itoa",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"net2",
|
"net2",
|
||||||
"pin-project",
|
"pin-project",
|
||||||
"time",
|
"time",
|
||||||
|
@ -944,7 +1039,7 @@ dependencies = [
|
||||||
"ct-logs",
|
"ct-logs",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hyper",
|
"hyper",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"rustls",
|
"rustls",
|
||||||
"rustls-native-certs",
|
"rustls-native-certs",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -1023,6 +1118,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "input_buffer"
|
||||||
|
version = "0.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19a8a95243d5a0398cae618ec29477c6e3cb631152be5c19481f80bc71559754"
|
||||||
|
dependencies = [
|
||||||
|
"bytes 0.5.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iovec"
|
name = "iovec"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
@ -1085,6 +1189,15 @@ dependencies = [
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
|
||||||
|
dependencies = [
|
||||||
|
"log 0.4.8",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.8"
|
version = "0.4.8"
|
||||||
|
@ -1112,20 +1225,41 @@ version = "2.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0"
|
||||||
|
dependencies = [
|
||||||
|
"log 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
version = "0.3.16"
|
version = "0.3.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mime_guess"
|
||||||
|
version = "1.8.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "216929a5ee4dd316b1702eedf5e74548c123d370f47841ceaac38ca154690ca3"
|
||||||
|
dependencies = [
|
||||||
|
"mime 0.2.6",
|
||||||
|
"phf",
|
||||||
|
"phf_codegen",
|
||||||
|
"unicase 1.4.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime_guess"
|
name = "mime_guess"
|
||||||
version = "2.0.3"
|
version = "2.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
|
checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"mime",
|
"mime 0.3.16",
|
||||||
"unicase",
|
"unicase 2.6.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1149,7 +1283,7 @@ dependencies = [
|
||||||
"iovec",
|
"iovec",
|
||||||
"kernel32-sys",
|
"kernel32-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"miow 0.2.1",
|
"miow 0.2.1",
|
||||||
"net2",
|
"net2",
|
||||||
"slab",
|
"slab",
|
||||||
|
@ -1163,7 +1297,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
|
checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazycell",
|
"lazycell",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"mio",
|
"mio",
|
||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
@ -1174,7 +1308,7 @@ version = "0.1.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3"
|
checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"mio",
|
"mio",
|
||||||
"miow 0.3.3",
|
"miow 0.3.3",
|
||||||
"winapi 0.3.8",
|
"winapi 0.3.8",
|
||||||
|
@ -1213,6 +1347,24 @@ dependencies = [
|
||||||
"winapi 0.3.8",
|
"winapi 0.3.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "multipart"
|
||||||
|
version = "0.16.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "136eed74cadb9edd2651ffba732b19a450316b680e4f48d6c79e905799e19d01"
|
||||||
|
dependencies = [
|
||||||
|
"buf_redux",
|
||||||
|
"httparse",
|
||||||
|
"log 0.4.8",
|
||||||
|
"mime 0.2.6",
|
||||||
|
"mime_guess 1.8.8",
|
||||||
|
"quick-error",
|
||||||
|
"rand 0.6.5",
|
||||||
|
"safemem",
|
||||||
|
"tempfile",
|
||||||
|
"twoway",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "net2"
|
name = "net2"
|
||||||
version = "0.2.33"
|
version = "0.2.33"
|
||||||
|
@ -1311,6 +1463,12 @@ version = "1.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b"
|
checksum = "b1c601810575c99596d4afc46f78a678c80105117c379eb3650cf99b8a21ce5b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "opaque-debug"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-probe"
|
name = "openssl-probe"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -1402,23 +1560,62 @@ version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf"
|
||||||
|
version = "0.7.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18"
|
||||||
|
dependencies = [
|
||||||
|
"phf_shared 0.7.24",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_codegen"
|
||||||
|
version = "0.7.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e"
|
||||||
|
dependencies = [
|
||||||
|
"phf_generator 0.7.24",
|
||||||
|
"phf_shared 0.7.24",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_generator"
|
||||||
|
version = "0.7.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662"
|
||||||
|
dependencies = [
|
||||||
|
"phf_shared 0.7.24",
|
||||||
|
"rand 0.6.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf_generator"
|
name = "phf_generator"
|
||||||
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"
|
||||||
checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
|
checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_shared",
|
"phf_shared 0.8.0",
|
||||||
"rand 0.7.3",
|
"rand 0.7.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_shared"
|
||||||
|
version = "0.7.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0"
|
||||||
|
dependencies = [
|
||||||
|
"siphasher 0.2.3",
|
||||||
|
"unicase 1.4.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "phf_shared"
|
name = "phf_shared"
|
||||||
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"
|
||||||
checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
|
checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"siphasher",
|
"siphasher 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1521,6 +1718,12 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quick-error"
|
||||||
|
version = "1.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "0.6.13"
|
version = "0.6.13"
|
||||||
|
@ -1780,9 +1983,9 @@ dependencies = [
|
||||||
"hyper-rustls",
|
"hyper-rustls",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"mime",
|
"mime 0.3.16",
|
||||||
"mime_guess",
|
"mime_guess 2.0.3",
|
||||||
"percent-encoding 2.1.0",
|
"percent-encoding 2.1.0",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rustls",
|
"rustls",
|
||||||
|
@ -1848,7 +2051,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1"
|
checksum = "c0d4a31f5d68413404705d6982529b0e11a9aacd4839d1d6222ee3b8cb4015e1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.11.0",
|
"base64 0.11.0",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"ring",
|
"ring",
|
||||||
"sct",
|
"sct",
|
||||||
"webpki",
|
"webpki",
|
||||||
|
@ -1888,7 +2091,7 @@ dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"dirs",
|
"dirs",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"memchr",
|
"memchr",
|
||||||
"nix",
|
"nix",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
|
@ -1903,6 +2106,12 @@ version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
|
checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "safemem"
|
||||||
|
version = "0.3.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "same-file"
|
name = "same-file"
|
||||||
version = "1.0.6"
|
version = "1.0.6"
|
||||||
|
@ -2031,6 +2240,18 @@ dependencies = [
|
||||||
"url 2.1.1",
|
"url 2.1.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha-1"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"digest",
|
||||||
|
"fake-simd",
|
||||||
|
"opaque-debug",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
@ -2041,6 +2262,12 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "siphasher"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "siphasher"
|
name = "siphasher"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -2116,7 +2343,7 @@ checksum = "2940c75beb4e3bf3a494cef919a747a2cb81e52571e212bfbd185074add7208a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
"phf_shared",
|
"phf_shared 0.8.0",
|
||||||
"precomputed-hash",
|
"precomputed-hash",
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -2127,8 +2354,8 @@ version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97"
|
checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"phf_generator",
|
"phf_generator 0.8.0",
|
||||||
"phf_shared",
|
"phf_shared 0.8.0",
|
||||||
"proc-macro2 1.0.9",
|
"proc-macro2 1.0.9",
|
||||||
"quote 1.0.3",
|
"quote 1.0.3",
|
||||||
]
|
]
|
||||||
|
@ -2182,7 +2409,7 @@ dependencies = [
|
||||||
"from_variant",
|
"from_variant",
|
||||||
"fxhash",
|
"fxhash",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"parking_lot 0.7.1",
|
"parking_lot 0.7.1",
|
||||||
"scoped-tls",
|
"scoped-tls",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -2214,7 +2441,7 @@ checksum = "701e681b7783c5b9d3df9e18592494ca3cba7a2fa8fc98d4d4f423ae993df155"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
"enum_kind",
|
"enum_kind",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -2377,7 +2604,7 @@ checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes 0.4.12",
|
"bytes 0.4.12",
|
||||||
"futures 0.1.29",
|
"futures 0.1.29",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2403,6 +2630,19 @@ dependencies = [
|
||||||
"webpki",
|
"webpki",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-tungstenite"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b8b8fe88007ebc363512449868d7da4389c9400072a3f666f212c7280082882a"
|
||||||
|
dependencies = [
|
||||||
|
"futures 0.3.4",
|
||||||
|
"log 0.4.8",
|
||||||
|
"pin-project",
|
||||||
|
"tokio",
|
||||||
|
"tungstenite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -2412,7 +2652,7 @@ dependencies = [
|
||||||
"bytes 0.5.4",
|
"bytes 0.5.4",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
@ -2429,13 +2669,56 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
|
checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tungstenite"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cfea31758bf674f990918962e8e5f07071a3161bd7c4138ed23e416e1ac4264e"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.11.0",
|
||||||
|
"byteorder",
|
||||||
|
"bytes 0.5.4",
|
||||||
|
"http",
|
||||||
|
"httparse",
|
||||||
|
"input_buffer",
|
||||||
|
"log 0.4.8",
|
||||||
|
"rand 0.7.3",
|
||||||
|
"sha-1",
|
||||||
|
"url 2.1.1",
|
||||||
|
"utf-8",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "twoway"
|
||||||
|
version = "0.1.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.11.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicase"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33"
|
||||||
|
dependencies = [
|
||||||
|
"version_check 0.1.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"version_check",
|
"version_check 0.9.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2508,6 +2791,18 @@ dependencies = [
|
||||||
"percent-encoding 2.1.0",
|
"percent-encoding 2.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "urlencoding"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3df3561629a8bb4c57e5a2e4c43348d9e29c7c29d9b1c4c1f47166deca8f37ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf-8"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05e42f7c18b8f902290b009cde6d651262f956c98bc51bca4cd1d511c9cd85c7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "utf8parse"
|
name = "utf8parse"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
|
@ -2525,12 +2820,27 @@ dependencies = [
|
||||||
"winapi 0.2.8",
|
"winapi 0.2.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "uuid"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11"
|
||||||
|
dependencies = [
|
||||||
|
"rand 0.7.3",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "vec_map"
|
name = "vec_map"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version_check"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.1"
|
version = "0.9.1"
|
||||||
|
@ -2560,10 +2870,36 @@ version = "0.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
|
checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"try-lock",
|
"try-lock",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "warp"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "54cd1e2b3eb3539284d88b76a9afcf5e20f2ef2fab74db5b21a1c30d7d945e82"
|
||||||
|
dependencies = [
|
||||||
|
"bytes 0.5.4",
|
||||||
|
"futures 0.3.4",
|
||||||
|
"headers",
|
||||||
|
"http",
|
||||||
|
"hyper",
|
||||||
|
"log 0.4.8",
|
||||||
|
"mime 0.3.16",
|
||||||
|
"mime_guess 2.0.3",
|
||||||
|
"multipart",
|
||||||
|
"pin-project",
|
||||||
|
"scoped-tls",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serde_urlencoded",
|
||||||
|
"tokio",
|
||||||
|
"tokio-tungstenite",
|
||||||
|
"tower-service",
|
||||||
|
"urlencoding",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.9.0+wasi-snapshot-preview1"
|
version = "0.9.0+wasi-snapshot-preview1"
|
||||||
|
@ -2590,7 +2926,7 @@ checksum = "e0da9c9a19850d3af6df1cb9574970b566d617ecfaf36eb0b706b6f3ef9bd2f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log 0.4.8",
|
||||||
"proc-macro2 1.0.9",
|
"proc-macro2 1.0.9",
|
||||||
"quote 1.0.3",
|
"quote 1.0.3",
|
||||||
"syn 1.0.16",
|
"syn 1.0.16",
|
||||||
|
|
|
@ -61,7 +61,10 @@ utime = "0.2.1"
|
||||||
webpki = "0.21.2"
|
webpki = "0.21.2"
|
||||||
webpki-roots = "0.19.0"
|
webpki-roots = "0.19.0"
|
||||||
walkdir = "2.3.1"
|
walkdir = "2.3.1"
|
||||||
|
warp = "0.2.2"
|
||||||
semver-parser = "0.9.0"
|
semver-parser = "0.9.0"
|
||||||
|
uuid = { version = "0.8", features = ["v4"] }
|
||||||
|
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = "0.3.8"
|
winapi = "0.3.8"
|
||||||
|
@ -72,6 +75,8 @@ nix = "0.14" # rustyline depends on 0.14, to avoid duplicates we do too.
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
os_pipe = "0.9.1"
|
os_pipe = "0.9.1"
|
||||||
|
# Used for testing inspector. Keep in-sync with warp.
|
||||||
|
tokio-tungstenite = { version = "0.10", features = ["connect"] }
|
||||||
|
|
||||||
[target.'cfg(unix)'.dev-dependencies]
|
[target.'cfg(unix)'.dev-dependencies]
|
||||||
pty = "0.2.2"
|
pty = "0.2.2"
|
||||||
|
|
88
cli/flags.rs
88
cli/flags.rs
|
@ -101,6 +101,8 @@ pub struct Flags {
|
||||||
pub no_prompts: bool,
|
pub no_prompts: bool,
|
||||||
pub no_remote: bool,
|
pub no_remote: bool,
|
||||||
pub cached_only: bool,
|
pub cached_only: bool,
|
||||||
|
pub inspect: Option<String>,
|
||||||
|
pub inspect_brk: Option<String>,
|
||||||
pub seed: Option<u64>,
|
pub seed: Option<u64>,
|
||||||
pub v8_flags: Option<Vec<String>>,
|
pub v8_flags: Option<Vec<String>>,
|
||||||
|
|
||||||
|
@ -474,6 +476,7 @@ fn run_test_args_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
no_remote_arg_parse(flags, matches);
|
no_remote_arg_parse(flags, matches);
|
||||||
permission_args_parse(flags, matches);
|
permission_args_parse(flags, matches);
|
||||||
ca_file_arg_parse(flags, matches);
|
ca_file_arg_parse(flags, matches);
|
||||||
|
inspect_arg_parse(flags, matches);
|
||||||
|
|
||||||
if matches.is_present("cached-only") {
|
if matches.is_present("cached-only") {
|
||||||
flags.cached_only = true;
|
flags.cached_only = true;
|
||||||
|
@ -825,7 +828,7 @@ fn permission_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_test_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
|
fn run_test_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
|
||||||
permission_args(app)
|
permission_args(inspect_args(app))
|
||||||
.arg(importmap_arg())
|
.arg(importmap_arg())
|
||||||
.arg(reload_arg())
|
.arg(reload_arg())
|
||||||
.arg(config_arg())
|
.arg(config_arg())
|
||||||
|
@ -956,6 +959,54 @@ fn ca_file_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
flags.ca_file = matches.value_of("cert").map(ToOwned::to_owned);
|
flags.ca_file = matches.value_of("cert").map(ToOwned::to_owned);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inspect_args<'a, 'b>(app: App<'a, 'b>) -> App<'a, 'b> {
|
||||||
|
app
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("inspect")
|
||||||
|
.long("inspect")
|
||||||
|
.value_name("HOST:PORT")
|
||||||
|
.help("activate inspector on host:port (default: 127.0.0.1:9229)")
|
||||||
|
.min_values(0)
|
||||||
|
.max_values(1)
|
||||||
|
.require_equals(true)
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("inspect-brk")
|
||||||
|
.long("inspect-brk")
|
||||||
|
.value_name("HOST:PORT")
|
||||||
|
.help(
|
||||||
|
"activate inspector on host:port and break at start of user script",
|
||||||
|
)
|
||||||
|
.min_values(0)
|
||||||
|
.max_values(1)
|
||||||
|
.require_equals(true)
|
||||||
|
.takes_value(true),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inspect_arg_parse(flags: &mut Flags, matches: &clap::ArgMatches) {
|
||||||
|
const DEFAULT: &str = "127.0.0.1:9229";
|
||||||
|
flags.inspect = if matches.is_present("inspect") {
|
||||||
|
if let Some(host) = matches.value_of("inspect") {
|
||||||
|
Some(host.to_string())
|
||||||
|
} else {
|
||||||
|
Some(DEFAULT.to_string())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
flags.inspect_brk = if matches.is_present("inspect-brk") {
|
||||||
|
if let Some(host) = matches.value_of("inspect-brk") {
|
||||||
|
Some(host.to_string())
|
||||||
|
} else {
|
||||||
|
Some(DEFAULT.to_string())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
fn reload_arg<'a, 'b>() -> Arg<'a, 'b> {
|
fn reload_arg<'a, 'b>() -> Arg<'a, 'b> {
|
||||||
Arg::with_name("reload")
|
Arg::with_name("reload")
|
||||||
.short("r")
|
.short("r")
|
||||||
|
@ -2327,3 +2378,38 @@ fn repl_with_cafile() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inspect_default_host() {
|
||||||
|
let r = flags_from_vec_safe(svec!["deno", "run", "--inspect", "foo.js"]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Run {
|
||||||
|
script: "foo.js".to_string(),
|
||||||
|
},
|
||||||
|
inspect: Some("127.0.0.1:9229".to_string()),
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn inspect_custom_host() {
|
||||||
|
let r = flags_from_vec_safe(svec![
|
||||||
|
"deno",
|
||||||
|
"run",
|
||||||
|
"--inspect=deno.land:80",
|
||||||
|
"foo.js"
|
||||||
|
]);
|
||||||
|
assert_eq!(
|
||||||
|
r.unwrap(),
|
||||||
|
Flags {
|
||||||
|
subcommand: DenoSubcommand::Run {
|
||||||
|
script: "foo.js".to_string(),
|
||||||
|
},
|
||||||
|
inspect: Some("deno.land:80".to_string()),
|
||||||
|
..Flags::default()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ use crate::deno_dir;
|
||||||
use crate::file_fetcher::SourceFileFetcher;
|
use crate::file_fetcher::SourceFileFetcher;
|
||||||
use crate::flags;
|
use crate::flags;
|
||||||
use crate::http_cache;
|
use crate::http_cache;
|
||||||
|
use crate::inspector::InspectorServer;
|
||||||
use crate::lockfile::Lockfile;
|
use crate::lockfile::Lockfile;
|
||||||
use crate::msg;
|
use crate::msg;
|
||||||
use crate::permissions::DenoPermissions;
|
use crate::permissions::DenoPermissions;
|
||||||
|
@ -42,6 +43,7 @@ pub struct GlobalStateInner {
|
||||||
pub wasm_compiler: WasmCompiler,
|
pub wasm_compiler: WasmCompiler,
|
||||||
pub lockfile: Option<Mutex<Lockfile>>,
|
pub lockfile: Option<Mutex<Lockfile>>,
|
||||||
pub compiler_starts: AtomicUsize,
|
pub compiler_starts: AtomicUsize,
|
||||||
|
pub inspector_server: Option<InspectorServer>,
|
||||||
compile_lock: AsyncMutex<()>,
|
compile_lock: AsyncMutex<()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +84,16 @@ impl GlobalState {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let inspector_server = if let Some(ref host) = flags.inspect {
|
||||||
|
Some(InspectorServer::new(host, false))
|
||||||
|
} else if let Some(ref host) = flags.inspect_brk {
|
||||||
|
Some(InspectorServer::new(host, true))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let inner = GlobalStateInner {
|
let inner = GlobalStateInner {
|
||||||
|
inspector_server,
|
||||||
dir,
|
dir,
|
||||||
permissions: DenoPermissions::from_flags(&flags),
|
permissions: DenoPermissions::from_flags(&flags),
|
||||||
flags,
|
flags,
|
||||||
|
|
549
cli/inspector.rs
Normal file
549
cli/inspector.rs
Normal file
|
@ -0,0 +1,549 @@
|
||||||
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
// The documentation for the inspector API is sparse, but these are helpful:
|
||||||
|
// https://chromedevtools.github.io/devtools-protocol/
|
||||||
|
// https://hyperandroid.com/2020/02/12/v8-inspector-from-an-embedder-standpoint/
|
||||||
|
|
||||||
|
use deno_core::v8;
|
||||||
|
use futures;
|
||||||
|
use futures::executor;
|
||||||
|
use futures::future;
|
||||||
|
use futures::FutureExt;
|
||||||
|
use futures::SinkExt;
|
||||||
|
use futures::StreamExt;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::ffi::c_void;
|
||||||
|
use std::future::Future;
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
|
use std::net::SocketAddrV4;
|
||||||
|
use std::pin::Pin;
|
||||||
|
use std::ptr;
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
|
use std::sync::atomic::Ordering;
|
||||||
|
use std::sync::Arc;
|
||||||
|
use std::task::Context;
|
||||||
|
use std::task::Poll;
|
||||||
|
use tokio;
|
||||||
|
use tokio::sync::mpsc;
|
||||||
|
use tokio::sync::mpsc::error::TryRecvError;
|
||||||
|
use uuid::Uuid;
|
||||||
|
use warp;
|
||||||
|
use warp::filters::ws;
|
||||||
|
use warp::Filter;
|
||||||
|
|
||||||
|
const CONTEXT_GROUP_ID: i32 = 1;
|
||||||
|
|
||||||
|
/// Owned by GloalState, this channel end can be used by any isolate thread
|
||||||
|
/// to register it's inspector with the inspector server.
|
||||||
|
type ServerMsgTx = mpsc::UnboundedSender<ServerMsg>;
|
||||||
|
/// Owned by the inspector server thread, used to to receive information about
|
||||||
|
/// new isolates.
|
||||||
|
type ServerMsgRx = mpsc::UnboundedReceiver<ServerMsg>;
|
||||||
|
/// These messages can be sent from any thread to the server thread.
|
||||||
|
enum ServerMsg {
|
||||||
|
AddInspector(InspectorInfo),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Owned by the web socket server. Relays incoming websocket connections and
|
||||||
|
/// messages to the isolate/inspector thread.
|
||||||
|
type FrontendToInspectorTx = mpsc::UnboundedSender<FrontendToInspectorMsg>;
|
||||||
|
/// Owned by the isolate/worker. Receives incoming websocket connections and
|
||||||
|
/// messages from the inspector server thread.
|
||||||
|
type FrontendToInspectorRx = mpsc::UnboundedReceiver<FrontendToInspectorMsg>;
|
||||||
|
/// Messages sent over the FrontendToInspectorTx/FrontendToInspectorRx channel.
|
||||||
|
pub enum FrontendToInspectorMsg {
|
||||||
|
WsConnection {
|
||||||
|
session_uuid: Uuid,
|
||||||
|
session_to_frontend_tx: SessionToFrontendTx,
|
||||||
|
},
|
||||||
|
WsIncoming {
|
||||||
|
session_uuid: Uuid,
|
||||||
|
msg: ws::Message,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Owned by the deno inspector session, used to forward messages from the
|
||||||
|
/// inspector channel on the isolate thread to the websocket that is owned by
|
||||||
|
/// the inspector server.
|
||||||
|
type SessionToFrontendTx = mpsc::UnboundedSender<ws::Message>;
|
||||||
|
/// Owned by the inspector server. Messages arriving on this channel, coming
|
||||||
|
/// from the inspector session on the isolate thread are forwarded over the
|
||||||
|
/// websocket to the devtools frontend.
|
||||||
|
type SessionToFrontendRx = mpsc::UnboundedReceiver<ws::Message>;
|
||||||
|
|
||||||
|
/// Stored in a UUID hashmap, used by WS server. Clonable.
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct InspectorInfo {
|
||||||
|
uuid: Uuid,
|
||||||
|
frontend_to_inspector_tx: FrontendToInspectorTx,
|
||||||
|
inspector_handle: DenoInspectorHandle,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Owned by GlobalState.
|
||||||
|
pub struct InspectorServer {
|
||||||
|
address: SocketAddrV4,
|
||||||
|
thread_handle: Option<std::thread::JoinHandle<()>>,
|
||||||
|
server_msg_tx: Option<ServerMsgTx>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InspectorServer {
|
||||||
|
pub fn new(host: &str, brk: bool) -> Self {
|
||||||
|
if brk {
|
||||||
|
todo!("--inspect-brk not yet supported");
|
||||||
|
}
|
||||||
|
let address = host.parse::<SocketAddrV4>().unwrap();
|
||||||
|
let (server_msg_tx, server_msg_rx) = mpsc::unbounded_channel::<ServerMsg>();
|
||||||
|
let thread_handle = std::thread::spawn(move || {
|
||||||
|
crate::tokio_util::run_basic(server(address, server_msg_rx));
|
||||||
|
});
|
||||||
|
Self {
|
||||||
|
address,
|
||||||
|
thread_handle: Some(thread_handle),
|
||||||
|
server_msg_tx: Some(server_msg_tx),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Each worker/isolate to be debugged should call this exactly one.
|
||||||
|
/// Called from worker's thread
|
||||||
|
pub fn add_inspector(
|
||||||
|
&self,
|
||||||
|
isolate: &mut deno_core::Isolate,
|
||||||
|
) -> Box<DenoInspector> {
|
||||||
|
let deno_core::Isolate {
|
||||||
|
v8_isolate,
|
||||||
|
global_context,
|
||||||
|
..
|
||||||
|
} = isolate;
|
||||||
|
let v8_isolate = v8_isolate.as_mut().unwrap();
|
||||||
|
|
||||||
|
let mut hs = v8::HandleScope::new(v8_isolate);
|
||||||
|
let scope = hs.enter();
|
||||||
|
let context = global_context.get(scope).unwrap();
|
||||||
|
|
||||||
|
let server_msg_tx = self.server_msg_tx.as_ref().unwrap().clone();
|
||||||
|
let address = self.address;
|
||||||
|
let (frontend_to_inspector_tx, frontend_to_inspector_rx) =
|
||||||
|
mpsc::unbounded_channel::<FrontendToInspectorMsg>();
|
||||||
|
let uuid = Uuid::new_v4();
|
||||||
|
|
||||||
|
let inspector = crate::inspector::DenoInspector::new(
|
||||||
|
scope,
|
||||||
|
context,
|
||||||
|
frontend_to_inspector_rx,
|
||||||
|
);
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"Debugger listening on {}",
|
||||||
|
websocket_debugger_url(address, &uuid)
|
||||||
|
);
|
||||||
|
|
||||||
|
server_msg_tx
|
||||||
|
.send(ServerMsg::AddInspector(InspectorInfo {
|
||||||
|
uuid,
|
||||||
|
frontend_to_inspector_tx,
|
||||||
|
inspector_handle: DenoInspectorHandle::new(
|
||||||
|
&inspector,
|
||||||
|
v8_isolate.thread_safe_handle(),
|
||||||
|
),
|
||||||
|
}))
|
||||||
|
.unwrap_or_else(|_| {
|
||||||
|
panic!("sending message to inspector server thread failed");
|
||||||
|
});
|
||||||
|
|
||||||
|
inspector
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for InspectorServer {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
self.server_msg_tx.take();
|
||||||
|
self.thread_handle.take().unwrap().join().unwrap();
|
||||||
|
panic!("TODO: this drop is never called");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn websocket_debugger_url(address: SocketAddrV4, uuid: &Uuid) -> String {
|
||||||
|
format!("ws://{}:{}/ws/{}", address.ip(), address.port(), uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn server(address: SocketAddrV4, mut server_msg_rx: ServerMsgRx) {
|
||||||
|
let inspector_map = HashMap::<Uuid, InspectorInfo>::new();
|
||||||
|
let inspector_map = Arc::new(std::sync::Mutex::new(inspector_map));
|
||||||
|
|
||||||
|
let inspector_map_ = inspector_map.clone();
|
||||||
|
let msg_handler = async move {
|
||||||
|
while let Some(msg) = server_msg_rx.next().await {
|
||||||
|
match msg {
|
||||||
|
ServerMsg::AddInspector(inspector_info) => {
|
||||||
|
let existing = inspector_map_
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.insert(inspector_info.uuid, inspector_info);
|
||||||
|
if existing.is_some() {
|
||||||
|
panic!("UUID already in map");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let inspector_map_ = inspector_map.clone();
|
||||||
|
let websocket = warp::path("ws")
|
||||||
|
.and(warp::path::param())
|
||||||
|
.and(warp::ws())
|
||||||
|
.map(move |uuid: String, ws: warp::ws::Ws| {
|
||||||
|
let inspector_map__ = inspector_map_.clone();
|
||||||
|
ws.on_upgrade(move |socket| async move {
|
||||||
|
let inspector_info = {
|
||||||
|
if let Ok(uuid) = Uuid::parse_str(&uuid) {
|
||||||
|
let g = inspector_map__.lock().unwrap();
|
||||||
|
if let Some(inspector_info) = g.get(&uuid) {
|
||||||
|
inspector_info.clone()
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// send a message back so register_worker can return...
|
||||||
|
let (mut ws_tx, mut ws_rx) = socket.split();
|
||||||
|
|
||||||
|
let (session_to_frontend_tx, mut session_to_frontend_rx): (
|
||||||
|
SessionToFrontendTx,
|
||||||
|
SessionToFrontendRx,
|
||||||
|
) = mpsc::unbounded_channel();
|
||||||
|
|
||||||
|
// Not to be confused with the WS's uuid...
|
||||||
|
let session_uuid = Uuid::new_v4();
|
||||||
|
|
||||||
|
inspector_info
|
||||||
|
.frontend_to_inspector_tx
|
||||||
|
.send(FrontendToInspectorMsg::WsConnection {
|
||||||
|
session_to_frontend_tx,
|
||||||
|
session_uuid,
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|_| {
|
||||||
|
panic!("sending message to frontend_to_inspector_tx failed");
|
||||||
|
});
|
||||||
|
|
||||||
|
inspector_info.inspector_handle.interrupt();
|
||||||
|
|
||||||
|
let pump_to_inspector = async {
|
||||||
|
while let Some(Ok(msg)) = ws_rx.next().await {
|
||||||
|
inspector_info
|
||||||
|
.frontend_to_inspector_tx
|
||||||
|
.send(FrontendToInspectorMsg::WsIncoming { msg, session_uuid })
|
||||||
|
.unwrap_or_else(|_| {
|
||||||
|
panic!("sending message to frontend_to_inspector_tx failed");
|
||||||
|
});
|
||||||
|
|
||||||
|
inspector_info.inspector_handle.interrupt();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let pump_from_session = async {
|
||||||
|
while let Some(msg) = session_to_frontend_rx.next().await {
|
||||||
|
ws_tx.send(msg).await.ok();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
future::join(pump_to_inspector, pump_from_session).await;
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let inspector_map_ = inspector_map.clone();
|
||||||
|
let json_list =
|
||||||
|
warp::path("json")
|
||||||
|
.map(move || {
|
||||||
|
let g = inspector_map_.lock().unwrap();
|
||||||
|
let json_values: Vec<serde_json::Value> = g.iter().map(|(uuid, _)| {
|
||||||
|
let url = websocket_debugger_url(address, uuid);
|
||||||
|
json!({
|
||||||
|
"description": "deno",
|
||||||
|
"devtoolsFrontendUrl": format!("chrome-devtools://devtools/bundled/js_app.html?experiments=true&v8only=true&ws={}", url),
|
||||||
|
"faviconUrl": "https://deno.land/favicon.ico",
|
||||||
|
"id": uuid.to_string(),
|
||||||
|
"title": format!("deno[{}]", std::process::id()),
|
||||||
|
"type": "deno",
|
||||||
|
"url": "file://",
|
||||||
|
"webSocketDebuggerUrl": url,
|
||||||
|
})
|
||||||
|
}).collect();
|
||||||
|
warp::reply::json(&json!(json_values))
|
||||||
|
});
|
||||||
|
|
||||||
|
let version = warp::path!("json" / "version").map(|| {
|
||||||
|
warp::reply::json(&json!({
|
||||||
|
"Browser": format!("Deno/{}", crate::version::DENO),
|
||||||
|
"Protocol-Version": "1.3",
|
||||||
|
"V8-Version": crate::version::v8(),
|
||||||
|
}))
|
||||||
|
});
|
||||||
|
|
||||||
|
let routes = websocket.or(version).or(json_list);
|
||||||
|
let web_handler = warp::serve(routes).bind(address);
|
||||||
|
|
||||||
|
future::join(msg_handler, web_handler).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DenoInspector {
|
||||||
|
client: v8::inspector::V8InspectorClientBase,
|
||||||
|
inspector: v8::UniqueRef<v8::inspector::V8Inspector>,
|
||||||
|
pub sessions: HashMap<Uuid, Box<DenoInspectorSession>>,
|
||||||
|
frontend_to_inspector_rx: FrontendToInspectorRx,
|
||||||
|
paused: bool,
|
||||||
|
interrupted: Arc<AtomicBool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DenoInspector {
|
||||||
|
pub fn new<P>(
|
||||||
|
scope: &mut P,
|
||||||
|
context: v8::Local<v8::Context>,
|
||||||
|
frontend_to_inspector_rx: FrontendToInspectorRx,
|
||||||
|
) -> Box<Self>
|
||||||
|
where
|
||||||
|
P: v8::InIsolate,
|
||||||
|
{
|
||||||
|
let mut deno_inspector = new_box_with(|address| Self {
|
||||||
|
client: v8::inspector::V8InspectorClientBase::new::<Self>(),
|
||||||
|
// TODO(piscisaureus): V8Inspector::create() should require that
|
||||||
|
// the 'client' argument cannot move.
|
||||||
|
inspector: v8::inspector::V8Inspector::create(scope, unsafe {
|
||||||
|
&mut *address
|
||||||
|
}),
|
||||||
|
sessions: HashMap::new(),
|
||||||
|
frontend_to_inspector_rx,
|
||||||
|
paused: false,
|
||||||
|
interrupted: Arc::new(AtomicBool::new(false)),
|
||||||
|
});
|
||||||
|
|
||||||
|
let empty_view = v8::inspector::StringView::empty();
|
||||||
|
deno_inspector.inspector.context_created(
|
||||||
|
context,
|
||||||
|
CONTEXT_GROUP_ID,
|
||||||
|
&empty_view,
|
||||||
|
);
|
||||||
|
|
||||||
|
deno_inspector
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connect(
|
||||||
|
&mut self,
|
||||||
|
session_uuid: Uuid,
|
||||||
|
session_to_frontend_tx: SessionToFrontendTx,
|
||||||
|
) {
|
||||||
|
let session =
|
||||||
|
DenoInspectorSession::new(&mut self.inspector, session_to_frontend_tx);
|
||||||
|
self.sessions.insert(session_uuid, session);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch_frontend_to_inspector_msg(
|
||||||
|
&mut self,
|
||||||
|
msg: FrontendToInspectorMsg,
|
||||||
|
) {
|
||||||
|
match msg {
|
||||||
|
FrontendToInspectorMsg::WsConnection {
|
||||||
|
session_uuid,
|
||||||
|
session_to_frontend_tx,
|
||||||
|
} => {
|
||||||
|
self.connect(session_uuid, session_to_frontend_tx);
|
||||||
|
}
|
||||||
|
FrontendToInspectorMsg::WsIncoming { session_uuid, msg } => {
|
||||||
|
if let Some(deno_session) = self.sessions.get_mut(&session_uuid) {
|
||||||
|
deno_session.dispatch_protocol_message(msg)
|
||||||
|
} else {
|
||||||
|
info!("Unknown inspector session {}. msg {:?}", session_uuid, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" fn poll_interrupt(
|
||||||
|
_isolate: &mut v8::Isolate,
|
||||||
|
self_ptr: *mut c_void,
|
||||||
|
) {
|
||||||
|
let self_ = unsafe { &mut *(self_ptr as *mut Self) };
|
||||||
|
let _ = self_.poll_without_waker();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_without_waker(&mut self) -> Poll<<Self as Future>::Output> {
|
||||||
|
loop {
|
||||||
|
match self.frontend_to_inspector_rx.try_recv() {
|
||||||
|
Ok(msg) => self.dispatch_frontend_to_inspector_msg(msg),
|
||||||
|
Err(TryRecvError::Closed) => break Poll::Ready(()),
|
||||||
|
Err(TryRecvError::Empty)
|
||||||
|
if self.interrupted.swap(false, Ordering::AcqRel) => {}
|
||||||
|
Err(TryRecvError::Empty) => break Poll::Pending,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// DenoInspector implements a Future so that it can poll for incoming messages
|
||||||
|
/// from the WebSocket server. Since a Worker ownes a DenoInspector, and because
|
||||||
|
/// a Worker is a Future too, Worker::poll will call this.
|
||||||
|
impl Future for DenoInspector {
|
||||||
|
type Output = ();
|
||||||
|
|
||||||
|
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
|
let self_ = self.get_mut();
|
||||||
|
loop {
|
||||||
|
match self_.frontend_to_inspector_rx.poll_recv(cx) {
|
||||||
|
Poll::Ready(Some(msg)) => self_.dispatch_frontend_to_inspector_msg(msg),
|
||||||
|
Poll::Ready(None) => break Poll::Ready(()),
|
||||||
|
Poll::Pending if self_.interrupted.swap(false, Ordering::AcqRel) => {}
|
||||||
|
Poll::Pending => break Poll::Pending,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl v8::inspector::V8InspectorClientImpl for DenoInspector {
|
||||||
|
fn base(&self) -> &v8::inspector::V8InspectorClientBase {
|
||||||
|
&self.client
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_mut(&mut self) -> &mut v8::inspector::V8InspectorClientBase {
|
||||||
|
&mut self.client
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_message_loop_on_pause(&mut self, context_group_id: i32) {
|
||||||
|
assert_eq!(context_group_id, CONTEXT_GROUP_ID);
|
||||||
|
assert!(!self.paused);
|
||||||
|
self.paused = true;
|
||||||
|
|
||||||
|
// Creating a new executor and calling block_on generally causes a panic.
|
||||||
|
// In this case it works because the outer executor is provided by tokio
|
||||||
|
// and the one created here comes from the 'futures' crate, and they don't
|
||||||
|
// see each other.
|
||||||
|
let dispatch_messages_while_paused =
|
||||||
|
future::poll_fn(|cx| match self.poll_unpin(cx) {
|
||||||
|
Poll::Pending if self.paused => Poll::Pending,
|
||||||
|
_ => Poll::Ready(()),
|
||||||
|
});
|
||||||
|
executor::block_on(dispatch_messages_while_paused);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quit_message_loop_on_pause(&mut self) {
|
||||||
|
self.paused = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_if_waiting_for_debugger(&mut self, context_group_id: i32) {
|
||||||
|
assert_eq!(context_group_id, CONTEXT_GROUP_ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct DenoInspectorHandle {
|
||||||
|
deno_inspector_ptr: *mut c_void,
|
||||||
|
isolate_handle: v8::IsolateHandle,
|
||||||
|
interrupted: Arc<AtomicBool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DenoInspectorHandle {
|
||||||
|
pub fn new(
|
||||||
|
deno_inspector: &DenoInspector,
|
||||||
|
isolate_handle: v8::IsolateHandle,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
deno_inspector_ptr: deno_inspector as *const DenoInspector
|
||||||
|
as *const c_void as *mut c_void,
|
||||||
|
isolate_handle,
|
||||||
|
interrupted: deno_inspector.interrupted.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn interrupt(&self) {
|
||||||
|
if !self.interrupted.swap(true, Ordering::AcqRel) {
|
||||||
|
self.isolate_handle.request_interrupt(
|
||||||
|
DenoInspector::poll_interrupt,
|
||||||
|
self.deno_inspector_ptr,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for DenoInspectorHandle {}
|
||||||
|
unsafe impl Sync for DenoInspectorHandle {}
|
||||||
|
|
||||||
|
/// sub-class of v8::inspector::Channel
|
||||||
|
pub struct DenoInspectorSession {
|
||||||
|
channel: v8::inspector::ChannelBase,
|
||||||
|
session: v8::UniqueRef<v8::inspector::V8InspectorSession>,
|
||||||
|
session_to_frontend_tx: SessionToFrontendTx,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DenoInspectorSession {
|
||||||
|
pub fn new(
|
||||||
|
inspector: &mut v8::inspector::V8Inspector,
|
||||||
|
session_to_frontend_tx: SessionToFrontendTx,
|
||||||
|
) -> Box<Self> {
|
||||||
|
new_box_with(|address| {
|
||||||
|
let empty_view = v8::inspector::StringView::empty();
|
||||||
|
Self {
|
||||||
|
channel: v8::inspector::ChannelBase::new::<Self>(),
|
||||||
|
session: inspector.connect(
|
||||||
|
CONTEXT_GROUP_ID,
|
||||||
|
// Todo(piscisaureus): V8Inspector::connect() should require that
|
||||||
|
// the 'channel' argument cannot move.
|
||||||
|
unsafe { &mut *address },
|
||||||
|
&empty_view,
|
||||||
|
),
|
||||||
|
session_to_frontend_tx,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dispatch_protocol_message(&mut self, ws_msg: ws::Message) {
|
||||||
|
let bytes = ws_msg.as_bytes();
|
||||||
|
let string_view = v8::inspector::StringView::from(bytes);
|
||||||
|
self.session.dispatch_protocol_message(&string_view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl v8::inspector::ChannelImpl for DenoInspectorSession {
|
||||||
|
fn base(&self) -> &v8::inspector::ChannelBase {
|
||||||
|
&self.channel
|
||||||
|
}
|
||||||
|
|
||||||
|
fn base_mut(&mut self) -> &mut v8::inspector::ChannelBase {
|
||||||
|
&mut self.channel
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_response(
|
||||||
|
&mut self,
|
||||||
|
_call_id: i32,
|
||||||
|
message: v8::UniquePtr<v8::inspector::StringBuffer>,
|
||||||
|
) {
|
||||||
|
let ws_msg = v8_to_ws_msg(message);
|
||||||
|
self.session_to_frontend_tx.send(ws_msg).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_notification(
|
||||||
|
&mut self,
|
||||||
|
message: v8::UniquePtr<v8::inspector::StringBuffer>,
|
||||||
|
) {
|
||||||
|
let ws_msg = v8_to_ws_msg(message);
|
||||||
|
self.session_to_frontend_tx.send(ws_msg).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush_protocol_notifications(&mut self) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO impl From or Into
|
||||||
|
fn v8_to_ws_msg(
|
||||||
|
message: v8::UniquePtr<v8::inspector::StringBuffer>,
|
||||||
|
) -> ws::Message {
|
||||||
|
let mut x = message.unwrap();
|
||||||
|
let s = x.string().to_string();
|
||||||
|
ws::Message::text(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_box_with<T>(new_fn: impl FnOnce(*mut T) -> T) -> Box<T> {
|
||||||
|
let b = Box::new(MaybeUninit::<T>::uninit());
|
||||||
|
let p = Box::into_raw(b) as *mut T;
|
||||||
|
unsafe { ptr::write(p, new_fn(p)) };
|
||||||
|
unsafe { Box::from_raw(p) }
|
||||||
|
}
|
|
@ -37,6 +37,7 @@ mod global_timer;
|
||||||
pub mod http_cache;
|
pub mod http_cache;
|
||||||
mod http_util;
|
mod http_util;
|
||||||
mod import_map;
|
mod import_map;
|
||||||
|
mod inspector;
|
||||||
pub mod installer;
|
pub mod installer;
|
||||||
mod js;
|
mod js;
|
||||||
mod lockfile;
|
mod lockfile;
|
||||||
|
|
|
@ -256,7 +256,7 @@ fn op_umask(
|
||||||
#[cfg(not(unix))]
|
#[cfg(not(unix))]
|
||||||
{
|
{
|
||||||
let _ = args.mask; // avoid unused warning.
|
let _ = args.mask; // avoid unused warning.
|
||||||
return Err(OpError::not_implemented());
|
Err(OpError::not_implemented())
|
||||||
}
|
}
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
{
|
{
|
||||||
|
@ -360,7 +360,7 @@ fn op_chmod(
|
||||||
{
|
{
|
||||||
// Still check file/dir exists on Windows
|
// Still check file/dir exists on Windows
|
||||||
let _metadata = std::fs::metadata(&path)?;
|
let _metadata = std::fs::metadata(&path)?;
|
||||||
return Err(OpError::not_implemented());
|
Err(OpError::not_implemented())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -400,7 +400,7 @@ fn op_chown(
|
||||||
{
|
{
|
||||||
// Still check file/dir exists on Windows
|
// Still check file/dir exists on Windows
|
||||||
let _metadata = std::fs::metadata(&path)?;
|
let _metadata = std::fs::metadata(&path)?;
|
||||||
return Err(OpError::not_implemented());
|
Err(OpError::not_implemented())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -731,7 +731,7 @@ fn op_symlink(
|
||||||
// Unlike with chmod/chown, here we don't
|
// Unlike with chmod/chown, here we don't
|
||||||
// require `oldpath` to exist on Windows
|
// require `oldpath` to exist on Windows
|
||||||
let _ = oldpath; // avoid unused warning
|
let _ = oldpath; // avoid unused warning
|
||||||
return Err(OpError::not_implemented());
|
Err(OpError::not_implemented())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
3
cli/tests/inspector1.js
Normal file
3
cli/tests/inspector1.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
setInterval(() => {
|
||||||
|
console.log("hello");
|
||||||
|
}, 1000);
|
|
@ -1967,6 +1967,111 @@ fn test_permissions_net_listen_allow_localhost() {
|
||||||
assert!(!err.contains(util::PERMISSION_DENIED_PATTERN));
|
assert!(!err.contains(util::PERMISSION_DENIED_PATTERN));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "linux"))] // TODO(ry) broken on github actions.
|
||||||
|
fn extract_ws_url_from_stderr(
|
||||||
|
stderr: &mut std::process::ChildStderr,
|
||||||
|
) -> url::Url {
|
||||||
|
use std::io::BufRead;
|
||||||
|
let mut stderr = std::io::BufReader::new(stderr);
|
||||||
|
let mut stderr_first_line = String::from("");
|
||||||
|
let _ = stderr.read_line(&mut stderr_first_line).unwrap();
|
||||||
|
assert!(stderr_first_line.starts_with("Debugger listening on "));
|
||||||
|
let v: Vec<_> = stderr_first_line.match_indices("ws:").collect();
|
||||||
|
assert_eq!(v.len(), 1);
|
||||||
|
let ws_url_index = v[0].0;
|
||||||
|
let ws_url = &stderr_first_line[ws_url_index..];
|
||||||
|
url::Url::parse(ws_url).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "linux"))] // TODO(ry) broken on github actions.
|
||||||
|
#[tokio::test]
|
||||||
|
async fn inspector_connect() {
|
||||||
|
let script = deno::test_util::root_path()
|
||||||
|
.join("cli")
|
||||||
|
.join("tests")
|
||||||
|
.join("inspector1.js");
|
||||||
|
let mut child = util::deno_cmd()
|
||||||
|
.arg("run")
|
||||||
|
// Warning: each inspector test should be on its own port to avoid
|
||||||
|
// conflicting with another inspector test.
|
||||||
|
.arg("--inspect=127.0.0.1:9229")
|
||||||
|
.arg(script)
|
||||||
|
.stderr(std::process::Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
let ws_url = extract_ws_url_from_stderr(child.stderr.as_mut().unwrap());
|
||||||
|
println!("ws_url {}", ws_url);
|
||||||
|
// We use tokio_tungstenite as a websocket client because warp (which is
|
||||||
|
// a dependency of Deno) uses it.
|
||||||
|
let (_socket, response) = tokio_tungstenite::connect_async(ws_url)
|
||||||
|
.await
|
||||||
|
.expect("Can't connect");
|
||||||
|
assert_eq!("101 Switching Protocols", response.status().to_string());
|
||||||
|
child.kill().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "linux"))] // TODO(ry) broken on github actions.
|
||||||
|
#[tokio::test]
|
||||||
|
async fn inspector_pause() {
|
||||||
|
let script = deno::test_util::root_path()
|
||||||
|
.join("cli")
|
||||||
|
.join("tests")
|
||||||
|
.join("inspector1.js");
|
||||||
|
let mut child = util::deno_cmd()
|
||||||
|
.arg("run")
|
||||||
|
// Warning: each inspector test should be on its own port to avoid
|
||||||
|
// conflicting with another inspector test.
|
||||||
|
.arg("--inspect=127.0.0.1:9230")
|
||||||
|
.arg(script)
|
||||||
|
.stderr(std::process::Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
let ws_url = extract_ws_url_from_stderr(child.stderr.as_mut().unwrap());
|
||||||
|
println!("ws_url {}", ws_url);
|
||||||
|
// We use tokio_tungstenite as a websocket client because warp (which is
|
||||||
|
// a dependency of Deno) uses it.
|
||||||
|
let (mut socket, _) = tokio_tungstenite::connect_async(ws_url)
|
||||||
|
.await
|
||||||
|
.expect("Can't connect");
|
||||||
|
|
||||||
|
/// Returns the next websocket message as a string ignoring
|
||||||
|
/// Debugger.scriptParsed messages.
|
||||||
|
async fn ws_read_msg(
|
||||||
|
socket: &mut tokio_tungstenite::WebSocketStream<tokio::net::TcpStream>,
|
||||||
|
) -> String {
|
||||||
|
use futures::stream::StreamExt;
|
||||||
|
while let Some(msg) = socket.next().await {
|
||||||
|
let msg = msg.unwrap().to_string();
|
||||||
|
assert!(!msg.contains("error"));
|
||||||
|
if !msg.contains("Debugger.scriptParsed") {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
|
||||||
|
use futures::sink::SinkExt;
|
||||||
|
socket
|
||||||
|
.send(r#"{"id":6,"method":"Debugger.enable"}"#.into())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let msg = ws_read_msg(&mut socket).await;
|
||||||
|
println!("response msg 1 {}", msg);
|
||||||
|
assert!(msg.starts_with(r#"{"id":6,"result":{"debuggerId":"#));
|
||||||
|
|
||||||
|
socket
|
||||||
|
.send(r#"{"id":31,"method":"Debugger.pause"}"#.into())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let msg = ws_read_msg(&mut socket).await;
|
||||||
|
println!("response msg 2 {}", msg);
|
||||||
|
assert_eq!(msg, r#"{"id":31,"result":{}}"#);
|
||||||
|
|
||||||
|
child.kill().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
mod util {
|
mod util {
|
||||||
use deno::colors::strip_ansi_codes;
|
use deno::colors::strip_ansi_codes;
|
||||||
pub use deno::test_util::*;
|
pub use deno::test_util::*;
|
||||||
|
|
|
@ -97,6 +97,7 @@ pub struct Worker {
|
||||||
pub waker: AtomicWaker,
|
pub waker: AtomicWaker,
|
||||||
pub(crate) internal_channels: WorkerChannelsInternal,
|
pub(crate) internal_channels: WorkerChannelsInternal,
|
||||||
external_channels: WorkerHandle,
|
external_channels: WorkerHandle,
|
||||||
|
inspector: Option<Box<crate::inspector::DenoInspector>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Worker {
|
impl Worker {
|
||||||
|
@ -104,9 +105,15 @@ impl Worker {
|
||||||
let loader = Rc::new(state.clone());
|
let loader = Rc::new(state.clone());
|
||||||
let mut isolate = deno_core::EsIsolate::new(loader, startup_data, false);
|
let mut isolate = deno_core::EsIsolate::new(loader, startup_data, false);
|
||||||
|
|
||||||
let global_state_ = state.borrow().global_state.clone();
|
let global_state = state.borrow().global_state.clone();
|
||||||
|
|
||||||
|
let inspector = global_state
|
||||||
|
.inspector_server
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| s.add_inspector(&mut *isolate));
|
||||||
|
|
||||||
isolate.set_js_error_create_fn(move |core_js_error| {
|
isolate.set_js_error_create_fn(move |core_js_error| {
|
||||||
JSError::create(core_js_error, &global_state_.ts_compiler)
|
JSError::create(core_js_error, &global_state.ts_compiler)
|
||||||
});
|
});
|
||||||
|
|
||||||
let (internal_channels, external_channels) = create_channels();
|
let (internal_channels, external_channels) = create_channels();
|
||||||
|
@ -118,6 +125,7 @@ impl Worker {
|
||||||
waker: AtomicWaker::new(),
|
waker: AtomicWaker::new(),
|
||||||
internal_channels,
|
internal_channels,
|
||||||
external_channels,
|
external_channels,
|
||||||
|
inspector,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,11 +183,23 @@ impl Worker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Drop for Worker {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// The Isolate object must outlive the Inspector object, but this is
|
||||||
|
// currently not enforced by the type system.
|
||||||
|
self.inspector.take();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Future for Worker {
|
impl Future for Worker {
|
||||||
type Output = Result<(), ErrBox>;
|
type Output = Result<(), ErrBox>;
|
||||||
|
|
||||||
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
|
||||||
let inner = self.get_mut();
|
let inner = self.get_mut();
|
||||||
|
if let Some(deno_inspector) = inner.inspector.as_mut() {
|
||||||
|
// We always poll the inspector if it exists.
|
||||||
|
let _ = deno_inspector.poll_unpin(cx);
|
||||||
|
}
|
||||||
inner.waker.register(cx.waker());
|
inner.waker.register(cx.waker());
|
||||||
inner.isolate.poll_unpin(cx)
|
inner.isolate.poll_unpin(cx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,11 +159,11 @@ type IsolateErrorHandleFn = dyn FnMut(ErrBox) -> Result<(), ErrBox>;
|
||||||
/// as arguments. An async Op corresponds exactly to a Promise in JavaScript.
|
/// as arguments. An async Op corresponds exactly to a Promise in JavaScript.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub struct Isolate {
|
pub struct Isolate {
|
||||||
pub(crate) v8_isolate: Option<v8::OwnedIsolate>,
|
pub v8_isolate: Option<v8::OwnedIsolate>,
|
||||||
snapshot_creator: Option<v8::SnapshotCreator>,
|
snapshot_creator: Option<v8::SnapshotCreator>,
|
||||||
has_snapshotted: bool,
|
has_snapshotted: bool,
|
||||||
snapshot: Option<SnapshotConfig>,
|
snapshot: Option<SnapshotConfig>,
|
||||||
pub(crate) global_context: v8::Global<v8::Context>,
|
pub global_context: v8::Global<v8::Context>,
|
||||||
pub(crate) shared_ab: v8::Global<v8::SharedArrayBuffer>,
|
pub(crate) shared_ab: v8::Global<v8::SharedArrayBuffer>,
|
||||||
pub(crate) js_recv_cb: v8::Global<v8::Function>,
|
pub(crate) js_recv_cb: v8::Global<v8::Function>,
|
||||||
pub(crate) js_macrotask_cb: v8::Global<v8::Function>,
|
pub(crate) js_macrotask_cb: v8::Global<v8::Function>,
|
||||||
|
|
|
@ -21,7 +21,7 @@ mod plugins;
|
||||||
mod resources;
|
mod resources;
|
||||||
mod shared_queue;
|
mod shared_queue;
|
||||||
|
|
||||||
use rusty_v8 as v8;
|
pub use rusty_v8 as v8;
|
||||||
|
|
||||||
pub use crate::any_error::*;
|
pub use crate::any_error::*;
|
||||||
pub use crate::es_isolate::*;
|
pub use crate::es_isolate::*;
|
||||||
|
|
Loading…
Add table
Reference in a new issue