Skip to content
File

Blob: src/workerd/io/worker-modules.c++

4.6 KB
1#include "worker-modules.h"
2 
3namespace workerd::modules::python {
4kj::Own<api::pyodide::PyodideMetadataReader::State> createPyodideMetadataState(
5 const Worker::Script::ModulesSource& source,
6 api::pyodide::IsWorkerd isWorkerd,
7 api::pyodide::IsTracing isTracing,
8 api::pyodide::SnapshotToDisk snapshotToDisk,
9 api::pyodide::CreateBaselineSnapshot createBaselineSnapshot,
10 PythonSnapshotRelease::Reader pythonRelease,
11 kj::Maybe<kj::Array<kj::byte>> maybeSnapshot,
12 CompatibilityFlags::Reader featureFlags) {
13 auto mainModule = kj::str(source.mainModule);
14 auto modules = source.modules.asPtr();
15 int numFiles = 0;
16 int numRequirements = 0;
17 for (auto& module: modules) {
18 KJ_SWITCH_ONEOF(module.content) {
19 KJ_CASE_ONEOF(content, Worker::Script::TextModule) {
20 numFiles++;
21 }
22 KJ_CASE_ONEOF(content, Worker::Script::DataModule) {
23 numFiles++;
24 }
25 KJ_CASE_ONEOF(content, Worker::Script::WasmModule) {
26 // Not exposed to Python.
27 }
28 KJ_CASE_ONEOF(content, Worker::Script::JsonModule) {
29 numFiles++;
30 }
31 KJ_CASE_ONEOF(content, Worker::Script::EsModule) {
32 // Not exposed to Python.
33 }
34 KJ_CASE_ONEOF(content, Worker::Script::CommonJsModule) {
35 // Not exposed to Python.
36 }
37 KJ_CASE_ONEOF(content, Worker::Script::PythonModule) {
38 numFiles++;
39 }
40 KJ_CASE_ONEOF(content, Worker::Script::PythonRequirement) {
41 numRequirements++;
42 }
43 KJ_CASE_ONEOF(content, Worker::Script::CapnpModule) {
44 // Not exposed to Python.
45 }
46 }
47 }
48 
49 auto names = kj::heapArrayBuilder<kj::String>(numFiles);
50 auto contents = kj::heapArrayBuilder<kj::Array<kj::byte>>(numFiles);
51 auto requirements = kj::heapArrayBuilder<kj::String>(numRequirements);
52 for (auto& module: modules) {
53 KJ_SWITCH_ONEOF(module.content) {
54 KJ_CASE_ONEOF(content, Worker::Script::TextModule) {
55 names.add(kj::str(module.name));
56 contents.add(kj::heapArray(content.body.asBytes()));
57 }
58 KJ_CASE_ONEOF(content, Worker::Script::DataModule) {
59 names.add(kj::str(module.name));
60 contents.add(kj::heapArray(content.body));
61 }
62 KJ_CASE_ONEOF(content, Worker::Script::WasmModule) {
63 // Not exposed to Python.
64 }
65 KJ_CASE_ONEOF(content, Worker::Script::JsonModule) {
66 names.add(kj::str(module.name));
67 contents.add(kj::heapArray(content.body.asBytes()));
68 }
69 KJ_CASE_ONEOF(content, Worker::Script::EsModule) {
70 // Not exposed to Python.
71 }
72 KJ_CASE_ONEOF(content, Worker::Script::CommonJsModule) {
73 // Not exposed to Python.
74 }
75 KJ_CASE_ONEOF(content, Worker::Script::PythonModule) {
76 KJ_REQUIRE(module.name.endsWith(".py"));
77 names.add(kj::str(module.name));
78 contents.add(kj::heapArray(content.body.asBytes()));
79 }
80 KJ_CASE_ONEOF(content, Worker::Script::PythonRequirement) {
81 requirements.add(kj::str(module.name));
82 }
83 KJ_CASE_ONEOF(content, Worker::Script::CapnpModule) {
84 // Not exposeud to Python.
85 }
86 }
87 }
88 
89 auto lock = KJ_ASSERT_NONNULL(workerd::api::pyodide::getPyodideLock(pythonRelease),
90 kj::str("No lock file defined for Python packages release ", pythonRelease.getPackages()));
91 
92 // clang-format off
93 return kj::heap<workerd::api::pyodide::PyodideMetadataReader::State>(
94 kj::mv(mainModule),
95 names.finish(),
96 contents.finish(),
97 requirements.finish(),
98 kj::str(pythonRelease.getPyodide()),
99 kj::str(pythonRelease.getPackages()),
100 kj::mv(lock),
101 isWorkerd,
102 isTracing,
103 snapshotToDisk,
104 createBaselineSnapshot,
105 kj::mv(maybeSnapshot));
106 // clang-format on
107}
108 
109kj::Maybe<kj::Array<kj::byte>> tryGetMetadataSnapshot(
110 const api::pyodide::PythonConfig& pythonConfig, api::pyodide::SnapshotToDisk snapshotToDisk) {
111 kj::Maybe<kj::Array<kj::byte>> memorySnapshot = kj::none;
112 KJ_IF_SOME(snapshot, pythonConfig.loadSnapshotFromDisk) {
113 auto& root = KJ_REQUIRE_NONNULL(pythonConfig.snapshotDirectory);
114 kj::Path path(snapshot);
115 auto maybeFile = root->tryOpenFile(path);
116 if (maybeFile == kj::none) {
117 KJ_FAIL_REQUIRE("Expected to find", snapshot, "in the package cache directory");
118 }
119 memorySnapshot = KJ_REQUIRE_NONNULL(maybeFile)->readAllBytes();
120 }
121 return kj::mv(memorySnapshot);
122}
123 
124jsg::Bundle::Reader retrievePyodideBundle(
125 const api::pyodide::PythonConfig& pyConfig, kj::StringPtr version) {
126 auto result = pyConfig.pyodideBundleManager.getPyodideBundle(version);
127 return KJ_ASSERT_NONNULL(result, "Failed to get Pyodide bundle", version);
128}
129} // namespace workerd::modules::python