From 25a9fc0aabfb052ec549f052edb634ea4d0e4db9 Mon Sep 17 00:00:00 2001 From: Srujan Gaddam Date: Fri, 14 Jun 2024 20:46:20 +0000 Subject: [PATCH] [ddc] Move null check to JS foreign function in isDartClass and isDartFunction The Dart != check lowers to !== in JS. The RTI property doesn't exist in the JS function, so the result is undefined. However, undefined !== null returns true, so JS functions are accidentally treated as Dart functions. This fixes that. Change-Id: I4c4e0018768c0ac29f4b5ee228c504b7cb0b7232 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/369200 Reviewed-by: Nicholas Shahan Commit-Queue: Srujan Gaddam --- .../private/ddc_runtime/types.dart | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart index 6d4a2893c43..a2bc6aaba95 100644 --- a/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart +++ b/sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart @@ -137,8 +137,12 @@ F assertInterop(F f) { bool isDartClass(Object? obj) { // All Dart classes are instances of JavaScript functions. if (!JS('!', '# instanceof Function', obj)) return false; - // All Dart classes have an interface type recipe attached to them. - return JS('', '#.#', obj, rti.interfaceTypeRecipePropertyName) != null; + // All Dart classes have an interface type recipe attached to them. We put the + // `!=` check in the foreign function call, since the Dart `!=` check would + // lower to `!==`. In the case where [obj] is a JS function, the result of + // getting this property would be `undefined`, and therefore `!== null` would + // be true, which is not what we want. + return JS('!', '#.# != null', obj, rti.interfaceTypeRecipePropertyName); } /// Returns `true` when [obj] represents a Dart function. @@ -146,8 +150,13 @@ bool isDartClass(Object? obj) { bool isDartFunction(Object? obj) { // All Dart functions are instances of JavaScript functions. if (!JS('!', '# instanceof Function', obj)) return false; - // All Dart functions have a signature attached to them. - return JS('!', '#[#]', obj, JS_GET_NAME(JsGetName.SIGNATURE_NAME)) != null; + // All Dart functions have a signature attached to them. We put the `!=` check + // in the foreign function call, since the Dart `!=` check would lower to + // `!==`. In the case where [obj] is a JS function, the result of getting this + // property would be `undefined`, and therefore `!== null` would be true, + // which is not what we want. + return JS( + '!', '#[#] != null', obj, JS_GET_NAME(JsGetName.SIGNATURE_NAME)); } Expando _assertInteropExpando = Expando();