main
js 236 lines 5.88 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8 'use strict';
9
10 const url = require('url');
11 const Module = require('module');
12
13 let webpackModuleIdx = 0;
14 let webpackChunkIdx = 0;
15 const webpackServerModules = {};
16 const webpackClientModules = {};
17 const webpackErroredModules = {};
18 const webpackServerMap = {};
19 const webpackClientMap = {};
20 const webpackChunkMap = {};
21 global.__webpack_chunk_load__ = function (id) {
22 return webpackChunkMap[id];
23 };
24 global.__webpack_require__ = function (id) {
25 if (webpackErroredModules[id]) {
26 throw webpackErroredModules[id];
27 }
28 return webpackClientModules[id] || webpackServerModules[id];
29 };
30 global.__webpack_get_script_filename__ = function (id) {
31 return id;
32 };
33
34 const previousCompile = Module.prototype._compile;
35
36 const register = require('react-server-dom-webpack/node-register');
37 // Register node compile
38 register();
39
40 const nodeCompile = Module.prototype._compile;
41
42 if (previousCompile === nodeCompile) {
43 throw new Error(
44 'Expected the Node loader to register the _compile extension',
45 );
46 }
47
48 Module.prototype._compile = previousCompile;
49
50 const Server = require('react-server-dom-webpack/server');
51 const registerClientReference = Server.registerClientReference;
52 const createClientModuleProxy = Server.createClientModuleProxy;
53
54 exports.webpackMap = webpackClientMap;
55 exports.webpackModules = webpackClientModules;
56 exports.webpackServerMap = webpackServerMap;
57 exports.moduleLoading = {
58 prefix: '/',
59 };
60
61 exports.clientModuleError = function clientModuleError(moduleError) {
62 const idx = '' + webpackModuleIdx++;
63 webpackErroredModules[idx] = moduleError;
64 const path = url.pathToFileURL(idx).href;
65 webpackClientMap[path] = {
66 id: idx,
67 chunks: [],
68 name: '*',
69 };
70 const mod = new Module();
71 nodeCompile.call(mod, '"use client"', idx);
72 return mod.exports;
73 };
74
75 exports.clientExports = function clientExports(
76 moduleExports,
77 chunkId,
78 chunkFilename,
79 blockOnChunk,
80 ) {
81 const chunks = [];
82 if (chunkId) {
83 chunks.push(chunkId, chunkFilename);
84
85 if (blockOnChunk) {
86 webpackChunkMap[chunkId] = blockOnChunk;
87 }
88 }
89 const idx = '' + webpackModuleIdx++;
90 webpackClientModules[idx] = moduleExports;
91 const path = url.pathToFileURL(idx).href;
92 webpackClientMap[path] = {
93 id: idx,
94 chunks,
95 name: '*',
96 };
97 // We only add this if this test is testing ESM compat.
98 if ('__esModule' in moduleExports) {
99 webpackClientMap[path + '#'] = {
100 id: idx,
101 chunks,
102 name: '',
103 };
104 }
105 if (typeof moduleExports.then === 'function') {
106 moduleExports.then(
107 asyncModuleExports => {
108 for (const name in asyncModuleExports) {
109 webpackClientMap[path + '#' + name] = {
110 id: idx,
111 chunks,
112 name: name,
113 };
114 }
115 },
116 () => {},
117 );
118 }
119 if ('split' in moduleExports) {
120 // If we're testing module splitting, we encode this name in a separate module id.
121 const splitIdx = '' + webpackModuleIdx++;
122 webpackClientModules[splitIdx] = {
123 s: moduleExports.split,
124 };
125 webpackClientMap[path + '#split'] = {
126 id: splitIdx,
127 chunks,
128 name: 's',
129 };
130 }
131 const mod = new Module();
132 nodeCompile.call(mod, '"use client"', idx);
133 return mod.exports;
134 };
135
136 exports.clientExportsESM = function clientExportsESM(
137 moduleExports,
138 options?: {forceClientModuleProxy?: boolean} = {},
139 ) {
140 const chunks = [];
141 const idx = '' + webpackModuleIdx++;
142 webpackClientModules[idx] = moduleExports;
143 const path = url.pathToFileURL(idx).href;
144
145 const createClientReferencesForExports = ({exports, async}) => {
146 webpackClientMap[path] = {
147 id: idx,
148 chunks,
149 name: '*',
150 async: true,
151 };
152
153 if (options.forceClientModuleProxy) {
154 return createClientModuleProxy(path);
155 }
156
157 if (typeof exports === 'object') {
158 const references = {};
159
160 for (const name in exports) {
161 const id = path + '#' + name;
162 webpackClientMap[path + '#' + name] = {
163 id: idx,
164 chunks,
165 name: name,
166 async,
167 };
168 references[name] = registerClientReference(() => {}, id, name);
169 }
170
171 return references;
172 }
173
174 return registerClientReference(() => {}, path, '*');
175 };
176
177 if (
178 moduleExports &&
179 typeof moduleExports === 'object' &&
180 typeof moduleExports.then === 'function'
181 ) {
182 return moduleExports.then(
183 asyncModuleExports =>
184 createClientReferencesForExports({
185 exports: asyncModuleExports,
186 async: true,
187 }),
188 () => {},
189 );
190 }
191
192 return createClientReferencesForExports({exports: moduleExports});
193 };
194
195 // This tests server to server references. There's another case of client to server references.
196 exports.serverExports = function serverExports(moduleExports, blockOnChunk) {
197 const idx = '' + webpackModuleIdx++;
198 webpackServerModules[idx] = moduleExports;
199 const path = url.pathToFileURL(idx).href;
200
201 const chunks = [];
202 if (blockOnChunk) {
203 const chunkId = webpackChunkIdx++;
204 webpackChunkMap[chunkId] = blockOnChunk;
205 chunks.push(chunkId);
206 }
207 webpackServerMap[path] = {
208 id: idx,
209 chunks: chunks,
210 name: '*',
211 };
212 // We only add this if this test is testing ESM compat.
213 if ('__esModule' in moduleExports) {
214 webpackServerMap[path + '#'] = {
215 id: idx,
216 chunks: [],
217 name: '',
218 };
219 }
220 if ('split' in moduleExports) {
221 // If we're testing module splitting, we encode this name in a separate module id.
222 const splitIdx = '' + webpackModuleIdx++;
223 webpackServerModules[splitIdx] = {
224 s: moduleExports.split,
225 };
226 webpackServerMap[path + '#split'] = {
227 id: splitIdx,
228 chunks: [],
229 name: 's',
230 };
231 }
232 const mod = new Module();
233 mod.exports = moduleExports;
234 nodeCompile.call(mod, '"use server"', idx);
235 return mod.exports;
236 };