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

[WIP] Refactor the compiler #6894

Closed
wants to merge 1 commit into from
Closed

Conversation

kitsonk
Copy link
Contributor

@kitsonk kitsonk commented Jul 27, 2020

This is a major refactor of the TypeScript compilation infrastructure. Raising for early visibility, but it is still very much a work in progress. It totally rewrites how the compilations are handled to abstract out the logic, which should make it easier to move parts and pieces in the future, at the same time leveraging more Rust infrastructure and signficantly "dumbing" down the interface to the TypeScript compiler.

Currently it is a seperate crate as that has been easier for me to work on it without having to deal with merge conflicts and other changes.

Currently I have the following working:

  • Ability to create snapshots with custom libs (like deno.ns).
  • Ability to compile a set of sources and specify any custom libs to type check against.
  • Ability to transpile an arbitrary set of sources.

Things that I need to do:

  • Introduce bundling, which the bundle creation will be done in Rust, using the TypeScript compiler just for type checking and transpilation.
  • Finish off the display of the diagnostics.
  • Look at moving the dependency graph logic in.
  • Integrate into the CLI.

When finished this will:

Fixes #5606
Fixes #5607
Fixes #6686

@ry
Copy link
Member

ry commented Jul 27, 2020

Can you git mv the various typescript files so the diff was easier to look at?

@CLAassistant
Copy link

CLAassistant commented Jul 27, 2020

CLA assistant check
All committers have signed the CLA.

@kitsonk
Copy link
Contributor Author

kitsonk commented Jul 28, 2020

Can you git mv the various typescript files so the diff was easier to look at?

If I did that right now, it would break CLI, so I have simply hacked around it for now.

@kitsonk kitsonk force-pushed the deno_compiler branch 3 times, most recently from ead32a6 to 97252ec Compare July 29, 2020 07:32
cli/tsc/00_typescript.js Outdated Show resolved Hide resolved
@kitsonk kitsonk force-pushed the deno_compiler branch 2 times, most recently from 905f218 to c03b273 Compare August 12, 2020 21:31
@kitsonk kitsonk force-pushed the deno_compiler branch 2 times, most recently from ea84031 to 3fd14f0 Compare August 14, 2020 20:26
@kitsonk
Copy link
Contributor Author

kitsonk commented Aug 15, 2020

It is getting closer and closer. Still to do:

  • Bundle needs to be refactored use Graph.
  • bring in the swc type stripping/transpiling
  • The diagnostics refactor needs to be completed.
  • import-map could use some cleanup and refactoring, maybe after this PR?
  • integrate with cli...
  • question: are redirects handled properly?
  • provide runtime APIs, likely will just go with the refactor proposed in Refactor runtime compiler APIs #4752 instead of trying to re-implement existing ones

Also, this will provide even more fixes:

Fixes #7005
Fixes #6176
Fixes #6995

Copy link
Member

@bartlomieju bartlomieju left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kitsonk here are some of my initial questions, I need to go over this PR a few more times as it's very compilated. Also what's your plan regarding integration with CLI?

serde = { version = "1.0.115", features = ["derive"] }
sourcemap = "6.0.1"
swc_common = { version = "=0.9.1", features = ["sourcemap"] }
swc_ecma_transforms = { version = "=0.19.7", features = ["react"] }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's already part of swc_ecmascript given "transforms" feature

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It wasn't... It was panic'ing. I will try again.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, validated it again, if I remove that, I get:

error[E0432]: unresolved import `swc_ecmascript::transforms::react`
  --> compiler/ast.rs:40:5
   |
40 | use swc_ecmascript::transforms::react;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `react` in `transforms`

So it appears to not be included in swc_ecmascript and you have to include the other crate to have it be available.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CC @kdy1 is there a better way to this?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I forgot adding cargo features to swc_ecmascript. I'm too good at forgotting thngs :(
I'll publish a patch soon.

compiler/ast.rs Outdated Show resolved Hide resolved
compiler/ast.rs Outdated Show resolved Hide resolved
Comment on lines 1 to 10
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.

use crate::source_map_bundler::SourceMapBundler;
use crate::Result;

use deno_core::ErrBox;
use std::error::Error;
use std::fmt;
use std::path::PathBuf;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sooo... swc_bundler is now available and I wanted to try and incorporate it into our workflow, but I guess we'll start with your version first and then try to switch to it. WDYT?

compiler/compiler.js Show resolved Hide resolved
compiler/config.rs Show resolved Hide resolved
compiler/module_graph.rs Show resolved Hide resolved
compiler/module_graph.rs Outdated Show resolved Hide resolved
compiler/module_graph.rs Outdated Show resolved Hide resolved
Comment on lines +3 to +6
use crate::msg::MediaType;
use crate::Result;

use deno_core::ErrBox;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self, most of the contents of this file are used in cli/ (mainly for compiler purposes but also for deno doc) as well as in deno_lint. It should be made into a utility crate that is shared between the other crates.

Comment on lines 3 to 17
use crate::ast::parse;
use crate::ast::Location;
use crate::ast::ParsedModule;
use crate::compiler::CompileOptions;
use crate::compiler::CompilerEmit;
use crate::compiler::CompilerIsolate;
use crate::compiler::TranspileOptions;
use crate::import_map::ImportMap;
use crate::msg::EmittedFile;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self: ModuleGraph/Graph should be used for deno info, investigate if this struct could be made into two separate structs - one for loading and parsing of dependencies (think collecting module tree), second for integration with TS compiler cache (think utilizing the graph that collects module tree to process the tree further). See #6786 for reference

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While it sort of overloads it a bit, I sort of like them together... In that Graph contains all the information that ops need to access files, you just wire it into that... I like having all the "what you can do with a graph" on the surface API of the graph...

For GraphBuilder there is only:

  • insert - Add a specifier as a "root".
  • get_graph - Move the graph out.

For Graph it currently is:

Updating a graph:

  • compile (update the graph with type checked code)
  • transpile (update the graph with type stripped code)

Things I need to refactor out/make non-public:

  • update (take emitted files and update the graph... I need to refactor this out, as compile and transpile should automatically do this, making the compiler less dependent)
  • flush (flush any "dirty" modules to the cache, again this should be refactored out as it need to be handled by compiler and transpile)
  • get_root_names (this was used by compiler.compile but needs to be passed)
  • get_sources (this was used by transpile but need to be passed)

Then needed for compiler ops:

  • pub modules (the Hashmap of modules)
  • resolve (takes a string specifier and a base module specifier and returns the module specifier in the graph, abstracting out all the logic for @deno-types and X-TypeScript-Types and triple-slash reference)
  • get_build_info/set_build_info

But talking that through here sounds like I should refactor that last group as a trait (and abstract out the public access to the hashmap of module).

Adding in info() to the Graph makes a lot of sense, and/or have the Display of a Graph be the output we need for info.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I have done a refactor... I still want to do some fine tuning of it, but basically the compiler and the graph are better decoupled, and the compiler ops only depend upon to methods in a trait. It means in practice, the only thing that needs to be interfaced with is the GraphBuilder and the Graph.

Comment on lines +2 to +6

use crate::Result;

use deno_core::ModuleSpecifier;
use indexmap::IndexMap;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ImportMap implementation hasn't really changed since it was introduced last year in May, maybe it would make more sense to make it a separate crate as well? It would still depend on deno_core for the sake of ModuleSpecifier, but could limit complexity by having a clear boundary between the crates. @kitsonk @ry what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it will "move" here, it shouldn't be needed by the CLI anywhere else. Though of course compiler is sort of becoming a bad name for this crate... but basically it is the all the higher order logic of dependency/handling/transforming/type checking of ES Modules under Deno, abstracted away from the fetching/caching/persistence/runtime execution considerations.

compiler/ast.rs Outdated Show resolved Hide resolved
@bartlomieju
Copy link
Member

question: are redirects handled properly?

At the moment I can't see any handling of redirects, I think we can punt on this issue for a bit longer. We need to take holistic approach and coordinate redirect handling in deno_core as well. See:

deno/core/modules.rs

Lines 40 to 44 in 684eddc

// TODO(bartlomieju): I have a strong opinion we should store all redirects
// that happened; not only first and final target. It would simplify a lot
// of things throughout the codebase otherwise we may end up requesting
// intermediate redirects from file loader.
#[derive(Debug, Eq, PartialEq)]

@kitsonk
Copy link
Contributor Author

kitsonk commented Aug 27, 2020

In chatting with @ry and @bartlomieju we agreed that we need to break this up into seperate things and for right now, moving this logic out to a seperate crate doesn't make sense...

I will use this branch though as a reference implementation for myself (and for @bartlomieju) to land some/all of these changes over a period of time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants