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

Fix JS value to Dart conversion when receiving from a web socket #298

Merged
merged 10 commits into from
Dec 9, 2023

Conversation

osa1
Copy link
Member

@osa1 osa1 commented Nov 30, 2023

MessageEvent is a package:web type and data field is a JS value of type JSAny?.

The receiving end of the sink is here: https://github.com/dart-lang/sdk/blob/26107a319a7503deafee404e3462644a873e2920/pkg/vm_service/lib/src/vm_service.dart#L1795

This code currently does not expect to see JS objects, so passing a JSAny? to the sink breaks it.

The fix should be in the generating end rather than the receiving end: JSAny? is supposed to be an unboxed value, not a boxed Dart value. In an ideal world we shouldn't be able to pass it as a Dart object. So we call dartify and convert it to a Dart object.

This fixes DevTools when compiled to Wasm:
6ET8SvwSiEjnx2G

Thanks to @eyebrowsoffire and @mkustermann for help with debugging.

Also ping @srujzs for the issue with passing JSAny? as Object?.

lib/html.dart Outdated Show resolved Hide resolved
lib/html.dart Outdated
@@ -127,13 +127,13 @@ class HtmlWebSocketChannel extends StreamChannelMixin
}

void _innerListen(MessageEvent event) {
final eventData = event.data;
final JSAny? eventData = event.data;
Copy link
Member

@mkustermann mkustermann Nov 30, 2023

Choose a reason for hiding this comment

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

Do we really need the if / else here? Can this be just

  void _innerListen(MessageEvent event) {
    final JSAny? eventData = event.data;
    _controller.local.sink.add(eventData.dartify());
  }

?

Copy link
Member Author

Choose a reason for hiding this comment

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

That changes how ArrayBuffer is handled as dartify will give you a ByteBuffer instead of a Uint8List.

Maybe package maintainers can comment on whether that's OK.

Copy link
Member Author

Choose a reason for hiding this comment

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

I've updated the type test.

I don't know why we want to convert ArrayBuffer (ByteBuffer in Dart) to Uint8List, it's not documented anywhere in this library as far as I can see. The receiver end of this stream in vm_service is here: https://github.com/dart-lang/sdk/blob/26107a319a7503deafee404e3462644a873e2920/pkg/vm_service/lib/src/vm_service.dart#L1795-L1807

It's expecting (1) String (2) List<int> (3) ByteData, but as far as I understand from https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/message_event and this library it will never receive a ByteData (JS DataView). Maybe it needs to handle ByteBuffer instead of ByteData?

@kevmoo
Copy link
Member

kevmoo commented Nov 30, 2023

SO EXCITED to see this wired up. @srujzs should absolutely look

Copy link
Member

@kevmoo kevmoo left a comment

Choose a reason for hiding this comment

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

I LOVE that the fix was so simple

lib/html.dart Outdated
data = (eventData as JSArrayBuffer).toDart.asUint8List();
} else {
data = event.data;
var data = event.data.dartify();
Copy link

Choose a reason for hiding this comment

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

It looks like the fix is to dartify non-ArrayBuffers as well, which should only ever be a JS string iiuc. Is it worth adding an assert in an else condition to ensure that the result is a String? This may be useful to avoid passing in unexpected Dart values down.

Copy link
Member

Choose a reason for hiding this comment

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

🤷

Copy link
Member

Choose a reason for hiding this comment

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

It looks like the fix is to dartify non-ArrayBuffers as well, which should only ever be a JS string iiuc.

With @osa1 we were looking at this today and the browser API says MessageEvent.data can be:

  • If the message type is "text", then this field is a string.
  • If the message type is "binary" type, then the type of this property can be inferred from the binaryType of this socket:

But it seemed the existing code somewhat assumed it's not going to get a Blob but only string or array buffer

Copy link
Member Author

Choose a reason for hiding this comment

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

But it seemed the existing code somewhat assumed it's not going to get a Blob but only string or array buffer

Expected JS type of binary messages is specified when constructing a web socket channel using this type:

/// An enum for choosing what type [HtmlWebSocketChannel] emits for binary
/// messages.
class BinaryType {
/// Tells the channel to emit binary messages as [Blob]s.
static const blob = BinaryType._('blob', 'blob');
/// Tells the channel to emit binary messages as [Uint8List]s.
static const list = BinaryType._('list', 'arraybuffer');
as either Blob (I don't know what would be the Dart type for this) or ArrayBuffer (which this library converts to Uint8List).

When I searched for BinaryType (ag -w --dart BinaryType) I can't find any uses in SDK or devtools, so it seems to me like we use the default BinaryType which is ArrayBuffer. That's why the use site doesn't handle the Blob case.

(Relevant MDN: https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/message_event#event_properties)

So we can't assert here that the data is either JSArrayBuffer or a String, it can also be Blob.

We could assert that the data is one of JSArrayBuffer, JSString, or the JS type for Blob.

I think it makes sense to avoid dartify here (which will do more type tests than necessary), and explicitly cover only these three cases. If the data is not a string or ArrayBuffer we can assert that it's a Blob.

Copy link
Member Author

Choose a reason for hiding this comment

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

@srujzs how should we convert the Blob data to Dart? This can happen when you pass BinaryType.blob to HtmlWebSocketChannel.connect.

Copy link

Choose a reason for hiding this comment

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

If I'm interpreting the code in vm_service correctly here, it doesn't look like we handle Blobs at all. On dart2js and ddc, we have dart:html, which includes Blob as a natively intercepted type. None of the type checks in the vm_service should apply to this type. Blob is now in package:web as a @staticInterop type. It's a JS object which doesn't have an equivalent Dart type since it's not a typed array or any of the other JS types.

Since we don't handle Blobs here to begin with, the correct migration might be to assert that it's one of those three types, and in the case of Blobs, pass it directly to the vm_service and have it log that it's an unknown message type.

If we want, we can extract the contents of the Blob into a typed array and use that, but it doesn't look like the code was doing that before: https://developer.mozilla.org/en-US/docs/Web/API/Blob#extracting_data_from_a_blob.

Copy link
Member Author

Choose a reason for hiding this comment

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

"and in the case of Blobs, pass it directly to the vm_service"

Do you mean pass the dartify of Blob, or the JSValue for it?

I think it should be the former, but want to make sure.

Copy link

Choose a reason for hiding this comment

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

dartify shouldn't do anything for a Blob as it's not any of the primitive types or typed arrays, so either way should produce the same JSValue.

Copy link
Member Author

Choose a reason for hiding this comment

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

OK, in that case I think the current changes are fine?

Copy link

Choose a reason for hiding this comment

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

Yes, it's up to you if you want to assert the types of data, but I think the functional changes are fine.

@srujzs
Copy link

srujzs commented Nov 30, 2023

issue with passing JSAny? as Object?.

The general issue with disallowing this is Object? is a top-type. We discussed another possible top-type so that the two hierarchies truly are orthogonal, but there are several complications. For example, collections can no longer store JS values (which may be a plus for some). There are also language and front-end complications iirc.

With extension types, we can disallow assignment of JSAny to Object if we wanted due to the way the implements clause works, but we can't disallow assignment to Object?. I don't know if we want the first part if the second part can't be addressed, because it just seems weirdly inconsistent. I haven't landed that change yet though, so if we do want it, this would be a good time to disallow it.

All this being said, we can certainly make it a lint when we upcast to Object?. Unlike JSString as String, it's a valid cast on all backends, however. It just might not be want you want in most cases.

@mkustermann
Copy link
Member

All this being said, we can certainly make it a lint when we upcast to Object?. Unlike JSString as String, it's a valid cast on all backends, however. It just might not be want you want in most cases.

If I understand this correctly, then the JS* classes will (on wasm) eventually be represented as inline classes with an externref member. Whenever such a JS* type flows into a top type, then it needs to be boxed (afaik JSValue is the actual box, right?) - otherwise just bad things happen, e.g. compiler crashes, ...

In the VM's C FFI we have an extra type checker (of sort) that will - for otherwise perfectly language compliant code - issue compile-time errors if it's not valid C FFI DSL code. Why not do something similar here? Whenever a JS* flows into top types (including into places of type parameters that have top type bounds), we issue a compile-time error.

@srujzs
Copy link

srujzs commented Nov 30, 2023

Kind of. externrefs are boxed to JSValue and then wrapped by the JS* extension types (whose representation types are naturally JSValue). So assigning it to an Object wouldn't break soundness since JSValue is still a Dart Object. We've discussed various alternatives to this like boxing only when flowing to Object, eliding the JSValue boxes, etc.

Can you point me to FFI's type checker where you check for flowing into top-types? I presumed catching all upcasts to top types is complicated, but I'd be curious to look at the implementation.

@mkustermann
Copy link
Member

mkustermann commented Nov 30, 2023

Kind of. externrefs are boxed to JSValue and then wrapped by the JS* extension types (whose representation types are naturally JSValue). So assigning it to an Object wouldn't break soundness since JSValue is still a Dart Object.

Ah, so it means JS values are always boxed in a JSValue (and other JS* inline classes + extensions on them are for convenience)? Though then I'm confused, as the problematic code in this PR looks like this:

  void _innerListen(MessageEvent event) {
    final eventData = event.data;
    Object? data;
    if (eventData.typeofEquals('object') &&
        (eventData as JSObject).instanceOfString('ArrayBuffer')) {
      data = (eventData as JSArrayBuffer).toDart.asUint8List();
    } else {
      data = event.data;  // <---XXX
    }
    _controller.local.sink.add(data);
  }

If what you say is true, then shouldn't we be adding a JSValue box to sink.add(data) here at XXX? Where it seems what actually happens is that data (when using dart2js) isn't a JSValue box around a javascript string but the javascript string itself.

(If all JS objects are immediately boxed into JSValue which are valid Dart objects and we have relaxed guarantees about identities of JSValue then our compilers could "unbox" those JSValues across method calls / in fields / etc and transparently box when flowing into top types - so doing this as a compiler optimization instead of something at compile-time)

Can you point me to FFI's type checker where you check for flowing into top-types? I presumed catching all upcasts to top types is complicated, but I'd be curious to look at the implementation.

The VM gets the valid type-checked Dart code from CFE in the form of kernel. In the VM target's modular transformations we then perform extra checks and issue compile-time errors if the checks don't succeed.

The checks e.g. check correspondence between FFI types and Dart types and various other properties of native definitions, native uses, ffi struct classes, .... See ffi/definitions.dart, ffi/use_sites.dart, ...

The FFI checks aren't related to things flowing into top types, but I'm suggesting we could do that for the the JS interop.

@srujzs
Copy link

srujzs commented Nov 30, 2023

Where it seems what actually happens is that data (when using dart2js) isn't a JSValue box around a javascript string but the javascript string itself.

Right, the JSValue discussion is purely for dart2wasm. JSValue as a concept doesn't quite exist in dart2js or DDC. In those compilers, we use a combination of leveraging the fact that primitives are JS values and the notion of interceptors.

For example:

  • JSString is really just String under the hood because String is a JS string.
  • JSObject are an "interceptor" under the hood. The key part here is that interceptors are not boxes. The value is still just the JS value, but dispatch on these values are handled specially. There's a useful doc here explaining them.

This (necessary) distinction between the compilers is where the source of the error comes from. This is partly why is, as, and various other runtime mechanisms are prone to error and I want to lock them down. It might help to look at my extension types CL that maps JS types to their reified types here to get an idea of what each JS type is under the hood on the different backends. In the current SDK, we do this with @staticInterop and custom erasure here.

we have relaxed guarantees about identities of JSValue

Ignoring identical, which I don't think is reasonable to make guarantees on, == forwards to the underlying JS value, so your observation that this could be a compiler optimization is spot on! That's the ideal plan.

The FFI checks aren't related to things flowing into top types, but I'm suggesting we could do that for the the JS interop.

Ah, got it. I think one of the things we need to investigate is whether these flow points are always observable in the kernel. Naturally, an explicit cast will be, but should implicit upcasts or assignments be harder to catch? There are more questions here, but that's the kind of stuff I'd want to look into. Long-term, we discussed doing similar things for the JS backends, but there's existing interop that might make this more complicated.

@eyebrowsoffire
Copy link

@srujzs Re: your comment here:

Ah, got it. I think one of the things we need to investigate is whether these flow points are always observable in the kernel. Naturally, an explicit cast will be, but should implicit upcasts or assignments be harder to catch?

I think if we are to have unboxed flow of externrefs in dart2wasm (which we don't have right now but Joshua was working on before he left) we will have to detect all the upcast cases and downcast cases and emit code that boxes and unboxes them respectively anyway if we want to support JSAny flowing into top types. Since we have to detect these cases anyway, it's probably actually less work to just never emit this boxing/unboxing code anyway and write a frontend pass that detects these cases and emits a compile error. The pass could be used by js and wasm backends, and would mean we'd never run into these sorts of dynamic craziness, and it would mean we would never have to emit bytecode that deals with upcasts of downcasts between JS types and Object/dynamic

@kevmoo
Copy link
Member

kevmoo commented Dec 5, 2023

Have we converged here? Can we land?

@kevmoo
Copy link
Member

kevmoo commented Dec 6, 2023

Friendly ping...any more discussion that needs to happen here? @osa1 ?

@kevmoo
Copy link
Member

kevmoo commented Dec 7, 2023 via email

@osa1
Copy link
Member Author

osa1 commented Dec 8, 2023

As discussed yesterday at the dart2wasm meeting, it would be good to avoid dartify as dartify handles more cases than necessary and it'll prevent tree shaking of some JS interop classes. I will replace the dartify call with type tests to explicitly handle the possibilities.

@osa1
Copy link
Member Author

osa1 commented Dec 8, 2023

I've updated the conversion to avoid using dartify. @srujzs ptal.

We should document what kind of values this library can write to the channel, but in a separate PR.

@osa1 osa1 requested a review from srujzs December 8, 2023 09:04
@srujzs
Copy link

srujzs commented Dec 8, 2023

Changes to use type-checks instead LGTM!

@osa1 osa1 merged commit 969bc6c into master Dec 9, 2023
4 checks passed
@osa1 osa1 deleted the osa1/js_value_fix branch December 9, 2023 09:47
copybara-service bot pushed a commit to dart-lang/sdk that referenced this pull request Feb 15, 2024
Revisions updated by `dart tools/rev_sdk_deps.dart`.

http (https://github.com/dart-lang/http/compare/f0a02f9..d8b237d):
  d8b237d  2024-02-15  Kevin Moore  [http] Migrate to the latest pkg:web, require Dart 3.3 (dart-lang/http#1132)
  5179d1c  2024-02-01  dependabot[bot]  Bump actions/cache from 3.3.2 to 4.0.0 (dart-lang/http#1125)
  0b803e8  2024-02-01  dependabot[bot]  Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/http#1124)
  82e0424  2024-01-29  Brian Quinlan  Use preferred flutter version constraints (dart-lang/http#1119)
  ccefa7c  2024-01-17  Brian Quinlan  Support `BaseResponseWithUrl` in `package:cupertino_http` and `package:cronet_http` (dart-lang/http#1110)
  e7a8e25  2024-01-16  Brian Quinlan  Add `BaseResponseWithUrl.url` (dart-lang/http#1109)
  c8f17a6  2024-01-12  Brian Quinlan  Add a contributing guide (dart-lang/http#1115)
  ebd86b9  2024-01-12  Brian Quinlan  Add the ability to get response headers as a `Map<String, List<String>>` (dart-lang/http#1114)
  5c75da6  2024-01-12  Brian Quinlan  Add tests for sending "cookie" and receiving "set-cookie" headers (dart-lang/http#1113)
  c2a6d64  2024-01-12  Alex Li  [cronet_http] ⬇️ Downgrade `minSdkVersion` to 21 (dart-lang/http#1104)
  661f5d6  2024-01-08  Brian Quinlan  Use `package:http_image_provider` in all `Client` implementation examples (dart-lang/http#1089)
  473a892  2024-01-04  Brian Quinlan  Remove the "play-services-cronet" dependency in the example app when building `package:cronet_http_embedded` (dart-lang/http#1103)
  e79ebe1  2024-01-03  Moritz  Fix `labeler.yml` (dart-lang/http#1099)
  73b0b1c  2024-01-01  dependabot[bot]  Bump actions/labeler from 4.3.0 to 5.0.0 (dart-lang/http#1096)
  15ec3ba  2023-12-21  Brian Quinlan  Prepare to publish `package:cronet_http` as 1.0.0 (dart-lang/http#1087)
  26e55c3  2023-12-21  Brian Quinlan  cronet_http: require android API level 28 (dart-lang/http#1088)
  b10f448  2023-12-22  Alex Li  [cronet_http] Enables CI for `cronet_http_embedded` (dart-lang/http#1070)
  a5b8eec  2023-12-18  Brian Quinlan  Prepare to publish cupertino 1.2.0 (dart-lang/http#1080)
  c114aa0  2023-12-15  Brian Quinlan  Add a fake response for PNG images (dart-lang/http#1081)
  db2cb76  2023-12-14  Kevin Moore  Run web tests with wasm with dev Dart sdk (dart-lang/http#1078)
  36f98e9  2023-12-12  Brian Quinlan  Fix a bug where BrowserClient was listed as requiring Flutter (dart-lang/http#1077)
  db7f165  2023-12-07  Brian Quinlan  Provide an example of configuring IOClient with an HttpClient. (dart-lang/http#1074)
  cd748b6  2023-12-04  Brian Quinlan  Document that runWithClient must be called for every isolate (dart-lang/http#1069)
  f585947  2023-12-04  Brian Quinlan  Test persistentConnection with large request bodies (dart-lang/http#984)
  7c05dde  2023-12-04  Brian Quinlan  Add documentation for "no_default_http_client" (dart-lang/http#1068)
  d8983fa  2023-12-04  Brian Quinlan  Add support for setting headers for all requests (dart-lang/http#1060)
  c90496e  2023-12-04  Brian Quinlan  Document how to use replacement `Client` implementations (dart-lang/http#1063)
  c8536e4  2023-12-01  Kevin Moore  [http_client_conformance_tests] Updates to support wasm compilation (dart-lang/http#1064)
  5dd5140  2023-12-01  dependabot[bot]  Bump actions/setup-java from 3 to 4 (dart-lang/http#1065)
  064f510  2023-11-30  Devon Carew  misc cleanup of yaml files (dart-lang/http#1061)
  22f52e2  2023-11-30  Brian Quinlan  Update pubspec.yaml to 0.4.2 (dart-lang/http#1059)
  40a46d8  2023-11-29  Brian Quinlan  Fix a bug where cronet_http sends incorrect HTTP request methods (dart-lang/http#1058)
  c125ed5  2023-11-27  Kevin Moore  [http] Allow pkg:web v0.3.0 (dart-lang/http#1055)
  9fb4cfa  2023-11-22  Kevin Moore  Update lints to latest, etc (dart-lang/http#1048)
  5e84d9f  2023-11-21  Kevin Moore  Update platform-specific imports for wasm (dart-lang/http#1051)
  8c9feb5  2023-11-21  Kevin Moore  [http] Fix type cast for dart2wasm (dart-lang/http#1050)
  a2f0b25  2023-11-21  Kevin Moore  [http] use pkg:web, require Dart 3.2 (dart-lang/http#1049)

markdown (https://github.com/dart-lang/markdown/compare/c2b8429..6efe141):
  6efe141  2024-02-14  Kevin Moore  Migrate example to pkg:web, update minimum required Dart version (dart-lang/markdown#582)

web_socket_channel (https://github.com/dart-lang/web_socket_channel/compare/5241175..3db86bc):
  3db86bc  2024-02-15  Kevin Moore  Require Dart 3.3 and the latest pkg:web (dart-lang/web_socket_channel#326)
  1c4a923  2024-02-01  dependabot[bot]  Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/web_socket_channel#323)
  041aa3c  2024-01-08  Devon Carew  adjust the HtmlWebSocketChannel ctor parameter type; rev to 2.4.3 (dart-lang/web_socket_channel#320)
  0e8bedc  2024-01-04  Tyler Dunn  Allow pkg:web v0.3.0 (dart-lang/web_socket_channel#306)
  62370cc  2024-01-01  dependabot[bot]  Bump actions/stale from 8.0.0 to 9.0.0 (dart-lang/web_socket_channel#312)
  2a0563f  2023-12-18  Kevin Moore  Prepare release v2.4.1 (dart-lang/web_socket_channel#301)
  906c944  2023-12-14  Kevin Moore  CI: test dev SDK with dart2wasm (dart-lang/web_socket_channel#304)
  a316c53  2023-12-13  Kevin Moore  Rename helper extensions to not collide with pkg:web unreleased (dart-lang/web_socket_channel#303)
  547184a  2023-12-11  Kevin Moore  blast_repo fixes (dart-lang/web_socket_channel#302)
  969bc6c  2023-12-09  Ömer Sinan Ağacan  Fix JS value to Dart conversion when receiving from a web socket (dart-lang/web_socket_channel#298)
  df096a9  2023-11-30  Ömer Sinan Ağacan  Remove removed lints (dart-lang/web_socket_channel#299)
  67bf9a3  2023-11-23  Nate Bosch  Drop some use of ! (dart-lang/web_socket_channel#296)
  d4a8d70  2023-11-22  Kevin Moore  Small tweak (dart-lang/web_socket_channel#295)
  9e80b8d  2023-11-22  Kevin Moore  migrate to pkg web (dart-lang/web_socket_channel#294)

Change-Id: I87c4baa07efc5fc2bb283c7b32e69ad69c5a02aa
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352960
Reviewed-by: Kevin Moore <kevmoo@google.com>
Commit-Queue: Devon Carew <devoncarew@google.com>
copybara-service bot pushed a commit to dart-lang/sdk that referenced this pull request Feb 16, 2024
This reverts commit 8d703d1.

Reason for revert: HHH bot is broken

Original change's description:
> [deps] rev http, markdown, web_socket_channel
>
> Revisions updated by `dart tools/rev_sdk_deps.dart`.
>
> http (https://github.com/dart-lang/http/compare/f0a02f9..d8b237d):
>   d8b237d  2024-02-15  Kevin Moore  [http] Migrate to the latest pkg:web, require Dart 3.3 (dart-lang/http#1132)
>   5179d1c  2024-02-01  dependabot[bot]  Bump actions/cache from 3.3.2 to 4.0.0 (dart-lang/http#1125)
>   0b803e8  2024-02-01  dependabot[bot]  Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/http#1124)
>   82e0424  2024-01-29  Brian Quinlan  Use preferred flutter version constraints (dart-lang/http#1119)
>   ccefa7c  2024-01-17  Brian Quinlan  Support `BaseResponseWithUrl` in `package:cupertino_http` and `package:cronet_http` (dart-lang/http#1110)
>   e7a8e25  2024-01-16  Brian Quinlan  Add `BaseResponseWithUrl.url` (dart-lang/http#1109)
>   c8f17a6  2024-01-12  Brian Quinlan  Add a contributing guide (dart-lang/http#1115)
>   ebd86b9  2024-01-12  Brian Quinlan  Add the ability to get response headers as a `Map<String, List<String>>` (dart-lang/http#1114)
>   5c75da6  2024-01-12  Brian Quinlan  Add tests for sending "cookie" and receiving "set-cookie" headers (dart-lang/http#1113)
>   c2a6d64  2024-01-12  Alex Li  [cronet_http] ⬇️ Downgrade `minSdkVersion` to 21 (dart-lang/http#1104)
>   661f5d6  2024-01-08  Brian Quinlan  Use `package:http_image_provider` in all `Client` implementation examples (dart-lang/http#1089)
>   473a892  2024-01-04  Brian Quinlan  Remove the "play-services-cronet" dependency in the example app when building `package:cronet_http_embedded` (dart-lang/http#1103)
>   e79ebe1  2024-01-03  Moritz  Fix `labeler.yml` (dart-lang/http#1099)
>   73b0b1c  2024-01-01  dependabot[bot]  Bump actions/labeler from 4.3.0 to 5.0.0 (dart-lang/http#1096)
>   15ec3ba  2023-12-21  Brian Quinlan  Prepare to publish `package:cronet_http` as 1.0.0 (dart-lang/http#1087)
>   26e55c3  2023-12-21  Brian Quinlan  cronet_http: require android API level 28 (dart-lang/http#1088)
>   b10f448  2023-12-22  Alex Li  [cronet_http] Enables CI for `cronet_http_embedded` (dart-lang/http#1070)
>   a5b8eec  2023-12-18  Brian Quinlan  Prepare to publish cupertino 1.2.0 (dart-lang/http#1080)
>   c114aa0  2023-12-15  Brian Quinlan  Add a fake response for PNG images (dart-lang/http#1081)
>   db2cb76  2023-12-14  Kevin Moore  Run web tests with wasm with dev Dart sdk (dart-lang/http#1078)
>   36f98e9  2023-12-12  Brian Quinlan  Fix a bug where BrowserClient was listed as requiring Flutter (dart-lang/http#1077)
>   db7f165  2023-12-07  Brian Quinlan  Provide an example of configuring IOClient with an HttpClient. (dart-lang/http#1074)
>   cd748b6  2023-12-04  Brian Quinlan  Document that runWithClient must be called for every isolate (dart-lang/http#1069)
>   f585947  2023-12-04  Brian Quinlan  Test persistentConnection with large request bodies (dart-lang/http#984)
>   7c05dde  2023-12-04  Brian Quinlan  Add documentation for "no_default_http_client" (dart-lang/http#1068)
>   d8983fa  2023-12-04  Brian Quinlan  Add support for setting headers for all requests (dart-lang/http#1060)
>   c90496e  2023-12-04  Brian Quinlan  Document how to use replacement `Client` implementations (dart-lang/http#1063)
>   c8536e4  2023-12-01  Kevin Moore  [http_client_conformance_tests] Updates to support wasm compilation (dart-lang/http#1064)
>   5dd5140  2023-12-01  dependabot[bot]  Bump actions/setup-java from 3 to 4 (dart-lang/http#1065)
>   064f510  2023-11-30  Devon Carew  misc cleanup of yaml files (dart-lang/http#1061)
>   22f52e2  2023-11-30  Brian Quinlan  Update pubspec.yaml to 0.4.2 (dart-lang/http#1059)
>   40a46d8  2023-11-29  Brian Quinlan  Fix a bug where cronet_http sends incorrect HTTP request methods (dart-lang/http#1058)
>   c125ed5  2023-11-27  Kevin Moore  [http] Allow pkg:web v0.3.0 (dart-lang/http#1055)
>   9fb4cfa  2023-11-22  Kevin Moore  Update lints to latest, etc (dart-lang/http#1048)
>   5e84d9f  2023-11-21  Kevin Moore  Update platform-specific imports for wasm (dart-lang/http#1051)
>   8c9feb5  2023-11-21  Kevin Moore  [http] Fix type cast for dart2wasm (dart-lang/http#1050)
>   a2f0b25  2023-11-21  Kevin Moore  [http] use pkg:web, require Dart 3.2 (dart-lang/http#1049)
>
> markdown (https://github.com/dart-lang/markdown/compare/c2b8429..6efe141):
>   6efe141  2024-02-14  Kevin Moore  Migrate example to pkg:web, update minimum required Dart version (dart-lang/markdown#582)
>
> web_socket_channel (https://github.com/dart-lang/web_socket_channel/compare/5241175..3db86bc):
>   3db86bc  2024-02-15  Kevin Moore  Require Dart 3.3 and the latest pkg:web (dart-lang/web_socket_channel#326)
>   1c4a923  2024-02-01  dependabot[bot]  Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (dart-lang/web_socket_channel#323)
>   041aa3c  2024-01-08  Devon Carew  adjust the HtmlWebSocketChannel ctor parameter type; rev to 2.4.3 (dart-lang/web_socket_channel#320)
>   0e8bedc  2024-01-04  Tyler Dunn  Allow pkg:web v0.3.0 (dart-lang/web_socket_channel#306)
>   62370cc  2024-01-01  dependabot[bot]  Bump actions/stale from 8.0.0 to 9.0.0 (dart-lang/web_socket_channel#312)
>   2a0563f  2023-12-18  Kevin Moore  Prepare release v2.4.1 (dart-lang/web_socket_channel#301)
>   906c944  2023-12-14  Kevin Moore  CI: test dev SDK with dart2wasm (dart-lang/web_socket_channel#304)
>   a316c53  2023-12-13  Kevin Moore  Rename helper extensions to not collide with pkg:web unreleased (dart-lang/web_socket_channel#303)
>   547184a  2023-12-11  Kevin Moore  blast_repo fixes (dart-lang/web_socket_channel#302)
>   969bc6c  2023-12-09  Ömer Sinan Ağacan  Fix JS value to Dart conversion when receiving from a web socket (dart-lang/web_socket_channel#298)
>   df096a9  2023-11-30  Ömer Sinan Ağacan  Remove removed lints (dart-lang/web_socket_channel#299)
>   67bf9a3  2023-11-23  Nate Bosch  Drop some use of ! (dart-lang/web_socket_channel#296)
>   d4a8d70  2023-11-22  Kevin Moore  Small tweak (dart-lang/web_socket_channel#295)
>   9e80b8d  2023-11-22  Kevin Moore  migrate to pkg web (dart-lang/web_socket_channel#294)
>
> Change-Id: I87c4baa07efc5fc2bb283c7b32e69ad69c5a02aa
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352960
> Reviewed-by: Kevin Moore <kevmoo@google.com>
> Commit-Queue: Devon Carew <devoncarew@google.com>

Change-Id: I8723a343908227e39604cba7827c0f99912a10f4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352967
Reviewed-by: Siva Annamalai <asiva@google.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Siva Annamalai <asiva@google.com>
Auto-Submit: Devon Carew <devoncarew@google.com>
Reviewed-by: Devon Carew <devoncarew@google.com>
mosuem pushed a commit to dart-lang/http that referenced this pull request Dec 11, 2024
…t-lang/web_socket_channel#298)

`MessageEvent` is a `package:web` type and `data` field is a JS value of type
`JSAny?`.

The receiving end of the `sink` is here:
https://github.com/dart-lang/sdk/blob/26107a319a7503deafee404e3462644a873e2920/pkg/vm_service/lib/src/vm_service.dart#L1795

This code currently does not expect to see JS objects, so passing a `JSAny?` to
the sink breaks it.

The fix should be in the generating end rather than the receiving end: `JSAny?`
is supposed to be an unboxed value, not a boxed Dart value. In an ideal world we
shouldn't be able to pass it as a Dart object. So we call `dartify` and convert
it to a Dart object.

This fixes DevTools when compiled to Wasm.

Thanks to @eyebrowsoffire and @mkustermann for help with debugging.

Co-authored-by: Kevin Moore <kevmoo@google.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.

5 participants