Skip to content

Commit e93e4c8

Browse files
committed
fix(transformer/styled-components): template literal expressions order is wrong after minification (#12211)
Related: #12202 `swap_remove` will swap the last element to the index you want to remove, so this will cause the expression's order to be incorrect. Here is order sensitive, so we can't use `swap_remove`.
1 parent 1920c6b commit e93e4c8

File tree

3 files changed

+30
-30
lines changed
  • crates/oxc_transformer/src/plugins
  • tasks/transform_conformance
    • snapshots
    • tests/plugin-styled-components/test/fixtures/styled-components/minify-single-line-comments-with-interpolations

3 files changed

+30
-30
lines changed

crates/oxc_transformer/src/plugins/styled_components.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -407,28 +407,31 @@ impl<'a> StyledComponents<'a, '_> {
407407

408408
let (new_raws, remained_expression_indices) = CssMinifier::minify_quasis(quasis, ctx.ast);
409409

410-
// Remove expressions that are not kept after minification.
411-
for i in (0..expressions.len()).rev() {
412-
if !remained_expression_indices.contains(&i) {
413-
expressions.swap_remove(i);
414-
}
415-
}
416-
417410
// Update the quasis with the new raw values.
418411
for (new_raw, quais) in new_raws.into_iter().zip(quasis.iter_mut()) {
419412
quais.value.raw = new_raw;
420413
}
421414

422-
// SAFETY:
423-
// This is safe because template literal has ensured that `quasis` always
424-
// has one more element than `expressions`, and the `CSSMinifier` guarantees that
425-
// once a expression is removed, the corresponding quasi will also be removed.
426-
// Therefore, the length of `quasis` will always be one more than `expressions`.
427-
// So we can safely set the length of `quasis` to `expressions.len() + 1`.
428-
unsafe {
429-
// Set the length of `quasis` to `expressions.len() + 1` to truncate the quasis that
430-
// have been minified out.
431-
quasis.set_len(expressions.len() + 1);
415+
// Keep expressions that are still present after minification.
416+
if expressions.len() != remained_expression_indices.len() {
417+
let mut i = 0;
418+
expressions.retain(|_| {
419+
let keep = remained_expression_indices.contains(&i);
420+
i += 1;
421+
keep
422+
});
423+
424+
// SAFETY:
425+
// This is safe because template literal has ensured that `quasis` always
426+
// has one more element than `expressions`, and the `CSSMinifier` guarantees that
427+
// once a expression is removed, the corresponding quasi will also be removed.
428+
// Therefore, the length of `quasis` will always be one more than `expressions`.
429+
// So we can safely set the length of `quasis` to `expressions.len() + 1`.
430+
unsafe {
431+
// Set the length of `quasis` to `expressions.len() + 1` to truncate the quasis that
432+
// have been minified out.
433+
quasis.set_len(expressions.len() + 1);
434+
}
432435
}
433436
}
434437

tasks/transform_conformance/snapshots/oxc.snap.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
commit: 1d4546bc
22

3-
Passed: 175/293
3+
Passed: 176/293
44

55
# All Passed:
66
* babel-plugin-transform-class-static-block
@@ -1417,7 +1417,7 @@ after transform: ["Function", "babelHelpers"]
14171417
rebuilt : ["babelHelpers", "dec"]
14181418

14191419

1420-
# plugin-styled-components (19/34)
1420+
# plugin-styled-components (20/34)
14211421
* styled-components/add-identifier-with-top-level-import-paths/input.js
14221422
x Output mismatch
14231423

@@ -1439,9 +1439,6 @@ x Output mismatch
14391439
* styled-components/does-not-replace-native-with-no-tags/input.js
14401440
x Output mismatch
14411441

1442-
* styled-components/minify-single-line-comments-with-interpolations/input.js
1443-
x Output mismatch
1444-
14451442
* styled-components/pre-transpiled/input.js
14461443
x Output mismatch
14471444

tasks/transform_conformance/tests/plugin-styled-components/test/fixtures/styled-components/minify-single-line-comments-with-interpolations/output.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
import styled from 'styled-components';
22

3-
const Test1 = styled.div.withConfig({ displayName: "input__Test1", componentId: "sc-4bekfz-0" })(["width:100%;"]);
4-
const Test2 = styled.div.withConfig({ displayName: "input__Test2", componentId: "sc-4bekfz-1" })(["width:100%;"]);
5-
const Test3 = styled.div.withConfig({ displayName: "input__Test3", componentId: "sc-4bekfz-2" })(["width:100%;", ";"], 'red');
6-
const Test4 = styled.div.withConfig({ displayName: "input__Test4", componentId: "sc-4bekfz-3" })(["width:100%;"]);
7-
const Test5 = styled.div.withConfig({ displayName: "input__Test5", componentId: "sc-4bekfz-4" })(["width:100%;"]);
8-
const Test6 = styled.div.withConfig({ displayName: "input__Test6", componentId: "sc-4bekfz-5" })(
3+
const Test1 = styled.div.withConfig({ displayName: "input__Test1", componentId: "sc-lh68ek-0" })(["width:100%;"]);
4+
const Test2 = styled.div.withConfig({ displayName: "input__Test2", componentId: "sc-lh68ek-1" })(["width:100%;"]);
5+
const Test3 = styled.div.withConfig({ displayName: "input__Test3", componentId: "sc-lh68ek-2" })(["width:100%;", ";"], 'red');
6+
const Test4 = styled.div.withConfig({ displayName: "input__Test4", componentId: "sc-lh68ek-3" })(["width:100%;"]);
7+
const Test5 = styled.div.withConfig({ displayName: "input__Test5", componentId: "sc-lh68ek-4" })(["width:100%;"]);
8+
const Test6 = styled.div.withConfig({ displayName: "input__Test6", componentId: "sc-lh68ek-5" })(
99
["background:url(\"https://google.com\");width:100%;", ""],
1010
'green',
1111
);
12-
const Test7 = styled.div.withConfig({ displayName: "input__Test7", componentId: "sc-4bekfz-6" })(
12+
const Test7 = styled.div.withConfig({ displayName: "input__Test7", componentId: "sc-lh68ek-6" })(
1313
["background:url(\"https://google.com\");width:", ";", "height:", ";"],
1414
p => p.props.width,
1515
'green',
1616
p => p.props.height,
1717
);
18-
const Test8 = styled.div.withConfig({ displayName: "input__Test8", componentId: "sc-clieju-7" })(
18+
const Test8 = styled.div.withConfig({ displayName: "input__Test8", componentId: "sc-lh68ek-7" })(
1919
["width:100%;color:", ";height:", ";"],
2020
"blue",
2121
123,

0 commit comments

Comments
 (0)