Skip to content

[dart:js_interop] Support allowInteropCaptureThis in some manner #54381

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

Closed
srujzs opened this issue Dec 15, 2023 · 4 comments
Closed

[dart:js_interop] Support allowInteropCaptureThis in some manner #54381

srujzs opened this issue Dec 15, 2023 · 4 comments
Assignees
Labels
area-web-js Issues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop web-js-interop Issues that impact all js interop

Comments

@srujzs
Copy link
Contributor

srujzs commented Dec 15, 2023

Previous iterations of JS interop allowed wrapping callbacks that allowed you to capture the calling this object.

external Function allowInteropCaptureThis(Function f);

While we do have support for allowInterop through Function.toJS, we don't support capturing this. Currently, that js_util method is unsupported in dart2wasm and the usage is low, but it would be nice to support the capture through something like .toJSWithThis so users can migrate off of dart:js_util easier.

@srujzs srujzs added web-js-interop Issues that impact all js interop area-web-js Issues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop labels Dec 15, 2023
@srujzs srujzs self-assigned this Dec 15, 2023
copybara-service bot pushed a commit that referenced this issue Dec 25, 2023
#54004

In order to reach parity with js_util, we expose operators
through an extension and do some partial renames in order
to make the member names sound better e.g. `equals` instead
of `equal`. We also expose the following from js_util:

- NullRejectionException

We don't expose `isJavaScriptArray` and `isJavaScriptSimpleObject`
as they can expressed through other forms of interop. There
was an esoteric bug where we needed these members for Firefox
in pkg:test, but the package no longer uses these members, so to
avoid increasing the API space too much, we do not export them.

For the same reason, we also don't expose `objectGetPrototypeOf`,
`objectPrototype`, `objectKeys`.

We don't expose `allowInteropCaptureThis` as it will take some
work to handle this in dart2wasm. That work is tracked in
#54381.

Lastly, `instanceof` and `instanceOfString` is moved to be on
`JSAny?`, as this operator is useful to avoid needing to
downcast to `JSObject` e.g. `any.instanceOfString('Window')`
instead of `any.typeofEquals('object') &&
(any as JSObject).instanceOfString('Window')`.

Extensions are reorganized and renamed to handle these changes.

CoreLibraryReviewExempt: Backend-specific library.
Change-Id: Ib1a7fabc3fa985ef6638620becccd27eeca68c25
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/341140
Reviewed-by: Sigmund Cherem <[email protected]>
@ykmnkmi
Copy link
Contributor

ykmnkmi commented Mar 20, 2024

Not necessary, but I need this.

@srujzs
Copy link
Contributor Author

srujzs commented May 22, 2024

FYI @nex3, iirc, Sass was one of the few codebases using this. There might be a way to work around this in the meantime, but I haven't gotten a chance to dig deeper. Let me know if this is a blocker.

@nex3
Copy link
Member

nex3 commented May 22, 2024

Yes, this is necessary. Generally speaking, JS libraries treat this as part of the API surface area for callbacks.

@Zekfad
Copy link

Zekfad commented Jul 4, 2024

Currently it is possible to partially workaround this by using raw JS wrapper function, although this will fail in contexts where CSP does not allow unsafe-eval.

@JS('Function')
external JSFunction _createDynamicJSFunctionUnsafe$1(JSString argument, JSString body);

final _captureThis = () {
  try {
    return _createDynamicJSFunctionUnsafe$1(
      'f'.toJS,
      'return function (...args) { return f.call(this, this, ...args); };'.toJS,
    );
  } catch(e) {
    return null;
  }
}();

JSFunction _tryCaptureThis$0<R extends JSAny?>(R Function(JSObject? context) f) {
  final jsF = f.toJS;
  if (_captureThis == null) {
    return (() => f(null)).toJS;
  }
  return _captureThis!.callAsFunction(_captureThis, jsF)! as JSFunction;
}

JSFunction _tryCaptureThis$1<R extends JSAny?, Arg1 extends JSAny?>(R Function(JSObject? context, Arg1 arg1) f) {
  final jsF = f.toJS;
  if (_captureThis == null) {
    return ((Arg1 arg1) => f(null, arg1)).toJS;
  }
  return _captureThis!.callAsFunction(_captureThis, jsF)! as JSFunction;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web-js Issues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop web-js-interop Issues that impact all js interop
Projects
Status: Done
Development

No branches or pull requests

4 participants