<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[200555] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/200555">200555</a></dd>
<dt>Author</dt> <dd>darin@apple.com</dd>
<dt>Date</dt> <dd>2016-05-08 09:54:09 -0700 (Sun, 08 May 2016)</dd>
</dl>
<h3>Log Message</h3>
<pre>Correct dictionary bindings handling of optional, null, and undefined
https://bugs.webkit.org/show_bug.cgi?id=157463
Reviewed by Chris Dumez.
Source/WebCore:
* bindings/js/JSDOMBinding.cpp:
(WebCore::propertyValue): Deleted.
* bindings/js/JSDOMBinding.h: Deleted propertyValue, not all that helpful for now.
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateDictionaryImplementationContent): Added a new early exit for convert to
a dictionary type when the value is undefined or null and all members are either
optional or have a default value. This returns the default values for everything
without raising an exception. Added checking that requires that the dictionary
argument is an object and not a regular expression, since that's also called for
in the latest draft of the Web IDL specification. This ends up speeding up the
code a bit since we now use JSObject::get for properties instead of JSValue::get.
(GenerateParametersCheck): Renamed some local variables. Taught the code that
optional dictionaries all have a default value; before it was doing that for the
type "Dictionary" but not the real dictionary types (IsDictionaryType).
* bindings/scripts/test/JS/JSTestObj.cpp: Regenerated.
* css/FontFace.cpp:
(WebCore::FontFace::create): Changed argument to be Descriptors instead of
Optional<Descriptors>. It would have compiled the other way, but there is now
no caller that will pass a null. Because the IDL dictionary support was new,
this was the only place that was doing it wrong. Good that we "nipped it in the bud"
before doing this in more places.
* css/FontFace.h: Ditto.
LayoutTests:
* fast/dom/MutationObserver/observe-exceptions-expected.txt: Reverted that
change to expect a more specific TypeError just as it was a day ago before
my last patch. The TypeError is back to being a problem with the specifics
of the arguments passed rather than a problem with null and undefined
themselves being invalid.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsfastdomMutationObserverobserveexceptionsexpectedtxt">trunk/LayoutTests/fast/dom/MutationObserver/observe-exceptions-expected.txt</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMBindingcpp">trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMBindingh">trunk/Source/WebCore/bindings/js/JSDOMBinding.h</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm">trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm</a></li>
<li><a href="#trunkSourceWebCorebindingsscriptstestJSJSTestObjcpp">trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp</a></li>
<li><a href="#trunkSourceWebCorecssFontFacecpp">trunk/Source/WebCore/css/FontFace.cpp</a></li>
<li><a href="#trunkSourceWebCorecssFontFaceh">trunk/Source/WebCore/css/FontFace.h</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (200554 => 200555)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-05-08 15:22:36 UTC (rev 200554)
+++ trunk/LayoutTests/ChangeLog        2016-05-08 16:54:09 UTC (rev 200555)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-05-08 Darin Adler <darin@apple.com>
+
+ Correct dictionary bindings handling of optional, null, and undefined
+ https://bugs.webkit.org/show_bug.cgi?id=157463
+
+ Reviewed by Chris Dumez.
+
+ * fast/dom/MutationObserver/observe-exceptions-expected.txt: Reverted that
+ change to expect a more specific TypeError just as it was a day ago before
+ my last patch. The TypeError is back to being a problem with the specifics
+ of the arguments passed rather than a problem with null and undefined
+ themselves being invalid.
+
</ins><span class="cx"> 2016-05-07 Darin Adler <darin@apple.com>
</span><span class="cx">
</span><span class="cx"> Change MutationObserver::observe to take an IDL dictionary, rather than WebCore::Dictionary
</span></span></pre></div>
<a id="trunkLayoutTestsfastdomMutationObserverobserveexceptionsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/fast/dom/MutationObserver/observe-exceptions-expected.txt (200554 => 200555)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/fast/dom/MutationObserver/observe-exceptions-expected.txt        2016-05-08 15:22:36 UTC (rev 200554)
+++ trunk/LayoutTests/fast/dom/MutationObserver/observe-exceptions-expected.txt        2016-05-08 16:54:09 UTC (rev 200555)
</span><span class="lines">@@ -7,8 +7,8 @@
</span><span class="cx"> PASS observer.observe(null) threw exception TypeError: Not enough arguments.
</span><span class="cx"> PASS observer.observe(undefined) threw exception TypeError: Not enough arguments.
</span><span class="cx"> PASS observer.observe(document.body) threw exception TypeError: Not enough arguments.
</span><del>-PASS observer.observe(document.body, null) threw exception TypeError: null is not an object (evaluating 'observer.observe(document.body, null)').
-PASS observer.observe(document.body, undefined) threw exception TypeError: undefined is not an object (evaluating 'observer.observe(document.body, undefined)').
</del><ins>+PASS observer.observe(document.body, null) threw exception TypeError: Type error.
+PASS observer.observe(document.body, undefined) threw exception TypeError: Type error.
</ins><span class="cx"> PASS observer.observe(null, {attributes: true}) threw exception TypeError: Type error.
</span><span class="cx"> PASS observer.observe(undefined, {attributes: true}) threw exception TypeError: Type error.
</span><span class="cx"> PASS observer.observe(document.body, {subtree: true}) threw exception TypeError: Type error.
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (200554 => 200555)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-05-08 15:22:36 UTC (rev 200554)
+++ trunk/Source/WebCore/ChangeLog        2016-05-08 16:54:09 UTC (rev 200555)
</span><span class="lines">@@ -1,3 +1,36 @@
</span><ins>+2016-05-08 Darin Adler <darin@apple.com>
+
+ Correct dictionary bindings handling of optional, null, and undefined
+ https://bugs.webkit.org/show_bug.cgi?id=157463
+
+ Reviewed by Chris Dumez.
+
+ * bindings/js/JSDOMBinding.cpp:
+ (WebCore::propertyValue): Deleted.
+ * bindings/js/JSDOMBinding.h: Deleted propertyValue, not all that helpful for now.
+
+ * bindings/scripts/CodeGeneratorJS.pm:
+ (GenerateDictionaryImplementationContent): Added a new early exit for convert to
+ a dictionary type when the value is undefined or null and all members are either
+ optional or have a default value. This returns the default values for everything
+ without raising an exception. Added checking that requires that the dictionary
+ argument is an object and not a regular expression, since that's also called for
+ in the latest draft of the Web IDL specification. This ends up speeding up the
+ code a bit since we now use JSObject::get for properties instead of JSValue::get.
+ (GenerateParametersCheck): Renamed some local variables. Taught the code that
+ optional dictionaries all have a default value; before it was doing that for the
+ type "Dictionary" but not the real dictionary types (IsDictionaryType).
+
+ * bindings/scripts/test/JS/JSTestObj.cpp: Regenerated.
+
+ * css/FontFace.cpp:
+ (WebCore::FontFace::create): Changed argument to be Descriptors instead of
+ Optional<Descriptors>. It would have compiled the other way, but there is now
+ no caller that will pass a null. Because the IDL dictionary support was new,
+ this was the only place that was doing it wrong. Good that we "nipped it in the bud"
+ before doing this in more places.
+ * css/FontFace.h: Ditto.
+
</ins><span class="cx"> 2016-05-08 David Kilzer <ddkilzer@apple.com>
</span><span class="cx">
</span><span class="cx"> ThreadSanitizer: Data race and thread leak in WebCore::ScrollingThread::createThreadIfNeeded
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMBindingcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp (200554 => 200555)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp        2016-05-08 15:22:36 UTC (rev 200554)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.cpp        2016-05-08 16:54:09 UTC (rev 200555)
</span><span class="lines">@@ -840,9 +840,4 @@
</span><span class="cx"> return CallType::Host;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-JSValue propertyValue(ExecState& state, JSValue value, const char* propertyName)
-{
- return value.get(&state, Identifier::fromString(&state, propertyName));
-}
-
</del><span class="cx"> } // namespace WebCore
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMBindingh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMBinding.h (200554 => 200555)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMBinding.h        2016-05-08 15:22:36 UTC (rev 200554)
+++ trunk/Source/WebCore/bindings/js/JSDOMBinding.h        2016-05-08 16:54:09 UTC (rev 200555)
</span><span class="lines">@@ -298,8 +298,6 @@
</span><span class="cx"> template<typename DOMClass> const JSC::HashTableValue* getStaticValueSlotEntryWithoutCaching(JSC::ExecState*, JSC::PropertyName);
</span><span class="cx"> template<JSC::NativeFunction, int length> JSC::EncodedJSValue nonCachingStaticFunctionGetter(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
</span><span class="cx">
</span><del>-JSC::JSValue propertyValue(JSC::ExecState&, JSC::JSValue, const char* propertyName);
-
</del><span class="cx"> // Inline functions and template definitions.
</span><span class="cx">
</span><span class="cx"> inline JSC::Structure* DOMConstructorObject::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptsCodeGeneratorJSpm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (200554 => 200555)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2016-05-08 15:22:36 UTC (rev 200554)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2016-05-08 16:54:09 UTC (rev 200555)
</span><span class="lines">@@ -958,8 +958,27 @@
</span><span class="cx"> # FIXME: A little ugly to have this be a side effect instead of a return value.
</span><span class="cx"> AddToImplIncludes("JSDOMConvert.h");
</span><span class="cx">
</span><ins>+ my $defaultValues = "";
+ my $comma = "";
+ foreach my $member (@{$dictionary->members}) {
+ if (!$member->isOptional) {
+ $defaultValues = "";
+ last;
+ }
+ $defaultValues .= $comma . (defined $member->default ? $member->default : "Nullopt");
+ $comma = ", ";
+ }
+
</ins><span class="cx"> $result .= "template<> $className convert<$className>(ExecState& state, JSValue value)\n";
</span><span class="cx"> $result .= "{\n";
</span><ins>+ $result .= " if (value.isUndefinedOrNull())\n" if $defaultValues;
+ $result .= " return { " . $defaultValues . " };\n" if $defaultValues;
+ $result .= " auto* object = value.getObject();\n";
+ $result .= " if (UNLIKELY(!object || object->type() == RegExpObjectType)) {\n";
+ $result .= " throwTypeError(&state);\n";
+ $result .= " return { };\n";
+ $result .= " }\n";
+
</ins><span class="cx"> my $needExceptionCheck = 0;
</span><span class="cx"> foreach my $member (@{$dictionary->members}) {
</span><span class="cx"> if ($needExceptionCheck) {
</span><span class="lines">@@ -970,16 +989,18 @@
</span><span class="cx"> my $function = $member->isOptional ? "convertOptional" : "convert";
</span><span class="cx"> my $defaultValueWithLeadingComma = $member->isOptional && defined $member->default ? ", " . $member->default : "";
</span><span class="cx"> $result .= " auto " . $member->name . " = " . $function . "<" . GetNativeTypeFromSignature($interface, $member) . ">"
</span><del>- . "(state, propertyValue(state, value, \"" . $member->name . "\")" . $defaultValueWithLeadingComma . ");\n";
</del><ins>+ . "(state, object->get(&state, Identifier::fromString(&state, \"" . $member->name . "\"))" . $defaultValueWithLeadingComma . ");\n";
</ins><span class="cx"> $needExceptionCheck = 1;
</span><span class="cx"> }
</span><del>- $result .= " return { ";
- my $comma = "";
</del><ins>+
+ my $arguments = "";
+ $comma = "";
</ins><span class="cx"> foreach my $member (@{$dictionary->members}) {
</span><del>- $result .= $comma . "WTFMove(" . $member->name . ")";
</del><ins>+ $arguments .= $comma . "WTFMove(" . $member->name . ")";
</ins><span class="cx"> $comma = ", ";
</span><span class="cx"> }
</span><del>- $result .= " };\n";
</del><ins>+
+ $result .= " return { " . $arguments . " };\n";
</ins><span class="cx"> $result .= "}\n\n";
</span><span class="cx">
</span><span class="cx"> $result .= "#endif\n\n" if $conditionalString;
</span><span class="lines">@@ -3592,90 +3613,90 @@
</span><span class="cx"> $implIncludes{"ExceptionCode.h"} = 1;
</span><span class="cx"> $implIncludes{"JSDOMBinding.h"} = 1;
</span><span class="cx">
</span><del>- my $argsIndex = 0;
</del><ins>+ my $argumentIndex = 0;
</ins><span class="cx"> foreach my $parameter (@{$function->parameters}) {
</span><del>- my $argType = $parameter->type;
</del><ins>+ my $type = $parameter->type;
</ins><span class="cx">
</span><del>- die "Optional parameters of non-nullable wrapper types are not supported" if $parameter->isOptional && !$parameter->isNullable && $codeGenerator->IsWrapperType($argType);
</del><ins>+ die "Optional parameters of non-nullable wrapper types are not supported" if $parameter->isOptional && !$parameter->isNullable && $codeGenerator->IsWrapperType($type);
</ins><span class="cx">
</span><span class="cx"> if ($parameter->isOptional && !defined($parameter->default)) {
</span><span class="cx"> # As per Web IDL, optional dictionary parameters are always considered to have a default value of an empty dictionary, unless otherwise specified.
</span><del>- $parameter->default("[]") if $argType eq "Dictionary";
-
</del><ins>+ $parameter->default("[]") if $type eq "Dictionary" or $codeGenerator->IsDictionaryType($type);
+
</ins><span class="cx"> # We use undefined as default value for optional parameters of type 'any' unless specified otherwise.
</span><del>- $parameter->default("undefined") if $argType eq "any";
</del><ins>+ $parameter->default("undefined") if $type eq "any";
</ins><span class="cx">
</span><span class="cx"> # We use the null string as default value for parameters of type DOMString unless specified otherwise.
</span><del>- $parameter->default("null") if $argType eq "DOMString";
</del><ins>+ $parameter->default("null") if $type eq "DOMString";
</ins><span class="cx">
</span><span class="cx"> # As per Web IDL, passing undefined for a nullable parameter is treated as null. Therefore, use null as
</span><span class="cx"> # default value for nullable parameters unless otherwise specified.
</span><span class="cx"> $parameter->default("null") if $parameter->isNullable;
</span><span class="cx">
</span><span class="cx"> # For callback parameters, the generated bindings treat undefined as null, so use null as implicit default value.
</span><del>- $parameter->default("null") if $codeGenerator->IsCallbackInterface($argType);
</del><ins>+ $parameter->default("null") if $codeGenerator->IsCallbackInterface($type);
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> my $name = $parameter->name;
</span><span class="cx"> my $value = $name;
</span><span class="cx">
</span><del>- if ($codeGenerator->IsCallbackInterface($argType)) {
- my $callbackClassName = GetCallbackClassName($argType);
</del><ins>+ if ($codeGenerator->IsCallbackInterface($type)) {
+ my $callbackClassName = GetCallbackClassName($type);
</ins><span class="cx"> $implIncludes{"$callbackClassName.h"} = 1;
</span><span class="cx"> if ($parameter->isOptional) {
</span><del>- push(@$outputArray, " RefPtr<$argType> $name;\n");
- push(@$outputArray, " if (!state->argument($argsIndex).isUndefinedOrNull()) {\n");
- if ($codeGenerator->IsFunctionOnlyCallbackInterface($argType)) {
- push(@$outputArray, " if (!state->uncheckedArgument($argsIndex).isFunction())\n");
</del><ins>+ push(@$outputArray, " RefPtr<$type> $name;\n");
+ push(@$outputArray, " if (!state->argument($argumentIndex).isUndefinedOrNull()) {\n");
+ if ($codeGenerator->IsFunctionOnlyCallbackInterface($type)) {
+ push(@$outputArray, " if (!state->uncheckedArgument($argumentIndex).isFunction())\n");
</ins><span class="cx"> } else {
</span><del>- push(@$outputArray, " if (!state->uncheckedArgument($argsIndex).isObject())\n");
</del><ins>+ push(@$outputArray, " if (!state->uncheckedArgument($argumentIndex).isObject())\n");
</ins><span class="cx"> }
</span><del>- push(@$outputArray, " return throwArgumentMustBeFunctionError(*state, $argsIndex, \"$name\", \"$interfaceName\", $quotedFunctionName);\n");
</del><ins>+ push(@$outputArray, " return throwArgumentMustBeFunctionError(*state, $argumentIndex, \"$name\", \"$interfaceName\", $quotedFunctionName);\n");
</ins><span class="cx"> if ($function->isStatic) {
</span><span class="cx"> AddToImplIncludes("CallbackFunction.h");
</span><del>- push(@$outputArray, " $name = createFunctionOnlyCallback<${callbackClassName}>(state, jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), state->uncheckedArgument($argsIndex));\n");
</del><ins>+ push(@$outputArray, " $name = createFunctionOnlyCallback<${callbackClassName}>(state, jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), state->uncheckedArgument($argumentIndex));\n");
</ins><span class="cx"> } else {
</span><del>- push(@$outputArray, " $name = ${callbackClassName}::create(asObject(state->uncheckedArgument($argsIndex)), castedThis->globalObject());\n");
</del><ins>+ push(@$outputArray, " $name = ${callbackClassName}::create(asObject(state->uncheckedArgument($argumentIndex)), castedThis->globalObject());\n");
</ins><span class="cx"> }
</span><span class="cx"> push(@$outputArray, " }\n");
</span><span class="cx"> } else {
</span><del>- if ($codeGenerator->IsFunctionOnlyCallbackInterface($argType)) {
- push(@$outputArray, " if (UNLIKELY(!state->argument($argsIndex).isFunction()))\n");
</del><ins>+ if ($codeGenerator->IsFunctionOnlyCallbackInterface($type)) {
+ push(@$outputArray, " if (UNLIKELY(!state->argument($argumentIndex).isFunction()))\n");
</ins><span class="cx"> } else {
</span><del>- push(@$outputArray, " if (UNLIKELY(!state->argument($argsIndex).isObject()))\n");
</del><ins>+ push(@$outputArray, " if (UNLIKELY(!state->argument($argumentIndex).isObject()))\n");
</ins><span class="cx"> }
</span><del>- push(@$outputArray, " return throwArgumentMustBeFunctionError(*state, $argsIndex, \"$name\", \"$interfaceName\", $quotedFunctionName);\n");
</del><ins>+ push(@$outputArray, " return throwArgumentMustBeFunctionError(*state, $argumentIndex, \"$name\", \"$interfaceName\", $quotedFunctionName);\n");
</ins><span class="cx"> if ($function->isStatic) {
</span><span class="cx"> AddToImplIncludes("CallbackFunction.h");
</span><del>- push(@$outputArray, " RefPtr<$argType> $name = createFunctionOnlyCallback<${callbackClassName}>(state, jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), state->uncheckedArgument($argsIndex));\n");
</del><ins>+ push(@$outputArray, " RefPtr<$type> $name = createFunctionOnlyCallback<${callbackClassName}>(state, jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject()), state->uncheckedArgument($argumentIndex));\n");
</ins><span class="cx"> } else {
</span><del>- push(@$outputArray, " RefPtr<$argType> $name = ${callbackClassName}::create(asObject(state->uncheckedArgument($argsIndex)), castedThis->globalObject());\n");
</del><ins>+ push(@$outputArray, " RefPtr<$type> $name = ${callbackClassName}::create(asObject(state->uncheckedArgument($argumentIndex)), castedThis->globalObject());\n");
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx"> $value = "WTFMove($name)";
</span><span class="cx"> } elsif ($parameter->isVariadic) {
</span><span class="cx"> my $nativeElementType;
</span><del>- if ($argType eq "DOMString") {
</del><ins>+ if ($type eq "DOMString") {
</ins><span class="cx"> $nativeElementType = "String";
</span><span class="cx"> } else {
</span><del>- $nativeElementType = GetNativeType($interface, $argType);
</del><ins>+ $nativeElementType = GetNativeType($interface, $type);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- if (!IsNativeType($argType)) {
</del><ins>+ if (!IsNativeType($type)) {
</ins><span class="cx"> push(@$outputArray, " Vector<$nativeElementType> $name;\n");
</span><del>- push(@$outputArray, " for (unsigned i = $argsIndex, count = state->argumentCount(); i < count; ++i) {\n");
- push(@$outputArray, " if (!state->uncheckedArgument(i).inherits(JS${argType}::info()))\n");
- push(@$outputArray, " return throwArgumentTypeError(*state, i, \"$name\", \"$interfaceName\", $quotedFunctionName, \"$argType\");\n");
- push(@$outputArray, " $name.append(JS${argType}::toWrapped(state->uncheckedArgument(i)));\n");
</del><ins>+ push(@$outputArray, " for (unsigned i = $argumentIndex, count = state->argumentCount(); i < count; ++i) {\n");
+ push(@$outputArray, " if (!state->uncheckedArgument(i).inherits(JS${type}::info()))\n");
+ push(@$outputArray, " return throwArgumentTypeError(*state, i, \"$name\", \"$interfaceName\", $quotedFunctionName, \"$type\");\n");
+ push(@$outputArray, " $name.append(JS${type}::toWrapped(state->uncheckedArgument(i)));\n");
</ins><span class="cx"> push(@$outputArray, " }\n")
</span><span class="cx"> } else {
</span><del>- push(@$outputArray, " Vector<$nativeElementType> $name = toNativeArguments<$nativeElementType>(state, $argsIndex);\n");
</del><ins>+ push(@$outputArray, " Vector<$nativeElementType> $name = toNativeArguments<$nativeElementType>(state, $argumentIndex);\n");
</ins><span class="cx"> # Check if the type conversion succeeded.
</span><span class="cx"> push(@$outputArray, " if (UNLIKELY(state->hadException()))\n");
</span><span class="cx"> push(@$outputArray, " return JSValue::encode(jsUndefined());\n");
</span><span class="cx"> }
</span><del>- } elsif ($codeGenerator->IsEnumType($argType)) {
- my $className = GetEnumerationClassName($interface, $argType);
</del><ins>+ } elsif ($codeGenerator->IsEnumType($type)) {
+ my $className = GetEnumerationClassName($interface, $type);
</ins><span class="cx">
</span><span class="cx"> $implIncludes{"<runtime/Error.h>"} = 1;
</span><span class="cx">
</span><span class="lines">@@ -3690,7 +3711,7 @@
</span><span class="cx"> $defineOptionalValue = $name;
</span><span class="cx"> }
</span><span class="cx">
</span><del>- push(@$outputArray, " auto ${name}Value = state->argument($argsIndex);\n");
</del><ins>+ push(@$outputArray, " auto ${name}Value = state->argument($argumentIndex);\n");
</ins><span class="cx"> push(@$outputArray, " $nativeType $name;\n");
</span><span class="cx">
</span><span class="cx"> if ($parameter->isOptional) {
</span><span class="lines">@@ -3707,7 +3728,7 @@
</span><span class="cx"> push(@$outputArray, "$indent if (UNLIKELY(state->hadException()))\n");
</span><span class="cx"> push(@$outputArray, "$indent return JSValue::encode(jsUndefined());\n");
</span><span class="cx"> push(@$outputArray, "$indent if (UNLIKELY(!$optionalValue))\n");
</span><del>- push(@$outputArray, "$indent return throwArgumentMustBeEnumError(*state, $argsIndex, \"$name\", \"$interfaceName\", $quotedFunctionName, expectedEnumerationValues<$className>());\n");
</del><ins>+ push(@$outputArray, "$indent return throwArgumentMustBeEnumError(*state, $argumentIndex, \"$name\", \"$interfaceName\", $quotedFunctionName, expectedEnumerationValues<$className>());\n");
</ins><span class="cx"> push(@$outputArray, "$indent $name = optionalValue.value();\n") if $optionalValue ne $name;
</span><span class="cx">
</span><span class="cx"> push(@$outputArray, " }\n") if $indent ne "";
</span><span class="lines">@@ -3720,16 +3741,16 @@
</span><span class="cx"> if ($function->signature->extendedAttributes->{"StrictTypeChecking"}) {
</span><span class="cx"> $implIncludes{"<runtime/Error.h>"} = 1;
</span><span class="cx">
</span><del>- my $argValue = "state->argument($argsIndex)";
- if ($codeGenerator->IsWrapperType($argType)) {
- push(@$outputArray, " if (UNLIKELY(!${argValue}.isUndefinedOrNull() && !${argValue}.inherits(JS${argType}::info())))\n");
- push(@$outputArray, " return throwArgumentTypeError(*state, $argsIndex, \"$name\", \"$interfaceName\", $quotedFunctionName, \"$argType\");\n");
</del><ins>+ my $argValue = "state->argument($argumentIndex)";
+ if ($codeGenerator->IsWrapperType($type)) {
+ push(@$outputArray, " if (UNLIKELY(!${argValue}.isUndefinedOrNull() && !${argValue}.inherits(JS${type}::info())))\n");
+ push(@$outputArray, " return throwArgumentTypeError(*state, $argumentIndex, \"$name\", \"$interfaceName\", $quotedFunctionName, \"$type\");\n");
</ins><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> if ($parameter->extendedAttributes->{"RequiresExistingAtomicString"}) {
</span><span class="cx"> # FIXME: This could be made slightly more efficient if we added an AtomicString(RefPtr<AtomicStringImpl>&&) constructor and removed the call to get() here.
</span><del>- push(@$outputArray, " AtomicString $name = state->argument($argsIndex).toString(state)->toExistingAtomicString(state).get();\n");
</del><ins>+ push(@$outputArray, " AtomicString $name = state->argument($argumentIndex).toString(state)->toExistingAtomicString(state).get();\n");
</ins><span class="cx"> push(@$outputArray, " if ($name.isNull())\n");
</span><span class="cx"> push(@$outputArray, " return JSValue::encode(jsNull());\n");
</span><span class="cx"> push(@$outputArray, " if (UNLIKELY(state->hadException()))\n");
</span><span class="lines">@@ -3739,11 +3760,11 @@
</span><span class="cx"> my $inner;
</span><span class="cx"> my $nativeType = GetNativeTypeFromSignature($interface, $parameter);
</span><span class="cx">
</span><del>- if ($parameter->isOptional && defined($parameter->default) && !WillConvertUndefinedToDefaultParameterValue($parameter->type, $parameter->default)) {
</del><ins>+ if ($parameter->isOptional && defined($parameter->default) && !WillConvertUndefinedToDefaultParameterValue($type, $parameter->default)) {
</ins><span class="cx"> my $defaultValue = $parameter->default;
</span><span class="cx">
</span><span class="cx"> # String-related optimizations.
</span><del>- if ($parameter->type eq "DOMString") {
</del><ins>+ if ($type eq "DOMString") {
</ins><span class="cx"> my $useAtomicString = $parameter->extendedAttributes->{"AtomicString"};
</span><span class="cx"> if ($defaultValue eq "null") {
</span><span class="cx"> $defaultValue = $useAtomicString ? "nullAtom" : "String()";
</span><span class="lines">@@ -3759,16 +3780,15 @@
</span><span class="cx"> $defaultValue = "JSValue::JSUndefined" if $defaultValue eq "undefined";
</span><span class="cx"> }
</span><span class="cx">
</span><del>- $outer = "state->argument($argsIndex).isUndefined() ? $defaultValue : ";
- $inner = "state->uncheckedArgument($argsIndex)";
</del><ins>+ $outer = "state->argument($argumentIndex).isUndefined() ? $defaultValue : ";
+ $inner = "state->uncheckedArgument($argumentIndex)";
</ins><span class="cx"> } elsif ($parameter->isOptional && !defined($parameter->default)) {
</span><del>- # Use WTF::Optional<>() for optional parameters that are missing or undefined and that do not have
- # a default value in the IDL.
- $outer = "state->argument($argsIndex).isUndefined() ? Optional<$nativeType>() : ";
- $inner = "state->uncheckedArgument($argsIndex)";
</del><ins>+ # Use WTF::Optional<>() for optional parameters that are missing or undefined and that do not have a default value in the IDL.
+ $outer = "state->argument($argumentIndex).isUndefined() ? Optional<$nativeType>() : ";
+ $inner = "state->uncheckedArgument($argumentIndex)";
</ins><span class="cx"> } else {
</span><span class="cx"> $outer = "";
</span><del>- $inner = "state->argument($argsIndex)";
</del><ins>+ $inner = "state->argument($argumentIndex)";
</ins><span class="cx"> }
</span><span class="cx"> my ($nativeValue, $mayThrowException) = JSValueToNative($interface, $parameter, $inner, $function->signature->extendedAttributes->{"Conditional"});
</span><span class="cx"> push(@$outputArray, " auto $name = ${outer}${nativeValue};\n");
</span><span class="lines">@@ -3779,7 +3799,7 @@
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><del>- my $isTearOff = $codeGenerator->IsSVGTypeNeedingTearOff($argType) && $interfaceName !~ /List$/;
</del><ins>+ my $isTearOff = $codeGenerator->IsSVGTypeNeedingTearOff($type) && $interfaceName !~ /List$/;
</ins><span class="cx"> my $shouldPassByReference = ShouldPassWrapperByReference($parameter, $interface);
</span><span class="cx"> if ($isTearOff or $shouldPassByReference) {
</span><span class="cx"> push(@$outputArray, " if (UNLIKELY(!$name))\n");
</span><span class="lines">@@ -3787,13 +3807,13 @@
</span><span class="cx"> $value = $isTearOff ? "$name->propertyReference()" : "*$name";
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if ($codeGenerator->IsTypedArrayType($argType) and $argType ne "ArrayBuffer") {
</del><ins>+ if ($codeGenerator->IsTypedArrayType($type) and $parameter->type ne "ArrayBuffer") {
</ins><span class="cx"> $value = $shouldPassByReference ? "$name.releaseNonNull()" : "WTFMove($name)";
</span><span class="cx"> }
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> push(@arguments, $value);
</span><del>- $argsIndex++;
</del><ins>+ $argumentIndex++;
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> push @arguments, GenerateReturnParameters($function);
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsscriptstestJSJSTestObjcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp (200554 => 200555)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp        2016-05-08 15:22:36 UTC (rev 200554)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp        2016-05-08 16:54:09 UTC (rev 200555)
</span><span class="lines">@@ -486,28 +486,47 @@
</span><span class="cx">
</span><span class="cx"> template<> TestObj::ShadowRootInit convert<TestObj::ShadowRootInit>(ExecState& state, JSValue value)
</span><span class="cx"> {
</span><del>- auto mode = convert<TestObj::ShadowRootMode>(state, propertyValue(state, value, "mode"));
</del><ins>+ auto* object = value.getObject();
+ if (UNLIKELY(!object || object->type() == RegExpObjectType)) {
+ throwTypeError(&state);
+ return { };
+ }
+ auto mode = convert<TestObj::ShadowRootMode>(state, object->get(&state, Identifier::fromString(&state, "mode")));
</ins><span class="cx"> return { WTFMove(mode) };
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template<> TestObj::FontFaceDescriptors convert<TestObj::FontFaceDescriptors>(ExecState& state, JSValue value)
</span><span class="cx"> {
</span><del>- auto style = convertOptional<String>(state, propertyValue(state, value, "style"), "normal");
</del><ins>+ if (value.isUndefinedOrNull())
+ return { "normal", "U+0-10FFFF" };
+ auto* object = value.getObject();
+ if (UNLIKELY(!object || object->type() == RegExpObjectType)) {
+ throwTypeError(&state);
+ return { };
+ }
+ auto style = convertOptional<String>(state, object->get(&state, Identifier::fromString(&state, "style")), "normal");
</ins><span class="cx"> if (UNLIKELY(state.hadException()))
</span><span class="cx"> return { };
</span><del>- auto unicodeRange = convertOptional<String>(state, propertyValue(state, value, "unicodeRange"), "U+0-10FFFF");
</del><ins>+ auto unicodeRange = convertOptional<String>(state, object->get(&state, Identifier::fromString(&state, "unicodeRange")), "U+0-10FFFF");
</ins><span class="cx"> return { WTFMove(style), WTFMove(unicodeRange) };
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> template<> TestObj::MutationObserverInit convert<TestObj::MutationObserverInit>(ExecState& state, JSValue value)
</span><span class="cx"> {
</span><del>- auto childList = convertOptional<bool>(state, propertyValue(state, value, "childList"), false);
</del><ins>+ if (value.isUndefinedOrNull())
+ return { false, Nullopt, Nullopt };
+ auto* object = value.getObject();
+ if (UNLIKELY(!object || object->type() == RegExpObjectType)) {
+ throwTypeError(&state);
+ return { };
+ }
+ auto childList = convertOptional<bool>(state, object->get(&state, Identifier::fromString(&state, "childList")), false);
</ins><span class="cx"> if (UNLIKELY(state.hadException()))
</span><span class="cx"> return { };
</span><del>- auto attributes = convertOptional<bool>(state, propertyValue(state, value, "attributes"));
</del><ins>+ auto attributes = convertOptional<bool>(state, object->get(&state, Identifier::fromString(&state, "attributes")));
</ins><span class="cx"> if (UNLIKELY(state.hadException()))
</span><span class="cx"> return { };
</span><del>- auto attributeFilter = convertOptional<Vector<String>>(state, propertyValue(state, value, "attributeFilter"));
</del><ins>+ auto attributeFilter = convertOptional<Vector<String>>(state, object->get(&state, Identifier::fromString(&state, "attributeFilter")));
</ins><span class="cx"> return { WTFMove(childList), WTFMove(attributes), WTFMove(attributeFilter) };
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceWebCorecssFontFacecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/FontFace.cpp (200554 => 200555)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/FontFace.cpp        2016-05-08 15:22:36 UTC (rev 200554)
+++ trunk/Source/WebCore/css/FontFace.cpp        2016-05-08 16:54:09 UTC (rev 200555)
</span><span class="lines">@@ -36,7 +36,7 @@
</span><span class="cx">
</span><span class="cx"> namespace WebCore {
</span><span class="cx">
</span><del>-RefPtr<FontFace> FontFace::create(JSC::ExecState& state, Document& document, const String& family, JSC::JSValue source, const Optional<Descriptors>& descriptors, ExceptionCode& ec)
</del><ins>+RefPtr<FontFace> FontFace::create(JSC::ExecState& state, Document& document, const String& family, JSC::JSValue source, const Descriptors& descriptors, ExceptionCode& ec)
</ins><span class="cx"> {
</span><span class="cx"> auto result = adoptRef(*new FontFace(document.fontSelector()));
</span><span class="cx">
</span><span class="lines">@@ -54,26 +54,24 @@
</span><span class="cx"> CSSFontFace::appendSources(result->backing(), downcast<CSSValueList>(*value), &document, false);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- if (descriptors) {
- result->setStyle(descriptors->style, ec);
- if (ec)
- return nullptr;
- result->setWeight(descriptors->weight, ec);
- if (ec)
- return nullptr;
- result->setStretch(descriptors->stretch, ec);
- if (ec)
- return nullptr;
- result->setUnicodeRange(descriptors->unicodeRange, ec);
- if (ec)
- return nullptr;
- result->setVariant(descriptors->variant, ec);
- if (ec)
- return nullptr;
- result->setFeatureSettings(descriptors->featureSettings, ec);
- if (ec)
- return nullptr;
- }
</del><ins>+ result->setStyle(descriptors.style, ec);
+ if (ec)
+ return nullptr;
+ result->setWeight(descriptors.weight, ec);
+ if (ec)
+ return nullptr;
+ result->setStretch(descriptors.stretch, ec);
+ if (ec)
+ return nullptr;
+ result->setUnicodeRange(descriptors.unicodeRange, ec);
+ if (ec)
+ return nullptr;
+ result->setVariant(descriptors.variant, ec);
+ if (ec)
+ return nullptr;
+ result->setFeatureSettings(descriptors.featureSettings, ec);
+ if (ec)
+ return nullptr;
</ins><span class="cx">
</span><span class="cx"> return WTFMove(result);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebCorecssFontFaceh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/css/FontFace.h (200554 => 200555)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/css/FontFace.h        2016-05-08 15:22:36 UTC (rev 200554)
+++ trunk/Source/WebCore/css/FontFace.h        2016-05-08 16:54:09 UTC (rev 200555)
</span><span class="lines">@@ -42,7 +42,7 @@
</span><span class="cx"> String variant;
</span><span class="cx"> String featureSettings;
</span><span class="cx"> };
</span><del>- static RefPtr<FontFace> create(JSC::ExecState&, Document&, const String& family, JSC::JSValue source, const Optional<Descriptors>&, ExceptionCode&);
</del><ins>+ static RefPtr<FontFace> create(JSC::ExecState&, Document&, const String& family, JSC::JSValue source, const Descriptors&, ExceptionCode&);
</ins><span class="cx"> static Ref<FontFace> create(CSSFontFace&);
</span><span class="cx"> virtual ~FontFace();
</span><span class="cx">
</span></span></pre>
</div>
</div>
</body>
</html>