diff --git a/Cargo.lock b/Cargo.lock index c45beffc2..605368528 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -801,6 +801,7 @@ dependencies = [ "deno_webgpu", "deno_webidl", "deno_websocket", + "either", "enum-as-inner", "eszip", "event_worker", diff --git a/crates/base/Cargo.toml b/crates/base/Cargo.toml index 0202a4987..df6799596 100644 --- a/crates/base/Cargo.toml +++ b/crates/base/Cargo.toml @@ -80,6 +80,7 @@ reqwest_v011.workspace = true tracing-subscriber = { workspace = true, optional = true, features = ["env-filter", "tracing-log"] } num-traits.workspace = true tempfile.workspace = true +either.workspace = true tls-listener = { version = "0.10", features = ["rustls"] } strum = { version = "0.25", features = ["derive"] } diff --git a/crates/base/src/deno_runtime.rs b/crates/base/src/deno_runtime.rs index f69e887ed..eaee239af 100644 --- a/crates/base/src/deno_runtime.rs +++ b/crates/base/src/deno_runtime.rs @@ -377,6 +377,11 @@ where let is_user_worker = conf.is_user_worker(); let is_some_entry_point = maybe_entrypoint.is_some(); + let maybe_user_conf = conf.as_user_worker(); + let user_context = maybe_user_conf + .and_then(|it| it.context.clone()) + .unwrap_or_default(); + if is_some_entry_point { main_module_url = Url::parse(&maybe_entrypoint.unwrap())?; } @@ -386,7 +391,7 @@ where let mut allow_remote_modules = true; if is_user_worker { - let user_conf = conf.as_user_worker().unwrap(); + let user_conf = maybe_user_conf.unwrap(); net_access_disabled = user_conf.net_access_disabled; allow_remote_modules = user_conf.allow_remote_modules; @@ -514,12 +519,17 @@ where } let has_inspector = maybe_inspector.is_some(); + let need_source_map = user_context + .get("sourceMap") + .and_then(serde_json::Value::as_bool) + .unwrap_or_default(); + let rt_provider = create_module_loader_for_standalone_from_eszip_kind( eszip, base_dir_path.clone(), maybe_import_map, import_map_path, - has_inspector, + has_inspector || need_source_map, ) .await?; @@ -645,7 +655,7 @@ where let beforeunload_mem_threshold = ArcSwapOption::::from_pointee(None); if conf.is_user_worker() { - let conf = conf.as_user_worker().unwrap(); + let conf = maybe_user_conf.unwrap(); let memory_limit_bytes = mib_to_bytes(conf.memory_limit_mb) as usize; beforeunload_mem_threshold.store( @@ -792,14 +802,7 @@ where let extra_context = { let mut context = serde_json::json!(RuntimeContext::get_extra_context()); - json::merge_object( - &mut context, - &conf - .as_user_worker() - .and_then(|it| it.context.clone()) - .map(serde_json::Value::Object) - .unwrap_or_else(|| serde_json::json!({})), - ); + json::merge_object(&mut context, &serde_json::Value::Object(user_context)); context }; diff --git a/crates/base/test_cases/issue-456/index.ts b/crates/base/test_cases/issue-456/index.ts new file mode 100644 index 000000000..6f83123de --- /dev/null +++ b/crates/base/test_cases/issue-456/index.ts @@ -0,0 +1,8 @@ +import { STATUS_CODE } from "jsr:@std/http"; +console.log(STATUS_CODE.Accepted); + +export default { + fetch() { + return new Response("meow"); + } +} \ No newline at end of file diff --git a/crates/base/test_cases/main/index.ts b/crates/base/test_cases/main/index.ts index 0f3eb2b62..2bb9ad6ee 100644 --- a/crates/base/test_cases/main/index.ts +++ b/crates/base/test_cases/main/index.ts @@ -41,6 +41,9 @@ Deno.serve((req: Request) => { const importMapPath = null; const envVarsObj = Deno.env.toObject(); const envVars = Object.keys(envVarsObj).map(k => [k, envVarsObj[k]]); + const context = { + sourceMap: req.headers.get("x-context-source-map") == "true" + }; return await EdgeRuntime.userWorkers.create({ servicePath, @@ -50,7 +53,8 @@ Deno.serve((req: Request) => { cpuTimeHardLimitMs, noModuleCache, importMapPath, - envVars + envVars, + context }); } diff --git a/crates/base/tests/integration_tests.rs b/crates/base/tests/integration_tests.rs index 932b9bffb..3b2c04cc8 100644 --- a/crates/base/tests/integration_tests.rs +++ b/crates/base/tests/integration_tests.rs @@ -2351,6 +2351,24 @@ async fn test_issue_420() { ); } +#[tokio::test] +#[serial] +async fn test_issue_456() { + let tb = TestBedBuilder::new("./test_cases/main").build().await; + let resp = tb + .request(|b| { + b.uri("/issue-456") + .header("x-context-source-map", "true") + .body(Body::empty()) + .context("can't make request") + }) + .await + .unwrap(); + + assert_eq!(resp.status().as_u16(), StatusCode::OK); + tb.exit(Duration::from_secs(TESTBED_DEADLINE_SEC)).await; +} + #[tokio::test] #[serial] async fn test_should_render_detailed_failed_to_create_graph_error() { diff --git a/crates/sb_module_loader/standalone/standalone_module_loader.rs b/crates/sb_module_loader/standalone/standalone_module_loader.rs index b64f2dd7d..e82bbd40f 100644 --- a/crates/sb_module_loader/standalone/standalone_module_loader.rs +++ b/crates/sb_module_loader/standalone/standalone_module_loader.rs @@ -16,6 +16,7 @@ use deno_core::{ModuleSpecifier, RequestedModuleType}; use deno_semver::npm::NpmPackageReqReference; use eszip::deno_graph; use eszip::EszipRelativeFileBaseUrl; +use eszip::ModuleKind; use sb_eszip_shared::AsyncEszipDataRead; use sb_graph::resolver::CliNodeResolver; use sb_graph::resolver::NpmModuleLoader; @@ -41,14 +42,17 @@ impl WorkspaceEszip { if specifier.scheme() == "file" { let specifier_key = EszipRelativeFileBaseUrl::new(&self.root_dir_url).specifier_key(specifier); + let module = self.eszip.ensure_module(&specifier_key)?; let specifier = self.root_dir_url.join(&module.specifier).unwrap(); + Some(WorkspaceEszipModule { specifier, inner: module, }) } else { let module = self.eszip.ensure_module(specifier.as_str())?; + Some(WorkspaceEszipModule { specifier: ModuleSpecifier::parse(&module.specifier).unwrap(), inner: module, @@ -85,6 +89,7 @@ impl ModuleLoader for EmbeddedModuleLoader { kind ))); } + let current_dir = std::env::current_dir().unwrap(); deno_core::resolve_path(".", ¤t_dir)? } else { @@ -122,11 +127,13 @@ impl ModuleLoader for EmbeddedModuleLoader { NodeResolutionMode::Execution, ) .map(|res| res.into_url()), + PackageJsonDepValue::Workspace(version_req) => { let pkg_folder = self .shared .workspace_resolver .resolve_workspace_pkg_json_folder_for_pkg_json_dep(alias, version_req)?; + Ok(self .shared .node_resolver @@ -185,6 +192,7 @@ impl ModuleLoader for EmbeddedModuleLoader { _requested_module_type: RequestedModuleType, ) -> deno_core::ModuleLoadResponse { let include_source_map = self.include_source_map; + if original_specifier.scheme() == "data" { let data_url_text = match deno_graph::source::RawDataUrl::parse(original_specifier) .and_then(|url| url.decode()) @@ -197,6 +205,7 @@ impl ModuleLoader for EmbeddedModuleLoader { )))); } }; + return deno_core::ModuleLoadResponse::Sync(Ok(deno_core::ModuleSource::new( deno_core::ModuleType::JavaScript, ModuleSourceCode::String(data_url_text.into()), @@ -209,11 +218,13 @@ impl ModuleLoader for EmbeddedModuleLoader { let npm_module_loader = self.shared.npm_module_loader.clone(); let original_specifier = original_specifier.clone(); let maybe_referrer = maybe_referrer.cloned(); + return deno_core::ModuleLoadResponse::Async( async move { let code_source = npm_module_loader .load(&original_specifier, maybe_referrer.as_ref()) .await?; + Ok(deno_core::ModuleSource::new_with_redirect( match code_source.media_type { MediaType::Json => ModuleType::Json, @@ -243,37 +254,44 @@ impl ModuleLoader for EmbeddedModuleLoader { let code = module.inner.source().await.ok_or_else(|| { type_error(format!("Module not found: {}", original_specifier)) })?; + let code = arc_u8_to_arc_str(code) .map_err(|_| type_error("Module source is not utf-8"))?; + let source_map = module.inner.source_map().await; let maybe_code_with_source_map = 'scope: { - if !include_source_map { + if !include_source_map || !matches!(module.inner.kind, ModuleKind::JavaScript) { break 'scope code; } let Some(source_map) = source_map else { break 'scope code; }; + if source_map.is_empty() { + break 'scope code; + } let mut src = code.to_string(); - if src.ends_with('\n') { + if !src.ends_with('\n') { src.push('\n'); } - src.push_str("//# sourceMappingURL=data:application/json;base64,"); - base64::prelude::BASE64_STANDARD.encode_string(source_map, &mut src); + const SOURCE_MAP_PREFIX: &str = + "//# sourceMappingURL=data:application/json;base64,"; + src.push_str(SOURCE_MAP_PREFIX); + + base64::prelude::BASE64_STANDARD.encode_string(source_map, &mut src); Arc::from(src) }; + Ok(deno_core::ModuleSource::new_with_redirect( match module.inner.kind { - eszip::ModuleKind::JavaScript => ModuleType::JavaScript, - eszip::ModuleKind::Json => ModuleType::Json, - eszip::ModuleKind::Jsonc => { - return Err(type_error("jsonc modules not supported")) - } - eszip::ModuleKind::OpaqueData => { + ModuleKind::JavaScript => ModuleType::JavaScript, + ModuleKind::Json => ModuleType::Json, + ModuleKind::Jsonc => return Err(type_error("jsonc modules not supported")), + ModuleKind::OpaqueData => { unreachable!(); } },