mirror of
https://github.com/swc-project/swc.git
synced 2024-12-25 14:43:33 +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},
|
||||
path::{ImportResolver, Resolver},
|
||||
util::{
|
||||
clone_first_use_directive, define_es_module, emit_export_stmts, local_name_for_src,
|
||||
use_strict, ImportInterop,
|
||||
define_es_module, emit_export_stmts, local_name_for_src, use_strict, ImportInterop,
|
||||
VecStmtLike,
|
||||
},
|
||||
};
|
||||
|
||||
@ -143,9 +143,19 @@ where
|
||||
|
||||
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";
|
||||
if self.config.strict_mode {
|
||||
stmts.push(clone_first_use_directive(&n.body, true).unwrap_or_else(use_strict));
|
||||
if self.config.strict_mode && !stmts.has_use_strict() {
|
||||
stmts.push(use_strict());
|
||||
}
|
||||
|
||||
let ModuleDeclStrip {
|
||||
@ -170,7 +180,7 @@ where
|
||||
);
|
||||
|
||||
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,
|
||||
}));
|
||||
|
||||
|
@ -16,8 +16,8 @@ use crate::{
|
||||
module_ref_rewriter::{ImportMap, ModuleRefRewriter},
|
||||
path::{ImportResolver, Resolver},
|
||||
util::{
|
||||
clone_first_use_directive, define_es_module, emit_export_stmts, local_name_for_src,
|
||||
prop_name, use_strict, ImportInterop, ObjPropKeyIdent,
|
||||
define_es_module, emit_export_stmts, local_name_for_src, prop_name, use_strict,
|
||||
ImportInterop, ObjPropKeyIdent, VecStmtLike,
|
||||
},
|
||||
};
|
||||
|
||||
@ -113,15 +113,18 @@ where
|
||||
|
||||
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";
|
||||
if self.config.strict_mode {
|
||||
stmts.push(
|
||||
clone_first_use_directive(&n.body, true)
|
||||
.unwrap_or_else(use_strict)
|
||||
.into(),
|
||||
);
|
||||
if self.config.strict_mode && !stmts.has_use_strict() {
|
||||
stmts.push(use_strict().into());
|
||||
}
|
||||
|
||||
let ModuleDeclStrip {
|
||||
@ -156,7 +159,7 @@ where
|
||||
);
|
||||
|
||||
stmts.extend(n.body.take().into_iter().filter(|item| match item {
|
||||
ModuleItem::Stmt(stmt) => !stmt.is_directive(),
|
||||
ModuleItem::Stmt(stmt) => !stmt.is_empty(),
|
||||
_ => false,
|
||||
}));
|
||||
|
||||
|
@ -17,8 +17,8 @@ use crate::{
|
||||
module_ref_rewriter::{ImportMap, ModuleRefRewriter},
|
||||
path::{ImportResolver, Resolver},
|
||||
util::{
|
||||
clone_first_use_directive, define_es_module, emit_export_stmts, local_name_for_src,
|
||||
use_strict, ImportInterop,
|
||||
define_es_module, emit_export_stmts, local_name_for_src, use_strict, ImportInterop,
|
||||
VecStmtLike,
|
||||
},
|
||||
};
|
||||
|
||||
@ -116,9 +116,18 @@ where
|
||||
|
||||
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";
|
||||
if self.config.config.strict_mode {
|
||||
stmts.push(clone_first_use_directive(module_items, true).unwrap_or_else(use_strict));
|
||||
if self.config.config.strict_mode && !stmts.has_use_strict() {
|
||||
stmts.push(use_strict());
|
||||
}
|
||||
|
||||
let ModuleDeclStrip {
|
||||
@ -143,7 +152,7 @@ where
|
||||
);
|
||||
|
||||
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,
|
||||
}));
|
||||
|
||||
|
@ -194,26 +194,33 @@ pub(super) fn define_es_module(exports: Ident) -> Stmt {
|
||||
.into_stmt()
|
||||
}
|
||||
|
||||
pub(super) fn clone_first_use_directive(
|
||||
stmts: &[ModuleItem],
|
||||
want_use_strict: bool,
|
||||
) -> Option<Stmt> {
|
||||
if stmts.is_empty() {
|
||||
return None;
|
||||
}
|
||||
pub(super) trait VecStmtLike {
|
||||
type StmtLike: IsDirective;
|
||||
|
||||
stmts.iter().find_map(|item| match item {
|
||||
ModuleItem::Stmt(stmt) => {
|
||||
if (want_use_strict && stmt.is_use_strict())
|
||||
|| (!want_use_strict && !stmt.is_use_strict() && stmt.is_directive())
|
||||
{
|
||||
Some(stmt.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
})
|
||||
fn as_ref(&self) -> &[Self::StmtLike];
|
||||
|
||||
fn has_use_strict(&self) -> bool {
|
||||
self.as_ref()
|
||||
.iter()
|
||||
.take_while(|s| s.directive_continue())
|
||||
.any(IsDirective::is_use_strict)
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -3,6 +3,7 @@ define([
|
||||
"require",
|
||||
"exports"
|
||||
], function(require, exports) {
|
||||
"use client";
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
|
@ -6,6 +6,7 @@
|
||||
], factory);
|
||||
else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) factory(global.input = {});
|
||||
})(this, function(exports) {
|
||||
"use client";
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
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 {
|
||||
fn as_ref(&self) -> Option<&Stmt>;
|
||||
#[deprecated(note = "use directive_continue instead")]
|
||||
fn is_directive(&self) -> bool {
|
||||
match self.as_ref() {
|
||||
Some(Stmt::Expr(expr)) => match &*expr.expr {
|
||||
@ -2273,6 +2274,15 @@ pub trait IsDirective {
|
||||
_ => 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 {
|
||||
match self.as_ref() {
|
||||
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 {
|
||||
fn prefix(&self, prefix: &str) -> Ident;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user