1import { spawnPromisified } from '../common/index.mjs'; 2import * as fixtures from '../common/fixtures.mjs'; 3import assert from 'node:assert'; 4import os from 'node:os'; 5import { execPath } from 'node:process'; 6import { describe, it } from 'node:test'; 7 8describe('globalPreload hook', () => { 9 it('should not emit deprecation warning when initialize is supplied', async () => { 10 const { stderr } = await spawnPromisified(execPath, [ 11 '--experimental-loader', 12 'data:text/javascript,export function globalPreload(){}export function initialize(){}', 13 fixtures.path('empty.js'), 14 ]); 15 16 assert.doesNotMatch(stderr, /`globalPreload` is an experimental feature/); 17 }); 18 19 it('should handle globalPreload returning undefined', async () => { 20 const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 21 '--no-warnings', 22 '--experimental-loader', 23 'data:text/javascript,export function globalPreload(){}', 24 fixtures.path('empty.js'), 25 ]); 26 27 assert.strictEqual(stderr, ''); 28 assert.strictEqual(stdout, ''); 29 assert.strictEqual(code, 0); 30 assert.strictEqual(signal, null); 31 }); 32 33 it('should handle loading node:test', async () => { 34 const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 35 '--no-warnings', 36 '--experimental-loader', 37 'data:text/javascript,export function globalPreload(){return `getBuiltin("node:test")()`}', 38 fixtures.path('empty.js'), 39 ]); 40 41 assert.strictEqual(stderr, ''); 42 assert.match(stdout, /\n# pass 1\r?\n/); 43 assert.strictEqual(code, 0); 44 assert.strictEqual(signal, null); 45 }); 46 47 it('should handle loading node:os with node: prefix', async () => { 48 const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 49 '--no-warnings', 50 '--experimental-loader', 51 'data:text/javascript,export function globalPreload(){return `console.log(getBuiltin("node:os").arch())`}', 52 fixtures.path('empty.js'), 53 ]); 54 55 assert.strictEqual(stderr, ''); 56 assert.strictEqual(stdout.trim(), os.arch()); 57 assert.strictEqual(code, 0); 58 assert.strictEqual(signal, null); 59 }); 60 61 // `os` is used here because it's simple and not mocked (the builtin module otherwise doesn't matter). 62 it('should handle loading builtin module without node: prefix', async () => { 63 const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 64 '--no-warnings', 65 '--experimental-loader', 66 'data:text/javascript,export function globalPreload(){return `console.log(getBuiltin("os").arch())`}', 67 fixtures.path('empty.js'), 68 ]); 69 70 assert.strictEqual(stderr, ''); 71 assert.strictEqual(stdout.trim(), os.arch()); 72 assert.strictEqual(code, 0); 73 assert.strictEqual(signal, null); 74 }); 75 76 it('should throw when loading node:test without node: prefix', async () => { 77 const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 78 '--no-warnings', 79 '--experimental-loader', 80 'data:text/javascript,export function globalPreload(){return `getBuiltin("test")()`}', 81 fixtures.path('empty.js'), 82 ]); 83 84 assert.match(stderr, /ERR_UNKNOWN_BUILTIN_MODULE/); 85 assert.strictEqual(stdout, ''); 86 assert.strictEqual(code, 1); 87 assert.strictEqual(signal, null); 88 }); 89 90 it('should register globals set from globalPreload', async () => { 91 const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 92 '--no-warnings', 93 '--experimental-loader', 94 'data:text/javascript,export function globalPreload(){return "this.myGlobal=4"}', 95 '--print', 'myGlobal', 96 ]); 97 98 assert.strictEqual(stderr, ''); 99 assert.strictEqual(stdout.trim(), '4'); 100 assert.strictEqual(code, 0); 101 assert.strictEqual(signal, null); 102 }); 103 104 it('should log console.log calls returned from globalPreload', async () => { 105 const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 106 '--no-warnings', 107 '--experimental-loader', 108 'data:text/javascript,export function globalPreload(){return `console.log("Hello from globalPreload")`}', 109 fixtures.path('empty.js'), 110 ]); 111 112 assert.strictEqual(stderr, ''); 113 assert.strictEqual(stdout.trim(), 'Hello from globalPreload'); 114 assert.strictEqual(code, 0); 115 assert.strictEqual(signal, null); 116 }); 117 118 it('should crash if globalPreload returns code that throws', async () => { 119 const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 120 '--no-warnings', 121 '--experimental-loader', 122 'data:text/javascript,export function globalPreload(){return `throw new Error("error from globalPreload")`}', 123 fixtures.path('empty.js'), 124 ]); 125 126 assert.match(stderr, /error from globalPreload/); 127 assert.strictEqual(stdout, ''); 128 assert.strictEqual(code, 1); 129 assert.strictEqual(signal, null); 130 }); 131 132 it('should have a `this` value that is not bound to the loader instance', async () => { 133 const { code, signal, stdout, stderr } = await spawnPromisified(execPath, [ 134 '--no-warnings', 135 '--experimental-loader', 136 `data:text/javascript,export ${function globalPreload() { 137 if (this != null) { 138 throw new Error('hook function must not be bound to ESMLoader instance'); 139 } 140 }}`, 141 fixtures.path('empty.js'), 142 ]); 143 144 assert.strictEqual(stderr, ''); 145 assert.strictEqual(stdout, ''); 146 assert.strictEqual(code, 0); 147 assert.strictEqual(signal, null); 148 }); 149}); 150