FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

fix(vite): fold an exports-map plugin's root entry onto its bare pack… · NativeScript/NativeScript@a76525a · GitHub

Commit a76525a

Browse files
authored
fix(vite): fold an exports-map plugin's root entry onto its bare package id (#11411)
Vite resolves a bare plugin import through the package's `exports` map to the concrete file before the rewriter sees it. For a NativeScript plugin with an `exports` map, `resolveInternalRuntimePluginBareSpecifier` kept that concrete subpath (`@scope/plugin/dist/index.js`) as the vendor id, which the device vendor registry (keyed on bare package ids) cannot serve; the import fell to the runtime's base require and came back as an empty placeholder module, so every named import was undefined. Consult the exports reverse map first and return the bare package id when the resolved file is the root export. Subpath exports still return null, package-internal files keep their concrete specifier, and main-field packages resolved to a platform file still fold through subpathMatchesMainEntry. [skip ci]
1 parent 6dba52f commit a76525a

2 files changed

Lines changed: 67 additions & 1 deletion

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'fs';
2+
import { tmpdir } from 'os';
3+
import { join } from 'path';
4+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5+
6+
import { resolveInternalRuntimePluginBareSpecifier } from './websocket-module-specifiers.js';
7+
8+
const CORE_PEER = { peerDependencies: { '@nativescript/core': '>=9.0.0' } };
9+
10+
function writePackage(root: string, name: string, pkg: Record<string, unknown>): void {
11+
const dir = join(root, 'node_modules', ...name.split('/'));
12+
mkdirSync(dir, { recursive: true });
13+
writeFileSync(join(dir, 'package.json'), JSON.stringify({ name, version: '1.0.0', ...pkg }));
14+
}
15+
16+
// Package names are unique per case: the exports reverse map is cached by name alone.
17+
describe('resolveInternalRuntimePluginBareSpecifier', () => {
18+
let root: string;
19+
20+
beforeEach(() => {
21+
root = mkdtempSync(join(tmpdir(), 'ns-vite-plugin-specifier-'));
22+
});
23+
24+
afterEach(() => {
25+
rmSync(root, { recursive: true, force: true });
26+
});
27+
28+
it('folds the root export of an exports-map plugin onto its bare package id', () => {
29+
writePackage(root, '@nativescript-community/exports-root-fixture', {
30+
...CORE_PEER,
31+
exports: {
32+
'./package.json': './package.json',
33+
'.': { types: './dist/index.d.ts', import: './dist/index.js', default: './dist/index.js' },
34+
'./config': './dist/config.js',
35+
},
36+
});
37+
expect(resolveInternalRuntimePluginBareSpecifier('/node_modules/@nativescript-community/exports-root-fixture/dist/index.js', root)).toBe('@nativescript-community/exports-root-fixture');
38+
});
39+
40+
it('leaves a subpath export to the vendor resolver', () => {
41+
writePackage(root, '@nativescript-community/exports-subpath-fixture', {
42+
...CORE_PEER,
43+
exports: { '.': './dist/index.js', './config': './dist/config.js' },
44+
});
45+
expect(resolveInternalRuntimePluginBareSpecifier('/node_modules/@nativescript-community/exports-subpath-fixture/dist/config.js', root)).toBeNull();
46+
});
47+
48+
it('keeps a package-internal file of an exports-map plugin as the concrete specifier', () => {
49+
writePackage(root, '@nativescript-community/exports-internal-fixture', {
50+
...CORE_PEER,
51+
exports: { '.': './dist/index.js' },
52+
});
53+
expect(resolveInternalRuntimePluginBareSpecifier('/node_modules/@nativescript-community/exports-internal-fixture/dist/driver.js', root)).toBe('@nativescript-community/exports-internal-fixture/dist/driver.js');
54+
});
55+
56+
it('folds a main-field plugin entry resolved to a platform file onto its bare package id', () => {
57+
writePackage(root, '@nativescript-community/main-field-fixture', { ...CORE_PEER, main: 'dist/index' });
58+
expect(resolveInternalRuntimePluginBareSpecifier('/node_modules/@nativescript-community/main-field-fixture/dist/index.ios.js', root)).toBe('@nativescript-community/main-field-fixture');
59+
});
60+
});

‎packages/vite/hmr/server/websocket-module-specifiers.ts‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,13 @@ export function resolveInternalRuntimePluginBareSpecifier(spec: string, projectR
742742

743743
const reverseMap = getExportsReverseMap(packageName, projectRoot);
744744
const originalSpec = reverseMap.get(subpath);
745-
if (originalSpec && originalSpec !== packageName) {
745+
// The device vendor registry serves plugins by bare package id, so the file
746+
// the root export resolves to must fold back onto that id whether the
747+
// package declares it through `exports` or `main`.
748+
if (originalSpec === packageName) {
749+
return packageName;
750+
}
751+
if (originalSpec) {
746752
return null;
747753
}
748754

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL