Skip to content

Commit ccd4d46

Browse files
committed
Handle cloudflare: scheeme and no longer rewrite node: scheme
1 parent c09fee7 commit ccd4d46

File tree

9 files changed

+141
-82
lines changed

9 files changed

+141
-82
lines changed

crates/parcel-resolver/src/lib.rs

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ pub enum Resolution {
181181
/// Resolved to a file path.
182182
Path(PathBuf),
183183
/// Resolved to a runtime builtin module.
184-
Builtin(String),
184+
Builtin { scheme: String, module: String },
185185
/// Resolved to an external module that should not be bundled.
186186
External,
187187
/// Resolved to an empty module (e.g. `false` in the package.json#browser field).
@@ -623,11 +623,14 @@ impl<'a> ResolveRequest<'a> {
623623
// Bare specifier.
624624
self.resolve_bare(module, subpath)
625625
}
626-
Specifier::Builtin(builtin) => {
626+
Specifier::Builtin(scheme, module) => {
627627
if let Some(res) = self.resolve_package_aliases_and_tsconfig_paths(self.specifier)? {
628628
return Ok(res);
629629
}
630-
Ok(Resolution::Builtin(builtin.as_ref().to_owned()))
630+
Ok(Resolution::Builtin {
631+
scheme: scheme.as_ref().to_owned(),
632+
module: module.as_ref().to_owned(),
633+
})
631634
}
632635
Specifier::Url(url) => {
633636
if self.specifier_type == SpecifierType::Url {
@@ -2521,15 +2524,21 @@ mod tests {
25212524
.result
25222525
.unwrap()
25232526
.resolution,
2524-
Resolution::Builtin("zlib".into())
2527+
Resolution::Builtin {
2528+
scheme: "".into(),
2529+
module: "zlib".into()
2530+
}
25252531
);
25262532
assert_eq!(
25272533
test_resolver()
25282534
.resolve("node:zlib", &root().join("foo.js"), SpecifierType::Esm)
25292535
.result
25302536
.unwrap()
25312537
.resolution,
2532-
Resolution::Builtin("zlib".into())
2538+
Resolution::Builtin {
2539+
scheme: "node".into(),
2540+
module: "zlib".into()
2541+
}
25332542
);
25342543
assert_eq!(
25352544
test_resolver()
@@ -2541,7 +2550,10 @@ mod tests {
25412550
.result
25422551
.unwrap()
25432552
.resolution,
2544-
Resolution::Builtin("fs/promises".into())
2553+
Resolution::Builtin {
2554+
scheme: "node".into(),
2555+
module: "fs/promises".into()
2556+
}
25452557
);
25462558
assert_eq!(
25472559
test_resolver()
@@ -2553,7 +2565,25 @@ mod tests {
25532565
.result
25542566
.unwrap()
25552567
.resolution,
2556-
Resolution::Builtin("@std/http/file-server".into())
2568+
Resolution::Builtin {
2569+
scheme: "jsr".into(),
2570+
module: "@std/http/file-server".into()
2571+
}
2572+
);
2573+
assert_eq!(
2574+
test_resolver()
2575+
.resolve(
2576+
"cloudflare:workers",
2577+
&root().join("foo.js"),
2578+
SpecifierType::Esm
2579+
)
2580+
.result
2581+
.unwrap()
2582+
.resolution,
2583+
Resolution::Builtin {
2584+
scheme: "cloudflare".into(),
2585+
module: "workers".into()
2586+
}
25572587
);
25582588
}
25592589

@@ -2675,7 +2705,10 @@ mod tests {
26752705
.result
26762706
.unwrap()
26772707
.resolution,
2678-
Resolution::Builtin("zlib".into())
2708+
Resolution::Builtin {
2709+
scheme: "".into(),
2710+
module: "zlib".into()
2711+
}
26792712
);
26802713

26812714
let invalidations = test_resolver()

crates/parcel-resolver/src/specifier.rs

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ pub enum Specifier<'a> {
6363
/// A package specifier and subpath, e.g. 'lodash/clone'.
6464
Package(Cow<'a, str>, Cow<'a, str>),
6565
/// A Node builtin module, e.g. 'path' or 'node:path'.
66-
Builtin(Cow<'a, str>),
66+
Builtin(Cow<'a, str>, Cow<'a, str>),
6767
/// A URL specifier.
6868
Url(&'a str),
6969
}
@@ -118,7 +118,10 @@ impl<'a> Specifier<'a> {
118118
match scheme.as_ref() {
119119
"npm" if flags.contains(Flags::NPM_SCHEME) => {
120120
if BUILTINS.contains(&path) {
121-
return Ok((Specifier::Builtin(Cow::Borrowed(path)), None));
121+
return Ok((
122+
Specifier::Builtin(Cow::Borrowed(""), Cow::Borrowed(path)),
123+
None,
124+
));
122125
}
123126

124127
(
@@ -127,10 +130,11 @@ impl<'a> Specifier<'a> {
127130
)
128131
}
129132
// Treat Deno's "jsr:" dependencies as builtins so they get marked as external.
130-
"node" | "jsr" => {
133+
// Also Cloudflare schemes: https://github.com/cloudflare/workerd/blob/b7bcb543812dfd9fdc0d9b391801ec1bc4f0973a/src/workerd/jsg/commonjs.c%2B%2B#L27
134+
"node" | "jsr" | "cloudflare" | "workerd" => {
131135
// Node does not URL decode or support query params here.
132136
// See https://github.com/nodejs/node/issues/39710.
133-
(Specifier::Builtin(Cow::Borrowed(path)), None)
137+
(Specifier::Builtin(scheme, Cow::Borrowed(path)), None)
134138
}
135139
"file" => (
136140
Specifier::Absolute(Cow::Owned(url_to_path(specifier)?)),
@@ -144,7 +148,10 @@ impl<'a> Specifier<'a> {
144148
let (path, rest) = parse_path(specifier);
145149
if specifier_type == SpecifierType::Esm {
146150
if BUILTINS.contains(&path) {
147-
return Ok((Specifier::Builtin(Cow::Borrowed(path)), None));
151+
return Ok((
152+
Specifier::Builtin(Cow::Borrowed(""), Cow::Borrowed(path)),
153+
None,
154+
));
148155
}
149156

150157
let (query, _) = parse_query(rest);
@@ -159,12 +166,20 @@ impl<'a> Specifier<'a> {
159166
}
160167
}
161168
SpecifierType::Cjs => {
162-
if let Some(node_prefixed) = specifier.strip_prefix("node:") {
163-
return Ok((Specifier::Builtin(Cow::Borrowed(node_prefixed)), None));
169+
if let Some((scheme, module)) = specifier.split_once(':') {
170+
if matches!(scheme, "node" | "jsr" | "cloudflare" | "workerd") {
171+
return Ok((
172+
Specifier::Builtin(Cow::Borrowed(scheme), Cow::Borrowed(module)),
173+
None,
174+
));
175+
}
164176
}
165177

166178
if BUILTINS.contains(&specifier) {
167-
(Specifier::Builtin(Cow::Borrowed(specifier)), None)
179+
(
180+
Specifier::Builtin(Cow::Borrowed(""), Cow::Borrowed(specifier)),
181+
None,
182+
)
168183
} else {
169184
#[cfg(windows)]
170185
if !flags.contains(Flags::ABSOLUTE_SPECIFIERS) {
@@ -200,7 +215,16 @@ impl<'a> Specifier<'a> {
200215
Cow::Owned(res)
201216
}
202217
}
203-
Specifier::Builtin(builtin) => Cow::Borrowed(builtin),
218+
Specifier::Builtin(scheme, builtin) => {
219+
if scheme.is_empty() {
220+
return Cow::Borrowed(builtin);
221+
}
222+
let mut res = String::with_capacity(scheme.len() + builtin.len() + 1);
223+
res.push_str(scheme);
224+
res.push(':');
225+
res.push_str(builtin);
226+
Cow::Owned(res)
227+
}
204228
Specifier::Url(url) => Cow::Borrowed(url),
205229
}
206230
}
@@ -350,7 +374,10 @@ impl<'de> serde::Deserialize<'de> for Specifier<'static> {
350374
Specifier::Package(a, b) => {
351375
Specifier::Package(Cow::Owned(a.into_owned()), Cow::Owned(b.into_owned()))
352376
}
353-
Specifier::Builtin(a) => Specifier::Builtin(Cow::Owned(a.into_owned())),
377+
Specifier::Builtin(scheme, module) => Specifier::Builtin(
378+
Cow::Owned(scheme.into_owned()),
379+
Cow::Owned(module.into_owned()),
380+
),
354381
Specifier::Url(_) => todo!(),
355382
})
356383
.map_err(|_| serde::de::Error::custom("Invalid specifier"))

packages/core/package-manager/src/NodePackageManager.js

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ import Module from 'module';
2323
import path from 'path';
2424
import semver from 'semver';
2525
import logger from '@parcel/logger';
26-
import nullthrows from 'nullthrows';
2726

2827
import {getModuleParts} from '@parcel/utils';
2928
import {getConflictingLocalDependencies} from './utils';
@@ -621,30 +620,36 @@ export class NodePackageManager implements PackageManager {
621620
e.code = 'MODULE_NOT_FOUND';
622621
throw e;
623622
}
624-
let getPkg;
625623
switch (res.resolution.type) {
626-
case 'Path':
627-
getPkg = () => {
628-
let pkgPath = this.fs.findAncestorFile(
629-
['package.json'],
630-
nullthrows(res.resolution.value),
631-
this.projectRoot,
632-
);
633-
return pkgPath
634-
? JSON.parse(this.fs.readFileSync(pkgPath, 'utf8'))
635-
: null;
636-
};
637-
// fallthrough
638-
case 'Builtin':
624+
case 'Path': {
625+
let self = this;
626+
let resolved = res.resolution.value;
639627
return {
640-
resolved: res.resolution.value,
628+
resolved,
641629
invalidateOnFileChange: new Set(res.invalidateOnFileChange),
642630
invalidateOnFileCreate: res.invalidateOnFileCreate,
643631
type: res.moduleType,
644632
get pkg() {
645-
return getPkg();
633+
let pkgPath = self.fs.findAncestorFile(
634+
['package.json'],
635+
resolved,
636+
self.projectRoot,
637+
);
638+
return pkgPath
639+
? JSON.parse(self.fs.readFileSync(pkgPath, 'utf8'))
640+
: null;
646641
},
647642
};
643+
}
644+
case 'Builtin': {
645+
let {scheme, module} = res.resolution.value;
646+
return {
647+
resolved: scheme ? `${scheme}:${module}` : module,
648+
invalidateOnFileChange: new Set(res.invalidateOnFileChange),
649+
invalidateOnFileCreate: res.invalidateOnFileCreate,
650+
type: res.moduleType,
651+
};
652+
}
648653
default:
649654
throw new Error('Unknown resolution type');
650655
}

packages/core/rust/index.js.flow

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export interface ResolveOptions {
4040
}
4141
export type Resolution =
4242
| {|type: 'Path', value: string|}
43-
| {|type: 'Builtin', value: string|}
43+
| {|type: 'Builtin', value: {|scheme: string, module: string|}|}
4444
| {|type: 'External'|}
4545
| {|type: 'Empty'|}
4646
| {|type: 'Global', value: string|};

packages/dev/repl/src/parcel/BrowserPackageManager.js

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -202,31 +202,38 @@ export class BrowserPackageManager implements PackageManager {
202202
e.code = 'MODULE_NOT_FOUND';
203203
throw e;
204204
}
205-
let getPkg;
206205
switch (res.resolution.type) {
207-
case 'Path':
208-
getPkg = () => {
209-
let pkgPath = this.fs.findAncestorFile(
210-
['package.json'],
211-
nullthrows(res.resolution.value),
212-
this.projectRoot,
213-
);
214-
resolved = pkgPath
215-
? JSON.parse(this.fs.readFileSync(pkgPath, 'utf8'))
216-
: null;
217-
};
218-
// fallthrough
219-
case 'Builtin':
206+
case 'Path': {
207+
let self = this;
208+
let resolution = res.resolution.value;
220209
resolved = {
221-
resolved: res.resolution.value,
210+
resolved: resolution,
222211
invalidateOnFileChange: new Set(res.invalidateOnFileChange),
223212
invalidateOnFileCreate: res.invalidateOnFileCreate,
224213
type: res.moduleType,
225214
get pkg() {
226-
return getPkg();
215+
let pkgPath = self.fs.findAncestorFile(
216+
['package.json'],
217+
resolution,
218+
self.projectRoot,
219+
);
220+
return pkgPath
221+
? JSON.parse(self.fs.readFileSync(pkgPath, 'utf8'))
222+
: null;
227223
},
228224
};
229225
break;
226+
}
227+
case 'Builtin': {
228+
let {scheme, module} = res.resolution.value;
229+
resolved = {
230+
resolved: scheme ? `${scheme}:${module}` : module,
231+
invalidateOnFileChange: new Set(res.invalidateOnFileChange),
232+
invalidateOnFileCreate: res.invalidateOnFileCreate,
233+
type: res.moduleType,
234+
};
235+
break;
236+
}
230237
default:
231238
throw new Error('Unknown resolution type');
232239
}

packages/packagers/react-static/src/ReactStaticPackager.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -439,12 +439,14 @@ async function loadBundleUncached(
439439
}
440440

441441
let defaultRequire = Module.createRequire(from);
442-
if (res.resolution.type === 'Builtin') {
443-
return defaultRequire(res.resolution.value);
442+
let resolution = res.resolution;
443+
if (resolution.type === 'Builtin') {
444+
let {scheme, module} = resolution.value;
445+
return defaultRequire(scheme ? `${scheme}:${module}` : module);
444446
}
445447

446-
if (res.resolution.type === 'Path') {
447-
let cacheKey = res.resolution.value + '#' + env;
448+
if (resolution.type === 'Path') {
449+
let cacheKey = resolution.value + '#' + env;
448450
const cachedModule = moduleCache.get(cacheKey);
449451
if (cachedModule) {
450452
return cachedModule.exports;
@@ -455,7 +457,7 @@ async function loadBundleUncached(
455457
return loadAsset(assetId);
456458
}
457459

458-
let filePath = nullthrows(res.resolution.value);
460+
let filePath = resolution.value;
459461
let code = fs.readFileSync(filePath, 'utf8');
460462
let require = (id: string) => {
461463
return loadModule(id, filePath, env);

packages/transformers/js/core/src/dependency_collector.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -347,18 +347,6 @@ impl<'a> DependencyCollector<'a> {
347347
}
348348
}
349349

350-
fn rewrite_require_specifier(node: ast::CallExpr, unresolved_mark: Mark) -> ast::CallExpr {
351-
if let Some(arg) = node.args.first() {
352-
if let Some((value, _)) = match_str(&arg.expr) {
353-
if value.starts_with("node:") {
354-
// create_require will take care of replacing the node: prefix...
355-
return create_require(value, unresolved_mark);
356-
}
357-
}
358-
}
359-
node
360-
}
361-
362350
impl<'a> Fold for DependencyCollector<'a> {
363351
fn fold_module(&mut self, node: ast::Module) -> ast::Module {
364352
let mut res = node.fold_children_with(self);
@@ -889,12 +877,11 @@ impl<'a> Fold for DependencyCollector<'a> {
889877
call.args.truncate(1);
890878

891879
// Track the returned require call to be replaced with a promise chain.
892-
let rewritten_call = rewrite_require_specifier(call, self.unresolved_mark);
893-
self.require_node = Some(rewritten_call.clone());
894-
rewritten_call
880+
self.require_node = Some(call.clone());
881+
call
895882
} else if kind == DependencyKind::Require {
896883
// Don't continue traversing so that the `require` isn't replaced with undefined
897-
rewrite_require_specifier(node, self.unresolved_mark)
884+
node
898885
} else {
899886
node.fold_children_with(self)
900887
}

0 commit comments

Comments
 (0)