Skip to content

Commit

Permalink
fix(es/minifier): Abort array property inliner if the array is used a…
Browse files Browse the repository at this point in the history
…s a ref (#8956)

**Description:**

Repro:
 - https://github.com/kdy1/repro-next-46887

**Related issue:**

 - vercel/next.js#46887
  • Loading branch information
kdy1 authored May 16, 2024
1 parent 73532ac commit 255485e
Show file tree
Hide file tree
Showing 4 changed files with 225 additions and 0 deletions.
1 change: 1 addition & 0 deletions crates/swc_ecma_minifier/src/compress/optimize/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ impl Optimizer<'_> {
&& usage.accessed_props.is_empty()
&& !usage.is_infected()
&& is_inline_enabled
&& !usage.used_as_ref
{
if let Expr::Array(arr) = init {
if arr.elems.len() < 32
Expand Down
158 changes: 158 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/next/46887/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@

export var CSL = {};

/*
* String parser for XML inputs
*/
CSL.parseXml = function (str) {

var _pos = 0;
var _obj = { children: [] };
var _stack = [_obj.children];

function _listifyString(str) {
str = str.split(/(?:\r\n|\n|\r)/).join(" ").replace(/>[ ]+</g, "><").replace(/<\!--.*?-->/g, "");
var lst = str.split("><");
var stylePos = null;
for (var i = 0, ilen = lst.length; i < ilen; i++) {
if (i > 0) {
lst[i] = "<" + lst[i];
}
if (i < (lst.length - 1)) {
lst[i] = lst[i] + ">";
}
if ("number" != typeof stylePos) {
if (lst[i].slice(0, 7) === "<style " || lst[i].slice(0, 8) == "<locale ") {
stylePos = i;
}
}
}
lst = lst.slice(stylePos);
// Combine open/close elements for empty terms,
// so that they will be passed through correctly
// as empty strings.
for (var i = lst.length - 2; i > -1; i--) {
if (lst[i].slice(1).indexOf("<") === -1) {
var stub = lst[i].slice(0, 5);
if (lst[i].slice(-2) !== "/>") {
if (stub === "<term") {
if (lst[i + 1].slice(0, 6) === "</term") {
lst[i] = lst[i] + lst[i + 1];
lst = lst.slice(0, i + 1).concat(lst.slice(i + 2));
}
} else if (["<sing", "<mult"].indexOf(stub) > -1) {
if (lst[i].slice(-2) !== "/>" && lst[i + 1].slice(0, 1) === "<") {
lst[i] = lst[i] + lst[i + 1];
lst = lst.slice(0, i + 1).concat(lst.slice(i + 2));
}
}
}
}
}
return lst;
}

function _decodeHtmlEntities(str) {
return str
.split("&amp;").join("&")
.split("&quot;").join("\"")
.split("&gt;").join(">").split("&lt;").join("<")
.replace(/&#([0-9]{1,6});/gi, function (match, numStr) {
var num = parseInt(numStr, 10); // read num as normal number
return String.fromCharCode(num);
})
.replace(/&#x([a-f0-9]{1,6});/gi, function (match, numStr) {
var num = parseInt(numStr, 16); // read num as hex
return String.fromCharCode(num);
});
}

function _getAttributes(elem) {
var m = elem.match(/([^\'\"= ]+)=(?:\"[^\"]*\"|\'[^\']*\')/g);
if (m) {
for (var i = 0, ilen = m.length; i < ilen; i++) {
m[i] = m[i].replace(/=.*/, "");
}
}
return m;
}

function _getAttribute(elem, attr) {
var rex = RegExp('^.*[ ]+' + attr + '=(\"(?:[^\"]*)\"|\'(?:[^\']*)\').*$');
var m = elem.match(rex);
return m ? m[1].slice(1, -1) : null;
}

function _getTagName(elem) {
var rex = RegExp("^<([^ />]+)");
var m = elem.match(rex);
return m ? m[1] : null;
}


function _castObjectFromOpeningTag(elem) {
var obj = {};
obj.name = _getTagName(elem);
obj.attrs = {};
var attributes = _getAttributes(elem);
if (attributes) {
for (var i = 0, ilen = attributes.length; i < ilen; i++) {
var attr = {
name: attributes[i],
value: _getAttribute(elem, attributes[i])
}
obj.attrs[attr.name] = _decodeHtmlEntities(attr.value);
}
}
obj.children = [];
return obj;
}

function _extractTextFromCompositeElement(elem) {
var m = elem.match(/^.*>([^<]*)<.*$/);
return _decodeHtmlEntities(m[1]);
}

function _appendToChildren(obj) {
_stack.slice(-1)[0].push(obj);
}

function _extendStackWithNewChildren(obj) {
_stack.push(obj.children);
}

function processElement(elem) {
var obj;
if (elem.slice(1).indexOf('<') > -1) {
// withtext
var tag = elem.slice(0, elem.indexOf('>') + 1);
obj = _castObjectFromOpeningTag(tag);
obj.children = [_extractTextFromCompositeElement(elem)];
_appendToChildren(obj);
} else if (elem.slice(-2) === '/>') {
// singleton
obj = _castObjectFromOpeningTag(elem);
// Empty term as singleton
if (_getTagName(elem) === 'term') {
obj.children.push('');
}
_appendToChildren(obj);
} else if (elem.slice(0, 2) === '</') {
// close
_stack.pop();
} else {
// open
obj = _castObjectFromOpeningTag(elem);
_appendToChildren(obj)
_extendStackWithNewChildren(obj);
}
}

var lst = _listifyString(str);

for (var i = 0, ilen = lst.length; i < ilen; i++) {
var elem = lst[i];
processElement(elem);
}
return _obj.children[0];
}
58 changes: 58 additions & 0 deletions crates/swc_ecma_minifier/tests/fixture/next/46887/output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
export var CSL = {};
CSL.parseXml = function(str) {
var _obj_children = [], _stack = [
_obj_children
];
function _decodeHtmlEntities(str) {
return str.split("&amp;").join("&").split("&quot;").join("\"").split("&gt;").join(">").split("&lt;").join("<").replace(/&#([0-9]{1,6});/gi, function(match, numStr) {
return String.fromCharCode(parseInt(numStr, 10));
}).replace(/&#x([a-f0-9]{1,6});/gi, function(match, numStr) {
return String.fromCharCode(parseInt(numStr, 16));
});
}
function _getTagName(elem) {
var rex = RegExp("^<([^ />]+)"), m = elem.match(rex);
return m ? m[1] : null;
}
function _castObjectFromOpeningTag(elem) {
var obj = {};
obj.name = _getTagName(elem), obj.attrs = {};
var attributes = function(elem) {
var m = elem.match(/([^\'\"= ]+)=(?:\"[^\"]*\"|\'[^\']*\')/g);
if (m) for(var i = 0, ilen = m.length; i < ilen; i++)m[i] = m[i].replace(/=.*/, "");
return m;
}(elem);
if (attributes) for(var i = 0, ilen = attributes.length; i < ilen; i++){
var attr = {
name: attributes[i],
value: function(elem, attr) {
var rex = RegExp('^.*[ ]+' + attr + '=(\"(?:[^\"]*)\"|\'(?:[^\']*)\').*$'), m = elem.match(rex);
return m ? m[1].slice(1, -1) : null;
}(elem, attributes[i])
};
obj.attrs[attr.name] = _decodeHtmlEntities(attr.value);
}
return obj.children = [], obj;
}
function _appendToChildren(obj) {
_stack.slice(-1)[0].push(obj);
}
for(var lst = function(str) {
for(var lst = (str = str.split(/(?:\r\n|\n|\r)/).join(" ").replace(/>[ ]+</g, "><").replace(/<\!--.*?-->/g, "")).split("><"), stylePos = null, i = 0, ilen = lst.length; i < ilen; i++)i > 0 && (lst[i] = "<" + lst[i]), i < lst.length - 1 && (lst[i] = lst[i] + ">"), "number" != typeof stylePos && ("<style " === lst[i].slice(0, 7) || "<locale " == lst[i].slice(0, 8)) && (stylePos = i);
lst = lst.slice(stylePos);
for(var i = lst.length - 2; i > -1; i--)if (-1 === lst[i].slice(1).indexOf("<")) {
var stub = lst[i].slice(0, 5);
"/>" !== lst[i].slice(-2) && ("<term" === stub ? "</term" === lst[i + 1].slice(0, 6) && (lst[i] = lst[i] + lst[i + 1], lst = lst.slice(0, i + 1).concat(lst.slice(i + 2))) : [
"<sing",
"<mult"
].indexOf(stub) > -1 && "/>" !== lst[i].slice(-2) && "<" === lst[i + 1].slice(0, 1) && (lst[i] = lst[i] + lst[i + 1], lst = lst.slice(0, i + 1).concat(lst.slice(i + 2))));
}
return lst;
}(str), i = 0, ilen = lst.length; i < ilen; i++)!function(elem) {
var obj, obj1;
elem.slice(1).indexOf('<') > -1 ? ((obj = _castObjectFromOpeningTag(elem.slice(0, elem.indexOf('>') + 1))).children = [
_decodeHtmlEntities(elem.match(/^.*>([^<]*)<.*$/)[1])
], _appendToChildren(obj)) : '/>' === elem.slice(-2) ? (obj = _castObjectFromOpeningTag(elem), 'term' === _getTagName(elem) && obj.children.push(''), _appendToChildren(obj)) : '</' === elem.slice(0, 2) ? _stack.pop() : (_appendToChildren(obj = _castObjectFromOpeningTag(elem)), obj1 = obj, _stack.push(obj1.children));
}(lst[i]);
return _obj_children[0];
};
8 changes: 8 additions & 0 deletions crates/swc_ecma_usage_analyzer/src/analyzer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,14 @@ where
{
noop_visit_type!();

fn visit_array_lit(&mut self, n: &ArrayLit) {
let ctx = Ctx {
is_id_ref: true,
..self.ctx
};
n.visit_children_with(&mut *self.with_ctx(ctx));
}

#[cfg_attr(feature = "debug", tracing::instrument(skip_all))]
fn visit_arrow_expr(&mut self, n: &ArrowExpr) {
self.with_child(n.span.ctxt, ScopeKind::Fn, |child| {
Expand Down

0 comments on commit 255485e

Please sign in to comment.