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

Error: Expected a value of type 'xxx', but got one of type 'JavaScriptObject' when running with debug #47786

Closed
technolion opened this issue Nov 26, 2021 · 8 comments
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. closed-duplicate Closed in favor of an existing report web-dev-compiler

Comments

@technolion
Copy link

A flutter web app that uses dart:html runs fine in release mode but fails when running with debug.

We are writing a Flutter app that runs on the browser and accepts files dropped to the browser window.
The app listens for onDrop events and tries to retrieve the dropped object. In our code we are using typed variables (not dynamic)

import 'dart:html' as html;

void _onDrop(html.MouseEvent mouseEvent) async {
    mouseEvent.stopImmediatePropagation();
    mouseEvent.preventDefault();

    html.DataTransfer transfer = mouseEvent.dataTransfer;
    if (transfer.items == null || transfer.items!.length == null) return;
    List<html.Entry> entries = [];
    for (int i = 0; i < transfer.items!.length!; i++) {
      entries.add(transfer.items![i].getAsEntry());
    }
}

html.document.body!.onDrop.listen(_onDrop);

This code runs fine when running in release mode:

flutter run --release -d chrome

However it fails when running in debug mode:

flutter run --debug -d chrome
Attempting to install properties from non-Object type 'FileEntry' onto the native JS Object.
Error: Expected a value of type 'Entry', but got one of type 'JavaScriptObject'
    at Object.throw_ [as throw] (http://localhost:54262/dart_sdk.js:5061:11)
    at Object.castError (http://localhost:54262/dart_sdk.js:5020:15)
    at Object.cast [as as] (http://localhost:54262/dart_sdk.js:5345:17)
    at Function.as_C [as as] (http://localhost:54262/dart_sdk.js:4966:19)
    at Array.[dartx.add] (http://localhost:54262/dart_sdk.js:16274:11)
    at io_html.DropTarget.new._onDrop (http://localhost:54262/packages/spaces_client/pages/theming.dart.lib.js:35303:33)
    at _onDrop.next (<anonymous>)
    at runBody (http://localhost:54262/dart_sdk.js:38659:34)
    at Object._async [as async] (http://localhost:54262/dart_sdk.js:38690:7)
    at io_html.DropTarget.new.[_onDrop] (http://localhost:54262/packages/spaces_client/pages/theming.dart.lib.js:35295:20)
    at Object._checkAndCall (http://localhost:54262/dart_sdk.js:5268:16)
    at Object.dcall (http://localhost:54262/dart_sdk.js:5273:17)
    at HTMLBodyElement.<anonymous> (http://localhost:54262/dart_sdk.js:101824:100)

It seems that using the type Entry (dart API) confuses the debugger because there is no native JavaScript object that matches this name and/or signature.

  • Dart/Flutter SDK version: Flutter (Channel stable, 2.5.3, on macOS 12.0.1 21A559 darwin-x64, locale de-DE)
@lrhn lrhn added area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-dev-compiler labels Nov 29, 2021
@Markzipan
Copy link
Contributor

I'm able to reproduce the Expected a value of type 'xxx', but got one of type 'JavaScriptObject' error but not the Attempting to install properties error. The latter usually happens when an underlying API change hides an object's JS constructor (DDC defaults this to the Object constructor). Potentially similar to #43750.

For the former error, it seems like dart:html performs an unsafe cast of the return value of _webkitGetAsEntry. See:

Entry entry = _webkitGetAsEntry() $#NULLSAFECAST(as Entry);

Can you chime in on the context here, @srujzs?

@srujzs
Copy link
Contributor

srujzs commented Nov 30, 2021

It seems identical to that and similar bugs. Likely, the @Native binding is outdated, and needs to be updated to 'FileEntry' and/or 'FileSystemFileEntry' (https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileEntry). The 'Entry' type seems to no longer exist. #45036 was filed to handle the chunk of file system APIs, so I'm going to dupe it under there. We should probably go through these classes of bugs again and either update the bindings, or think of some smarter way to determine underlying types.

It is interesting that dart2js doesn't fail for this though. I know it uses the object's prototype's toString value to determine what native type to resolve to, so I wonder what the value for FileEntry is.

@srujzs
Copy link
Contributor

srujzs commented Nov 30, 2021

Duplicate of #45036.

@srujzs srujzs closed this as completed Nov 30, 2021
@srujzs srujzs reopened this Dec 23, 2021
@srujzs
Copy link
Contributor

srujzs commented Dec 23, 2021

I'm reopening this issue even though the bug I duped this under has been resolved. It seems like this is a missing constructor issue, and not a wrong binding issue, so if that impression is correct, this problem should actually still persist in debug mode even though the other bug has been fixed.

Unfortunately, this means this goes back to the grouping of classes we're unable to natively bind to the dart:html types in DDC. We are still brainstorming resolutions for these types of classes, and such resolutions will likely be complicated.

@technolion
Copy link
Author

This issue is still not fixed and I don't see how this is a duplicate of of #45036.

@srujzs
Copy link
Contributor

srujzs commented May 1, 2023

Unfortunately, it's unlikely we can get a good fix here that would unify the compilers without changing the way DDC detects native types, and the scope of that change might be quite large. We've been working on introducing new forms of interop that users can use to work around such problems with dart:html. Eventually, the goal is to move away from dart:html and move to a package that exposes the DOM using low-level interop. It's a WIP, but we're getting there: https://github.com/dart-lang/web.

https://github.com/dart-lang/sdk/blob/main/sdk/lib/html/doc/WORKAROUNDS.md has some workarounds to show how you can use @staticInterop in the general case.

In your case, I think this might be resolved if you defined your own interface for Entry and used that instead for entries. I think with Completers and external extension members (with renaming using @JS as needed), it should be portable to a @staticInterop interface. Let me know if you come across any complications.

@technolion
Copy link
Author

In your case, I think this might be resolved if you defined your own interface for Entry and used that instead for entries. I think with Completers and external extension members (with renaming using @JS as needed), it should be portable to a @staticInterop interface. Let me know if you come across any complications.

Thank you very much, that helped a lot! We were able to access the correct Javascript objects using @staticInterop.

@sigmundch
Copy link
Member

Not much to update here, but I added #53864 to describe the problem in DDC and why we are not planning to push on it at the moment. Our current plan is to leverage JS interop and package:web in the future to circumvent these issues.

I'll be marking this issue as a duplicate.

@sigmundch sigmundch added the closed-duplicate Closed in favor of an existing report label Oct 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. closed-duplicate Closed in favor of an existing report web-dev-compiler
Projects
None yet
Development

No branches or pull requests

5 participants