Skip to content

Commit

Permalink
Remove this exports tracking for files with module syntax (#9330)
Browse files Browse the repository at this point in the history
Co-authored-by: Devon Govett <devongovett@gmail.com>
  • Loading branch information
mattcompiles and devongovett committed Oct 23, 2023
1 parent 295958f commit 808edd8
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 25 deletions.
41 changes: 41 additions & 0 deletions packages/core/integration-tests/test/scope-hoisting.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
overlayFS,
run,
runBundle,
fsFixture,
} from '@parcel/test-utils';

const bundle = (name, opts = {}) => {
Expand Down Expand Up @@ -2487,6 +2488,23 @@ describe('scope hoisting', function () {
assert.equal(await output, 42);
});

it('should handle TSC polyfills', async () => {
await fsFixture(overlayFS, __dirname)`
tsc-polyfill-es6
library.js:
var __polyfill = (this && this.__polyfill) || function (a) {return a;};
export default __polyfill('es6')
index.js:
import value from './library';
output = value;`;

let b = await bundle(path.join(__dirname, 'tsc-polyfill-es6/index.js'), {
inputFS: overlayFS,
});
assert.equal(await run(b), 'es6');
});

describe("considers an asset's closest package.json for sideEffects, not the package through which it found the asset", () => {
it('handles redirects up the tree', async () => {
let b = await bundle(
Expand Down Expand Up @@ -5265,6 +5283,29 @@ describe('scope hoisting', function () {

assert.deepEqual(await run(b), {test: 2});
});

it('should handle TSC polyfills', async () => {
await fsFixture(overlayFS, __dirname)`
tsc-polyfill-commonjs
library.js:
"use strict";
var __polyfill = (this && this.__polyfill) || function (a) {return a;};
exports.value = __polyfill('cjs')
index.js:
const value = require('./library');
output = value;
`;

let b = await bundle(
path.join(__dirname, 'tsc-polyfill-commonjs/index.js'),
{
inputFS: overlayFS,
},
);

assert.deepEqual(await run(b), {value: 'cjs'});
});
});

it('should not throw with JS included from HTML', async function () {
Expand Down
30 changes: 7 additions & 23 deletions packages/transformers/js/core/src/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub struct Collect {
in_function: bool,
in_assign: bool,
in_class: bool,
is_module: bool,
}

#[derive(Debug, Serialize)]
Expand Down Expand Up @@ -120,12 +121,14 @@ impl Collect {
ignore_mark: Mark,
global_mark: Mark,
trace_bailouts: bool,
is_module: bool,
) -> Self {
Collect {
source_map,
decls,
ignore_mark,
global_mark,
is_module,
static_cjs_exports: true,
has_cjs_exports: false,
is_esm: false,
Expand Down Expand Up @@ -690,7 +693,9 @@ impl Visit for Collect {
}
Expr::This(_this) => {
if self.in_module_this {
handle_export!();
if !self.is_module {
handle_export!();
}
} else if !self.in_class {
if let MemberProp::Ident(prop) = &node.prop {
self.this_exprs.insert(id!(prop), (prop.clone(), node.span));
Expand Down Expand Up @@ -767,27 +772,6 @@ impl Visit for Collect {
self.used_imports.insert(id!(ident));
}
}
Expr::Bin(bin_expr) => {
if self.in_module_this {
// Some TSC polyfills use a pattern like below.
// We want to avoid marking these modules as CJS
// e.g. var _polyfill = (this && this.polyfill) || function () {}
if matches!(bin_expr.op, BinaryOp::LogicalAnd) && matches!(*bin_expr.left, Expr::This(..))
{
match &*bin_expr.right {
Expr::Member(member_expr) => {
if matches!(*member_expr.obj, Expr::This(..))
&& matches!(member_expr.prop, MemberProp::Ident(..))
{
return;
}
}
_ => {}
}
}
}
node.visit_children_with(self);
}
_ => {
node.visit_children_with(self);
}
Expand Down Expand Up @@ -820,7 +804,7 @@ impl Visit for Collect {
}

fn visit_this_expr(&mut self, node: &ThisExpr) {
if self.in_module_this {
if !self.is_module && self.in_module_this {
self.has_cjs_exports = true;
self.static_cjs_exports = false;
self.add_bailout(node.span, BailoutReason::FreeExports);
Expand Down
2 changes: 2 additions & 0 deletions packages/transformers/js/core/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub fn inline_fs<'a>(
global_mark: Mark,
project_root: &'a str,
deps: &'a mut Vec<DependencyDescriptor>,
is_module: bool,
) -> impl Fold + 'a {
InlineFS {
filename: Path::new(filename).to_path_buf(),
Expand All @@ -26,6 +27,7 @@ pub fn inline_fs<'a>(
Mark::fresh(Mark::root()),
global_mark,
false,
is_module,
),
global_mark,
project_root,
Expand Down
16 changes: 14 additions & 2 deletions packages/transformers/js/core/src/hoist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1140,11 +1140,21 @@ mod tests {
);

let mut parser = Parser::new_from(lexer);
match parser.parse_module() {
Ok(module) => swc_core::common::GLOBALS.set(&Globals::new(), || {
match parser.parse_program() {
Ok(program) => swc_core::common::GLOBALS.set(&Globals::new(), || {
swc_core::ecma::transforms::base::helpers::HELPERS.set(
&swc_core::ecma::transforms::base::helpers::Helpers::new(false),
|| {
let is_module = program.is_module();
let module = match program {
Program::Module(module) => module,
Program::Script(script) => Module {
span: script.span,
shebang: None,
body: script.body.into_iter().map(ModuleItem::Stmt).collect(),
},
};

let unresolved_mark = Mark::fresh(Mark::root());
let global_mark = Mark::fresh(Mark::root());
let module = module.fold_with(&mut resolver(unresolved_mark, global_mark, false));
Expand All @@ -1155,6 +1165,7 @@ mod tests {
Mark::fresh(Mark::root()),
global_mark,
true,
is_module,
);
module.visit_with(&mut collect);

Expand Down Expand Up @@ -1444,6 +1455,7 @@ mod tests {
// We want to avoid marking these modules as CJS
let (collect, _code, _hoist) = parse(
r#"
import 'something';
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function () {}
"#,
);
Expand Down
3 changes: 3 additions & 0 deletions packages/transformers/js/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ pub fn transform(config: Config) -> Result<TransformResult, std::io::Error> {
),
));

let is_module = module.is_module();
// If it's a script, convert into module. This needs to happen after
// the resolver (which behaves differently for non-/strict mode).
let module = match module {
Expand Down Expand Up @@ -342,6 +343,7 @@ pub fn transform(config: Config) -> Result<TransformResult, std::io::Error> {
global_mark,
&config.project_root,
&mut fs_deps,
is_module
),
should_inline_fs
),
Expand Down Expand Up @@ -448,6 +450,7 @@ pub fn transform(config: Config) -> Result<TransformResult, std::io::Error> {
ignore_mark,
global_mark,
config.trace_bailouts,
is_module,
);
module.visit_with(&mut collect);
if let Some(bailouts) = &collect.bailouts {
Expand Down

0 comments on commit 808edd8

Please sign in to comment.