mirror of
https://github.com/swc-project/swc.git
synced 2024-12-25 22:56:11 +03:00
fix(es/module): Handle directives (#8048)
**Related issue:** - Closes: #8047
This commit is contained in:
parent
0c8d8a3f4a
commit
4d8e1013bb
@ -20,8 +20,8 @@ use crate::{
|
|||||||
module_ref_rewriter::{ImportMap, ModuleRefRewriter},
|
module_ref_rewriter::{ImportMap, ModuleRefRewriter},
|
||||||
path::{ImportResolver, Resolver},
|
path::{ImportResolver, Resolver},
|
||||||
util::{
|
util::{
|
||||||
clone_first_use_directive, define_es_module, emit_export_stmts, local_name_for_src,
|
define_es_module, emit_export_stmts, local_name_for_src, use_strict, ImportInterop,
|
||||||
use_strict, ImportInterop,
|
VecStmtLike,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -143,9 +143,19 @@ where
|
|||||||
|
|
||||||
let mut stmts: Vec<Stmt> = Vec::with_capacity(n.body.len() + 4);
|
let mut stmts: Vec<Stmt> = Vec::with_capacity(n.body.len() + 4);
|
||||||
|
|
||||||
|
// Collect directives
|
||||||
|
stmts.extend(
|
||||||
|
&mut n
|
||||||
|
.body
|
||||||
|
.iter_mut()
|
||||||
|
.take_while(|i| i.directive_continue())
|
||||||
|
.map(|i| i.take())
|
||||||
|
.map(ModuleItem::expect_stmt),
|
||||||
|
);
|
||||||
|
|
||||||
// "use strict";
|
// "use strict";
|
||||||
if self.config.strict_mode {
|
if self.config.strict_mode && !stmts.has_use_strict() {
|
||||||
stmts.push(clone_first_use_directive(&n.body, true).unwrap_or_else(use_strict));
|
stmts.push(use_strict());
|
||||||
}
|
}
|
||||||
|
|
||||||
let ModuleDeclStrip {
|
let ModuleDeclStrip {
|
||||||
@ -170,7 +180,7 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
stmts.extend(n.body.take().into_iter().filter_map(|item| match item {
|
stmts.extend(n.body.take().into_iter().filter_map(|item| match item {
|
||||||
ModuleItem::Stmt(stmt) if !stmt.is_directive() => Some(stmt),
|
ModuleItem::Stmt(stmt) if !stmt.is_empty() => Some(stmt),
|
||||||
_ => None,
|
_ => None,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ use crate::{
|
|||||||
module_ref_rewriter::{ImportMap, ModuleRefRewriter},
|
module_ref_rewriter::{ImportMap, ModuleRefRewriter},
|
||||||
path::{ImportResolver, Resolver},
|
path::{ImportResolver, Resolver},
|
||||||
util::{
|
util::{
|
||||||
clone_first_use_directive, define_es_module, emit_export_stmts, local_name_for_src,
|
define_es_module, emit_export_stmts, local_name_for_src, prop_name, use_strict,
|
||||||
prop_name, use_strict, ImportInterop, ObjPropKeyIdent,
|
ImportInterop, ObjPropKeyIdent, VecStmtLike,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -113,15 +113,18 @@ where
|
|||||||
|
|
||||||
let mut stmts: Vec<ModuleItem> = Vec::with_capacity(n.body.len() + 6);
|
let mut stmts: Vec<ModuleItem> = Vec::with_capacity(n.body.len() + 6);
|
||||||
|
|
||||||
stmts.extend(clone_first_use_directive(&n.body, false).map(From::from));
|
// Collect directives
|
||||||
|
stmts.extend(
|
||||||
|
&mut n
|
||||||
|
.body
|
||||||
|
.iter_mut()
|
||||||
|
.take_while(|i| i.directive_continue())
|
||||||
|
.map(|i| i.take()),
|
||||||
|
);
|
||||||
|
|
||||||
// "use strict";
|
// "use strict";
|
||||||
if self.config.strict_mode {
|
if self.config.strict_mode && !stmts.has_use_strict() {
|
||||||
stmts.push(
|
stmts.push(use_strict().into());
|
||||||
clone_first_use_directive(&n.body, true)
|
|
||||||
.unwrap_or_else(use_strict)
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let ModuleDeclStrip {
|
let ModuleDeclStrip {
|
||||||
@ -156,7 +159,7 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
stmts.extend(n.body.take().into_iter().filter(|item| match item {
|
stmts.extend(n.body.take().into_iter().filter(|item| match item {
|
||||||
ModuleItem::Stmt(stmt) => !stmt.is_directive(),
|
ModuleItem::Stmt(stmt) => !stmt.is_empty(),
|
||||||
_ => false,
|
_ => false,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ use crate::{
|
|||||||
module_ref_rewriter::{ImportMap, ModuleRefRewriter},
|
module_ref_rewriter::{ImportMap, ModuleRefRewriter},
|
||||||
path::{ImportResolver, Resolver},
|
path::{ImportResolver, Resolver},
|
||||||
util::{
|
util::{
|
||||||
clone_first_use_directive, define_es_module, emit_export_stmts, local_name_for_src,
|
define_es_module, emit_export_stmts, local_name_for_src, use_strict, ImportInterop,
|
||||||
use_strict, ImportInterop,
|
VecStmtLike,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -116,9 +116,18 @@ where
|
|||||||
|
|
||||||
let mut stmts: Vec<Stmt> = Vec::with_capacity(module_items.len() + 4);
|
let mut stmts: Vec<Stmt> = Vec::with_capacity(module_items.len() + 4);
|
||||||
|
|
||||||
|
// Collect directives
|
||||||
|
stmts.extend(
|
||||||
|
module_items
|
||||||
|
.iter_mut()
|
||||||
|
.take_while(|i| i.directive_continue())
|
||||||
|
.map(|i| i.take())
|
||||||
|
.map(ModuleItem::expect_stmt),
|
||||||
|
);
|
||||||
|
|
||||||
// "use strict";
|
// "use strict";
|
||||||
if self.config.config.strict_mode {
|
if self.config.config.strict_mode && !stmts.has_use_strict() {
|
||||||
stmts.push(clone_first_use_directive(module_items, true).unwrap_or_else(use_strict));
|
stmts.push(use_strict());
|
||||||
}
|
}
|
||||||
|
|
||||||
let ModuleDeclStrip {
|
let ModuleDeclStrip {
|
||||||
@ -143,7 +152,7 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
stmts.extend(module_items.take().into_iter().filter_map(|i| match i {
|
stmts.extend(module_items.take().into_iter().filter_map(|i| match i {
|
||||||
ModuleItem::Stmt(stmt) if !stmt.is_directive() => Some(stmt),
|
ModuleItem::Stmt(stmt) if !stmt.is_empty() => Some(stmt),
|
||||||
_ => None,
|
_ => None,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -194,26 +194,33 @@ pub(super) fn define_es_module(exports: Ident) -> Stmt {
|
|||||||
.into_stmt()
|
.into_stmt()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn clone_first_use_directive(
|
pub(super) trait VecStmtLike {
|
||||||
stmts: &[ModuleItem],
|
type StmtLike: IsDirective;
|
||||||
want_use_strict: bool,
|
|
||||||
) -> Option<Stmt> {
|
|
||||||
if stmts.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
stmts.iter().find_map(|item| match item {
|
fn as_ref(&self) -> &[Self::StmtLike];
|
||||||
ModuleItem::Stmt(stmt) => {
|
|
||||||
if (want_use_strict && stmt.is_use_strict())
|
fn has_use_strict(&self) -> bool {
|
||||||
|| (!want_use_strict && !stmt.is_use_strict() && stmt.is_directive())
|
self.as_ref()
|
||||||
{
|
.iter()
|
||||||
Some(stmt.clone())
|
.take_while(|s| s.directive_continue())
|
||||||
} else {
|
.any(IsDirective::is_use_strict)
|
||||||
None
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => None,
|
impl VecStmtLike for [ModuleItem] {
|
||||||
})
|
type StmtLike = ModuleItem;
|
||||||
|
|
||||||
|
fn as_ref(&self) -> &[Self::StmtLike] {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VecStmtLike for [Stmt] {
|
||||||
|
type StmtLike = Stmt;
|
||||||
|
|
||||||
|
fn as_ref(&self) -> &[Self::StmtLike] {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn use_strict() -> Stmt {
|
pub(super) fn use_strict() -> Stmt {
|
||||||
|
@ -3,6 +3,7 @@ define([
|
|||||||
"require",
|
"require",
|
||||||
"exports"
|
"exports"
|
||||||
], function(require, exports) {
|
], function(require, exports) {
|
||||||
|
"use client";
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", {
|
Object.defineProperty(exports, "__esModule", {
|
||||||
value: true
|
value: true
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
], factory);
|
], factory);
|
||||||
else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) factory(global.input = {});
|
else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) factory(global.input = {});
|
||||||
})(this, function(exports) {
|
})(this, function(exports) {
|
||||||
|
"use client";
|
||||||
"use strict";
|
"use strict";
|
||||||
Object.defineProperty(exports, "__esModule", {
|
Object.defineProperty(exports, "__esModule", {
|
||||||
value: true
|
value: true
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
"foo";
|
||||||
|
|
||||||
|
"use bar";
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
// All above are directives
|
||||||
|
|
||||||
|
function foo() { }
|
||||||
|
|
||||||
|
"use hello"; // This is not directive
|
@ -0,0 +1,11 @@
|
|||||||
|
define([
|
||||||
|
"require"
|
||||||
|
], function(require) {
|
||||||
|
"use client";
|
||||||
|
"foo";
|
||||||
|
"use bar";
|
||||||
|
"use strict";
|
||||||
|
// All above are directives
|
||||||
|
function foo() {}
|
||||||
|
"use hello"; // This is not directive
|
||||||
|
});
|
@ -0,0 +1,7 @@
|
|||||||
|
"use client";
|
||||||
|
"foo";
|
||||||
|
"use bar";
|
||||||
|
"use strict";
|
||||||
|
// All above are directives
|
||||||
|
function foo() {}
|
||||||
|
"use hello"; // This is not directive
|
@ -0,0 +1,13 @@
|
|||||||
|
(function(global, factory) {
|
||||||
|
if (typeof module === "object" && typeof module.exports === "object") factory();
|
||||||
|
else if (typeof define === "function" && define.amd) define([], factory);
|
||||||
|
else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) factory();
|
||||||
|
})(this, function() {
|
||||||
|
"use client";
|
||||||
|
"foo";
|
||||||
|
"use bar";
|
||||||
|
"use strict";
|
||||||
|
// All above are directives
|
||||||
|
function foo() {}
|
||||||
|
"use hello"; // This is not directive
|
||||||
|
});
|
@ -2262,6 +2262,7 @@ pub fn prepend_stmts<T: StmtLike>(
|
|||||||
|
|
||||||
pub trait IsDirective {
|
pub trait IsDirective {
|
||||||
fn as_ref(&self) -> Option<&Stmt>;
|
fn as_ref(&self) -> Option<&Stmt>;
|
||||||
|
#[deprecated(note = "use directive_continue instead")]
|
||||||
fn is_directive(&self) -> bool {
|
fn is_directive(&self) -> bool {
|
||||||
match self.as_ref() {
|
match self.as_ref() {
|
||||||
Some(Stmt::Expr(expr)) => match &*expr.expr {
|
Some(Stmt::Expr(expr)) => match &*expr.expr {
|
||||||
@ -2273,6 +2274,15 @@ pub trait IsDirective {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn directive_continue(&self) -> bool {
|
||||||
|
match self.as_ref() {
|
||||||
|
Some(Stmt::Expr(expr)) => match &*expr.expr {
|
||||||
|
Expr::Lit(Lit::Str(..)) => true,
|
||||||
|
_ => false,
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
fn is_use_strict(&self) -> bool {
|
fn is_use_strict(&self) -> bool {
|
||||||
match self.as_ref() {
|
match self.as_ref() {
|
||||||
Some(Stmt::Expr(expr)) => match *expr.expr {
|
Some(Stmt::Expr(expr)) => match *expr.expr {
|
||||||
@ -2292,6 +2302,18 @@ impl IsDirective for Stmt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IsDirective for ModuleItem {
|
||||||
|
fn as_ref(&self) -> Option<&Stmt> {
|
||||||
|
self.as_stmt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsDirective for &ModuleItem {
|
||||||
|
fn as_ref(&self) -> Option<&Stmt> {
|
||||||
|
self.as_stmt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait IdentExt {
|
pub trait IdentExt {
|
||||||
fn prefix(&self, prefix: &str) -> Ident;
|
fn prefix(&self, prefix: &str) -> Ident;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user