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

Deprecate IDisposable and related utilities #7309

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open

Conversation

wgoehrig
Copy link
Member

Since TypeScript 5.2 added support for the explicit resource management feature in ECMAScript, let's deprecate IDisposable and use the new built-in Disposable instead.

@pmconne
Copy link
Member

pmconne commented Oct 31, 2024

I want to see what output the linter produces. You've presumably introduced a ton of deprecation warnings.

I'd remove all the implements IDisposables from our code - they all implicitly implement it and you'd otherwise presumably have to suppress the lint rule at each occurrence.

@wgoehrig
Copy link
Member Author

This is actually passing lint without any errors in its current state - looks like the @typescript-eslint/no-deprecated rule just doesn't check implements clauses...

@pmconne
Copy link
Member

pmconne commented Oct 31, 2024

I'd remove implements IDisposable everywhere anyway, no reason to document implementation of an interface we discourage people from using.

@aruniverse
Copy link
Member

Over the last few weeks I have been running into issues in my deployed app where it complains about "Uncaught SyntaxError: Missing initializer in using declaration".

image

I'm not necessarily sure if this is browser specific or not, I know others are not able to repro with the same version of chrome(Version 131.0.6778.109 (Official Build) (arm64)), and if I switch browsers it works fine.

I havent investigated too much, but I think the changes in this PR would help solve it. Not sure why when I build my app, depending on the browser it decides to use the global using instead of using from core-bentley

@wgoehrig wgoehrig marked this pull request as ready for review December 11, 2024 15:19
@wgoehrig wgoehrig requested review from a team, aruniverse and calebmshafer as code owners December 11, 2024 15:19
Copy link
Member

@dassaf4 dassaf4 left a comment

Choose a reason for hiding this comment

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

core-geometry change is good.

}
```

> Note that while public types with deterministic cleanup logic in iTwin.js will continue to implement _both_ `IDisposable` and `Disposable` until the former is fully removed in iTwin.js 7.0 (in accordance with our [API support policy](../learning/api-support-policies)), disposable objects should still only be disposed once - _either_ with [IDisposable.dispose]($core-bentley) _or_ `Symbol.dispose()` but not both! Where possible, prefer `using` declarations or the [dispose]($core-bentley) helper function over directly calling either method.
Copy link
Member

Choose a reason for hiding this comment

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

nit: idk if you should explicitly mention a future version, and i dont think you need to call out the support policy

@@ -20,6 +20,29 @@ Table of contents:

## API deprecations

### @itwin/core-bentley
Copy link
Member

Choose a reason for hiding this comment

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

nit: missing in the ToC above
only update this if you are reacting to the other comment on this file. this will get fixed automatically by the next time someone edits this file and has markdownlint/formatters enabled

Copy link
Member

@tcobbs-bentley tcobbs-bentley left a comment

Choose a reason for hiding this comment

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

Mobile changes look fine.

Copy link
Member

@grigasp grigasp left a comment

Choose a reason for hiding this comment

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

Presentation: did some cleanup, fixed coverage not being 100%. Thanks for taking this up!

Copy link
Contributor

mergify bot commented Dec 12, 2024

This pull request is now in conflicts. Could you fix it @wgoehrig? 🙏
To fixup this pull request, you can check out it locally. See documentation: https://help.github.com/articles/checking-out-pull-requests-locally/

@grigasp
Copy link
Member

grigasp commented Dec 13, 2024

I've been making similar changes in presentation repo and came up with a situation that concerns me. I'm not sure it's really something we should worry about, but just wanted to raise this and hear your opinion.

Here's a hypothetical situation before the changes:

class Ours {
  public dispose() {
    // do our dispose
  }
}
class Theirs extends Ours {
  public override dispose() {
    super.dispose();
    // do their dispose
  }
}
function useAndDispose(factory: () => Ours) {
  const instance = factory();
  // ... do something with instance
  // the below call does theirs as well as ours dispose:
  instance.dispose();
}

There could be problems with Theirs.dispose not being called after the changes:

class Ours {
  public [Symbol.dispose]() {
    // do our dispose
  }
  /** @deprecated */
  public dispose() {
    this[Symbol.dispose]();
  }
}
// this class has not been updated to use the new disposal method:
class Theirs extends Ours {
  public override dispose() {
    super.dispose();
    // do their dispose
  }
}
function useAndDispose(factory: () => Ours) {
  // this won't do "theirs dispose"!
  using instance = factory();

  // this wouldn't either:
  const instance = factory();    
  instance[Symbol.dispose]();

  // and even this wouldn't:
  const instance = factory();    
  if (isDisposable(instance)) {
    instance[Symbol.dispose]();
  } else if (isIDisposable(instance)) {
    instance.dispose();
  }

  // only this would:
  const instance = factory();    
  if (isIDisposable(instance)) {
    instance.dispose();
  } else if (isDisposable(instance)) {
    instance[Symbol.dispose]();
  }
}

It seems we should be very careful about only calling Symbol.dispose if the instance we're calling it on is not 100% created by ourselves.

@wgoehrig
Copy link
Member Author

wgoehrig commented Dec 13, 2024

It seems we should be very careful about only calling Symbol.dispose if the instance we're calling it on is not 100% created by ourselves.

I agree this is an important consideration - I checked earlier with @pmconne and he seemed confident that we don't have any patterns in at least the render system where ownership is "transferred" in this way (i.e., where we're responsible for the disposal of something passed in). @grigasp are you aware of anywhere that's happening in presentation?

@grigasp
Copy link
Member

grigasp commented Dec 16, 2024

It seems we should be very careful about only calling Symbol.dispose if the instance we're calling it on is not 100% created by ourselves.

I agree this is an important consideration - I checked earlier with @pmconne and he seemed confident that we don't have any patterns in at least the render system where ownership is "transferred" in this way (i.e., where we're responsible for the disposal of something passed in). @grigasp are you aware of anywhere that's happening in presentation?

There is one place... In the presentation repo I have a safeDispose function which is similar to your dispose, except that it prefers the deprecated dispose over the new Symbol.dispose. What do you think about switching the order in the core-bentley's dispose?

@aruniverse
Copy link
Member

Over the last few weeks I have been running into issues in my deployed app where it complains about "Uncaught SyntaxError: Missing initializer in using declaration".

image

I'm not necessarily sure if this is browser specific or not, I know others are not able to repro with the same version of chrome(Version 131.0.6778.109 (Official Build) (arm64)), and if I switch browsers it works fine.

I havent investigated too much, but I think the changes in this PR would help solve it. Not sure why when I build my app, depending on the browser it decides to use the global using instead of using from core-bentley

So I have unknowingly fixed this in my app. Changed sourcemap config option in vite from inline to true and this fixed the issue for me. So when you inline source maps you have both the using directive and the using utlitity function in the same file. Strange part I dont still dont understand is why this worked for some and not others, and worked in some browsers vs not.

Either way, I think this PR is still in our best interest to complete.

Copy link
Contributor

mergify bot commented Dec 18, 2024

This pull request is now in conflicts. Could you fix it @wgoehrig? 🙏
To fixup this pull request, you can check out it locally. See documentation: https://help.github.com/articles/checking-out-pull-requests-locally/

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.

8 participants