Skip to content

Commit e29c9c0

Browse files
authored
fix: make can specify no_npm when creating a user worker in main worker (#631)
* fix: make can specify `no_npm` when creating a user worker in main worker * chore: add an integration test
1 parent 998284f commit e29c9c0

File tree

12 files changed

+114
-0
lines changed

12 files changed

+114
-0
lines changed

crates/base/src/runtime/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ where
470470
mut conf,
471471
service_path,
472472
no_module_cache,
473+
no_npm,
473474
env_vars,
474475
maybe_eszip,
475476
maybe_entrypoint,
@@ -584,6 +585,8 @@ where
584585
if let Some(module_url) = main_module_url.as_ref() {
585586
builder.set_entrypoint(Some(module_url.to_file_path().unwrap()));
586587
}
588+
builder.set_no_npm(no_npm);
589+
587590
emitter_factory.set_deno_options(builder.build()?);
588591

589592
let deno_options = emitter_factory.deno_options()?;
@@ -2465,6 +2468,7 @@ mod test {
24652468
maybe_module_code: None,
24662469

24672470
no_module_cache: false,
2471+
no_npm: None,
24682472
env_vars: env_vars.unwrap_or_default(),
24692473

24702474
static_patterns,
@@ -2558,6 +2562,7 @@ mod test {
25582562
WorkerContextInitOpts {
25592563
service_path: PathBuf::from("./test_cases/"),
25602564
no_module_cache: false,
2565+
no_npm: None,
25612566
env_vars: Default::default(),
25622567
timing: None,
25632568
maybe_eszip: None,
@@ -2626,6 +2631,7 @@ mod test {
26262631
WorkerContextInitOpts {
26272632
service_path: PathBuf::from("./test_cases/"),
26282633
no_module_cache: false,
2634+
no_npm: None,
26292635
env_vars: Default::default(),
26302636
timing: None,
26312637
maybe_eszip: Some(EszipPayloadKind::VecKind(eszip_code)),
@@ -2714,6 +2720,7 @@ mod test {
27142720
WorkerContextInitOpts {
27152721
service_path,
27162722
no_module_cache: false,
2723+
no_npm: None,
27172724
env_vars: Default::default(),
27182725
timing: None,
27192726
maybe_eszip: Some(EszipPayloadKind::VecKind(eszip_code)),

crates/base/src/utils/test_utils.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ impl TestBedBuilder {
242242
.init_opts(WorkerContextInitOpts {
243243
service_path: self.main_service_path,
244244
no_module_cache: false,
245+
no_npm: None,
245246
env_vars: std::env::vars().collect(),
246247
timing: None,
247248
maybe_eszip: None,

crates/base/src/worker/pool.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,7 @@ impl WorkerPool {
391391
let WorkerContextInitOpts {
392392
service_path,
393393
no_module_cache,
394+
no_npm,
394395
env_vars,
395396
conf,
396397
maybe_eszip,
@@ -408,6 +409,7 @@ impl WorkerPool {
408409
WorkerContextInitOpts {
409410
service_path,
410411
no_module_cache,
412+
no_npm,
411413
env_vars,
412414
timing: None,
413415
conf,

crates/base/src/worker/worker_surface_creation.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -630,6 +630,7 @@ impl MainWorkerSurfaceBuilder {
630630
inner.set_init_opts(Some(WorkerContextInitOpts {
631631
service_path,
632632
no_module_cache: no_module_cache.unwrap_or(flags.no_module_cache),
633+
no_npm: None,
633634

634635
timing: None,
635636
maybe_eszip,
@@ -783,6 +784,7 @@ impl EventWorkerSurfaceBuilder {
783784
inner.set_init_opts(Some(WorkerContextInitOpts {
784785
service_path,
785786
no_module_cache: no_module_cache.unwrap_or(flags.no_module_cache),
787+
no_npm: None,
786788

787789
env_vars: std::env::vars().collect(),
788790
timing: None,

crates/base/test_cases/main/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,13 @@ Deno.serve(async (req: Request) => {
6565
"x-cpu-time-hard-limit-ms",
6666
10 * 60 * 1000,
6767
);
68+
const noNpm = parseIntFromHeadersOrDefault(
69+
req,
70+
"x-no-npm",
71+
void 0,
72+
) === 1
73+
? true
74+
: null;
6875
const noModuleCache = false;
6976
const envVarsObj = Deno.env.toObject();
7077
const envVars = Object.keys(envVarsObj).map((k) => [k, envVarsObj[k]]);
@@ -87,6 +94,7 @@ Deno.serve(async (req: Request) => {
8794
cpuTimeSoftLimitMs,
8895
cpuTimeHardLimitMs,
8996
noModuleCache,
97+
noNpm,
9098
envVars,
9199
context,
92100
});
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import isEven from "npm:is-even";
2+
console.log(isEven);
3+
Deno.serve(() => new Response());
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "meow",
3+
"workspaces": []
4+
}

crates/base/tests/eszip_migration.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ where
123123
.init_opts(WorkerContextInitOpts {
124124
service_path: PathBuf::from("meow"),
125125
no_module_cache: false,
126+
no_npm: None,
126127
// XXX: This seems insufficient as it may rely on the env contained in
127128
// Edge Functions' metadata.
128129
env_vars: std::env::vars().collect(),

crates/base/tests/integration_tests.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use base::utils::test_utils::create_test_user_worker;
2929
use base::utils::test_utils::ensure_npm_package_installed;
3030
use base::utils::test_utils::test_user_runtime_opts;
3131
use base::utils::test_utils::test_user_worker_pool_policy;
32+
use base::utils::test_utils::TestBed;
3233
use base::utils::test_utils::TestBedBuilder;
3334
use base::utils::test_utils::{self};
3435
use base::worker;
@@ -212,6 +213,7 @@ async fn test_not_trigger_pku_sigsegv_due_to_jit_compilation_non_cli() {
212213
.init_opts(WorkerContextInitOpts {
213214
service_path: "./test_cases/slow_resp".into(),
214215
no_module_cache: false,
216+
no_npm: None,
215217
env_vars: HashMap::new(),
216218
timing: None,
217219
maybe_eszip: None,
@@ -371,6 +373,7 @@ async fn test_main_worker_boot_error() {
371373
.init_opts(WorkerContextInitOpts {
372374
service_path: "./test_cases/meow".into(),
373375
no_module_cache: false,
376+
no_npm: None,
374377
env_vars: HashMap::new(),
375378
timing: None,
376379
maybe_eszip: None,
@@ -494,6 +497,7 @@ async fn test_main_worker_user_worker_mod_evaluate_exception() {
494497
.init_opts(WorkerContextInitOpts {
495498
service_path: "./test_cases/main".into(),
496499
no_module_cache: false,
500+
no_npm: None,
497501
env_vars: HashMap::new(),
498502
timing: None,
499503
maybe_eszip: None,
@@ -877,6 +881,7 @@ async fn test_worker_boot_invalid_imports() {
877881
let opts = WorkerContextInitOpts {
878882
service_path: "./test_cases/invalid_imports".into(),
879883
no_module_cache: false,
884+
no_npm: None,
880885
env_vars: HashMap::new(),
881886
timing: None,
882887
maybe_eszip: None,
@@ -905,6 +910,7 @@ async fn test_worker_boot_with_0_byte_eszip() {
905910
let opts = WorkerContextInitOpts {
906911
service_path: "./test_cases/meow".into(),
907912
no_module_cache: false,
913+
no_npm: None,
908914
env_vars: HashMap::new(),
909915
timing: None,
910916
maybe_eszip: Some(EszipPayloadKind::VecKind(vec![])),
@@ -932,6 +938,7 @@ async fn test_worker_boot_with_invalid_entrypoint() {
932938
let opts = WorkerContextInitOpts {
933939
service_path: "./test_cases/meow".into(),
934940
no_module_cache: false,
941+
no_npm: None,
935942
env_vars: HashMap::new(),
936943
timing: None,
937944
maybe_eszip: None,
@@ -4095,6 +4102,80 @@ async fn test_user_workers_cleanup_idle_workers() {
40954102
unreachable!("test failed");
40964103
}
40974104

4105+
#[tokio::test]
4106+
#[serial]
4107+
async fn test_no_npm() {
4108+
async fn send_it(
4109+
no_npm: bool,
4110+
tx: mpsc::UnboundedSender<WorkerEventWithMetadata>,
4111+
) -> (TestBed, u16) {
4112+
let tb = TestBedBuilder::new("./test_cases/main")
4113+
.with_per_worker_policy(None)
4114+
.with_worker_event_sender(Some(tx))
4115+
.build()
4116+
.await;
4117+
4118+
let resp = tb
4119+
.request(|mut b| {
4120+
b = b.uri("/npm-import-with-package-json");
4121+
if no_npm {
4122+
b = b.header("x-no-npm", HeaderValue::from_static("1"))
4123+
}
4124+
b.body(Body::empty()).context("can't make request")
4125+
})
4126+
.await
4127+
.unwrap();
4128+
4129+
(tb, resp.status().as_u16())
4130+
}
4131+
4132+
{
4133+
// Since `noNpm` is configured, it will not discover package.json, and
4134+
// `npm:is-even` will resolve normally using Deno's original module
4135+
// resolution method.
4136+
let (tx, mut rx) = mpsc::unbounded_channel();
4137+
let (tb, status_code) = send_it(true, tx).await;
4138+
4139+
assert_eq!(status_code, StatusCode::OK);
4140+
4141+
rx.close();
4142+
tb.exit(Duration::from_secs(TESTBED_DEADLINE_SEC)).await;
4143+
}
4144+
{
4145+
// Note that `noNpm` is not set this time. In this case, it will try to
4146+
// discover package.json and will eventually find it.
4147+
//
4148+
// This causes it to switch to Byonm mode and try to resolve modules from
4149+
// the adjacent node_modules/.
4150+
//
4151+
// However, since node_modules/ does not exist anywhere, the attempt to
4152+
// resolve `npm:is-even` will fail.
4153+
let (tx, mut rx) = mpsc::unbounded_channel();
4154+
let (tb, status_code) = send_it(false, tx).await;
4155+
4156+
assert_eq!(status_code, StatusCode::INTERNAL_SERVER_ERROR);
4157+
4158+
rx.close();
4159+
tb.exit(Duration::from_secs(TESTBED_DEADLINE_SEC)).await;
4160+
4161+
while let Some(ev) = rx.recv().await {
4162+
let WorkerEvents::BootFailure(ev) = ev.event else {
4163+
continue;
4164+
};
4165+
4166+
assert!(ev.msg.starts_with(
4167+
"worker boot error: failed to bootstrap runtime: failed to create the \
4168+
graph: Could not find a matching package for 'npm:is-even' in the node_modules \
4169+
directory."
4170+
));
4171+
4172+
return;
4173+
}
4174+
4175+
unreachable!("test failed");
4176+
}
4177+
}
4178+
40984179
#[derive(Deserialize)]
40994180
struct ErrorResponsePayload {
41004181
msg: String,

ext/workers/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ impl Default for Timing {
256256
pub struct WorkerContextInitOpts {
257257
pub service_path: PathBuf,
258258
pub no_module_cache: bool,
259+
pub no_npm: Option<bool>,
259260
pub env_vars: HashMap<String, String>,
260261
pub conf: WorkerRuntimeOpts,
261262
pub static_patterns: Vec<String>,

0 commit comments

Comments
 (0)