Skip to content

Commit f681712

Browse files
committed
feat(compiler): Implement constant propagation for template literals (facebook#33139)
New take on facebook#29716 ## Summary Template literals consisting entirely of constant values will be inlined to a string literal, effectively replacing the backticks with a double quote. This is done primarily to make the resulting instruction a string literal, so it can be processed further in constant propatation. So this is now correctly simplified to `true`: ```js `` === "" // now true `a${1}` === "a1" // now true ``` If a template string literal can only partially be comptime-evaluated, it is not that useful for dead code elimination or further constant folding steps and thus, is left as-is in that case. Same is true if the literal contains an array, object, symbol or function. ## How did you test this change? See added tests. DiffTrain build for [ac06829](facebook@ac06829)
1 parent 87da0ba commit f681712

35 files changed

+132
-86
lines changed

compiled/eslint-plugin-react-hooks/index.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40446,6 +40446,52 @@ function evaluateInstruction(constants, instr) {
4044640446
}
4044740447
return null;
4044840448
}
40449+
case 'TemplateLiteral': {
40450+
if (value.subexprs.length === 0) {
40451+
const result = {
40452+
kind: 'Primitive',
40453+
value: value.quasis.map(q => q.cooked).join(''),
40454+
loc: value.loc,
40455+
};
40456+
instr.value = result;
40457+
return result;
40458+
}
40459+
if (value.subexprs.length !== value.quasis.length - 1) {
40460+
return null;
40461+
}
40462+
if (value.quasis.some(q => q.cooked === undefined)) {
40463+
return null;
40464+
}
40465+
let quasiIndex = 0;
40466+
let resultString = value.quasis[quasiIndex].cooked;
40467+
++quasiIndex;
40468+
for (const subExpr of value.subexprs) {
40469+
const subExprValue = read(constants, subExpr);
40470+
if (!subExprValue || subExprValue.kind !== 'Primitive') {
40471+
return null;
40472+
}
40473+
const expressionValue = subExprValue.value;
40474+
if (typeof expressionValue !== 'number' &&
40475+
typeof expressionValue !== 'string' &&
40476+
typeof expressionValue !== 'boolean' &&
40477+
!(typeof expressionValue === 'object' && expressionValue === null)) {
40478+
return null;
40479+
}
40480+
const suffix = value.quasis[quasiIndex].cooked;
40481+
++quasiIndex;
40482+
if (suffix === undefined) {
40483+
return null;
40484+
}
40485+
resultString = resultString.concat(expressionValue, suffix);
40486+
}
40487+
const result = {
40488+
kind: 'Primitive',
40489+
value: resultString,
40490+
loc: value.loc,
40491+
};
40492+
instr.value = result;
40493+
return result;
40494+
}
4044940495
case 'LoadLocal': {
4045040496
const placeValue = read(constants, value.place);
4045140497
if (placeValue !== null) {

compiled/facebook-www/REVISION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8a8df5dbdd57bf63d5156c1a9cba21ac6106b83d
1+
ac06829246287751e6b74bd99cd1b39d1aeba06a
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8a8df5dbdd57bf63d5156c1a9cba21ac6106b83d
1+
ac06829246287751e6b74bd99cd1b39d1aeba06a

compiled/facebook-www/React-dev.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1538,7 +1538,7 @@ __DEV__ &&
15381538
exports.useTransition = function () {
15391539
return resolveDispatcher().useTransition();
15401540
};
1541-
exports.version = "19.2.0-www-classic-8a8df5db-20250507";
1541+
exports.version = "19.2.0-www-classic-ac068292-20250508";
15421542
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
15431543
"function" ===
15441544
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-dev.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1538,7 +1538,7 @@ __DEV__ &&
15381538
exports.useTransition = function () {
15391539
return resolveDispatcher().useTransition();
15401540
};
1541-
exports.version = "19.2.0-www-modern-8a8df5db-20250507";
1541+
exports.version = "19.2.0-www-modern-ac068292-20250508";
15421542
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
15431543
"function" ===
15441544
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-prod.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,4 +636,4 @@ exports.useSyncExternalStore = function (
636636
exports.useTransition = function () {
637637
return ReactSharedInternals.H.useTransition();
638638
};
639-
exports.version = "19.2.0-www-classic-8a8df5db-20250507";
639+
exports.version = "19.2.0-www-classic-ac068292-20250508";

compiled/facebook-www/React-prod.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,4 +636,4 @@ exports.useSyncExternalStore = function (
636636
exports.useTransition = function () {
637637
return ReactSharedInternals.H.useTransition();
638638
};
639-
exports.version = "19.2.0-www-modern-8a8df5db-20250507";
639+
exports.version = "19.2.0-www-modern-ac068292-20250508";

compiled/facebook-www/React-profiling.classic.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ exports.useSyncExternalStore = function (
640640
exports.useTransition = function () {
641641
return ReactSharedInternals.H.useTransition();
642642
};
643-
exports.version = "19.2.0-www-classic-8a8df5db-20250507";
643+
exports.version = "19.2.0-www-classic-ac068292-20250508";
644644
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
645645
"function" ===
646646
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/React-profiling.modern.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ exports.useSyncExternalStore = function (
640640
exports.useTransition = function () {
641641
return ReactSharedInternals.H.useTransition();
642642
};
643-
exports.version = "19.2.0-www-modern-8a8df5db-20250507";
643+
exports.version = "19.2.0-www-modern-ac068292-20250508";
644644
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
645645
"function" ===
646646
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

compiled/facebook-www/ReactART-dev.classic.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19032,10 +19032,10 @@ __DEV__ &&
1903219032
(function () {
1903319033
var internals = {
1903419034
bundleType: 1,
19035-
version: "19.2.0-www-classic-8a8df5db-20250507",
19035+
version: "19.2.0-www-classic-ac068292-20250508",
1903619036
rendererPackageName: "react-art",
1903719037
currentDispatcherRef: ReactSharedInternals,
19038-
reconcilerVersion: "19.2.0-www-classic-8a8df5db-20250507"
19038+
reconcilerVersion: "19.2.0-www-classic-ac068292-20250508"
1903919039
};
1904019040
internals.overrideHookState = overrideHookState;
1904119041
internals.overrideHookStateDeletePath = overrideHookStateDeletePath;
@@ -19069,7 +19069,7 @@ __DEV__ &&
1906919069
exports.Shape = Shape;
1907019070
exports.Surface = Surface;
1907119071
exports.Text = Text;
19072-
exports.version = "19.2.0-www-classic-8a8df5db-20250507";
19072+
exports.version = "19.2.0-www-classic-ac068292-20250508";
1907319073
"undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
1907419074
"function" ===
1907519075
typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&

0 commit comments

Comments
 (0)