66 * found in the LICENSE file at https://angular.dev/license
77 */
88
9+ import assert from 'node:assert' ;
10+ import { mkdir , mkdtemp , rm , writeFile } from 'node:fs/promises' ;
11+ import { join } from 'node:path' ;
12+ import { pathToFileURL } from 'node:url' ;
913import { initialize , load , resolve } from './loader-hooks' ;
1014import { createSharedServerFiles } from './utils' ;
1115
@@ -124,46 +128,46 @@ describe('esm-in-memory-loader loader-hooks', () => {
124128 } ) ;
125129
126130 describe ( 'load' , ( ) => {
127- it ( 'should load in-memory file source from SharedArrayBuffer backed Uint8Array' , async ( ) => {
131+ it ( 'should load in-memory file source from SharedArrayBuffer backed Uint8Array' , ( ) => {
128132 const memoryUrl = new URL ( './main.server.mjs' , 'memory://' ) . href ;
129133 const rootResolve = resolve ( memoryUrl , { parentURL : undefined } , ( ) => { } ) ;
130134 const nextLoad = jasmine . createSpy ( 'nextLoad' ) ;
131135
132- const result = await load ( rootResolve . url , { format : 'module' } , nextLoad ) ;
136+ const result = load ( rootResolve . url , { format : 'module' } , nextLoad ) ;
133137
134138 expect ( nextLoad ) . not . toHaveBeenCalled ( ) ;
135139 expect ( result . format ) . toBe ( 'module' ) ;
136140 expect ( result . shortCircuit ) . toBeTrue ( ) ;
137141 expect ( result . source ) . toBe ( 'export const main = true;' ) ;
138142 } ) ;
139143
140- it ( 'should load in-memory file with multi-byte UTF-8 characters' , async ( ) => {
144+ it ( 'should load in-memory file with multi-byte UTF-8 characters' , ( ) => {
141145 const memoryUrl = new URL ( './utf8.mjs' , 'memory://' ) . href ;
142146 const rootResolve = resolve ( memoryUrl , { parentURL : undefined } , ( ) => { } ) ;
143147 const nextLoad = jasmine . createSpy ( 'nextLoad' ) ;
144148
145- const result = await load ( rootResolve . url , { format : 'module' } , nextLoad ) ;
149+ const result = load ( rootResolve . url , { format : 'module' } , nextLoad ) ;
146150
147151 expect ( nextLoad ) . not . toHaveBeenCalled ( ) ;
148152 expect ( result . format ) . toBe ( 'module' ) ;
149153 expect ( result . shortCircuit ) . toBeTrue ( ) ;
150154 expect ( result . source ) . toBe ( 'export const text = "🔥 UTF-8 🚀";' ) ;
151155 } ) ;
152156
153- it ( 'should load in-memory file with empty content' , async ( ) => {
157+ it ( 'should load in-memory file with empty content' , ( ) => {
154158 const memoryUrl = new URL ( './empty.mjs' , 'memory://' ) . href ;
155159 const rootResolve = resolve ( memoryUrl , { parentURL : undefined } , ( ) => { } ) ;
156160 const nextLoad = jasmine . createSpy ( 'nextLoad' ) ;
157161
158- const result = await load ( rootResolve . url , { format : 'module' } , nextLoad ) ;
162+ const result = load ( rootResolve . url , { format : 'module' } , nextLoad ) ;
159163
160164 expect ( nextLoad ) . not . toHaveBeenCalled ( ) ;
161165 expect ( result . format ) . toBe ( 'module' ) ;
162166 expect ( result . shortCircuit ) . toBeTrue ( ) ;
163167 expect ( result . source ) . toBe ( '' ) ;
164168 } ) ;
165169
166- it ( 'should load in-memory file source with non-zero byteOffset in Uint8Array' , async ( ) => {
170+ it ( 'should load in-memory file source with non-zero byteOffset in Uint8Array' , ( ) => {
167171 const target = 'export const sliced = 42;' ;
168172 const fullBuffer = Buffer . from ( `__PADDING__${ target } __MORE__` ) ;
169173 const offset = Buffer . byteLength ( '__PADDING__' , 'utf-8' ) ;
@@ -181,15 +185,15 @@ describe('esm-in-memory-loader loader-hooks', () => {
181185 const rootResolve = resolve ( memoryUrl , { parentURL : undefined } , ( ) => { } ) ;
182186 const nextLoad = jasmine . createSpy ( 'nextLoad' ) ;
183187
184- const result = await load ( rootResolve . url , { format : 'module' } , nextLoad ) ;
188+ const result = load ( rootResolve . url , { format : 'module' } , nextLoad ) ;
185189
186190 expect ( nextLoad ) . not . toHaveBeenCalled ( ) ;
187191 expect ( result . format ) . toBe ( 'module' ) ;
188192 expect ( result . shortCircuit ) . toBeTrue ( ) ;
189193 expect ( result . source ) . toBe ( target ) ;
190194 } ) ;
191195
192- it ( 'should load in-memory file source when outputFiles contain string values' , async ( ) => {
196+ it ( 'should load in-memory file source when outputFiles contain string values' , ( ) => {
193197 initialize ( {
194198 workspaceRoot,
195199 outputFiles : {
@@ -201,29 +205,54 @@ describe('esm-in-memory-loader loader-hooks', () => {
201205 const rootResolve = resolve ( memoryUrl , { parentURL : undefined } , ( ) => { } ) ;
202206 const nextLoad = jasmine . createSpy ( 'nextLoad' ) ;
203207
204- const result = await load ( rootResolve . url , { format : 'module' } , nextLoad ) ;
208+ const result = load ( rootResolve . url , { format : 'module' } , nextLoad ) ;
205209
206210 expect ( nextLoad ) . not . toHaveBeenCalled ( ) ;
207211 expect ( result . format ) . toBe ( 'module' ) ;
208212 expect ( result . shortCircuit ) . toBeTrue ( ) ;
209213 expect ( result . source ) . toBe ( 'export const fromString = 1;' ) ;
210214 } ) ;
211215
212- it ( 'should reject when in-memory file does not exist in outputFiles' , async ( ) => {
216+ it ( 'should throw when in-memory file does not exist in outputFiles' , ( ) => {
213217 const memoryUrl = new URL ( './main.server.mjs' , 'memory://' ) . href ;
214218 const rootResolve = resolve ( memoryUrl , { parentURL : undefined } , ( ) => { } ) ;
215219 const nonExistentVirtualUrl = rootResolve . url . replace ( 'main.server.mjs' , 'missing.mjs' ) ;
216220 const nextLoad = jasmine . createSpy ( 'nextLoad' ) ;
217221
218- await expectAsync (
219- load ( nonExistentVirtualUrl , { format : 'module' } , nextLoad ) ,
220- ) . toBeRejectedWithError ( / R e s o l v e d i n - m e m o r y E S M f i l e s h o u l d a l w a y s e x i s t / ) ;
222+ expect ( ( ) => load ( nonExistentVirtualUrl , { format : 'module' } , nextLoad ) ) . toThrowError (
223+ / R e s o l v e d i n - m e m o r y E S M f i l e s h o u l d a l w a y s e x i s t / ,
224+ ) ;
221225 expect ( nextLoad ) . not . toHaveBeenCalled ( ) ;
222226 } ) ;
223227
224- it ( 'should delegate to nextLoad for non-angular file URLs' , async ( ) => {
225- const nextLoad = jasmine . createSpy ( 'nextLoad' ) . and . resolveTo ( { format : 'module' } ) ;
226- const result = await load (
228+ it ( 'should prepend ngServerMode initialization for @angular/ file URLs' , async ( ) => {
229+ const baseTmpDir = process . env [ 'TEST_TMPDIR' ] ;
230+ assert ( baseTmpDir , 'TEST_TMPDIR is not set' ) ;
231+ const tmpDir = await mkdtemp ( join ( baseTmpDir , 'loader-hooks-test-' ) ) ;
232+
233+ try {
234+ const angularDir = join ( tmpDir , '@angular/core' ) ;
235+ await mkdir ( angularDir , { recursive : true } ) ;
236+ const filePath = join ( angularDir , 'index.mjs' ) ;
237+ await writeFile ( filePath , 'export const VERSION = "1.0.0";' ) ;
238+
239+ const nextLoad = jasmine . createSpy ( 'nextLoad' ) ;
240+ const result = load ( pathToFileURL ( filePath ) . href , { format : 'module' } , nextLoad ) ;
241+
242+ expect ( nextLoad ) . not . toHaveBeenCalled ( ) ;
243+ expect ( result . format ) . toBe ( 'module' ) ;
244+ expect ( result . shortCircuit ) . toBeTrue ( ) ;
245+ expect ( new TextDecoder ( ) . decode ( result . source ) ) . toBe (
246+ 'var ngServerMode=true;export const VERSION = "1.0.0";' ,
247+ ) ;
248+ } finally {
249+ await rm ( tmpDir , { recursive : true , force : true } ) ;
250+ }
251+ } ) ;
252+
253+ it ( 'should delegate to nextLoad for non-angular file URLs' , ( ) => {
254+ const nextLoad = jasmine . createSpy ( 'nextLoad' ) . and . returnValue ( { format : 'module' } ) ;
255+ const result = load (
227256 'file:///workspace/node_modules/rxjs/index.js' ,
228257 { format : 'module' } ,
229258 nextLoad ,
@@ -235,9 +264,9 @@ describe('esm-in-memory-loader loader-hooks', () => {
235264 expect ( result . format ) . toBe ( 'module' ) ;
236265 } ) ;
237266
238- it ( 'should delegate to nextLoad for non-memory non-file URLs' , async ( ) => {
239- const nextLoad = jasmine . createSpy ( 'nextLoad' ) . and . resolveTo ( { format : 'builtin' } ) ;
240- const result = await load ( 'node:fs' , { format : 'builtin' } , nextLoad ) ;
267+ it ( 'should delegate to nextLoad for non-memory non-file URLs' , ( ) => {
268+ const nextLoad = jasmine . createSpy ( 'nextLoad' ) . and . returnValue ( { format : 'builtin' } ) ;
269+ const result = load ( 'node:fs' , { format : 'builtin' } , nextLoad ) ;
241270
242271 expect ( nextLoad ) . toHaveBeenCalledWith ( 'node:fs' ) ;
243272 expect ( result . format ) . toBe ( 'builtin' ) ;
0 commit comments