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

implement lowering for using and await using #3192

Merged
merged 2 commits into from
Jun 23, 2023
Merged

implement lowering for using and await using #3192

merged 2 commits into from
Jun 23, 2023

Conversation

evanw
Copy link
Owner

@evanw evanw commented Jun 23, 2023

TypeScript 5.2 (due to be released in August of 2023) will introduce using declarations, which will allow you to automatically dispose of the declared resources when leaving the current scope. You can read the TypeScript PR for this feature for more information. This PR adds support for transforming this syntax to target environments without support for using declarations (which is currently all targets other than esnext). Here's an example (helper functions are omitted):

// Original code
class Foo {
  [Symbol.dispose]() {
    console.log('cleanup')
  }
}
using foo = new Foo;
foo.bar();

// New output (with --target=es6)
var _stack = [];
try {
  var Foo = class {
    [Symbol.dispose]() {
      console.log("cleanup");
    }
  };
  var foo = __using(_stack, new Foo());
  foo.bar();
} catch (_) {
  var _error = _, _hasError = true;
} finally {
  __callDispose(_stack, _error, _hasError);
}

The injected helper functions ensure that the method called Symbol.dispose is called on new Foo when control exits the scope. Note that as with all new JavaScript APIs, you'll need to polyfill Symbol.dispose if it's not present before you use it. This is not something that esbuild does for you because esbuild only handles syntax, not APIs. Polyfilling it can be done with something like this:

Symbol.dispose ||= Symbol.for('Symbol.dispose')

This feature also introduces await using declarations which are like using declarations but they call await on the disposal method (not on the initializer). Here's an example (helper functions are omitted):

// Original code
class Foo {
  async [Symbol.asyncDispose]() {
    await new Promise(done => {
      setTimeout(done, 1000)
    })
    console.log('cleanup')
  }
}
await using foo = new Foo;
foo.bar();

// New output (with --target=es2022)
var _stack = [];
try {
  var Foo = class {
    async [Symbol.asyncDispose]() {
      await new Promise((done) => {
        setTimeout(done, 1e3);
      });
      console.log("cleanup");
    }
  };
  var foo = __using(_stack, new Foo(), true);
  foo.bar();
} catch (_) {
  var _error = _, _hasError = true;
} finally {
  var _promise = __callDispose(_stack, _error, _hasError);
  _promise && await _promise;
}

The injected helper functions ensure that the method called Symbol.asyncDispose is called on new Foo when control exits the scope, and that the returned promise is awaited. Similarly to Symbol.dispose, you'll also need to polyfill Symbol.asyncDispose before you use it.

Fixes #3191

@evanw evanw merged commit ecb33a3 into main Jun 23, 2023
@evanw evanw deleted the using branch June 23, 2023 23:44
paperdave added a commit to oven-sh/bun that referenced this pull request Jan 13, 2024
Jarred-Sumner added a commit to oven-sh/bun that referenced this pull request Jan 16, 2024
* port 'initial support for using declarations'

1:1 port of this commit:

evanw/esbuild@56a3e01

* port 'initial support for await using declarations'

1:1 port of this commit:
evanw/esbuild@1634a0b

* fix cmake config for local jsc

* add global defines for symbols

* begin porting lowering implementation

based off of
evanw/esbuild#3192

* [autofix.ci] apply automated fixes

* add some fun webkit scripts

* fix the minification bug

* refactor runtime_js, etc

* rename test file

* finished yapping

* silly silyl

* Update src/bundler.zig

* ok

* a

* Fix crash

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
ryoppippi pushed a commit to ryoppippi/bun that referenced this pull request Feb 1, 2024
…sh#8151)

* port 'initial support for using declarations'

1:1 port of this commit:

evanw/esbuild@56a3e01

* port 'initial support for await using declarations'

1:1 port of this commit:
evanw/esbuild@1634a0b

* fix cmake config for local jsc

* add global defines for symbols

* begin porting lowering implementation

based off of
evanw/esbuild#3192

* [autofix.ci] apply automated fixes

* add some fun webkit scripts

* fix the minification bug

* refactor runtime_js, etc

* rename test file

* finished yapping

* silly silyl

* Update src/bundler.zig

* ok

* a

* Fix crash

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Jarred Sumner <709451+Jarred-Sumner@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support explicit resource management
1 participant