Bug 205239 - Add WKWebView SPI to evaluate a function with arguments
Summary: Add WKWebView SPI to evaluate a function with arguments
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore Misc. (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Brady Eidson
URL:
Keywords: InRadar
: 134330 (view as bug list)
Depends on:
Blocks:
 
Reported: 2019-12-14 14:06 PST by Brady Eidson
Modified: 2020-02-19 00:18 PST (History)
26 users (show)

See Also:


Attachments
Patch (54.46 KB, patch)
2019-12-15 15:33 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (54.95 KB, patch)
2019-12-15 15:46 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (55.53 KB, patch)
2019-12-15 21:48 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (55.67 KB, patch)
2019-12-15 22:07 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (56.00 KB, patch)
2019-12-15 22:42 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (55.72 KB, patch)
2019-12-16 11:15 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (55.71 KB, patch)
2019-12-16 12:47 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (55.98 KB, patch)
2019-12-16 13:11 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (58.36 KB, patch)
2019-12-16 13:59 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
WIP to take home might not even build. (10.19 KB, patch)
2019-12-16 17:12 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (13.07 KB, patch)
2019-12-16 21:00 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (58.17 KB, patch)
2019-12-19 22:09 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (57.96 KB, patch)
2019-12-23 10:38 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (57.97 KB, patch)
2019-12-23 15:50 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (57.87 KB, patch)
2019-12-23 16:09 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (58.56 KB, patch)
2019-12-23 21:39 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (57.86 KB, patch)
2019-12-23 21:47 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (63.32 KB, patch)
2019-12-23 23:33 PST, Tim Horton
no flags Details | Formatted Diff | Diff
Patch (64.24 KB, patch)
2019-12-24 13:27 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (52.82 KB, patch)
2019-12-26 21:52 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (63.76 KB, patch)
2019-12-26 22:00 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (64.26 KB, patch)
2019-12-26 22:08 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (64.98 KB, patch)
2019-12-27 19:05 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (66.55 KB, patch)
2019-12-29 22:11 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (66.35 KB, patch)
2019-12-30 08:40 PST, Brady Eidson
no flags Details | Formatted Diff | Diff
Patch (66.35 KB, patch)
2019-12-30 08:53 PST, Brady Eidson
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Brady Eidson 2019-12-14 14:06:53 PST
More ScriptController refactoring in preparation for async functions

- Bundle everything needed for script evaluation into a "JavaScriptExecutionParameters" object
- Instead of returning a value, make evaluateInWorld take a completion handler to callback with the result

(For this patch, the completion handler will always be called synchronously)
Comment 1 Brady Eidson 2019-12-15 15:33:02 PST
Created attachment 385725 [details]
Patch
Comment 2 Brady Eidson 2019-12-15 15:37:30 PST
Going to be going through a series of EWS runs to find failures on the other platforms
Comment 3 Brady Eidson 2019-12-15 15:46:17 PST
Created attachment 385726 [details]
Patch
Comment 4 Brady Eidson 2019-12-15 21:48:28 PST
Created attachment 385736 [details]
Patch
Comment 5 Brady Eidson 2019-12-15 22:07:17 PST
Created attachment 385737 [details]
Patch
Comment 6 Brady Eidson 2019-12-15 22:42:36 PST
Created attachment 385738 [details]
Patch
Comment 7 Brady Eidson 2019-12-16 11:15:01 PST
Created attachment 385789 [details]
Patch
Comment 8 Brady Eidson 2019-12-16 12:47:52 PST
Created attachment 385797 [details]
Patch
Comment 9 Brady Eidson 2019-12-16 13:11:23 PST
Created attachment 385800 [details]
Patch
Comment 10 Brady Eidson 2019-12-16 13:59:36 PST
Created attachment 385808 [details]
Patch
Comment 11 Brady Eidson 2019-12-16 15:36:31 PST
The changes further required to make this a no-behavior change are becoming problematic. Resetting a bit.
Comment 12 Brady Eidson 2019-12-16 17:12:44 PST
Created attachment 385835 [details]
WIP to take home might not even build.
Comment 13 Brady Eidson 2019-12-16 21:00:40 PST
Created attachment 385852 [details]
Patch
Comment 14 Alex Christensen 2019-12-17 11:26:50 PST
Comment on attachment 385852 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=385852&action=review

I don't think this accomplishes anything.  It just makes a Function that must be called immediately.  The whole point of Functions is that they don't need to be called immediately.  Do you have plans to push this asynchrony lower?  If not, then your intended caller could just take a Function, do the work synchronously, then call the Function with the result.

> Source/WebCore/bindings/js/ExceptionDetails.h:36
> -    String sourceURL;
> +    String sourceURL { };

This does nothing because String has a default constructor.

> Source/WebCore/bindings/js/ScriptController.h:93
> +    using ResolveFunction = WTF::Function<void(ValueOrException)>;

CompletionHandler?
Comment 15 Brady Eidson 2019-12-17 12:01:55 PST
(In reply to Alex Christensen from comment #14)
> Comment on attachment 385852 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=385852&action=review
> 
> I don't think this accomplishes anything.  It just makes a Function that
> must be called immediately.  The whole point of Functions is that they don't
> need to be called immediately.  Do you have plans to push this asynchrony
> lower?  If not, then your intended caller could just take a Function, do the
> work synchronously, then call the Function with the result.
> 
> > Source/WebCore/bindings/js/ExceptionDetails.h:36
> > -    String sourceURL;
> > +    String sourceURL { };
> 
> This does nothing because String has a default constructor.

Actually it does!

On older compilers (such as High Sierra which the bots run), you can't do a partial struct initialization when some members have default initializers but others don't.

See the build failure from the penultimate patch that this ultimate patch fixes (https://ews-build.webkit.org/#/builders/7/builds/15941)

> 
> > Source/WebCore/bindings/js/ScriptController.h:93
> > +    using ResolveFunction = WTF::Function<void(ValueOrException)>;
> 
> CompletionHandler?

ResolveFunction is a carryover from a future patch - as the asynchrnocity will be waiting for a promise to resolve.

If you insist it be called CompletionHandler now I can change it, but I'll be changing it back two patches from now.
Comment 16 Brady Eidson 2019-12-17 13:05:23 PST
Discussed IRL - This was broken out from a completed larger patch, but the discussion inspired me to reanalyze the completed larger patch.
Comment 17 Brady Eidson 2019-12-19 22:08:11 PST
Repurposing
Comment 18 Brady Eidson 2019-12-19 22:09:55 PST
Created attachment 386182 [details]
Patch
Comment 19 Brady Eidson 2019-12-19 22:10:28 PST
Patch not quite for review - Trying the EWS builds, and also getting feedback from JS folks
Comment 20 Keith Miller 2019-12-19 22:39:55 PST
Comment on attachment 386182 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=386182&action=review

> Source/WebCore/bindings/js/ExceptionDetails.h:36
> +    String sourceURL { };

Does this do anything? String has a default initializer.

> Source/WebCore/bindings/js/RunJavaScriptParameters.h:32
> +enum class RunAsAsyncFunction {

I think this can be `enum class RunAsAsyncFunction : uint8_t`? But maybe EnumTraits will do this for you when XPCing?

> Source/WebCore/bindings/js/RunJavaScriptParameters.h:62
> +    String source;
> +    RunAsAsyncFunction runAsAsyncFunction;
> +    Optional<WebCore::ScriptController::ArgumentWireBytesMap> arguments;
> +    ForceUserGesture forceUserGesture;

Isn't it standard WebKit practice to put the members of a struct/class at the bottom of the struct/class?

> Source/WebCore/bindings/js/RunJavaScriptParameters.h:66
> +        encoder << source << runAsAsyncFunction << arguments << forceUserGesture;

Out of curiosity, why does encoder use << and not a variadic template call?

> Source/WebCore/bindings/js/ScriptController.cpp:643
> +        JSValue functionObject = JSExecState::profiledEvaluate(&globalObject, JSC::ProfilingReason::Other, jsSourceCode, &proxy, evaluationException);

You probably to check for an exception after this call. Then you don't need to check for !functionObject below.

> Source/WebCore/bindings/js/ScriptController.cpp:647
> +        // FIXME: JS guys say there's a more correct way to do this
> +        if (!functionObject || !functionObject.isFunction(world.vm()))
> +            break;

I leave this to Saam. I'm not exactly sure which method he was thinking of right now... maybe isCallable?

> Source/WebCore/bindings/js/ScriptController.cpp:656
> +        returnValue = JSExecState::profiledCall(&globalObject, JSC::ProfilingReason::Other, functionObject, callType, callData, &proxy, markedArguments, evaluationException);

Ugh, getting the CallData/CallType shouldn't be required to make a call into JS... Unfortunately, we don't have a profiling version of call for places where we haven't already entered the VM. Can you file a bug against JSC to add this and FIXME link to it here?
Comment 21 Alex Christensen 2019-12-20 09:44:44 PST
Comment on attachment 386182 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=386182&action=review

>> Source/WebCore/bindings/js/ExceptionDetails.h:36
>> +    String sourceURL { };
> 
> Does this do anything? String has a default initializer.

https://bugs.webkit.org/show_bug.cgi?id=205239#c15

>> Source/WebCore/bindings/js/RunJavaScriptParameters.h:32
>> +enum class RunAsAsyncFunction {
> 
> I think this can be `enum class RunAsAsyncFunction : uint8_t`? But maybe EnumTraits will do this for you when XPCing?

These should use bool as their storage type.  Then you don't need EnumTraits at all because our IPC code knows bool enum types only have two possible values.

> Source/WebCore/bindings/js/RunJavaScriptParameters.h:77
> +        RunAsAsyncFunction runAsAsyncFunction;
> +        if (!decoder.decode(runAsAsyncFunction))
> +            return WTF::nullopt;

Could you use Decoder's operator>> into an Optional<RunAsAsyncFunction>?  That's what we're trying to push our decoders towards.

> Source/WebCore/bindings/js/ScriptController.cpp:599
> +    StringBuilder functionStringBuilder;

There's got to be a more efficient way of doing this.
Comment 22 Darin Adler 2019-12-20 14:08:08 PST
Comment on attachment 386182 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=386182&action=review

> Source/WebCore/bindings/js/ScriptController.cpp:619
> +            functionStringBuilder.append(",");

Can append a character instead of a one-character string literal. Slightly more efficient.

> Source/WebCore/bindings/js/ScriptController.cpp:627
> +    functionStringBuilder.append("){");
> +    functionStringBuilder.append(parameters.source);
> +    functionStringBuilder.append("})");

Can do all three of these with a single call to append and three arguments. Slightly more efficient.
Comment 23 Brady Eidson 2019-12-23 10:18:34 PST
(In reply to Alex Christensen from comment #21)

> 
> > Source/WebCore/bindings/js/RunJavaScriptParameters.h:77
> > +        RunAsAsyncFunction runAsAsyncFunction;
> > +        if (!decoder.decode(runAsAsyncFunction))
> > +            return WTF::nullopt;
> 
> Could you use Decoder's operator>> into an Optional<RunAsAsyncFunction>? 
> That's what we're trying to push our decoders towards.

For pods like an enum, isn't that more code and more storage space?

> 
> > Source/WebCore/bindings/js/ScriptController.cpp:599
> > +    StringBuilder functionStringBuilder;
> 
> There's got to be a more efficient way of doing this.

I'll implement Darin's suggestions.
Comment 24 Brady Eidson 2019-12-23 10:25:01 PST
(In reply to Keith Miller from comment #20)
> Comment on attachment 386182 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=386182&action=review
> 
> > Source/WebCore/bindings/js/ExceptionDetails.h:36
> > +    String sourceURL { };
> 
> Does this do anything? String has a default initializer.

Alex already covered this by linking to a past comment.
But for those following along that don't click his link:

When using partial initialion lists with struct in older compilers they require explicit default initialization of all members, even if they are a class that has a default constructor.

> 
> > Source/WebCore/bindings/js/RunJavaScriptParameters.h:62
> > +    String source;
> > +    RunAsAsyncFunction runAsAsyncFunction;
> > +    Optional<WebCore::ScriptController::ArgumentWireBytesMap> arguments;
> > +    ForceUserGesture forceUserGesture;
> 
> Isn't it standard WebKit practice to put the members of a struct/class at
> the bottom of the struct/class?

I don't think we have any such guideline. I've definitely seen it all ways.
Maybe more structs lean one way than the other and we should formalize the style.

> > Source/WebCore/bindings/js/RunJavaScriptParameters.h:66
> > +        encoder << source << runAsAsyncFunction << arguments << forceUserGesture;
> 
> Out of curiosity, why does encoder use << and not a variadic template call?

We started on WK2 before C++11 was formalized and available everywhere, and IPC encoder/decoder were kind of a core feature.

So the answer is "appeal to ancient wisdom"


> > Source/WebCore/bindings/js/ScriptController.cpp:643
> > +        JSValue functionObject = JSExecState::profiledEvaluate(&globalObject, JSC::ProfilingReason::Other, jsSourceCode, &proxy, evaluationException);
> 
> You probably to check for an exception after this call. Then you don't need
> to check for !functionObject below.

Okay.

> 
> > Source/WebCore/bindings/js/ScriptController.cpp:647
> > +        // FIXME: JS guys say there's a more correct way to do this
> > +        if (!functionObject || !functionObject.isFunction(world.vm()))
> > +            break;
> 
> I leave this to Saam. I'm not exactly sure which method he was thinking of
> right now... maybe isCallable?

I guess I'll go with isCallable.

> 
> > Source/WebCore/bindings/js/ScriptController.cpp:656
> > +        returnValue = JSExecState::profiledCall(&globalObject, JSC::ProfilingReason::Other, functionObject, callType, callData, &proxy, markedArguments, evaluationException);
> 
> Ugh, getting the CallData/CallType shouldn't be required to make a call into
> JS... Unfortunately, we don't have a profiling version of call for places
> where we haven't already entered the VM. Can you file a bug against JSC to
> add this and FIXME link to it here?

Can do. Thanks!
Comment 25 Brady Eidson 2019-12-23 10:28:01 PST
(In reply to Brady Eidson from comment #24)
> (In reply to Keith Miller from comment #20)
> > 
> > > Source/WebCore/bindings/js/ScriptController.cpp:647
> > > +        // FIXME: JS guys say there's a more correct way to do this
> > > +        if (!functionObject || !functionObject.isFunction(world.vm()))
> > > +            break;
> > 
> > I leave this to Saam. I'm not exactly sure which method he was thinking of
> > right now... maybe isCallable?
> 
> I guess I'll go with isCallable.

Actually it looks like isCallable requires the CallData stuff, which you later suggest shouldn't really be required.

So I'll leave it as isFunction for now.
Comment 26 Brady Eidson 2019-12-23 10:35:10 PST
(In reply to Keith Miller from comment #20)
> Comment on attachment 386182 [details]
> 
> > Source/WebCore/bindings/js/ScriptController.cpp:656
> > +        returnValue = JSExecState::profiledCall(&globalObject, JSC::ProfilingReason::Other, functionObject, callType, callData, &proxy, markedArguments, evaluationException);
> 
> Ugh, getting the CallData/CallType shouldn't be required to make a call into
> JS... Unfortunately, we don't have a profiling version of call for places
> where we haven't already entered the VM. Can you file a bug against JSC to
> add this and FIXME link to it here?


Added to the patch, and: https://bugs.webkit.org/show_bug.cgi?id=205562
Comment 27 Brady Eidson 2019-12-23 10:38:28 PST
Created attachment 386345 [details]
Patch
Comment 28 Brady Eidson 2019-12-23 15:50:16 PST
Created attachment 386362 [details]
Patch
Comment 29 Brady Eidson 2019-12-23 16:09:10 PST
Created attachment 386365 [details]
Patch
Comment 30 Brady Eidson 2019-12-23 18:51:17 PST
The build failures on the bots:
Undefined symbols for architecture arm64:
  "JSC::getVM(JSC::JSGlobalObject*)", referenced from:
      API::SerializedScriptValue::wireBytesFromNSObject(objc_object*) in UnifiedSource19-mm.o

Unfortunately, wireBytesFromNSObject() doesn't directly call getVM, *and* both debug and release are building great for me locally.

Will explore in a bit.
Comment 31 Brady Eidson 2019-12-23 21:39:09 PST
Created attachment 386373 [details]
Patch

Commenting out the suspicious GetVM.h to try on EWS
Comment 32 Brady Eidson 2019-12-23 21:45:29 PST
(In reply to Brady Eidson from comment #31)
> Created attachment 386373 [details]
> Patch
> 
> Commenting out the suspicious GetVM.h to try on EWS

So that clearly didn't work.

GetVM.h declares the existence of getVM(), but there is no actual definition anywhere but inline in JSGlobalObjectInlines.h

Which is fine... Except the bizarre linker error says it can't be found.
Comment 33 Brady Eidson 2019-12-23 21:47:13 PST
Created attachment 386374 [details]
Patch
Comment 34 Brady Eidson 2019-12-23 22:21:28 PST
The linux build failures are now similar to an earlier much different patch in this series:

In file included from DerivedSources/WebCore/unified-sources/UnifiedSource-42f7b70e-2.cpp:6:
WebCore/xml/XPathGrammar.y: In function ‘int xpathyyparse(WebCore::XPath::Parser&)’:
WebCore/xml/XPathGrammar.y:404:34: error: expected type-specifier before ‘Path’
In file included from DerivedSources/WebCore/unified-sources/UnifiedSource-42f7b70e-2.cpp:6:
WebCore/xml/XPathGrammar.y:411:34: error: expected type-specifier before ‘Path’

I'm... really not sure how to proceed resolving that.
Comment 35 Tim Horton 2019-12-23 23:33:21 PST
Created attachment 386380 [details]
Patch
Comment 36 EWS Watchlist 2019-12-23 23:34:22 PST
Thanks for the patch. If this patch contains new public API please make sure it follows the guidelines for new WebKit2 GTK+ API. See http://trac.webkit.org/wiki/WebKitGTK/AddingNewWebKit2API
Comment 37 Tim Horton 2019-12-23 23:35:56 PST
That patch fixes the XPath complaints for me locally, and then fixes the rest of the subsequent GTK build errors (Headers.cmake, WebKitWebView, etc.)
Comment 38 Brady Eidson 2019-12-24 13:19:17 PST
(In reply to Tim Horton from comment #37)
> That patch fixes the XPath complaints for me locally, and then fixes the
> rest of the subsequent GTK build errors (Headers.cmake, WebKitWebView, etc.)

Thanks for your help!
Comment 39 Brady Eidson 2019-12-24 13:27:43 PST
Created attachment 386393 [details]
Patch
Comment 40 Darin Adler 2019-12-26 17:51:19 PST
Comment on attachment 386393 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=386393&action=review

Did not review the entire patch, but one thought.

> Source/WebCore/bindings/js/ExceptionDetails.h:36
> -    String sourceURL;
> +    String sourceURL { };

Should not make this change. This doesn’t make a difference ... sourceURL will be a null string with or without this new set of braces. Also note that the data member above named "message" behaves the same and we are not changing it.

> Source/WebCore/bindings/js/RunJavaScriptParameters.h:48
> +    RunJavaScriptParameters(const String& source, RunAsAsyncFunction runAsAsyncFunction, Optional<ArgumentWireBytesMap> arguments, ForceUserGesture forceUserGesture)

Need an overload with String&& and Optional<ArgumentWireBytesMap>&&. That can be used in the decode function template below. Without the && on the arguments, the WTFMove does not good. Without the && on source, then WTFMove can’t be done to save a little reference count churn.

> Source/WebCore/bindings/js/RunJavaScriptParameters.h:84
> +        return { { source, runAsAsyncFunction, WTFMove(arguments), forceUserGesture } };

Should add a WTFMove around source.
Comment 41 Brady Eidson 2019-12-26 21:34:54 PST
(In reply to Darin Adler from comment #40)
> Comment on attachment 386393 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=386393&action=review
> 
> Did not review the entire patch, but one thought.
> 
> > Source/WebCore/bindings/js/ExceptionDetails.h:36
> > -    String sourceURL;
> > +    String sourceURL { };
> 
> Should not make this change. This doesn’t make a difference ... sourceURL
> will be a null string with or without this new set of braces. Also note that
> the data member above named "message" behaves the same and we are not
> changing it.

This is the third time I've had to reply to this very same comment.

This change is required by older compilers (e.g. High Sierra on the bots) because they improperly handle initialization lists without it.

Here is a direct link to an error caused by omitting this change:
https://ews-build.webkit.org/#/builders/7/builds/15941/steps/7/logs/errors

> 
> > Source/WebCore/bindings/js/RunJavaScriptParameters.h:48
> > +    RunJavaScriptParameters(const String& source, RunAsAsyncFunction runAsAsyncFunction, Optional<ArgumentWireBytesMap> arguments, ForceUserGesture forceUserGesture)
> 
> Need an overload with String&& and Optional<ArgumentWireBytesMap>&&. That
> can be used in the decode function template below. Without the && on the
> arguments, the WTFMove does not good. Without the && on source, then WTFMove
> can’t be done to save a little reference count churn.
> 
> > Source/WebCore/bindings/js/RunJavaScriptParameters.h:84
> > +        return { { source, runAsAsyncFunction, WTFMove(arguments), forceUserGesture } };
> 
> Should add a WTFMove around source.

Will do both of these.
Comment 42 Brady Eidson 2019-12-26 21:52:33 PST
Created attachment 386432 [details]
Patch
Comment 43 Brady Eidson 2019-12-26 22:00:29 PST
Created attachment 386433 [details]
Patch
Comment 44 Brady Eidson 2019-12-26 22:07:14 PST
(In reply to Brady Eidson from comment #43)
> Created attachment 386433 [details]
> Patch

Confirmed with this patch that removing the sourceURL intializer definitely still breaks things on the older compilers :P
Comment 45 Brady Eidson 2019-12-26 22:08:11 PST
Created attachment 386434 [details]
Patch
Comment 46 Darin Adler 2019-12-27 09:59:57 PST
Comment on attachment 386393 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=386393&action=review

>>> Source/WebCore/bindings/js/ExceptionDetails.h:36
>>> +    String sourceURL { };
>> 
>> Should not make this change. This doesn’t make a difference ... sourceURL will be a null string with or without this new set of braces. Also note that the data member above named "message" behaves the same and we are not changing it.
> 
> This is the third time I've had to reply to this very same comment.
> 
> This change is required by older compilers (e.g. High Sierra on the bots) because they improperly handle initialization lists without it.
> 
> Here is a direct link to an error caused by omitting this change:
> https://ews-build.webkit.org/#/builders/7/builds/15941/steps/7/logs/errors

Given your experience having to respond to this comment three times, I think a brief comment on that line of source code is called for. That way someone won’t remove this in the future and then learn about why it’s there only when a High Sierra build fails.
Comment 47 Brady Eidson 2019-12-27 19:05:49 PST
Created attachment 386461 [details]
Patch
Comment 48 Brady Eidson 2019-12-27 19:07:41 PST
(In reply to Darin Adler from comment #46)
> Comment on attachment 386393 [details]
> 
> Given your experience having to respond to this comment three times, I think
> a brief comment on that line of source code is called for. That way someone
> won’t remove this in the future and then learn about why it’s there only
> when a High Sierra build fails.

Indeed! Done.

Perhaps we can all band together for a small Christmas miracle and review the parts of this patch not contained in ExceptionDetails.h :)
Comment 49 Alex Christensen 2019-12-27 19:56:29 PST
Comment on attachment 386461 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=386461&action=review

r=me with lots of nits.

> Source/WebCore/bindings/js/RunJavaScriptParameters.h:40
> +    RunJavaScriptParameters(const String& source, bool runAsAsyncFunction, Optional<ArgumentWireBytesMap> arguments, bool forceUserGesture)

I think if we remove both of these constructors and just use WTFMove in the decoder, it should do everything Darin hoped.

> Source/WebCore/bindings/js/ScriptController.cpp:569
> +    auto result = executeScriptInWorld(world, { script, false, WTF::nullopt, forceUserGesture });

It would probably be worth putting RunJavaScriptParameters here so we find it easier when we add more members to RunJavaScriptParameters that have initializers and this will continue to successfully compile.

> Source/WebCore/bindings/js/ScriptController.cpp:589
> +    default:
> +        RELEASE_ASSERT_NOT_REACHED();

I think it would be better to not have a default here.

> Source/WebCore/bindings/js/ScriptController.cpp:614
> +            errorMessage = "Unable to deserialize argument to execute asynchronous JavaScript function";
> +            break;

Should we return the exception here?

> Source/WebCore/bindings/js/ScriptController.h:99
> +    using ResolveFunction = WTF::Function<void(ValueOrException)>;

Could this be a CompletionHandler, because it needs to be called once?
WTF:: unnecessary in either case.

> Source/WebCore/xml/XPathGrammar.y:404
> +        $$ = new XPath::Path(std::unique_ptr<Expression>($1), std::unique_ptr<LocationPath>($3));

This could use a comment in the ChangeLog saying it's unrelated but necessary to continue compiling for some reason.

> Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm:904
> +    _page->runJavaScriptInMainFrame({ javaScriptString, (bool)asAsyncFunction, WTFMove(argumentsMap), (bool)forceUserGesture }, [handler](API::SerializedScriptValue* serializedScriptValue, Optional<WebCore::ExceptionDetails> details, WebKit::ScriptValueCallback::Error errorCode) {

I think we prefer !! or static_cast<bool> over c-style casting to bool.
Also, we should move handler into the capture list.

> Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivate.h:319
> +- (void)_callAsyncFunction:(NSString *)javaScriptString withArguments:(NSDictionary *)arguments completionHandler:(void (^)(id, NSError *error))completionHandler;

Could this be NSDictionary<NSString *, id> *?  It seems the keys are the variable names.

> Source/WebKit/WebProcess/WebPage/WebPage.cpp:3382
> +        send(Messages::WebPageProxy::ScriptValueCallback(dataReference, details, callbackID));

Maybe as a followup we could use sendWithAsyncReply instead of two messages and manually generating and keeping track of this identifier.

> Tools/TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm:92
> +    // Values can only be NSString, NSNumber, NSDate, NSArray, NSDictionary, and may only contain those 5 types.

The return value seems to be able to be NSNull.  Can a parameter? Either way,  I think that would be a great test case.
Also, what about NSMutableDictionary?  Also, what about custom classes that inherit from these types?
Comment 50 Brady Eidson 2019-12-27 21:56:53 PST
(In reply to Alex Christensen from comment #49)
> Comment on attachment 386461 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=386461&action=review
> 
> r=me with lots of nits.

Accepting all of the nits except for where I comment:

> 
> > Source/WebCore/bindings/js/ScriptController.cpp:589
> > +    default:
> > +        RELEASE_ASSERT_NOT_REACHED();
> 
> I think it would be better to not have a default here.

This was to placate one of the windows or linux compilers that complained about lack of return statement. *sigh*

> > Source/WebCore/bindings/js/ScriptController.cpp:614
> > +            errorMessage = "Unable to deserialize argument to execute asynchronous JavaScript function";
> > +            break;
> 
> Should we return the exception here?

I waffled on this.

Certainly not just the raw exception, as it would appear as if the function executed with a bizarre error.

So I decided to skip it because - since we validate the arguments up front in the UI process - I don't think we'll ever actually hit this.

> 
> > Tools/TestWebKitAPI/Tests/WebKitCocoa/AsyncFunction.mm:92
> > +    // Values can only be NSString, NSNumber, NSDate, NSArray, NSDictionary, and may only contain those 5 types.
> 
> The return value seems to be able to be NSNull.  Can a parameter? 

Totally. Dunno how I missed that since I literally copied the comment from WKScriptMessage.h

> Also, what about NSMutableDictionary?

Since it's a subclass of NSDictionary, yes. I'll add a test.

> Also, what about custom classes that inherit from these types?

For string, number, and date. subclasses will work fine. The base class accessors will be used to serialize the argument to the javascript type.

Custom subclassing of NSArray and NSDictionary is a nonstarter for outside devs because of class clustering, etc etc.

I'll update the comment.
Comment 51 Brady Eidson 2019-12-27 22:00:44 PST
(In reply to Brady Eidson from comment #50)
> (In reply to Alex Christensen from comment #49)
> 
> > Also, what about custom classes that inherit from these types?
> 
> For string, number, and date. subclasses will work fine. The base class
> accessors will be used to serialize the argument to the javascript type.
> 
> Custom subclassing of NSArray and NSDictionary is a nonstarter for outside
> devs because of class clustering, etc etc.
> 
> I'll update the comment.

I was totally wrong; NSString, NSNumber, and NSDate are also all class clusters that are difficult to subclass.

I'm gonna leave it as-is (besides adding NSNull)
Comment 52 Brady Eidson 2019-12-29 22:03:41 PST
(In reply to Alex Christensen from comment #49)
> 
> > Source/WebCore/bindings/js/RunJavaScriptParameters.h:40
> > +    RunJavaScriptParameters(const String& source, bool runAsAsyncFunction, Optional<ArgumentWireBytesMap> arguments, bool forceUserGesture)
> 
> I think if we remove both of these constructors and just use WTFMove in the
> decoder, it should do everything Darin hoped.

More followup:

The key to having these at all was the constructor that took the bools (which the API layers speak) and converted them to the enums (which IPC and WebCore now speak)

By adding the bool form, you lose the implicit constructor, so I needed to add that one too.

I've left them and added all the WTFMoves
Comment 53 Brady Eidson 2019-12-29 22:11:06 PST
Created attachment 386509 [details]
Patch
Comment 54 Brady Eidson 2019-12-30 08:40:53 PST
Created attachment 386535 [details]
Patch
Comment 55 Brady Eidson 2019-12-30 08:53:50 PST
Created attachment 386536 [details]
Patch
Comment 56 WebKit Commit Bot 2019-12-30 12:23:27 PST
Comment on attachment 386536 [details]
Patch

Clearing flags on attachment: 386536

Committed r253950: <https://trac.webkit.org/changeset/253950>
Comment 57 WebKit Commit Bot 2019-12-30 12:23:30 PST
All reviewed patches have been landed.  Closing bug.
Comment 58 Radar WebKit Bug Importer 2019-12-30 12:27:09 PST
<rdar://problem/58245873>
Comment 59 Saam Barati 2019-12-30 12:50:12 PST
Comment on attachment 386536 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=386536&action=review

> Source/WebCore/bindings/js/ScriptController.cpp:649
> +        if (!functionObject || !functionObject.isFunction(world.vm())) {

This check is ok. I was mistaken. This isn't the correct way to check if an arbitrary value is "callable". However, the value here isn't arbitrary. You're using a function in your text that you're evaluating. So isFunction is sufficient. Sorry for getting confused.
Comment 60 Brady Eidson 2020-01-03 09:07:01 PST
*** Bug 134330 has been marked as a duplicate of this bug. ***