Skip to content

Commit 6455c37

Browse files
committed
feat: add enableSyntheticElementInternals flag
1 parent 1a8b40b commit 6455c37

File tree

11 files changed

+51
-2
lines changed

11 files changed

+51
-2
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { LightningElement as Component } from "lwc";
2+
3+
export default class Test extends Component {}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"enableSyntheticElementInternals": true
3+
}

packages/@lwc/babel-plugin-component/src/__tests__/fixtures/component/enable-synthetic-element-internals/error.json

Whitespace-only changes.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import _tmpl from "./test.html";
2+
import { LightningElement as Component, registerComponent as _registerComponent } from "lwc";
3+
class Test extends Component {
4+
/*LWC compiler vX.X.X*/
5+
}
6+
const __lwc_component_class_internal = _registerComponent(Test, {
7+
tmpl: _tmpl,
8+
sel: "lwc-test",
9+
apiVersion: 9999999,
10+
enableSyntheticElementInternals: true
11+
});
12+
export default __lwc_component_class_internal;

packages/@lwc/babel-plugin-component/src/component.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
TEMPLATE_KEY,
1515
API_VERSION_KEY,
1616
COMPONENT_CLASS_ID,
17+
SYNTHETIC_ELEMENT_INTERNALS_KEY,
1718
} from './constants';
1819
import type { types, NodePath, Visitor } from '@babel/core';
1920
import type { BabelAPI, BabelTypes, LwcBabelPluginPass } from './types';
@@ -75,6 +76,10 @@ export default function ({ types: t }: BabelAPI): Visitor<LwcBabelPluginPass> {
7576

7677
const apiVersion = getAPIVersionFromNumber(state.opts.apiVersion);
7778

79+
const supportsSyntheticElementInternals = t.booleanLiteral(
80+
state.opts.enableSyntheticElementInternals
81+
);
82+
7883
// Example:
7984
// registerComponent(cmp, {
8085
// tmpl: template,
@@ -89,6 +94,10 @@ export default function ({ types: t }: BabelAPI): Visitor<LwcBabelPluginPass> {
8994
// It's important that, at this point, we have an APIVersion rather than just a number.
9095
// The client needs to trust the server that it's providing an actual known API version
9196
t.objectProperty(t.identifier(API_VERSION_KEY), t.numericLiteral(apiVersion)),
97+
t.objectProperty(
98+
t.identifier(SYNTHETIC_ELEMENT_INTERNALS_KEY),
99+
supportsSyntheticElementInternals
100+
),
92101
]),
93102
]);
94103

packages/@lwc/babel-plugin-component/src/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const TEMPLATE_KEY = 'tmpl';
3434
const COMPONENT_NAME_KEY = 'sel';
3535
const API_VERSION_KEY = 'apiVersion';
3636
const COMPONENT_CLASS_ID = '__lwc_component_class_internal';
37+
const SYNTHETIC_ELEMENT_INTERNALS_KEY = 'enableSyntheticElementInternals';
3738

3839
export {
3940
DECORATOR_TYPES,
@@ -46,4 +47,5 @@ export {
4647
COMPONENT_NAME_KEY,
4748
API_VERSION_KEY,
4849
COMPONENT_CLASS_ID,
50+
SYNTHETIC_ELEMENT_INTERNALS_KEY,
4951
};

packages/@lwc/babel-plugin-component/src/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export interface LwcBabelPluginOptions {
2121
name: string;
2222
instrumentation?: InstrumentationObject;
2323
apiVersion?: number;
24+
enableSyntheticElementInternals?: boolean;
2425
}
2526

2627
export interface LwcBabelPluginPass extends PluginPass {

packages/@lwc/compiler/src/options.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ export interface TransformOptions {
108108
experimentalDynamicDirective?: boolean;
109109
/** Flag to enable usage of dynamic component(lwc:is) directive in HTML template */
110110
enableDynamicComponents?: boolean;
111+
/** Flag to enable usage of ElementInternals in synthetic shadow DOM */
112+
enableSyntheticElementInternals?: boolean;
111113
// TODO [#3370]: remove experimental template expression flag
112114
/** Flag to enable use of (a subset of) JavaScript expressions in place of template bindings. Passed to `@lwc/template-compiler`. */
113115
experimentalComplexExpressions?: boolean;
@@ -153,6 +155,7 @@ type OptionalTransformKeys =
153155
| 'enableLwcOn'
154156
| 'enableLightningWebSecurityTransforms'
155157
| 'enableDynamicComponents'
158+
| 'enableSyntheticElementInternals'
156159
| 'experimentalDynamicDirective'
157160
| 'experimentalDynamicComponent'
158161
| 'instrumentation';

packages/@lwc/engine-core/src/framework/base-lightning-element.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ import {
3838
} from '../libs/reflection';
3939

4040
import { HTMLElementOriginalDescriptors } from './html-properties';
41-
import { getComponentAPIVersion, getWrappedComponentsListener } from './component';
41+
import {
42+
getComponentAPIVersion,
43+
getWrappedComponentsListener,
44+
supportsSyntheticElementInternals,
45+
} from './component';
4246
import { isBeingConstructed, isInvokingRender, vmBeingConstructed } from './invoker';
4347
import { associateVM, getAssociatedVM, RenderMode, ShadowMode } from './vm';
4448
import { componentValueObserved } from './mutation-tracker';
@@ -493,6 +497,7 @@ function warnIfInvokedDuringConstruction(vm: VM, methodOrPropName: string) {
493497
attachInternals(): ElementInternals {
494498
const vm = getAssociatedVM(this);
495499
const {
500+
def: { ctor },
496501
elm,
497502
apiVersion,
498503
renderer: { attachInternals },
@@ -507,7 +512,7 @@ function warnIfInvokedDuringConstruction(vm: VM, methodOrPropName: string) {
507512
}
508513

509514
const internals = attachInternals(elm);
510-
if (vm.shadowMode === ShadowMode.Synthetic) {
515+
if (supportsSyntheticElementInternals(ctor) && vm.shadowMode === ShadowMode.Synthetic) {
511516
const handler: ProxyHandler<ElementInternals> = {
512517
get(target: ElementInternals, prop: keyof ElementInternals) {
513518
if (prop === 'shadowRoot') {

packages/@lwc/engine-core/src/framework/component.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type ComponentConstructorMetadata = {
2424
tmpl: Template;
2525
sel: string;
2626
apiVersion: APIVersion;
27+
enableSyntheticElementInternals: boolean;
2728
};
2829
const registeredComponentMap: Map<LightningElementConstructor, ComponentConstructorMetadata> =
2930
new Map();
@@ -76,6 +77,12 @@ export function getComponentAPIVersion(Ctor: LightningElementConstructor): APIVe
7677
return apiVersion;
7778
}
7879

80+
export function supportsSyntheticElementInternals(
81+
Ctor: LightningElementConstructor
82+
): boolean | undefined {
83+
return registeredComponentMap.get(Ctor)?.enableSyntheticElementInternals;
84+
}
85+
7986
export function getTemplateReactiveObserver(vm: VM): ReactiveObserver {
8087
const reactiveObserver = createReactiveObserver(() => {
8188
const { isDirty } = vm;

0 commit comments

Comments
 (0)