Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add default exports to lwc @W-13710298 #3997

Merged
merged 11 commits into from
Feb 16, 2024
58 changes: 58 additions & 0 deletions packages/lwc/__tests__/default-exports.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
import * as fs from 'node:fs';
import * as path from 'node:path';

const PACKAGE_ROOT = path.join(__dirname, '..');

const expectExportDefaultFromPackageInFile = (pkgName: string, ext: string) => {
const filename = path.join(PACKAGE_ROOT, pkgName + ext);
const contents = fs.readFileSync(filename, 'utf8');
const exportDefaultFromPackage = new RegExp(
`^export \\{ default \\} from '@lwc/${pkgName}';$`,
'm'
);
expect(contents).toMatch(exportDefaultFromPackage);
};

/**
* Packages with no exports (e.g. polyfill packages) have a "default" export of {default: {}}. The
* placeholder object is an empty object whose prototype is an empty object with null prototype.
*/
const hasExplicitDefaultExport = (mod: object) => {
// No default export = self explanatory
if (!('default' in mod)) return false;
// If we have more than one export, then we must have explicitly declared them
if (Object.keys(mod).length > 1) return true;
const def = mod.default;
// If it's not an object, it must be an explicit export
if (typeof def !== 'object' || def === null) return true;
// If it's not an empty object, it's not the placeholder object
if (Object.keys(def).length > 0) return true;
const proto = Object.getPrototypeOf(def);
// If the prototype isn't an empty null-prototype object, it's not the placeholder object
if (Object.keys(proto).length > 0 || Object.getPrototypeOf(proto) !== null) return true;
// It must be the placeholder object!
return false;
};

describe('default exports are not forgotten', () => {
const allFiles = fs.readdirSync(PACKAGE_ROOT);
const packages = allFiles
.filter((f) => f.endsWith('.js') && f !== 'index.js')
.map((f) => f.slice(0, -3));
test.each(packages)('@lwc/%s', async (pkg) => {
const realModule = await import(`@lwc/${pkg}`);
// When jest properly supports ESM, this will be a lot simpler
// const aliasedModule = await import(`lwc/${pkg}`);
// expect(aliasedModule.default).toBe(realModule.default);
if (hasExplicitDefaultExport(realModule)) {
expectExportDefaultFromPackageInFile(pkg, '.d.ts');
expectExportDefaultFromPackageInFile(pkg, '.js');
}
});
});
16 changes: 16 additions & 0 deletions packages/lwc/__tests__/package-exports.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
import { readFileSync } from 'node:fs';
import { join } from 'node:path';

describe('packaged dependencies are re-exported', () => {
const pkg = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8'));
test.each(Object.keys(pkg.dependencies))(`%s is exported`, (name) => {
const relative = name.replace('@lwc', '.');
expect(pkg.exports[relative]).toBe(`${relative}.js`);
});
});
3 changes: 2 additions & 1 deletion packages/lwc/babel-plugin-component.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
* Copyright (c) 2023, salesforce.com, inc.
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
export type * from '@lwc/babel-plugin-component';
export { default } from '@lwc/babel-plugin-component';
3 changes: 2 additions & 1 deletion packages/lwc/babel-plugin-component.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
* Copyright (c) 2023, salesforce.com, inc.
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
export * from '@lwc/babel-plugin-component';
export { default } from '@lwc/babel-plugin-component';
3 changes: 2 additions & 1 deletion packages/lwc/features.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
* Copyright (c) 2023, salesforce.com, inc.
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
export type * from '@lwc/features';
export { default } from '@lwc/features';
3 changes: 2 additions & 1 deletion packages/lwc/features.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
* Copyright (c) 2023, salesforce.com, inc.
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
export * from '@lwc/features';
export { default } from '@lwc/features';
22 changes: 22 additions & 0 deletions packages/lwc/jest.config.cjs
wjhsf marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright (c) 2024, Salesforce, Inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
/* eslint-env node */

/**
* This is a .cjs file because this package is an ESM package, but jest needs CJS to work.
* If this file is ever changed to a .js file, add an exclusion to the package.json "files" list,
* so that this is not shipped as part of the package.
*/

// eslint-disable-next-line @typescript-eslint/no-var-requires
const BASE_CONFIG = require('../../scripts/jest/base.config');

module.exports = {
...BASE_CONFIG,
displayName: 'lwc',
testEnvironment: 'jsdom',
};
3 changes: 2 additions & 1 deletion packages/lwc/rollup-plugin.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
* Copyright (c) 2023, salesforce.com, inc.
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
export type * from '@lwc/rollup-plugin';
export { default } from '@lwc/rollup-plugin';
3 changes: 2 additions & 1 deletion packages/lwc/rollup-plugin.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
* Copyright (c) 2023, salesforce.com, inc.
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
export * from '@lwc/rollup-plugin';
export { default } from '@lwc/rollup-plugin';
3 changes: 2 additions & 1 deletion packages/lwc/template-compiler.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
* Copyright (c) 2023, salesforce.com, inc.
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
export type * from '@lwc/template-compiler';
export { default } from '@lwc/template-compiler';
3 changes: 2 additions & 1 deletion packages/lwc/template-compiler.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
/*
* Copyright (c) 2023, salesforce.com, inc.
* Copyright (c) 2024, salesforce.com, inc.
* All rights reserved.
* SPDX-License-Identifier: MIT
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT
*/
export * from '@lwc/template-compiler';
export { default } from '@lwc/template-compiler';
4 changes: 3 additions & 1 deletion packages/lwc/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"extends": "../../tsconfig.json",

"compilerOptions": {
"lib": ["dom"]
"lib": ["dom", "es2021"]
}
}
1 change: 1 addition & 0 deletions scripts/jest/root.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module.exports = {
'<rootDir>/packages/@lwc/synthetic-shadow',
'<rootDir>/packages/@lwc/template-compiler',
'<rootDir>/packages/@lwc/wire-service',
'<rootDir>/packages/lwc',
],
coverageThreshold: {
global: {
Expand Down
Loading