diff --git a/packages/@lwc/engine-core/src/index.ts b/packages/@lwc/engine-core/src/index.ts index c7d536e4a6..4f483cfa5d 100644 --- a/packages/@lwc/engine-core/src/index.ts +++ b/packages/@lwc/engine-core/src/index.ts @@ -5,4 +5,7 @@ * For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/MIT */ +// Tests +import './testFeatureFlag'; + export * from './framework/main'; diff --git a/packages/@lwc/engine-core/src/testFeatureFlag.ts b/packages/@lwc/engine-core/src/testFeatureFlag.ts new file mode 100644 index 0000000000..d7b4b6c551 --- /dev/null +++ b/packages/@lwc/engine-core/src/testFeatureFlag.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, 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 + */ + +import features from '@lwc/features'; + +if (process.env.NODE_ENV !== 'production' && typeof window !== 'undefined') { + window.addEventListener('test-dummy-flag', () => { + let hasFlag = false; + if (features.DUMMY_TEST_FLAG) { + hasFlag = true; + } + + window.dispatchEvent( + new CustomEvent('has-dummy-flag', { + detail: { + package: '@lwc/engine-core', + hasFlag, + }, + }) + ); + }); +} diff --git a/packages/@lwc/engine-dom/scripts/rollup.config.js b/packages/@lwc/engine-dom/scripts/rollup.config.js index 25260078a2..728d5fe988 100644 --- a/packages/@lwc/engine-dom/scripts/rollup.config.js +++ b/packages/@lwc/engine-dom/scripts/rollup.config.js @@ -11,6 +11,7 @@ const path = require('path'); const { nodeResolve } = require('@rollup/plugin-node-resolve'); const typescript = require('../../../../scripts/rollup/typescript'); const writeDistAndTypes = require('../../../../scripts/rollup/writeDistAndTypes'); +const lwcFeatures = require('../../../../scripts/rollup/lwcFeatures'); const { version } = require('../package.json'); const banner = `/* proxy-compat-disable */`; @@ -35,6 +36,7 @@ module.exports = { }), typescript(), writeDistAndTypes(), + lwcFeatures(), ], onwarn({ code, message }) { diff --git a/packages/@lwc/engine-dom/src/index.ts b/packages/@lwc/engine-dom/src/index.ts index ca90813c0b..f06f545b6e 100644 --- a/packages/@lwc/engine-dom/src/index.ts +++ b/packages/@lwc/engine-dom/src/index.ts @@ -11,6 +11,9 @@ import './polyfills/aria-properties/main'; // Renderer initialization ------------------------------------------------------------------------- import './initializeRenderer'; +// Tests ------------------------------------------------------------------------------------------- +import './testFeatureFlag.ts'; + // Engine-core public APIs ------------------------------------------------------------------------- export { createContextProvider, diff --git a/packages/@lwc/engine-dom/src/testFeatureFlag.ts b/packages/@lwc/engine-dom/src/testFeatureFlag.ts new file mode 100644 index 0000000000..6489948e5e --- /dev/null +++ b/packages/@lwc/engine-dom/src/testFeatureFlag.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, 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 + */ + +import features from '@lwc/features'; + +if (process.env.NODE_ENV !== 'production' && typeof window !== 'undefined') { + window.addEventListener('test-dummy-flag', () => { + let hasFlag = false; + if (features.DUMMY_TEST_FLAG) { + hasFlag = true; + } + + window.dispatchEvent( + new CustomEvent('has-dummy-flag', { + detail: { + package: '@lwc/engine-dom', + hasFlag, + }, + }) + ); + }); +} diff --git a/packages/@lwc/engine-server/scripts/rollup.config.js b/packages/@lwc/engine-server/scripts/rollup.config.js index fb155beb1c..60ee1f1f91 100644 --- a/packages/@lwc/engine-server/scripts/rollup.config.js +++ b/packages/@lwc/engine-server/scripts/rollup.config.js @@ -9,6 +9,7 @@ const path = require('path'); const { nodeResolve } = require('@rollup/plugin-node-resolve'); const typescript = require('../../../../scripts/rollup/typescript'); const writeDistAndTypes = require('../../../../scripts/rollup/writeDistAndTypes'); +const lwcFeatures = require('../../../../scripts/rollup/lwcFeatures'); const { version } = require('../package.json'); const banner = `/* proxy-compat-disable */`; @@ -33,6 +34,7 @@ module.exports = { }), typescript(), writeDistAndTypes(), + lwcFeatures(), ], onwarn({ code, message }) { diff --git a/packages/@lwc/features/src/flags.ts b/packages/@lwc/features/src/flags.ts index e31c03932f..04ff3d6e16 100644 --- a/packages/@lwc/features/src/flags.ts +++ b/packages/@lwc/features/src/flags.ts @@ -8,6 +8,7 @@ import { create, keys, defineProperty, isUndefined, isBoolean, globalThis } from import { FeatureFlagMap, FeatureFlagName, FeatureFlagValue } from './types'; const features: FeatureFlagMap = { + DUMMY_TEST_FLAG: null, ENABLE_ELEMENT_PATCH: null, ENABLE_FORCE_NATIVE_SHADOW_MODE_FOR_TEST: null, ENABLE_HMR: null, diff --git a/packages/@lwc/features/src/types.ts b/packages/@lwc/features/src/types.ts index bc6d7186c7..348e6f2155 100644 --- a/packages/@lwc/features/src/types.ts +++ b/packages/@lwc/features/src/types.ts @@ -16,6 +16,11 @@ export type FeatureFlagValue = boolean | null; export interface FeatureFlagMap { + /** + * This is only used to test that feature flags are actually working + */ + DUMMY_TEST_FLAG: FeatureFlagValue; + /** * LWC engine flag to enable mixed shadow mode. Setting this flag to `true` enables usage of * native shadow DOM even when the synthetic shadow polyfill is applied. diff --git a/packages/@lwc/synthetic-shadow/src/index.ts b/packages/@lwc/synthetic-shadow/src/index.ts index cc64722ee7..135e45cd1a 100644 --- a/packages/@lwc/synthetic-shadow/src/index.ts +++ b/packages/@lwc/synthetic-shadow/src/index.ts @@ -39,3 +39,6 @@ import './faux-shadow/html-element'; import './faux-shadow/slot'; import './faux-shadow/portal'; import './faux-shadow/shadow-token'; + +// Tests +import './testFeatureFlag'; diff --git a/packages/@lwc/synthetic-shadow/src/testFeatureFlag.ts b/packages/@lwc/synthetic-shadow/src/testFeatureFlag.ts new file mode 100644 index 0000000000..a4fbab8348 --- /dev/null +++ b/packages/@lwc/synthetic-shadow/src/testFeatureFlag.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, 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 + */ + +import features from '@lwc/features'; + +if (process.env.NODE_ENV !== 'production' && typeof window !== 'undefined') { + window.addEventListener('test-dummy-flag', () => { + let hasFlag = false; + if (features.DUMMY_TEST_FLAG) { + hasFlag = true; + } + + window.dispatchEvent( + new CustomEvent('has-dummy-flag', { + detail: { + package: '@lwc/synthetic-shadow', + hasFlag, + }, + }) + ); + }); +} diff --git a/packages/integration-karma/scripts/karma-plugins/env.js b/packages/integration-karma/scripts/karma-plugins/env.js index 37048e3696..833a1c385f 100644 --- a/packages/integration-karma/scripts/karma-plugins/env.js +++ b/packages/integration-karma/scripts/karma-plugins/env.js @@ -42,6 +42,7 @@ function createEnvFile() { MIXED_SHADOW: ${FORCE_NATIVE_SHADOW_MODE_FOR_TEST}, NATIVE_SHADOW: ${!SYNTHETIC_SHADOW_ENABLED || FORCE_NATIVE_SHADOW_MODE_FOR_TEST}, NATIVE_SHADOW_ROOT_DEFINED: typeof ShadowRoot !== 'undefined', + SYNTHETIC_SHADOW_ENABLED: ${SYNTHETIC_SHADOW_ENABLED}, LWC_VERSION: ${JSON.stringify(LWC_VERSION)} } }; diff --git a/packages/integration-karma/test/features/index.spec.js b/packages/integration-karma/test/features/index.spec.js new file mode 100644 index 0000000000..caf0706547 --- /dev/null +++ b/packages/integration-karma/test/features/index.spec.js @@ -0,0 +1,46 @@ +import { setFeatureFlagForTest } from 'lwc'; + +describe('feature flags', () => { + let packages; + + const onHasDummyFlag = (event) => { + if (event.detail.hasFlag) { + packages.push(event.detail.package); + } + }; + + beforeEach(() => { + packages = []; + window.addEventListener('has-dummy-flag', onHasDummyFlag); + }); + + afterEach(() => { + window.removeEventListener('has-dummy-flag', onHasDummyFlag); + }); + + describe('flag enabled', () => { + beforeEach(() => { + setFeatureFlagForTest('DUMMY_TEST_FLAG', true); + }); + + afterEach(() => { + setFeatureFlagForTest('DUMMY_TEST_FLAG', false); + }); + + it('works', () => { + window.dispatchEvent(new CustomEvent('test-dummy-flag')); + const expected = ['@lwc/engine-core', '@lwc/engine-dom']; + if (process.env.SYNTHETIC_SHADOW_ENABLED) { + expected.push('@lwc/synthetic-shadow'); + } + expect(packages.sort()).toEqual(expected); + }); + }); + + describe('flag disabled', () => { + it('works', () => { + window.dispatchEvent(new CustomEvent('test-dummy-flag')); + expect(packages.sort()).toEqual([]); + }); + }); +}); diff --git a/scripts/rollup/lwcFeatures.js b/scripts/rollup/lwcFeatures.js index ef4e2aa71f..39015049ec 100644 --- a/scripts/rollup/lwcFeatures.js +++ b/scripts/rollup/lwcFeatures.js @@ -14,8 +14,13 @@ module.exports = function lwcFeatures() { return { id: 'rollup-plugin-lwc-features', transform(source, id) { - if (id.includes('/node_modules/') || !source.includes('@lwc/features')) { + if ( + id.includes('/node_modules/') || + id.includes('/dist/') || + !source.includes('@lwc/features') + ) { // Skip 3rd-party files and files that don't mention @lwc/features + // Also skip /dist/ files because these have presumably already been run through lwcFeatures return null; } return babel.transform(source, {