mirror of
https://github.com/denoland/deno.git
synced 2025-12-23 08:48:24 +00:00
feat(unstable): typescript-go integration for deno check (#30920)
Integrated only with deno check (and test, `run --check`, etc) currently. All spec tests for deno check pass except for 3, which i've disabled --------- Co-authored-by: Bartek Iwańczuk <biwanczuk@gmail.com> Co-authored-by: Divy Srivastava <me@littledivy.com>
This commit is contained in:
parent
6e4f7677ea
commit
b252cc78c2
133 changed files with 4727 additions and 1451 deletions
2
.github/workflows/ci.generate.ts
vendored
2
.github/workflows/ci.generate.ts
vendored
|
|
@ -5,7 +5,7 @@ import { stringify } from "jsr:@std/yaml@^0.221/stringify";
|
|||
// Bump this number when you want to purge the cache.
|
||||
// Note: the tools/release/01_bump_crate_versions.ts script will update this version
|
||||
// automatically via regex, so ensure that this line maintains this format.
|
||||
const cacheVersion = 76;
|
||||
const cacheVersion = 77;
|
||||
|
||||
const ubuntuX86Runner = "ubuntu-24.04";
|
||||
const ubuntuX86XlRunner = "ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04";
|
||||
|
|
|
|||
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
|
|
@ -189,8 +189,8 @@ jobs:
|
|||
~/.cargo/registry/index
|
||||
~/.cargo/registry/cache
|
||||
~/.cargo/git/db
|
||||
key: '76-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
||||
restore-keys: '76-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-'
|
||||
key: '77-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-${{ hashFiles(''Cargo.lock'') }}'
|
||||
restore-keys: '77-cargo-home-${{ matrix.os }}-${{ matrix.arch }}-'
|
||||
if: '!(matrix.skip)'
|
||||
- uses: dsherret/rust-toolchain-file@v1
|
||||
if: '!(matrix.skip)'
|
||||
|
|
@ -392,7 +392,7 @@ jobs:
|
|||
!./target/*/*.zip
|
||||
!./target/*/*.tar.gz
|
||||
key: never_saved
|
||||
restore-keys: '76-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
||||
restore-keys: '77-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-'
|
||||
- name: Apply and update mtime cache
|
||||
if: '!(matrix.skip) && (!startsWith(github.ref, ''refs/tags/''))'
|
||||
uses: ./.github/mtime_cache
|
||||
|
|
@ -773,7 +773,7 @@ jobs:
|
|||
!./target/*/gn_root
|
||||
!./target/*/*.zip
|
||||
!./target/*/*.tar.gz
|
||||
key: '76-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
||||
key: '77-cargo-target-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}'
|
||||
libs:
|
||||
name: build libs
|
||||
needs:
|
||||
|
|
|
|||
30
Cargo.lock
generated
30
Cargo.lock
generated
|
|
@ -1647,6 +1647,7 @@ dependencies = [
|
|||
"deno_telemetry",
|
||||
"deno_terminal 0.2.2",
|
||||
"deno_tower_lsp",
|
||||
"deno_typescript_go_client_rust",
|
||||
"dhat",
|
||||
"dissimilar",
|
||||
"dotenvy",
|
||||
|
|
@ -3073,6 +3074,19 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deno_typescript_go_client_rust"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"indexmap 2.9.0",
|
||||
"log",
|
||||
"rmp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_repr",
|
||||
"thiserror 2.0.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deno_unsync"
|
||||
version = "0.4.4"
|
||||
|
|
@ -5903,9 +5917,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.27"
|
||||
version = "0.4.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
|
@ -7714,6 +7728,17 @@ dependencies = [
|
|||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rmp"
|
||||
version = "0.8.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"num-traits",
|
||||
"paste",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ron"
|
||||
version = "0.8.1"
|
||||
|
|
@ -9369,6 +9394,7 @@ dependencies = [
|
|||
"url",
|
||||
"win32job",
|
||||
"winapi",
|
||||
"zip",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ members = [
|
|||
"libs/npm_installer",
|
||||
"libs/package_json",
|
||||
"libs/resolver",
|
||||
"libs/typescript_go_client",
|
||||
"runtime",
|
||||
"runtime/features",
|
||||
"runtime/permissions",
|
||||
|
|
@ -131,6 +132,7 @@ deno_resolver = { version = "0.50.0", path = "./libs/resolver" }
|
|||
deno_runtime = { version = "0.227.0", path = "./runtime" }
|
||||
deno_snapshots = { version = "0.34.0", path = "./cli/snapshot" }
|
||||
deno_subprocess_windows = { path = "./runtime/subprocess_windows", version = "0.14.0" }
|
||||
deno_typescript_go_client_rust = { version = "0.1.0", path = "./libs/typescript_go_client" }
|
||||
napi_sym = { version = "0.149.0", path = "./ext/napi/sym" }
|
||||
node_resolver = { version = "0.57.0", path = "./libs/node_resolver" }
|
||||
test_util = { package = "test_server", path = "./tests/util/server" }
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ deno_snapshots.workspace = true
|
|||
deno_task_shell.workspace = true
|
||||
deno_telemetry.workspace = true
|
||||
deno_terminal.workspace = true
|
||||
deno_typescript_go_client_rust.workspace = true
|
||||
eszip.workspace = true
|
||||
libsui.workspace = true
|
||||
node_resolver = { workspace = true, features = ["graph", "sync"] }
|
||||
|
|
|
|||
|
|
@ -6628,6 +6628,7 @@ fn unstable_args_parse(
|
|||
matches.get_flag("unstable-sloppy-imports");
|
||||
flags.unstable_config.npm_lazy_caching =
|
||||
matches.get_flag("unstable-npm-lazy-caching");
|
||||
flags.unstable_config.tsgo = matches.get_flag("unstable-tsgo");
|
||||
|
||||
if matches!(cfg, UnstableArgsConfig::ResolutionAndRuntime) {
|
||||
for feature in deno_runtime::UNSTABLE_FEATURES {
|
||||
|
|
|
|||
|
|
@ -1210,6 +1210,10 @@ impl CliOptions {
|
|||
self.flags.type_check_mode
|
||||
}
|
||||
|
||||
pub fn unstable_tsgo(&self) -> bool {
|
||||
self.flags.unstable_config.tsgo || self.workspace().has_unstable("tsgo")
|
||||
}
|
||||
|
||||
pub fn unsafely_ignore_certificate_errors(&self) -> &Option<Vec<String>> {
|
||||
&self.flags.unsafely_ignore_certificate_errors
|
||||
}
|
||||
|
|
|
|||
|
|
@ -524,6 +524,20 @@ impl CliFactory {
|
|||
self.resolver_factory()?.in_npm_package_checker()
|
||||
}
|
||||
|
||||
pub async fn tsgo_path(&self) -> Result<Option<&PathBuf>, AnyError> {
|
||||
if self.cli_options()?.unstable_tsgo() {
|
||||
Ok(Some(
|
||||
crate::tsc::ensure_tsgo(
|
||||
self.deno_dir()?,
|
||||
self.http_client_provider().clone(),
|
||||
)
|
||||
.await?,
|
||||
))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn jsr_version_resolver(
|
||||
&self,
|
||||
) -> Result<&Arc<JsrVersionResolver>, AnyError> {
|
||||
|
|
@ -757,6 +771,7 @@ impl CliFactory {
|
|||
self.module_graph_builder().await?.clone(),
|
||||
self.node_resolver().await?.clone(),
|
||||
self.npm_resolver().await?.clone(),
|
||||
self.resolver_factory()?.pkg_json_resolver().clone(),
|
||||
self.sys(),
|
||||
self.compiler_options_resolver()?.clone(),
|
||||
if cli_options.code_cache_enabled() {
|
||||
|
|
@ -764,6 +779,7 @@ impl CliFactory {
|
|||
} else {
|
||||
None
|
||||
},
|
||||
self.tsgo_path().await?.cloned(),
|
||||
)))
|
||||
}
|
||||
.boxed_local(),
|
||||
|
|
|
|||
|
|
@ -211,6 +211,7 @@ pub struct UnstableConfig {
|
|||
pub raw_imports: bool,
|
||||
pub sloppy_imports: bool,
|
||||
pub npm_lazy_caching: bool,
|
||||
pub tsgo: bool,
|
||||
pub features: Vec<String>, // --unstabe-kv --unstable-cron
|
||||
}
|
||||
|
||||
|
|
@ -234,6 +235,7 @@ impl UnstableConfig {
|
|||
&mut self.npm_lazy_caching,
|
||||
UNSTABLE_ENV_VAR_NAMES.npm_lazy_caching,
|
||||
);
|
||||
maybe_set(&mut self.tsgo, UNSTABLE_ENV_VAR_NAMES.tsgo);
|
||||
maybe_set(&mut self.raw_imports, UNSTABLE_ENV_VAR_NAMES.raw_imports);
|
||||
maybe_set(
|
||||
&mut self.sloppy_imports,
|
||||
|
|
|
|||
|
|
@ -5269,6 +5269,12 @@ fn op_project_version(state: &mut OpState) -> usize {
|
|||
r
|
||||
}
|
||||
|
||||
#[op2]
|
||||
#[serde]
|
||||
fn op_tsc_constants() -> crate::tsc::TscConstants {
|
||||
crate::tsc::TscConstants::new()
|
||||
}
|
||||
|
||||
struct TscRuntime {
|
||||
js_runtime: JsRuntime,
|
||||
server_main_loop_fn_global: v8::Global<v8::Function>,
|
||||
|
|
@ -5393,6 +5399,7 @@ deno_core::extension!(deno_tsc,
|
|||
op_is_cancelled,
|
||||
op_is_node_file,
|
||||
op_load,
|
||||
op_tsc_constants,
|
||||
op_release,
|
||||
op_resolve,
|
||||
op_respond,
|
||||
|
|
|
|||
|
|
@ -788,6 +788,7 @@ impl<'a> DenoCompileBinaryWriter<'a> {
|
|||
npm_lazy_caching: self.cli_options.unstable_npm_lazy_caching(),
|
||||
raw_imports: self.cli_options.unstable_raw_imports(),
|
||||
sloppy_imports: self.cli_options.unstable_sloppy_imports(),
|
||||
tsgo: self.cli_options.unstable_tsgo(),
|
||||
},
|
||||
otel_config: self.cli_options.otel_config(),
|
||||
vfs_case_sensitivity: vfs.case_sensitivity,
|
||||
|
|
|
|||
|
|
@ -303,51 +303,12 @@ const CACHE_URL_PREFIX = "cache:///";
|
|||
|
||||
/** Diagnostics that are intentionally ignored when compiling TypeScript in
|
||||
* Deno, as they provide misleading or incorrect information. */
|
||||
const IGNORED_DIAGNOSTICS = [
|
||||
// TS1452: 'resolution-mode' assertions are only supported when `moduleResolution` is `node16` or `nodenext`.
|
||||
// We specify the resolution mode to be CommonJS for some npm files and this
|
||||
// diagnostic gets generated even though we're using custom module resolution.
|
||||
1452,
|
||||
// Module '...' cannot be imported using this construct. The specifier only resolves to an
|
||||
// ES module, which cannot be imported with 'require'.
|
||||
1471,
|
||||
// TS1479: The current file is a CommonJS module whose imports will produce 'require' calls;
|
||||
// however, the referenced file is an ECMAScript module and cannot be imported with 'require'.
|
||||
1479,
|
||||
// TS1543: Importing a JSON file into an ECMAScript module requires a 'type: \"json\"' import
|
||||
// attribute when 'module' is set to 'NodeNext'.
|
||||
1543,
|
||||
// TS2306: File '.../index.d.ts' is not a module.
|
||||
// We get this for `x-typescript-types` declaration files which don't export
|
||||
// anything. We prefer to treat these as modules with no exports.
|
||||
2306,
|
||||
// TS2688: Cannot find type definition file for '...'.
|
||||
// We ignore because type definition files can end with '.ts'.
|
||||
2688,
|
||||
// TS2792: Cannot find module. Did you mean to set the 'moduleResolution'
|
||||
// option to 'node', or to add aliases to the 'paths' option?
|
||||
2792,
|
||||
// TS2307: Cannot find module '{0}' or its corresponding type declarations.
|
||||
2307,
|
||||
// Relative import errors to add an extension
|
||||
2834,
|
||||
2835,
|
||||
// TS5009: Cannot find the common subdirectory path for the input files.
|
||||
5009,
|
||||
// TS5055: Cannot write file
|
||||
// 'http://localhost:4545/subdir/mt_application_x_javascript.j4.js'
|
||||
// because it would overwrite input file.
|
||||
5055,
|
||||
// TypeScript is overly opinionated that only CommonJS modules kinds can
|
||||
// support JSON imports. Allegedly this was fixed in
|
||||
// Microsoft/TypeScript#26825 but that doesn't seem to be working here,
|
||||
// so we will ignore complaints about this compiler setting.
|
||||
5070,
|
||||
// TS7016: Could not find a declaration file for module '...'. '...'
|
||||
// implicitly has an 'any' type. This is due to `allowJs` being off by
|
||||
// default but importing of a JavaScript module.
|
||||
7016,
|
||||
];
|
||||
const TSC_CONSTANTS = ops.op_tsc_constants();
|
||||
const IGNORED_DIAGNOSTICS = TSC_CONSTANTS.ignoredDiagnosticCodes;
|
||||
const TYPES_NODE_IGNORABLE_NAMES = new Set(
|
||||
TSC_CONSTANTS.typesNodeIgnorableNames,
|
||||
);
|
||||
const NODE_ONLY_GLOBALS = new Set(TSC_CONSTANTS.nodeOnlyGlobals);
|
||||
|
||||
// todo(dsherret): can we remove this and just use ts.OperationCanceledException?
|
||||
/** Error thrown on cancellation. */
|
||||
|
|
@ -851,94 +812,14 @@ export function filterMapDiagnostic(diagnostic) {
|
|||
|
||||
// list of globals that should be kept in Node's globalThis
|
||||
ts.deno.setNodeOnlyGlobalNames(
|
||||
new Set([
|
||||
"__dirname",
|
||||
"__filename",
|
||||
'"buffer"',
|
||||
"Buffer",
|
||||
"BufferConstructor",
|
||||
"BufferEncoding",
|
||||
"clearImmediate",
|
||||
"clearInterval",
|
||||
"clearTimeout",
|
||||
"console",
|
||||
"Console",
|
||||
"crypto",
|
||||
"ErrorConstructor",
|
||||
"gc",
|
||||
"Global",
|
||||
"localStorage",
|
||||
"queueMicrotask",
|
||||
"RequestInit",
|
||||
"ResponseInit",
|
||||
"sessionStorage",
|
||||
"setImmediate",
|
||||
"setInterval",
|
||||
"setTimeout",
|
||||
]),
|
||||
NODE_ONLY_GLOBALS,
|
||||
);
|
||||
// List of globals in @types/node that collide with Deno's types.
|
||||
// When the `@types/node` package attempts to assign to these types
|
||||
// if the type is already in the global symbol table, then assignment
|
||||
// will be a no-op, but if the global type does not exist then the package can
|
||||
// create the global.
|
||||
const setTypesNodeIgnorableNames = new Set([
|
||||
"AbortController",
|
||||
"AbortSignal",
|
||||
"AsyncIteratorObject",
|
||||
"atob",
|
||||
"Blob",
|
||||
"BroadcastChannel",
|
||||
"btoa",
|
||||
"ByteLengthQueuingStrategy",
|
||||
"CloseEvent",
|
||||
"CompressionStream",
|
||||
"CountQueuingStrategy",
|
||||
"CustomEvent",
|
||||
"DecompressionStream",
|
||||
"Disposable",
|
||||
"DOMException",
|
||||
"Event",
|
||||
"EventSource",
|
||||
"EventTarget",
|
||||
"fetch",
|
||||
"File",
|
||||
"Float32Array",
|
||||
"Float64Array",
|
||||
"FormData",
|
||||
"Headers",
|
||||
"ImportMeta",
|
||||
"MessageChannel",
|
||||
"MessageEvent",
|
||||
"MessagePort",
|
||||
"performance",
|
||||
"PerformanceEntry",
|
||||
"PerformanceMark",
|
||||
"PerformanceMeasure",
|
||||
"ReadableByteStreamController",
|
||||
"ReadableStream",
|
||||
"ReadableStreamBYOBReader",
|
||||
"ReadableStreamBYOBRequest",
|
||||
"ReadableStreamDefaultController",
|
||||
"ReadableStreamDefaultReader",
|
||||
"ReadonlyArray",
|
||||
"Request",
|
||||
"Response",
|
||||
"Storage",
|
||||
"TextDecoder",
|
||||
"TextDecoderStream",
|
||||
"TextEncoder",
|
||||
"TextEncoderStream",
|
||||
"TransformStream",
|
||||
"TransformStreamDefaultController",
|
||||
"URL",
|
||||
"URLPattern",
|
||||
"URLSearchParams",
|
||||
"WebSocket",
|
||||
"WritableStream",
|
||||
"WritableStreamDefaultController",
|
||||
"WritableStreamDefaultWriter",
|
||||
]);
|
||||
const setTypesNodeIgnorableNames = TYPES_NODE_IGNORABLE_NAMES;
|
||||
ts.deno.setTypesNodeIgnorableNames(setTypesNodeIgnorableNames);
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -81,10 +81,10 @@ impl From<i64> for DiagnosticCategory {
|
|||
#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DiagnosticMessageChain {
|
||||
message_text: String,
|
||||
category: DiagnosticCategory,
|
||||
code: i64,
|
||||
next: Option<Vec<DiagnosticMessageChain>>,
|
||||
pub message_text: String,
|
||||
pub category: DiagnosticCategory,
|
||||
pub code: i64,
|
||||
pub next: Option<Vec<DiagnosticMessageChain>>,
|
||||
}
|
||||
|
||||
impl DiagnosticMessageChain {
|
||||
|
|
@ -358,6 +358,12 @@ impl fmt::Display for Diagnostic {
|
|||
#[class(generic)]
|
||||
pub struct Diagnostics(Vec<Diagnostic>);
|
||||
|
||||
impl From<Vec<Diagnostic>> for Diagnostics {
|
||||
fn from(diagnostics: Vec<Diagnostic>) -> Self {
|
||||
Diagnostics(diagnostics)
|
||||
}
|
||||
}
|
||||
|
||||
impl Diagnostics {
|
||||
#[cfg(test)]
|
||||
pub fn new(diagnostics: Vec<Diagnostic>) -> Self {
|
||||
|
|
|
|||
671
cli/tsc/go.rs
Normal file
671
cli/tsc/go.rs
Normal file
|
|
@ -0,0 +1,671 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
mod setup;
|
||||
mod tsgo_version;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use deno_ast::MediaType;
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_config::deno_json::CompilerOptions;
|
||||
use deno_core::serde_json;
|
||||
use deno_core::serde_json::json;
|
||||
use deno_graph::ModuleGraph;
|
||||
use deno_typescript_go_client_rust::CallbackHandler;
|
||||
use deno_typescript_go_client_rust::SyncRpcChannel;
|
||||
use deno_typescript_go_client_rust::types::GetImpliedNodeFormatForFilePayload;
|
||||
use deno_typescript_go_client_rust::types::Project;
|
||||
use deno_typescript_go_client_rust::types::ResolveModuleNamePayload;
|
||||
use deno_typescript_go_client_rust::types::ResolveTypeReferenceDirectivePayload;
|
||||
pub use setup::DownloadError;
|
||||
pub use setup::ensure_tsgo;
|
||||
|
||||
use super::Request;
|
||||
use super::Response;
|
||||
use crate::args::TypeCheckMode;
|
||||
|
||||
macro_rules! jsons {
|
||||
($($arg:tt)*) => {
|
||||
serde_json::to_string(&json!($($arg)*))
|
||||
};
|
||||
}
|
||||
|
||||
fn deser<T: serde::de::DeserializeOwned>(
|
||||
payload: impl AsRef<str>,
|
||||
) -> Result<T, serde_json::Error> {
|
||||
serde_json::from_str::<T>(payload.as_ref())
|
||||
}
|
||||
|
||||
// the way tsgo currently works, it really wants an actual tsconfig.json file.
|
||||
// it also doesn't let you just pass in root file names. instead of making more changes in tsgo,
|
||||
// work around both by making a fake tsconfig.json file with the `"files"` field set to the root file names.
|
||||
// it's "synthetic" because it's not actually on disk, we pass a fake path to load it from memory.
|
||||
fn synthetic_config(
|
||||
config: &CompilerOptions,
|
||||
root_names: &[String],
|
||||
type_check_mode: TypeCheckMode,
|
||||
) -> Result<String, serde_json::Error> {
|
||||
let mut config = serde_json::to_value(config)?;
|
||||
let obj = config.as_object_mut().unwrap();
|
||||
obj.insert("allowImportingTsExtensions".to_string(), json!(true));
|
||||
if type_check_mode != TypeCheckMode::All {
|
||||
obj.insert("skipDefaultLibCheck".to_string(), json!(true));
|
||||
}
|
||||
if let Some(jsx) = obj.get("jsx")
|
||||
&& jsx.as_str() == Some("precompile")
|
||||
{
|
||||
obj.insert("jsx".to_string(), json!("react-jsx"));
|
||||
}
|
||||
let config = serde_json::to_string(&json!({
|
||||
"compilerOptions": config,
|
||||
"files": root_names,
|
||||
}))?;
|
||||
log::debug!("synthetic config: {}", config);
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
pub fn exec_request(
|
||||
request: Request,
|
||||
root_names: Vec<String>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||
tsgo_path: &Path,
|
||||
) -> Result<Response, super::ExecError> {
|
||||
exec_request_inner(
|
||||
request,
|
||||
root_names,
|
||||
root_map,
|
||||
remapped_specifiers,
|
||||
tsgo_path,
|
||||
)
|
||||
.map_err(super::ExecError::Go)
|
||||
}
|
||||
|
||||
fn exec_request_inner(
|
||||
request: Request,
|
||||
root_names: Vec<String>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||
tsgo_path: &Path,
|
||||
) -> Result<Response, ExecError> {
|
||||
let handler = Handler::new(
|
||||
"/virtual/tsconfig.json".to_string(),
|
||||
synthetic_config(request.config.as_ref(), &root_names, request.check_mode)?,
|
||||
remapped_specifiers,
|
||||
root_map,
|
||||
request.initial_cwd,
|
||||
request.graph.clone(),
|
||||
request.maybe_npm,
|
||||
);
|
||||
|
||||
let callbacks = handler.supported_callbacks();
|
||||
let bin_path = tsgo_path;
|
||||
let mut channel = SyncRpcChannel::new(bin_path, vec!["--api"], handler)?;
|
||||
|
||||
channel.request_sync(
|
||||
"configure",
|
||||
jsons!({
|
||||
"callbacks": callbacks.iter().collect::<Vec<_>>(),
|
||||
"logFile": "",
|
||||
"forkContextInfo": {
|
||||
"typesNodeIgnorableNames": super::TYPES_NODE_IGNORABLE_NAMES,
|
||||
"nodeOnlyGlobalNames": super::NODE_ONLY_GLOBALS,
|
||||
},
|
||||
})?,
|
||||
)?;
|
||||
|
||||
let project = channel.request_sync(
|
||||
"loadProject",
|
||||
jsons!({
|
||||
"configFileName": "/virtual/tsconfig.json",
|
||||
})?,
|
||||
)?;
|
||||
let project = deser::<Project>(project)?;
|
||||
|
||||
let file_names = if request.check_mode != TypeCheckMode::All {
|
||||
root_names
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
let diagnostics = channel.request_sync(
|
||||
"getDiagnostics",
|
||||
jsons!({
|
||||
"project": &project.id,
|
||||
"fileNames": file_names,
|
||||
})?,
|
||||
)?;
|
||||
let diagnostics = deser::<
|
||||
Vec<deno_typescript_go_client_rust::types::Diagnostic>,
|
||||
>(diagnostics)?;
|
||||
|
||||
Ok(Response {
|
||||
diagnostics: convert_diagnostics(diagnostics),
|
||||
maybe_tsbuildinfo: None,
|
||||
ambient_modules: vec![],
|
||||
stats: super::Stats::default(),
|
||||
})
|
||||
}
|
||||
|
||||
fn diagnostic_category(category: &str) -> super::DiagnosticCategory {
|
||||
match category {
|
||||
"error" => super::DiagnosticCategory::Error,
|
||||
"warning" => super::DiagnosticCategory::Warning,
|
||||
"message" => super::DiagnosticCategory::Message,
|
||||
"suggestion" => super::DiagnosticCategory::Suggestion,
|
||||
_ => unreachable!("unexpected diagnostic category: {category}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_rewrite_message(message: String, code: u64) -> String {
|
||||
if code == 2304 && message.starts_with("Cannot find name 'Deno'") {
|
||||
r#"Cannot find name 'Deno'. Do you need to change your target library? Try changing the 'lib' compiler option to include 'deno.ns' or add a triple-slash directive to the top of your entrypoint (main file): /// <reference lib="deno.ns" />"#.to_string()
|
||||
} else if code == 2581 {
|
||||
r#"Cannot find name '$'. Did you mean to import jQuery? Try adding `import $ from "npm:jquery";`."#.to_string()
|
||||
} else if code == 2580 {
|
||||
let regex = lazy_regex::regex!(r#"Cannot find name '([^']+)'"#);
|
||||
let captures = regex.captures(&message).unwrap();
|
||||
let name = captures.get(1).unwrap().as_str();
|
||||
format!("Cannot find name '{}'.", name)
|
||||
} else if code == 1203 {
|
||||
"Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead. This will start erroring in a future version of Deno 2 in order to align with TypeScript.".to_string()
|
||||
} else if code == 2339 && message.contains("on type 'typeof Deno'") {
|
||||
let regex = lazy_regex::regex!(
|
||||
r#"Property '([^']+)' does not exist on type 'typeof Deno'"#
|
||||
);
|
||||
let captures = regex.captures(&message).unwrap();
|
||||
let name = captures.get(1).unwrap().as_str();
|
||||
format!(
|
||||
"Property '{name}' does not exist on type 'typeof Deno'. 'Deno.{name}' is an unstable API. If not, try changing the 'lib' compiler option to include 'deno.unstable' or add a triple-slash directive to the top of your entrypoint (main file): /// <reference lib=\"deno.unstable\" />",
|
||||
)
|
||||
} else {
|
||||
message
|
||||
}
|
||||
}
|
||||
|
||||
fn maybe_remap_category(
|
||||
code: u64,
|
||||
category: super::DiagnosticCategory,
|
||||
) -> super::DiagnosticCategory {
|
||||
if code == 1203 {
|
||||
super::DiagnosticCategory::Warning
|
||||
} else {
|
||||
category
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_diagnostic(
|
||||
diagnostic: deno_typescript_go_client_rust::types::Diagnostic,
|
||||
_diagnostics: &[deno_typescript_go_client_rust::types::Diagnostic],
|
||||
) -> super::Diagnostic {
|
||||
let (start, end) = if diagnostic.start.line == 0
|
||||
&& diagnostic.start.character == 0
|
||||
&& diagnostic.end.line == 0
|
||||
&& diagnostic.end.character == 0
|
||||
{
|
||||
(None, None)
|
||||
} else {
|
||||
(Some(diagnostic.start), Some(diagnostic.end))
|
||||
};
|
||||
|
||||
super::Diagnostic {
|
||||
category: maybe_remap_category(
|
||||
diagnostic.code as u64,
|
||||
diagnostic_category(diagnostic.category.as_str()),
|
||||
),
|
||||
code: diagnostic.code as u64,
|
||||
start: start.map(|s| super::Position {
|
||||
line: s.line,
|
||||
character: s.character,
|
||||
}),
|
||||
end: end.map(|e| super::Position {
|
||||
line: e.line,
|
||||
character: e.character,
|
||||
}),
|
||||
original_source_start: None,
|
||||
message_chain: None,
|
||||
message_text: Some(maybe_rewrite_message(
|
||||
diagnostic.message,
|
||||
diagnostic.code as u64,
|
||||
)),
|
||||
file_name: Some(diagnostic.file_name),
|
||||
missing_specifier: None,
|
||||
other: Default::default(),
|
||||
related_information: if diagnostic.related_information.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
diagnostic
|
||||
.related_information
|
||||
.into_iter()
|
||||
.map(|d| convert_diagnostic(d, _diagnostics))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
},
|
||||
reports_deprecated: Some(diagnostic.reports_deprecated),
|
||||
reports_unnecessary: Some(diagnostic.reports_unnecessary),
|
||||
source: None,
|
||||
source_line: Some(diagnostic.source_line),
|
||||
}
|
||||
}
|
||||
|
||||
fn should_ignore_diagnostic(diagnostic: &super::Diagnostic) -> bool {
|
||||
super::IGNORED_DIAGNOSTIC_CODES.contains(&diagnostic.code)
|
||||
}
|
||||
|
||||
fn convert_diagnostics(
|
||||
diagnostics: Vec<deno_typescript_go_client_rust::types::Diagnostic>,
|
||||
) -> super::Diagnostics {
|
||||
super::diagnostics::Diagnostics::from(
|
||||
diagnostics
|
||||
.iter()
|
||||
.map(|diagnostic| convert_diagnostic(diagnostic.clone(), &diagnostics))
|
||||
.filter(|diagnostic| !should_ignore_diagnostic(diagnostic))
|
||||
.collect::<Vec<_>>(),
|
||||
)
|
||||
}
|
||||
|
||||
struct Handler {
|
||||
state: RefCell<HandlerState>,
|
||||
}
|
||||
|
||||
impl Handler {
|
||||
fn new(
|
||||
config_path: String,
|
||||
synthetic_config: String,
|
||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
current_dir: PathBuf,
|
||||
graph: Arc<ModuleGraph>,
|
||||
maybe_npm: Option<super::RequestNpmState>,
|
||||
) -> Self {
|
||||
Self {
|
||||
state: RefCell::new(HandlerState {
|
||||
config_path,
|
||||
synthetic_config,
|
||||
remapped_specifiers,
|
||||
root_map,
|
||||
current_dir,
|
||||
graph,
|
||||
maybe_npm,
|
||||
module_kind_map: HashMap::new(),
|
||||
load_result_pending: HashMap::new(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_package_json_scope_if_applicable(
|
||||
state: &mut HandlerState,
|
||||
payload: String,
|
||||
) -> Result<String, deno_typescript_go_client_rust::Error> {
|
||||
log::debug!("get_package_json_scope_if_applicable: {}", payload);
|
||||
if let Some(maybe_npm) = state.maybe_npm.as_ref() {
|
||||
let file_path = deser::<String>(&payload)?;
|
||||
let file_path = if let Ok(specifier) = ModuleSpecifier::parse(&file_path) {
|
||||
deno_path_util::url_to_file_path(&specifier).ok()
|
||||
} else {
|
||||
Some(PathBuf::from(file_path))
|
||||
};
|
||||
let Some(file_path) = file_path else {
|
||||
return Ok(jsons!(None::<String>)?);
|
||||
};
|
||||
if let Some(package_json) = maybe_npm
|
||||
.package_json_resolver
|
||||
.get_closest_package_jsons(&file_path)
|
||||
.next()
|
||||
.and_then(|r| r.ok())
|
||||
{
|
||||
let package_directory = package_json.path.parent();
|
||||
let contents = serde_json::to_string(&package_json).ok();
|
||||
if let Some(contents) = contents {
|
||||
return Ok(jsons!({
|
||||
"packageDirectory": package_directory,
|
||||
"directoryExists": true,
|
||||
"contents": contents,
|
||||
})?);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(jsons!(None::<String>)?)
|
||||
}
|
||||
|
||||
struct HandlerState {
|
||||
config_path: String,
|
||||
synthetic_config: String,
|
||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
current_dir: PathBuf,
|
||||
graph: Arc<ModuleGraph>,
|
||||
maybe_npm: Option<super::RequestNpmState>,
|
||||
|
||||
module_kind_map:
|
||||
HashMap<String, deno_typescript_go_client_rust::types::ResolutionMode>,
|
||||
|
||||
load_result_pending: HashMap<String, LoadResult>,
|
||||
}
|
||||
|
||||
impl deno_typescript_go_client_rust::CallbackHandler for Handler {
|
||||
fn supported_callbacks(&self) -> &'static [&'static str] {
|
||||
&[
|
||||
"readFile",
|
||||
"resolveModuleName",
|
||||
"getPackageJsonScopeIfApplicable",
|
||||
"getPackageScopeForPath",
|
||||
"resolveTypeReferenceDirective",
|
||||
"getImpliedNodeFormatForFile",
|
||||
"isNodeSourceFile",
|
||||
]
|
||||
}
|
||||
|
||||
fn handle_callback(
|
||||
&self,
|
||||
name: &str,
|
||||
payload: String,
|
||||
) -> Result<String, deno_typescript_go_client_rust::Error> {
|
||||
let mut state = self.state.borrow_mut();
|
||||
match name {
|
||||
"readFile" => {
|
||||
log::debug!("readFile: {}", payload);
|
||||
let payload = deser::<String>(payload)?;
|
||||
if payload == state.config_path {
|
||||
Ok(jsons!(&state.synthetic_config)?)
|
||||
} else {
|
||||
if let Some(load_result) = state.load_result_pending.remove(&payload)
|
||||
{
|
||||
return Ok(jsons!(load_result.contents)?);
|
||||
}
|
||||
let result = load_inner(&mut state, &payload).map_err(adhoc)?;
|
||||
|
||||
if let Some(result) = result {
|
||||
let contents = result.contents;
|
||||
Ok(jsons!(&contents)?)
|
||||
} else {
|
||||
let path = Path::new(&payload);
|
||||
|
||||
if let Ok(contents) = std::fs::read_to_string(path) {
|
||||
Ok(jsons!(&contents)?)
|
||||
} else {
|
||||
Ok(jsons!(None::<String>)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"loadSourceFile" => {
|
||||
let payload = deser::<String>(payload)?;
|
||||
log::debug!("loadSourceFile: {}", payload);
|
||||
if let Some(load_result) = state.load_result_pending.remove(&payload) {
|
||||
Ok(jsons!(&load_result)?)
|
||||
} else {
|
||||
let result = load_inner(&mut state, &payload).map_err(adhoc)?;
|
||||
Ok(jsons!(&result)?)
|
||||
}
|
||||
}
|
||||
"resolveModuleName" => {
|
||||
let payload = deser::<ResolveModuleNamePayload>(payload)?;
|
||||
let (out_name, extension) = resolve_name(&mut state, payload)?;
|
||||
|
||||
Ok(jsons!({
|
||||
"resolvedFileName": out_name,
|
||||
"extension": extension,
|
||||
})?)
|
||||
}
|
||||
"getPackageJsonScopeIfApplicable" => {
|
||||
log::debug!("getPackageJsonScopeIfApplicable: {}", payload);
|
||||
get_package_json_scope_if_applicable(&mut state, payload).inspect(
|
||||
|res| log::debug!("getPackageJsonScopeIfApplicable -> {}", res),
|
||||
)
|
||||
}
|
||||
"getPackageScopeForPath" => {
|
||||
log::debug!("getPackageScopeForPath: {}", payload);
|
||||
get_package_json_scope_if_applicable(&mut state, payload)
|
||||
.inspect(|res| log::debug!("getPackageScopeForPath -> {}", res))
|
||||
}
|
||||
"resolveTypeReferenceDirective" => {
|
||||
log::debug!("resolveTypeReferenceDirective: {}", payload);
|
||||
let payload = deser::<ResolveTypeReferenceDirectivePayload>(payload)?;
|
||||
let payload = ResolveModuleNamePayload {
|
||||
module_name: payload.type_reference_directive_name,
|
||||
containing_file: payload.containing_file,
|
||||
resolution_mode: payload.resolution_mode,
|
||||
};
|
||||
let (out_name, extension) = resolve_name(&mut state, payload)?;
|
||||
log::debug!(
|
||||
"resolveTypeReferenceDirective: {:?}",
|
||||
(&out_name, &extension)
|
||||
);
|
||||
Ok(jsons!({
|
||||
"resolvedFileName": out_name,
|
||||
"extension": extension,
|
||||
"primary": true,
|
||||
})?)
|
||||
}
|
||||
"getImpliedNodeFormatForFile" => {
|
||||
let payload = deser::<GetImpliedNodeFormatForFilePayload>(payload)?;
|
||||
log::debug!("getImpliedNodeFormatForFile: {:?}", payload);
|
||||
// check if we already determined the module kind from a previous load
|
||||
if let Some(module_kind) = state.module_kind_map.get(&payload.file_name)
|
||||
{
|
||||
log::debug!("getImpliedNodeFormatForFile -> {:?}", module_kind);
|
||||
Ok(jsons!(&module_kind)?)
|
||||
} else {
|
||||
// if not, load the file and determine the module kind
|
||||
let load_result =
|
||||
load_inner(&mut state, &payload.file_name).map_err(adhoc)?;
|
||||
if let Some(load_result) = load_result {
|
||||
// store the load result in the pending map to avoid loading the file again
|
||||
state
|
||||
.load_result_pending
|
||||
.insert(payload.file_name.clone(), load_result);
|
||||
let module_kind = state
|
||||
.module_kind_map
|
||||
.get(&payload.file_name)
|
||||
.copied()
|
||||
.unwrap_or(
|
||||
deno_typescript_go_client_rust::types::ResolutionMode::ESM,
|
||||
);
|
||||
Ok(jsons!(&module_kind)?)
|
||||
} else {
|
||||
Ok(jsons!(
|
||||
&deno_typescript_go_client_rust::types::ResolutionMode::ESM
|
||||
)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
"isNodeSourceFile" => {
|
||||
let path = deser::<String>(payload)?;
|
||||
let state = &*state;
|
||||
let result = ModuleSpecifier::parse(&path)
|
||||
.ok()
|
||||
.or_else(|| {
|
||||
deno_path_util::resolve_url_or_path(&path, &state.current_dir).ok()
|
||||
})
|
||||
.and_then(|specifier| {
|
||||
state
|
||||
.maybe_npm
|
||||
.as_ref()
|
||||
.map(|n| n.node_resolver.in_npm_package(&specifier))
|
||||
})
|
||||
.unwrap_or(false);
|
||||
Ok(jsons!(result)?)
|
||||
}
|
||||
_ => unreachable!("unknown callback: {name}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn adhoc(err: impl std::error::Error) -> deno_typescript_go_client_rust::Error {
|
||||
deno_typescript_go_client_rust::Error::AdHoc(err.to_string())
|
||||
}
|
||||
|
||||
fn resolve_name(
|
||||
handler: &mut HandlerState,
|
||||
payload: ResolveModuleNamePayload,
|
||||
) -> Result<(String, Option<&'static str>), deno_typescript_go_client_rust::Error>
|
||||
{
|
||||
let graph = &handler.graph;
|
||||
let maybe_npm = handler.maybe_npm.as_ref();
|
||||
let referrer = if let Some(remapped_specifier) =
|
||||
handler.maybe_remapped_specifier(&payload.containing_file)
|
||||
{
|
||||
remapped_specifier.clone()
|
||||
} else {
|
||||
deno_path_util::resolve_url_or_path(
|
||||
&payload.containing_file,
|
||||
&handler.current_dir,
|
||||
)
|
||||
.map_err(adhoc)?
|
||||
};
|
||||
let referrer_module = graph.get(&referrer);
|
||||
let specifier = payload.module_name;
|
||||
let result = super::resolve_specifier_for_tsc(
|
||||
specifier,
|
||||
&referrer,
|
||||
graph,
|
||||
match payload.resolution_mode {
|
||||
deno_typescript_go_client_rust::types::ResolutionMode::None => {
|
||||
super::ResolutionMode::Import
|
||||
}
|
||||
deno_typescript_go_client_rust::types::ResolutionMode::CommonJS => {
|
||||
super::ResolutionMode::Require
|
||||
}
|
||||
deno_typescript_go_client_rust::types::ResolutionMode::ESM => {
|
||||
super::ResolutionMode::Import
|
||||
}
|
||||
},
|
||||
maybe_npm,
|
||||
referrer_module,
|
||||
&mut handler.remapped_specifiers,
|
||||
)
|
||||
.map_err(adhoc)?;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
impl HandlerState {
|
||||
pub fn maybe_remapped_specifier(
|
||||
&self,
|
||||
specifier: &str,
|
||||
) -> Option<&ModuleSpecifier> {
|
||||
self
|
||||
.remapped_specifiers
|
||||
.get(specifier)
|
||||
.or_else(|| self.root_map.get(specifier))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||
pub enum ExecError {
|
||||
#[class(generic)]
|
||||
#[error(transparent)]
|
||||
SerdeJson(#[from] serde_json::Error),
|
||||
#[class(generic)]
|
||||
#[error(transparent)]
|
||||
TsgoClient(#[from] deno_typescript_go_client_rust::Error),
|
||||
|
||||
#[class(generic)]
|
||||
#[error(transparent)]
|
||||
PackageJsonLoad(#[from] deno_package_json::PackageJsonLoadError),
|
||||
|
||||
#[class(generic)]
|
||||
#[error(transparent)]
|
||||
PackageJsonLoadError(#[from] node_resolver::errors::PackageJsonLoadError),
|
||||
|
||||
#[class(generic)]
|
||||
#[error(transparent)]
|
||||
DownloadError(#[from] DownloadError),
|
||||
|
||||
#[class(generic)]
|
||||
#[error(transparent)]
|
||||
LoadError(#[from] super::LoadError),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct LoadResult {
|
||||
contents: String,
|
||||
script_kind: i32,
|
||||
}
|
||||
|
||||
impl super::LoadContent for String {
|
||||
fn from_static(source: &'static str) -> Self {
|
||||
source.to_string()
|
||||
}
|
||||
fn from_string(source: String) -> Self {
|
||||
source
|
||||
}
|
||||
fn from_arc_str(source: Arc<str>) -> Self {
|
||||
source.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl super::Mapper for HandlerState {
|
||||
fn maybe_remapped_specifier(
|
||||
&self,
|
||||
specifier: &str,
|
||||
) -> Option<&ModuleSpecifier> {
|
||||
self.maybe_remapped_specifier(specifier)
|
||||
}
|
||||
}
|
||||
|
||||
fn load_inner(
|
||||
state: &mut HandlerState,
|
||||
load_specifier: &str,
|
||||
) -> Result<Option<LoadResult>, ExecError> {
|
||||
log::debug!("load_inner: {}", load_specifier);
|
||||
let result = super::load_for_tsc(
|
||||
load_specifier,
|
||||
state.maybe_npm.as_ref(),
|
||||
&state.current_dir,
|
||||
&state.graph,
|
||||
None,
|
||||
0,
|
||||
state,
|
||||
)?;
|
||||
let Some(result) = result else {
|
||||
return Ok(None);
|
||||
};
|
||||
let is_cjs = result.is_cjs;
|
||||
let media_type = result.media_type;
|
||||
|
||||
let module_kind = get_resolution_mode(is_cjs, media_type);
|
||||
let script_kind = super::as_ts_script_kind(media_type);
|
||||
log::debug!("load_inner {load_specifier} -> {:?}", module_kind);
|
||||
state
|
||||
.module_kind_map
|
||||
.insert(load_specifier.to_string(), module_kind);
|
||||
Ok(Some(LoadResult {
|
||||
contents: result.data,
|
||||
script_kind,
|
||||
}))
|
||||
}
|
||||
|
||||
fn get_resolution_mode(
|
||||
is_cjs: bool,
|
||||
media_type: MediaType,
|
||||
) -> deno_typescript_go_client_rust::types::ResolutionMode {
|
||||
if is_cjs {
|
||||
deno_typescript_go_client_rust::types::ResolutionMode::CommonJS
|
||||
} else {
|
||||
match media_type {
|
||||
MediaType::Cjs | MediaType::Dcts | MediaType::Cts => {
|
||||
deno_typescript_go_client_rust::types::ResolutionMode::CommonJS
|
||||
}
|
||||
|
||||
MediaType::Css
|
||||
| MediaType::Json
|
||||
| MediaType::Html
|
||||
| MediaType::Sql
|
||||
| MediaType::Wasm
|
||||
| MediaType::SourceMap
|
||||
| MediaType::Unknown => {
|
||||
deno_typescript_go_client_rust::types::ResolutionMode::None
|
||||
}
|
||||
_ => deno_typescript_go_client_rust::types::ResolutionMode::ESM,
|
||||
}
|
||||
}
|
||||
}
|
||||
169
cli/tsc/go/setup.rs
Normal file
169
cli/tsc/go/setup.rs
Normal file
|
|
@ -0,0 +1,169 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use deno_core::error::AnyError;
|
||||
use deno_error::JsErrorBox;
|
||||
use sha2::Digest;
|
||||
|
||||
use super::tsgo_version;
|
||||
use crate::cache::DenoDir;
|
||||
use crate::http_util::HttpClientProvider;
|
||||
|
||||
fn get_download_url(platform: &str) -> String {
|
||||
format!(
|
||||
"{}/typescript-go-{}-{}.zip",
|
||||
tsgo_version::DOWNLOAD_BASE_URL,
|
||||
tsgo_version::VERSION,
|
||||
platform
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||
#[class(generic)]
|
||||
pub enum DownloadError {
|
||||
#[error("unsupported platform for typescript-go: {0}")]
|
||||
UnsupportedPlatform(String),
|
||||
#[error("invalid download url: {0}")]
|
||||
InvalidDownloadUrl(String, #[source] deno_core::url::ParseError),
|
||||
#[error("failed to unpack typescript-go: {0}")]
|
||||
UnpackFailed(#[source] AnyError),
|
||||
#[error("failed to rename typescript-go: {0}")]
|
||||
RenameFailed(#[source] std::io::Error),
|
||||
#[error("failed to write zip file to {0}: {1}")]
|
||||
WriteZipFailed(String, #[source] std::io::Error),
|
||||
#[error("failed to download typescript-go: {0}")]
|
||||
DownloadFailed(#[source] crate::http_util::DownloadError),
|
||||
#[error("{0}")]
|
||||
HttpClient(#[source] JsErrorBox),
|
||||
#[error("failed to create temp directory: {0}")]
|
||||
CreateTempDirFailed(#[source] std::io::Error),
|
||||
#[error("hash mismatch: expected {0}, got {1}")]
|
||||
HashMismatch(String, String),
|
||||
#[error("binary not found: {0}")]
|
||||
BinaryNotFound(String),
|
||||
}
|
||||
|
||||
fn verify_hash(platform: &str, data: &[u8]) -> Result<(), DownloadError> {
|
||||
let expected_hash = match platform {
|
||||
"windows-x64" => tsgo_version::HASHES.windows_x64,
|
||||
"macos-x64" => tsgo_version::HASHES.macos_x64,
|
||||
"macos-arm64" => tsgo_version::HASHES.macos_arm64,
|
||||
"linux-x64" => tsgo_version::HASHES.linux_x64,
|
||||
"linux-arm64" => tsgo_version::HASHES.linux_arm64,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let (algorithm, expected_hash) = expected_hash.split_once(':').unwrap();
|
||||
if algorithm != "sha256" {
|
||||
panic!("Hash algorithm is not sha256");
|
||||
}
|
||||
|
||||
let mut hash = sha2::Sha256::new();
|
||||
hash.update(data);
|
||||
let hash = hash.finalize();
|
||||
|
||||
let hash = faster_hex::hex_string(&hash);
|
||||
if hash != expected_hash {
|
||||
return Err(DownloadError::HashMismatch(expected_hash.to_string(), hash));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn ensure_tsgo(
|
||||
deno_dir: &DenoDir,
|
||||
http_client_provider: Arc<HttpClientProvider>,
|
||||
) -> Result<&'static PathBuf, DownloadError> {
|
||||
static TSGO_PATH: OnceLock<PathBuf> = OnceLock::new();
|
||||
|
||||
if let Some(bin_path) = TSGO_PATH.get() {
|
||||
return Ok(bin_path);
|
||||
}
|
||||
|
||||
if let Ok(tsgo_path) = std::env::var("DENO_TSGO_PATH") {
|
||||
let tsgo_path = Path::new(&tsgo_path);
|
||||
if tsgo_path.exists() {
|
||||
return Ok(TSGO_PATH.get_or_init(|| PathBuf::from(tsgo_path)));
|
||||
} else {
|
||||
return Err(DownloadError::BinaryNotFound(
|
||||
tsgo_path.to_string_lossy().into_owned(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let platform = match (std::env::consts::OS, std::env::consts::ARCH) {
|
||||
("windows", "x86_64") => "windows-x64",
|
||||
("macos", "x86_64") => "macos-x64",
|
||||
("macos", "aarch64") => "macos-arm64",
|
||||
("linux", "x86_64") => "linux-x64",
|
||||
("linux", "aarch64") => "linux-arm64",
|
||||
_ => {
|
||||
return Err(DownloadError::UnsupportedPlatform(format!(
|
||||
"{} {}",
|
||||
std::env::consts::OS,
|
||||
std::env::consts::ARCH
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
let folder_path = deno_dir
|
||||
.dl_folder_path()
|
||||
.join(format!("tsgo-{}", tsgo_version::VERSION));
|
||||
|
||||
let bin_path = folder_path.join(format!(
|
||||
"tsgo-{}{}",
|
||||
platform,
|
||||
if cfg!(windows) { ".exe" } else { "" }
|
||||
));
|
||||
|
||||
if bin_path.exists() {
|
||||
return Ok(TSGO_PATH.get_or_init(|| bin_path));
|
||||
}
|
||||
|
||||
std::fs::create_dir_all(&folder_path)
|
||||
.map_err(DownloadError::CreateTempDirFailed)?;
|
||||
|
||||
let client = http_client_provider
|
||||
.get_or_create()
|
||||
.map_err(DownloadError::HttpClient)?;
|
||||
let download_url = get_download_url(platform);
|
||||
log::debug!("Downloading tsgo from {}", download_url);
|
||||
let temp = tempfile::tempdir().map_err(DownloadError::CreateTempDirFailed)?;
|
||||
let path = temp.path().join("tsgo.zip");
|
||||
log::debug!("Downloading tsgo to {}", path.display());
|
||||
let data = client
|
||||
.download(
|
||||
deno_core::url::Url::parse(&download_url)
|
||||
.map_err(|e| DownloadError::InvalidDownloadUrl(download_url, e))?,
|
||||
)
|
||||
.await
|
||||
.map_err(DownloadError::DownloadFailed)?;
|
||||
|
||||
verify_hash(platform, &data)?;
|
||||
|
||||
std::fs::write(&path, &data).map_err(|e| {
|
||||
DownloadError::WriteZipFailed(path.display().to_string(), e)
|
||||
})?;
|
||||
|
||||
log::debug!(
|
||||
"Unpacking tsgo from {} to {}",
|
||||
path.display(),
|
||||
temp.path().display()
|
||||
);
|
||||
let unpacked_path =
|
||||
crate::util::archive::unpack_into_dir(crate::util::archive::UnpackArgs {
|
||||
exe_name: "tsgo",
|
||||
archive_name: "tsgo.zip",
|
||||
archive_data: &data,
|
||||
is_windows: cfg!(windows),
|
||||
dest_path: temp.path(),
|
||||
})
|
||||
.map_err(DownloadError::UnpackFailed)?;
|
||||
std::fs::rename(unpacked_path, &bin_path)
|
||||
.map_err(DownloadError::RenameFailed)?;
|
||||
|
||||
Ok(TSGO_PATH.get_or_init(|| bin_path))
|
||||
}
|
||||
55
cli/tsc/go/tsgo_version.rs
Normal file
55
cli/tsc/go/tsgo_version.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
// This file is auto-generated by tools/update_tsgo.ts
|
||||
// DO NOT EDIT THIS FILE MANUALLY
|
||||
|
||||
pub struct Hashes {
|
||||
pub windows_x64: &'static str,
|
||||
pub macos_x64: &'static str,
|
||||
pub macos_arm64: &'static str,
|
||||
pub linux_x64: &'static str,
|
||||
pub linux_arm64: &'static str,
|
||||
}
|
||||
|
||||
impl Hashes {
|
||||
pub const fn all(&self) -> [&'static str; 5] {
|
||||
[
|
||||
self.windows_x64,
|
||||
self.macos_x64,
|
||||
self.macos_arm64,
|
||||
self.linux_x64,
|
||||
self.linux_arm64,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
pub const VERSION: &str = "0.1.6";
|
||||
pub const DOWNLOAD_BASE_URL: &str =
|
||||
"https://github.com/denoland/typescript-go/releases/download/v0.1.6";
|
||||
pub const HASHES: Hashes = Hashes {
|
||||
windows_x64: "sha256:04f85a9a64807437471cd45ed569b1ee9910dbe9751c1a5085028ae5eb09db56",
|
||||
macos_x64: "sha256:84619ab4a6ac3dc1c78a62c209ea853cf077871fe086657bc861e268b9c0412c",
|
||||
macos_arm64: "sha256:cef3d3f60abe9f2947f2e30f8075d860f9bf176a5545c651eabfcaa9e791e0f9",
|
||||
linux_x64: "sha256:ea0ae7f3782a8372a03ec2c1f1bbb415e0c10a43ce917b0564084f896e0df127",
|
||||
linux_arm64: "sha256:67b4f4d9982ff5c5c14105b37c48b582e3dc806c8a504f1a1b5416e29de68198",
|
||||
};
|
||||
|
||||
const _: () = {
|
||||
let sha256 = "sha256".as_bytes();
|
||||
|
||||
let mut i = 0;
|
||||
let hashes = HASHES.all();
|
||||
|
||||
while i < hashes.len() {
|
||||
let hash = hashes[i].as_bytes();
|
||||
let mut j = 0;
|
||||
|
||||
while j < 6 {
|
||||
if hash[j] != sha256[j] {
|
||||
panic!("Hash algorithm is not sha256");
|
||||
}
|
||||
j += 1;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
};
|
||||
985
cli/tsc/js.rs
Normal file
985
cli/tsc/js.rs
Normal file
|
|
@ -0,0 +1,985 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use deno_core::FastString;
|
||||
use deno_core::JsRuntime;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_core::OpState;
|
||||
use deno_core::RuntimeOptions;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::located_script_name;
|
||||
use deno_core::op2;
|
||||
use deno_core::serde::Deserialize;
|
||||
use deno_core::serde::Serialize;
|
||||
use deno_core::serde_json::json;
|
||||
use deno_core::url::Url;
|
||||
use deno_graph::GraphKind;
|
||||
use deno_graph::ModuleGraph;
|
||||
use deno_lib::util::hash::FastInsecureHasher;
|
||||
use deno_lib::worker::create_isolate_create_params;
|
||||
use deno_path_util::resolve_url_or_path;
|
||||
use node_resolver::ResolutionMode;
|
||||
|
||||
use super::LAZILY_LOADED_STATIC_ASSETS;
|
||||
use super::ResolveArgs;
|
||||
use super::ResolveError;
|
||||
use crate::args::TypeCheckMode;
|
||||
use crate::tsc::Diagnostics;
|
||||
use crate::tsc::ExecError;
|
||||
use crate::tsc::LoadError;
|
||||
use crate::tsc::Request;
|
||||
use crate::tsc::RequestNpmState;
|
||||
use crate::tsc::Response;
|
||||
use crate::tsc::Stats;
|
||||
use crate::tsc::get_hash;
|
||||
|
||||
#[op2]
|
||||
#[string]
|
||||
fn op_remap_specifier(
|
||||
state: &mut OpState,
|
||||
#[string] specifier: &str,
|
||||
) -> Option<String> {
|
||||
let state = state.borrow::<State>();
|
||||
state
|
||||
.maybe_remapped_specifier(specifier)
|
||||
.map(|url| url.to_string())
|
||||
}
|
||||
|
||||
#[op2]
|
||||
#[serde]
|
||||
fn op_libs() -> Vec<String> {
|
||||
let mut out = Vec::with_capacity(LAZILY_LOADED_STATIC_ASSETS.len());
|
||||
for (key, value) in LAZILY_LOADED_STATIC_ASSETS.iter() {
|
||||
if !value.is_lib {
|
||||
continue;
|
||||
}
|
||||
let lib = key
|
||||
.replace("lib.", "")
|
||||
.replace(".d.ts", "")
|
||||
.replace("deno_", "deno.");
|
||||
out.push(lib);
|
||||
}
|
||||
out
|
||||
}
|
||||
|
||||
#[op2]
|
||||
#[serde]
|
||||
fn op_resolve(
|
||||
state: &mut OpState,
|
||||
#[string] base: String,
|
||||
#[serde] specifiers: Vec<(bool, String)>,
|
||||
) -> Result<Vec<(String, Option<&'static str>)>, ResolveError> {
|
||||
op_resolve_inner(state, ResolveArgs { base, specifiers })
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct TscConstants {
|
||||
types_node_ignorable_names: Vec<&'static str>,
|
||||
node_only_globals: Vec<&'static str>,
|
||||
ignored_diagnostic_codes: Vec<u64>,
|
||||
}
|
||||
|
||||
impl TscConstants {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
types_node_ignorable_names: super::TYPES_NODE_IGNORABLE_NAMES.to_vec(),
|
||||
node_only_globals: super::NODE_ONLY_GLOBALS.to_vec(),
|
||||
ignored_diagnostic_codes: super::IGNORED_DIAGNOSTIC_CODES
|
||||
.iter()
|
||||
.copied()
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[op2]
|
||||
#[serde]
|
||||
fn op_tsc_constants() -> TscConstants {
|
||||
TscConstants::new()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn op_resolve_inner(
|
||||
state: &mut OpState,
|
||||
args: ResolveArgs,
|
||||
) -> Result<Vec<(String, Option<&'static str>)>, ResolveError> {
|
||||
let state = state.borrow_mut::<State>();
|
||||
let mut resolved: Vec<(String, Option<&'static str>)> =
|
||||
Vec::with_capacity(args.specifiers.len());
|
||||
let referrer = if let Some(remapped_specifier) =
|
||||
state.maybe_remapped_specifier(&args.base)
|
||||
{
|
||||
remapped_specifier.clone()
|
||||
} else {
|
||||
resolve_url_or_path(&args.base, &state.current_dir)?
|
||||
};
|
||||
let referrer_module = state.graph.get(&referrer);
|
||||
for (is_cjs, specifier) in args.specifiers {
|
||||
let result = super::resolve_specifier_for_tsc(
|
||||
specifier,
|
||||
&referrer,
|
||||
&state.graph,
|
||||
if is_cjs {
|
||||
ResolutionMode::Require
|
||||
} else {
|
||||
ResolutionMode::Import
|
||||
},
|
||||
state.maybe_npm.as_ref(),
|
||||
referrer_module,
|
||||
&mut state.remapped_specifiers,
|
||||
)?;
|
||||
resolved.push(result);
|
||||
}
|
||||
|
||||
Ok(resolved)
|
||||
}
|
||||
|
||||
deno_core::extension!(deno_cli_tsc,
|
||||
ops = [
|
||||
op_create_hash,
|
||||
op_emit,
|
||||
op_is_node_file,
|
||||
op_load,
|
||||
op_remap_specifier,
|
||||
op_resolve,
|
||||
op_tsc_constants,
|
||||
op_respond,
|
||||
op_libs,
|
||||
],
|
||||
options = {
|
||||
request: Request,
|
||||
root_map: HashMap<String, Url>,
|
||||
remapped_specifiers: HashMap<String, Url>,
|
||||
},
|
||||
state = |state, options| {
|
||||
state.put(State::new(
|
||||
options.request.graph,
|
||||
options.request.hash_data,
|
||||
options.request.maybe_npm,
|
||||
options.request.maybe_tsbuildinfo,
|
||||
options.root_map,
|
||||
options.remapped_specifiers,
|
||||
std::env::current_dir()
|
||||
.context("Unable to get CWD")
|
||||
.unwrap(),
|
||||
));
|
||||
},
|
||||
customizer = |ext: &mut deno_core::Extension| {
|
||||
use deno_core::ExtensionFileSource;
|
||||
ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/99_main_compiler.js", crate::tsc::MAIN_COMPILER_SOURCE.as_str().into()));
|
||||
ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/97_ts_host.js", crate::tsc::TS_HOST_SOURCE.as_str().into()));
|
||||
ext.esm_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/98_lsp.js", crate::tsc::LSP_SOURCE.as_str().into()));
|
||||
ext.js_files.to_mut().push(ExtensionFileSource::new_computed("ext:deno_cli_tsc/00_typescript.js", crate::tsc::TYPESCRIPT_SOURCE.as_str().into()));
|
||||
ext.esm_entry_point = Some("ext:deno_cli_tsc/99_main_compiler.js");
|
||||
}
|
||||
);
|
||||
// TODO(bartlomieju): this mechanism is questionable.
|
||||
// Can't we use something more efficient here?
|
||||
#[op2]
|
||||
fn op_respond(state: &mut OpState, #[serde] args: RespondArgs) {
|
||||
op_respond_inner(state, args)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn op_respond_inner(state: &mut OpState, args: RespondArgs) {
|
||||
let state = state.borrow_mut::<State>();
|
||||
state.maybe_response = Some(args);
|
||||
}
|
||||
|
||||
#[op2]
|
||||
#[string]
|
||||
fn op_create_hash(s: &mut OpState, #[string] text: &str) -> String {
|
||||
op_create_hash_inner(s, text)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn op_create_hash_inner(s: &mut OpState, text: &str) -> String {
|
||||
let state = s.borrow_mut::<State>();
|
||||
get_hash(text, state.hash_data)
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct EmitArgs {
|
||||
/// The text data/contents of the file.
|
||||
data: String,
|
||||
/// The _internal_ filename for the file. This will be used to determine how
|
||||
/// the file is cached and stored.
|
||||
file_name: String,
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
fn op_emit(
|
||||
state: &mut OpState,
|
||||
#[string] data: String,
|
||||
#[string] file_name: String,
|
||||
) -> bool {
|
||||
op_emit_inner(state, EmitArgs { data, file_name })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn op_emit_inner(state: &mut OpState, args: EmitArgs) -> bool {
|
||||
let state = state.borrow_mut::<State>();
|
||||
match args.file_name.as_ref() {
|
||||
"internal:///.tsbuildinfo" => state.maybe_tsbuildinfo = Some(args.data),
|
||||
_ => {
|
||||
if cfg!(debug_assertions) {
|
||||
panic!("Unhandled emit write: {}", args.file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
#[op2(fast)]
|
||||
fn op_is_node_file(state: &mut OpState, #[string] path: &str) -> bool {
|
||||
let state = state.borrow::<State>();
|
||||
ModuleSpecifier::parse(path)
|
||||
.ok()
|
||||
.and_then(|specifier| {
|
||||
state
|
||||
.maybe_npm
|
||||
.as_ref()
|
||||
.map(|n| n.node_resolver.in_npm_package(&specifier))
|
||||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Eq, PartialEq)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct RespondArgs {
|
||||
pub diagnostics: Diagnostics,
|
||||
pub ambient_modules: Vec<String>,
|
||||
pub stats: Stats,
|
||||
}
|
||||
|
||||
impl super::LoadContent for FastString {
|
||||
fn from_static(source: &'static str) -> Self {
|
||||
FastString::from_static(source)
|
||||
}
|
||||
fn from_string(source: String) -> Self {
|
||||
FastString::from(source)
|
||||
}
|
||||
fn from_arc_str(source: Arc<str>) -> Self {
|
||||
FastString::from(source)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct LoadResponse {
|
||||
data: FastString,
|
||||
version: Option<String>,
|
||||
script_kind: i32,
|
||||
is_cjs: bool,
|
||||
}
|
||||
|
||||
#[op2]
|
||||
#[serde]
|
||||
fn op_load(
|
||||
state: &mut OpState,
|
||||
#[string] load_specifier: &str,
|
||||
) -> Result<Option<LoadResponse>, LoadError> {
|
||||
op_load_inner(state, load_specifier)
|
||||
}
|
||||
|
||||
impl super::Mapper for State {
|
||||
fn maybe_remapped_specifier(
|
||||
&self,
|
||||
specifier: &str,
|
||||
) -> Option<&ModuleSpecifier> {
|
||||
self.maybe_remapped_specifier(specifier)
|
||||
}
|
||||
}
|
||||
|
||||
fn op_load_inner(
|
||||
state: &mut OpState,
|
||||
load_specifier: &str,
|
||||
) -> Result<Option<LoadResponse>, LoadError> {
|
||||
let state = state.borrow::<State>();
|
||||
Ok(
|
||||
super::load_for_tsc::<FastString, _>(
|
||||
load_specifier,
|
||||
state.maybe_npm.as_ref(),
|
||||
&state.current_dir,
|
||||
&state.graph,
|
||||
state.maybe_tsbuildinfo.as_deref(),
|
||||
state.hash_data,
|
||||
state,
|
||||
)?
|
||||
.map(|res| LoadResponse {
|
||||
data: res.data,
|
||||
version: res.version,
|
||||
is_cjs: res.is_cjs,
|
||||
script_kind: super::as_ts_script_kind(res.media_type),
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn exec_request(
|
||||
request: Request,
|
||||
root_names: Vec<String>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||
code_cache: Option<Arc<dyn deno_runtime::code_cache::CodeCache>>,
|
||||
) -> Result<Response, ExecError> {
|
||||
let request_value = json!({
|
||||
"config": request.config,
|
||||
"debug": request.debug,
|
||||
"rootNames": root_names,
|
||||
"localOnly": request.check_mode == TypeCheckMode::Local,
|
||||
});
|
||||
let exec_source = format!("globalThis.exec({request_value})");
|
||||
|
||||
let mut extensions =
|
||||
deno_runtime::snapshot_info::get_extensions_in_snapshot();
|
||||
extensions.push(deno_cli_tsc::init(request, root_map, remapped_specifiers));
|
||||
let extension_code_cache = code_cache.map(|cache| {
|
||||
Rc::new(TscExtCodeCache::new(cache)) as Rc<dyn deno_core::ExtCodeCache>
|
||||
});
|
||||
let mut runtime = JsRuntime::new(RuntimeOptions {
|
||||
extensions,
|
||||
create_params: create_isolate_create_params(&crate::sys::CliSys::default()),
|
||||
startup_snapshot: deno_snapshots::CLI_SNAPSHOT,
|
||||
extension_code_cache,
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
runtime
|
||||
.execute_script(located_script_name!(), exec_source)
|
||||
.map_err(ExecError::Js)?;
|
||||
|
||||
let op_state = runtime.op_state();
|
||||
let mut op_state = op_state.borrow_mut();
|
||||
let state = op_state.take::<State>();
|
||||
|
||||
if let Some(response) = state.maybe_response {
|
||||
let diagnostics = response.diagnostics;
|
||||
let ambient_modules = response.ambient_modules;
|
||||
let maybe_tsbuildinfo = state.maybe_tsbuildinfo;
|
||||
let stats = response.stats;
|
||||
|
||||
Ok(Response {
|
||||
diagnostics,
|
||||
ambient_modules,
|
||||
maybe_tsbuildinfo,
|
||||
stats,
|
||||
})
|
||||
} else {
|
||||
Err(ExecError::ResponseNotSet)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TscExtCodeCache {
|
||||
cache: Arc<dyn deno_runtime::code_cache::CodeCache>,
|
||||
}
|
||||
|
||||
impl TscExtCodeCache {
|
||||
pub fn new(cache: Arc<dyn deno_runtime::code_cache::CodeCache>) -> Self {
|
||||
Self { cache }
|
||||
}
|
||||
}
|
||||
|
||||
impl deno_core::ExtCodeCache for TscExtCodeCache {
|
||||
fn get_code_cache_info(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
code: &deno_core::ModuleSourceCode,
|
||||
esm: bool,
|
||||
) -> deno_core::SourceCodeCacheInfo {
|
||||
use deno_runtime::code_cache::CodeCacheType;
|
||||
let code_hash = FastInsecureHasher::new_deno_versioned()
|
||||
.write_hashable(code)
|
||||
.finish();
|
||||
let data = self
|
||||
.cache
|
||||
.get_sync(
|
||||
specifier,
|
||||
if esm {
|
||||
CodeCacheType::EsModule
|
||||
} else {
|
||||
CodeCacheType::Script
|
||||
},
|
||||
code_hash,
|
||||
)
|
||||
.map(Cow::from)
|
||||
.inspect(|_| {
|
||||
log::debug!(
|
||||
"V8 code cache hit for Extension module: {specifier}, [{code_hash:?}]"
|
||||
);
|
||||
});
|
||||
deno_core::SourceCodeCacheInfo {
|
||||
hash: code_hash,
|
||||
data,
|
||||
}
|
||||
}
|
||||
|
||||
fn code_cache_ready(
|
||||
&self,
|
||||
specifier: ModuleSpecifier,
|
||||
source_hash: u64,
|
||||
code_cache: &[u8],
|
||||
esm: bool,
|
||||
) {
|
||||
use deno_runtime::code_cache::CodeCacheType;
|
||||
|
||||
log::debug!(
|
||||
"Updating V8 code cache for Extension module: {specifier}, [{source_hash:?}]"
|
||||
);
|
||||
self.cache.set_sync(
|
||||
specifier,
|
||||
if esm {
|
||||
CodeCacheType::EsModule
|
||||
} else {
|
||||
CodeCacheType::Script
|
||||
},
|
||||
source_hash,
|
||||
code_cache,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(bartlomieju): we have similar struct in `tsc.rs` - maybe at least change
|
||||
// the name of the struct to avoid confusion?
|
||||
#[derive(Debug)]
|
||||
struct State {
|
||||
hash_data: u64,
|
||||
graph: Arc<ModuleGraph>,
|
||||
maybe_tsbuildinfo: Option<String>,
|
||||
maybe_response: Option<RespondArgs>,
|
||||
maybe_npm: Option<RequestNpmState>,
|
||||
// todo(dsherret): it looks like the remapped_specifiers and
|
||||
// root_map could be combined... what is the point of the separation?
|
||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
current_dir: PathBuf,
|
||||
}
|
||||
|
||||
impl Default for State {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
hash_data: Default::default(),
|
||||
graph: Arc::new(ModuleGraph::new(GraphKind::All)),
|
||||
maybe_tsbuildinfo: Default::default(),
|
||||
maybe_response: Default::default(),
|
||||
maybe_npm: Default::default(),
|
||||
remapped_specifiers: Default::default(),
|
||||
root_map: Default::default(),
|
||||
current_dir: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl State {
|
||||
pub fn new(
|
||||
graph: Arc<ModuleGraph>,
|
||||
hash_data: u64,
|
||||
maybe_npm: Option<RequestNpmState>,
|
||||
maybe_tsbuildinfo: Option<String>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||
current_dir: PathBuf,
|
||||
) -> Self {
|
||||
State {
|
||||
hash_data,
|
||||
graph,
|
||||
maybe_npm,
|
||||
maybe_tsbuildinfo,
|
||||
maybe_response: None,
|
||||
remapped_specifiers,
|
||||
root_map,
|
||||
current_dir,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybe_remapped_specifier(
|
||||
&self,
|
||||
specifier: &str,
|
||||
) -> Option<&ModuleSpecifier> {
|
||||
self
|
||||
.remapped_specifiers
|
||||
.get(specifier)
|
||||
.or_else(|| self.root_map.get(specifier))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use deno_ast::MediaType;
|
||||
use deno_core::OpState;
|
||||
use deno_core::futures::future;
|
||||
use deno_core::parking_lot::Mutex;
|
||||
use deno_core::serde_json;
|
||||
use deno_error::JsErrorBox;
|
||||
use deno_graph::GraphKind;
|
||||
use deno_graph::ModuleGraph;
|
||||
use deno_runtime::code_cache::CodeCacheType;
|
||||
use test_util::PathRef;
|
||||
|
||||
use super::super::Diagnostic;
|
||||
use super::super::DiagnosticCategory;
|
||||
use super::*;
|
||||
use crate::args::CompilerOptions;
|
||||
use crate::tsc::MISSING_DEPENDENCY_SPECIFIER;
|
||||
use crate::tsc::get_lazily_loaded_asset;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct MockLoader {
|
||||
pub fixtures: PathRef,
|
||||
}
|
||||
|
||||
impl deno_graph::source::Loader for MockLoader {
|
||||
fn load(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
_options: deno_graph::source::LoadOptions,
|
||||
) -> deno_graph::source::LoadFuture {
|
||||
let specifier_text = specifier
|
||||
.to_string()
|
||||
.replace(":///", "_")
|
||||
.replace("://", "_")
|
||||
.replace('/', "-");
|
||||
let source_path = self.fixtures.join(specifier_text);
|
||||
let response = source_path
|
||||
.read_to_bytes_if_exists()
|
||||
.map(|c| {
|
||||
Some(deno_graph::source::LoadResponse::Module {
|
||||
specifier: specifier.clone(),
|
||||
mtime: None,
|
||||
maybe_headers: None,
|
||||
content: c.into(),
|
||||
})
|
||||
})
|
||||
.map_err(|e| {
|
||||
deno_graph::source::LoadError::Other(Arc::new(JsErrorBox::generic(
|
||||
e.to_string(),
|
||||
)))
|
||||
});
|
||||
Box::pin(future::ready(response))
|
||||
}
|
||||
}
|
||||
|
||||
async fn setup(
|
||||
maybe_specifier: Option<ModuleSpecifier>,
|
||||
maybe_hash_data: Option<u64>,
|
||||
maybe_tsbuildinfo: Option<String>,
|
||||
) -> OpState {
|
||||
let specifier = maybe_specifier
|
||||
.unwrap_or_else(|| ModuleSpecifier::parse("file:///main.ts").unwrap());
|
||||
let hash_data = maybe_hash_data.unwrap_or(0);
|
||||
let fixtures = test_util::testdata_path().join("tsc2");
|
||||
let loader = MockLoader { fixtures };
|
||||
let mut graph = ModuleGraph::new(GraphKind::TypesOnly);
|
||||
graph
|
||||
.build(vec![specifier], Vec::new(), &loader, Default::default())
|
||||
.await;
|
||||
let state = State::new(
|
||||
Arc::new(graph),
|
||||
hash_data,
|
||||
None,
|
||||
maybe_tsbuildinfo,
|
||||
HashMap::new(),
|
||||
HashMap::new(),
|
||||
std::env::current_dir()
|
||||
.context("Unable to get CWD")
|
||||
.unwrap(),
|
||||
);
|
||||
let mut op_state = OpState::new(None);
|
||||
op_state.put(state);
|
||||
op_state
|
||||
}
|
||||
|
||||
async fn test_exec(
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Result<Response, ExecError> {
|
||||
test_exec_with_cache(specifier, None).await
|
||||
}
|
||||
async fn test_exec_with_cache(
|
||||
specifier: &ModuleSpecifier,
|
||||
code_cache: Option<Arc<dyn deno_runtime::code_cache::CodeCache>>,
|
||||
) -> Result<Response, ExecError> {
|
||||
let hash_data = 123; // something random
|
||||
let fixtures = test_util::testdata_path().join("tsc2");
|
||||
let loader = MockLoader { fixtures };
|
||||
let mut graph = ModuleGraph::new(GraphKind::TypesOnly);
|
||||
graph
|
||||
.build(
|
||||
vec![specifier.clone()],
|
||||
Vec::new(),
|
||||
&loader,
|
||||
Default::default(),
|
||||
)
|
||||
.await;
|
||||
let config = Arc::new(CompilerOptions::new(json!({
|
||||
"allowJs": true,
|
||||
"checkJs": false,
|
||||
"esModuleInterop": true,
|
||||
"emitDecoratorMetadata": false,
|
||||
"incremental": true,
|
||||
"jsx": "react",
|
||||
"jsxFactory": "React.createElement",
|
||||
"jsxFragmentFactory": "React.Fragment",
|
||||
"lib": ["deno.window"],
|
||||
"noEmit": true,
|
||||
"outDir": "internal:///",
|
||||
"strict": true,
|
||||
"target": "esnext",
|
||||
"tsBuildInfoFile": "internal:///.tsbuildinfo",
|
||||
})));
|
||||
let request = Request {
|
||||
config,
|
||||
debug: false,
|
||||
graph: Arc::new(graph),
|
||||
hash_data,
|
||||
maybe_npm: None,
|
||||
maybe_tsbuildinfo: None,
|
||||
root_names: vec![(specifier.clone(), MediaType::TypeScript)],
|
||||
check_mode: TypeCheckMode::All,
|
||||
initial_cwd: std::env::current_dir().unwrap(),
|
||||
};
|
||||
crate::tsc::exec(request, code_cache, None)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_hash() {
|
||||
let mut state = setup(None, Some(123), None).await;
|
||||
let actual = op_create_hash_inner(&mut state, "some sort of content");
|
||||
assert_eq!(actual, "11905938177474799758");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_hash_url() {
|
||||
let specifier = deno_core::resolve_url(
|
||||
"data:application/javascript,console.log(\"Hello%20Deno\");",
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
crate::tsc::hash_url(&specifier, MediaType::JavaScript),
|
||||
"data:///d300ea0796bd72b08df10348e0b70514c021f2e45bfe59cec24e12e97cd79c58.js"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_emit_tsbuildinfo() {
|
||||
let mut state = setup(None, None, None).await;
|
||||
let actual = op_emit_inner(
|
||||
&mut state,
|
||||
EmitArgs {
|
||||
data: "some file content".to_string(),
|
||||
file_name: "internal:///.tsbuildinfo".to_string(),
|
||||
},
|
||||
);
|
||||
assert!(actual);
|
||||
let state = state.borrow::<State>();
|
||||
assert_eq!(
|
||||
state.maybe_tsbuildinfo,
|
||||
Some("some file content".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_load() {
|
||||
let mut state = setup(
|
||||
Some(ModuleSpecifier::parse("https://deno.land/x/mod.ts").unwrap()),
|
||||
None,
|
||||
Some("some content".to_string()),
|
||||
)
|
||||
.await;
|
||||
let actual =
|
||||
op_load_inner(&mut state, "https://deno.land/x/mod.ts").unwrap();
|
||||
assert_eq!(
|
||||
serde_json::to_value(actual).unwrap(),
|
||||
json!({
|
||||
"data": "console.log(\"hello deno\");\n",
|
||||
"version": "7821807483407828376",
|
||||
"scriptKind": 3,
|
||||
"isCjs": false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_load_asset() {
|
||||
let mut state = setup(
|
||||
Some(ModuleSpecifier::parse("https://deno.land/x/mod.ts").unwrap()),
|
||||
None,
|
||||
Some("some content".to_string()),
|
||||
)
|
||||
.await;
|
||||
let actual = op_load_inner(&mut state, "asset:///lib.dom.d.ts")
|
||||
.expect("should have invoked op")
|
||||
.expect("load should have succeeded");
|
||||
let expected = get_lazily_loaded_asset("lib.dom.d.ts").unwrap();
|
||||
assert_eq!(actual.data.to_string(), expected.to_string());
|
||||
assert!(actual.version.is_some());
|
||||
assert_eq!(actual.script_kind, 3);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_load_tsbuildinfo() {
|
||||
let mut state = setup(
|
||||
Some(ModuleSpecifier::parse("https://deno.land/x/mod.ts").unwrap()),
|
||||
None,
|
||||
Some("some content".to_string()),
|
||||
)
|
||||
.await;
|
||||
let actual = op_load_inner(&mut state, "internal:///.tsbuildinfo")
|
||||
.expect("should have invoked op")
|
||||
.expect("load should have succeeded");
|
||||
assert_eq!(
|
||||
serde_json::to_value(actual).unwrap(),
|
||||
json!({
|
||||
"data": "some content",
|
||||
"version": null,
|
||||
"scriptKind": 0,
|
||||
"isCjs": false,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_load_missing_specifier() {
|
||||
let mut state = setup(None, None, None).await;
|
||||
let actual = op_load_inner(&mut state, "https://deno.land/x/mod.ts")
|
||||
.expect("should have invoked op");
|
||||
assert_eq!(serde_json::to_value(actual).unwrap(), json!(null));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_resolve() {
|
||||
let mut state = setup(
|
||||
Some(ModuleSpecifier::parse("https://deno.land/x/a.ts").unwrap()),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let actual = op_resolve_inner(
|
||||
&mut state,
|
||||
ResolveArgs {
|
||||
base: "https://deno.land/x/a.ts".to_string(),
|
||||
specifiers: vec![(false, "./b.ts".to_string())],
|
||||
},
|
||||
)
|
||||
.expect("should have invoked op");
|
||||
assert_eq!(
|
||||
actual,
|
||||
vec![("https://deno.land/x/b.ts".into(), Some(".ts"))]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_resolve_empty() {
|
||||
let mut state = setup(
|
||||
Some(ModuleSpecifier::parse("https://deno.land/x/a.ts").unwrap()),
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let actual = op_resolve_inner(
|
||||
&mut state,
|
||||
ResolveArgs {
|
||||
base: "https://deno.land/x/a.ts".to_string(),
|
||||
specifiers: vec![(false, "./bad.ts".to_string())],
|
||||
},
|
||||
)
|
||||
.expect("should have not errored");
|
||||
assert_eq!(
|
||||
actual,
|
||||
vec![(MISSING_DEPENDENCY_SPECIFIER.into(), Some(".d.ts"))]
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_respond() {
|
||||
let mut state = setup(None, None, None).await;
|
||||
let args = serde_json::from_value(json!({
|
||||
"diagnostics": [
|
||||
{
|
||||
"messageText": "Unknown compiler option 'invalid'.",
|
||||
"category": 1,
|
||||
"code": 5023
|
||||
}
|
||||
],
|
||||
"stats": [["a", 12]],
|
||||
"ambientModules": []
|
||||
}))
|
||||
.unwrap();
|
||||
op_respond_inner(&mut state, args);
|
||||
let state = state.borrow::<State>();
|
||||
assert_eq!(
|
||||
state.maybe_response,
|
||||
Some(RespondArgs {
|
||||
diagnostics: Diagnostics::new(vec![Diagnostic {
|
||||
category: DiagnosticCategory::Error,
|
||||
code: 5023,
|
||||
start: None,
|
||||
end: None,
|
||||
original_source_start: None,
|
||||
message_text: Some(
|
||||
"Unknown compiler option \'invalid\'.".to_string()
|
||||
),
|
||||
message_chain: None,
|
||||
source: None,
|
||||
source_line: None,
|
||||
file_name: None,
|
||||
related_information: None,
|
||||
reports_deprecated: None,
|
||||
reports_unnecessary: None,
|
||||
other: Default::default(),
|
||||
missing_specifier: None,
|
||||
}]),
|
||||
ambient_modules: vec![],
|
||||
stats: Stats(vec![("a".to_string(), 12)])
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_exec_basic() {
|
||||
let specifier = ModuleSpecifier::parse("https://deno.land/x/a.ts").unwrap();
|
||||
let actual = test_exec(&specifier)
|
||||
.await
|
||||
.expect("exec should not have errored");
|
||||
assert!(!actual.diagnostics.has_diagnostic());
|
||||
assert!(actual.maybe_tsbuildinfo.is_some());
|
||||
assert_eq!(actual.stats.0.len(), 12);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_exec_reexport_dts() {
|
||||
let specifier = ModuleSpecifier::parse("file:///reexports.ts").unwrap();
|
||||
let actual = test_exec(&specifier)
|
||||
.await
|
||||
.expect("exec should not have errored");
|
||||
assert!(!actual.diagnostics.has_diagnostic());
|
||||
assert!(actual.maybe_tsbuildinfo.is_some());
|
||||
assert_eq!(actual.stats.0.len(), 12);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn fix_lib_ref() {
|
||||
let specifier = ModuleSpecifier::parse("file:///libref.ts").unwrap();
|
||||
let actual = test_exec(&specifier)
|
||||
.await
|
||||
.expect("exec should not have errored");
|
||||
assert!(!actual.diagnostics.has_diagnostic());
|
||||
}
|
||||
|
||||
pub type SpecifierWithType = (ModuleSpecifier, CodeCacheType);
|
||||
|
||||
#[derive(Default)]
|
||||
struct TestExtCodeCache {
|
||||
cache: Mutex<HashMap<(SpecifierWithType, u64), Vec<u8>>>,
|
||||
|
||||
hits: Mutex<HashMap<SpecifierWithType, usize>>,
|
||||
misses: Mutex<HashMap<SpecifierWithType, usize>>,
|
||||
}
|
||||
|
||||
impl deno_runtime::code_cache::CodeCache for TestExtCodeCache {
|
||||
fn get_sync(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
code_cache_type: CodeCacheType,
|
||||
source_hash: u64,
|
||||
) -> Option<Vec<u8>> {
|
||||
let result = self
|
||||
.cache
|
||||
.lock()
|
||||
.get(&((specifier.clone(), code_cache_type), source_hash))
|
||||
.cloned();
|
||||
if result.is_some() {
|
||||
*self
|
||||
.hits
|
||||
.lock()
|
||||
.entry((specifier.clone(), code_cache_type))
|
||||
.or_default() += 1;
|
||||
} else {
|
||||
*self
|
||||
.misses
|
||||
.lock()
|
||||
.entry((specifier.clone(), code_cache_type))
|
||||
.or_default() += 1;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
fn set_sync(
|
||||
&self,
|
||||
specifier: ModuleSpecifier,
|
||||
code_cache_type: CodeCacheType,
|
||||
source_hash: u64,
|
||||
data: &[u8],
|
||||
) {
|
||||
self
|
||||
.cache
|
||||
.lock()
|
||||
.insert(((specifier, code_cache_type), source_hash), data.to_vec());
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_exec_code_cache() {
|
||||
let code_cache = Arc::new(TestExtCodeCache::default());
|
||||
let specifier = ModuleSpecifier::parse("https://deno.land/x/a.ts").unwrap();
|
||||
let actual = test_exec_with_cache(&specifier, Some(code_cache.clone()))
|
||||
.await
|
||||
.expect("exec should not have errored");
|
||||
assert!(!actual.diagnostics.has_diagnostic());
|
||||
|
||||
let expect = [
|
||||
(
|
||||
"ext:deno_cli_tsc/99_main_compiler.js",
|
||||
CodeCacheType::EsModule,
|
||||
),
|
||||
("ext:deno_cli_tsc/98_lsp.js", CodeCacheType::EsModule),
|
||||
("ext:deno_cli_tsc/97_ts_host.js", CodeCacheType::EsModule),
|
||||
("ext:deno_cli_tsc/00_typescript.js", CodeCacheType::Script),
|
||||
];
|
||||
|
||||
{
|
||||
let mut files = HashMap::new();
|
||||
|
||||
for (((specifier, ty), _), _) in code_cache.cache.lock().iter() {
|
||||
let specifier = specifier.to_string();
|
||||
if files.contains_key(&specifier) {
|
||||
panic!("should have only 1 entry per specifier");
|
||||
}
|
||||
files.insert(specifier, *ty);
|
||||
}
|
||||
|
||||
// 99_main_compiler, 98_lsp, 97_ts_host, 00_typescript
|
||||
assert_eq!(files.len(), 4);
|
||||
assert_eq!(code_cache.hits.lock().len(), 0);
|
||||
assert_eq!(code_cache.misses.lock().len(), 4);
|
||||
|
||||
for (specifier, ty) in &expect {
|
||||
assert_eq!(files.get(*specifier), Some(ty));
|
||||
}
|
||||
|
||||
code_cache.hits.lock().clear();
|
||||
code_cache.misses.lock().clear();
|
||||
}
|
||||
|
||||
{
|
||||
let _ = test_exec_with_cache(&specifier, Some(code_cache.clone()))
|
||||
.await
|
||||
.expect("exec should not have errored");
|
||||
|
||||
// 99_main_compiler, 98_lsp, 97_ts_host, 00_typescript
|
||||
assert_eq!(code_cache.hits.lock().len(), 4);
|
||||
assert_eq!(code_cache.misses.lock().len(), 0);
|
||||
|
||||
for (specifier, ty) in expect {
|
||||
let url = ModuleSpecifier::parse(specifier).unwrap();
|
||||
assert_eq!(code_cache.hits.lock().get(&(url, ty)), Some(&1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1548
cli/tsc/mod.rs
1548
cli/tsc/mod.rs
File diff suppressed because it is too large
Load diff
|
|
@ -3,6 +3,7 @@
|
|||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::VecDeque;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
|
@ -37,6 +38,7 @@ use crate::graph_util::BuildFastCheckGraphOptions;
|
|||
use crate::graph_util::ModuleGraphBuilder;
|
||||
use crate::graph_util::module_error_for_tsc_diagnostic;
|
||||
use crate::node::CliNodeResolver;
|
||||
use crate::node::CliPackageJsonResolver;
|
||||
use crate::npm::CliNpmResolver;
|
||||
use crate::sys::CliSys;
|
||||
use crate::tsc;
|
||||
|
|
@ -103,9 +105,11 @@ pub struct TypeChecker {
|
|||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
npm_resolver: CliNpmResolver,
|
||||
package_json_resolver: Arc<CliPackageJsonResolver>,
|
||||
sys: CliSys,
|
||||
compiler_options_resolver: Arc<CompilerOptionsResolver>,
|
||||
code_cache: Option<Arc<crate::cache::CodeCache>>,
|
||||
tsgo_path: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl TypeChecker {
|
||||
|
|
@ -117,9 +121,11 @@ impl TypeChecker {
|
|||
module_graph_builder: Arc<ModuleGraphBuilder>,
|
||||
node_resolver: Arc<CliNodeResolver>,
|
||||
npm_resolver: CliNpmResolver,
|
||||
package_json_resolver: Arc<CliPackageJsonResolver>,
|
||||
sys: CliSys,
|
||||
compiler_options_resolver: Arc<CompilerOptionsResolver>,
|
||||
code_cache: Option<Arc<crate::cache::CodeCache>>,
|
||||
tsgo_path: Option<PathBuf>,
|
||||
) -> Self {
|
||||
Self {
|
||||
caches,
|
||||
|
|
@ -128,9 +134,11 @@ impl TypeChecker {
|
|||
module_graph_builder,
|
||||
node_resolver,
|
||||
npm_resolver,
|
||||
package_json_resolver,
|
||||
sys,
|
||||
compiler_options_resolver,
|
||||
code_cache,
|
||||
tsgo_path,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -233,6 +241,7 @@ impl TypeChecker {
|
|||
cjs_tracker: &self.cjs_tracker,
|
||||
node_resolver: &self.node_resolver,
|
||||
npm_resolver: &self.npm_resolver,
|
||||
package_json_resolver: &self.package_json_resolver,
|
||||
compiler_options_resolver: &self.compiler_options_resolver,
|
||||
log_level: self.cli_options.log_level(),
|
||||
npm_check_state_hash: check_state_hash(&self.npm_resolver),
|
||||
|
|
@ -244,6 +253,8 @@ impl TypeChecker {
|
|||
options,
|
||||
seen_diagnotics: Default::default(),
|
||||
code_cache: self.code_cache.clone(),
|
||||
tsgo_path: self.tsgo_path.clone(),
|
||||
initial_cwd: self.cli_options.initial_cwd().to_path_buf(),
|
||||
}),
|
||||
))
|
||||
}
|
||||
|
|
@ -362,6 +373,7 @@ struct DiagnosticsByFolderRealIterator<'a> {
|
|||
cjs_tracker: &'a Arc<TypeCheckingCjsTracker>,
|
||||
node_resolver: &'a Arc<CliNodeResolver>,
|
||||
npm_resolver: &'a CliNpmResolver,
|
||||
package_json_resolver: &'a Arc<CliPackageJsonResolver>,
|
||||
compiler_options_resolver: &'a CompilerOptionsResolver,
|
||||
type_check_cache: TypeCheckCache,
|
||||
groups: Vec<CheckGroup<'a>>,
|
||||
|
|
@ -371,6 +383,8 @@ struct DiagnosticsByFolderRealIterator<'a> {
|
|||
seen_diagnotics: HashSet<String>,
|
||||
options: CheckOptions,
|
||||
code_cache: Option<Arc<crate::cache::CodeCache>>,
|
||||
tsgo_path: Option<PathBuf>,
|
||||
initial_cwd: PathBuf,
|
||||
}
|
||||
|
||||
impl Iterator for DiagnosticsByFolderRealIterator<'_> {
|
||||
|
|
@ -522,12 +536,15 @@ impl DiagnosticsByFolderRealIterator<'_> {
|
|||
cjs_tracker: self.cjs_tracker.clone(),
|
||||
node_resolver: self.node_resolver.clone(),
|
||||
npm_resolver: self.npm_resolver.clone(),
|
||||
package_json_resolver: self.package_json_resolver.clone(),
|
||||
}),
|
||||
maybe_tsbuildinfo,
|
||||
root_names,
|
||||
check_mode: self.options.type_check_mode,
|
||||
initial_cwd: self.initial_cwd.clone(),
|
||||
},
|
||||
code_cache,
|
||||
self.tsgo_path.as_deref(),
|
||||
)?;
|
||||
|
||||
let ambient_modules = response.ambient_modules;
|
||||
|
|
|
|||
39
docs/tsgo.md
Normal file
39
docs/tsgo.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# Typescript-Go Integration
|
||||
|
||||
Currently only integrated with deno check, though in the future it will also be
|
||||
integrated with our LSP implementation.
|
||||
|
||||
In the CLI, we have a small abstraction over the tsc backend in
|
||||
[cli/tsc/mod.rs](../cli/tsc/mod.rs). Along with some shared types and
|
||||
functionality, the main piece is the `exec` function, which takes a "request" to
|
||||
be served by the typescript compiler and returns the result. This now has two
|
||||
different "backend" which can serve the request – the current tsc, which runs in
|
||||
an isolate and communicates via ops, and typescript-go which runs in a
|
||||
subprocess and uses IPC.
|
||||
|
||||
From a high level, the way the tsgo backend works is that we download a
|
||||
typescript-go binary from
|
||||
[github releases](https://github.com/denoland/typescript-go/releases) into the
|
||||
deno cache dir. To actually interface with tsgo, we spawn it in a subprocess and
|
||||
write messages over stdin/stdout (similar to the Language Server Protocol). The
|
||||
format is a mixture of binary data (for the header and other protocol level
|
||||
details) followed by json encoded values for RPC calls. The rust implementation
|
||||
of the IPC protocol is in the
|
||||
[deno_typescript_go_client_rust crate](../libs/typescript_go_client/src/lib.rs).
|
||||
|
||||
We currently maintain a
|
||||
[fork of typescript-go](https://github.com/denoland/typescript-go) with the
|
||||
following changes:
|
||||
|
||||
- Special handling of the global symbol tables to account for the fact that we
|
||||
have two slightly different sets of globals: one for node contexts (in npm
|
||||
packages), and one for deno contexts. At this point, the main difference is
|
||||
the type returned by `setTimeout`. With node globals `setTimeout` returns an
|
||||
object, and with deno globals it returns a number (just like the web
|
||||
standard).
|
||||
- Symbol table logic to prevent @types/node from creating type errors by
|
||||
introducing incompatible definitions for globals
|
||||
- Additional hooks to allow us to provide our own resolution, determine whether
|
||||
a file is esm/cjs, etc.
|
||||
- Additional APIs exposed from the IPC server
|
||||
- Support for deno's custom libs (`deno.window`, `deno.worker`, etc)
|
||||
|
|
@ -8,6 +8,7 @@ use std::path::PathBuf;
|
|||
use deno_package_json::PackageJson;
|
||||
use deno_package_json::PackageJsonCacheResult;
|
||||
use deno_package_json::PackageJsonRc;
|
||||
use sys_traits::FsMetadata;
|
||||
use sys_traits::FsRead;
|
||||
|
||||
use crate::errors::PackageJsonLoadError;
|
||||
|
|
@ -76,12 +77,12 @@ pub type PackageJsonResolverRc<TSys> =
|
|||
deno_maybe_sync::MaybeArc<PackageJsonResolver<TSys>>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PackageJsonResolver<TSys: FsRead> {
|
||||
pub struct PackageJsonResolver<TSys: FsRead + FsMetadata> {
|
||||
sys: TSys,
|
||||
loader_cache: Option<PackageJsonCacheRc>,
|
||||
}
|
||||
|
||||
impl<TSys: FsRead> PackageJsonResolver<TSys> {
|
||||
impl<TSys: FsRead + FsMetadata> PackageJsonResolver<TSys> {
|
||||
pub fn new(sys: TSys, loader_cache: Option<PackageJsonCacheRc>) -> Self {
|
||||
Self { sys, loader_cache }
|
||||
}
|
||||
|
|
@ -124,12 +125,14 @@ impl<TSys: FsRead> PackageJsonResolver<TSys> {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct ClosestPackageJsonsIterator<'a, TSys: FsRead> {
|
||||
pub struct ClosestPackageJsonsIterator<'a, TSys: FsRead + FsMetadata> {
|
||||
current_path: &'a Path,
|
||||
resolver: &'a PackageJsonResolver<TSys>,
|
||||
}
|
||||
|
||||
impl<'a, TSys: FsRead> Iterator for ClosestPackageJsonsIterator<'a, TSys> {
|
||||
impl<'a, TSys: FsRead + FsMetadata> Iterator
|
||||
for ClosestPackageJsonsIterator<'a, TSys>
|
||||
{
|
||||
type Item = Result<PackageJsonRc, PackageJsonLoadError>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ impl NodeAnalysisCache for NullNodeAnalysisCache {
|
|||
|
||||
#[sys_traits::auto_impl]
|
||||
pub trait DenoCjsCodeAnalyzerSys:
|
||||
sys_traits::FsRead + MaybeSend + MaybeSync + 'static
|
||||
sys_traits::FsRead + sys_traits::FsMetadata + MaybeSend + MaybeSync + 'static
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ use node_resolver::InNpmPackageChecker;
|
|||
use node_resolver::PackageJsonResolverRc;
|
||||
use node_resolver::ResolutionMode;
|
||||
use node_resolver::errors::PackageJsonLoadError;
|
||||
use sys_traits::FsMetadata;
|
||||
use sys_traits::FsRead;
|
||||
use url::Url;
|
||||
|
||||
|
|
@ -21,12 +22,15 @@ pub type CjsTrackerRc<TInNpmPackageChecker, TSys> =
|
|||
/// be CJS or ESM after they're loaded based on their contents. So these
|
||||
/// files will be "maybe CJS" until they're loaded.
|
||||
#[derive(Debug)]
|
||||
pub struct CjsTracker<TInNpmPackageChecker: InNpmPackageChecker, TSys: FsRead> {
|
||||
pub struct CjsTracker<
|
||||
TInNpmPackageChecker: InNpmPackageChecker,
|
||||
TSys: FsRead + FsMetadata,
|
||||
> {
|
||||
is_cjs_resolver: IsCjsResolver<TInNpmPackageChecker, TSys>,
|
||||
known: MaybeDashMap<Url, ResolutionMode>,
|
||||
}
|
||||
|
||||
impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: FsRead>
|
||||
impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: FsRead + FsMetadata>
|
||||
CjsTracker<TInNpmPackageChecker, TSys>
|
||||
{
|
||||
pub fn new(
|
||||
|
|
@ -155,14 +159,14 @@ pub enum IsCjsResolutionMode {
|
|||
#[derive(Debug)]
|
||||
pub struct IsCjsResolver<
|
||||
TInNpmPackageChecker: InNpmPackageChecker,
|
||||
TSys: FsRead,
|
||||
TSys: FsRead + FsMetadata,
|
||||
> {
|
||||
in_npm_pkg_checker: TInNpmPackageChecker,
|
||||
pkg_json_resolver: PackageJsonResolverRc<TSys>,
|
||||
mode: IsCjsResolutionMode,
|
||||
}
|
||||
|
||||
impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: FsRead>
|
||||
impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: FsRead + FsMetadata>
|
||||
IsCjsResolver<TInNpmPackageChecker, TSys>
|
||||
{
|
||||
pub fn new(
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ pub enum ByonmResolvePkgFolderFromDenoReqError {
|
|||
JsrReqUnsupported { req: PackageReq },
|
||||
}
|
||||
|
||||
pub struct ByonmNpmResolverCreateOptions<TSys: FsRead> {
|
||||
pub struct ByonmNpmResolverCreateOptions<TSys: FsRead + FsMetadata> {
|
||||
// todo(dsherret): investigate removing this
|
||||
pub root_node_modules_dir: Option<PathBuf>,
|
||||
pub sys: NodeResolutionSys<TSys>,
|
||||
|
|
|
|||
17
libs/typescript_go_client/Cargo.toml
Normal file
17
libs/typescript_go_client/Cargo.toml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
[package]
|
||||
name = "deno_typescript_go_client_rust"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
description = "Rust library to communicate with TSGO binary over IPC"
|
||||
|
||||
[dependencies]
|
||||
indexmap = { version = "2", features = ["serde"] }
|
||||
log = "0.4.28"
|
||||
rmp = "0.8.14"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
serde_repr = "0.1"
|
||||
thiserror = "2"
|
||||
77
libs/typescript_go_client/src/connection.rs
Normal file
77
libs/typescript_go_client/src/connection.rs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
// Partially extracted / adapted from https://github.com/microsoft/libsyncrpc
|
||||
// Copyright 2024 Microsoft Corporation. MIT license.
|
||||
|
||||
use std::io::BufRead;
|
||||
use std::io::Result;
|
||||
use std::io::Write;
|
||||
use std::io::{self};
|
||||
|
||||
/// Lower-level wrapper around RPC-related messaging and process management.
|
||||
pub struct RpcConnection<R: BufRead, W: Write> {
|
||||
reader: R,
|
||||
writer: W,
|
||||
}
|
||||
|
||||
impl<R: BufRead, W: Write> RpcConnection<R, W> {
|
||||
pub fn new(reader: R, writer: W) -> Result<Self> {
|
||||
Ok(Self { reader, writer })
|
||||
}
|
||||
|
||||
pub fn write(&mut self, ty: u8, name: &[u8], payload: &[u8]) -> Result<()> {
|
||||
let w = &mut self.writer;
|
||||
rmp::encode::write_array_len(w, 3)?;
|
||||
rmp::encode::write_u8(w, ty)?;
|
||||
rmp::encode::write_bin(w, name)?;
|
||||
rmp::encode::write_bin(w, payload)?;
|
||||
w.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn read(&mut self) -> Result<(u8, Vec<u8>, Vec<u8>)> {
|
||||
let r = &mut self.reader;
|
||||
assert_eq!(
|
||||
rmp::decode::read_array_len(r).map_err(to_io)?,
|
||||
3,
|
||||
"Message components must be a valid 3-part messagepack array."
|
||||
);
|
||||
Ok((
|
||||
rmp::decode::read_int(r).map_err(to_io)?,
|
||||
self.read_bin()?,
|
||||
self.read_bin()?,
|
||||
))
|
||||
}
|
||||
|
||||
fn read_bin(&mut self) -> Result<Vec<u8>> {
|
||||
let r = &mut self.reader;
|
||||
let payload_len = rmp::decode::read_bin_len(r).map_err(to_io)?;
|
||||
let mut payload = vec![0u8; payload_len as usize];
|
||||
r.read_exact(&mut payload)?;
|
||||
Ok(payload)
|
||||
}
|
||||
|
||||
// Helper method to create an error
|
||||
pub fn create_error(
|
||||
&self,
|
||||
name: &str,
|
||||
payload: Vec<u8>,
|
||||
expected_method: &str,
|
||||
) -> io::Error {
|
||||
if name == expected_method {
|
||||
let payload = match String::from_utf8(payload) {
|
||||
Ok(payload) => payload,
|
||||
Err(err) => return io::Error::other(format!("{err}")),
|
||||
};
|
||||
io::Error::other(payload)
|
||||
} else {
|
||||
io::Error::other(format!(
|
||||
"name mismatch for response: expected `{expected_method}`, got `{name}`"
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn to_io<T: std::error::Error>(err: T) -> io::Error {
|
||||
io::Error::other(format!("{err}"))
|
||||
}
|
||||
320
libs/typescript_go_client/src/lib.rs
Normal file
320
libs/typescript_go_client/src/lib.rs
Normal file
|
|
@ -0,0 +1,320 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
// Partially extracted / adapted from https://github.com/microsoft/libsyncrpc
|
||||
// Copyright 2024 Microsoft Corporation. MIT license.
|
||||
|
||||
pub mod connection;
|
||||
pub mod types;
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::ffi::OsStr;
|
||||
use std::io::BufReader;
|
||||
use std::io::BufWriter;
|
||||
use std::process::Child;
|
||||
use std::process::ChildStdin;
|
||||
use std::process::ChildStdout;
|
||||
|
||||
use connection::RpcConnection;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("Failed to spawn process: {0}")]
|
||||
ProcessSpawn(#[source] std::io::Error),
|
||||
|
||||
#[error("Failed to kill process: {0}")]
|
||||
ProcessKill(#[source] std::io::Error),
|
||||
|
||||
#[error("Error in RPC connection: {0}")]
|
||||
RpcConnection(#[source] std::io::Error),
|
||||
|
||||
#[error("Error encoding {obj} as {ty}: {source}")]
|
||||
Encoding {
|
||||
obj: &'static str,
|
||||
ty: &'static str,
|
||||
source: Box<Error>,
|
||||
},
|
||||
|
||||
#[error("Error decoding UTF-8: {0}")]
|
||||
Utf8(#[source] std::string::FromUtf8Error),
|
||||
|
||||
#[error("Invalid message type: {0}")]
|
||||
InvalidMessageType(MessageType),
|
||||
|
||||
#[error("{0}")]
|
||||
AdHoc(String),
|
||||
|
||||
#[error("serde json error: {0}")]
|
||||
Json(#[from] serde_json::Error),
|
||||
}
|
||||
|
||||
impl Error {
|
||||
pub fn from_reason<S: Into<String>>(reason: S) -> Self {
|
||||
Self::AdHoc(reason.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub trait CallbackHandler {
|
||||
fn supported_callbacks(&self) -> &'static [&'static str];
|
||||
|
||||
fn handle_callback(
|
||||
&self,
|
||||
name: &str,
|
||||
payload: String,
|
||||
) -> Result<String, Error>;
|
||||
}
|
||||
|
||||
/// A synchronous RPC channel that allows JavaScript to synchronously call out
|
||||
/// to a child process and get a response over a line-based protocol,
|
||||
/// including handling of JavaScript-side callbacks before the call completes.
|
||||
///
|
||||
/// #### Protocol
|
||||
///
|
||||
/// Requests follow a MessagePack-based "tuple"/array protocol with 3 items:
|
||||
/// `(<type>, <name>, <payload>)`. All items are binary arrays of 8-bit
|
||||
/// integers, including the `<type>` and `<name>`, to avoid unnecessary
|
||||
/// encoding/decoding at the protocol level.
|
||||
///
|
||||
/// For specific message types and their corresponding protocol behavior, please
|
||||
/// see `MessageType` below.
|
||||
pub struct SyncRpcChannel<T> {
|
||||
child: Child,
|
||||
conn: RpcConnection<BufReader<ChildStdout>, BufWriter<ChildStdin>>,
|
||||
callback_handler: T,
|
||||
supported_callbacks: HashSet<&'static str>,
|
||||
}
|
||||
|
||||
impl<T: CallbackHandler> SyncRpcChannel<T> {
|
||||
/// Constructs a new `SyncRpcChannel` by spawning a child process with the
|
||||
/// given `exe` executable, and a given set of `args`.
|
||||
pub fn new<I, S>(
|
||||
exe: impl AsRef<OsStr>,
|
||||
args: I,
|
||||
callback_handler: T,
|
||||
) -> Result<Self, Error>
|
||||
where
|
||||
I: IntoIterator<Item = S>,
|
||||
S: AsRef<OsStr>,
|
||||
{
|
||||
let mut child = std::process::Command::new(exe)
|
||||
.stdin(std::process::Stdio::piped())
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::inherit())
|
||||
.args(args)
|
||||
.spawn()
|
||||
.map_err(Error::ProcessSpawn)?;
|
||||
let supported_callbacks = callback_handler.supported_callbacks();
|
||||
Ok(Self {
|
||||
conn: RpcConnection::new(
|
||||
BufReader::new(child.stdout.take().expect("Where did ChildStdout go?")),
|
||||
BufWriter::new(child.stdin.take().expect("Where did ChildStdin go?")),
|
||||
)
|
||||
.map_err(Error::RpcConnection)?,
|
||||
supported_callbacks: supported_callbacks.iter().copied().collect(),
|
||||
callback_handler,
|
||||
child,
|
||||
})
|
||||
}
|
||||
|
||||
/// Send a request to the child process and wait for a response. The method
|
||||
/// will not return, synchronously, until a response is received or an error
|
||||
/// occurs.
|
||||
///
|
||||
/// This method will take care of encoding and decoding the binary payload to
|
||||
/// and from a JS string automatically and suitable for smaller payloads.
|
||||
pub fn request_sync(
|
||||
&mut self,
|
||||
method: &str,
|
||||
payload: String,
|
||||
) -> Result<String, Error> {
|
||||
self
|
||||
.request_bytes_sync(method, payload.as_bytes())
|
||||
.and_then(|arr| {
|
||||
String::from_utf8((&arr[..]).into()).map_err(|e| Error::Encoding {
|
||||
obj: "response",
|
||||
ty: "string",
|
||||
source: Box::new(Error::Utf8(e)),
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/// Send a request to the child process and wait for a response. The method
|
||||
/// will not return, synchronously, until a response is received or an error
|
||||
/// occurs.
|
||||
///
|
||||
/// Unlike `requestSync`, this method will not do any of its own encoding or
|
||||
/// decoding of payload data. Everything will be as sent/received through the
|
||||
/// underlying protocol.
|
||||
pub fn request_bytes_sync(
|
||||
&mut self,
|
||||
method: &str,
|
||||
payload: &[u8],
|
||||
) -> Result<Vec<u8>, Error> {
|
||||
log::trace!("request_bytes_sync: {method}");
|
||||
let method_bytes = method.as_bytes();
|
||||
self
|
||||
.conn
|
||||
.write(MessageType::Request as u8, method_bytes, payload)
|
||||
.map_err(Error::RpcConnection)?;
|
||||
loop {
|
||||
let (ty, name, payload) =
|
||||
self.conn.read().map_err(Error::RpcConnection)?;
|
||||
match ty.try_into().map_err(Error::from_reason)? {
|
||||
MessageType::Response => {
|
||||
if name == method_bytes {
|
||||
return Ok(payload);
|
||||
} else {
|
||||
let name = String::from_utf8_lossy(&name);
|
||||
return Err(Error::from_reason(format!(
|
||||
"name mismatch for response: expected `{method}`, got `{name}`"
|
||||
)));
|
||||
}
|
||||
}
|
||||
MessageType::Error => {
|
||||
return Err(Error::RpcConnection(self.conn.create_error(
|
||||
&String::from_utf8_lossy(&name),
|
||||
payload,
|
||||
method,
|
||||
)));
|
||||
}
|
||||
MessageType::Call => {
|
||||
self.handle_call(&String::from_utf8_lossy(&name), payload)?;
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::from_reason(format!(
|
||||
"Invalid message type from child: {ty:?}"
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Closes the channel, terminating its underlying process.
|
||||
pub fn close(&mut self) -> Result<(), Error> {
|
||||
self.child.kill().map_err(Error::ProcessKill)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Helper method to handle callback calls
|
||||
fn handle_call(&mut self, name: &str, payload: Vec<u8>) -> Result<(), Error> {
|
||||
if !self.supported_callbacks.contains(name) {
|
||||
self.conn.write(MessageType::CallError as u8, name.as_bytes(), format!("unknown callback: `{name}`. Please make sure to register it on the JavaScript side before invoking it.").as_bytes())
|
||||
.map_err(Error::RpcConnection)?;
|
||||
return Err(Error::from_reason(format!(
|
||||
"no callback named `{name}` found"
|
||||
)));
|
||||
}
|
||||
let res = self
|
||||
.callback_handler
|
||||
.handle_callback(name, String::from_utf8(payload).map_err(Error::Utf8)?);
|
||||
match res {
|
||||
Ok(res) => {
|
||||
self
|
||||
.conn
|
||||
.write(
|
||||
MessageType::CallResponse as u8,
|
||||
name.as_bytes(),
|
||||
res.as_bytes(),
|
||||
)
|
||||
.map_err(Error::RpcConnection)?;
|
||||
}
|
||||
Err(e) => {
|
||||
self
|
||||
.conn
|
||||
.write(
|
||||
MessageType::CallError as u8,
|
||||
name.as_bytes(),
|
||||
format!("{e}").trim().as_bytes(),
|
||||
)
|
||||
.map_err(Error::RpcConnection)?;
|
||||
return Err(Error::from_reason(format!(
|
||||
"Error calling callback `{name}`: {}",
|
||||
e
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Messages types exchanged between the channel and its child. All messages
|
||||
/// have an associated `<name>` and `<payload>`, which will both be arrays of
|
||||
/// 8-bit integers (`Uint8Array`s).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
pub enum MessageType {
|
||||
// --- Sent by channel---
|
||||
/// A request to the child with the given raw byte `<payload>`, with
|
||||
/// `<name>` as the method name. The child may send back any number of
|
||||
/// `MessageType.Call` messages and must then close the request with either a
|
||||
/// `MessageType.Response`, or a `MessageType.Error`. message.
|
||||
Request = 1,
|
||||
/// A response to a `MessageType.Call` message that the child previously sent.
|
||||
/// The `<payload>` is the return value from invoking the JavaScript callback
|
||||
/// associated with it. If the callback errors, `MessageType.CallError` will
|
||||
/// be sent to the child.
|
||||
CallResponse,
|
||||
/// Informs the child that an error occurred. The `<payload>` will be the
|
||||
/// binary representation of the stringified error, as UTF-8 bytes, not
|
||||
/// necessarily in JSON format. The method linked to this message will also
|
||||
/// throw an error after sending this message to its child and terminate the
|
||||
/// request call.
|
||||
CallError,
|
||||
|
||||
// --- Sent by child ---
|
||||
/// A response to a request that the call was for. `<name>` MUST match the
|
||||
/// `MessageType.Request` message's `<name>` argument.
|
||||
Response,
|
||||
/// A response that denotes some error occurred while processing the request
|
||||
/// on the child side. The `<payload>` will simply be the binary
|
||||
/// representation of the stringified error, as UTF-8 bytes, not necessarily
|
||||
/// in JSON format. The method associated with this call will also throw an
|
||||
/// error after receiving this message from the child.
|
||||
Error,
|
||||
/// A request to invoke a pre-registered JavaScript callback (see
|
||||
/// `SyncRpcChannel#registerCallback`). `<name>` is the name of the callback,
|
||||
/// and `<payload>` is an encoded UTF-8 string that the callback will be
|
||||
/// called with. The child should then listen for `MessageType.CallResponse`
|
||||
/// and `MessageType.CallError` messages.
|
||||
Call,
|
||||
// NOTE: Do NOT put any variants below this one, always add them _before_ it.
|
||||
// See comment in TryFrom impl, and remove this when `variant_count` stabilizes.
|
||||
_UnusedPlaceholderVariant,
|
||||
// NOTHING SHOULD GO BELOW HERE
|
||||
}
|
||||
|
||||
impl std::fmt::Display for MessageType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MessageType::Request => write!(f, "MessageType::Request"),
|
||||
MessageType::CallResponse => write!(f, "MessageType::CallResponse"),
|
||||
MessageType::CallError => write!(f, "MessageType::CallError"),
|
||||
MessageType::Response => write!(f, "MessageType::Response"),
|
||||
MessageType::Error => write!(f, "MessageType::Error"),
|
||||
MessageType::Call => write!(f, "MessageType::Call"),
|
||||
MessageType::_UnusedPlaceholderVariant => {
|
||||
write!(f, "MessageType::_UnusedPlaceholderVariant")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for MessageType {
|
||||
type Error = String;
|
||||
|
||||
fn try_from(
|
||||
value: u8,
|
||||
) -> std::result::Result<Self, <MessageType as TryFrom<u8>>::Error> {
|
||||
// TODO: change to the following line when `variant_count` stabilizes
|
||||
// (https://github.com/rust-lang/rust/issues/73662) and remove `_UnusedPlaceholderVariant`
|
||||
//
|
||||
// if (1..=std::mem::variant_count::<MessageType>()) {
|
||||
if (1..(MessageType::_UnusedPlaceholderVariant as u8)).contains(&value) {
|
||||
// SAFETY: This is safe as long as the above holds true. It'll be fully
|
||||
// safe once `variant_count` stabilizes.
|
||||
Ok(unsafe { std::mem::transmute::<u8, MessageType>(value) })
|
||||
} else {
|
||||
Err(format!("Invalid message type: {value}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
134
libs/typescript_go_client/src/types.rs
Normal file
134
libs/typescript_go_client/src/types.rs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
#[derive(serde::Deserialize, Debug, Clone, Copy)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Position {
|
||||
pub line: u64,
|
||||
pub character: u64,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Diagnostic {
|
||||
pub file_name: String,
|
||||
pub start: Position,
|
||||
pub end: Position,
|
||||
pub start_pos: u32,
|
||||
pub end_pos: u32,
|
||||
pub code: u32,
|
||||
pub category: String,
|
||||
pub message: String,
|
||||
pub message_chain: Vec<Diagnostic>,
|
||||
pub related_information: Vec<Diagnostic>,
|
||||
pub reports_unnecessary: bool,
|
||||
pub reports_deprecated: bool,
|
||||
pub skipped_on_no_emit: bool,
|
||||
pub source_line: String,
|
||||
}
|
||||
|
||||
pub type DiagnosticId = u32;
|
||||
|
||||
#[derive(
|
||||
serde_repr::Deserialize_repr, serde_repr::Serialize_repr, Debug, Clone, Copy,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum ResolutionMode {
|
||||
None = 0,
|
||||
CommonJS = 1,
|
||||
ESM = 99,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ResolveModuleNamePayload {
|
||||
pub module_name: String,
|
||||
pub containing_file: String,
|
||||
pub resolution_mode: ResolutionMode,
|
||||
// redirected_reference: Handle<Project>,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ResolveTypeReferenceDirectivePayload {
|
||||
pub type_reference_directive_name: String,
|
||||
pub containing_file: String,
|
||||
pub resolution_mode: ResolutionMode,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, serde::Serialize)]
|
||||
#[serde(from = "String", into = "String")]
|
||||
pub struct Handle<T> {
|
||||
pub id: String,
|
||||
#[serde(skip)]
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> std::fmt::Debug for Handle<T> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_tuple("Handle").field(&self.id).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<Handle<T>> for String {
|
||||
fn from(value: Handle<T>) -> Self {
|
||||
value.id
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for Handle<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
id: self.id.clone(),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<String> for Handle<T> {
|
||||
fn from(id: String) -> Self {
|
||||
Self {
|
||||
id,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Project {
|
||||
pub id: Handle<Self>,
|
||||
pub config_file_name: String,
|
||||
pub root_files: Vec<String>,
|
||||
pub compiler_options: IndexMap<String, serde_json::Value>,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Debug, Clone, serde_repr::Deserialize_repr, serde_repr::Serialize_repr,
|
||||
)]
|
||||
#[repr(u32)]
|
||||
pub enum ModuleKind {
|
||||
None = 0,
|
||||
CommonJS = 1,
|
||||
AMD = 2,
|
||||
UMD = 3,
|
||||
System = 4,
|
||||
ES2015 = 5,
|
||||
ES2020 = 6,
|
||||
ES2022 = 7,
|
||||
ESNext = 99,
|
||||
Node16 = 100,
|
||||
Node18 = 101,
|
||||
NodeNext = 199,
|
||||
Preserve = 200,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct GetImpliedNodeFormatForFilePayload {
|
||||
pub file_name: String,
|
||||
pub package_json_type: String,
|
||||
}
|
||||
|
|
@ -232,4 +232,12 @@ pub static FEATURE_DESCRIPTIONS: &[UnstableFeatureDescription] = &[
|
|||
config_option: ConfigFileOption::SameAsFlagName,
|
||||
env_var: None,
|
||||
},
|
||||
UnstableFeatureDescription {
|
||||
name: "tsgo",
|
||||
help_text: "Enable unstable TypeScript Go integration",
|
||||
show_in_help: true,
|
||||
kind: UnstableFeatureKind::Cli,
|
||||
config_option: ConfigFileOption::SameAsFlagName,
|
||||
env_var: Some("DENO_UNSTABLE_TSGO"),
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ export const unstableIds = {
|
|||
process: 17,
|
||||
rawImports: 18,
|
||||
temporal: 21,
|
||||
unsafeProto: 22,
|
||||
vsock: 23,
|
||||
webgpu: 24,
|
||||
workerOptions: 25,
|
||||
unsafeProto: 23,
|
||||
vsock: 24,
|
||||
webgpu: 25,
|
||||
workerOptions: 26,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -205,12 +205,21 @@ pub static UNSTABLE_FEATURES: &[UnstableFeatureDefinition] = &[
|
|||
kind: UnstableFeatureKind::Runtime,
|
||||
config_file_option: "temporal",
|
||||
},
|
||||
UnstableFeatureDefinition {
|
||||
name: "tsgo",
|
||||
flag_name: "unstable-tsgo",
|
||||
help_text: "Enable unstable TypeScript Go integration",
|
||||
show_in_help: true,
|
||||
id: 22,
|
||||
kind: UnstableFeatureKind::Cli,
|
||||
config_file_option: "tsgo",
|
||||
},
|
||||
UnstableFeatureDefinition {
|
||||
name: "unsafe-proto",
|
||||
flag_name: "unstable-unsafe-proto",
|
||||
help_text: "Enable unsafe __proto__ support. This is a security risk.",
|
||||
show_in_help: true,
|
||||
id: 22,
|
||||
id: 23,
|
||||
kind: UnstableFeatureKind::Runtime,
|
||||
config_file_option: "unsafe-proto",
|
||||
},
|
||||
|
|
@ -219,7 +228,7 @@ pub static UNSTABLE_FEATURES: &[UnstableFeatureDefinition] = &[
|
|||
flag_name: "unstable-vsock",
|
||||
help_text: "Enable unstable VSOCK APIs",
|
||||
show_in_help: false,
|
||||
id: 23,
|
||||
id: 24,
|
||||
kind: UnstableFeatureKind::Runtime,
|
||||
config_file_option: "vsock",
|
||||
},
|
||||
|
|
@ -228,7 +237,7 @@ pub static UNSTABLE_FEATURES: &[UnstableFeatureDefinition] = &[
|
|||
flag_name: "unstable-webgpu",
|
||||
help_text: "Enable unstable WebGPU APIs",
|
||||
show_in_help: true,
|
||||
id: 24,
|
||||
id: 25,
|
||||
kind: UnstableFeatureKind::Runtime,
|
||||
config_file_option: "webgpu",
|
||||
},
|
||||
|
|
@ -237,7 +246,7 @@ pub static UNSTABLE_FEATURES: &[UnstableFeatureDefinition] = &[
|
|||
flag_name: "unstable-worker-options",
|
||||
help_text: "Enable unstable Web Worker APIs",
|
||||
show_in_help: true,
|
||||
id: 25,
|
||||
id: 26,
|
||||
kind: UnstableFeatureKind::Runtime,
|
||||
config_file_option: "worker-options",
|
||||
},
|
||||
|
|
@ -250,6 +259,7 @@ pub struct UnstableEnvVarNames {
|
|||
pub raw_imports: &'static str,
|
||||
pub sloppy_imports: &'static str,
|
||||
pub subdomain_wildcards: &'static str,
|
||||
pub tsgo: &'static str,
|
||||
}
|
||||
pub static UNSTABLE_ENV_VAR_NAMES: UnstableEnvVarNames = UnstableEnvVarNames {
|
||||
bare_node_builtins: "DENO_UNSTABLE_BARE_NODE_BUILTINS",
|
||||
|
|
@ -259,4 +269,5 @@ pub static UNSTABLE_ENV_VAR_NAMES: UnstableEnvVarNames = UnstableEnvVarNames {
|
|||
raw_imports: "DENO_UNSTABLE_RAW_IMPORTS",
|
||||
sloppy_imports: "DENO_UNSTABLE_SLOPPY_IMPORTS",
|
||||
subdomain_wildcards: "DENO_UNSTABLE_SUBDOMAIN_WILDCARDS",
|
||||
tsgo: "DENO_UNSTABLE_TSGO",
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ use util::TestContextBuilder;
|
|||
use util::assert_not_contains;
|
||||
use util::testdata_path;
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn compile_basic() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
|
|
@ -57,6 +61,10 @@ fn compile_basic() {
|
|||
output.assert_matches_text("Welcome to Deno!\n");
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn standalone_args() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
|
|
@ -88,6 +96,10 @@ fn standalone_args() {
|
|||
.assert_matches_text("a\nb\nfoo\n--bar\n--unstable\n");
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn standalone_load_datauri() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
|
|
@ -117,6 +129,10 @@ fn standalone_load_datauri() {
|
|||
}
|
||||
|
||||
// https://github.com/denoland/deno/issues/13704
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn standalone_follow_redirects() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
|
|
@ -262,6 +278,10 @@ fn compile_and_overwrite_file() {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn standalone_runtime_flags() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
|
|
@ -298,6 +318,10 @@ fn standalone_runtime_flags() {
|
|||
);
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn standalone_ext_flag_ts() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
|
|
@ -329,6 +353,10 @@ fn standalone_ext_flag_ts() {
|
|||
.assert_matches_text("executing typescript with no extension\n");
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn standalone_ext_flag_js() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
|
|
@ -359,6 +387,10 @@ fn standalone_ext_flag_js() {
|
|||
.assert_matches_text("executing javascript with no extension\n");
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn standalone_import_map() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
|
|
@ -390,6 +422,10 @@ fn standalone_import_map() {
|
|||
.assert_exit_code(0);
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn standalone_import_map_config_file() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
|
|
@ -421,6 +457,10 @@ fn standalone_import_map_config_file() {
|
|||
.assert_exit_code(0);
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
// https://github.com/denoland/deno/issues/12670
|
||||
fn skip_rebundle() {
|
||||
|
|
@ -500,6 +540,10 @@ fn check_local_by_default2() {
|
|||
);
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn workers_basic() {
|
||||
let context = TestContext::with_http_server();
|
||||
|
|
@ -530,6 +574,10 @@ fn workers_basic() {
|
|||
.assert_matches_file("./compile/workers/basic.out");
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn workers_not_in_module_map() {
|
||||
let context = TestContext::with_http_server();
|
||||
|
|
@ -559,6 +607,10 @@ fn workers_not_in_module_map() {
|
|||
));
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn workers_with_include_flag() {
|
||||
let context = TestContext::with_http_server();
|
||||
|
|
@ -590,6 +642,10 @@ fn workers_with_include_flag() {
|
|||
.assert_matches_text("Hello from worker!\nReceived 42\nClosing\n");
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn dynamic_import() {
|
||||
let context = TestContext::with_http_server();
|
||||
|
|
@ -620,6 +676,10 @@ fn dynamic_import() {
|
|||
.assert_exit_code(0);
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn dynamic_import_unanalyzable() {
|
||||
let context = TestContext::with_http_server();
|
||||
|
|
@ -772,6 +832,10 @@ testing[WILDCARD]this
|
|||
.assert_matches_text("2\n");
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn compile_npm_bin_esm() {
|
||||
run_npm_bin_compile_test(RunNpmBinCompileOptions {
|
||||
|
|
@ -788,6 +852,10 @@ fn compile_npm_bin_esm() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
fn compile_npm_bin_cjs() {
|
||||
run_npm_bin_compile_test(RunNpmBinCompileOptions {
|
||||
input_specifier: "npm:@denotest/bin/cli-cjs",
|
||||
|
|
@ -803,6 +871,10 @@ fn compile_npm_bin_cjs() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
fn compile_npm_cowsay_main() {
|
||||
run_npm_bin_compile_test(RunNpmBinCompileOptions {
|
||||
input_specifier: "npm:cowsay@1.5.0",
|
||||
|
|
@ -818,6 +890,10 @@ fn compile_npm_cowsay_main() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
fn compile_npm_no_permissions() {
|
||||
run_npm_bin_compile_test(RunNpmBinCompileOptions {
|
||||
input_specifier: "npm:@denotest/cli-with-permissions@1.0.0",
|
||||
|
|
@ -833,6 +909,10 @@ fn compile_npm_no_permissions() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
fn compile_npm_cowsay_explicit() {
|
||||
run_npm_bin_compile_test(RunNpmBinCompileOptions {
|
||||
input_specifier: "npm:cowsay@1.5.0/cowsay",
|
||||
|
|
@ -848,6 +928,10 @@ fn compile_npm_cowsay_explicit() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
fn compile_npm_cowthink() {
|
||||
run_npm_bin_compile_test(RunNpmBinCompileOptions {
|
||||
input_specifier: "npm:cowsay@1.5.0/cowthink",
|
||||
|
|
@ -921,6 +1005,10 @@ fn run_npm_bin_compile_test(opts: RunNpmBinCompileOptions) {
|
|||
output.assert_matches_file(opts.output_file);
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn compile_node_modules_symlink_outside() {
|
||||
// this code is using a canonicalized temp dir because otherwise
|
||||
|
|
@ -989,6 +1077,10 @@ fn compile_node_modules_symlink_outside() {
|
|||
output.assert_matches_file("compile/node_modules_symlink_outside/main.out");
|
||||
}
|
||||
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
#[test]
|
||||
fn compile_node_modules_symlink_non_existent() {
|
||||
let context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
||||
|
|
@ -1033,6 +1125,10 @@ Embedded Files
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
fn dynamic_imports_tmp_lit() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
let dir = context.temp_dir();
|
||||
|
|
@ -1057,6 +1153,10 @@ fn dynamic_imports_tmp_lit() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
fn granular_unstable_features() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
let dir = context.temp_dir();
|
||||
|
|
@ -1084,6 +1184,10 @@ fn granular_unstable_features() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
fn granular_unstable_features_config_file() {
|
||||
let context = TestContextBuilder::new().use_temp_cwd().build();
|
||||
let dir = context.temp_dir();
|
||||
|
|
@ -1121,6 +1225,10 @@ fn granular_unstable_features_config_file() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
fn dynamic_import_bad_data_uri() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
let dir = context.temp_dir();
|
||||
|
|
@ -1150,6 +1258,10 @@ fn dynamic_import_bad_data_uri() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
fn standalone_config_file_respects_compiler_options() {
|
||||
let context = TestContextBuilder::new().build();
|
||||
let dir = context.temp_dir();
|
||||
|
|
@ -1179,6 +1291,10 @@ fn standalone_config_file_respects_compiler_options() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(
|
||||
all(target_os = "macos", target_arch = "x86_64", debug_assertions),
|
||||
ignore // TODO: fix this, see https://github.com/denoland/sui/issues/43
|
||||
)]
|
||||
fn standalone_jsr_dynamic_import() {
|
||||
let context = TestContextBuilder::for_jsr().build();
|
||||
let dir = context.temp_dir();
|
||||
|
|
|
|||
|
|
@ -1,18 +1,36 @@
|
|||
{
|
||||
"steps": [{
|
||||
"args": "check foo.ts",
|
||||
"output": "foo.out"
|
||||
}, {
|
||||
"args": "check bar.ts",
|
||||
"output": "bar.out",
|
||||
"exitCode": 1
|
||||
}, {
|
||||
"args": "run foo.ts",
|
||||
"output": "run.out",
|
||||
"exitCode": 1
|
||||
}, {
|
||||
"args": "run bar.ts",
|
||||
"output": "run.out",
|
||||
"exitCode": 1
|
||||
}]
|
||||
"steps": [
|
||||
{
|
||||
"args": "check foo.ts",
|
||||
"output": "foo.out"
|
||||
},
|
||||
{
|
||||
"args": "check bar.ts",
|
||||
"output": "bar.out",
|
||||
"exitCode": 1
|
||||
},
|
||||
{
|
||||
"args": "run foo.ts",
|
||||
"output": "run.out",
|
||||
"exitCode": 1
|
||||
},
|
||||
{
|
||||
"args": "run bar.ts",
|
||||
"output": "run.out",
|
||||
"exitCode": 1
|
||||
}
|
||||
],
|
||||
"variants": {
|
||||
// TODO(nathanwhit): not implemented yet, needs extra api to get ambient modules on
|
||||
// the tsgo side
|
||||
// "tsgo": {
|
||||
// "use_tsgo": "1"
|
||||
// },
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
// https://github.com/denoland/deno/issues/30116
|
||||
{
|
||||
"tests": {
|
||||
"import_map": {
|
||||
|
|
@ -11,5 +10,16 @@
|
|||
"output": "check_no_import_map.out",
|
||||
"exitCode": 1
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check main.ts",
|
||||
"output": "check.out"
|
||||
"output": "check.out",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,21 @@
|
|||
{
|
||||
"args": "check --unstable-raw-imports main.ts",
|
||||
"output": "main.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
// TODO(nathanwhit): not implemented yet, needs tsgo changes
|
||||
// see appendRawImportFragment in cli/tsc/97_ts_host.js and the code that calls it.
|
||||
// it will need tsgo changes because the import kind is not easily available on the tsgo side
|
||||
// during resolution.
|
||||
//
|
||||
// "tsgo": {
|
||||
// "use_tsgo": "1"
|
||||
// },
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --allow-import --quiet --all check_all.ts",
|
||||
"output": "check_all.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --allow-import --quiet check_all_local.ts",
|
||||
"output": "",
|
||||
"exitCode": 0
|
||||
"exitCode": 0,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --quiet broadcast_channel.ts",
|
||||
"output": "",
|
||||
"exitCode": 0
|
||||
"exitCode": 0,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --quiet deno_not_found/main.ts",
|
||||
"output": "deno_not_found/main.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5
tests/specs/check/check_deno_not_found/deno.json
Normal file
5
tests/specs/check/check_deno_not_found/deno.json
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"lib": []
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --quiet dts/check_dts.d.ts",
|
||||
"output": "dts/check_dts.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,5 +15,16 @@
|
|||
"output": "exclude_option.ts.error.out",
|
||||
"exitCode": 1
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --quiet --config exclude_option/deno.exclude_dir.json exclude_option/index.ts",
|
||||
"output": "exclude_option/exclude_option.ts.error.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check --quiet --config jsximportsource_importmap_config/deno.json jsximportsource_importmap_config/main.tsx",
|
||||
"output": ""
|
||||
"output": "",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --quiet no_error_truncation/main.ts --config no_error_truncation/deno.json",
|
||||
"output": "no_error_truncation/main.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,26 @@
|
|||
"tests": {
|
||||
"js": {
|
||||
"args": "check --quiet mod.js",
|
||||
"output": "mod.js.out",
|
||||
"output": "mod.js${out_suffix}",
|
||||
"exitCode": 1
|
||||
},
|
||||
"ts": {
|
||||
"args": "check --quiet mod.ts",
|
||||
"output": "mod.ts.out",
|
||||
"output": "mod.ts${out_suffix}",
|
||||
"exitCode": 1
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1",
|
||||
"out_suffix": ".tsgo.out"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": "",
|
||||
"out_suffix": ".out"
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
tests/specs/check/check_node_builtin_modules/mod.js.tsgo.out
Normal file
11
tests/specs/check/check_node_builtin_modules/mod.js.tsgo.out
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
TS2769 [ERROR]: No overload matches this call.
|
||||
const _data = fs.readFileSync("./node_builtin.js", 123);
|
||||
~~~
|
||||
at [WILDLINE]/mod.js:3:52
|
||||
|
||||
TS2771 [ERROR]: The last overload is declared here.
|
||||
export function readFileSync(
|
||||
~~~~~~~~~~~~
|
||||
at [WILDLINE]/fs.d.ts:2925:21
|
||||
|
||||
error: Type checking failed.
|
||||
18
tests/specs/check/check_node_builtin_modules/mod.ts.tsgo.out
Normal file
18
tests/specs/check/check_node_builtin_modules/mod.ts.tsgo.out
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
TS2769 [ERROR]: No overload matches this call.
|
||||
const _data = fs.readFileSync("./node_builtin.js", 123);
|
||||
~~~
|
||||
at [WILDLINE]/mod.ts:2:52
|
||||
|
||||
TS2771 [ERROR]: The last overload is declared here.
|
||||
export function readFileSync(
|
||||
~~~~~~~~~~~~
|
||||
at [WILDLINE]/fs.d.ts:2925:21
|
||||
|
||||
TS4104 [ERROR]: The type 'readonly string[]' is 'readonly' and cannot be assigned to the mutable type 'number[]'.
|
||||
const _testString: number[] = builtinModules;
|
||||
~~~~~~~~~~~
|
||||
at [WILDLINE]/mod.ts:9:7
|
||||
|
||||
Found 2 errors.
|
||||
|
||||
error: Type checking failed.
|
||||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --quiet",
|
||||
"output": "",
|
||||
"exitCode": 0
|
||||
"exitCode": 0,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --quiet npm_install_diagnostics/main.ts",
|
||||
"output": "npm_install_diagnostics/main.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --quiet response_json.ts",
|
||||
"output": "",
|
||||
"exitCode": 0
|
||||
"exitCode": 0,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check main.ts",
|
||||
"output": "main.out",
|
||||
"exitCode": 0
|
||||
"exitCode": 0,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check lib/types.d.ts",
|
||||
"output": "check.out"
|
||||
"output": "check.out",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,5 +10,16 @@
|
|||
"output": "check_config_flag.out",
|
||||
"exitCode": 1
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check main.ts",
|
||||
"output": "main.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,5 +9,16 @@
|
|||
"output": "unmapped.out",
|
||||
"exitCode": 1
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check --quiet subdir/mod.ts",
|
||||
"output": ""
|
||||
"output": "",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,5 +49,16 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +1,46 @@
|
|||
{
|
||||
"steps": [{
|
||||
"args": "check exists.ts",
|
||||
"output": "exists.out"
|
||||
}, {
|
||||
"args": "run --check exists.ts",
|
||||
"output": "exists_run_with_check.out",
|
||||
"exitCode": 1
|
||||
}, {
|
||||
"args": "check not_exists.ts",
|
||||
"output": "not_exists.out",
|
||||
"exitCode": 1
|
||||
}, {
|
||||
"args": "run --check not_exists.ts",
|
||||
"output": "not_exists_run.out",
|
||||
"exitCode": 1
|
||||
}, {
|
||||
"args": "check exists_and_try_uses.ts",
|
||||
"output": "exists_and_try_uses.out"
|
||||
}, {
|
||||
"args": "check exists_dynamic_import.ts",
|
||||
"output": "Check file:///[WILDCARD]exists_dynamic_import.ts\n"
|
||||
}, {
|
||||
"args": "run --check --reload exists_dynamic_import.ts",
|
||||
"output": "Check file:///[WILDCARD]exists_dynamic_import.ts\n"
|
||||
}]
|
||||
"steps": [
|
||||
{
|
||||
"args": "check exists.ts",
|
||||
"output": "exists.out"
|
||||
},
|
||||
{
|
||||
"args": "run --check exists.ts",
|
||||
"output": "exists_run_with_check.out",
|
||||
"exitCode": 1
|
||||
},
|
||||
{
|
||||
"args": "check not_exists.ts",
|
||||
"output": "not_exists.out",
|
||||
"exitCode": 1
|
||||
},
|
||||
{
|
||||
"args": "run --check not_exists.ts",
|
||||
"output": "not_exists_run.out",
|
||||
"exitCode": 1
|
||||
},
|
||||
{
|
||||
"args": "check exists_and_try_uses.ts",
|
||||
"output": "exists_and_try_uses.out"
|
||||
},
|
||||
{
|
||||
"args": "check exists_dynamic_import.ts",
|
||||
"output": "Check file:///[WILDCARD]exists_dynamic_import.ts\n"
|
||||
},
|
||||
{
|
||||
"args": "run --check --reload exists_dynamic_import.ts",
|
||||
"output": "Check file:///[WILDCARD]exists_dynamic_import.ts\n"
|
||||
}
|
||||
],
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check --quiet declaration_header_file_with_no_exports.ts",
|
||||
"output": ""
|
||||
"output": "",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"tempDir": true,
|
||||
"envs": {
|
||||
"RUST_BACKTRACE": "0"
|
||||
"RUST_BACKTRACE": "0",
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
},
|
||||
"tests": {
|
||||
"node_modules_dir_auto": {
|
||||
|
|
@ -72,5 +73,13 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check index.js",
|
||||
"output": "check.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check main.ts",
|
||||
"output": "error.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,23 @@
|
|||
{
|
||||
"steps": [{
|
||||
"args": "check main.ts",
|
||||
"output": "main.out"
|
||||
}, {
|
||||
// ensure diagnostic is not cached
|
||||
"args": "check main.ts",
|
||||
"output": "main.out"
|
||||
}]
|
||||
"steps": [
|
||||
{
|
||||
"args": "check main.ts",
|
||||
"output": "main.out"
|
||||
},
|
||||
{
|
||||
"args": "check main.ts",
|
||||
"output": "main.out"
|
||||
}
|
||||
],
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check --reload --all http://localhost:4545/subdir/no_js_ext",
|
||||
"output": "check.out"
|
||||
"output": "check.out",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,5 +20,16 @@
|
|||
"output": "Check [WILDLINE]sub_dir/main.ts\nTS2322[WILDCARD]",
|
||||
"exitCode": 1
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,5 +49,16 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,5 +10,16 @@
|
|||
"output": "check_all.out",
|
||||
"exitCode": 1
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check main.ts",
|
||||
"output": "[WILDCARD]",
|
||||
"exitCode": 0 // should be successful
|
||||
"exitCode": 0,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --allow-import main.js",
|
||||
"output": "check.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,24 @@
|
|||
{
|
||||
"tempDir": true,
|
||||
"steps": [{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
}, {
|
||||
"args": "check main.tsx",
|
||||
"output": "check.out"
|
||||
}]
|
||||
"steps": [
|
||||
{
|
||||
"args": "install",
|
||||
"output": "[WILDCARD]"
|
||||
},
|
||||
{
|
||||
"args": "check main.tsx",
|
||||
"output": "check.out"
|
||||
}
|
||||
],
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check main.ts",
|
||||
"output": "main.out"
|
||||
"output": "main.out",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check --allow-import --all main.tsx",
|
||||
"output": "main.out"
|
||||
"output": "main.out",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check --allow-import --all main.tsx",
|
||||
"output": "main.out"
|
||||
"output": "main.out",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check jsx_not_checked/main.jsx",
|
||||
"output": "jsx_not_checked/main.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,30 +2,48 @@
|
|||
"tempDir": true,
|
||||
"tests": {
|
||||
"check": {
|
||||
"steps": [{
|
||||
"args": "check --frozen=true",
|
||||
"output": "[WILDCARD]The lockfile is out of date.[WILDCARD]",
|
||||
"exitCode": 1
|
||||
}, {
|
||||
"args": "check --frozen=false",
|
||||
"output": "[WILDCARD]",
|
||||
"exitCode": 0
|
||||
}, {
|
||||
"args": "check --frozen=true",
|
||||
"output": "[WILDCARD]",
|
||||
"exitCode": 0
|
||||
}]
|
||||
"steps": [
|
||||
{
|
||||
"args": "check --frozen=true",
|
||||
"output": "[WILDCARD]The lockfile is out of date.[WILDCARD]",
|
||||
"exitCode": 1
|
||||
},
|
||||
{
|
||||
"args": "check --frozen=false",
|
||||
"output": "[WILDCARD]",
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"args": "check --frozen=true",
|
||||
"output": "[WILDCARD]",
|
||||
"exitCode": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"install": {
|
||||
"steps": [{
|
||||
"args": "install --frozen=false --entrypoint main.ts",
|
||||
"output": "[WILDCARD]",
|
||||
"exitCode": 0
|
||||
}, {
|
||||
"args": "check --frozen=true",
|
||||
"output": "[WILDCARD]",
|
||||
"exitCode": 0
|
||||
}]
|
||||
"steps": [
|
||||
{
|
||||
"args": "install --frozen=false --entrypoint main.ts",
|
||||
"output": "[WILDCARD]",
|
||||
"exitCode": 0
|
||||
},
|
||||
{
|
||||
"args": "check --frozen=true",
|
||||
"output": "[WILDCARD]",
|
||||
"exitCode": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --frozen=true",
|
||||
"output": "[WILDCARD]",
|
||||
"exitCode": 0
|
||||
"exitCode": 0,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,18 @@
|
|||
// Regression test for https://github.com/denoland/deno/issues/27411.
|
||||
{
|
||||
"args": "check --quiet message_chain_formatting.ts",
|
||||
"output": "message_chain_formatting.out",
|
||||
"exitCode": 1
|
||||
"output": "${out}",
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1",
|
||||
"out": "message_chain_formatting_tsgo.out"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": "",
|
||||
"out": "message_chain_formatting.out"
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
TS2769 [ERROR]: No overload matches this call.
|
||||
foo("hello", 42);
|
||||
~~~~~~~
|
||||
at [WILDLINE]/message_chain_formatting.ts:8:5
|
||||
|
||||
TS2771 [ERROR]: The last overload is declared here.
|
||||
function foo(ss: string[], b: Date): void;
|
||||
~~~
|
||||
at [WILDLINE]/message_chain_formatting.ts:3:10
|
||||
|
||||
error: Type checking failed.
|
||||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check --quiet module_detection_force/main.ts",
|
||||
"output": ""
|
||||
"output": "",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,5 +20,16 @@
|
|||
"output": "missing_remote_root.out",
|
||||
"exitCode": 1
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check main.ts",
|
||||
"output": "check.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,17 @@
|
|||
{
|
||||
"args": "check --all main.ts",
|
||||
"output": "check.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
// currently failing
|
||||
// "tsgo": {
|
||||
// "use_tsgo": "1"
|
||||
// },
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,5 +15,16 @@
|
|||
"output": "main.out",
|
||||
"exitCode": 1
|
||||
}
|
||||
},
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check main.ts",
|
||||
"output": "main.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,24 @@
|
|||
{
|
||||
"steps": [{
|
||||
"args": "check index.ts",
|
||||
"output": "check.out",
|
||||
"exitCode": 1
|
||||
}, {
|
||||
"args": "run index.ts",
|
||||
"output": "run.out"
|
||||
}]
|
||||
"steps": [
|
||||
{
|
||||
"args": "check index.ts",
|
||||
"output": "check.out",
|
||||
"exitCode": 1
|
||||
},
|
||||
{
|
||||
"args": "run index.ts",
|
||||
"output": "run.out"
|
||||
}
|
||||
],
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,5 +9,16 @@
|
|||
"args": "check main.ts",
|
||||
"output": "check.out"
|
||||
}
|
||||
]
|
||||
],
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,5 +5,16 @@
|
|||
"args": "check main.ts",
|
||||
"output": "check.out"
|
||||
}
|
||||
]
|
||||
],
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,5 +10,16 @@
|
|||
"output": "fail_check.out",
|
||||
"exitCode": 1
|
||||
}
|
||||
]
|
||||
],
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,5 +10,16 @@
|
|||
"output": "check.out",
|
||||
"exitCode": 1
|
||||
}
|
||||
]
|
||||
],
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check --reload --all http://localhost:4545/subdir/no_js_ext@1.0.0",
|
||||
"output": "output.out"
|
||||
"output": "output.out",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check ./main.ts",
|
||||
"output": "main.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check --allow-import --all main.ts",
|
||||
"output": "Download [WILDLINE]\nCheck [WILDLINE]\n"
|
||||
"output": "Download [WILDLINE]\nCheck [WILDLINE]\n",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check --quiet types.d.ts",
|
||||
"output": ""
|
||||
"output": "",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check",
|
||||
"output": "check.out"
|
||||
"output": "check.out",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --all main.ts",
|
||||
"output": "check.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,15 @@
|
|||
{
|
||||
"args": "check --quiet",
|
||||
"output": ""
|
||||
"output": "",
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --quiet",
|
||||
"output": "main.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,16 @@
|
|||
{
|
||||
"args": "check --quiet",
|
||||
"output": "main.out",
|
||||
"exitCode": 1
|
||||
"exitCode": 1,
|
||||
"variants": {
|
||||
"tsgo": {
|
||||
"use_tsgo": "1"
|
||||
},
|
||||
"tsc": {
|
||||
"use_tsgo": ""
|
||||
}
|
||||
},
|
||||
"envs": {
|
||||
"DENO_UNSTABLE_TSGO": "${use_tsgo}"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue