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

Suboptimal code generation for transpiled class expressions #1660

Closed
mischnic opened this issue May 8, 2021 · 2 comments · Fixed by #1664 or #1669
Closed

Suboptimal code generation for transpiled class expressions #1660

mischnic opened this issue May 8, 2021 · 2 comments · Fixed by #1664 or #1669
Assignees
Labels
Milestone

Comments

@mischnic
Copy link
Contributor

mischnic commented May 8, 2021

Describe the bug

There is a unnecessary IIFE wrapper (which is also missing a pure comment, but ideally it would be removed entirely) around class expressions (not declarations)

Input code

console.log(class {run(){}});

Output code

console.log(function() {
    var _class = /*#__PURE__*/ function() {
        "use strict";
        function _class() {
            _classCallCheck(this, _class);
        }
        _createClass(_class, [
            {
                key: "run",
                value: function run() {
                }
            }
        ]);
        return _class;
    }();
    return _class;
}());

Expected behavior

Something like

console.log(/*#__PURE__*/ function() {
        "use strict";
        function _class() {
            _classCallCheck(this, _class);
        }
        _createClass(...);
        return _class;
    }()
);

so without that function(){var _class = ...; return _class;}() wrapper

Config

Full example
use swc_common::comments::SingleThreadedComments;
use swc_common::{chain, sync::Lrc, FileName, Globals, Mark, SourceMap};
use swc_ecma_ast::Module;
use swc_ecma_codegen::text_writer::JsWriter;
use swc_ecma_codegen::{Config, Emitter};
use swc_ecma_parser::lexer::Lexer;
use swc_ecma_parser::{EsConfig, PResult, Parser, StringInput, Syntax};
use swc_ecma_preset_env::preset_env;
use swc_ecma_transforms::{
    compat::reserved_words::reserved_words, fixer, helpers, hygiene, resolver::resolver_with_mark,
};
use swc_ecma_visit::FoldWith;

fn main() {
    let cm = Lrc::<SourceMap>::default();
    // let src = "console.log(<h1>s</h1>);";
    let src = "console.log(class {run(){}});";
    let (module, comments) = parse(src, "test.js", &cm).unwrap();

    swc_common::GLOBALS.set(&Globals::new(), || {
        helpers::HELPERS.set(&helpers::Helpers::default(), || {
            let global_mark = Mark::fresh(Mark::root());
            let module = module.fold_with(&mut resolver_with_mark(global_mark));

            // let transform =
            //     &mut react::react(cm.clone(), Some(&comments),
            // react::Options::default());
            let transform = &mut preset_env(
                global_mark,
                Some(&comments),
                swc_ecma_preset_env::Config::default(),
            );
            let module = module.fold_with(transform);

            println!("{:?}", comments);

            let module = module.fold_with(&mut chain!(
                reserved_words(),
                hygiene(),
                fixer(Some(&comments))
            ));

            let code = emit(&module, &comments, cm);
            println!("{}", code);
        });
    });
}

fn parse(
    code: &str,
    filename: &str,
    cm: &Lrc<SourceMap>,
) -> PResult<(Module, SingleThreadedComments)> {
    let source_file = cm.new_source_file(FileName::Real(filename.into()), code.into());
    let comments = SingleThreadedComments::default();

    let lexer = Lexer::new(
        Syntax::Es(EsConfig {
            jsx: true,
            ..Default::default()
        }),
        Default::default(),
        StringInput::from(&*source_file),
        Some(&comments),
    );
    let mut parser = Parser::new_from(lexer);
    match parser.parse_module() {
        Err(err) => Err(err),
        Ok(module) => Ok((module, comments)),
    }
}

fn emit(module: &Module, comments: &SingleThreadedComments, cm: Lrc<SourceMap>) -> String {
    let mut buf = vec![];
    {
        let writer = Box::new(JsWriter::new(cm.clone(), "\n", &mut buf, None));
        let config = Config { minify: false };
        let mut emitter = Emitter {
            cfg: config,
            comments: Some(&comments),
            cm,
            wr: writer,
        };
        emitter.emit_module(&module).unwrap();
    }

    String::from_utf8(buf).unwrap()
}

Version
c3bf517

@mischnic mischnic added the C-bug label May 8, 2021
@kdy1 kdy1 added this to the v1.2.57 milestone May 9, 2021
kdy1 added a commit to kdy1/swc that referenced this issue May 9, 2021
kdy1 added a commit to kdy1/swc that referenced this issue May 9, 2021
@kdy1 kdy1 mentioned this issue May 9, 2021
2 tasks
@kdy1 kdy1 self-assigned this May 9, 2021
@kdy1 kdy1 closed this as completed in #1664 May 9, 2021
kdy1 added a commit that referenced this issue May 9, 2021
swc_ecma_codegen:
 - Emit comments of `BytePos(0)`. (#1657)

swc_ecma_transforms_compat:
 - `classes`: Optimize class expresssions. (#1660)
@mischnic
Copy link
Contributor Author

mischnic commented May 9, 2021

With your PR, I'm still seeing the additional wrapper

console.log(function() {
    var _class = /*#__PURE__*/ function() {
        "use strict";
        function _class() {
            _classCallCheck(this, _class);
        }
        _createClass(_class, [
            {
                key: "run",
                value: function run() {
                }
            }
        ]);
        return _class;
    }();
    return _class;
}());

@kdy1 kdy1 reopened this May 9, 2021
kdy1 added a commit to kdy1/swc that referenced this issue May 9, 2021
kdy1 added a commit to kdy1/swc that referenced this issue May 9, 2021
kdy1 added a commit to kdy1/swc that referenced this issue May 9, 2021
kdy1 added a commit to kdy1/swc that referenced this issue May 9, 2021
kdy1 added a commit to kdy1/swc that referenced this issue May 9, 2021
kdy1 added a commit that referenced this issue May 10, 2021
swc_ecma_transforms_compat:
 - `class_properties`: Do not create iife if possible. (#1660)
@swc-bot
Copy link
Collaborator

swc-bot commented Oct 24, 2022

This closed issue has been automatically locked because it had no new activity for a month. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@swc-project swc-project locked as resolved and limited conversation to collaborators Oct 24, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
3 participants