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

feat: allow computed properties in @wire if they are constants or primitives @W-14785085 #3955

Merged
merged 13 commits into from
Jan 22, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This diff is git being silly. I deleted the old file because it was a duplicate of another test, and the new file is unrelated.

Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { wire, LightningElement } from "lwc";
import { Foo } from "data-service";
import { getFoo } from "data-service";
export default class Test extends LightningElement {
@wire(Foo.Bar, {}) wiredProp;
@wire(getFoo, {
method() {}
})
wiredProp;
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { registerDecorators as _registerDecorators, registerComponent as _registerComponent, LightningElement } from "lwc";
import _tmpl from "./test.html";
import { Foo } from "data-service";
import { getFoo } from "data-service";
class Test extends LightningElement {
wiredProp;
/*LWC compiler vX.X.X*/
}
_registerDecorators(Test, {
wire: {
wiredProp: {
adapter: Foo.Bar,
adapter: getFoo,
dynamic: [],
config: function ($cmp) {
return {};
return {
method() {}
};
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { wire, LightningElement } from "lwc";
import { getFoo } from "data-service";
const spreadMe = {
key1: "$prop2"
}
export default class Test extends LightningElement {
@wire(getFoo, {
...spreadMe,
...({key2: "$prop2"})
})
wiredProp;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { registerDecorators as _registerDecorators, registerComponent as _registerComponent, LightningElement } from "lwc";
import _tmpl from "./test.html";
import { getFoo } from "data-service";
const spreadMe = {
key1: "$prop2"
};
class Test extends LightningElement {
wiredProp;
/*LWC compiler vX.X.X*/
}
_registerDecorators(Test, {
wire: {
wiredProp: {
adapter: getFoo,
dynamic: [],
config: function ($cmp) {
return {
...spreadMe,
...{
key2: "$prop2"
}
};
}
}
}
});
export default _registerComponent(Test, {
tmpl: _tmpl,
sel: "lwc-test",
apiVersion: 9999999
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { wire, LightningElement } from "lwc";
import { getFoo } from "data-service";
const symbol = Symbol.for("key");
export default class Test extends LightningElement {
// accidentally an array expression = oops!
@wire(getFoo, { [[symbol]]: "$prop1", key2: ["fixed", "array"] })
wiredFoo;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"message": "LWC1200: Computed property in @wire config must be a constant or primitive literal.",
"loc": {
"line": 6,
"column": 19,
"start": 237,
"length": 8
},
"filename": "test.js"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { wire, LightningElement } from "lwc";
import { getFoo } from "data-service";
let key1 = 'key1'
export default class Test extends LightningElement {
@wire(getFoo, { [key1]: "$prop1", key2: ["fixed", "array"] })
wiredFoo;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"message": "LWC1200: Computed property in @wire config must be a constant or primitive literal.",
"loc": {
"line": 5,
"column": 19,
"start": 175,
"length": 4
},
"filename": "test.js"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { wire, LightningElement } from "lwc";
import { getFoo } from "data-service";
export default class Test extends LightningElement {
@wire(getFoo, { [/key1/]: "$prop1", key2: ["fixed", "array"] })
wiredFoo;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"message": "LWC1200: Computed property in @wire config must be a constant or primitive literal.",
"loc": {
"line": 4,
"column": 19,
"start": 157,
"length": 6
},
"filename": "test.js"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { wire, LightningElement } from "lwc";
import { getFoo } from "data-service";
export default class Test extends LightningElement {
@wire(getFoo, { [`key1`]: "$prop1", key2: ["fixed", "array"] })
wiredFoo;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"message": "LWC1199: Cannot use a template literal as a computed property key. Instead, use a string or extract the value to a constant.",
"loc": {
"line": 4,
"column": 19,
"start": 157,
"length": 6
},
"filename": "test.js"
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { wire, LightningElement } from "lwc";
import { getFoo, getBar } from "data-service";
const key1 = Symbol.for("key");
export default class Test extends LightningElement {
@wire(getBar, { [key1]: "$prop1", key2: ["fixed", "array"] })
wiredBar;

// eslint-disable-next-line no-useless-computed-key
@wire(getFoo, { ["key1"]: "$prop1", key2: ["fixed", "array"] })
wiredFoo;
const symbol = Symbol.for("key");
export default class Test extends LightningElement {
@wire(getFoo, {
[symbol]: '$prop'
})
wiredIdentifier;

@wire(getBar, {
['computedStringLiteral']: '$prop',
[123n]: '$prop',
[321]: '$prop',
[null]: '$prop',
[undefined]: '$prop'
})
wiredPrimitives;
}
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
import { registerDecorators as _registerDecorators, registerComponent as _registerComponent, LightningElement } from "lwc";
import _tmpl from "./test.html";
import { getFoo, getBar } from "data-service";
const key1 = Symbol.for("key");
const symbol = Symbol.for("key");
class Test extends LightningElement {
wiredBar;

// eslint-disable-next-line no-useless-computed-key
wiredFoo;
wiredIdentifier;
wiredPrimitives;
/*LWC compiler vX.X.X*/
}
_registerDecorators(Test, {
wire: {
wiredBar: {
adapter: getBar,
dynamic: [key1],
wiredIdentifier: {
adapter: getFoo,
dynamic: [symbol],
config: function ($cmp) {
return {
key2: ["fixed", "array"],
[key1]: $cmp.prop1
[symbol]: $cmp.prop
};
}
},
wiredFoo: {
adapter: getFoo,
dynamic: ["key1"],
wiredPrimitives: {
adapter: getBar,
dynamic: ["computedStringLiteral", "123", "321", "null", undefined],
config: function ($cmp) {
return {
key2: ["fixed", "array"],
["key1"]: $cmp.prop1
['computedStringLiteral']: $cmp.prop,
[123n]: $cmp.prop,
[321]: $cmp.prop,
[null]: $cmp.prop,
[undefined]: $cmp.prop
};
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { wire, LightningElement } from "lwc";
import { getFoo } from "data-service";
export default class Test extends LightningElement {
// Did you know numeric literals can be used as property keys? This becomes "123"!
@wire(getFoo, { 1.2_3e2: "$prop" })
wiredProp;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { registerDecorators as _registerDecorators, registerComponent as _registerComponent, LightningElement } from "lwc";
import _tmpl from "./test.html";
import { getFoo } from "data-service";
class Test extends LightningElement {
// Did you know numeric literals can be used as property keys? This becomes "123"!
wiredProp;
/*LWC compiler vX.X.X*/
}
_registerDecorators(Test, {
wire: {
wiredProp: {
adapter: getFoo,
dynamic: ["123"],
config: function ($cmp) {
return {
1.2_3e2: $cmp.prop
};
}
}
}
});
export default _registerComponent(Test, {
tmpl: _tmpl,
sel: "lwc-test",
apiVersion: 9999999
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* 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
Expand Down Expand Up @@ -175,12 +175,22 @@ function buildWireConfigValue(t: BabelTypes, wiredValues: WiredValue[]) {

if (wiredValue.params) {
const dynamicParamNames = wiredValue.params.map((p) => {
const value = t.isIdentifier(p.key)
? p.key.name
: (p.key as types.StringLiteral).value;
return p.computed && t.isIdentifier(p.key)
? t.identifier(value)
: t.stringLiteral(value);
if (t.isIdentifier(p.key)) {
return p.computed ? t.identifier(p.key.name) : t.stringLiteral(p.key.name);
} else if (
t.isLiteral(p.key) &&
// Template literals may contain expressions, so they are not allowed
!t.isTemplateLiteral(p.key) &&
// RegExp are not primitives, so they are not allowed
!t.isRegExpLiteral(p.key)
) {
const value = t.isNullLiteral(p.key) ? null : p.key.value;
return t.stringLiteral(String(value));
}
// If it's not an identifier or primitive literal then it's a computed expression
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fall through will probably never occur, because it should already be covered by the validation, but we should still play it safe.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add this as a comment here? You can also add /* istanbul ignore next */ to drive home the point that this code should never get hit.

throw new TypeError(
`Expected object property key to be an identifier or a literal, but instead saw "${p.key.type}".`
);
});
wireConfig.push(
t.objectProperty(t.identifier('dynamic'), t.arrayExpression(dynamicParamNames))
Expand Down
Loading