Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(es/compat): Implement transform for explicit resource management #7376

Merged
merged 68 commits into from
Jun 29, 2023
Merged
Show file tree
Hide file tree
Changes from 62 commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
f164917
Add a test
kdy1 May 11, 2023
ebc1193
More work
kdy1 May 11, 2023
fed116f
test
kdy1 May 11, 2023
dffab9f
test_fixture
kdy1 May 11, 2023
cf3bdbb
Add tests
kdy1 Jun 20, 2023
4df3c9c
Rename
kdy1 Jun 20, 2023
3ccc155
output path
kdy1 Jun 20, 2023
cc066ce
Fix path
kdy1 Jun 20, 2023
df0c3a3
Typo
kdy1 Jun 20, 2023
83e22df
mjs
kdy1 Jun 20, 2023
262e96f
exec
kdy1 Jun 20, 2023
62ca46e
test name
kdy1 Jun 20, 2023
0a4489b
`await_`
kdy1 Jun 20, 2023
d2a5479
Fix visitor
kdy1 Jun 20, 2023
ba73363
`is_await`
kdy1 Jun 20, 2023
fe5f1d8
fixup
kdy1 Jun 20, 2023
088cd13
await
kdy1 Jun 20, 2023
be84c8f
serde
kdy1 Jun 20, 2023
93c5e5b
Fix quote
kdy1 Jun 20, 2023
028c537
`visit_mut_stmt_likes`
kdy1 Jun 27, 2023
9bbaf40
codegen
kdy1 Jun 27, 2023
0bffa0d
More
kdy1 Jun 27, 2023
7f2e857
WIP
kdy1 Jun 27, 2023
69f71d4
helper
kdy1 Jun 29, 2023
f05664f
try
kdy1 Jun 29, 2023
95823f4
_using
kdy1 Jun 29, 2023
8810c61
using
kdy1 Jun 29, 2023
7d37526
sort
kdy1 Jun 29, 2023
0cdb779
Prevent overflow
kdy1 Jun 29, 2023
e0b9c99
stack var
kdy1 Jun 29, 2023
694cd7b
await using
kdy1 Jun 29, 2023
16ab2b1
await
kdy1 Jun 29, 2023
18831f0
Var decl
kdy1 Jun 29, 2023
11bf306
input.mjs
kdy1 Jun 29, 2023
5e5bcd2
`allow_using_decl`
kdy1 Jun 29, 2023
f839993
`allow_using_decl`
kdy1 Jun 29, 2023
a220dda
Drop `;`
kdy1 Jun 29, 2023
2018855
fixup: doc
kdy1 Jun 29, 2023
e98c211
await dispose
kdy1 Jun 29, 2023
fd8e906
is_await
kdy1 Jun 29, 2023
533fb3e
order
kdy1 Jun 29, 2023
566ee08
Update test refs
kdy1 Jun 29, 2023
0a4365d
const
kdy1 Jun 29, 2023
7c1060e
Update test refs
kdy1 Jun 29, 2023
fa0c57a
Update test refs
kdy1 Jun 29, 2023
7c96a55
Ignore
kdy1 Jun 29, 2023
16a7411
Update test refs
kdy1 Jun 29, 2023
c562a1e
external helpers
kdy1 Jun 29, 2023
0e068e1
Update test refs
kdy1 Jun 29, 2023
f5761be
Update test refs
kdy1 Jun 29, 2023
e5b404b
Fix parser
kdy1 Jun 29, 2023
0cda26a
`use_const`
kdy1 Jun 29, 2023
12a393a
Update test refs
kdy1 Jun 29, 2023
3f7ecfa
for of
kdy1 Jun 29, 2023
faee8e7
fixup
kdy1 Jun 29, 2023
059a37e
Update test refs
kdy1 Jun 29, 2023
a733502
Rename
kdy1 Jun 29, 2023
35a6b5c
hoist
kdy1 Jun 29, 2023
98999aa
export default decl
kdy1 Jun 29, 2023
fe2aabf
Update test refs
kdy1 Jun 29, 2023
9139151
export default expr
kdy1 Jun 29, 2023
7349008
Update test refs
kdy1 Jun 29, 2023
6806fd2
Update test refs
kdy1 Jun 29, 2023
b771a14
_
kdy1 Jun 29, 2023
1ad03e6
Fix helpers
kdy1 Jun 29, 2023
2e59114
Merge branch 'main' into erm-transform
swc-bot Jun 29, 2023
29f8b58
Merge branch 'main' into erm-transform
swc-bot Jun 29, 2023
23b739d
Ignore
kdy1 Jun 29, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions crates/swc_ecma_ast/src/decl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,21 @@ impl Take for VarDeclarator {
#[derive(Eq, Hash, EqIgnoreSpan)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub struct UsingDecl {
#[cfg_attr(feature = "serde-impl", serde(default))]
pub span: Span,

#[cfg_attr(feature = "serde-impl", serde(default))]
pub is_await: bool,

#[cfg_attr(feature = "serde-impl", serde(default))]
pub decls: Vec<VarDeclarator>,
}

impl Take for UsingDecl {
fn dummy() -> Self {
Self {
span: DUMMY_SP,
is_await: Default::default(),
decls: Take::dummy(),
}
}
Expand Down
5 changes: 5 additions & 0 deletions crates/swc_ecma_codegen/src/decl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ where
fn emit_using_decl(&mut self, node: &UsingDecl) -> Result {
self.emit_leading_comments_of_span(node.span(), false)?;

if node.is_await {
keyword!("await");
space!();
}

keyword!("using");
space!();

Expand Down
1 change: 1 addition & 0 deletions crates/swc_ecma_parser/src/parser/class_and_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,7 @@ impl<I: Tokens> Parser<I> {
let body = self
.with_ctx(Context {
in_class_field: true,
allow_using_decl: true,
..self.ctx()
})
.parse_block(false)?;
Expand Down
31 changes: 28 additions & 3 deletions crates/swc_ecma_parser/src/parser/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ impl<'a, I: Tokens> Parser<I> {

let ctx = Context {
will_expect_colon_for_cond: false,
allow_using_decl: true,
..self.ctx()
};
self.with_ctx(ctx)
Expand Down Expand Up @@ -132,6 +133,15 @@ impl<'a, I: Tokens> Parser<I> {
self.emit_err(self.input.cur_span(), SyntaxError::TopLevelAwaitInScript);
}

if peeked_is!(self, "using") {
assert_and_bump!(self, "await");

let v = self.parse_using_decl(start, true)?;
if let Some(v) = v {
return Ok(Stmt::Decl(Decl::Using(v)));
}
}

let expr = self.parse_await_expr()?;
let expr = self
.include_in_expr(true)
Expand All @@ -154,6 +164,16 @@ impl<'a, I: Tokens> Parser<I> {
}

match cur!(self, true)? {
tok!("await") if include_decl => {
if peeked_is!(self, "using") {
assert_and_bump!(self, "await");
let v = self.parse_using_decl(start, true)?;
if let Some(v) = v {
return Ok(Stmt::Decl(Decl::Using(v)));
}
}
}

tok!("break") | tok!("continue") => {
let is_break = is!(self, "break");
bump!(self);
Expand Down Expand Up @@ -302,7 +322,7 @@ impl<'a, I: Tokens> Parser<I> {
}

tok!("using") if include_decl => {
let v = self.parse_using_decl()?;
let v = self.parse_using_decl(start, false)?;
if let Some(v) = v {
return Ok(Stmt::Decl(Decl::Using(v)));
}
Expand Down Expand Up @@ -762,7 +782,11 @@ impl<'a, I: Tokens> Parser<I> {
}
}

pub(super) fn parse_using_decl(&mut self) -> PResult<Option<Box<UsingDecl>>> {
pub(super) fn parse_using_decl(
&mut self,
start: BytePos,
is_await: bool,
) -> PResult<Option<Box<UsingDecl>>> {
// using
// reader = init()

Expand All @@ -776,7 +800,6 @@ impl<'a, I: Tokens> Parser<I> {
return Ok(None);
}

let start = cur_pos!(self);
assert_and_bump!(self, "using");

let mut decls = vec![];
Expand Down Expand Up @@ -822,6 +845,7 @@ impl<'a, I: Tokens> Parser<I> {

Ok(Some(Box::new(UsingDecl {
span: span!(self, start),
is_await,
decls,
})))
}
Expand Down Expand Up @@ -1278,6 +1302,7 @@ impl<'a, I: Tokens> Parser<I> {

let pat = Box::new(UsingDecl {
span: span!(self, start),
is_await: false,
decls: vec![decl],
});

Expand Down
2 changes: 1 addition & 1 deletion crates/swc_ecma_quote_macros/src/ast/decl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ impl_struct!(ClassDecl, [ident, class]);
impl_struct!(FnDecl, [ident, function]);
impl_struct!(VarDecl, [span, kind, declare, decls]);
impl_struct!(VarDeclarator, [span, name, init, definite]);
impl_struct!(UsingDecl, [span, decls]);
impl_struct!(UsingDecl, [span, is_await, decls]);
45 changes: 45 additions & 0 deletions crates/swc_ecma_transforms_base/src/helpers/_dispose.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* @minVersion 7.22.0 */
function dispose_SuppressedError(suppressed, error) {
if (typeof SuppressedError !== "undefined") {
// eslint-disable-next-line no-undef
dispose_SuppressedError = SuppressedError;
} else {
dispose_SuppressedError = function SuppressedError(suppressed, error) {
this.suppressed = suppressed;
this.error = error;
this.stack = new Error().stack;
};
dispose_SuppressedError.prototype = Object.create(Error.prototype, {
constructor: {
value: dispose_SuppressedError,
writable: true,
configurable: true,
},
});
}
return new dispose_SuppressedError(suppressed, error);
}

function _dispose(stack, error, hasError) {
function next() {
while (stack.length > 0) {
try {
var r = stack.pop();
var p = r.d.call(r.v);
if (r.a) return Promise.resolve(p).then(next, err);
} catch (e) {
return err(e);
}
}
if (hasError) throw error;
}

function err(e) {
error = hasError ? new dispose_SuppressedError(e, error) : e;
hasError = true;

return next();
}

return next();
}
21 changes: 21 additions & 0 deletions crates/swc_ecma_transforms_base/src/helpers/_using.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
function _using(stack, value, isAwait) {
if (value === null || value === void 0) return value;
if (typeof value !== "object") {
throw new TypeError(
"using declarations can only be used with objects, null, or undefined."
);
}
// core-js-pure uses Symbol.for for polyfilling well-known symbols
if (isAwait) {
var dispose =
value[Symbol.asyncDispose || Symbol.for("Symbol.asyncDispose")];
}
if (dispose === null || dispose === void 0) {
dispose = value[Symbol.dispose || Symbol.for("Symbol.dispose")];
}
if (typeof dispose !== "function") {
throw new TypeError(`Property [Symbol.dispose] is not a function.`);
}
stack.push({ v: value, d: dispose, a: isAwait });
return value;
}
2 changes: 2 additions & 0 deletions crates/swc_ecma_transforms_base/src/helpers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,8 @@ define_helpers!(Helpers {

apply_decs_2203_r: (),
identity: (),
dispose: (),
using: (),
});

pub fn inject_helpers(global_mark: Mark) -> impl Fold + VisitMut {
Expand Down