fix(swc): Run resolver before everything (#3400)

swc:
 - Use `ts_resolver` for typescript. This is required to handle decorators properly.
 - Apply `resolver` before creating custom passes.
This commit is contained in:
Donny/강동윤 2022-01-29 13:36:34 +09:00 committed by GitHub
parent c49ffc2c8b
commit cebc5dc148
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 46 additions and 36 deletions

View File

@ -48,11 +48,13 @@ use swc_ecma_transforms::{
optimization::{const_modules, json_parse, simplifier},
pass::{noop, Optional},
proposals::{decorators, export_default_from, import_assertions},
react, resolver_with_mark, typescript, Assumptions,
react,
resolver::ts_resolver,
resolver_with_mark, typescript, Assumptions,
};
use swc_ecma_transforms_compat::es2015::regenerator;
use swc_ecma_transforms_optimization::{inline_globals2, GlobalExprMap};
use swc_ecma_visit::Fold;
use swc_ecma_visit::{Fold, VisitMutWith};
#[cfg(test)]
mod tests;
@ -243,6 +245,7 @@ impl Default for InputSourceMap {
impl Options {
/// `parse`: `(syntax, target, is_module)`
#[allow(clippy::too_many_arguments)]
pub fn build_as_input<'a, P>(
&self,
cm: &Arc<SourceMap>,
@ -289,11 +292,26 @@ impl Options {
}
});
let top_level_mark = self
.global_mark
.unwrap_or_else(|| Mark::fresh(Mark::root()));
let target = target.unwrap_or_default();
let syntax = syntax.unwrap_or_default();
let program = parse(syntax, target, is_module)?;
let mut program = parse(syntax, target, is_module)?;
// Do a resolver pass before everything.
//
// We do this before creating custom passses, so custom passses can use the
// variable management system based on the syntax contexts.
if syntax.typescript() {
program.visit_mut_with(&mut ts_resolver(top_level_mark));
} else {
program.visit_mut_with(&mut resolver_with_mark(top_level_mark));
}
let mut transform = transform.unwrap_or_default();
if program.is_module() {
@ -365,10 +383,6 @@ impl Options {
}
};
let top_level_mark = self
.global_mark
.unwrap_or_else(|| Mark::fresh(Mark::root()));
let top_level_ctxt = SyntaxContext::empty().apply_mark(top_level_mark);
let pass = chain!(
@ -412,11 +426,6 @@ impl Options {
// The transform strips import assertions, so it's only enabled if
// keep_import_assertions is false.
Optional::new(import_assertions(), !experimental.keep_import_assertions),
// Do a resolver pass after decorators as it might
// emit runtime declarations and do it before
// type stripping as we need to know scope information
// for emitting enums and namespaces.
resolver_with_mark(top_level_mark),
Optional::new(
typescript::strip_with_jsx(
cm.clone(),

View File

@ -45,9 +45,9 @@ var _dec16 = ViewEntity({
name: "AccountMemberView",
expression: "\n SELECT\n m.tmcode, m.mid, m.accea, m.qaccea, m.endday, m.quick_endday,\n (SELECT COUNT(*) FROM TBLACCOUNT a WHERE m.mid = a.mid AND a.use_quick=\"F\") as accountCnt,\n (SELECT COUNT(*) FROM TBLACCOUNT a WHERE m.mid = a.mid AND a.use_quick=\"T\") as accountQuickCnt\n FROM TBLMEMBER m\n "
});
export var AccountMemberView = _class = _dec16((_class = function AccountMemberView1() {
export var AccountMemberView = _class = _dec16((_class = function AccountMemberView() {
"use strict";
_classCallCheck(this, AccountMemberView1);
_classCallCheck(this, AccountMemberView);
_initializerDefineProperty(this, "memberId", _descriptor, this);
_initializerDefineProperty(this, "mallId", _descriptor1, this);
_initializerDefineProperty(this, "allowAccountCnt", _descriptor2, this);

View File

@ -49,9 +49,9 @@ var column = function() {
Reflect.defineMetadata(COL_KEY, 'value', object, key);
};
};
var User = ((_class = function User1() {
var User = ((_class = function User() {
"use strict";
_classCallCheck(this, User1);
_classCallCheck(this, User);
_initializerDefineProperty(this, "currency", _descriptor, this);
}) || _class, _dec = column(), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", String), _descriptor = _applyDecoratedDescriptor(_class.prototype, "currency", [
_dec,

View File

@ -5,9 +5,9 @@ function _classCallCheck(instance, Constructor) {
}
var _class;
var _class1;
var TestClass = _class1 = someClassDecorator((_class1 = (_class = function TestClass1() {
var TestClass = _class1 = someClassDecorator((_class1 = (_class = function TestClass() {
"use strict";
_classCallCheck(this, TestClass1);
_classCallCheck(this, TestClass);
}, _class.Something = 'hello', _class.SomeProperties = {
firstProp: _class.Something
}, _class)) || _class1) || _class1;

View File

@ -467,13 +467,13 @@ function _createSuper(Derived) {
};
}
var SomeClass = _decorate([], function(_initialize) {
var SomeClass1 = function SomeClass1() {
var SomeClass = function SomeClass() {
"use strict";
_classCallCheck(this, SomeClass1);
_classCallCheck(this, SomeClass);
_initialize(this);
};
return {
F: SomeClass1,
F: SomeClass,
d: [
{
kind: "method",
@ -487,21 +487,21 @@ var SomeClass = _decorate([], function(_initialize) {
};
});
var OtherClass = _decorate([], function(_initialize, _SomeClass1) {
var OtherClass1 = /*#__PURE__*/ function(_SomeClass) {
var OtherClass = /*#__PURE__*/ function(_SomeClass) {
"use strict";
_inherits(OtherClass1, _SomeClass);
var _super = _createSuper(OtherClass1);
function OtherClass1() {
_classCallCheck(this, OtherClass1);
_inherits(OtherClass, _SomeClass);
var _super = _createSuper(OtherClass);
function OtherClass() {
_classCallCheck(this, OtherClass);
var _this;
_this = _super.apply(this, arguments);
_initialize(_assertThisInitialized(_this));
return _this;
}
return OtherClass1;
return OtherClass;
}(_SomeClass1);
return {
F: OtherClass1,
F: OtherClass,
d: [
{
kind: "method",
@ -510,7 +510,7 @@ var OtherClass = _decorate([], function(_initialize, _SomeClass1) {
],
key: "anotherMethod",
value: function anotherMethod() {
_get(_getPrototypeOf(OtherClass1.prototype), "someMethod", this).call(this);
_get(_getPrototypeOf(OtherClass.prototype), "someMethod", this).call(this);
}
}
]

View File

@ -1,8 +1,8 @@
use super::EnumKind;
use swc_atoms::js_word;
use swc_atoms::{js_word, JsWord};
use swc_common::{collections::AHashMap, util::move_map::MoveMap, Spanned, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_utils::{ident::IdentLike, member_expr, quote_ident, undefined, ExprFactory, Id};
use swc_ecma_utils::{member_expr, quote_ident, undefined, ExprFactory};
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith};
/// https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/blob/master/src/parameter/parameterVisitor.ts
@ -121,7 +121,7 @@ impl ParamMetadata {
/// https://github.com/leonardfactory/babel-plugin-transform-typescript-metadata/blob/master/src/metadata/metadataVisitor.ts
pub(super) struct Metadata<'a> {
pub(super) enums: &'a AHashMap<Id, EnumKind>,
pub(super) enums: &'a AHashMap<JsWord, EnumKind>,
pub(super) class_name: Option<&'a Ident>,
}
@ -237,7 +237,7 @@ impl Fold for Metadata<'_> {
TsEntityName::Ident(i) => Some(i),
})
{
if let Some(kind) = self.enums.get(&name.to_id()) {
if let Some(kind) = self.enums.get(&name.sym) {
let dec = self.create_metadata_design_decorator(
"design:type",
match kind {

View File

@ -2,13 +2,14 @@ use self::metadata::{Metadata, ParamMetadata};
use super::{contains_decorator, DecoratorFinder};
use smallvec::SmallVec;
use std::mem::take;
use swc_atoms::JsWord;
use swc_common::{collections::AHashMap, util::move_map::MoveMap, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_transforms_base::helper;
use swc_ecma_utils::{
alias_if_required, default_constructor, ident::IdentLike, member_expr, prepend, private_ident,
prop_name_to_expr, prop_name_to_expr_value, quote_ident, replace_ident, undefined, ExprFactory,
Id, ModuleItemLike, StmtLike,
ModuleItemLike, StmtLike,
};
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Visit, VisitWith};
@ -27,7 +28,7 @@ pub(super) struct Legacy {
uninitialized_vars: Vec<VarDeclarator>,
initialized_vars: Vec<VarDeclarator>,
exports: Vec<ExportSpecifier>,
enums: AHashMap<Id, EnumKind>,
enums: AHashMap<JsWord, EnumKind>,
}
pub(super) fn new(metadata: bool) -> Legacy {
@ -76,7 +77,7 @@ impl Visit for Legacy {
}
});
if let Some(kind) = enum_kind {
self.enums.insert(e.id.to_id(), kind);
self.enums.insert(e.id.sym.clone(), kind);
}
}
}