Repository: nodejs/node
Pull request: [v22.x backport] esm: implement import.meta.main

Backport #57804 and #58661 to v22.x release line

Changed files:
filename: lib/internal/modules/esm/translators.js
patch: @@ -511,17 +511,17 @@ translators.set('wasm', async function(url, source) {
 });
 
 // Strategy for loading a commonjs TypeScript module
-translators.set('commonjs-typescript', function(url, source) {
+translators.set('commonjs-typescript', function(url, source, isMain) {
   assertBufferSource(source, true, 'load');
   const code = stripTypeScriptModuleTypes(stringify(source), url);
   debug(`Translating TypeScript ${url}`);
-  return FunctionPrototypeCall(translators.get('commonjs'), this, url, code, false);
+  return FunctionPrototypeCall(translators.get('commonjs'), this, url, code, isMain);
 });
 
 // Strategy for loading an esm TypeScript module
-translators.set('module-typescript', function(url, source) {
+translators.set('module-typescript', function(url, source, isMain) {
   assertBufferSource(source, true, 'load');
   const code = stripTypeScriptModuleTypes(stringify(source), url);
   debug(`Translating TypeScript ${url}`);
-  return FunctionPrototypeCall(translators.get('module'), this, url, code, false);
+  return FunctionPrototypeCall(translators.get('module'), this, url, code, isMain);
 });

filename: test/es-module/test-esm-import-meta-main-eval.mjs
patch: @@ -3,17 +3,6 @@ import * as fixtures from '../common/fixtures.js';
 import assert from 'node:assert/strict';
 import { describe, it } from 'node:test';
 
-const importMetaMainScript = `
-import assert from 'node:assert/strict';
-
-assert.strictEqual(import.meta.main, true, 'import.meta.main should evaluate true in main module');
-
-const { isMain: importedModuleIsMain } = await import(
-    ${JSON.stringify(fixtures.fileURL('es-modules/import-meta-main.mjs'))}
-);
-assert.strictEqual(importedModuleIsMain, false, 'import.meta.main should evaluate false in imported module');
-`;
-
 function wrapScriptInEvalWorker(script) {
   return `
   import { Worker } from 'node:worker_threads';
@@ -33,6 +22,17 @@ function wrapScriptInUrlWorker(script) {
 }
 
 describe('import.meta.main in evaluated scripts', () => {
+  const importMetaMainScript = `
+import assert from 'node:assert/strict';
+
+assert.strictEqual(import.meta.main, true, 'import.meta.main should evaluate true in main module');
+
+const { isMain: importedModuleIsMain } = await import(
+    ${JSON.stringify(fixtures.fileURL('es-modules/import-meta-main.mjs'))}
+);
+assert.strictEqual(importedModuleIsMain, false, 'import.meta.main should evaluate false in imported module');
+`;
+
   it('should evaluate true in evaluated script', async () => {
     const result = await spawnPromisified(
       process.execPath,
@@ -72,3 +72,65 @@ describe('import.meta.main in evaluated scripts', () => {
     });
   });
 });
+
+describe('import.meta.main in typescript scripts', () => {
+  const importMetaMainTSScript = `
+import assert from 'node:assert/strict';
+
+assert.strictEqual(import.meta.main, true, 'import.meta.main should evaluate true in main module');
+
+const { isMain: importedModuleIsMain } = await import(
+    ${JSON.stringify(fixtures.fileURL('es-modules/import-meta-main.ts'))}
+);
+assert.strictEqual(importedModuleIsMain, false, 'import.meta.main should evaluate false in imported module');
+`;
+
+  it('should evaluate true in evaluated script', async () => {
+    const result = await spawnPromisified(
+      process.execPath,
+      ['--experimental-strip-types',
+       '--input-type=module-typescript',
+       '--disable-warning=ExperimentalWarning',
+       '--eval', importMetaMainTSScript],
+    );
+    assert.deepStrictEqual(result, {
+      stderr: '',
+      stdout: '',
+      code: 0,
+      signal: null,
+    });
+  });
+
+  it('should evaluate true in worker instantiated with module source by evaluated script', async () => {
+    const result = await spawnPromisified(
+      process.execPath,
+      ['--experimental-strip-types',
+       '--input-type=module-typescript',
+       '--disable-warning=ExperimentalWarning',
+       '--eval', wrapScriptInEvalWorker(importMetaMainTSScript)],
+    );
+    assert.deepStrictEqual(result, {
+      stderr: '',
+      stdout: '',
+      code: 0,
+      signal: null,
+    });
+  });
+
+  it('should evaluate true in worker instantiated with `data:` URL by evaluated script', async () => {
+    const result = await spawnPromisified(
+      process.execPath,
+      ['--input-type=module',
+       '--experimental-strip-types',
+       '--input-type=module-typescript',
+       '--disable-warning=ExperimentalWarning',
+       '--eval', wrapScriptInUrlWorker(importMetaMainTSScript)],
+    );
+    assert.deepStrictEqual(result, {
+      stderr: '',
+      stdout: '',
+      code: 0,
+      signal: null,
+    });
+  });
+});

filename: test/fixtures/es-modules/import-meta-main.ts
patch: @@ -0,0 +1 @@
+export const isMain = import.meta.main;