mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 05:42:25 -05:00
feat: Wasm module support (#26668)
Support for Wasm modules. Note this implements the standard where the default export is the instance (not the module). The module will come later with source phase imports. ```ts import { add } from "./math.wasm"; console.log(add(1, 2)); ```
This commit is contained in:
parent
6b478cd0a3
commit
8be2bbf074
60 changed files with 401 additions and 46 deletions
14
Cargo.lock
generated
14
Cargo.lock
generated
|
@ -1466,9 +1466,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_core"
|
name = "deno_core"
|
||||||
version = "0.320.0"
|
version = "0.321.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f285eed7b072749f9c3a9c4cf2c9ebb06462a2c22afec94892a6684c38f32696"
|
checksum = "cd2a54cda74cdc187d5fc2d23370a45cf09f912caf566dd1cd24a50157d809c7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
|
@ -1480,6 +1480,7 @@ dependencies = [
|
||||||
"deno_ops",
|
"deno_ops",
|
||||||
"deno_unsync",
|
"deno_unsync",
|
||||||
"futures",
|
"futures",
|
||||||
|
"indexmap 2.3.0",
|
||||||
"libc",
|
"libc",
|
||||||
"memoffset",
|
"memoffset",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
@ -1494,6 +1495,7 @@ dependencies = [
|
||||||
"tokio",
|
"tokio",
|
||||||
"url",
|
"url",
|
||||||
"v8",
|
"v8",
|
||||||
|
"wasm_dep_analyzer",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1981,9 +1983,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_ops"
|
name = "deno_ops"
|
||||||
version = "0.196.0"
|
version = "0.197.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d35c75ae05062f37ec2ae5fd1d99b2dcdfa0aef70844d3706759b8775056c5f6"
|
checksum = "37a8825d92301cf445727c43f17fee2a20fcdf4370004339965156ae7c56c97e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-rules",
|
"proc-macro-rules",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -6517,9 +6519,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_v8"
|
name = "serde_v8"
|
||||||
version = "0.229.0"
|
version = "0.230.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e1dbbda82d67a393ea96f75d8383bc41fcd0bba43164aeaab599e1c2c2d46d7"
|
checksum = "b5a783242d2af51d6955cc04bf2b64adb643ab588b61e9573c908a69dabf8c2f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
|
@ -46,7 +46,7 @@ repository = "https://github.com/denoland/deno"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
deno_ast = { version = "=0.43.3", features = ["transpiling"] }
|
deno_ast = { version = "=0.43.3", features = ["transpiling"] }
|
||||||
deno_core = { version = "0.320.0" }
|
deno_core = { version = "0.321.0" }
|
||||||
|
|
||||||
deno_bench_util = { version = "0.171.0", path = "./bench_util" }
|
deno_bench_util = { version = "0.171.0", path = "./bench_util" }
|
||||||
deno_config = { version = "=0.39.1", features = ["workspace", "sync"] }
|
deno_config = { version = "=0.39.1", features = ["workspace", "sync"] }
|
||||||
|
|
|
@ -1548,6 +1548,10 @@ impl CliOptions {
|
||||||
}) => Url::parse(&flags.module_url)
|
}) => Url::parse(&flags.module_url)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|url| vec![Cow::Owned(url)]),
|
.map(|url| vec![Cow::Owned(url)]),
|
||||||
|
DenoSubcommand::Doc(DocFlags {
|
||||||
|
source_files: DocSourceFileFlag::Paths(paths),
|
||||||
|
..
|
||||||
|
}) => Some(files_to_urls(paths)),
|
||||||
_ => None,
|
_ => None,
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
|
@ -38,6 +38,7 @@ fn get_module_graph_error_class(err: &ModuleGraphError) -> &'static str {
|
||||||
ModuleGraphError::ModuleError(err) => match err {
|
ModuleGraphError::ModuleError(err) => match err {
|
||||||
ModuleError::InvalidTypeAssertion { .. } => "SyntaxError",
|
ModuleError::InvalidTypeAssertion { .. } => "SyntaxError",
|
||||||
ModuleError::ParseErr(_, diagnostic) => get_diagnostic_class(diagnostic),
|
ModuleError::ParseErr(_, diagnostic) => get_diagnostic_class(diagnostic),
|
||||||
|
ModuleError::WasmParseErr(..) => "SyntaxError",
|
||||||
ModuleError::UnsupportedMediaType { .. }
|
ModuleError::UnsupportedMediaType { .. }
|
||||||
| ModuleError::UnsupportedImportAttributeType { .. } => "TypeError",
|
| ModuleError::UnsupportedImportAttributeType { .. } => "TypeError",
|
||||||
ModuleError::Missing(_, _) | ModuleError::MissingDynamic(_, _) => {
|
ModuleError::Missing(_, _) | ModuleError::MissingDynamic(_, _) => {
|
||||||
|
@ -71,7 +72,6 @@ fn get_module_graph_error_class(err: &ModuleGraphError) -> &'static str {
|
||||||
| JsrLoadError::UnknownExport { .. } => "NotFound",
|
| JsrLoadError::UnknownExport { .. } => "NotFound",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ModuleError::WasmParseErr(_, _) => "SyntaxError",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -883,8 +883,13 @@ impl FileSystemDocuments {
|
||||||
let doc = if specifier.scheme() == "file" {
|
let doc = if specifier.scheme() == "file" {
|
||||||
let path = url_to_file_path(specifier).ok()?;
|
let path = url_to_file_path(specifier).ok()?;
|
||||||
let bytes = fs::read(path).ok()?;
|
let bytes = fs::read(path).ok()?;
|
||||||
let content =
|
let content = bytes_to_content(
|
||||||
deno_graph::source::decode_owned_source(specifier, bytes, None).ok()?;
|
specifier,
|
||||||
|
MediaType::from_specifier(specifier),
|
||||||
|
bytes,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
.ok()?;
|
||||||
Document::new(
|
Document::new(
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
content.into(),
|
content.into(),
|
||||||
|
@ -923,19 +928,24 @@ impl FileSystemDocuments {
|
||||||
specifier,
|
specifier,
|
||||||
Some(&cached_file.metadata.headers),
|
Some(&cached_file.metadata.headers),
|
||||||
);
|
);
|
||||||
let content = deno_graph::source::decode_owned_source(
|
let media_type = resolve_media_type(
|
||||||
specifier,
|
specifier,
|
||||||
|
Some(&cached_file.metadata.headers),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
let content = bytes_to_content(
|
||||||
|
specifier,
|
||||||
|
media_type,
|
||||||
cached_file.content,
|
cached_file.content,
|
||||||
maybe_charset,
|
maybe_charset,
|
||||||
)
|
)
|
||||||
.ok()?;
|
.ok()?;
|
||||||
let maybe_headers = Some(cached_file.metadata.headers);
|
|
||||||
Document::new(
|
Document::new(
|
||||||
specifier.clone(),
|
specifier.clone(),
|
||||||
content.into(),
|
content.into(),
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
maybe_headers,
|
Some(cached_file.metadata.headers),
|
||||||
is_cjs_resolver,
|
is_cjs_resolver,
|
||||||
resolver.clone(),
|
resolver.clone(),
|
||||||
config.clone(),
|
config.clone(),
|
||||||
|
@ -1706,6 +1716,24 @@ fn analyze_module(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bytes_to_content(
|
||||||
|
specifier: &ModuleSpecifier,
|
||||||
|
media_type: MediaType,
|
||||||
|
bytes: Vec<u8>,
|
||||||
|
maybe_charset: Option<&str>,
|
||||||
|
) -> Result<String, AnyError> {
|
||||||
|
if media_type == MediaType::Wasm {
|
||||||
|
// we use the dts representation for Wasm modules
|
||||||
|
Ok(deno_graph::source::wasm::wasm_module_to_dts(&bytes)?)
|
||||||
|
} else {
|
||||||
|
Ok(deno_graph::source::decode_owned_source(
|
||||||
|
specifier,
|
||||||
|
bytes,
|
||||||
|
maybe_charset,
|
||||||
|
)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -5609,7 +5609,7 @@ mod tests {
|
||||||
let (_tx, rx) = mpsc::unbounded_channel();
|
let (_tx, rx) = mpsc::unbounded_channel();
|
||||||
let state =
|
let state =
|
||||||
State::new(state_snapshot, Default::default(), Default::default(), rx);
|
State::new(state_snapshot, Default::default(), Default::default(), rx);
|
||||||
let mut op_state = OpState::new(None);
|
let mut op_state = OpState::new(None, None);
|
||||||
op_state.put(state);
|
op_state.put(state);
|
||||||
op_state
|
op_state
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,6 +66,7 @@ use deno_graph::JsonModule;
|
||||||
use deno_graph::Module;
|
use deno_graph::Module;
|
||||||
use deno_graph::ModuleGraph;
|
use deno_graph::ModuleGraph;
|
||||||
use deno_graph::Resolution;
|
use deno_graph::Resolution;
|
||||||
|
use deno_graph::WasmModule;
|
||||||
use deno_runtime::code_cache;
|
use deno_runtime::code_cache;
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
use deno_runtime::deno_fs::FileSystem;
|
||||||
use deno_runtime::deno_node::create_host_defined_options;
|
use deno_runtime::deno_node::create_host_defined_options;
|
||||||
|
@ -368,7 +369,9 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
requested_module_type: RequestedModuleType,
|
requested_module_type: RequestedModuleType,
|
||||||
) -> Result<ModuleSource, AnyError> {
|
) -> Result<ModuleSource, AnyError> {
|
||||||
let code_source = self.load_code_source(specifier, maybe_referrer).await?;
|
let code_source = self.load_code_source(specifier, maybe_referrer).await?;
|
||||||
let code = if self.shared.is_inspecting {
|
let code = if self.shared.is_inspecting
|
||||||
|
|| code_source.media_type == MediaType::Wasm
|
||||||
|
{
|
||||||
// we need the code with the source map in order for
|
// we need the code with the source map in order for
|
||||||
// it to work with --inspect or --inspect-brk
|
// it to work with --inspect or --inspect-brk
|
||||||
code_source.code
|
code_source.code
|
||||||
|
@ -378,6 +381,7 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
};
|
};
|
||||||
let module_type = match code_source.media_type {
|
let module_type = match code_source.media_type {
|
||||||
MediaType::Json => ModuleType::Json,
|
MediaType::Json => ModuleType::Json,
|
||||||
|
MediaType::Wasm => ModuleType::Wasm,
|
||||||
_ => ModuleType::JavaScript,
|
_ => ModuleType::JavaScript,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -545,6 +549,7 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
Some(Module::Node(module)) => module.specifier.clone(),
|
Some(Module::Node(module)) => module.specifier.clone(),
|
||||||
Some(Module::Js(module)) => module.specifier.clone(),
|
Some(Module::Js(module)) => module.specifier.clone(),
|
||||||
Some(Module::Json(module)) => module.specifier.clone(),
|
Some(Module::Json(module)) => module.specifier.clone(),
|
||||||
|
Some(Module::Wasm(module)) => module.specifier.clone(),
|
||||||
Some(Module::External(module)) => {
|
Some(Module::External(module)) => {
|
||||||
node::resolve_specifier_into_node_modules(
|
node::resolve_specifier_into_node_modules(
|
||||||
&module.specifier,
|
&module.specifier,
|
||||||
|
@ -552,7 +557,6 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
None => specifier.into_owned(),
|
None => specifier.into_owned(),
|
||||||
Some(Module::Wasm(_)) => todo!("@dsherret"),
|
|
||||||
};
|
};
|
||||||
Ok(specifier)
|
Ok(specifier)
|
||||||
}
|
}
|
||||||
|
@ -717,13 +721,19 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
media_type: *media_type,
|
media_type: *media_type,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
|
Some(deno_graph::Module::Wasm(WasmModule {
|
||||||
|
source, specifier, ..
|
||||||
|
})) => Ok(Some(CodeOrDeferredEmit::Code(ModuleCodeStringSource {
|
||||||
|
code: ModuleSourceCode::Bytes(source.clone().into()),
|
||||||
|
found_url: specifier.clone(),
|
||||||
|
media_type: MediaType::Wasm,
|
||||||
|
}))),
|
||||||
Some(
|
Some(
|
||||||
deno_graph::Module::External(_)
|
deno_graph::Module::External(_)
|
||||||
| deno_graph::Module::Node(_)
|
| deno_graph::Module::Node(_)
|
||||||
| deno_graph::Module::Npm(_),
|
| deno_graph::Module::Npm(_),
|
||||||
)
|
)
|
||||||
| None => Ok(None),
|
| None => Ok(None),
|
||||||
Some(deno_graph::Module::Wasm(_)) => todo!("@dsherret"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -675,10 +675,12 @@ impl<'a> DenoCompileBinaryWriter<'a> {
|
||||||
deno_graph::Module::Json(m) => {
|
deno_graph::Module::Json(m) => {
|
||||||
(Some(m.source.as_bytes().to_vec()), m.media_type)
|
(Some(m.source.as_bytes().to_vec()), m.media_type)
|
||||||
}
|
}
|
||||||
|
deno_graph::Module::Wasm(m) => {
|
||||||
|
(Some(m.source.to_vec()), MediaType::Wasm)
|
||||||
|
}
|
||||||
deno_graph::Module::Npm(_)
|
deno_graph::Module::Npm(_)
|
||||||
| deno_graph::Module::Node(_)
|
| deno_graph::Module::Node(_)
|
||||||
| deno_graph::Module::External(_) => (None, MediaType::Unknown),
|
| deno_graph::Module::External(_) => (None, MediaType::Unknown),
|
||||||
deno_graph::Module::Wasm(_) => todo!("@dsherret"),
|
|
||||||
};
|
};
|
||||||
if module.specifier().scheme() == "file" {
|
if module.specifier().scheme() == "file" {
|
||||||
let file_path = deno_path_util::url_to_file_path(module.specifier())?;
|
let file_path = deno_path_util::url_to_file_path(module.specifier())?;
|
||||||
|
|
|
@ -380,10 +380,14 @@ fn get_check_hash(
|
||||||
hasher.write_str(module.specifier.as_str());
|
hasher.write_str(module.specifier.as_str());
|
||||||
hasher.write_str(&module.source);
|
hasher.write_str(&module.source);
|
||||||
}
|
}
|
||||||
|
Module::Wasm(module) => {
|
||||||
|
has_file_to_type_check = true;
|
||||||
|
hasher.write_str(module.specifier.as_str());
|
||||||
|
hasher.write_str(&module.source_dts);
|
||||||
|
}
|
||||||
Module::External(module) => {
|
Module::External(module) => {
|
||||||
hasher.write_str(module.specifier.as_str());
|
hasher.write_str(module.specifier.as_str());
|
||||||
}
|
}
|
||||||
Module::Wasm(_) => todo!("@dsherret"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,11 +442,11 @@ fn get_tsc_roots(
|
||||||
| MediaType::SourceMap
|
| MediaType::SourceMap
|
||||||
| MediaType::Unknown => None,
|
| MediaType::Unknown => None,
|
||||||
},
|
},
|
||||||
|
Module::Wasm(module) => Some((module.specifier.clone(), MediaType::Dmts)),
|
||||||
Module::External(_)
|
Module::External(_)
|
||||||
| Module::Node(_)
|
| Module::Node(_)
|
||||||
| Module::Npm(_)
|
| Module::Npm(_)
|
||||||
| Module::Json(_) => None,
|
| Module::Json(_) => None,
|
||||||
Module::Wasm(_) => todo!("@dsherret"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -446,8 +446,8 @@ impl<'a> GraphDisplayContext<'a> {
|
||||||
let maybe_cache_info = match root {
|
let maybe_cache_info = match root {
|
||||||
Module::Js(module) => module.maybe_cache_info.as_ref(),
|
Module::Js(module) => module.maybe_cache_info.as_ref(),
|
||||||
Module::Json(module) => module.maybe_cache_info.as_ref(),
|
Module::Json(module) => module.maybe_cache_info.as_ref(),
|
||||||
|
Module::Wasm(module) => module.maybe_cache_info.as_ref(),
|
||||||
Module::Node(_) | Module::Npm(_) | Module::External(_) => None,
|
Module::Node(_) | Module::Npm(_) | Module::External(_) => None,
|
||||||
Module::Wasm(_) => todo!("@dsherret"),
|
|
||||||
};
|
};
|
||||||
if let Some(cache_info) = maybe_cache_info {
|
if let Some(cache_info) = maybe_cache_info {
|
||||||
if let Some(local) = &cache_info.local {
|
if let Some(local) = &cache_info.local {
|
||||||
|
@ -469,8 +469,8 @@ impl<'a> GraphDisplayContext<'a> {
|
||||||
let size = match m {
|
let size = match m {
|
||||||
Module::Js(module) => module.size(),
|
Module::Js(module) => module.size(),
|
||||||
Module::Json(module) => module.size(),
|
Module::Json(module) => module.size(),
|
||||||
|
Module::Wasm(module) => module.size(),
|
||||||
Module::Node(_) | Module::Npm(_) | Module::External(_) => 0,
|
Module::Node(_) | Module::Npm(_) | Module::External(_) => 0,
|
||||||
Module::Wasm(_) => todo!("@dsherret"),
|
|
||||||
};
|
};
|
||||||
size as f64
|
size as f64
|
||||||
})
|
})
|
||||||
|
@ -569,8 +569,8 @@ impl<'a> GraphDisplayContext<'a> {
|
||||||
Specifier(_) => match module {
|
Specifier(_) => match module {
|
||||||
Module::Js(module) => Some(module.size() as u64),
|
Module::Js(module) => Some(module.size() as u64),
|
||||||
Module::Json(module) => Some(module.size() as u64),
|
Module::Json(module) => Some(module.size() as u64),
|
||||||
|
Module::Wasm(module) => Some(module.size() as u64),
|
||||||
Module::Node(_) | Module::Npm(_) | Module::External(_) => None,
|
Module::Node(_) | Module::Npm(_) | Module::External(_) => None,
|
||||||
Module::Wasm(_) => todo!("@dsherret"),
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
format!("{} {}", header_text, maybe_size_to_text(maybe_size))
|
format!("{} {}", header_text, maybe_size_to_text(maybe_size))
|
||||||
|
@ -583,8 +583,8 @@ impl<'a> GraphDisplayContext<'a> {
|
||||||
Package(package) => {
|
Package(package) => {
|
||||||
tree_node.children.extend(self.build_npm_deps(package));
|
tree_node.children.extend(self.build_npm_deps(package));
|
||||||
}
|
}
|
||||||
Specifier(_) => {
|
Specifier(_) => match module {
|
||||||
if let Some(module) = module.js() {
|
Module::Js(module) => {
|
||||||
if let Some(types_dep) = &module.maybe_types_dependency {
|
if let Some(types_dep) = &module.maybe_types_dependency {
|
||||||
if let Some(child) =
|
if let Some(child) =
|
||||||
self.build_resolved_info(&types_dep.dependency, true)
|
self.build_resolved_info(&types_dep.dependency, true)
|
||||||
|
@ -596,7 +596,16 @@ impl<'a> GraphDisplayContext<'a> {
|
||||||
tree_node.children.extend(self.build_dep_info(dep));
|
tree_node.children.extend(self.build_dep_info(dep));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
Module::Wasm(module) => {
|
||||||
|
for dep in module.dependencies.values() {
|
||||||
|
tree_node.children.extend(self.build_dep_info(dep));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Module::Json(_)
|
||||||
|
| Module::Npm(_)
|
||||||
|
| Module::Node(_)
|
||||||
|
| Module::External(_) => {}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tree_node
|
tree_node
|
||||||
|
@ -661,7 +670,7 @@ impl<'a> GraphDisplayContext<'a> {
|
||||||
};
|
};
|
||||||
self.build_error_msg(specifier, message.as_ref())
|
self.build_error_msg(specifier, message.as_ref())
|
||||||
}
|
}
|
||||||
ModuleError::ParseErr(_, _) => {
|
ModuleError::ParseErr(_, _) | ModuleError::WasmParseErr(_, _) => {
|
||||||
self.build_error_msg(specifier, "(parsing error)")
|
self.build_error_msg(specifier, "(parsing error)")
|
||||||
}
|
}
|
||||||
ModuleError::UnsupportedImportAttributeType { .. } => {
|
ModuleError::UnsupportedImportAttributeType { .. } => {
|
||||||
|
@ -673,7 +682,6 @@ impl<'a> GraphDisplayContext<'a> {
|
||||||
ModuleError::Missing(_, _) | ModuleError::MissingDynamic(_, _) => {
|
ModuleError::Missing(_, _) | ModuleError::MissingDynamic(_, _) => {
|
||||||
self.build_error_msg(specifier, "(missing)")
|
self.build_error_msg(specifier, "(missing)")
|
||||||
}
|
}
|
||||||
ModuleError::WasmParseErr(_, _) => todo!("@dsherret"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,6 @@ use deno_core::serde_json;
|
||||||
use deno_core::serde_json::json;
|
use deno_core::serde_json::json;
|
||||||
use deno_core::serde_json::Value;
|
use deno_core::serde_json::Value;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_graph::Module;
|
|
||||||
use deno_terminal::colors;
|
use deno_terminal::colors;
|
||||||
use http_body_util::BodyExt;
|
use http_body_util::BodyExt;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -1108,13 +1107,12 @@ fn collect_excluded_module_diagnostics(
|
||||||
let graph_specifiers = graph
|
let graph_specifiers = graph
|
||||||
.modules()
|
.modules()
|
||||||
.filter_map(|m| match m {
|
.filter_map(|m| match m {
|
||||||
deno_graph::Module::Js(_) | deno_graph::Module::Json(_) => {
|
deno_graph::Module::Js(_)
|
||||||
Some(m.specifier())
|
| deno_graph::Module::Json(_)
|
||||||
}
|
| deno_graph::Module::Wasm(_) => Some(m.specifier()),
|
||||||
deno_graph::Module::Npm(_)
|
deno_graph::Module::Npm(_)
|
||||||
| deno_graph::Module::Node(_)
|
| deno_graph::Module::Node(_)
|
||||||
| deno_graph::Module::External(_) => None,
|
| deno_graph::Module::External(_) => None,
|
||||||
Module::Wasm(_) => todo!("@dsherret"),
|
|
||||||
})
|
})
|
||||||
.filter(|s| s.as_str().starts_with(root.as_str()));
|
.filter(|s| s.as_str().starts_with(root.as_str()));
|
||||||
for specifier in graph_specifiers {
|
for specifier in graph_specifiers {
|
||||||
|
|
|
@ -450,6 +450,12 @@ delete Object.prototype.__proto__;
|
||||||
// We specify the resolution mode to be CommonJS for some npm files and this
|
// 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.
|
// diagnostic gets generated even though we're using custom module resolution.
|
||||||
1452,
|
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,
|
||||||
// TS2306: File '.../index.d.ts' is not a module.
|
// TS2306: File '.../index.d.ts' is not a module.
|
||||||
// We get this for `x-typescript-types` declaration files which don't export
|
// We get this for `x-typescript-types` declaration files which don't export
|
||||||
// anything. We prefer to treat these as modules with no exports.
|
// anything. We prefer to treat these as modules with no exports.
|
||||||
|
|
|
@ -650,6 +650,10 @@ fn op_load_inner(
|
||||||
media_type = MediaType::Json;
|
media_type = MediaType::Json;
|
||||||
Some(Cow::Borrowed(&*module.source))
|
Some(Cow::Borrowed(&*module.source))
|
||||||
}
|
}
|
||||||
|
Module::Wasm(module) => {
|
||||||
|
media_type = MediaType::Dts;
|
||||||
|
Some(Cow::Borrowed(&*module.source_dts))
|
||||||
|
}
|
||||||
Module::Npm(_) | Module::Node(_) => None,
|
Module::Npm(_) | Module::Node(_) => None,
|
||||||
Module::External(module) => {
|
Module::External(module) => {
|
||||||
// means it's Deno code importing an npm module
|
// means it's Deno code importing an npm module
|
||||||
|
@ -664,7 +668,6 @@ fn op_load_inner(
|
||||||
&mut is_cjs,
|
&mut is_cjs,
|
||||||
)?))
|
)?))
|
||||||
}
|
}
|
||||||
Module::Wasm(_) => todo!("@dsherret"),
|
|
||||||
}
|
}
|
||||||
} else if let Some(npm) = state
|
} else if let Some(npm) = state
|
||||||
.maybe_npm
|
.maybe_npm
|
||||||
|
@ -890,6 +893,9 @@ fn resolve_graph_specifier_types(
|
||||||
Some(Module::Json(module)) => {
|
Some(Module::Json(module)) => {
|
||||||
Ok(Some((module.specifier.clone(), module.media_type)))
|
Ok(Some((module.specifier.clone(), module.media_type)))
|
||||||
}
|
}
|
||||||
|
Some(Module::Wasm(module)) => {
|
||||||
|
Ok(Some((module.specifier.clone(), MediaType::Dmts)))
|
||||||
|
}
|
||||||
Some(Module::Npm(module)) => {
|
Some(Module::Npm(module)) => {
|
||||||
if let Some(npm) = &state.maybe_npm.as_ref() {
|
if let Some(npm) = &state.maybe_npm.as_ref() {
|
||||||
let package_folder = npm
|
let package_folder = npm
|
||||||
|
@ -929,7 +935,6 @@ fn resolve_graph_specifier_types(
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
Some(Module::Node(_)) | None => Ok(None),
|
Some(Module::Node(_)) | None => Ok(None),
|
||||||
Some(Module::Wasm(_)) => todo!("@dsherret"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1198,7 +1203,7 @@ mod tests {
|
||||||
.context("Unable to get CWD")
|
.context("Unable to get CWD")
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
let mut op_state = OpState::new(None);
|
let mut op_state = OpState::new(None, None);
|
||||||
op_state.put(state);
|
op_state.put(state);
|
||||||
op_state
|
op_state
|
||||||
}
|
}
|
||||||
|
|
|
@ -1086,12 +1086,10 @@ function loadESMFromCJS(module, filename, code) {
|
||||||
module.exports = namespace;
|
module.exports = namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
Module._extensions[".mjs"] = Module._extensions[".mts"] = function (
|
Module._extensions[".mjs"] =
|
||||||
module,
|
Module._extensions[".mts"] =
|
||||||
filename,
|
Module._extensions[".wasm"] =
|
||||||
) {
|
loadESMFromCJS;
|
||||||
loadESMFromCJS(module, filename);
|
|
||||||
};
|
|
||||||
|
|
||||||
function stripBOM(content) {
|
function stripBOM(content) {
|
||||||
if (StringPrototypeCharCodeAt(content, 0) === 0xfeff) {
|
if (StringPrototypeCharCodeAt(content, 0) === 0xfeff) {
|
||||||
|
|
|
@ -78,7 +78,7 @@ pub fn validate_import_attributes_callback(
|
||||||
for (key, value) in attributes {
|
for (key, value) in attributes {
|
||||||
let msg = if key != "type" {
|
let msg = if key != "type" {
|
||||||
Some(format!("\"{key}\" attribute is not supported."))
|
Some(format!("\"{key}\" attribute is not supported."))
|
||||||
} else if value != "json" {
|
} else if value != "json" && value != "$$deno-core-internal-wasm-module" {
|
||||||
Some(format!("\"{value}\" is not a valid module type."))
|
Some(format!("\"{value}\" is not a valid module type."))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -5427,7 +5427,8 @@ fn lsp_code_actions_deno_cache() {
|
||||||
|
|
||||||
let res =
|
let res =
|
||||||
client
|
client
|
||||||
.write_request( "textDocument/codeAction",
|
.write_request(
|
||||||
|
"textDocument/codeAction",
|
||||||
json!({
|
json!({
|
||||||
"textDocument": {
|
"textDocument": {
|
||||||
"uri": "file:///a/file.ts"
|
"uri": "file:///a/file.ts"
|
||||||
|
@ -5453,8 +5454,7 @@ fn lsp_code_actions_deno_cache() {
|
||||||
"only": ["quickfix"]
|
"only": ["quickfix"]
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
)
|
);
|
||||||
;
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
res,
|
res,
|
||||||
json!([{
|
json!([{
|
||||||
|
@ -16516,3 +16516,47 @@ fn lsp_jsdoc_named_example() {
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lsp_wasm_module() {
|
||||||
|
let context = TestContextBuilder::new()
|
||||||
|
.use_temp_cwd()
|
||||||
|
.use_http_server()
|
||||||
|
.build();
|
||||||
|
let mut client = context.new_lsp_command().build();
|
||||||
|
client.initialize_default();
|
||||||
|
client.did_open(json!({
|
||||||
|
"textDocument": {
|
||||||
|
"uri": "file:///a/file.ts",
|
||||||
|
"languageId": "typescript",
|
||||||
|
"version": 1,
|
||||||
|
"text": "import { add } from \"http://localhost:4545/wasm/math.wasm\";\nadd(1, '');\n"
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
client.write_request(
|
||||||
|
"workspace/executeCommand",
|
||||||
|
json!({
|
||||||
|
"command": "deno.cache",
|
||||||
|
"arguments": [[], "file:///a/file.ts"],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let diagnostics = client.read_diagnostics();
|
||||||
|
assert_eq!(
|
||||||
|
json!(diagnostics.all()),
|
||||||
|
json!([
|
||||||
|
{
|
||||||
|
"range": {
|
||||||
|
"start": { "line": 1, "character": 7 },
|
||||||
|
"end": { "line": 1, "character": 9 }
|
||||||
|
},
|
||||||
|
"severity": 1,
|
||||||
|
"code": 2345,
|
||||||
|
"source": "deno-ts",
|
||||||
|
"message": "Argument of type 'string' is not assignable to parameter of type 'number'."
|
||||||
|
}
|
||||||
|
])
|
||||||
|
);
|
||||||
|
client.shutdown();
|
||||||
|
}
|
||||||
|
|
5
tests/specs/check/wasm/__test__.jsonc
Normal file
5
tests/specs/check/wasm/__test__.jsonc
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"args": "check --allow-import main.ts",
|
||||||
|
"output": "check.out",
|
||||||
|
"exitCode": 1
|
||||||
|
}
|
6
tests/specs/check/wasm/check.out
Normal file
6
tests/specs/check/wasm/check.out
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Download http://localhost:4545/wasm/math.wasm
|
||||||
|
Check file:///[WILDLINE]/main.ts
|
||||||
|
error: TS2345 [ERROR]: Argument of type 'string' is not assignable to parameter of type 'number'.
|
||||||
|
console.log(add(1, ""));
|
||||||
|
~~
|
||||||
|
at file:///[WILDLINE]/main.ts:3:20
|
3
tests/specs/check/wasm/main.ts
Normal file
3
tests/specs/check/wasm/main.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { add } from "http://localhost:4545/wasm/math.wasm";
|
||||||
|
|
||||||
|
console.log(add(1, ""));
|
4
tests/specs/doc/wasm/__test__.jsonc
Normal file
4
tests/specs/doc/wasm/__test__.jsonc
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"args": "doc http://localhost:4545/wasm/math.wasm",
|
||||||
|
"output": "doc.out"
|
||||||
|
}
|
21
tests/specs/doc/wasm/doc.out
Normal file
21
tests/specs/doc/wasm/doc.out
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
Download http://localhost:4545/wasm/math.wasm
|
||||||
|
Defined in http://localhost:4545/wasm/math.wasm:2:1
|
||||||
|
|
||||||
|
function add(arg0: number, arg1: number): number
|
||||||
|
|
||||||
|
Defined in http://localhost:4545/wasm/math.wasm:3:1
|
||||||
|
|
||||||
|
function subtract(arg0: number, arg1: number): number
|
||||||
|
|
||||||
|
Defined in http://localhost:4545/wasm/math.wasm:4:22
|
||||||
|
|
||||||
|
const __data_end: number
|
||||||
|
|
||||||
|
Defined in http://localhost:4545/wasm/math.wasm:5:22
|
||||||
|
|
||||||
|
const __heap_base: number
|
||||||
|
|
||||||
|
Defined in http://localhost:4545/wasm/math.wasm:1:22
|
||||||
|
|
||||||
|
const memory: WebAssembly.Memory
|
||||||
|
|
4
tests/specs/info/wasm_module/__test__.jsonc
Normal file
4
tests/specs/info/wasm_module/__test__.jsonc
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"args": "info --allow-import main.js",
|
||||||
|
"output": "main.out"
|
||||||
|
}
|
7
tests/specs/info/wasm_module/main.js
Normal file
7
tests/specs/info/wasm_module/main.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import {
|
||||||
|
add,
|
||||||
|
subtract,
|
||||||
|
} from "http://localhost:4545/wasm/math_with_import.wasm";
|
||||||
|
|
||||||
|
console.log(add(1, 2));
|
||||||
|
console.log(subtract(100, 50));
|
10
tests/specs/info/wasm_module/main.out
Normal file
10
tests/specs/info/wasm_module/main.out
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
Download http://localhost:4545/wasm/math_with_import.wasm
|
||||||
|
Download http://localhost:4545/wasm/math.ts
|
||||||
|
local: [WILDLINE]main.js
|
||||||
|
type: JavaScript
|
||||||
|
dependencies: 2 unique
|
||||||
|
size: [WILDLINE]
|
||||||
|
|
||||||
|
file:///[WILDLINE]/main.js ([WILDLINE])
|
||||||
|
└─┬ http://localhost:4545/wasm/math_with_import.wasm ([WILDLINE])
|
||||||
|
└── http://localhost:4545/wasm/math.ts ([WILDLINE])
|
12
tests/specs/run/wasm_module/cjs_importing/__test__.jsonc
Normal file
12
tests/specs/run/wasm_module/cjs_importing/__test__.jsonc
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"steps": [{
|
||||||
|
"args": "run -A setup.ts",
|
||||||
|
"output": "[WILDCARD]"
|
||||||
|
}, {
|
||||||
|
"args": "run -A --check main.cts",
|
||||||
|
"output": "main.out"
|
||||||
|
}, {
|
||||||
|
"args": "run -A --check main.cjs",
|
||||||
|
"output": "main.out"
|
||||||
|
}]
|
||||||
|
}
|
5
tests/specs/run/wasm_module/cjs_importing/main.cjs
Normal file
5
tests/specs/run/wasm_module/cjs_importing/main.cjs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
// @ts-check
|
||||||
|
const { add, subtract } = require("./math.wasm");
|
||||||
|
|
||||||
|
console.log(add(1, 2));
|
||||||
|
console.log(subtract(9, 3));
|
4
tests/specs/run/wasm_module/cjs_importing/main.cts
Normal file
4
tests/specs/run/wasm_module/cjs_importing/main.cts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import WasmModule = require("./math.wasm");
|
||||||
|
|
||||||
|
console.log(WasmModule.add(1, 2));
|
||||||
|
console.log(WasmModule.subtract(9, 3));
|
3
tests/specs/run/wasm_module/cjs_importing/main.out
Normal file
3
tests/specs/run/wasm_module/cjs_importing/main.out
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Check file:///[WILDLINE]
|
||||||
|
3
|
||||||
|
6
|
BIN
tests/specs/run/wasm_module/cjs_importing/math.wasm
Normal file
BIN
tests/specs/run/wasm_module/cjs_importing/math.wasm
Normal file
Binary file not shown.
4
tests/specs/run/wasm_module/cjs_importing/package.json
Normal file
4
tests/specs/run/wasm_module/cjs_importing/package.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"args": "run -A main.cjs",
|
||||||
|
"output": "main.out"
|
||||||
|
}
|
7
tests/specs/run/wasm_module/cjs_importing/setup.ts
Normal file
7
tests/specs/run/wasm_module/cjs_importing/setup.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
fetch("http://localhost:4545/wasm/math.wasm").then(async (response) => {
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to fetch WASM module: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
using file = Deno.openSync("math.wasm", { write: true, create: true });
|
||||||
|
await response.body!.pipeTo(file.writable);
|
||||||
|
});
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"args": "--allow-import main.js",
|
||||||
|
"output": "main.out",
|
||||||
|
"exitCode": 1
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"lock": false,
|
||||||
|
"scopes": {
|
||||||
|
"http://localhost:4545/wasm/": {
|
||||||
|
// file won't exist
|
||||||
|
"http://localhost:4545/wasm/math.ts": "./local_math.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import {
|
||||||
|
add,
|
||||||
|
subtract,
|
||||||
|
} from "http://localhost:4545/wasm/math_with_import.wasm";
|
||||||
|
|
||||||
|
console.log(add(1, 2));
|
||||||
|
console.log(subtract(100, 50));
|
|
@ -0,0 +1,3 @@
|
||||||
|
Download http://localhost:4545/wasm/math_with_import.wasm
|
||||||
|
error: Module not found "file:///[WILDLINE]/local_math.ts".
|
||||||
|
at http://localhost:4545/wasm/math_with_import.wasm:1:8
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"args": "--allow-import main.js",
|
||||||
|
"output": "main.out",
|
||||||
|
"exitCode": 1
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"lock": false,
|
||||||
|
"scopes": {
|
||||||
|
"http://localhost:4545/wasm/": {
|
||||||
|
"http://localhost:4545/wasm/math.ts": "./local_math.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
export function addTest(a: number, b: number) {
|
||||||
|
return (a + b) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function subtractTest(a: number, b: number) {
|
||||||
|
return (a - b) / 2;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import {
|
||||||
|
add,
|
||||||
|
subtract,
|
||||||
|
} from "http://localhost:4545/wasm/math_with_import.wasm";
|
||||||
|
|
||||||
|
console.log(add(1, 2));
|
||||||
|
console.log(subtract(100, 50));
|
|
@ -0,0 +1,3 @@
|
||||||
|
Download http://localhost:4545/wasm/math_with_import.wasm
|
||||||
|
error: Uncaught SyntaxError: The requested module './math.ts' does not provide an export named 'add'
|
||||||
|
at <anonymous> (http://localhost:4545/wasm/math_with_import.wasm:[WILDLINE])
|
4
tests/specs/run/wasm_module/imports/__test__.jsonc
Normal file
4
tests/specs/run/wasm_module/imports/__test__.jsonc
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"args": "--allow-import main.js",
|
||||||
|
"output": "main.out"
|
||||||
|
}
|
7
tests/specs/run/wasm_module/imports/main.js
Normal file
7
tests/specs/run/wasm_module/imports/main.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import {
|
||||||
|
add,
|
||||||
|
subtract,
|
||||||
|
} from "http://localhost:4545/wasm/math_with_import.wasm";
|
||||||
|
|
||||||
|
console.log(add(1, 2));
|
||||||
|
console.log(subtract(100, 50));
|
4
tests/specs/run/wasm_module/imports/main.out
Normal file
4
tests/specs/run/wasm_module/imports/main.out
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Download http://localhost:4545/wasm/math_with_import.wasm
|
||||||
|
Download http://localhost:4545/wasm/math.ts
|
||||||
|
3
|
||||||
|
50
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"args": "--allow-import main.js",
|
||||||
|
"output": "main.out",
|
||||||
|
"exitCode": 10
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"version": "4",
|
||||||
|
"remote": {
|
||||||
|
"http://localhost:4545/wasm/math.wasm": "c4fdd49432f1517835b93274447890007947f9d30674ab7f1474091860113d95"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
import { add, subtract } from "http://localhost:4545/wasm/math.wasm";
|
||||||
|
|
||||||
|
console.log(add(1, 2));
|
||||||
|
console.log(subtract(100, 50));
|
12
tests/specs/run/wasm_module/integrity_check_failed/main.out
Normal file
12
tests/specs/run/wasm_module/integrity_check_failed/main.out
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
Download http://localhost:4545/wasm/math.wasm
|
||||||
|
error: Integrity check failed for remote specifier. The source code is invalid, as it does not match the expected hash in the lock file.
|
||||||
|
|
||||||
|
Specifier: http://localhost:4545/wasm/math.wasm
|
||||||
|
Actual: d1643d9d4ba8f34ee5198717860cbc629013179addba6d4e347b68eb721c73b4
|
||||||
|
Expected: c4fdd49432f1517835b93274447890007947f9d30674ab7f1474091860113d95
|
||||||
|
|
||||||
|
This could be caused by:
|
||||||
|
* the lock file may be corrupt
|
||||||
|
* the source itself may be corrupt
|
||||||
|
|
||||||
|
Investigate the lockfile; delete it to regenerate the lockfile or --reload to reload the source code from the server.
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"args": "--allow-import main.js",
|
||||||
|
"output": "main.out"
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"lock": false,
|
||||||
|
"scopes": {
|
||||||
|
"http://localhost:4545/wasm/": {
|
||||||
|
"http://localhost:4545/wasm/math.ts": "./local_math.ts"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
export function add(a: number, b: number) {
|
||||||
|
return (a + b) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function subtract(a: number, b: number) {
|
||||||
|
return (a - b) / 2;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import {
|
||||||
|
add,
|
||||||
|
subtract,
|
||||||
|
} from "http://localhost:4545/wasm/math_with_import.wasm";
|
||||||
|
|
||||||
|
console.log(add(1, 2));
|
||||||
|
console.log(subtract(100, 50));
|
|
@ -0,0 +1,3 @@
|
||||||
|
Download http://localhost:4545/wasm/math_with_import.wasm
|
||||||
|
6
|
||||||
|
25
|
4
tests/specs/run/wasm_module/no_imports/__test__.jsonc
Normal file
4
tests/specs/run/wasm_module/no_imports/__test__.jsonc
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"args": "run --allow-import main.ts",
|
||||||
|
"output": "main.out"
|
||||||
|
}
|
3
tests/specs/run/wasm_module/no_imports/main.out
Normal file
3
tests/specs/run/wasm_module/no_imports/main.out
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Download http://localhost:4545/wasm/math.wasm
|
||||||
|
3
|
||||||
|
6
|
4
tests/specs/run/wasm_module/no_imports/main.ts
Normal file
4
tests/specs/run/wasm_module/no_imports/main.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import { add, subtract } from "http://localhost:4545/wasm/math.wasm";
|
||||||
|
|
||||||
|
console.log(add(1, 2));
|
||||||
|
console.log(subtract(8, 2));
|
8
tests/testdata/wasm/math.ts
vendored
Normal file
8
tests/testdata/wasm/math.ts
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// this file is imported by math_with_import.wasm
|
||||||
|
export function add(a: number, b: number) {
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function subtract(a: number, b: number) {
|
||||||
|
return a - b;
|
||||||
|
}
|
BIN
tests/testdata/wasm/math.wasm
vendored
Normal file
BIN
tests/testdata/wasm/math.wasm
vendored
Normal file
Binary file not shown.
BIN
tests/testdata/wasm/math_with_import.wasm
vendored
Normal file
BIN
tests/testdata/wasm/math_with_import.wasm
vendored
Normal file
Binary file not shown.
|
@ -919,6 +919,11 @@ pub fn wildcard_match_detailed(
|
||||||
|
|
||||||
if was_last_wildcard || was_last_wildline || current_text.is_empty() {
|
if was_last_wildcard || was_last_wildline || current_text.is_empty() {
|
||||||
WildcardMatchResult::Success
|
WildcardMatchResult::Success
|
||||||
|
} else if current_text == "\n" {
|
||||||
|
WildcardMatchResult::Fail(
|
||||||
|
"<matched everything>\n!!!! PROBLEM: Missing final newline at end of expected output !!!!"
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
output_lines.push("==== HAD TEXT AT END OF FILE ====".to_string());
|
output_lines.push("==== HAD TEXT AT END OF FILE ====".to_string());
|
||||||
output_lines.push(colors::red(annotate_whitespace(current_text)));
|
output_lines.push(colors::red(annotate_whitespace(current_text)));
|
||||||
|
|
Loading…
Reference in a new issue