#pragma once #include #include #include #include #include #include namespace workerd::api { class Fetcher; class DurableObjectClass; // JS stub pointing to a remote Worker loaded using WorkerLoader. This is not a stub for a specific // entrypoint, but instead the entire Worker, allowing the caller to call any entrypoint (and // specify arbitrary props). class WorkerStub: public jsg::Object { public: WorkerStub(IoOwn channel): channel(kj::mv(channel)) {} struct EntrypointOptions { jsg::Optional> props; jsg::Optional limits; JSG_STRUCT(props, limits); }; jsg::Ref getEntrypoint(jsg::Lock& js, jsg::Optional> name, jsg::Optional options); jsg::Ref getDurableObjectClass(jsg::Lock& js, jsg::Optional> name, jsg::Optional options); JSG_RESOURCE_TYPE(WorkerStub, CompatibilityFlags::Reader flags) { JSG_METHOD(getEntrypoint); JSG_METHOD(getDurableObjectClass); JSG_TS_OVERRIDE({ getEntrypoint( name?: string, options?: WorkerStubEntrypointOptions): Fetcher; getDurableObjectClass( name?: string, options?: WorkerStubEntrypointOptions): DurableObjectClass; }); } private: IoOwn channel; }; // JS interface for worker loader binding. class WorkerLoader: public jsg::Object { public: // Create a WorkerLoader backed by the given I/O channel. // // `compatDateValidation` will differ between workerd vs. production. explicit WorkerLoader(uint channel, CompatibilityDateValidation compatDateValidation) : channel(channel), compatDateValidation(compatDateValidation) {} struct Module { // Exactly one must be filled in. jsg::Optional js; // ES module jsg::Optional cjs; // Common JS module jsg::Optional text; // text blob, imports as a string jsg::Optional> data; // byte blob, imports as ArrayBuffer jsg::Optional json; // arbitrary JS value, will be serialized to JSON // and then parsed again when imported jsg::Optional py; // Python module jsg::Optional> wasm; // compiled WASM module JSG_STRUCT(js, cjs, text, data, json, py, wasm); // HACK: When we serialize the JSON in extractSource() we need to place the owned kj::String // somewhere since Worker::Script::Source only gets a kj::StringPtr. kj::Maybe serializedJson; }; struct WorkerCode { kj::String compatibilityDate; jsg::Optional> compatibilityFlags; jsg::Optional allowExperimental = false; jsg::Optional limits; kj::String mainModule; // Modules are specified as an object mapping names to content. If the content is just a // string, an ES module is assumed. If it's an object, the type of module is determined // based on which property is set. jsg::Dict> modules; // Any RPC-serializable value! jsg::Optional> env; // `Fetcher` (e.g. service binding) representing the loaded worker's global outbound. // // If omitted, inherit the current worker's global outbound. // // If `null`, block the global outbound (all requests throw errors). jsg::Optional>> globalOutbound; // Specify tail workers. jsg::Optional>> tails; jsg::Optional>> streamingTails; // TODO(someday): cache API outbound? JSG_STRUCT(compatibilityDate, compatibilityFlags, allowExperimental, limits, mainModule, modules, env, globalOutbound, tails, streamingTails); }; jsg::Ref get( jsg::Lock& js, kj::Maybe name, jsg::Function()> getCode); // Shortcut for `get(null, () => code)`. jsg::Ref load(jsg::Lock& js, WorkerCode code); JSG_RESOURCE_TYPE(WorkerLoader) { JSG_METHOD(get); JSG_METHOD(load); JSG_TS_ROOT(); } private: uint channel; CompatibilityDateValidation compatDateValidation; static DynamicWorkerSource toDynamicWorkerSource(jsg::Lock& js, IoContext& ioctx, CompatibilityDateValidation compatDateValidation, WorkerCode code); static Worker::Script::Source extractSource(jsg::Lock& js, WorkerCode& code); static kj::Own extractCompatFlags( jsg::Lock& js, WorkerCode& code, CompatibilityDateValidation compatDateValidation); kj::Promise> startWorker( Worker::Script::Source extractedSource, CompatibilityFlags::Reader compatibilityFlags); }; #define EW_WORKER_LOADER_ISOLATE_TYPES \ api::WorkerStub, api::WorkerStub::EntrypointOptions, api::WorkerLoader, \ api::WorkerLoader::Module, api::WorkerLoader::WorkerCode, workerd::ResourceLimits } // namespace workerd::api