perf(es/codegen, es/parser): Improve performance (#2406)

ast_node:
 - Make `.span()` inlinable.

swc_ecma_codegen:
 - Reduce call to *heavy* `.span()` calls.

swc_ecma_parser:
 - Reduce `memmove` by using typed-arena.

swc_bundler:
 - Make `Bundle.bundle` take `&mut self`.
 - Make drop concurrent.
This commit is contained in:
Donny/강동윤 2021-10-15 12:49:37 +09:00 committed by GitHub
parent 93a7a17472
commit 4c983e9158
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 903 additions and 612 deletions

56
Cargo.lock generated
View File

@ -147,7 +147,7 @@ dependencies = [
[[package]]
name = "ast_node"
version = "0.7.3"
version = "0.7.4"
dependencies = [
"darling",
"pmutil",
@ -2324,7 +2324,7 @@ checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c"
[[package]]
name = "swc"
version = "0.68.1"
version = "0.69.0"
dependencies = [
"ahash",
"anyhow",
@ -2428,7 +2428,7 @@ dependencies = [
[[package]]
name = "swc_bundler"
version = "0.69.0"
version = "0.70.0"
dependencies = [
"ahash",
"anyhow",
@ -2500,7 +2500,7 @@ dependencies = [
[[package]]
name = "swc_css"
version = "0.15.0"
version = "0.16.0"
dependencies = [
"swc_css_ast",
"swc_css_codegen",
@ -2511,7 +2511,7 @@ dependencies = [
[[package]]
name = "swc_css_ast"
version = "0.14.0"
version = "0.15.0"
dependencies = [
"is-macro",
"serde",
@ -2522,7 +2522,7 @@ dependencies = [
[[package]]
name = "swc_css_codegen"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"auto_impl",
"bitflags",
@ -2548,7 +2548,7 @@ dependencies = [
[[package]]
name = "swc_css_parser"
version = "0.15.0"
version = "0.16.0"
dependencies = [
"bitflags",
"lexical",
@ -2564,7 +2564,7 @@ dependencies = [
[[package]]
name = "swc_css_utils"
version = "0.11.0"
version = "0.12.0"
dependencies = [
"swc_atoms 0.2.8",
"swc_common",
@ -2574,7 +2574,7 @@ dependencies = [
[[package]]
name = "swc_css_visit"
version = "0.13.0"
version = "0.14.0"
dependencies = [
"swc_atoms 0.2.8",
"swc_common",
@ -2598,7 +2598,7 @@ dependencies = [
[[package]]
name = "swc_ecma_codegen"
version = "0.74.4"
version = "0.75.0"
dependencies = [
"bitflags",
"memchr",
@ -2612,6 +2612,7 @@ dependencies = [
"swc_ecma_parser",
"swc_node_base",
"testing",
"tracing",
]
[[package]]
@ -2674,7 +2675,7 @@ dependencies = [
[[package]]
name = "swc_ecma_minifier"
version = "0.38.1"
version = "0.39.0"
dependencies = [
"ansi_term 0.12.1",
"anyhow",
@ -2706,7 +2707,7 @@ dependencies = [
[[package]]
name = "swc_ecma_parser"
version = "0.73.12"
version = "0.73.13"
dependencies = [
"either",
"enum_kind",
@ -2724,13 +2725,14 @@ dependencies = [
"swc_node_base",
"testing",
"tracing",
"typed-arena",
"unicode-xid",
"walkdir",
]
[[package]]
name = "swc_ecma_preset_env"
version = "0.53.0"
version = "0.54.0"
dependencies = [
"ahash",
"dashmap",
@ -2756,7 +2758,7 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms"
version = "0.82.0"
version = "0.83.0"
dependencies = [
"pretty_assertions 0.6.1",
"sourcemap",
@ -2783,7 +2785,7 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_base"
version = "0.37.5"
version = "0.38.0"
dependencies = [
"once_cell",
"phf",
@ -2801,7 +2803,7 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_classes"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"swc_atoms 0.2.8",
"swc_common",
@ -2813,7 +2815,7 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_compat"
version = "0.42.0"
version = "0.43.0"
dependencies = [
"ahash",
"arrayvec",
@ -2849,7 +2851,7 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_module"
version = "0.46.0"
version = "0.47.0"
dependencies = [
"Inflector",
"ahash",
@ -2872,7 +2874,7 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_optimization"
version = "0.52.0"
version = "0.53.0"
dependencies = [
"ahash",
"dashmap",
@ -2900,7 +2902,7 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_proposal"
version = "0.46.1"
version = "0.47.0"
dependencies = [
"either",
"serde",
@ -2924,7 +2926,7 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_react"
version = "0.48.3"
version = "0.49.0"
dependencies = [
"ahash",
"base64 0.13.0",
@ -2951,7 +2953,7 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_testing"
version = "0.38.1"
version = "0.39.0"
dependencies = [
"ansi_term 0.12.1",
"anyhow",
@ -2970,7 +2972,7 @@ dependencies = [
[[package]]
name = "swc_ecma_transforms_typescript"
version = "0.49.1"
version = "0.50.0"
dependencies = [
"serde",
"swc_atoms 0.2.8",
@ -3018,7 +3020,7 @@ dependencies = [
[[package]]
name = "swc_ecmascript"
version = "0.74.0"
version = "0.75.0"
dependencies = [
"swc_ecma_ast",
"swc_ecma_codegen",
@ -3108,7 +3110,7 @@ dependencies = [
[[package]]
name = "swc_plugin_runner"
version = "0.9.0"
version = "0.10.0"
dependencies = [
"abi_stable",
"anyhow",
@ -3126,7 +3128,7 @@ dependencies = [
[[package]]
name = "swc_plugin_testing"
version = "0.10.0"
version = "0.11.0"
dependencies = [
"anyhow",
"swc_atoms 0.2.8",
@ -3140,7 +3142,7 @@ dependencies = [
[[package]]
name = "swc_stylis"
version = "0.12.0"
version = "0.13.0"
dependencies = [
"swc_atoms 0.2.8",
"swc_common",

View File

@ -20,7 +20,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc"
repository = "https://github.com/swc-project/swc.git"
version = "0.68.1"
version = "0.69.0"
[lib]
name = "swc"
@ -51,16 +51,16 @@ serde = {version = "1", features = ["derive"]}
serde_json = "1"
sourcemap = "6"
swc_atoms = {version = "0.2", path = "./atoms"}
swc_bundler = {version = "0.69.0", path = "./bundler"}
swc_bundler = {version = "0.70.0", path = "./bundler"}
swc_common = {version = "0.13.5", path = "./common", features = ["sourcemap", "concurrent"]}
swc_ecma_ast = {version = "0.54.0", path = "./ecmascript/ast"}
swc_ecma_codegen = {version = "0.74.0", path = "./ecmascript/codegen"}
swc_ecma_codegen = {version = "0.75.0", path = "./ecmascript/codegen"}
swc_ecma_ext_transforms = {version = "0.32.0", path = "./ecmascript/ext-transforms"}
swc_ecma_loader = {version = "0.21.0", path = "./ecmascript/loader", features = ["lru", "node", "tsc"]}
swc_ecma_minifier = {version = "0.38.0", path = "./ecmascript/minifier"}
swc_ecma_minifier = {version = "0.39.0", path = "./ecmascript/minifier"}
swc_ecma_parser = {version = "0.73.0", path = "./ecmascript/parser"}
swc_ecma_preset_env = {version = "0.53.0", path = "./ecmascript/preset-env"}
swc_ecma_transforms = {version = "0.82.0", path = "./ecmascript/transforms", features = [
swc_ecma_preset_env = {version = "0.54.0", path = "./ecmascript/preset-env"}
swc_ecma_transforms = {version = "0.83.0", path = "./ecmascript/transforms", features = [
"compat",
"module",
"optimization",
@ -68,10 +68,10 @@ swc_ecma_transforms = {version = "0.82.0", path = "./ecmascript/transforms", fea
"react",
"typescript",
]}
swc_ecma_transforms_base = {version = "0.37.4", path = "./ecmascript/transforms/base"}
swc_ecma_transforms_base = {version = "0.38.0", path = "./ecmascript/transforms/base"}
swc_ecma_utils = {version = "0.47.0", path = "./ecmascript/utils"}
swc_ecma_visit = {version = "0.40.0", path = "./ecmascript/visit"}
swc_ecmascript = {version = "0.74.0", path = "./ecmascript"}
swc_ecmascript = {version = "0.75.0", path = "./ecmascript"}
swc_visit = {version = "0.2.3", path = "./visit"}
tracing = "0.1.28"

View File

@ -1,414 +0,0 @@
/** @prettier */
import { Observable } from '../../Observable';
import { Subscriber } from '../../Subscriber';
import { TeardownLogic, PartialObserver } from '../../types';
export interface AjaxRequest {
url?: string;
body?: any;
user?: string;
async?: boolean;
method?: string;
headers?: object;
timeout?: number;
password?: string;
hasContent?: boolean;
crossDomain?: boolean;
withCredentials?: boolean;
createXHR?: () => XMLHttpRequest;
progressSubscriber?: PartialObserver<ProgressEvent>;
responseType?: string;
}
function isFormData(body: any): body is FormData {
return typeof FormData !== 'undefined' && body instanceof FormData;
}
/**
* We need this JSDoc comment for affecting ESDoc.
* @extends {Ignored}
* @hide true
*/
export class AjaxObservable<T> extends Observable<T> {
private request: AjaxRequest;
constructor(urlOrRequest: string | AjaxRequest) {
super();
const request: AjaxRequest = {
async: true,
createXHR: () => new XMLHttpRequest(),
crossDomain: true,
withCredentials: false,
headers: {},
method: 'GET',
responseType: 'json',
timeout: 0,
};
if (typeof urlOrRequest === 'string') {
request.url = urlOrRequest;
} else {
for (const prop in urlOrRequest) {
if (urlOrRequest.hasOwnProperty(prop)) {
(request as any)[prop] = (urlOrRequest as any)[prop];
}
}
}
this.request = request;
}
/** @deprecated This is an internal implementation detail, do not use. */
_subscribe(subscriber: Subscriber<T>): TeardownLogic {
return new AjaxSubscriber(subscriber, this.request);
}
}
/**
* We need this JSDoc comment for affecting ESDoc.
* @ignore
* @extends {Ignored}
*/
export class AjaxSubscriber<T> extends Subscriber<Event> {
// @ts-ignore: Property has no initializer and is not definitely assigned
private xhr: XMLHttpRequest;
private done: boolean = false;
constructor(destination: Subscriber<T>, public request: AjaxRequest) {
super(destination);
const headers = (request.headers = request.headers || {});
// force CORS if requested
if (!request.crossDomain && !this.getHeader(headers, 'X-Requested-With')) {
(headers as any)['X-Requested-With'] = 'XMLHttpRequest';
}
// ensure content type is set
let contentTypeHeader = this.getHeader(headers, 'Content-Type');
if (!contentTypeHeader && typeof request.body !== 'undefined' && !isFormData(request.body)) {
(headers as any)['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
}
// properly serialize body
request.body = this.serializeBody(request.body, this.getHeader(request.headers, 'Content-Type'));
this.send();
}
next(e: Event): void {
this.done = true;
const destination = this.destination as Subscriber<any>;
let result: AjaxResponse;
try {
result = new AjaxResponse(e, this.xhr, this.request);
} catch (err) {
return destination.error(err);
}
destination.next(result);
}
private send(): void {
const {
request,
request: { user, method, url, async, password, headers, body },
} = this;
try {
const xhr = (this.xhr = request.createXHR!());
// set up the events before open XHR
// https://developer.mozilla.org/en/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest
// You need to add the event listeners before calling open() on the request.
// Otherwise the progress events will not fire.
this.setupEvents(xhr, request);
// open XHR
if (user) {
xhr.open(method!, url!, async!, user, password);
} else {
xhr.open(method!, url!, async!);
}
// timeout, responseType and withCredentials can be set once the XHR is open
if (async) {
xhr.timeout = request.timeout!;
xhr.responseType = request.responseType as any;
}
if ('withCredentials' in xhr) {
xhr.withCredentials = !!request.withCredentials;
}
// set headers
this.setHeaders(xhr, headers!);
// finally send the request
if (body) {
xhr.send(body);
} else {
xhr.send();
}
} catch (err) {
this.error(err);
}
}
private serializeBody(body: any, contentType?: string) {
if (!body || typeof body === 'string') {
return body;
} else if (isFormData(body)) {
return body;
}
if (contentType) {
const splitIndex = contentType.indexOf(';');
if (splitIndex !== -1) {
contentType = contentType.substring(0, splitIndex);
}
}
switch (contentType) {
case 'application/x-www-form-urlencoded':
return Object.keys(body)
.map((key) => `${encodeURIComponent(key)}=${encodeURIComponent(body[key])}`)
.join('&');
case 'application/json':
return JSON.stringify(body);
default:
return body;
}
}
private setHeaders(xhr: XMLHttpRequest, headers: Object) {
for (let key in headers) {
if (headers.hasOwnProperty(key)) {
xhr.setRequestHeader(key, (headers as any)[key]);
}
}
}
private getHeader(headers: {}, headerName: string): any {
for (let key in headers) {
if (key.toLowerCase() === headerName.toLowerCase()) {
return (headers as any)[key];
}
}
return undefined;
}
private setupEvents(xhr: XMLHttpRequest, request: AjaxRequest) {
const progressSubscriber = request.progressSubscriber;
xhr.ontimeout = (e: ProgressEvent) => {
progressSubscriber?.error?.(e);
let error;
try {
error = new AjaxTimeoutError(xhr, request); // TODO: Make betterer.
} catch (err) {
error = err;
}
this.error(error);
};
if (progressSubscriber) {
xhr.upload.onprogress = (e: ProgressEvent) => {
progressSubscriber.next?.(e);
};
}
xhr.onerror = (e: ProgressEvent) => {
progressSubscriber?.error?.(e);
this.error(new AjaxError('ajax error', xhr, request));
};
xhr.onload = (e: ProgressEvent) => {
// 4xx and 5xx should error (https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
if (xhr.status < 400) {
progressSubscriber?.complete?.();
this.next(e);
this.complete();
} else {
progressSubscriber?.error?.(e);
let error;
try {
error = new AjaxError('ajax error ' + xhr.status, xhr, request);
} catch (err) {
error = err;
}
this.error(error);
}
};
}
unsubscribe() {
const { done, xhr } = this;
if (!done && xhr && xhr.readyState !== 4 && typeof xhr.abort === 'function') {
xhr.abort();
}
super.unsubscribe();
}
}
/**
* A normalized AJAX response.
*
* @see {@link ajax}
*
* @class AjaxResponse
*/
export class AjaxResponse {
/** @type {number} The HTTP status code */
status: number;
/** @type {string|ArrayBuffer|Document|object|any} The response data */
response: any;
/** @type {string} The raw responseText */
// @ts-ignore: Property has no initializer and is not definitely assigned
responseText: string;
/** @type {string} The responseType (e.g. 'json', 'arraybuffer', or 'xml') */
responseType: string;
constructor(public originalEvent: Event, public xhr: XMLHttpRequest, public request: AjaxRequest) {
this.status = xhr.status;
this.responseType = xhr.responseType || request.responseType!;
this.response = getXHRResponse(xhr);
}
}
export type AjaxErrorNames = 'AjaxError' | 'AjaxTimeoutError';
/**
* A normalized AJAX error.
*
* @see {@link ajax}
*
* @class AjaxError
*/
export interface AjaxError extends Error {
/**
* The XHR instance associated with the error
*/
xhr: XMLHttpRequest;
/**
* The AjaxRequest associated with the error
*/
request: AjaxRequest;
/**
*The HTTP status code
*/
status: number;
/**
*The responseType (e.g. 'json', 'arraybuffer', or 'xml')
*/
responseType: XMLHttpRequestResponseType;
/**
* The response data
*/
response: any;
}
export interface AjaxErrorCtor {
/**
* Internal use only. Do not manually create instances of this type.
* @internal
*/
new (message: string, xhr: XMLHttpRequest, request: AjaxRequest): AjaxError;
}
const AjaxErrorImpl = (() => {
function AjaxErrorImpl(this: any, message: string, xhr: XMLHttpRequest, request: AjaxRequest): AjaxError {
Error.call(this);
this.message = message;
this.name = 'AjaxError';
this.xhr = xhr;
this.request = request;
this.status = xhr.status;
this.responseType = xhr.responseType;
let response: any;
try {
response = getXHRResponse(xhr);
} catch (err) {
response = xhr.responseText;
}
this.response = response;
return this;
}
AjaxErrorImpl.prototype = Object.create(Error.prototype);
return AjaxErrorImpl;
})();
/**
* Thrown when an error occurs during an AJAX request.
* This is only exported because it is useful for checking to see if an error
* is an `instanceof AjaxError`. DO NOT create new instances of `AjaxError` with
* the constructor.
*
* @class AjaxError
* @see ajax
*/
export const AjaxError: AjaxErrorCtor = AjaxErrorImpl as any;
function getXHRResponse(xhr: XMLHttpRequest) {
switch (xhr.responseType) {
case 'json': {
if ('response' in xhr) {
return xhr.response;
} else {
// IE
const ieXHR: any = xhr;
return JSON.parse(ieXHR.responseText);
}
}
case 'document':
return xhr.responseXML;
case 'text':
default: {
if ('response' in xhr) {
return xhr.response;
} else {
// IE
const ieXHR: any = xhr;
return ieXHR.responseText;
}
}
}
}
export interface AjaxTimeoutError extends AjaxError {}
export interface AjaxTimeoutErrorCtor {
/**
* Internal use only. Do not manually create instances of this type.
* @internal
*/
new (xhr: XMLHttpRequest, request: AjaxRequest): AjaxTimeoutError;
}
const AjaxTimeoutErrorImpl = (() => {
function AjaxTimeoutErrorImpl(this: any, xhr: XMLHttpRequest, request: AjaxRequest) {
AjaxError.call(this, 'ajax timeout', xhr, request);
this.name = 'AjaxTimeoutError';
return this;
}
AjaxTimeoutErrorImpl.prototype = Object.create(AjaxError.prototype);
return AjaxTimeoutErrorImpl;
})();
/**
* Thrown when an AJAX request timesout. Not to be confused with {@link TimeoutError}.
*
* This is exported only because it is useful for checking to see if errors are an
* `instanceof AjaxTimeoutError`. DO NOT use the constructor to create an instance of
* this type.
*
* @class AjaxTimeoutError
* @see ajax
*/
export const AjaxTimeoutError: AjaxTimeoutErrorCtor = AjaxTimeoutErrorImpl as any;

View File

@ -0,0 +1,543 @@
/**
* @prettier
*/
import { Operator } from './Operator';
import { SafeSubscriber, Subscriber } from './Subscriber';
import { isSubscription, Subscription } from './Subscription';
import { TeardownLogic, OperatorFunction, Subscribable, Observer } from './types';
import { observable as Symbol_observable } from './symbol/observable';
import { pipeFromArray } from './util/pipe';
import { config } from './config';
import { isFunction } from './util/isFunction';
/**
* A representation of any set of values over any amount of time. This is the most basic building block
* of RxJS.
*
* @class Observable<T>
*/
export class Observable<T> implements Subscribable<T> {
/**
* @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.
*/
source: Observable<any> | undefined;
/**
* @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.
*/
operator: Operator<any, T> | undefined;
/**
* @constructor
* @param {Function} subscribe the function that is called when the Observable is
* initially subscribed to. This function is given a Subscriber, to which new values
* can be `next`ed, or an `error` method can be called to raise an error, or
* `complete` can be called to notify of a successful completion.
*/
constructor(subscribe?: (this: Observable<T>, subscriber: Subscriber<T>) => TeardownLogic) {
if (subscribe) {
this._subscribe = subscribe;
}
}
// HACK: Since TypeScript inherits static properties too, we have to
// fight against TypeScript here so Subject can have a different static create signature
/**
* Creates a new Observable by calling the Observable constructor
* @owner Observable
* @method create
* @param {Function} subscribe? the subscriber function to be passed to the Observable constructor
* @return {Observable} a new observable
* @nocollapse
* @deprecated Use `new Observable()` instead. Will be removed in v8.
*/
static create: (...args: any[]) => any = <T>(subscribe?: (subscriber: Subscriber<T>) => TeardownLogic) => {
return new Observable<T>(subscribe);
};
/**
* Creates a new Observable, with this Observable instance as the source, and the passed
* operator defined as the new observable's operator.
* @method lift
* @param operator the operator defining the operation to take on the observable
* @return a new observable with the Operator applied
* @deprecated Internal implementation detail, do not use directly. Will be made internal in v8.
* If you have implemented an operator using `lift`, it is recommended that you create an
* operator by simply returning `new Observable()` directly. See "Creating new operators from
* scratch" section here: https://rxjs.dev/guide/operators
*/
lift<R>(operator?: Operator<T, R>): Observable<R> {
const observable = new Observable<R>();
observable.source = this;
observable.operator = operator;
return observable;
}
subscribe(observer?: Partial<Observer<T>>): Subscription;
subscribe(next: (value: T) => void): Subscription;
/** @deprecated Instead of passing separate callback arguments, use an observer argument. Signatures taking separate callback arguments will be removed in v8. Details: https://rxjs.dev/deprecations/subscribe-arguments */
subscribe(next?: ((value: T) => void) | null, error?: ((error: any) => void) | null, complete?: (() => void) | null): Subscription;
/**
* Invokes an execution of an Observable and registers Observer handlers for notifications it will emit.
*
* <span class="informal">Use it when you have all these Observables, but still nothing is happening.</span>
*
* `subscribe` is not a regular operator, but a method that calls Observable's internal `subscribe` function. It
* might be for example a function that you passed to Observable's constructor, but most of the time it is
* a library implementation, which defines what will be emitted by an Observable, and when it be will emitted. This means
* that calling `subscribe` is actually the moment when Observable starts its work, not when it is created, as it is often
* the thought.
*
* Apart from starting the execution of an Observable, this method allows you to listen for values
* that an Observable emits, as well as for when it completes or errors. You can achieve this in two
* of the following ways.
*
* The first way is creating an object that implements {@link Observer} interface. It should have methods
* defined by that interface, but note that it should be just a regular JavaScript object, which you can create
* yourself in any way you want (ES6 class, classic function constructor, object literal etc.). In particular, do
* not attempt to use any RxJS implementation details to create Observers - you don't need them. Remember also
* that your object does not have to implement all methods. If you find yourself creating a method that doesn't
* do anything, you can simply omit it. Note however, if the `error` method is not provided and an error happens,
* it will be thrown asynchronously. Errors thrown asynchronously cannot be caught using `try`/`catch`. Instead,
* use the {@link onUnhandledError} configuration option or use a runtime handler (like `window.onerror` or
* `process.on('error)`) to be notified of unhandled errors. Because of this, it's recommended that you provide
* an `error` method to avoid missing thrown errors.
*
* The second way is to give up on Observer object altogether and simply provide callback functions in place of its methods.
* This means you can provide three functions as arguments to `subscribe`, where the first function is equivalent
* of a `next` method, the second of an `error` method and the third of a `complete` method. Just as in case of an Observer,
* if you do not need to listen for something, you can omit a function by passing `undefined` or `null`,
* since `subscribe` recognizes these functions by where they were placed in function call. When it comes
* to the `error` function, as with an Observer, if not provided, errors emitted by an Observable will be thrown asynchronously.
*
* You can, however, subscribe with no parameters at all. This may be the case where you're not interested in terminal events
* and you also handled emissions internally by using operators (e.g. using `tap`).
*
* Whichever style of calling `subscribe` you use, in both cases it returns a Subscription object.
* This object allows you to call `unsubscribe` on it, which in turn will stop the work that an Observable does and will clean
* up all resources that an Observable used. Note that cancelling a subscription will not call `complete` callback
* provided to `subscribe` function, which is reserved for a regular completion signal that comes from an Observable.
*
* Remember that callbacks provided to `subscribe` are not guaranteed to be called asynchronously.
* It is an Observable itself that decides when these functions will be called. For example {@link of}
* by default emits all its values synchronously. Always check documentation for how given Observable
* will behave when subscribed and if its default behavior can be modified with a `scheduler`.
*
* ## Example
* ### Subscribe with an Observer
* ```ts
* import { of } from 'rxjs';
*
* const sumObserver = {
* sum: 0,
* next(value) {
* console.log('Adding: ' + value);
* this.sum = this.sum + value;
* },
* error() {
* // We actually could just remove this method,
* // since we do not really care about errors right now.
* },
* complete() {
* console.log('Sum equals: ' + this.sum);
* }
* };
*
* of(1, 2, 3) // Synchronously emits 1, 2, 3 and then completes.
* .subscribe(sumObserver);
*
* // Logs:
* // "Adding: 1"
* // "Adding: 2"
* // "Adding: 3"
* // "Sum equals: 6"
* ```
*
* ### Subscribe with functions
* ```ts
* import { of } from 'rxjs'
*
* let sum = 0;
*
* of(1, 2, 3).subscribe(
* value => {
* console.log('Adding: ' + value);
* sum = sum + value;
* },
* undefined,
* () => console.log('Sum equals: ' + sum)
* );
*
* // Logs:
* // "Adding: 1"
* // "Adding: 2"
* // "Adding: 3"
* // "Sum equals: 6"
* ```
*
* ### Cancel a subscription
* ```ts
* import { interval } from 'rxjs';
*
* const subscription = interval(1000).subscribe({
* next(num) {
* console.log(num)
* },
* complete() {
* // Will not be called, even when cancelling subscription.
* console.log('completed!');
* }
* });
*
* setTimeout(() => {
* subscription.unsubscribe();
* console.log('unsubscribed!');
* }, 2500);
*
* // Logs:
* // 0 after 1s
* // 1 after 2s
* // "unsubscribed!" after 2.5s
* ```
*
* @param {Observer|Function} observerOrNext (optional) Either an observer with methods to be called,
* or the first of three possible handlers, which is the handler for each value emitted from the subscribed
* Observable.
* @param {Function} error (optional) A handler for a terminal event resulting from an error. If no error handler is provided,
* the error will be thrown asynchronously as unhandled.
* @param {Function} complete (optional) A handler for a terminal event resulting from successful completion.
* @return {Subscription} a subscription reference to the registered handlers
* @method subscribe
*/
subscribe(
observerOrNext?: Partial<Observer<T>> | ((value: T) => void) | null,
error?: ((error: any) => void) | null,
complete?: (() => void) | null
): Subscription {
const subscriber = isSubscriber(observerOrNext) ? observerOrNext : new SafeSubscriber(observerOrNext, error, complete);
if (config.useDeprecatedSynchronousErrorHandling) {
this._deprecatedSyncErrorSubscribe(subscriber);
} else {
const { operator, source } = this;
subscriber.add(
operator
? // We're dealing with a subscription in the
// operator chain to one of our lifted operators.
operator.call(subscriber, source)
: source
? // If `source` has a value, but `operator` does not, something that
// had intimate knowledge of our API, like our `Subject`, must have
// set it. We're going to just call `_subscribe` directly.
this._subscribe(subscriber)
: // In all other cases, we're likely wrapping a user-provided initializer
// function, so we need to catch errors and handle them appropriately.
this._trySubscribe(subscriber)
);
}
return subscriber;
}
/**
* REMOVE THIS ENTIRE METHOD IN VERSION 8.
*/
private _deprecatedSyncErrorSubscribe(subscriber: Subscriber<unknown>) {
const localSubscriber: any = subscriber;
localSubscriber._syncErrorHack_isSubscribing = true;
const { operator } = this;
if (operator) {
// We don't need to try/catch on operators, as they
// are doing their own try/catching, and will
// properly decorate the subscriber with `__syncError`.
subscriber.add(operator.call(subscriber, this.source));
} else {
try {
subscriber.add(this._subscribe(subscriber));
} catch (err) {
localSubscriber.__syncError = err;
}
}
// In the case of the deprecated sync error handling,
// we need to crawl forward through our subscriber chain and
// look to see if there's any synchronously thrown errors.
// Does this suck for perf? Yes. So stop using the deprecated sync
// error handling already. We're removing this in v8.
let dest = localSubscriber;
while (dest) {
// Technically, someone could throw something falsy, like 0, or "",
// so we need to check to see if anything was thrown, and we know
// that by the mere existence of `__syncError`.
if ('__syncError' in dest) {
try {
throw dest.__syncError;
} finally {
subscriber.unsubscribe();
}
}
dest = dest.destination;
}
localSubscriber._syncErrorHack_isSubscribing = false;
}
/** @internal */
protected _trySubscribe(sink: Subscriber<T>): TeardownLogic {
try {
return this._subscribe(sink);
} catch (err) {
// We don't need to return anything in this case,
// because it's just going to try to `add()` to a subscription
// above.
sink.error(err);
}
}
/**
* Used as a NON-CANCELLABLE means of subscribing to an observable, for use with
* APIs that expect promises, like `async/await`. You cannot unsubscribe from this.
*
* **WARNING**: Only use this with observables you *know* will complete. If the source
* observable does not complete, you will end up with a promise that is hung up, and
* potentially all of the state of an async function hanging out in memory. To avoid
* this situation, look into adding something like {@link timeout}, {@link take},
* {@link takeWhile}, or {@link takeUntil} amongst others.
*
* ### Example:
*
* ```ts
* import { interval } from 'rxjs';
* import { take } from 'rxjs/operators';
*
* const source$ = interval(1000).pipe(take(4));
*
* async function getTotal() {
* let total = 0;
*
* await source$.forEach(value => {
* total += value;
* console.log('observable -> ', value);
* });
*
* return total;
* }
*
* getTotal().then(
* total => console.log('Total:', total)
* )
*
* // Expected:
* // "observable -> 0"
* // "observable -> 1"
* // "observable -> 2"
* // "observable -> 3"
* // "Total: 6"
* ```
* @param next a handler for each value emitted by the observable
* @return a promise that either resolves on observable completion or
* rejects with the handled error
*/
forEach(next: (value: T) => void): Promise<void>;
/**
* @param next a handler for each value emitted by the observable
* @param promiseCtor a constructor function used to instantiate the Promise
* @return a promise that either resolves on observable completion or
* rejects with the handled error
* @deprecated Passing a Promise constructor will no longer be available
* in upcoming versions of RxJS. This is because it adds weight to the library, for very
* little benefit. If you need this functionality, it is recommended that you either
* polyfill Promise, or you create an adapter to convert the returned native promise
* to whatever promise implementation you wanted. Will be removed in v8.
*/
forEach(next: (value: T) => void, promiseCtor: PromiseConstructorLike): Promise<void>;
forEach(next: (value: T) => void, promiseCtor?: PromiseConstructorLike): Promise<void> {
promiseCtor = getPromiseCtor(promiseCtor);
return new promiseCtor<void>((resolve, reject) => {
// Must be declared in a separate statement to avoid a ReferenceError when
// accessing subscription below in the closure due to Temporal Dead Zone.
let subscription: Subscription;
subscription = this.subscribe(
(value) => {
try {
next(value);
} catch (err) {
reject(err);
subscription?.unsubscribe();
}
},
reject,
resolve
);
}) as Promise<void>;
}
/** @internal */
protected _subscribe(subscriber: Subscriber<any>): TeardownLogic {
return this.source?.subscribe(subscriber);
}
/**
* An interop point defined by the es7-observable spec https://github.com/zenparsing/es-observable
* @method Symbol.observable
* @return {Observable} this instance of the observable
*/
[Symbol_observable]() {
return this;
}
/* tslint:disable:max-line-length */
pipe(): Observable<T>;
pipe<A>(op1: OperatorFunction<T, A>): Observable<A>;
pipe<A, B>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>): Observable<B>;
pipe<A, B, C>(op1: OperatorFunction<T, A>, op2: OperatorFunction<A, B>, op3: OperatorFunction<B, C>): Observable<C>;
pipe<A, B, C, D>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>
): Observable<D>;
pipe<A, B, C, D, E>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>
): Observable<E>;
pipe<A, B, C, D, E, F>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>,
op6: OperatorFunction<E, F>
): Observable<F>;
pipe<A, B, C, D, E, F, G>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>,
op6: OperatorFunction<E, F>,
op7: OperatorFunction<F, G>
): Observable<G>;
pipe<A, B, C, D, E, F, G, H>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>,
op6: OperatorFunction<E, F>,
op7: OperatorFunction<F, G>,
op8: OperatorFunction<G, H>
): Observable<H>;
pipe<A, B, C, D, E, F, G, H, I>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>,
op6: OperatorFunction<E, F>,
op7: OperatorFunction<F, G>,
op8: OperatorFunction<G, H>,
op9: OperatorFunction<H, I>
): Observable<I>;
pipe<A, B, C, D, E, F, G, H, I>(
op1: OperatorFunction<T, A>,
op2: OperatorFunction<A, B>,
op3: OperatorFunction<B, C>,
op4: OperatorFunction<C, D>,
op5: OperatorFunction<D, E>,
op6: OperatorFunction<E, F>,
op7: OperatorFunction<F, G>,
op8: OperatorFunction<G, H>,
op9: OperatorFunction<H, I>,
...operations: OperatorFunction<any, any>[]
): Observable<unknown>;
/* tslint:enable:max-line-length */
/**
* Used to stitch together functional operators into a chain.
* @method pipe
* @return {Observable} the Observable result of all of the operators having
* been called in the order they were passed in.
*
* ### Example
* ```ts
* import { interval } from 'rxjs';
* import { map, filter, scan } from 'rxjs/operators';
*
* interval(1000)
* .pipe(
* filter(x => x % 2 === 0),
* map(x => x + x),
* scan((acc, x) => acc + x)
* )
* .subscribe(x => console.log(x))
* ```
*/
pipe(...operations: OperatorFunction<any, any>[]): Observable<any> {
return operations.length ? pipeFromArray(operations)(this) : this;
}
/* tslint:disable:max-line-length */
/** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */
toPromise(): Promise<T | undefined>;
/** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */
toPromise(PromiseCtor: typeof Promise): Promise<T | undefined>;
/** @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise */
toPromise(PromiseCtor: PromiseConstructorLike): Promise<T | undefined>;
/* tslint:enable:max-line-length */
/**
* Subscribe to this Observable and get a Promise resolving on
* `complete` with the last emission (if any).
*
* **WARNING**: Only use this with observables you *know* will complete. If the source
* observable does not complete, you will end up with a promise that is hung up, and
* potentially all of the state of an async function hanging out in memory. To avoid
* this situation, look into adding something like {@link timeout}, {@link take},
* {@link takeWhile}, or {@link takeUntil} amongst others.
*
* @method toPromise
* @param [promiseCtor] a constructor function used to instantiate
* the Promise
* @return A Promise that resolves with the last value emit, or
* rejects on an error. If there were no emissions, Promise
* resolves with undefined.
* @deprecated Replaced with {@link firstValueFrom} and {@link lastValueFrom}. Will be removed in v8. Details: https://rxjs.dev/deprecations/to-promise
*/
toPromise(promiseCtor?: PromiseConstructorLike): Promise<T | undefined> {
promiseCtor = getPromiseCtor(promiseCtor);
return new promiseCtor((resolve, reject) => {
let value: T | undefined;
this.subscribe(
(x: T) => (value = x),
(err: any) => reject(err),
() => resolve(value)
);
}) as Promise<T | undefined>;
}
}
/**
* Decides between a passed promise constructor from consuming code,
* A default configured promise constructor, and the native promise
* constructor and returns it. If nothing can be found, it will throw
* an error.
* @param promiseCtor The optional promise constructor to passed by consuming code
*/
function getPromiseCtor(promiseCtor: PromiseConstructorLike | undefined) {
return promiseCtor ?? config.Promise ?? Promise;
}
function isObserver<T>(value: any): value is Observer<T> {
return value && isFunction(value.next) && isFunction(value.error) && isFunction(value.complete);
}
function isSubscriber<T>(value: any): value is Subscriber<T> {
return (value && value instanceof Subscriber) || (isObserver(value) && isSubscription(value));
}

View File

@ -17,7 +17,7 @@ use swc_ecma_transforms::{fixer, hygiene, pass::noop, resolver, typescript};
use swc_ecma_visit::FoldWith;
use test::Bencher;
static SOURCE: &str = include_str!("assets/AjaxObservable.ts");
static SOURCE: &str = include_str!("assets/Observable.ts");
fn mk() -> swc::Compiler {
let cm = Arc::new(SourceMap::new(FilePathMapping::empty()));
@ -29,7 +29,7 @@ fn mk() -> swc::Compiler {
fn parse(c: &swc::Compiler) -> Program {
let fm = c.cm.new_source_file(
FileName::Real("rxjs/src/internal/observable/dom/AjaxObservable.ts".into()),
FileName::Real("rxjs/src/internal/Observable.ts".into()),
SOURCE.to_string(),
);
let handler = Handler::with_emitter_writer(Box::new(io::stderr()), Some(c.cm.clone()));
@ -108,7 +108,7 @@ fn config_for_file(b: &mut Bencher) {
is_module: true,
..Default::default()
},
&FileName::Real("rxjs/src/internal/observable/dom/AjaxObservable.ts".into()),
&FileName::Real("rxjs/src/internal/Observable.ts".into()),
noop(),
))
});
@ -167,7 +167,7 @@ fn bench_full(b: &mut Bencher, opts: &Options) {
let handler = Handler::with_emitter_writer(Box::new(stderr()), Some(c.cm.clone()));
let fm = c.cm.new_source_file(
FileName::Real("rxjs/src/internal/observable/dom/AjaxObservable.ts".into()),
FileName::Real("rxjs/src/internal/Observable.ts".into()),
SOURCE.to_string(),
);
let _ = c.process_js_file(fm, &handler, opts).unwrap();
@ -241,9 +241,7 @@ macro_rules! tr_only {
is_module: true,
..Default::default()
},
&FileName::Real(
"rxjs/src/internal/observable/dom/AjaxObservable.ts".into(),
),
&FileName::Real("rxjs/src/internal/Observable.ts".into()),
noop(),
)
.unwrap()

View File

@ -9,7 +9,7 @@ include = ["Cargo.toml", "build.rs", "src/**/*.rs", "src/**/*.js"]
license = "Apache-2.0/MIT"
name = "swc_bundler"
repository = "https://github.com/swc-project/swc.git"
version = "0.69.0"
version = "0.70.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
@ -39,11 +39,11 @@ retain_mut = "0.1.2"
swc_atoms = {version = "0.2.4", path = "../atoms"}
swc_common = {version = "0.13.0", path = "../common"}
swc_ecma_ast = {version = "0.54.0", path = "../ecmascript/ast"}
swc_ecma_codegen = {version = "0.74.0", path = "../ecmascript/codegen"}
swc_ecma_codegen = {version = "0.75.0", path = "../ecmascript/codegen"}
swc_ecma_loader = {version = "0.21.0", path = "../ecmascript/loader"}
swc_ecma_parser = {version = "0.73.0", path = "../ecmascript/parser"}
swc_ecma_transforms_base = {version = "0.37.0", path = "../ecmascript/transforms/base"}
swc_ecma_transforms_optimization = {version = "0.52.0", path = "../ecmascript/transforms/optimization"}
swc_ecma_transforms_base = {version = "0.38.0", path = "../ecmascript/transforms/base"}
swc_ecma_transforms_optimization = {version = "0.53.0", path = "../ecmascript/transforms/optimization"}
swc_ecma_utils = {version = "0.47.0", path = "../ecmascript/utils"}
swc_ecma_visit = {version = "0.40.0", path = "../ecmascript/visit"}
tracing = "0.1.28"
@ -54,8 +54,9 @@ ntest = "0.7.2"
path-clean = "=0.1.0"
reqwest = {version = "0.11.4", features = ["blocking"]}
sha-1 = "0.9"
swc_ecma_transforms_react = {version = "0.48.0", path = "../ecmascript/transforms/react"}
swc_ecma_transforms_typescript = {version = "0.49.0", path = "../ecmascript/transforms/typescript"}
swc_ecma_loader = {version = "0.21.0", path = "../ecmascript/loader", features = ["node", "lru"]}
swc_ecma_transforms_react = {version = "0.49.0", path = "../ecmascript/transforms/react"}
swc_ecma_transforms_typescript = {version = "0.50.0", path = "../ecmascript/transforms/typescript"}
swc_node_base = {version = "0.4.0", path = "../node/base"}
tempfile = "3.1.0"
testing = {version = "0.14.0", path = "../testing"}

View File

@ -18,6 +18,7 @@ use swc_common::{
};
use swc_ecma_ast::*;
use swc_ecma_codegen::{text_writer::JsWriter, Emitter};
use swc_ecma_loader::resolvers::{lru::CachingResolver, node::NodeModulesResolver};
use swc_ecma_parser::{lexer::Lexer, EsConfig, Parser, StringInput, Syntax};
fn print_bundles(cm: Lrc<SourceMap>, modules: Vec<Bundle>) {
@ -32,7 +33,7 @@ fn print_bundles(cm: Lrc<SourceMap>, modules: Vec<Bundle>) {
},
cm: cm.clone(),
comments: None,
wr: Box::new(JsWriter::new(cm.clone(), "\n", &mut buf, None)),
wr: JsWriter::new(cm.clone(), "\n", &mut buf, None),
};
emitter.emit_module(&bundled.module).unwrap();
@ -41,18 +42,26 @@ fn print_bundles(cm: Lrc<SourceMap>, modules: Vec<Bundle>) {
String::from_utf8_lossy(&buf).to_string()
};
#[cfg(feature = "concurrent")]
rayon::spawn(move || drop(bundled));
fs::write("output.js", &code).unwrap();
}
}
fn do_test(_entry: &Path, entries: HashMap<String, FileName>, inline: bool) {
testing::run_test2(false, |cm, _| {
let globals = Globals::default();
let bundler = Bundler::new(
&globals,
let start = Instant::now();
let globals = Box::leak(Box::new(Globals::default()));
let mut bundler = Bundler::new(
globals,
cm.clone(),
Loader { cm: cm.clone() },
NodeResolver,
CachingResolver::new(
4096,
NodeModulesResolver::new(TargetEnv::Node, Default::default()),
),
swc_bundler::Config {
require: true,
disable_inliner: !inline,
@ -67,9 +76,22 @@ fn do_test(_entry: &Path, entries: HashMap<String, FileName>, inline: bool) {
.map_err(|err| println!("{:?}", err))?;
println!("Bundled as {} modules", modules.len());
#[cfg(feature = "concurrent")]
rayon::spawn(move || {
drop(bundler);
});
{
let dur = start.elapsed();
println!("Bundler.bundle() took {:?}", dur);
}
let error = false;
print_bundles(cm.clone(), modules);
{
let cm = cm.clone();
print_bundles(cm, modules);
}
if error {
return Err(());

View File

@ -13,7 +13,7 @@ fn main() {
let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
// This example does not use core modules.
let external_modules = vec![];
let bundler = Bundler::new(
let mut bundler = Bundler::new(
&globals,
cm.clone(),
PathLoader { cm: cm.clone() },

View File

@ -1,7 +1,7 @@
use self::scope::Scope;
use crate::{Hook, Load, ModuleId, Resolve};
use anyhow::{Context, Error};
use std::collections::HashMap;
use std::{collections::HashMap, mem::take};
use swc_atoms::JsWord;
use swc_common::{
collections::AHashMap, sync::Lrc, FileName, Globals, Mark, SourceMap, SyntaxContext, GLOBALS,
@ -138,7 +138,7 @@ where
/// Note: This method will panic if entries references each other in
/// circular manner. However, it applies only to the provided `entries`, and
/// dependencies with circular reference is ok.
pub fn bundle(&self, entries: HashMap<String, FileName>) -> Result<Vec<Bundle>, Error> {
pub fn bundle(&mut self, entries: HashMap<String, FileName>) -> Result<Vec<Bundle>, Error> {
let results = entries
.into_iter()
.map(|(name, path)| -> Result<_, Error> {
@ -182,6 +182,13 @@ where
let bundles = self.chunk(local)?;
let bundles = self.finalize(bundles)?;
#[cfg(feature = "concurrent")]
{
let scope = take(&mut self.scope);
rayon::spawn(move || drop(scope))
}
Ok(bundles)
}

View File

@ -114,4 +114,9 @@ impl WriteJs for &mut Hasher {
self.w(s);
Ok(())
}
#[inline]
fn care_about_srcmap(&self) -> bool {
false
}
}

View File

@ -1020,7 +1020,7 @@ fn run(url: &str, exports: &[&str]) {
fn bundle(url: &str) -> String {
let result = testing::run_test2(false, |cm, _handler| {
GLOBALS.with(|globals| {
let bundler = Bundler::new(
let mut bundler = Bundler::new(
globals,
cm.clone(),
Loader { cm: cm.clone() },

View File

@ -25,7 +25,7 @@ mod common;
fn do_test(entry: &Path, entries: HashMap<String, FileName>, inline: bool) {
testing::run_test2(false, |cm, _| {
let globals = Globals::default();
let bundler = Bundler::new(
let mut bundler = Bundler::new(
&globals,
cm.clone(),
Loader { cm: cm.clone() },

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecmascript"
repository = "https://github.com/swc-project/swc.git"
version = "0.74.0"
version = "0.75.0"
[package.metadata.docs.rs]
all-features = true
@ -33,12 +33,12 @@ typescript = ["typescript-parser", "swc_ecma_transforms/typescript"]
[dependencies]
swc_ecma_ast = {version = "0.54.0", path = "./ast"}
swc_ecma_codegen = {version = "0.74.0", path = "./codegen", optional = true}
swc_ecma_codegen = {version = "0.75.0", path = "./codegen", optional = true}
swc_ecma_dep_graph = {version = "0.42.0", path = "./dep-graph", optional = true}
swc_ecma_minifier = {version = "0.38.0", path = "./minifier", optional = true}
swc_ecma_minifier = {version = "0.39.0", path = "./minifier", optional = true}
swc_ecma_parser = {version = "0.73.0", path = "./parser", optional = true, default-features = false}
swc_ecma_preset_env = {version = "0.53.0", path = "./preset-env", optional = true}
swc_ecma_transforms = {version = "0.82.0", path = "./transforms", optional = true}
swc_ecma_preset_env = {version = "0.54.0", path = "./preset-env", optional = true}
swc_ecma_transforms = {version = "0.83.0", path = "./transforms", optional = true}
swc_ecma_utils = {version = "0.47.0", path = "./utils", optional = true}
swc_ecma_visit = {version = "0.40.0", path = "./visit", optional = true}

1
ecmascript/codegen/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/output.js

View File

@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"]
license = "Apache-2.0/MIT"
name = "swc_ecma_codegen"
repository = "https://github.com/swc-project/swc.git"
version = "0.74.4"
version = "0.75.0"
[dependencies]
bitflags = "1"
@ -20,6 +20,7 @@ swc_common = {version = "0.13.0", path = "../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../ast"}
swc_ecma_codegen_macros = {version = "0.6.0", path = "./macros"}
swc_ecma_parser = {version = "0.73.0", path = "../parser"}
tracing = "0.1"
[dev-dependencies]
swc_common = {version = "0.13.0", path = "../../common", features = ["sourcemap"]}

View File

@ -0,0 +1,61 @@
/// Use memory allocator
extern crate swc_node_base;
use std::{env, fs, path::Path, time::Instant};
use swc_common::input::SourceFileInput;
use swc_ecma_ast::*;
use swc_ecma_codegen::{text_writer::JsWriter, Emitter};
use swc_ecma_parser::{lexer::Lexer, Parser, Syntax};
fn do_test(entry: &Path) {
testing::run_test2(false, |cm, _| {
let fm = cm.load_file(entry).unwrap();
let lexer = Lexer::new(
Syntax::Typescript(Default::default()),
EsVersion::latest(),
SourceFileInput::from(&*fm),
None,
);
let mut parser = Parser::new_from(lexer);
let m = parser
.parse_module()
.expect("failed to parse input as a module");
for _ in 0..100 {
let code = {
let mut buf = vec![];
{
let mut emitter = Emitter {
cfg: swc_ecma_codegen::Config {
..Default::default()
},
cm: cm.clone(),
comments: None,
wr: JsWriter::new(cm.clone(), "\n", &mut buf, None),
};
emitter.emit_module(&m).unwrap();
}
String::from_utf8_lossy(&buf).to_string()
};
fs::write("output.js", &code).unwrap();
}
Ok(())
})
.expect("failed to process a module");
}
/// Usage: ./scripts/instruements path/to/input/file
fn main() {
let main_file = env::args().nth(1).unwrap();
let start = Instant::now();
do_test(Path::new(&main_file));
let dur = start.elapsed();
println!("Took {:?}", dur);
}

View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -eu
cargo instruments --release -t time --example gen --features tracing/release_max_level_off -- $@

View File

@ -59,15 +59,15 @@ where
}
pub(super) fn emit_leading_comments(&mut self, mut pos: BytePos, is_hi: bool) -> Result {
if is_hi {
pos = pos - BytePos(1)
}
let comments = match self.comments {
Some(ref comments) => comments,
None => return Ok(()),
};
if is_hi {
pos = pos - BytePos(1)
}
write_comments!(self, false, comments.take_leading(pos))
}

View File

@ -10,11 +10,9 @@ use self::{
use crate::util::EndsWithAlphaNum;
use memchr::memmem::Finder;
use once_cell::sync::Lazy;
use std::{borrow::Cow, fmt::Write, io, sync::Arc};
use std::{borrow::Cow, fmt::Write, io};
use swc_atoms::JsWord;
use swc_common::{
comments::Comments, sync::Lrc, BytePos, SourceMap, Span, Spanned, SyntaxContext, DUMMY_SP,
};
use swc_common::{comments::Comments, sync::Lrc, BytePos, SourceMap, Span, Spanned, DUMMY_SP};
use swc_ecma_ast::*;
use swc_ecma_codegen_macros::emitter;
use swc_ecma_parser::JscTarget;
@ -612,7 +610,9 @@ where
Expr::Invalid(ref n) => emit!(n),
}
self.emit_trailing_comments_of_pos(node.span().hi, true, true)?;
if self.comments.is_some() {
self.emit_trailing_comments_of_pos(node.span().hi, true, true)?;
}
}
#[emitter]
@ -792,7 +792,9 @@ where
#[emitter]
fn emit_meta_prop_expr(&mut self, node: &MetaPropExpr) -> Result {
self.emit_leading_comments_of_span(node.span(), false)?;
if self.comments.is_some() {
self.emit_leading_comments_of_span(node.span(), false)?;
}
emit!(node.meta);
punct!(".");
@ -1508,7 +1510,9 @@ where
#[emitter]
fn emit_expr_or_spread(&mut self, node: &ExprOrSpread) -> Result {
self.emit_leading_comments_of_span(node.span(), false)?;
if self.comments.is_some() {
self.emit_leading_comments_of_span(node.span(), false)?;
}
if node.spread.is_some() {
punct!("...");
@ -1857,9 +1861,11 @@ where
// -> this comment isn't considered to be trailing comment of parameter "a" due
// to newline ,
if format.contains(ListFormat::DelimitersMask)
&& previous_sibling.span().hi() != parent_node.hi()
&& previous_sibling.hi != parent_node.hi()
{
self.emit_leading_comments(previous_sibling.span().hi(), true)?;
if self.comments.is_some() {
self.emit_leading_comments(previous_sibling.span().hi(), true)?;
}
}
self.write_delim(format)?;
@ -1894,8 +1900,10 @@ where
// Emit this child.
if should_emit_intervening_comments {
let comment_range = child.comment_range();
self.emit_trailing_comments_of_pos(comment_range.hi(), false, true)?;
if self.comments.is_some() {
let comment_range = child.comment_range();
self.emit_trailing_comments_of_pos(comment_range.hi(), false, true)?;
}
} else {
should_emit_intervening_comments = may_emit_intervening_comments;
}
@ -1954,7 +1962,9 @@ where
&& previous_sibling.span().hi() != parent_node.hi()
&& emit_trailing_comments
{
self.emit_leading_comments(previous_sibling.span().hi(), true)?;
if self.comments.is_some() {
self.emit_leading_comments(previous_sibling.span().hi(), true)?;
}
}
}
}
@ -2023,7 +2033,9 @@ where
Pat::Invalid(n) => emit!(n),
}
self.emit_trailing_comments_of_pos(node.span().hi, true, true)?;
if self.comments.is_some() {
self.emit_trailing_comments_of_pos(node.span().hi, true, true)?;
}
}
#[emitter]
@ -2050,7 +2062,9 @@ where
#[emitter]
fn emit_spread_element(&mut self, node: &SpreadElement) -> Result {
self.emit_leading_comments_of_span(node.span(), false)?;
if self.comments.is_some() {
self.emit_leading_comments_of_span(node.span(), false)?;
}
punct!("...");
emit!(node.expr)
@ -2216,7 +2230,9 @@ where
Stmt::ForOf(ref e) => emit!(e),
Stmt::Decl(ref e) => emit!(e),
}
self.emit_trailing_comments_of_pos(node.span().hi(), true, true)?;
if self.comments.is_some() {
self.emit_trailing_comments_of_pos(node.span().hi(), true, true)?;
}
if !self.cfg.minify {
self.wr.write_line()?;
@ -2777,25 +2793,6 @@ where
}
}
#[allow(dead_code)]
fn get_text_of_node<T: Spanned>(
cm: &Arc<SourceMap>,
node: &T,
_include_travia: bool,
) -> Option<String> {
let span = node.span();
if span.is_dummy() || span.ctxt() != SyntaxContext::empty() {
// This node is transformed so we shoukld not use original source code.
return None;
}
let s = cm.span_to_snippet(span).unwrap();
if s == "" {
return None;
}
Some(s)
}
/// In some cases, we need to emit a space between the operator and the operand.
/// One obvious case is when the operator is an identifier, like delete or
/// typeof. We also need to do this for plus and minus expressions in certain

View File

@ -45,66 +45,96 @@ pub trait WriteJs {
fn write_symbol(&mut self, span: Span, s: &str) -> Result;
fn write_punct(&mut self, span: Option<Span>, s: &'static str) -> Result;
fn care_about_srcmap(&self) -> bool;
}
impl<W> WriteJs for Box<W>
where
W: ?Sized + WriteJs,
{
#[inline]
fn target(&self) -> JscTarget {
(**self).target()
}
#[inline]
fn increase_indent(&mut self) -> Result {
(**self).increase_indent()
}
#[inline]
fn decrease_indent(&mut self) -> Result {
(**self).decrease_indent()
}
#[inline]
fn write_semi(&mut self, span: Option<Span>) -> Result {
(**self).write_semi(span)
}
#[inline]
fn write_space(&mut self) -> Result {
(**self).write_space()
}
#[inline]
fn write_keyword(&mut self, span: Option<Span>, s: &'static str) -> Result {
(**self).write_keyword(span, s)
}
#[inline]
fn write_operator(&mut self, span: Option<Span>, s: &str) -> Result {
(**self).write_operator(span, s)
}
#[inline]
fn write_param(&mut self, s: &str) -> Result {
(**self).write_param(s)
}
#[inline]
fn write_property(&mut self, s: &str) -> Result {
(**self).write_property(s)
}
#[inline]
fn write_line(&mut self) -> Result {
(**self).write_line()
}
#[inline]
fn write_lit(&mut self, span: Span, s: &str) -> Result {
(**self).write_lit(span, s)
}
fn write_str_lit(&mut self, span: Span, s: &str) -> Result {
(**self).write_str_lit(span, s)
}
fn write_str(&mut self, s: &str) -> Result {
(**self).write_str(s)
}
fn write_symbol(&mut self, span: Span, s: &str) -> Result {
(**self).write_symbol(span, s)
}
#[inline]
fn write_comment(&mut self, span: Span, s: &str) -> Result {
(**self).write_comment(span, s)
}
#[inline]
fn write_str_lit(&mut self, span: Span, s: &str) -> Result {
(**self).write_str_lit(span, s)
}
#[inline]
fn write_str(&mut self, s: &str) -> Result {
(**self).write_str(s)
}
#[inline]
fn write_symbol(&mut self, span: Span, s: &str) -> Result {
(**self).write_symbol(span, s)
}
#[inline]
fn write_punct(&mut self, span: Option<Span>, s: &'static str) -> Result {
(**self).write_punct(span, s)
}
fn target(&self) -> JscTarget {
(**self).target()
#[inline]
fn care_about_srcmap(&self) -> bool {
(**self).care_about_srcmap()
}
}

View File

@ -10,8 +10,6 @@ use swc_ecma_parser::JscTarget;
///
/// https://github.com/Microsoft/TypeScript/blob/45eaf42006/src/compiler/utilities.ts#L2548
pub struct JsWriter<'a, W: Write> {
/// We may use this in future...
_cm: Lrc<SourceMap>,
indent: usize,
line_start: bool,
line_count: usize,
@ -19,7 +17,6 @@ pub struct JsWriter<'a, W: Write> {
new_line: &'a str,
srcmap: Option<&'a mut Vec<(BytePos, LineCol)>>,
wr: W,
written_bytes: usize,
target: JscTarget,
}
@ -34,14 +31,13 @@ impl<'a, W: Write> JsWriter<'a, W> {
}
pub fn with_target(
cm: Lrc<SourceMap>,
_: Lrc<SourceMap>,
new_line: &'a str,
wr: W,
srcmap: Option<&'a mut Vec<(BytePos, LineCol)>>,
target: JscTarget,
) -> Self {
JsWriter {
_cm: cm,
indent: Default::default(),
line_start: true,
line_count: 0,
@ -49,7 +45,6 @@ impl<'a, W: Write> JsWriter<'a, W> {
new_line,
srcmap,
wr,
written_bytes: 0,
target,
}
}
@ -67,7 +62,6 @@ impl<'a, W: Write> JsWriter<'a, W> {
fn raw_write(&mut self, data: &[u8]) -> io::Result<usize> {
let written = self.wr.write(data)?;
self.written_bytes += written;
self.line_pos += written;
Ok(written)
}
@ -113,19 +107,23 @@ impl<'a, W: Write> JsWriter<'a, W> {
}
impl<'a, W: Write> WriteJs for JsWriter<'a, W> {
fn target(&self) -> JscTarget {
self.target
}
fn increase_indent(&mut self) -> Result {
self.indent += 1;
Ok(())
}
fn decrease_indent(&mut self) -> Result {
self.indent -= 1;
Ok(())
}
fn write_semi(&mut self, span: Option<Span>) -> Result {
self.write(span, ";")?;
Ok(())
}
fn write_space(&mut self) -> Result {
self.write(None, " ")?;
Ok(())
@ -209,8 +207,8 @@ impl<'a, W: Write> WriteJs for JsWriter<'a, W> {
Ok(())
}
fn target(&self) -> JscTarget {
self.target
fn care_about_srcmap(&self) -> bool {
self.srcmap.is_some()
}
}

View File

@ -75,6 +75,11 @@ impl<W: WriteJs> WriteJs for OmitTrailingSemi<W> {
fn target(&self) -> swc_ecma_ast::EsVersion {
self.inner.target()
}
#[inline]
fn care_about_srcmap(&self) -> bool {
self.inner.care_about_srcmap()
}
}
impl<W: WriteJs> OmitTrailingSemi<W> {

View File

@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "src/lists/*.json"]
license = "Apache-2.0/MIT"
name = "swc_ecma_minifier"
repository = "https://github.com/swc-project/swc.git"
version = "0.38.1"
version = "0.39.0"
[features]
debug = ["backtrace"]
@ -26,10 +26,10 @@ serde_regex = "1.1.0"
swc_atoms = {version = "0.2", path = "../../atoms"}
swc_common = {version = "0.13.0", path = "../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../ast"}
swc_ecma_codegen = {version = "0.74.0", path = "../codegen"}
swc_ecma_codegen = {version = "0.75.0", path = "../codegen"}
swc_ecma_parser = {version = "0.73.0", path = "../parser"}
swc_ecma_transforms = {version = "0.82.0", path = "../transforms/", features = ["optimization"]}
swc_ecma_transforms_base = {version = "0.37.0", path = "../transforms/base"}
swc_ecma_transforms = {version = "0.83.0", path = "../transforms/", features = ["optimization"]}
swc_ecma_transforms_base = {version = "0.38.0", path = "../transforms/base"}
swc_ecma_utils = {version = "0.47.0", path = "../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../visit"}
tracing = "0.1.28"

View File

@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs", "examples/**/*.rs"]
license = "Apache-2.0/MIT"
name = "swc_ecma_parser"
repository = "https://github.com/swc-project/swc.git"
version = "0.73.12"
version = "0.73.13"
[package.metadata.docs.rs]
all-features = true
@ -30,6 +30,7 @@ swc_common = {version = "0.13.0", path = "../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../ast"}
swc_ecma_visit = {version = "0.40.0", path = "../visit"}
tracing = "0.1.28"
typed-arena = "2.0.1"
unicode-xid = "0.2"
[dev-dependencies]

View File

@ -2,6 +2,7 @@ use super::{pat::PatType, *};
use crate::error::SyntaxError;
use swc_atoms::js_word;
use swc_common::Spanned;
use typed_arena::Arena;
mod module_item;
@ -20,7 +21,7 @@ impl<'a, I: Tokens> Parser<I> {
let old_ctx = self.ctx();
let mut stmts = Vec::with_capacity(16);
let stmts = Arena::new();
while {
let c = cur!(self, false).ok();
c != end
@ -45,7 +46,7 @@ impl<'a, I: Tokens> Parser<I> {
}
}
stmts.push(stmt);
stmts.alloc(stmt);
}
if end.is_some() {
@ -54,7 +55,7 @@ impl<'a, I: Tokens> Parser<I> {
self.set_ctx(old_ctx);
Ok(stmts)
Ok(stmts.into_vec())
}
pub fn parse_stmt(&mut self, top_level: bool) -> PResult<Stmt> {
@ -1136,6 +1137,15 @@ pub(super) trait IsDirective {
}
}
impl<T> IsDirective for Box<T>
where
T: IsDirective,
{
fn as_ref(&self) -> Option<&Stmt> {
T::as_ref(&**self)
}
}
impl IsDirective for Stmt {
fn as_ref(&self) -> Option<&Stmt> {
Some(self)
@ -1150,6 +1160,20 @@ pub(super) trait StmtLikeParser<'a, Type: IsDirective> {
) -> PResult<Type>;
}
impl<'a, I: Tokens, T> StmtLikeParser<'a, Box<T>> for Parser<I>
where
T: IsDirective,
Self: StmtLikeParser<'a, T>,
{
fn handle_import_export(
&mut self,
top_level: bool,
decorators: Vec<Decorator>,
) -> PResult<Box<T>> {
<Self as StmtLikeParser<T>>::handle_import_export(self, top_level, decorators).map(Box::new)
}
}
impl<'a, I: Tokens> StmtLikeParser<'a, Stmt> for Parser<I> {
fn handle_import_export(&mut self, top_level: bool, _: Vec<Decorator>) -> PResult<Stmt> {
let start = cur_pos!(self);

View File

@ -5,7 +5,7 @@ documentation = "https://rustdoc.swc.rs/swc_ecma_preset_env/"
edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_preset_env"
version = "0.53.0"
version = "0.54.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -22,13 +22,13 @@ string_enum = {version = "0.3.1", path = "../../macros/string_enum"}
swc_atoms = {version = "0.2", path = "../../atoms"}
swc_common = {version = "0.13.0", path = "../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../ast"}
swc_ecma_transforms = {version = "0.82.0", path = "../transforms", features = ["compat", "proposal"]}
swc_ecma_transforms = {version = "0.83.0", path = "../transforms", features = ["compat", "proposal"]}
swc_ecma_utils = {version = "0.47.0", path = "../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../visit"}
walkdir = "2"
[dev-dependencies]
pretty_assertions = "0.6"
swc_ecma_codegen = {version = "0.74.0", path = "../codegen"}
swc_ecma_codegen = {version = "0.75.0", path = "../codegen"}
swc_ecma_parser = {version = "0.73.0", path = "../parser"}
testing = {version = "0.14.0", path = "../../testing"}

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms"
repository = "https://github.com/swc-project/swc.git"
version = "0.82.0"
version = "0.83.0"
[package.metadata.docs.rs]
all-features = true
@ -26,13 +26,13 @@ swc_atoms = {version = "0.2.0", path = "../../atoms"}
swc_common = {version = "0.13.0", path = "../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../ast"}
swc_ecma_parser = {version = "0.73.0", path = "../parser"}
swc_ecma_transforms_base = {version = "0.37.0", path = "./base"}
swc_ecma_transforms_compat = {version = "0.42.0", path = "./compat", optional = true}
swc_ecma_transforms_module = {version = "0.46.0", path = "./module", optional = true}
swc_ecma_transforms_optimization = {version = "0.52.0", path = "./optimization", optional = true}
swc_ecma_transforms_proposal = {version = "0.46.0", path = "./proposal", optional = true}
swc_ecma_transforms_react = {version = "0.48.0", path = "./react", optional = true}
swc_ecma_transforms_typescript = {version = "0.49.0", path = "./typescript", optional = true}
swc_ecma_transforms_base = {version = "0.38.0", path = "./base"}
swc_ecma_transforms_compat = {version = "0.43.0", path = "./compat", optional = true}
swc_ecma_transforms_module = {version = "0.47.0", path = "./module", optional = true}
swc_ecma_transforms_optimization = {version = "0.53.0", path = "./optimization", optional = true}
swc_ecma_transforms_proposal = {version = "0.47.0", path = "./proposal", optional = true}
swc_ecma_transforms_react = {version = "0.49.0", path = "./react", optional = true}
swc_ecma_transforms_typescript = {version = "0.50.0", path = "./typescript", optional = true}
swc_ecma_utils = {version = "0.47.0", path = "../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../visit"}
unicode-xid = "0.2"
@ -40,8 +40,8 @@ unicode-xid = "0.2"
[dev-dependencies]
pretty_assertions = "0.6"
sourcemap = "6"
swc_ecma_codegen = {version = "0.74.0", path = "../codegen"}
swc_ecma_transforms_testing = {version = "0.38.0", path = "./testing"}
swc_ecma_codegen = {version = "0.75.0", path = "../codegen"}
swc_ecma_transforms_testing = {version = "0.39.0", path = "./testing"}
tempfile = "3"
testing = {version = "0.14.0", path = "../../testing"}
walkdir = "2"

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_base"
repository = "https://github.com/swc-project/swc.git"
version = "0.37.5"
version = "0.38.0"
[dependencies]
once_cell = "1.5.2"
@ -21,5 +21,5 @@ swc_ecma_utils = {version = "0.47.0", path = "../../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../../visit"}
[dev-dependencies]
swc_ecma_codegen = {version = "0.74.0", path = "../../codegen"}
swc_ecma_codegen = {version = "0.75.0", path = "../../codegen"}
testing = {version = "0.14.0", path = "../../../testing"}

View File

@ -6,12 +6,12 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_classes"
repository = "https://github.com/swc-project/swc.git"
version = "0.23.0"
version = "0.24.0"
[dependencies]
swc_atoms = {version = "0.2.6", path = "../../../atoms"}
swc_common = {version = "0.13.0", path = "../../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../../ast"}
swc_ecma_transforms_base = {version = "0.37.0", path = "../base"}
swc_ecma_transforms_base = {version = "0.38.0", path = "../base"}
swc_ecma_utils = {version = "0.47.0", path = "../../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../../visit"}

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_compat"
repository = "https://github.com/swc-project/swc.git"
version = "0.42.0"
version = "0.43.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@ -21,13 +21,13 @@ smallvec = "1.6.0"
swc_atoms = {version = "0.2.5", path = "../../../atoms"}
swc_common = {version = "0.13.0", path = "../../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../../ast"}
swc_ecma_transforms_base = {version = "0.37.0", path = "../base"}
swc_ecma_transforms_classes = {version = "0.23.0", path = "../classes"}
swc_ecma_transforms_base = {version = "0.38.0", path = "../base"}
swc_ecma_transforms_classes = {version = "0.24.0", path = "../classes"}
swc_ecma_transforms_macros = {version = "0.2.1", path = "../macros"}
swc_ecma_utils = {version = "0.47.0", path = "../../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../../visit"}
[dev-dependencies]
swc_ecma_parser = {version = "0.73.0", path = "../../parser"}
swc_ecma_transforms_testing = {version = "0.38.0", path = "../testing"}
swc_ecma_transforms_testing = {version = "0.39.0", path = "../testing"}
testing = {version = "0.14.0", path = "../../../testing"}

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_module"
repository = "https://github.com/swc-project/swc.git"
version = "0.46.0"
version = "0.47.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@ -21,11 +21,11 @@ swc_common = {version = "0.13.0", path = "../../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../../ast"}
swc_ecma_loader = {version = "0.21.0", path = "../../loader", features = ["node"]}
swc_ecma_parser = {version = "0.73.0", path = "../../parser"}
swc_ecma_transforms_base = {version = "0.37.0", path = "../base"}
swc_ecma_transforms_base = {version = "0.38.0", path = "../base"}
swc_ecma_utils = {version = "0.47.0", path = "../../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../../visit"}
[dev-dependencies]
swc_ecma_transforms_compat = {version = "0.42.0", path = "../compat"}
swc_ecma_transforms_testing = {version = "0.38.0", path = "../testing/"}
swc_ecma_transforms_compat = {version = "0.43.0", path = "../compat"}
swc_ecma_transforms_testing = {version = "0.39.0", path = "../testing/"}
testing = {version = "0.14.0", path = "../../../testing/"}

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_optimization"
repository = "https://github.com/swc-project/swc.git"
version = "0.52.0"
version = "0.53.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
@ -29,16 +29,16 @@ swc_atoms = {version = "0.2", path = "../../../atoms"}
swc_common = {version = "0.13.0", path = "../../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../../ast"}
swc_ecma_parser = {version = "0.73.0", path = "../../parser"}
swc_ecma_transforms_base = {version = "0.37.0", path = "../base"}
swc_ecma_transforms_base = {version = "0.38.0", path = "../base"}
swc_ecma_utils = {version = "0.47.0", path = "../../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../../visit"}
tracing = "0.1.28"
[dev-dependencies]
swc_ecma_transforms_compat = {version = "0.42.0", path = "../compat"}
swc_ecma_transforms_module = {version = "0.46.0", path = "../module"}
swc_ecma_transforms_proposal = {version = "0.46.0", path = "../proposal"}
swc_ecma_transforms_react = {version = "0.48.0", path = "../react"}
swc_ecma_transforms_testing = {version = "0.38.0", path = "../testing"}
swc_ecma_transforms_typescript = {version = "0.49.0", path = "../typescript"}
swc_ecma_transforms_compat = {version = "0.43.0", path = "../compat"}
swc_ecma_transforms_module = {version = "0.47.0", path = "../module"}
swc_ecma_transforms_proposal = {version = "0.47.0", path = "../proposal"}
swc_ecma_transforms_react = {version = "0.49.0", path = "../react"}
swc_ecma_transforms_testing = {version = "0.39.0", path = "../testing"}
swc_ecma_transforms_typescript = {version = "0.50.0", path = "../typescript"}
testing = {version = "0.14.0", path = "../../../testing"}

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_proposal"
repository = "https://github.com/swc-project/swc.git"
version = "0.46.1"
version = "0.47.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -23,15 +23,15 @@ swc_common = {version = "0.13.0", path = "../../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../../ast"}
swc_ecma_loader = {version = "0.21.0", path = "../../loader", optional = true}
swc_ecma_parser = {version = "0.73.0", path = "../../parser"}
swc_ecma_transforms_base = {version = "0.37.0", path = "../base"}
swc_ecma_transforms_classes = {version = "0.23.0", path = "../classes"}
swc_ecma_transforms_base = {version = "0.38.0", path = "../base"}
swc_ecma_transforms_classes = {version = "0.24.0", path = "../classes"}
swc_ecma_transforms_macros = {version = "0.2.1", path = "../macros"}
swc_ecma_utils = {version = "0.47.0", path = "../../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../../visit"}
[dev-dependencies]
serde_json = "1.0.66"
swc_ecma_transforms_compat = {version = "0.42.0", path = "../compat"}
swc_ecma_transforms_module = {version = "0.46.0", path = "../module"}
swc_ecma_transforms_testing = {version = "0.38.0", path = "../testing"}
swc_ecma_transforms_compat = {version = "0.43.0", path = "../compat"}
swc_ecma_transforms_module = {version = "0.47.0", path = "../module"}
swc_ecma_transforms_testing = {version = "0.39.0", path = "../testing"}
testing = {version = "0.14.0", path = "../../../testing"}

View File

@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"]
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_react"
repository = "https://github.com/swc-project/swc.git"
version = "0.48.3"
version = "0.49.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@ -24,13 +24,13 @@ swc_atoms = {version = "0.2", path = "../../../atoms"}
swc_common = {version = "0.13.5", path = "../../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../../ast"}
swc_ecma_parser = {version = "0.73.0", path = "../../parser"}
swc_ecma_transforms_base = {version = "0.37.0", path = "../base"}
swc_ecma_transforms_base = {version = "0.38.0", path = "../base"}
swc_ecma_utils = {version = "0.47.0", path = "../../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../../visit"}
[dev-dependencies]
swc_ecma_codegen = {version = "0.74.0", path = "../../codegen/"}
swc_ecma_transforms_compat = {version = "0.42.0", path = "../compat/"}
swc_ecma_transforms_module = {version = "0.46.0", path = "../module"}
swc_ecma_transforms_testing = {version = "0.38.0", path = "../testing/"}
swc_ecma_codegen = {version = "0.75.0", path = "../../codegen/"}
swc_ecma_transforms_compat = {version = "0.43.0", path = "../compat/"}
swc_ecma_transforms_module = {version = "0.47.0", path = "../module"}
swc_ecma_transforms_testing = {version = "0.39.0", path = "../testing/"}
testing = {version = "0.14.0", path = "../../../testing"}

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_testing"
repository = "https://github.com/swc-project/swc.git"
version = "0.38.1"
version = "0.39.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -17,9 +17,9 @@ serde = "1"
serde_json = "1"
swc_common = {version = "0.13.0", path = "../../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../../ast"}
swc_ecma_codegen = {version = "0.74.0", path = "../../codegen"}
swc_ecma_codegen = {version = "0.75.0", path = "../../codegen"}
swc_ecma_parser = {version = "0.73.0", path = "../../parser"}
swc_ecma_transforms_base = {version = "0.37.0", path = "../base"}
swc_ecma_transforms_base = {version = "0.38.0", path = "../base"}
swc_ecma_utils = {version = "0.47.0", path = "../../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../../visit"}
tempfile = "3.1.0"

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_typescript"
repository = "https://github.com/swc-project/swc.git"
version = "0.49.1"
version = "0.50.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@ -15,16 +15,16 @@ swc_atoms = {version = "0.2", path = "../../../atoms"}
swc_common = {version = "0.13.5", path = "../../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../../ast"}
swc_ecma_parser = {version = "0.73.0", path = "../../parser"}
swc_ecma_transforms_base = {version = "0.37.4", path = "../base"}
swc_ecma_transforms_react = {version = "0.48.3", path = "../react"}
swc_ecma_transforms_base = {version = "0.38.0", path = "../base"}
swc_ecma_transforms_react = {version = "0.49.0", path = "../react"}
swc_ecma_utils = {version = "0.47.0", path = "../../utils"}
swc_ecma_visit = {version = "0.40.0", path = "../../visit"}
[dev-dependencies]
swc_ecma_codegen = {version = "0.74.0", path = "../../codegen"}
swc_ecma_transforms_compat = {version = "0.42.0", path = "../compat"}
swc_ecma_transforms_module = {version = "0.46.0", path = "../module"}
swc_ecma_transforms_proposal = {version = "0.46.0", path = "../proposal/"}
swc_ecma_transforms_testing = {version = "0.38.0", path = "../testing"}
swc_ecma_codegen = {version = "0.75.0", path = "../../codegen"}
swc_ecma_transforms_compat = {version = "0.43.0", path = "../compat"}
swc_ecma_transforms_module = {version = "0.47.0", path = "../module"}
swc_ecma_transforms_proposal = {version = "0.47.0", path = "../proposal/"}
swc_ecma_transforms_testing = {version = "0.39.0", path = "../testing"}
testing = {version = "0.14.0", path = "../../../testing"}
walkdir = "2.3.1"

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "ast_node"
repository = "https://github.com/swc-project/swc.git"
version = "0.7.3"
version = "0.7.4"
[lib]
proc-macro = true

View File

@ -66,6 +66,7 @@ pub fn derive(input: DeriveInput) -> ItemImpl {
},
{
impl swc_common::Spanned for Type {
#[inline]
fn span(&self) -> swc_common::Span {
body
}

View File

@ -65,7 +65,7 @@ impl Task for BundleTask {
.unwrap_or_default();
let res = catch_unwind(AssertUnwindSafe(|| {
let bundler = Bundler::new(
let mut bundler = Bundler::new(
self.swc.globals(),
self.swc.cm.clone(),
&self.config.loader,

View File

@ -37,7 +37,7 @@ fn run_bench(b: &mut Bencher, entry: &Path) {
::testing::run_test2(false, |cm, _| {
b.iter(|| {
GLOBALS.with(|globals| {
let bundler = Bundler::new(
let mut bundler = Bundler::new(
globals,
cm.clone(),
Loader { cm: cm.clone() },

View File

@ -67,7 +67,7 @@ fn pass(input_dir: PathBuf) {
..Default::default()
},
);
let bundler = Bundler::new(
let mut bundler = Bundler::new(
compiler.globals(),
cm.clone(),
&loader,

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_plugin_runner"
repository = "https://github.com/swc-project/swc.git"
version = "0.9.0"
version = "0.10.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
@ -22,5 +22,5 @@ swc_ecma_parser = {version = "0.73.0", path = "../../ecmascript/parser"}
swc_plugin = {version = "0.7.0", path = "../"}
[dev-dependencies]
swc_ecma_codegen = {version = "0.74.0", path = "../../ecmascript/codegen"}
swc_ecma_codegen = {version = "0.75.0", path = "../../ecmascript/codegen"}
testing = {version = "0.14.0", path = "../../testing"}

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT"
name = "swc_plugin_testing"
repository = "https://github.com/swc-project/swc.git"
version = "0.10.0"
version = "0.11.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -15,7 +15,7 @@ anyhow = "1.0.41"
swc_atoms = {version = "0.2.7", path = "../../atoms"}
swc_common = {version = "0.13.0", path = "../../common"}
swc_ecma_ast = {version = "0.54.0", path = "../../ecmascript/ast"}
swc_ecma_codegen = {version = "0.74.0", path = "../../ecmascript/codegen"}
swc_ecma_codegen = {version = "0.75.0", path = "../../ecmascript/codegen"}
swc_ecma_utils = {version = "0.47.0", path = "../../ecmascript/utils"}
swc_ecma_visit = {version = "0.40.0", path = "../../ecmascript/visit"}
swc_plugin = {version = "0.7.0", path = "../"}

4
scripts/instrument.sh Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env bash
set -eu
cargo instruments --release -t time --bench typescript --features tracing/release_max_level_off $@