Skip to content

Commit

Permalink
Provide the raw specifier for the module fallback service (#2131)
Browse files Browse the repository at this point in the history
  • Loading branch information
jasnell authored May 22, 2024
1 parent 1917675 commit ad19b37
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 22 deletions.
3 changes: 2 additions & 1 deletion src/workerd/io/worker.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,8 @@ class Worker::Api {
kj::StringPtr,
kj::Maybe<kj::String>,
jsg::CompilationObserver&,
jsg::ModuleRegistry::ResolveMethod);
jsg::ModuleRegistry::ResolveMethod,
kj::Maybe<kj::StringPtr>);
virtual void setModuleFallbackCallback(
kj::Function<ModuleFallbackCallback>&& callback) const {
// By default does nothing.
Expand Down
19 changes: 12 additions & 7 deletions src/workerd/jsg/modules.c++
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ v8::MaybeLocal<v8::Module> resolveCallback(v8::Local<v8::Context> context,
kj::Path targetPath = ([&] {
// If the specifier begins with one of our known prefixes, let's not resolve
// it against the referrer.
auto spec = kj::str(specifier);
if (internalOnly ||
spec.startsWith("node:") ||
spec.startsWith("cloudflare:") ||
Expand All @@ -81,7 +80,9 @@ v8::MaybeLocal<v8::Module> resolveCallback(v8::Local<v8::Context> context,
KJ_IF_SOME(resolved, registry->resolve(js, targetPath, ref.specifier,
internalOnly ?
ModuleRegistry::ResolveOption::INTERNAL_ONLY :
ModuleRegistry::ResolveOption::DEFAULT)) {
ModuleRegistry::ResolveOption::DEFAULT,
ModuleRegistry::ResolveMethod::IMPORT,
spec.asPtr())) {
result = resolved.module.getHandle(js);
} else {
// This is a bit annoying. If the module was not found, then
Expand All @@ -92,7 +93,8 @@ v8::MaybeLocal<v8::Module> resolveCallback(v8::Local<v8::Context> context,
// We only need to do this if internalOnly is false.
if (!internalOnly && (spec.startsWith("node:") || spec.startsWith("cloudflare:"))) {
KJ_IF_SOME(resolve, registry->resolve(js, kj::Path::parse(spec), ref.specifier,
ModuleRegistry::ResolveOption::DEFAULT)) {
ModuleRegistry::ResolveOption::DEFAULT,
ModuleRegistry::ResolveMethod::IMPORT, spec.asPtr())) {
result = resolve.module.getHandle(js);
return;
}
Expand Down Expand Up @@ -271,7 +273,8 @@ v8::Local<v8::Value> CommonJsModuleContext::require(jsg::Lock& js, kj::String sp
auto& info = JSG_REQUIRE_NONNULL(
modulesForResolveCallback->resolve(js, targetPath, path,
ModuleRegistry::ResolveOption::DEFAULT,
ModuleRegistry::ResolveMethod::REQUIRE),
ModuleRegistry::ResolveMethod::REQUIRE,
specifier.asPtr()),
Error, "No such module \"", targetPath.toString(), "\".");
// Adding imported from suffix here not necessary like it is for resolveCallback, since we have a
// js stack that will include the parent module's name and location of the failed require().
Expand Down Expand Up @@ -621,7 +624,8 @@ v8::Local<v8::Value> NodeJsModuleContext::require(jsg::Lock& js, kj::String spec
// excluded.
auto& info = JSG_REQUIRE_NONNULL(
modulesForResolveCallback->resolve(js, targetPath, path, resolveOption,
ModuleRegistry::ResolveMethod::REQUIRE),
ModuleRegistry::ResolveMethod::REQUIRE,
specifier.asPtr()),
Error, "No such module \"", targetPath.toString(), "\".");
// Adding imported from suffix here not necessary like it is for resolveCallback, since we have a
// js stack that will include the parent module's name and location of the failed require().
Expand Down Expand Up @@ -703,14 +707,15 @@ kj::Maybe<kj::OneOf<kj::String, ModuleRegistry::ModuleInfo>> tryResolveFromFallb
Lock& js, const kj::Path& specifier,
kj::Maybe<const kj::Path&>& referrer,
CompilationObserver& observer,
ModuleRegistry::ResolveMethod method) {
ModuleRegistry::ResolveMethod method,
kj::Maybe<kj::StringPtr> rawSpecifier) {
auto& isolateBase = IsolateBase::from(js.v8Isolate);
KJ_IF_SOME(fallback, isolateBase.tryGetModuleFallback()) {
kj::Maybe<kj::String> maybeRef;
KJ_IF_SOME(ref, referrer) {
maybeRef = ref.toString(true);
}
return fallback(js, specifier.toString(true), kj::mv(maybeRef), observer, method);
return fallback(js, specifier.toString(true), kj::mv(maybeRef), observer, method, rawSpecifier);
}
return kj::none;
}
Expand Down
32 changes: 20 additions & 12 deletions src/workerd/jsg/modules.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,13 +374,15 @@ class ModuleRegistry {
const kj::Path& specifier,
kj::Maybe<const kj::Path&> referrer = kj::none,
ResolveOption option = ResolveOption::DEFAULT,
ResolveMethod method = ResolveMethod::IMPORT) = 0;
ResolveMethod method = ResolveMethod::IMPORT,
kj::Maybe<kj::StringPtr> rawSpecifier = kj::none) = 0;

virtual kj::Maybe<ModuleRef> resolve(jsg::Lock& js, v8::Local<v8::Module> module) = 0;

virtual Promise<Value> resolveDynamicImport(jsg::Lock& js,
const kj::Path& specifier,
const kj::Path& referrer) = 0;
const kj::Path& referrer,
kj::StringPtr rawSpecifier) = 0;

virtual Value resolveInternalImport(jsg::Lock& js, const kj::StringPtr specifier) = 0;

Expand All @@ -403,7 +405,8 @@ kj::Maybe<kj::OneOf<kj::String, ModuleRegistry::ModuleInfo>> tryResolveFromFallb
Lock& js, const kj::Path& specifier,
kj::Maybe<const kj::Path&>& referrer,
CompilationObserver& observer,
ModuleRegistry::ResolveMethod method);
ModuleRegistry::ResolveMethod method,
kj::Maybe<kj::StringPtr> rawSpecifier);

template <typename TypeWrapper>
class ModuleRegistryImpl final: public ModuleRegistry {
Expand Down Expand Up @@ -556,7 +559,8 @@ class ModuleRegistryImpl final: public ModuleRegistry {
const kj::Path& specifier,
kj::Maybe<const kj::Path&> referrer = kj::none,
ResolveOption option = ResolveOption::DEFAULT,
ResolveMethod method = ResolveMethod::IMPORT) override {
ResolveMethod method = ResolveMethod::IMPORT,
kj::Maybe<kj::StringPtr> rawSpecifier = kj::none) override {
using Key = typename Entry::Key;
if (option == ResolveOption::INTERNAL_ONLY) {
KJ_IF_SOME(entry, entries.find(Key(specifier, Type::INTERNAL))) {
Expand Down Expand Up @@ -587,9 +591,10 @@ class ModuleRegistryImpl final: public ModuleRegistry {
// let's use it to try to resolve. Make sure we're using DEFAULT resolution so BUNDLE-typed
// modules from the fallback service can be used.
option = ResolveOption::DEFAULT;
return resolve(js, specifier.parent().eval(found), referrer, option, method);
return resolve(js, specifier.parent().eval(found), referrer, option, method, rawSpecifier);
}
KJ_IF_SOME(info, tryResolveFromFallbackService(js, specifier, referrer, observer, method)) {
KJ_IF_SOME(info, tryResolveFromFallbackService(js, specifier, referrer, observer,
method, rawSpecifier)) {
// If we resolved a module from the fallback service, we have to be sure
// to add it to the registry...
KJ_SWITCH_ONEOF(info) {
Expand All @@ -615,7 +620,7 @@ class ModuleRegistryImpl final: public ModuleRegistry {
// Make sure we're using DEFAULT resolution so BUNDLE-typed modules from the fallback
// service can be used.
option = ResolveOption::DEFAULT;
return resolve(js, specifier.parent().eval(s), referrer, option, method);
return resolve(js, specifier.parent().eval(s), referrer, option, method, rawSpecifier);
}
}
}
Expand Down Expand Up @@ -645,7 +650,8 @@ class ModuleRegistryImpl final: public ModuleRegistry {

Promise<Value> resolveDynamicImport(jsg::Lock& js,
const kj::Path& specifier,
const kj::Path& referrer) override {
const kj::Path& referrer,
kj::StringPtr rawSpecifier) override {
// Here, we first need to determine if the referrer is a built-in module
// or not. If it is a built-in, then we are only permitted to resolve
// internal modules. If the worker bundle provided an override for the
Expand All @@ -657,7 +663,8 @@ class ModuleRegistryImpl final: public ModuleRegistry {
resolveOption = ModuleRegistry::ResolveOption::INTERNAL_ONLY;
}

KJ_IF_SOME(info, resolve(js, specifier, referrer, resolveOption)) {
KJ_IF_SOME(info, resolve(js, specifier, referrer, resolveOption,
ResolveMethod::IMPORT, rawSpecifier)) {
KJ_IF_SOME(func, dynamicImportHandler) {
auto handler = [&info, isolate = js.v8Isolate]() -> Value {
auto& js = Lock::from(isolate);
Expand All @@ -679,7 +686,8 @@ class ModuleRegistryImpl final: public ModuleRegistry {
Value resolveInternalImport(jsg::Lock& js, const kj::StringPtr specifier) override {
auto specifierPath = kj::Path(specifier);
auto resolveOption = jsg::ModuleRegistry::ResolveOption::INTERNAL_ONLY;
auto maybeModuleInfo = resolve(js, specifierPath, kj::none, resolveOption);
auto maybeModuleInfo = resolve(js, specifierPath, kj::none, resolveOption,
ResolveMethod::IMPORT, specifier);
auto moduleInfo = &KJ_REQUIRE_NONNULL(maybeModuleInfo, "No such module \"", specifier, "\".");
auto handle = moduleInfo->module.getHandle(js);
jsg::instantiateModule(js, handle);
Expand Down Expand Up @@ -823,10 +831,10 @@ v8::MaybeLocal<v8::Promise> dynamicImportCallback(v8::Local<v8::Context> context
}
})();

auto spec = kj::str(specifier);
auto maybeSpecifierPath = ([&]() -> kj::Maybe<kj::Path> {
// If the specifier begins with one of our known prefixes, let's not resolve
// it against the referrer.
auto spec = kj::str(specifier);
if (spec.startsWith("node:") ||
spec.startsWith("cloudflare:") ||
spec.startsWith("workerd:")) {
Expand Down Expand Up @@ -854,7 +862,7 @@ v8::MaybeLocal<v8::Promise> dynamicImportCallback(v8::Local<v8::Context> context

try {
return wrapper.wrap(context, kj::none,
registry->resolveDynamicImport(js, specifierPath, referrerPath));
registry->resolveDynamicImport(js, specifierPath, referrerPath, spec));
} catch (JsExceptionThrown&) {
// If the tryCatch.Exception().IsEmpty() here is true, no JavaScript error
// was scheduled which can happen in a few edge cases. Treat it as if
Expand Down
3 changes: 2 additions & 1 deletion src/workerd/jsg/setup.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ class IsolateBase {
kj::StringPtr,
kj::Maybe<kj::String>,
jsg::CompilationObserver&,
jsg::ModuleRegistry::ResolveMethod);
jsg::ModuleRegistry::ResolveMethod,
kj::Maybe<kj::StringPtr>);
inline void setModuleFallbackCallback(kj::Function<ModuleFallbackCallback>&& callback) {
maybeModuleFallbackCallback = kj::mv(callback);
}
Expand Down
8 changes: 7 additions & 1 deletion src/workerd/server/server.c++
Original file line number Diff line number Diff line change
Expand Up @@ -2715,7 +2715,8 @@ kj::Own<Server::Service> Server::makeWorker(kj::StringPtr name, config::Worker::
kj::StringPtr specifier,
kj::Maybe<kj::String> referrer,
jsg::CompilationObserver& observer,
jsg::ModuleRegistry::ResolveMethod method) mutable
jsg::ModuleRegistry::ResolveMethod method,
kj::Maybe<kj::StringPtr> rawSpecifier) mutable
-> kj::Maybe<kj::OneOf<kj::String, jsg::ModuleRegistry::ModuleInfo>> {
kj::Maybe<kj::String> jsonPayload;
bool redirect = false;
Expand Down Expand Up @@ -2753,6 +2754,11 @@ kj::Own<Server::Service> Server::makeWorker(kj::StringPtr name, config::Worker::
kj::Url::QueryParam { kj::str("referrer"), kj::mv(ref) }
);
}
KJ_IF_SOME(raw, rawSpecifier) {
url.query.add(
kj::Url::QueryParam { kj::str("raw"), kj::str(raw) }
);
}

auto spec = url.toString(kj::Url::HTTP_REQUEST);

Expand Down

0 comments on commit ad19b37

Please sign in to comment.