fix: Fix bugs (#1590)

swc_ecma_transforms_proposal:
 - Detect decorators in typescript parameter properties. (#1456)

swc:
 - Add tests for #1362. (#1362)
This commit is contained in:
강동윤 2021-04-19 19:16:10 +09:00 committed by GitHub
parent 4db24fb7f6
commit c765c7e06e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 410 additions and 35 deletions

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_common"
repository = "https://github.com/swc-project/swc.git"
version = "0.10.16"
version = "0.10.17"
[features]
concurrent = ["parking_lot"]

View File

@ -1012,6 +1012,16 @@ impl SourceMap {
&self,
mappings: &mut Vec<(BytePos, LineCol)>,
orig: Option<&sourcemap::SourceMap>,
) -> sourcemap::SourceMap {
self.build_source_map_with_config(mappings, orig, DefaultSourceMapGenConfig)
}
#[cfg(feature = "sourcemap")]
pub fn build_source_map_with_config(
&self,
mappings: &mut Vec<(BytePos, LineCol)>,
orig: Option<&sourcemap::SourceMap>,
config: impl SourceMapGenConfig,
) -> sourcemap::SourceMap {
let mut builder = SourceMapBuilder::new(None);
@ -1049,7 +1059,7 @@ impl SourceMap {
Some(ref f) if f.start_pos <= pos && pos < f.end_pos => f,
_ => {
f = self.lookup_source_file(pos);
src_id = builder.add_source(&f.name.to_string());
src_id = builder.add_source(&config.file_name_to_source(&f.name));
builder.set_source_contents(src_id, Some(&f.src));
cur_file = Some(f.clone());
ch_start = 0;
@ -1150,6 +1160,42 @@ impl FilePathMapping {
}
}
pub trait SourceMapGenConfig {
/// # Returns
///
/// File path to used in `SourceMap.sources`.
///
/// This should **not** return content of the file.
fn file_name_to_source(&self, f: &FileName) -> String;
}
#[derive(Debug, Clone)]
pub struct DefaultSourceMapGenConfig;
macro_rules! impl_ref {
($TP:ident, $T:ty) => {
impl<$TP> SourceMapGenConfig for $T
where
$TP: SourceMapGenConfig,
{
fn file_name_to_source(&self, f: &FileName) -> String {
(**self).file_name_to_source(f)
}
}
};
}
impl_ref!(T, &'_ T);
impl_ref!(T, Box<T>);
impl_ref!(T, std::rc::Rc<T>);
impl_ref!(T, std::sync::Arc<T>);
impl SourceMapGenConfig for DefaultSourceMapGenConfig {
fn file_name_to_source(&self, f: &FileName) -> String {
f.to_string()
}
}
// _____________________________________________________________________________
// Tests
//

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_proposal"
repository = "https://github.com/swc-project/swc.git"
version = "0.13.3"
version = "0.13.4"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View File

@ -11,11 +11,9 @@ use swc_ecma_utils::{
alias_ident_for, constructor::inject_after_super, prop_name_to_expr_value, undefined,
ExprFactory, IdentExt,
};
use swc_ecma_visit::noop_visit_type;
use swc_ecma_visit::{noop_fold_type, Fold, FoldWith, Node, Visit, VisitWith};
mod legacy;
mod usage;
/// ## Simple class decorator
///
@ -162,7 +160,7 @@ impl Fold for Decorators {
}
fn fold_module_items(&mut self, items: Vec<ModuleItem>) -> Vec<ModuleItem> {
if !self::usage::has_decorator(&items) {
if !contains_decorator(&items) {
return items;
}
@ -171,7 +169,7 @@ impl Fold for Decorators {
let mut buf = Vec::with_capacity(items.len() + 4);
items.into_iter().for_each(|item| {
if !self::usage::has_decorator(&item) {
if !contains_decorator(&item) {
buf.push(item);
return;
}
@ -643,8 +641,6 @@ struct DecoratorFinder {
found: bool,
}
impl Visit for DecoratorFinder {
noop_visit_type!();
fn visit_decorator(&mut self, _: &Decorator, _: &dyn Node) {
self.found = true
}

View File

@ -1,5 +1,6 @@
use self::metadata::{Metadata, ParamMetadata};
use super::usage::DecoratorFinder;
use super::contains_decorator;
use super::DecoratorFinder;
use fxhash::FxHashMap;
use smallvec::SmallVec;
use std::mem::replace;
@ -239,14 +240,14 @@ impl Legacy {
T: FoldWith<Self> + VisitWith<DecoratorFinder> + StmtLike + ModuleItemLike,
Vec<T>: VisitWith<DecoratorFinder>,
{
if !super::usage::has_decorator(&stmts) {
if !contains_decorator(&stmts) {
return stmts;
}
let mut buf = Vec::with_capacity(stmts.len() + 4);
for stmt in stmts {
if !super::usage::has_decorator(&stmt) {
if !contains_decorator(&stmt) {
buf.push(stmt);
continue;
}

View File

@ -1,23 +0,0 @@
use swc_common::DUMMY_SP;
use swc_ecma_ast::{Decorator, Invalid};
use swc_ecma_visit::noop_visit_type;
use swc_ecma_visit::{Node, Visit, VisitWith};
pub(super) fn has_decorator<T: VisitWith<DecoratorFinder>>(node: &T) -> bool {
let mut v = DecoratorFinder { found: false };
node.visit_with(&Invalid { span: DUMMY_SP } as _, &mut v);
v.found
}
pub(super) struct DecoratorFinder {
found: bool,
}
impl Visit for DecoratorFinder {
noop_visit_type!();
fn visit_decorator(&mut self, _: &Decorator, _parent: &dyn Node) {
self.found = true;
}
}

View File

@ -5703,3 +5703,30 @@ test!(
}), _class);
"
);
test!(
ts(),
|_| decorators(decorators::Config {
legacy: true,
emit_metadata: true,
..Default::default()
}),
issue_1456_1,
"
class MyClass {
constructor(@Inject() param1: Injected) {}
}
",
r#"
var _class;
var _dec = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof Injected === "undefined" ? Object : Injected
]), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec2 = function(target, key) {
return Inject()(target, undefined, 0);
};
let MyClass = _class = _dec2(_class = _dec1(_class = _dec((_class = class MyClass {
constructor(param1: Injected){
}
}) || _class) || _class) || _class) || _class;
"#
);

View File

@ -226,6 +226,9 @@ impl Compiler {
})
}
/// Converts ast node to source string and sourcemap.
///
/// TODO: Receive target file path to fix https://github.com/swc-project/swc/issues/1255
pub fn print<T>(
&self,
node: &T,

View File

@ -0,0 +1,3 @@
{
"sourceMaps": true
}

View File

@ -0,0 +1,3 @@
import { main } from './foo'
main()

View File

@ -0,0 +1,17 @@
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
},
"target": "es2018"
},
"module": {
"type": "commonjs"
}
}

View File

@ -0,0 +1,22 @@
import { Body, Controller, Get, Post } from '@nestjs/common';
import { AppService } from './app.service';
import { CreateUserDto } from './dtos/CreateUserDto';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) { }
@Get()
async getHello() {
const result = await this.appService.getHello()
return result;
}
@Post()
async create(@Body() createUserDto: CreateUserDto) {
console.log("createUserDto", createUserDto)
return "Hello User!"
}
}

View File

@ -0,0 +1,66 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.AppController = void 0;
var _common = require("@nestjs/common");
var _appService = require("./app.service");
var _createUserDto = require("./dtos/CreateUserDto");
function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) {
var desc = {
};
Object.keys(descriptor).forEach(function(key) {
desc[key] = descriptor[key];
});
desc.enumerable = !!desc.enumerable;
desc.configurable = !!desc.configurable;
if ("value" in desc || desc.initializer) {
desc.writable = true;
}
desc = decorators.slice().reverse().reduce(function(desc, decorator) {
return decorator(target, property, desc) || desc;
}, desc);
if (context && desc.initializer !== void 0) {
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
desc.initializer = undefined;
}
if (desc.initializer === void 0) {
Object.defineProperty(target, property, desc);
desc = null;
}
return desc;
}
var _class, _dec, _dec1, _dec2, _dec3, _dec4, _dec5, _dec6;
var _dec7 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof _appService.AppService === "undefined" ? Object : _appService.AppService
]), _dec8 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec9 = (0, _common).Controller();
let AppController = _class = _dec9(_class = _dec8(_class = _dec7(((_class = function() {
class AppController1 {
async getHello() {
const result = await this.appService.getHello();
return result;
}
async create(createUserDto) {
console.log("createUserDto", createUserDto);
return "Hello User!";
}
constructor(appService){
this.appService = appService;
}
}
return AppController1;
}()) || _class, _dec = (0, _common).Get(), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec2 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", []), _applyDecoratedDescriptor(_class.prototype, "getHello", [
_dec,
_dec1,
_dec2
], Object.getOwnPropertyDescriptor(_class.prototype, "getHello"), _class.prototype), _dec3 = (0, _common).Post(), _dec4 = function(target, key) {
return (0, _common).Body()(target, key, 0);
}, _dec5 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec6 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof _createUserDto.CreateUserDto === "undefined" ? Object : _createUserDto.CreateUserDto
]), _applyDecoratedDescriptor(_class.prototype, "create", [
_dec3,
_dec4,
_dec5,
_dec6
], Object.getOwnPropertyDescriptor(_class.prototype, "create"), _class.prototype), _class)) || _class) || _class) || _class;
exports.AppController = AppController;

View File

@ -0,0 +1,18 @@
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
},
"target": "es2018"
},
"module": {
"type": "commonjs",
"noInterop": true
}
}

View File

@ -0,0 +1,3 @@
import * as request from 'supertest';
console.log(request());

View File

@ -0,0 +1,3 @@
"use strict";
var request = require("supertest");
console.log(request());

View File

@ -0,0 +1,19 @@
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
}
},
"module": {
"type": "commonjs"
},
"env": {
"targets": "node 12"
}
}

View File

@ -0,0 +1,28 @@
// not work
class MyClass {
constructor(@Inject() readonly param1: Injected) { }
}
class MyClass {
constructor(@Inject() public param1: Injected) { }
}
class MyClass {
constructor(@Inject() public readonly param1: Injected) { }
}
class MyClass {
constructor(@Inject() private param1: Injected) { }
}
class MyClass {
constructor(@Inject() private readonly param1: Injected) { }
}
class MyClass {
constructor(
@Inject() public param1: Injected,
@Inject() public param2: Injected
) { }
}

View File

@ -0,0 +1,67 @@
"use strict";
var _class, _class1, _class2, _class3, _class4, _class5;
var _dec = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof Injected === "undefined" ? Object : Injected
]), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec2 = function(target, key) {
return Inject()(target, undefined, 0);
};
let MyClass = _class = _dec2(_class = _dec1(_class = _dec((_class = // not work
class MyClass1 {
constructor(param1){
this.param1 = param1;
}
}) || _class) || _class) || _class) || _class;
var _dec3 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof Injected === "undefined" ? Object : Injected
]), _dec4 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec5 = function(target, key) {
return Inject()(target, undefined, 0);
};
let MyClass = _class1 = _dec5(_class1 = _dec4(_class1 = _dec3((_class1 = class MyClass2 {
constructor(param11){
this.param1 = param11;
}
}) || _class1) || _class1) || _class1) || _class1;
var _dec6 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof Injected === "undefined" ? Object : Injected
]), _dec7 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec8 = function(target, key) {
return Inject()(target, undefined, 0);
};
let MyClass = _class2 = _dec8(_class2 = _dec7(_class2 = _dec6((_class2 = class MyClass3 {
constructor(param12){
this.param1 = param12;
}
}) || _class2) || _class2) || _class2) || _class2;
var _dec9 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof Injected === "undefined" ? Object : Injected
]), _dec10 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec11 = function(target, key) {
return Inject()(target, undefined, 0);
};
let MyClass = _class3 = _dec11(_class3 = _dec10(_class3 = _dec9((_class3 = class MyClass4 {
constructor(param13){
this.param1 = param13;
}
}) || _class3) || _class3) || _class3) || _class3;
var _dec12 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof Injected === "undefined" ? Object : Injected
]), _dec13 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec14 = function(target, key) {
return Inject()(target, undefined, 0);
};
let MyClass = _class4 = _dec14(_class4 = _dec13(_class4 = _dec12((_class4 = class MyClass5 {
constructor(param14){
this.param1 = param14;
}
}) || _class4) || _class4) || _class4) || _class4;
var _dec15 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof Injected === "undefined" ? Object : Injected,
typeof Injected === "undefined" ? Object : Injected
]), _dec16 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec17 = function(target, key) {
return Inject()(target, undefined, 1);
}, _dec18 = function(target, key) {
return Inject()(target, undefined, 0);
};
let MyClass = _class5 = _dec18(_class5 = _dec17(_class5 = _dec16(_class5 = _dec15((_class5 = class MyClass6 {
constructor(param15, param2){
this.param1 = param15;
this.param2 = param2;
}
}) || _class5) || _class5) || _class5) || _class5) || _class5;

View File

@ -0,0 +1,19 @@
{
"jsc": {
"parser": {
"syntax": "typescript",
"tsx": false,
"decorators": true
},
"transform": {
"legacyDecorator": true,
"decoratorMetadata": true
}
},
"module": {
"type": "commonjs"
},
"env": {
"targets": "node 12"
}
}

View File

@ -0,0 +1,19 @@
// work
class MyClass {
constructor(@Inject() param1: Injected) { }
}
class MyClass {
constructor(
@Inject() public readonly param1: Injected,
@Inject() param2: Injected
) { }
}
class MyClass {
constructor(
@Inject() param1: Injected,
@Inject() public readonly param2: Injected
) { }
}

View File

@ -0,0 +1,38 @@
"use strict";
var _class, _class1, _class2;
var _dec = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof Injected === "undefined" ? Object : Injected
]), _dec1 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec2 = function(target, key) {
return Inject()(target, undefined, 0);
};
let MyClass = _class = _dec2(_class = _dec1(_class = _dec((_class = // work
class MyClass1 {
constructor(param1){
}
}) || _class) || _class) || _class) || _class;
var _dec3 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof Injected === "undefined" ? Object : Injected,
typeof Injected === "undefined" ? Object : Injected
]), _dec4 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec5 = function(target, key) {
return Inject()(target, undefined, 1);
}, _dec6 = function(target, key) {
return Inject()(target, undefined, 0);
};
let MyClass = _class1 = _dec6(_class1 = _dec5(_class1 = _dec4(_class1 = _dec3((_class1 = class MyClass2 {
constructor(param11, param2){
this.param1 = param11;
}
}) || _class1) || _class1) || _class1) || _class1) || _class1;
var _dec7 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:paramtypes", [
typeof Injected === "undefined" ? Object : Injected,
typeof Injected === "undefined" ? Object : Injected
]), _dec8 = typeof Reflect !== "undefined" && typeof Reflect.metadata === "function" && Reflect.metadata("design:type", Function), _dec9 = function(target, key) {
return Inject()(target, undefined, 1);
}, _dec10 = function(target, key) {
return Inject()(target, undefined, 0);
};
let MyClass = _class2 = _dec10(_class2 = _dec9(_class2 = _dec8(_class2 = _dec7((_class2 = class MyClass3 {
constructor(param12, param21){
this.param2 = param21;
}
}) || _class2) || _class2) || _class2) || _class2) || _class2;