mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 13:51:19 +03:00
hygiene: handle use-use conflict (#599)
Note that as we don't care about emitting a clean code, the renamed output may not match it of bind-bind conflict or bind-use conflict.
This commit is contained in:
parent
08ce8d0293
commit
8ecbe14207
@ -2,5 +2,7 @@
|
||||
"devDependencies": {
|
||||
"browserslist": "=4.7.3"
|
||||
},
|
||||
"browserslist": ["defaults"]
|
||||
"browserslist": [
|
||||
"defaults"
|
||||
]
|
||||
}
|
||||
|
@ -1,13 +1,20 @@
|
||||
const browserslist = require('browserslist')
|
||||
let target = JSON.parse(process.argv[1]);
|
||||
"use strict";
|
||||
|
||||
var browserslist = require('browserslist');
|
||||
|
||||
var target = JSON.parse(process.argv[1]);
|
||||
target = target.browsers ? target.browsers : target;
|
||||
target = Array.isArray(target) ? target : (typeof target === 'string' ? [target] : Object.keys(target).map((k) => `${k} ${target[k]}`));
|
||||
target = target.filter(v => !v.startsWith('esmodules') && !!v);
|
||||
target = Array.isArray(target) ? target : typeof target === 'string' ? [target] : Object.keys(target).map(function (k) {
|
||||
return k + " " + target[k];
|
||||
});
|
||||
target = target.filter(function (v) {
|
||||
return !v.startsWith('esmodules') && !!v;
|
||||
}); // console.log('Target: ', target);
|
||||
|
||||
// console.log('Target: ', target);
|
||||
|
||||
const browsers = browserslist(target && target.length ? target : undefined, {
|
||||
mobileToDesktop: true,
|
||||
var browsers = browserslist(target && target.length ? target : undefined, {
|
||||
mobileToDesktop: true
|
||||
});
|
||||
browsers = browsers.filter(function (v) {
|
||||
return !v.includes("TP");
|
||||
});
|
||||
console.log(JSON.stringify(browsers));
|
14
ecmascript/preset_env/src/query.src.js
Normal file
14
ecmascript/preset_env/src/query.src.js
Normal file
@ -0,0 +1,14 @@
|
||||
const browserslist = require('browserslist')
|
||||
let target = JSON.parse(process.argv[1]);
|
||||
|
||||
target = target.browsers ? target.browsers : target;
|
||||
target = Array.isArray(target) ? target : (typeof target === 'string' ? [target] : Object.keys(target).map((k) => `${k} ${target[k]}`));
|
||||
target = target.filter(v => !v.startsWith('esmodules') && !!v);
|
||||
|
||||
// console.log('Target: ', target);
|
||||
|
||||
let browsers = browserslist(target && target.length ? target : undefined, {
|
||||
mobileToDesktop: true,
|
||||
});
|
||||
browsers = browsers.filter((v) => !v.includes("TP"))
|
||||
console.log(JSON.stringify(browsers));
|
@ -55,12 +55,20 @@ impl<'a> Hygiene<'a> {
|
||||
fn add_used_ref(&mut self, ident: Ident) {
|
||||
let ctxt = ident.span.ctxt();
|
||||
|
||||
self.current
|
||||
.declared_symbols
|
||||
.borrow_mut()
|
||||
.entry(ident.sym.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(ctxt);
|
||||
|
||||
// We rename declaration instead of usage
|
||||
let conflicts = self.current.conflicts(ident.sym.clone(), ctxt);
|
||||
|
||||
if cfg!(debug_assertions) && LOG && !conflicts.is_empty() {
|
||||
eprintln!("Renaming from usage");
|
||||
}
|
||||
|
||||
for cx in conflicts {
|
||||
self.rename(ident.sym.clone(), cx)
|
||||
}
|
||||
@ -111,7 +119,7 @@ impl<'a> Hygiene<'a> {
|
||||
ctxt
|
||||
);
|
||||
old.retain(|c| *c != ctxt);
|
||||
debug_assert!(old.is_empty() || old.len() == 1);
|
||||
// debug_assert!(old.is_empty() || old.len() == 1);
|
||||
|
||||
let new = declared_symbols.entry(renamed.clone()).or_default();
|
||||
new.push(ctxt);
|
||||
@ -257,6 +265,11 @@ impl<'a> Fold<FnDecl> for Hygiene<'a> {
|
||||
impl<'a> Fold<Ident> for Hygiene<'a> {
|
||||
/// Invoked for `IdetifierRefrence` / `BindingIdentifier`
|
||||
fn fold(&mut self, i: Ident) -> Ident {
|
||||
// Special case
|
||||
if i.sym == js_word!("arguments") {
|
||||
return i;
|
||||
}
|
||||
|
||||
match self.ident_type {
|
||||
IdentType::Binding => self.add_declared_ref(i.clone()),
|
||||
IdentType::Ref => {
|
||||
@ -400,6 +413,7 @@ impl<'a> Scope<'a> {
|
||||
}
|
||||
|
||||
ctxts.retain(|c| *c != ctxt);
|
||||
ctxts.dedup();
|
||||
|
||||
ctxts
|
||||
}
|
||||
@ -443,6 +457,27 @@ impl<'a> Scope<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<Constructor> for Hygiene<'_> {
|
||||
fn fold(&mut self, c: Constructor) -> Constructor {
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Binding;
|
||||
let params = c.params.fold_with(self);
|
||||
self.ident_type = old;
|
||||
|
||||
let body = c.body.map(|bs| bs.fold_children(self));
|
||||
let key = c.key.fold_with(self);
|
||||
|
||||
let c = Constructor {
|
||||
params,
|
||||
body,
|
||||
key,
|
||||
..c
|
||||
};
|
||||
|
||||
self.apply_ops(c)
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! track_ident {
|
||||
($T:tt) => {
|
||||
@ -480,25 +515,6 @@ macro_rules! track_ident {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<Constructor> for $T<'a> {
|
||||
fn fold(&mut self, c: Constructor) -> Constructor {
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Binding;
|
||||
let params = c.params.fold_with(self);
|
||||
self.ident_type = old;
|
||||
|
||||
let body = c.body.fold_with(self);
|
||||
let key = c.key.fold_with(self);
|
||||
|
||||
Constructor {
|
||||
params,
|
||||
body,
|
||||
key,
|
||||
..c
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Fold<SetterProp> for $T<'a> {
|
||||
fn fold(&mut self, f: SetterProp) -> SetterProp {
|
||||
let old = self.ident_type;
|
||||
|
@ -45,6 +45,7 @@ impl<'a> Fold<Vec<ModuleItem>> for Operator<'a> {
|
||||
declare,
|
||||
}),
|
||||
})) => {
|
||||
let class = class.fold_with(self);
|
||||
let orig_ident = ident.clone();
|
||||
match self.rename_ident(ident) {
|
||||
Ok(ident) => {
|
||||
@ -76,6 +77,7 @@ impl<'a> Fold<Vec<ModuleItem>> for Operator<'a> {
|
||||
declare,
|
||||
}),
|
||||
})) => {
|
||||
let function = function.fold_with(self);
|
||||
let orig_ident = ident.clone();
|
||||
match self.rename_ident(ident) {
|
||||
Ok(ident) => {
|
||||
|
@ -1,4 +1,5 @@
|
||||
use super::*;
|
||||
use crate::tests::HygieneVisualizer;
|
||||
use std::collections::HashMap;
|
||||
use swc_common::{hygiene::*, Fold, DUMMY_SP};
|
||||
use swc_ecma_parser::Syntax;
|
||||
@ -71,6 +72,14 @@ where
|
||||
crate::tests::Tester::run(|tester| {
|
||||
let module = op(tester)?;
|
||||
|
||||
match ::std::env::var("PRINT_HYGIENE") {
|
||||
Ok(ref s) if s == "1" => {
|
||||
let hygiene_src = tester.print(&module.clone().fold_with(&mut HygieneVisualizer));
|
||||
println!("----- Hygiene -----\n{}", hygiene_src);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let module = module.fold_with(&mut hygiene());
|
||||
|
||||
let actual = tester.print(&module);
|
||||
@ -1164,3 +1173,93 @@ fn exported_class_1() {
|
||||
export { Foo1 as Foo };",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_598() {
|
||||
test_module(
|
||||
|tester| {
|
||||
let mark1 = Mark::fresh(Mark::root());
|
||||
let mark2 = Mark::fresh(Mark::root());
|
||||
|
||||
Ok(tester
|
||||
.parse_module(
|
||||
"actual1.js",
|
||||
"export function foo() {
|
||||
console.log(i18n(_templateObject()));
|
||||
console.log(i18n(_templateObject()));
|
||||
}",
|
||||
)?
|
||||
.fold_with(&mut OnceMarker::new(&[(
|
||||
"_templateObject",
|
||||
&[mark1, mark2],
|
||||
)])))
|
||||
},
|
||||
"export function foo() {
|
||||
console.log(i18n(_templateObject1()));
|
||||
console.log(i18n(_templateObject()));
|
||||
}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_598_2() {
|
||||
test_module(
|
||||
|tester| {
|
||||
let mark1 = Mark::fresh(Mark::root());
|
||||
let mark2 = Mark::fresh(Mark::root());
|
||||
let mark3 = Mark::fresh(Mark::root());
|
||||
|
||||
Ok(tester
|
||||
.parse_module(
|
||||
"actual1.js",
|
||||
"export function foo() {
|
||||
console.log(i18n(_templateObject()));
|
||||
console.log(i18n(_templateObject()));
|
||||
console.log(i18n(_templateObject()));
|
||||
}",
|
||||
)?
|
||||
.fold_with(&mut OnceMarker::new(&[(
|
||||
"_templateObject",
|
||||
&[mark1, mark2, mark3],
|
||||
)])))
|
||||
},
|
||||
"export function foo() {
|
||||
console.log(i18n(_templateObject1()));
|
||||
console.log(i18n(_templateObject2()));
|
||||
console.log(i18n(_templateObject()));
|
||||
}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_598_3() {
|
||||
test_module(
|
||||
|tester| {
|
||||
let mark1 = Mark::fresh(Mark::root());
|
||||
let mark2 = Mark::fresh(Mark::root());
|
||||
let mark3 = Mark::fresh(Mark::root());
|
||||
let mark4 = Mark::fresh(Mark::root());
|
||||
|
||||
Ok(tester
|
||||
.parse_module(
|
||||
"actual1.js",
|
||||
"export function foo() {
|
||||
console.log(i18n(_templateObject()));
|
||||
console.log(i18n(_templateObject()));
|
||||
console.log(i18n(_templateObject()));
|
||||
console.log(i18n(_templateObject()));
|
||||
}",
|
||||
)?
|
||||
.fold_with(&mut OnceMarker::new(&[(
|
||||
"_templateObject",
|
||||
&[mark1, mark2, mark3, mark4],
|
||||
)])))
|
||||
},
|
||||
"export function foo() {
|
||||
console.log(i18n(_templateObject1()));
|
||||
console.log(i18n(_templateObject2()));
|
||||
console.log(i18n(_templateObject3()));
|
||||
console.log(i18n(_templateObject()));
|
||||
}",
|
||||
);
|
||||
}
|
||||
|
@ -491,3 +491,22 @@ impl Fold<Function> for Hoister<'_, '_> {
|
||||
node
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<Constructor> for Resolver<'_> {
|
||||
fn fold(&mut self, c: Constructor) -> Constructor {
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Binding;
|
||||
let params = c.params.fold_with(self);
|
||||
self.ident_type = old;
|
||||
|
||||
let body = c.body.fold_with(self);
|
||||
let key = c.key.fold_with(self);
|
||||
|
||||
Constructor {
|
||||
params,
|
||||
body,
|
||||
key,
|
||||
..c
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -408,7 +408,7 @@ impl Fold<PatOrExpr> for Normalizer {
|
||||
}
|
||||
}
|
||||
|
||||
struct HygieneVisualizer;
|
||||
pub(crate) struct HygieneVisualizer;
|
||||
impl Fold<Ident> for HygieneVisualizer {
|
||||
fn fold(&mut self, ident: Ident) -> Ident {
|
||||
Ident {
|
||||
|
@ -3490,7 +3490,7 @@ var _myAsyncMethod1 = new WeakMap();
|
||||
|
||||
class MyClass3{
|
||||
constructor(){
|
||||
_myAsyncMethod2.set(this, {
|
||||
_myAsyncMethod.set(this, {
|
||||
writable: true,
|
||||
value: (function() {
|
||||
var _ref = _asyncToGenerator((function*() {
|
||||
@ -3503,7 +3503,7 @@ class MyClass3{
|
||||
});
|
||||
}
|
||||
}
|
||||
var _myAsyncMethod2 = new WeakMap();
|
||||
var _myAsyncMethod = new WeakMap();
|
||||
export { MyClass3 as default }
|
||||
|
||||
"#
|
||||
@ -4059,8 +4059,8 @@ new SuperClass(); // ensure ComputedKey Method is still transformed
|
||||
|
||||
class ComputedMethod extends Obj {
|
||||
constructor() {
|
||||
var _temp;
|
||||
var tmp = (_temp = super(), _defineProperty(this, "field", 1), _temp);
|
||||
var _temp1;
|
||||
var tmp = (_temp1 = super(), _defineProperty(this, "field", 1), _temp1);
|
||||
class B extends Obj {
|
||||
[tmp]() {}
|
||||
|
||||
@ -4082,9 +4082,9 @@ new ComputedMethod(); // ensure ComputedKey Field is still transformed
|
||||
|
||||
class ComputedField extends Obj {
|
||||
constructor() {
|
||||
var _temp;
|
||||
var _temp2;
|
||||
|
||||
var _ref = (_temp = super(), _defineProperty(this, "field", 1), _temp);
|
||||
var _ref = (_temp2 = super(), _defineProperty(this, "field", 1), _temp2);
|
||||
|
||||
class B extends Obj {
|
||||
constructor() {
|
||||
@ -4651,8 +4651,8 @@ export class Foo extends Bar {
|
||||
"#,
|
||||
r#"
|
||||
export class Foo extends Bar {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
constructor(...args1) {
|
||||
super(...args1);
|
||||
_defineProperty(this, "test", args);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user