Skip to content

Commit 00b56c9

Browse files
committed
refactor(wire-service): wire decorator reform
Squashed commit of the following: commit 0f00e08 Author: Jose David Rodriguez <jodarove@gmail.com> Date: Thu Sep 19 23:13:15 2019 -0700 refactor(wire-service): wire decorator reform Squashed commit of the following: commit fb136b7 Author: Caridy Patiño <caridy@gmail.com> Date: Thu Aug 29 23:59:16 2019 -0400 fix(wire-service): does not accept adapter id to be a symbol commit 91c2d97 Author: Caridy Patiño <caridy@gmail.com> Date: Thu Aug 29 15:04:19 2019 -0400 fix(engine): tests and karma tests fixes commit 719c41e Merge: 3cdf650 8e5035e Author: Caridy Patiño <caridy@gmail.com> Date: Sat Aug 31 14:31:07 2019 -0400 Merge branch 'master' into caridy/wire-reform-2 commit 8e5035e Author: Caridy Patiño <caridy@gmail.com> Date: Fri Aug 30 22:25:49 2019 -0400 refactor: hidden fields instead of internal fields (2) (#1485) * chore: package-unique keys for engine and synthetic shadow * refactor: remove internal fields in favor of hidden fields * fix: avoid returning boolean false when field undefined * test: use hidden fields instead of internal fields * refactor(synthetic-shadow): hidden fields instead of internal fields * chore(synthetic-shadow): "unique" string keys * fix(engine): issue 1299 second attempt * fix(engine): removing hasOwnProperty check * chore: revert changes for vm access by getComponentConstructor commit 9a7f822 Author: Ravi Jayaramappa <ravi.jayaramappa@salesforce.com> Date: Thu Aug 29 14:05:57 2019 -0700 fix: cloneNode() default behavior should match spec (#1480) commit 3cdf650 Author: Caridy Patiño <caridy@gmail.com> Date: Thu Aug 29 05:40:52 2019 -0400 fix(engine): context to work as expected commit 2224bd2 Author: Caridy Patiño <caridy@gmail.com> Date: Thu Aug 29 04:38:45 2019 -0400 fix(engine): karma tests for context providers commit 8b6c978 Merge: d02243b 5d5f7af Author: Caridy Patiño <caridy@gmail.com> Date: Thu Aug 29 04:33:58 2019 -0400 Merge branch 'caridy/wire-reform-2' of github.com:salesforce/lwc into caridy/wire-reform-2 commit 5d5f7af Author: Jose David Rodriguez <jodarove@gmail.com> Date: Fri Aug 30 13:30:34 2019 -0700 fix: observable-fields commit a901a64 Author: Jose David Rodriguez <jodarove@gmail.com> Date: Thu Aug 29 22:41:50 2019 -0700 wip: wire register is broken it was making karma fail commit d02243b Author: Caridy Patiño <caridy@gmail.com> Date: Wed Aug 28 07:46:56 2019 -0400 fix(engine): remove unnecessary comment commit c9ad2c5 Author: Caridy Patiño <caridy@gmail.com> Date: Wed Aug 28 02:59:29 2019 -0400 refactor(engine): context provider options commit 6bcf0be Author: Caridy Patiño <caridy@gmail.com> Date: Tue Jul 16 23:03:56 2019 -0400 fix(engine): @wire() protocol reform RFC fix: rebase issues fix: wire-reform tests (#1524) * fix: invalid syntax error on invalid wire param value When a wire parameter has invalid value (eg: foo..bar, foo.bar[3]) it should (ideally) resolve in a compilation error during validation phase. This is not possible due that platform components may have a param definition which is invalid but passes compilation, and throwing at compile time would break such components. In such cases where the param does not have proper notation, the config generated will use the bracket notation to match the current behavior (that most likely end up resolving that param as undefined). * fix: tests for wire reactive parameters * fix: unit test register and WireAdapter * fix: backward compability when adding config listener * fix: adding general tests for wire adapter * wip: address pr comments and lint errors fix: reactivity of wire params (#1526) * fix: reactivity of wire params * wip: address review comments and run performance * wip: trigger perf measures * fix: remove valueMutated pruning condition * fix: add componentValueObserved for consistency * fix: remove tf because of wired properties being track before the wire reform. * fix: ensure component rerender in compat * fix: tf because registerDecorators happens before registerAdapter * Revert "fix: tf because registerDecorators happens before registerAdapter" This reverts commit b2d1a89. * fix: wire integration tests fix: rebase issues fix: remove tests because wire defs is not part of the public api of getComponentDef fix: add test for inherited methods fix: context in targets hierarchy
1 parent 03231bb commit 00b56c9

File tree

68 files changed

+2331
-2975
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+2331
-2975
lines changed

packages/@lwc/babel-plugin-component/src/__tests__/wire-decorator.spec.js

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,112 @@ describe('Transform property', () => {
586586
}
587587
);
588588

589+
pluginTest(
590+
"config function should use bracket notation for param when it's definition has invalid identifier as segment",
591+
`
592+
import { api, wire } from 'lwc';
593+
import { getFoo } from 'data-service';
594+
export default class Test {
595+
@wire(getFoo, { key1: "$prop1.a b", key2: "$p1.p2" })
596+
wiredProp;
597+
}
598+
`,
599+
{
600+
output: {
601+
code: `
602+
import { registerDecorators as _registerDecorators } from "lwc";
603+
import _tmpl from "./test.html";
604+
import { registerComponent as _registerComponent } from "lwc";
605+
import { getFoo } from "data-service";
606+
607+
class Test {
608+
constructor() {
609+
this.wiredProp = void 0;
610+
}
611+
}
612+
613+
_registerDecorators(Test, {
614+
wire: {
615+
wiredProp: {
616+
adapter: getFoo,
617+
params: {
618+
key1: "prop1.a b",
619+
key2: "p1.p2"
620+
},
621+
static: {},
622+
config: function($cmp) {
623+
let v1 = $cmp["prop1"];
624+
let v2 = $cmp.p1;
625+
return {
626+
key1: v1 != null ? v1["a b"] : undefined,
627+
key2: v2 != null ? v2.p2 : undefined
628+
};
629+
}
630+
}
631+
}
632+
});
633+
634+
export default _registerComponent(Test, {
635+
tmpl: _tmpl
636+
});
637+
`,
638+
},
639+
}
640+
);
641+
642+
pluginTest(
643+
'config function should use bracket notation when param definition has empty segment',
644+
`
645+
import { api, wire } from 'lwc';
646+
import { getFoo } from 'data-service';
647+
export default class Test {
648+
@wire(getFoo, { key1: "$prop1..prop2", key2: ["fixed", 'array']})
649+
wiredProp;
650+
}
651+
`,
652+
{
653+
output: {
654+
code: `
655+
import { registerDecorators as _registerDecorators } from "lwc";
656+
import _tmpl from "./test.html";
657+
import { registerComponent as _registerComponent } from "lwc";
658+
import { getFoo } from "data-service";
659+
660+
class Test {
661+
constructor() {
662+
this.wiredProp = void 0;
663+
}
664+
}
665+
666+
_registerDecorators(Test, {
667+
wire: {
668+
wiredProp: {
669+
adapter: getFoo,
670+
params: {
671+
key1: "prop1..prop2"
672+
},
673+
static: {
674+
key2: ["fixed", "array"]
675+
},
676+
config: function($cmp) {
677+
let v1 = $cmp["prop1"];
678+
return {
679+
key2: ["fixed", "array"],
680+
key1: v1 != null && (v1 = v1[""]) != null ? v1["prop2"] : undefined
681+
};
682+
}
683+
}
684+
}
685+
});
686+
687+
export default _registerComponent(Test, {
688+
tmpl: _tmpl
689+
});
690+
`,
691+
},
692+
}
693+
);
694+
589695
pluginTest(
590696
'throws when wired property is combined with @track',
591697
`

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const LWC_API_WHITELIST = new Set([
4040
'getComponentDef',
4141
'getComponentConstructor',
4242
'isComponentConstructor',
43+
'createContextProvider',
4344
'readonly',
4445
'register',
4546
'setFeatureFlagForTest',

packages/@lwc/babel-plugin-component/src/decorators/wire/transform.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,22 @@ function getGeneratedConfig(t, wiredValue) {
4343
const configBlockBody = [];
4444
const configProps = [];
4545
const generateParameterConfigValue = memberExprPaths => {
46+
// Note: When memberExprPaths ($foo.bar) has an invalid identifier (eg: foo..bar, foo.bar[3])
47+
// it should (ideally) resolve in a compilation error during validation phase.
48+
// This is not possible due that platform components may have a param definition which is invalid
49+
// but passes compilation, and throwing at compile time would break such components.
50+
// In such cases where the param does not have proper notation, the config generated will use the bracket
51+
// notation to match the current behavior (that most likely end up resolving that param as undefined).
52+
const isInvalidMemberExpr = memberExprPaths.some(
53+
maybeIdentifier => !t.isValidES3Identifier(maybeIdentifier)
54+
);
55+
const memberExprPropertyGen = !isInvalidMemberExpr ? t.identifier : t.StringLiteral;
56+
4657
if (memberExprPaths.length === 1) {
4758
return {
4859
configValueExpression: t.memberExpression(
4960
t.identifier(WIRE_CONFIG_ARG_NAME),
50-
t.identifier(memberExprPaths[0])
61+
memberExprPropertyGen(memberExprPaths[0])
5162
),
5263
};
5364
}
@@ -58,7 +69,8 @@ function getGeneratedConfig(t, wiredValue) {
5869
t.identifier(varName),
5970
t.memberExpression(
6071
t.identifier(WIRE_CONFIG_ARG_NAME),
61-
t.identifier(memberExprPaths[0])
72+
memberExprPropertyGen(memberExprPaths[0]),
73+
isInvalidMemberExpr
6274
)
6375
),
6476
]);
@@ -70,7 +82,11 @@ function getGeneratedConfig(t, wiredValue) {
7082
const nextPropValue = t.assignmentExpression(
7183
'=',
7284
t.identifier(varName),
73-
t.memberExpression(t.identifier(varName), t.identifier(memberExprPaths[i]))
85+
t.memberExpression(
86+
t.identifier(varName),
87+
memberExprPropertyGen(memberExprPaths[i]),
88+
isInvalidMemberExpr
89+
)
7490
);
7591

7692
conditionTest = t.logicalExpression(
@@ -85,7 +101,8 @@ function getGeneratedConfig(t, wiredValue) {
85101
conditionTest,
86102
t.memberExpression(
87103
t.identifier(varName),
88-
t.identifier(memberExprPaths[memberExprPaths.length - 1])
104+
memberExprPropertyGen(memberExprPaths[memberExprPaths.length - 1]),
105+
isInvalidMemberExpr
89106
),
90107
t.identifier('undefined')
91108
);

packages/@lwc/engine/src/framework/__tests__/error-boundary.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,7 @@ describe('error boundary component', () => {
979979
}
980980
}
981981
registerDecorators(PreErrorChildContent, {
982-
publicProps: { foo: { config: 1 } },
982+
publicProps: { foo: { config: 3 } },
983983
});
984984
const baseTmpl = compileTemplate(
985985
`

packages/@lwc/engine/src/framework/__tests__/html-element.spec.ts

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -494,10 +494,7 @@ describe('html-element', () => {
494494
}
495495
}
496496
registerDecorators(MyComponent, {
497-
publicProps: { foo: {} },
498-
});
499-
500-
registerDecorators(MyComponent, {
497+
publicProps: { foo: { config: 3 } },
501498
track: { state: 1 },
502499
});
503500

@@ -550,7 +547,7 @@ describe('html-element', () => {
550547
}
551548
}
552549
registerDecorators(MyComponent, {
553-
publicProps: { role: {} },
550+
publicProps: { role: { config: 3 } },
554551
});
555552
const element = createElement('prop-getter-aria-role', { is: MyComponent });
556553
document.body.appendChild(element);
@@ -588,7 +585,7 @@ describe('html-element', () => {
588585
}
589586
}
590587
registerDecorators(MyComponent, {
591-
publicProps: { lang: {} },
588+
publicProps: { lang: { config: 3 } },
592589
});
593590

594591
const element = createElement('prop-setter-lang', { is: MyComponent });
@@ -634,7 +631,7 @@ describe('html-element', () => {
634631
}
635632
}
636633
registerDecorators(MyComponent, {
637-
publicProps: { lang: {} },
634+
publicProps: { lang: { config: 1 } },
638635
});
639636

640637
const element = createElement('prop-getter-lang-imperative', { is: MyComponent });
@@ -708,7 +705,7 @@ describe('html-element', () => {
708705
}
709706
}
710707
registerDecorators(MyComponent, {
711-
publicProps: { hidden: {} },
708+
publicProps: { hidden: { config: 3 } },
712709
});
713710

714711
const element = createElement('prop-setter-hidden', { is: MyComponent });
@@ -753,7 +750,7 @@ describe('html-element', () => {
753750
}
754751
}
755752
registerDecorators(MyComponent, {
756-
publicProps: { hidden: {} },
753+
publicProps: { hidden: { config: 1 } },
757754
});
758755

759756
const element = createElement('prop-getter-hidden-imperative', { is: MyComponent });
@@ -831,7 +828,7 @@ describe('html-element', () => {
831828
}
832829

833830
registerDecorators(MyComponent, {
834-
publicProps: { dir: {} },
831+
publicProps: { dir: { config: 3 } },
835832
});
836833

837834
const element = createElement('prop-setter-dir', { is: MyComponent });
@@ -877,7 +874,7 @@ describe('html-element', () => {
877874
}
878875
}
879876
registerDecorators(MyComponent, {
880-
publicProps: { dir: {} },
877+
publicProps: { dir: { config: 1 } },
881878
});
882879

883880
const element = createElement('prop-getter-dir-imperative', { is: MyComponent });
@@ -953,7 +950,7 @@ describe('html-element', () => {
953950
}
954951
}
955952
registerDecorators(MyComponent, {
956-
publicProps: { id: {} },
953+
publicProps: { id: { config: 3 } },
957954
});
958955

959956
const element = createElement('prop-setter-id', { is: MyComponent });
@@ -999,7 +996,7 @@ describe('html-element', () => {
999996
}
1000997
}
1001998
registerDecorators(MyComponent, {
1002-
publicProps: { id: {} },
999+
publicProps: { id: { config: 1 } },
10031000
});
10041001

10051002
const element = createElement('prop-getter-id-imperative', { is: MyComponent });
@@ -1077,7 +1074,7 @@ describe('html-element', () => {
10771074
}
10781075
}
10791076
registerDecorators(MyComponent, {
1080-
publicProps: { accessKey: {} },
1077+
publicProps: { accessKey: { config: 3 } },
10811078
});
10821079

10831080
const element = createElement('prop-setter-accessKey', { is: MyComponent });
@@ -1124,7 +1121,7 @@ describe('html-element', () => {
11241121
}
11251122
}
11261123
registerDecorators(MyComponent, {
1127-
publicProps: { accessKey: {} },
1124+
publicProps: { accessKey: { config: 1 } },
11281125
});
11291126
const element = createElement('prop-getter-accessKey-imperative', {
11301127
is: MyComponent,
@@ -1201,7 +1198,7 @@ describe('html-element', () => {
12011198
}
12021199
}
12031200
registerDecorators(MyComponent, {
1204-
publicProps: { title: {} },
1201+
publicProps: { title: { config: 3 } },
12051202
});
12061203
const element = createElement('prop-setter-title', { is: MyComponent });
12071204
(element.title = {}), expect(count).toBe(1);
@@ -1244,7 +1241,7 @@ describe('html-element', () => {
12441241
}
12451242
}
12461243
registerDecorators(MyComponent, {
1247-
publicProps: { title: {} },
1244+
publicProps: { title: { config: 1 } },
12481245
});
12491246

12501247
const element = createElement('prop-getter-title-imperative', { is: MyComponent });

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

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,15 @@
1313
* shape of a component. It is also used internally to apply extra optimizations.
1414
*/
1515
import {
16-
ArrayReduce,
1716
assert,
1817
create,
1918
defineProperties,
2019
fields,
2120
freeze,
22-
getOwnPropertyNames,
23-
isFalse,
2421
isFunction,
2522
isNull,
26-
isObject,
2723
seal,
24+
isObject,
2825
} from '@lwc/shared';
2926
import { logError } from '../shared/assert';
3027
import { HTMLElementOriginalDescriptors } from './html-properties';
@@ -38,7 +35,7 @@ import {
3835
import { ViewModelReflection, EmptyObject } from './utils';
3936
import { vmBeingConstructed, isBeingConstructed, isRendering, vmBeingRendered } from './invoker';
4037
import { getComponentVM, VM } from './vm';
41-
import { valueObserved, valueMutated } from '../libs/mutation-tracker';
38+
import { componentValueMutated, componentValueObserved } from './mutation-tracker';
4239
import { dispatchEvent } from '../env/dom';
4340
import { patchComponentWithRestrictions, patchShadowRootWithRestrictions } from './restrictions';
4441
import { unlockAttribute, lockAttribute } from './attributes';
@@ -93,7 +90,7 @@ function createBridgeToElementDescriptor(
9390
}
9491
return;
9592
}
96-
valueObserved(this, propName);
93+
componentValueObserved(vm, propName);
9794
return get.call(vm.elm);
9895
},
9996
set(this: ComponentInterface, newValue: any) {
@@ -118,10 +115,8 @@ function createBridgeToElementDescriptor(
118115

119116
if (newValue !== vm.cmpProps[propName]) {
120117
vm.cmpProps[propName] = newValue;
121-
if (isFalse(vm.isDirty)) {
122-
// perf optimization to skip this step if not in the DOM
123-
valueMutated(this, propName);
124-
}
118+
119+
componentValueMutated(vm, propName);
125120
}
126121
return set.call(vm.elm, newValue);
127122
},
@@ -564,22 +559,15 @@ BaseLightningElementConstructor.prototype = {
564559
},
565560
};
566561

567-
// Typescript is inferring the wrong function type for this particular
568-
// overloaded method: https://github.com/Microsoft/TypeScript/issues/27972
569-
// @ts-ignore type-mismatch
570-
const baseDescriptors: PropertyDescriptorMap = ArrayReduce.call(
571-
getOwnPropertyNames(HTMLElementOriginalDescriptors),
572-
(descriptors: PropertyDescriptorMap, propName: string) => {
573-
descriptors[propName] = createBridgeToElementDescriptor(
574-
propName,
575-
HTMLElementOriginalDescriptors[propName]
576-
);
577-
return descriptors;
578-
},
579-
create(null)
580-
);
562+
export const lightningBasedDescriptors: PropertyDescriptorMap = create(null);
563+
for (const propName in HTMLElementOriginalDescriptors) {
564+
lightningBasedDescriptors[propName] = createBridgeToElementDescriptor(
565+
propName,
566+
HTMLElementOriginalDescriptors[propName]
567+
);
568+
}
581569

582-
defineProperties(BaseLightningElementConstructor.prototype, baseDescriptors);
570+
defineProperties(BaseLightningElementConstructor.prototype, lightningBasedDescriptors);
583571

584572
if (process.env.NODE_ENV !== 'production') {
585573
patchLightningElementPrototypeWithRestrictions(BaseLightningElementConstructor.prototype);

0 commit comments

Comments
 (0)