|
1 | 1 | #include "HMRSupport.h" |
2 | 2 | #import <Foundation/Foundation.h> |
3 | 3 | #include <algorithm> |
| 4 | +#include <cctype> |
| 5 | +#include <cstring> |
4 | 6 | #include "DevFlags.h" |
5 | 7 |
|
6 | 8 | #include <unordered_map> |
@@ -182,78 +184,38 @@ void InitializeImportMetaHot(v8::Isolate* isolate, |
182 | 184 | std::string originAndPath = (qPos == std::string::npos) ? noHash : noHash.substr(0, qPos); |
183 | 185 | std::string query = (qPos == std::string::npos) ? std::string() : noHash.substr(qPos + 1); |
184 | 186 |
|
185 | | - // Decide behavior based on path prefix |
186 | | - std::string pathOnly = noHash.substr(pathStart, (qPos == std::string::npos) ? std::string::npos : (qPos - pathStart)); |
187 | | - bool isAppMod = pathOnly.find("/ns/m") != std::string::npos; |
188 | | - bool isSfcMod = pathOnly.find("/ns/sfc") != std::string::npos; |
189 | | - bool isSfcAsm = pathOnly.find("/ns/asm") != std::string::npos; |
190 | | - bool isRt = pathOnly.find("/ns/rt") != std::string::npos; |
191 | | - bool isCore = pathOnly.find("/ns/core") != std::string::npos; |
192 | | - |
193 | | - if (query.empty()) return originAndPath; |
194 | | - |
195 | | - if (isAppMod) { |
196 | | - // Treat query params as part of module identity (browser-like), |
197 | | - // but ignore internal `import` markers. |
198 | | - std::vector<std::string> kept; |
199 | | - size_t start = 0; |
200 | | - while (start <= query.size()) { |
201 | | - size_t amp = query.find('&', start); |
202 | | - std::string pair = (amp == std::string::npos) ? query.substr(start) : query.substr(start, amp - start); |
203 | | - if (!pair.empty()) { |
204 | | - size_t eq = pair.find('='); |
205 | | - std::string name = (eq == std::string::npos) ? pair : pair.substr(0, eq); |
206 | | - if (!(name == "import")) kept.push_back(pair); |
| 187 | + // Normalize bridge endpoints to keep a single realm across HMR updates: |
| 188 | + // - /ns/rt/<ver> -> /ns/rt |
| 189 | + // - /ns/core/<ver> -> /ns/core |
| 190 | + // Preserve query params (e.g. /ns/core?p=...) as part of module identity. |
| 191 | + { |
| 192 | + std::string pathOnly = originAndPath.substr(pathStart); |
| 193 | + auto normalizeBridge = [&](const char* needle) { |
| 194 | + size_t nlen = strlen(needle); |
| 195 | + if (pathOnly.compare(0, nlen, needle) != 0) return; |
| 196 | + if (pathOnly.size() == nlen) return; // already canonical |
| 197 | + if (pathOnly.size() <= nlen + 1 || pathOnly[nlen] != '/') return; |
| 198 | + |
| 199 | + // Only normalize exact version segment: /ns/*/<digits> (no further segments) |
| 200 | + size_t i = nlen + 1; |
| 201 | + size_t j = i; |
| 202 | + while (j < pathOnly.size() && std::isdigit(static_cast<unsigned char>(pathOnly[j]))) { |
| 203 | + j++; |
207 | 204 | } |
208 | | - if (amp == std::string::npos) break; |
209 | | - start = amp + 1; |
210 | | - } |
211 | | - if (kept.empty()) return originAndPath; |
212 | | - std::sort(kept.begin(), kept.end()); |
213 | | - std::string rebuilt = originAndPath + "?"; |
214 | | - for (size_t i = 0; i < kept.size(); i++) { |
215 | | - if (i > 0) rebuilt += "&"; |
216 | | - rebuilt += kept[i]; |
217 | | - } |
218 | | - return rebuilt; |
219 | | - } |
| 205 | + if (j == i) return; // no digits |
| 206 | + if (j != pathOnly.size()) return; // has extra path |
220 | 207 |
|
221 | | - if (isRt || isCore) { |
222 | | - std::string canonical = originAndPath; |
223 | | - const char* needle = isRt ? "/ns/rt" : "/ns/core"; |
224 | | - size_t pos = canonical.find(needle); |
225 | | - if (pos != std::string::npos) { |
226 | | - canonical = canonical.substr(0, pos) + std::string(needle); |
227 | | - } |
228 | | - return canonical; |
229 | | - } |
| 208 | + originAndPath = originAndPath.substr(0, pathStart) + std::string(needle); |
| 209 | + pathOnly = originAndPath.substr(pathStart); |
| 210 | + }; |
230 | 211 |
|
231 | | - if (isSfcMod || isSfcAsm) { |
232 | | - std::vector<std::string> keptParams; |
233 | | - size_t startPos = 0; |
234 | | - while (startPos <= query.size()) { |
235 | | - size_t amp = query.find('&', startPos); |
236 | | - std::string pair = (amp == std::string::npos) ? query.substr(startPos) : query.substr(startPos, amp - startPos); |
237 | | - if (!pair.empty()) { |
238 | | - size_t eq = pair.find('='); |
239 | | - std::string name = (eq == std::string::npos) ? pair : pair.substr(0, eq); |
240 | | - if (!(name == "import")) { |
241 | | - keptParams.push_back(pair); |
242 | | - } |
243 | | - } |
244 | | - if (amp == std::string::npos) break; |
245 | | - startPos = amp + 1; |
246 | | - } |
247 | | - if (keptParams.empty()) return originAndPath; |
248 | | - std::string rebuilt = originAndPath + "?"; |
249 | | - for (size_t i = 0; i < keptParams.size(); i++) { |
250 | | - rebuilt += keptParams[i]; |
251 | | - if (i + 1 < keptParams.size()) rebuilt += "&"; |
252 | | - } |
253 | | - return rebuilt; |
| 212 | + normalizeBridge("/ns/rt"); |
| 213 | + normalizeBridge("/ns/core"); |
254 | 214 | } |
255 | 215 |
|
256 | | - // Other URLs: keep all params except Vite's import marker; sort for stability |
| 216 | + if (query.empty()) return originAndPath; |
| 217 | + |
| 218 | + // Keep all params except Vite's import marker; sort for stability. |
257 | 219 | std::vector<std::string> kept; |
258 | 220 | size_t start = 0; |
259 | 221 | while (start <= query.size()) { |
|
0 commit comments