Uh oh!
There was an error while loading. Please reload this page.
Wasm marshaler API for user-defined types; migrate Uri and DateTime to new API - #47640
Wasm marshaler API for user-defined types; migrate Uri and DateTime to new API#47640kg wants to merge 3 commits into
Conversation
ghost
commented
Jan 29, 2021
Tagging subscribers to 'arch-wasm': @lewing Issue DetailsThis PR introduces a system for defining custom JS➔Managed and Managed➔JS marshaling primitives so that any* user-defined type can cross between environments seamlessly. The ideal end goal is to use this new system for marshaling types like First, some sample code: publicstructCustomDate{publicDateTimeDate;privatestaticstringJSToManaged_PreFilter()=>"value.toISOString()";privatestaticstringManagedToJS_PostFilter()=>"new Date(value)";privatestaticCustomDateJSToManaged(strings){returnnewCustomDate{Date=DateTime.Parse(s).ToUniversalTime()};}privatestaticstringManagedToJS(refCustomDatecd){returncd.Date.ToString("o");}}General overview:
More detailed notes:
Also in this PR:
|
ghost
commented
Jan 29, 2021
I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label. |
kg
commented
Jan 29, 2021
To help with understanding some of what this machinery does, here's an example of some of the code generated by the bindings to facilitate calling C# from JS: |
lewing
commented
Jan 30, 2021
Failure is relevant |
This breaks debugger tests with It fails at The method in question: .. is in a nested class |
kg
commented
Feb 2, 2021
Thanks for digging in. I bet it's due to generics. |
kjpou1
commented
Feb 5, 2021
Not sure if it is generics or not but I had to add some code for handling generic signatures in the PR here: #47519 This allows for generic signatures. |
2a4b472 to
c8554ecComparekjpou1
commented
Feb 10, 2021
Just running through the DRAFT PR: |
d4fef0c to
7d09a5dComparea439856 to
52d3615Compare8897689 to
990a19fCompareUh oh!
There was an error while loading. Please reload this page.
ghost
commented
Apr 26, 2021
Draft Pull Request was automatically closed for inactivity. It can be manually reopened in the next 30 days if the work resumes. |
4f05f98 to
fd96dc3Compare5eca689 to
86b404bComparelewing
commented
May 21, 2021
@kg are you still missing some changes? |
kg
commented
May 22, 2021
I'm still working through the msbuild integration in a way that won't break tests |
b69bcc0 to
7a1c854CompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
kg
commented
Nov 10, 2021
Here are a set of generated marshaler functions, @pavelsavara //# sourceURL=https://mono-wasm.invalid/System_DateTime$FromJavaScript"use strict";constModule=__closure__.Module;constmono_wasm_new_root=__closure__.mono_wasm_new_root;const_create_temp_frame=__closure__._create_temp_frame;const_get_args_root_buffer_for_method_call=__closure__._get_args_root_buffer_for_method_call;const_get_buffer_for_method_call=__closure__._get_buffer_for_method_call;const_handle_exception_for_call=__closure__._handle_exception_for_call;const_teardown_after_call=__closure__._teardown_after_call;constmono_wasm_try_unbox_primitive_and_get_type=__closure__.mono_wasm_try_unbox_primitive_and_get_type;const_unbox_mono_obj_root_with_known_nonprimitive_type=__closure__._unbox_mono_obj_root_with_known_nonprimitive_type;constinvoke_method=__closure__.invoke_method;constmethod=__closure__.method;constthis_arg=__closure__.this_arg;consttoken=__closure__.token;constunbox_buffer=__closure__.unbox_buffer;constunbox_buffer_size=__closure__.unbox_buffer_size;constgetI32=__closure__.getI32;constgetU32=__closure__.getU32;constgetF32=__closure__.getF32;constgetF64=__closure__.getF64;constconverter_d_result_unmarshaled=__closure__.converter_d_result_unmarshaled;functionSystem_DateTime$FromJavaScript(arg0){_create_temp_frame();letresultRoot=token.scratchResultRoot,exceptionRoot=token.scratchExceptionRoot;token.scratchResultRoot=null;token.scratchExceptionRoot=null;if(resultRoot===null)resultRoot=mono_wasm_new_root();if(exceptionRoot===null)exceptionRoot=mono_wasm_new_root();letargsRootBuffer=_get_args_root_buffer_for_method_call(converter_d_result_unmarshaled,token);letscratchBuffer=_get_buffer_for_method_call(converter_d_result_unmarshaled,token);letbuffer=converter_d_result_unmarshaled.compiled_function(scratchBuffer,argsRootBuffer,method,arg0);letis_result_marshaled=false;resultRoot.value=invoke_method(method,this_arg,buffer,exceptionRoot.get_address());_handle_exception_for_call(converter_d_result_unmarshaled,token,buffer,resultRoot,exceptionRoot,argsRootBuffer);letresultPtr=resultRoot.value,result=undefined;result=resultPtr;_teardown_after_call(converter_d_result_unmarshaled,token,buffer,resultRoot,exceptionRoot,argsRootBuffer);returnresult;};returnSystem_DateTime$FromJavaScript;//# sourceURL=https://mono-wasm.invalid/interchange_filter_for_type62173044"use strict";constModule=__closure__.Module;constMONO=__closure__.MONO;constBINDING=__closure__.BINDING;consttypePtr=__closure__.typePtr;constalloca=__closure__.alloca;constgetI8=__closure__.getI8;constgetI16=__closure__.getI16;constgetI32=__closure__.getI32;constgetI64=__closure__.getI64;constgetU8=__closure__.getU8;constgetU16=__closure__.getU16;constgetU32=__closure__.getU32;constgetF32=__closure__.getF32;constgetF64=__closure__.getF64;constsetI8=__closure__.setI8;constsetI16=__closure__.setI16;constsetI32=__closure__.setI32;constsetI64=__closure__.setI64;constsetU8=__closure__.setU8;constsetU16=__closure__.setU16;constsetU32=__closure__.setU32;constsetF32=__closure__.setF32;constsetF64=__closure__.setF64;constSystem_DateTime$FromJavaScript=__closure__.System_DateTime$FromJavaScript;functioninterchange_filter_for_type62173044(value){switch(typeof(value)){case'number':
returnvalue;default:
if(valueinstanceofDate){returnvalue.valueOf();}elsethrownewError('Value must be a number (msecs since unix epoch), or a Date');}};returninterchange_filter_for_type62173044;//# sourceURL=https://mono-wasm.invalid/js_to_interchange_for_type62173044"use strict";constModule=__closure__.Module;constMONO=__closure__.MONO;constBINDING=__closure__.BINDING;consttypePtr=__closure__.typePtr;constalloca=__closure__.alloca;constgetI8=__closure__.getI8;constgetI16=__closure__.getI16;constgetI32=__closure__.getI32;constgetI64=__closure__.getI64;constgetU8=__closure__.getU8;constgetU16=__closure__.getU16;constgetU32=__closure__.getU32;constgetF32=__closure__.getF32;constgetF64=__closure__.getF64;constsetI8=__closure__.setI8;constsetI16=__closure__.setI16;constsetI32=__closure__.setI32;constsetI64=__closure__.setI64;constsetU8=__closure__.setU8;constsetU16=__closure__.setU16;constsetU32=__closure__.setU32;constsetF32=__closure__.setF32;constsetF64=__closure__.setF64;constSystem_DateTime$FromJavaScript=__closure__.System_DateTime$FromJavaScript;constfilter=__closure__.filter;functionjs_to_interchange_for_type62173044(value,method,parmIdx){letfilteredValue=filter(value);letconvertedResult=System_DateTime$FromJavaScript(filteredValue,method,parmIdx);returnconvertedResult;};returnjs_to_interchange_for_type62173044; |
Uh oh!
There was an error while loading. Please reload this page.
kg
commented
Nov 11, 2021
via email
Vs code with default settings, not sure why
On November 10, 2021 10:49:13 PM PST, Pavel Savara ***@***.***> wrote:
***@***.*** commented on this pull request.
> @@ -188,8 +193,8 @@ export function _handle_exception_for_call(
function _handle_exception_and_produce_result_for_call(
converter: Converter | undefined, token: BoundMethodToken | null,
- buffer: VoidPtr, resultRoot: WasmRoot<MonoString>,
- exceptionRoot: WasmRoot<MonoObject>, argsRootBuffer: WasmRootBuffer | undefined,
+ buffer: VoidPtr, resultRoot: WasmRoot<MonoString>,
The whitespace at the end is something your editor does ?
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#47640 (review) - kg (mobile) |
kg
commented
Nov 20, 2021
PR updated with support for passing |
|
Pull request contains merge conflicts. |
ceba251 to
def3119Compare|
Azure Pipelines successfully started running 1 pipeline(s). |
kg
commented
Dec 9, 2021
/azp run runtime-manual |
|
Azure Pipelines successfully started running 1 pipeline(s). |
221f4c4 to
b23df27Comparekg
commented
Dec 15, 2021
/azp run runtime-manual |
|
Azure Pipelines successfully started running 1 pipeline(s). |
kg
commented
Dec 15, 2021
/azp run runtime-manual |
|
Azure Pipelines successfully started running 1 pipeline(s). |
8afdc4a to
0deb1c2CompareAdd test coverage for date marshaling Add uri test Disable some log statements Returning structs works Returning custom classes works Add null checks to describe_value Remove invalid cwrap Add trimming annotations Restore old benchmark html Reuse result and exception roots Cleaner codegen Disambiguate converters in devtools Transition back to static methods, add signature checks and more error handling Implement a simple bound method cache so that automated tests don't exhaust the scratch root buffer; make the scratch root buffer smaller Fix a LMF leak Fix C warnings Hard-coded table of marshalers is no longer needed Shorter wrapper function names for better stacks Add linker exclusions for custom marshalers Hack around bug in linker/runtime that causes System.Uri forwarder to break Rework class lookup Support passing numeric values as DateTime Transition some null returns to asserts Clean up conditionals Don't use ISO strings Change pre/post filter syntax to require an explicit "return" so it can contain multiple statements Allow ToJavaScript to accept a pointer instead of an 'in' reference Support managed pointer return/parameter types in more places Add marshal_type for pointers Add tests verifying that you can marshal structs by address and then unpack them Initial gc safety work Fix formatting rule Rename pre/post filters Fix type error in driver.c remove _pick_result_chara_for_marshal_type Add library build descriptor to ensure marshalers are not stripped when the BCL is trimmed Attempt to fix the linker stripping test code Better version of no-configured-marshaler warning Annotate SetupJSContinuation Annotate safehandle APIs and add null checks Update targets file to pass custom marshaler msbuild items through to the helix proxy project (requires another change to work) Add tests for Task and ValueTask marshaling Fix unboxing for generic structs Rebase cleanups Correct datetime test to use UTC for comparison Eliminate use of MONO. and BINDING. in closures Optimize out a js->c call Normalize some APIs to take MonoType instead of MonoClass Repair merge damage Address PR feedback Move some types around Repair merge damage Type system fixes Rework create_named_function so that it can handle larger numbers of closure keys more efficiently Remove unnecessary test instrumentation Fix closure variables being generated in the wrong place Use a single memory slab for temp_malloc Checkpoint span support Fix unbuffered filters, support ReadOnlySpan Fix auto signatures for primitives and add test Use 4-chara unicode escapes since the x escapes are not officially permitted in JSON Checkpoint C# implementation of converter generator Align everything by 8 when constructing argument buffers because if you don't do that, the runtime passes corrupt data to C# functions Don't shove raw mono pointers into root buffers since we weren't doing it before (it might be nice to do it though) Fully transition over to having C# generate signature converters C# implementation of bind_method codegen Clean up the bindings named closure table management Add some comments Don't allocate a root for the this-ref when binding methods if the this-ref is null Don't generate dead code for void signatures Remove some dead code and refactor bound method generator Generate more specialized result handling code for bound methods. Align C# and C's idea of marshal types better. Fix GC safety issue Fix tsc wasting 70 seconds on every build Add basic build profiling information Fix root index being incorrect Rename MemOffset and MemValue Remove bind_method this_arg support Move some stuff around Change nested type descriptor syntax
…m hiding other errors, and avoid double teardown when managed code throws
fd1dc81 to
85eb349Compare
This PR introduces a system for defining custom JS➔Managed and Managed➔JS marshaling primitives so that any* user-defined type can cross between environments seamlessly, and migrates our existing Uri and DateTime marshaling logic to use the new system.
First, some sample code:
General overview:
Dateor C#DateTimecan cross the bindings boundary directly, you can marshal it as a string and then use a filter to map it to/from the JSDatetype.const stringinstead of function getters, but right now the only straightforward way to get at managed values is through function calls.'a'type specifier for method signatures (the strings you pass tocall_static_method,bind_static_methodetc) that basically means 'figure it out'. When you use this specifier, the bindings layer will examine the target method and identify the best fit for that parameter. This is meant for the purpose of passing user-defined types so you don't need to think about whether they're classes or structs, but it also can be useful in other cases.More detailed notes:
JSON.parse(value)) to simplify the former, but the latter really demands integrated support for passingSpans around and I have no idea how we'd do this in the existing setup.BinaryFormatteror something like that, but it seems out of scope. This system is at least relatively easy to extend to do that as a fallback.Also in this PR:
box_js_obj_with_converterAPI that allows you to request a specific managed type when boxing a JS value (this is how you create a type like Uri explicitly)Dates. I think that was actually broken, but Blazor works so whatever...