Skip to content

Commit 51b6306

Browse files
ci-bothsy822
authored andcommitted
wip: add comments for reviewer
1 parent d1401c7 commit 51b6306

File tree

5 files changed

+36
-35
lines changed

5 files changed

+36
-35
lines changed

apps/remix-ide/src/app/editor/editor.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,7 @@ export default class Editor extends Plugin {
283283
console.log(`[DIAGNOSE-LIBS] Files added. Total extra libs now: ${Object.keys(tsDefaults.getExtraLibs()).length}.`)
284284
}
285285

286+
// Called on every editor content change to parse import statements and trigger type loading.
286287
async _onChange (file) {
287288
this.triggerEvent('didChangeFile', [file])
288289

@@ -312,15 +313,20 @@ export default class Editor extends Plugin {
312313

313314
console.log('[DIAGNOSE] New base packages for analysis:', newBasePackages)
314315

316+
// Temporarily disable type checking during type loading to prevent error flickering.
315317
this.beginTypesBatch()
316318

319+
// [Phase 1: Fast Feedback]
320+
// Add temporary type definitions (shims) first to immediately remove red underlines on import statements.
317321
uniqueImports.forEach(pkgImport => {
318322
this.addShimForPackage(pkgImport)
319323
})
320324

321325
this.updateTsCompilerOptions()
322326
console.log('[DIAGNOSE] Shims added. Red lines should disappear.')
323327

328+
// [Phase 2: Deep Analysis]
329+
// In the background, fetch the actual type files to enable autocompletion.
324330
await Promise.all(newBasePackages.map(async (basePackage) => {
325331
this.processedPackages.add(basePackage)
326332

@@ -329,8 +335,10 @@ export default class Editor extends Plugin {
329335
const result = await startTypeLoadingProcess(basePackage)
330336
if (result && result.libs && result.libs.length > 0) {
331337
console.log(`[DIAGNOSE-DEEP-PASS] "${basePackage}" deep pass complete. Adding ${result.libs.length} files.`)
338+
// Add all fetched type files to Monaco.
332339
this.addExtraLibs(result.libs)
333340

341+
// Update path mappings so TypeScript can find the types.
334342
if (result.subpathMap) {
335343
for (const [subpath, virtualPath] of Object.entries(result.subpathMap)) {
336344
this.tsModuleMappings[subpath] = [virtualPath]
@@ -341,19 +349,23 @@ export default class Editor extends Plugin {
341349
}
342350
this.tsModuleMappings[`${basePackage}/*`] = [`${basePackage}/*`]
343351

352+
// Remove the temporary shims now that the real types are loaded.
344353
uniqueImports
345354
.filter(p => getBasePackage(p) === basePackage)
346355
.forEach(p => this.removeShimsForPackage(p))
347356

348357
} else {
358+
// Shim will remain if no types are found.
349359
console.warn(`[DIAGNOSE-DEEP-PASS] No types found for "${basePackage}". Shim will remain.`)
350360
}
351361
} catch (e) {
362+
// Crawler can fail, but we don't want to crash the whole process.
352363
console.error(`[DIAGNOSE-DEEP-PASS] Crawler failed for "${basePackage}":`, e)
353364
}
354365
}))
355366

356367
console.log('[DIAGNOSE] All processes finished.')
368+
// After all type loading is complete, re-enable type checking and apply the final state.
357369
this.endTypesBatch()
358370

359371
} catch (error) {

apps/remix-ide/src/app/editor/type-fetcher.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ function normalizeBareSpecifier(p: string): string {
2525
return p.split('/')[0]
2626
}
2727

28+
// Function to generate @types package names, includes logic to prevent infinite recursion.
2829
function toTypesScopedName(pkg: string): string {
2930
if (pkg.startsWith('@types/')) return pkg
3031
if (pkg.startsWith('@')) return '@types/' + pkg.slice(1).replace('/', '__')
@@ -45,11 +46,13 @@ async function fetchJson<T = any>(url: string): Promise<T> {
4546
return res.json()
4647
}
4748

49+
// Guesses potential type definition file (.d.ts) paths from a JS file path.
4850
function guessDtsFromJs(jsPath: string): string[] {
4951
const base = stripJsLike(jsPath)
5052
return [`${base}.d.ts`, `${base}.ts`, `${base}/index.d.ts`, `${base}/index.ts`]
5153
}
5254

55+
// Analyzes the 'exports' field of package.json to create a map of subpaths to their type file URLs.
5356
function buildExportTypeMap(pkgName: string, pkgJson: PackageJson): Record<string, string[]> {
5457
const map: Record<string, string[]> = {}
5558
const base = `${CDN_BASE}${pkgName}/`
@@ -68,6 +71,7 @@ function buildExportTypeMap(pkgName: string, pkgJson: PackageJson): Record<strin
6871
}
6972
}
7073
}
74+
// Fallback to 'types'/'typings' field if 'exports' is missing or has no main '.' path defined.
7175
if (!map['.'] && (pkgJson.types || pkgJson.typings)) {
7276
push('.', pkgJson.types || pkgJson.typings)
7377
}
@@ -83,6 +87,7 @@ async function tryFetchOne(urls: string[]): Promise<ResolveResult | null> {
8387
return null
8488
}
8589

90+
// A crawler that recursively follows imports/exports within a type definition file (.d.ts).
8691
async function crawl(entryUrl: string, pkgName: string, visited: Set<string>, enqueuePackage: (name: string) => void): Promise<Library[]> {
8792
if (visited.has(entryUrl)) return []
8893
visited.add(entryUrl)
@@ -97,13 +102,16 @@ async function crawl(entryUrl: string, pkgName: string, visited: Set<string>, en
97102
const crawlNext = (nextUrl: string) => {
98103
if (!visited.has(nextUrl)) subPromises.push(crawl(nextUrl, pkgName, visited, enqueuePackage))
99104
}
105+
// Handles triple-slash directives like '/// <reference ... />'.
100106
for (const m of content.matchAll(TRIPLE_SLASH_REF_RE)) crawlNext(new URL(m[1], finalUrl).href)
101107
for (const m of content.matchAll(IMPORT_ANY_RE)) {
102108
const spec = (m[1] || m[2] || m[3] || '').trim()
103109
if (!spec) continue
110+
// Continues crawling for relative path imports, and queues up external package imports.
104111
if (isRelative(spec)) crawlNext(new URL(spec, finalUrl).href)
105112
else {
106113
const bare = normalizeBareSpecifier(spec)
114+
// Ignores Node.js built-in modules that use the 'node:' protocol.
107115
if (bare && !bare.startsWith('node:')) enqueuePackage(bare)
108116
}
109117
}
@@ -113,11 +121,13 @@ async function crawl(entryUrl: string, pkgName: string, visited: Set<string>, en
113121
return out
114122
}
115123

124+
// Main function for the type loading process. Fetches type files for a package and all its dependencies.
116125
export async function startTypeLoadingProcess(packageName: string): Promise<{ mainVirtualPath: string; libs: Library[]; subpathMap: Record<string, string> } | void> {
117126
const visitedPackages = new Set<string>()
118127
const collected: Library[] = []
119128
const subpathMap: Record<string, string> = {}
120129

130+
// An inner function that recursively loads packages.
121131
async function loadPackage(pkgNameToLoad: string) {
122132
if (visitedPackages.has(pkgNameToLoad)) return
123133
visitedPackages.add(pkgNameToLoad)
@@ -128,12 +138,14 @@ export async function startTypeLoadingProcess(packageName: string): Promise<{ ma
128138
pkgJson = await fetchJson<PackageJson>(pkgJsonUrl)
129139
} catch (e) {
130140
console.log(`- Package '${pkgNameToLoad}' not found. Attempting @types fallback.`)
141+
// If the package is not found, attempt to find its @types equivalent.
131142
try { await loadPackage(toTypesScopedName(pkgNameToLoad)) } catch (ee) {}
132143
return
133144
}
134145

135146
const exportMap = buildExportTypeMap(pkgNameToLoad, pkgJson)
136147

148+
// If the package is found but contains no type information, attempt the @types fallback.
137149
if (Object.keys(exportMap).length === 0) {
138150
console.log(`- No type declarations in '${pkgNameToLoad}'. Attempting @types fallback.`)
139151
try { await loadPackage(toTypesScopedName(pkgNameToLoad)) } catch (ee) {}
@@ -145,6 +157,7 @@ export async function startTypeLoadingProcess(packageName: string): Promise<{ ma
145157
const enqueuePackage = (p: string) => { if (!visitedPackages.has(p)) pendingDependencies.add(p) }
146158

147159
const crawlPromises: Promise<Library[]>[] = []
160+
// Crawl all entry points of the package to gather complete type information.
148161
for (const [subpath, urls] of Object.entries(exportMap)) {
149162
const entryPointUrl = urls[0]
150163
if (entryPointUrl) {
@@ -157,6 +170,7 @@ export async function startTypeLoadingProcess(packageName: string): Promise<{ ma
157170
const libsArrays = await Promise.all(crawlPromises)
158171
libsArrays.forEach(libs => collected.push(...libs))
159172

173+
// Recursively load any discovered dependency packages.
160174
if (pendingDependencies.size > 0) {
161175
console.log(`- Found dependencies for '${pkgNameToLoad}': ${Array.from(pendingDependencies).join(', ')}`)
162176
await Promise.all(Array.from(pendingDependencies).map(loadPackage))

apps/remix-ide/src/app/plugins/script-runner-bridge.tsx

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,34 +28,23 @@ const configFileName = 'remix.config.json'
2828
let baseUrl = 'https://remix-project-org.github.io/script-runner-generator'
2929
const customBuildUrl = 'http://localhost:4000/build' // this will be used when the server is ready
3030

31-
/**
32-
* Transforms standard import statements into dynamic import statements for runtime execution.
33-
* @param {string} scriptContent The original script content.
34-
* @returns {string} The transformed script content.
35-
*/
3631
function transformScriptForRuntime(scriptContent: string): string {
37-
// 1. dynamicImport 헬퍼 함수를 스크립트 맨 위에 주입
38-
const dynamicImportHelper = `const dynamicImport = (p) => new Function(\`return import('https://cdn.jsdelivr.net/npm/\${p}/+esm')\`)();\n`;
32+
const dynamicImportHelper = `const dynamicImport = (p) => new Function(\`return import('https://cdn.jsdelivr.net/npm/\${p}/+esm')\`)();\n`
3933

40-
// 2. 다양한 import 구문을 변환
41-
// 'import { ... } from "package"' 구문
4234
let transformed = scriptContent.replace(
4335
/import\s+({[\s\S]*?})\s+from\s+['"]([^'"]+)['"]/g,
4436
'const $1 = await dynamicImport("$2");'
45-
);
46-
// 'import Default from "package"' 구문
37+
)
4738
transformed = transformed.replace(
4839
/import\s+([\w\d_$]+)\s+from\s+['"]([^'"]+)['"]/g,
4940
'const $1 = (await dynamicImport("$2")).default;'
50-
);
51-
// 'import * as name from "package"' 구문
41+
)
5242
transformed = transformed.replace(
5343
/import\s+\*\s+as\s+([\w\d_$]+)\s+from\s+['"]([^'"]+)['"]/g,
5444
'const $1 = await dynamicImport("$2");'
55-
);
45+
)
5646

57-
// 3. 모든 코드를 async IIFE로 감싸서 top-level await 문제 해결
58-
return `${dynamicImportHelper}\n(async () => {\n try {\n${transformed}\n } catch (e) { console.error('Error executing script:', e); }\n})();`;
47+
return `${dynamicImportHelper}\n(async () => {\n try {\n${transformed}\n } catch (e) { console.error('Error executing script:', e); }\n})();`
5948
}
6049

6150
export class ScriptRunnerBridgePlugin extends Plugin {
@@ -227,12 +216,12 @@ export class ScriptRunnerBridgePlugin extends Plugin {
227216
}
228217
try {
229218
this.setIsLoading(this.activeConfig.name, true)
230-
const transformedScript = transformScriptForRuntime(script);
219+
const transformedScript = transformScriptForRuntime(script)
231220

232-
console.log('--- [ScriptRunner] Original Script ---');
233-
console.log(script);
234-
console.log('--- [ScriptRunner] Transformed Script for Runtime ---');
235-
console.log(transformedScript);
221+
console.log('--- [ScriptRunner] Original Script ---')
222+
console.log(script)
223+
console.log('--- [ScriptRunner] Transformed Script for Runtime ---')
224+
console.log(transformedScript)
236225

237226
await this.call(`${this.scriptRunnerProfileName}${this.activeConfig.name}`, 'execute',transformedScript, filePath)
238227

package.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,7 @@
127127
"@reown/appkit": "^1.7.4",
128128
"@reown/appkit-adapter-ethers": "^1.7.4",
129129
"@ricarso/react-image-magnifiers": "^1.9.0",
130-
"@types/acorn": "^6.0.4",
131130
"@types/nightwatch": "^2.3.1",
132-
"acorn": "^8.15.0",
133131
"ansi-gray": "^0.1.1",
134132
"assert": "^2.1.0",
135133
"async": "^2.6.2",

yarn.lock

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7248,13 +7248,6 @@
72487248
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e"
72497249
integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==
72507250

7251-
"@types/acorn@^6.0.4":
7252-
version "6.0.4"
7253-
resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-6.0.4.tgz#b1a652a373d0cace52dace608fced14f58e9c4a9"
7254-
integrity sha512-DafqcBAjbOOmgqIx3EF9EAdBKAKgspv00aQVIW3fVQ0TXo5ZPBeSRey1SboVAUzjw8Ucm7cd1gtTSlosYoEQLA==
7255-
dependencies:
7256-
acorn "*"
7257-
72587251
"@types/aria-query@^4.2.0":
72597252
version "4.2.2"
72607253
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.2.tgz#ed4e0ad92306a704f9fb132a0cfcf77486dbe2bc"
@@ -8725,11 +8718,6 @@ acorn-walk@^8.0.0, acorn-walk@^8.1.1:
87258718
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1"
87268719
integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==
87278720

8728-
acorn@*, acorn@^8.15.0:
8729-
version "8.15.0"
8730-
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816"
8731-
integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==
8732-
87338721
"acorn@>= 2.5.2 <= 5.7.5":
87348722
version "5.7.4"
87358723
resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e"

0 commit comments

Comments
 (0)