Changeset 57653 in webkit
- Timestamp:
- Apr 15, 2010 10:33:34 AM (14 years ago)
- Location:
- trunk/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/WebCore/ChangeLog
r57652 r57653 1 2010-04-15 Yaar Schnitman <yaar@chromium.org> 2 3 Reviewed by Nate Chapin. 4 5 Overloads auto-generation in V8 6 https://bugs.webkit.org/show_bug.cgi?id=37373 7 8 This will be used by XHR.send/open, Canvas.*, WebGL.* methods that are currently custom. When more than a single overload exists for a method, the correct overload is chosen based on the total number of arguments passed as well as the values passed to non-primitive arguments. 9 10 Overload dispatch order depends on the order the functions are defined in the IDL. Overloads must be specified from the most precise (overloads with wrapper type arguments) to the least precise (overloads with only primitive type arguments). 11 12 * bindings/scripts/CodeGeneratorV8.pm: Identify and output overloads callbacks and dispatch code. 13 * bindings/v8/test/TestObj.idl: Overloads sample. 14 * bindings/v8/test/V8TestObj.cpp: Output change. 15 1 16 2010-04-15 Ben Murdoch <benm@google.com> 2 17 -
trunk/WebCore/bindings/scripts/CodeGeneratorV8.pm
r57505 r57653 194 194 return ""; 195 195 } 196 } 197 198 sub LinkOverloadedFunctions 199 { 200 my $dataNode = shift; 201 202 # Identifies overloaded functions and for each function adds an array with 203 # links to its respective overloads (including itself). 204 my %nameToFunctionsMap = (); 205 foreach my $function (@{$dataNode->functions}) { 206 my $name = $function->signature->name; 207 $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name}; 208 push(@{$nameToFunctionsMap{$name}}, $function); 209 $function->{overloads} = $nameToFunctionsMap{$name}; 210 $function->{overloadIndex} = @{$nameToFunctionsMap{$name}}; 211 } 212 196 213 } 197 214 … … 1002 1019 } 1003 1020 1004 sub GenerateFunctionCallback 1021 sub GenerateParametersCheckExpression 1022 { 1023 my $numParameters = shift; 1024 my $function = shift; 1025 1026 my @andExpression = (); 1027 push(@andExpression, "args.Length() == $numParameters"); 1028 my $parameterIndex = 0; 1029 foreach $parameter (@{$function->parameters}) { 1030 last if $parameterIndex >= $numParameters; 1031 my $value = "args[$parameterIndex]"; 1032 my $type = GetTypeFromSignature($parameter); 1033 1034 # Only DOMString or wrapper types are checked. 1035 # For DOMString, Null or Undefined are accepted too, as these are 1036 # usually acceptable values for a DOMString argument. 1037 push(@andExpression, "(${value}.IsNull() || ${value}.IsUndefined() || ${value}.IsString())") if $codeGenerator->IsStringType($type); 1038 push(@andExpression, "V8${type}::HasInstance($value)") if IsWrapperType($type); 1039 1040 $parameterIndex++; 1041 } 1042 my $res = join(" && ", @andExpression); 1043 $res = "($res)" if @andExpression > 1; 1044 return $res; 1045 } 1046 1047 sub GenerateFunctionParametersCheck 1048 { 1049 my $function = shift; 1050 1051 my @orExpression = (); 1052 my $numParameters = 0; 1053 foreach $parameter (@{$function->parameters}) { 1054 if ($parameter->extendedAttributes->{"Optional"}) { 1055 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); 1056 } 1057 $numParameters++; 1058 } 1059 push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); 1060 return join(" || ", @orExpression); 1061 } 1062 1063 sub GenerateOverloadedFunctionCallback 1005 1064 { 1006 1065 my $function = shift; … … 1008 1067 my $implClassName = shift; 1009 1068 1069 # Generate code for choosing the correct overload to call. Overloads are 1070 # chosen based on the total number of arguments passed and the type of 1071 # values passed in non-primitive argument slots. When more than a single 1072 # overload is applicable, precedence is given according to the order of 1073 # declaration in the IDL. 1074 1075 my $name = $function->signature->name; 1076 push(@implContentDecls, <<END); 1077 static v8::Handle<v8::Value> ${name}Callback(const v8::Arguments& args) { 1078 INC_STATS(\"DOM.$implClassName.$name\"); 1079 END 1080 foreach my $overload (@{$function->{overloads}}) { 1081 my $parametersCheck = GenerateFunctionParametersCheck($overload); 1082 if ($overload->{overloadIndex} == 1) { 1083 push(@implContentDecls, " if ($parametersCheck) {\n"); 1084 } else { 1085 push(@implContentDecls, " } else if ($parametersCheck) {\n"); 1086 } 1087 push(@implContentDecls, " return ${name}$overload->{overloadIndex}Callback(args);\n"); 1088 } 1089 push(@implContentDecls, <<END); 1090 } else { 1091 V8Proxy::setDOMException(SYNTAX_ERR); 1092 return notHandledByInterceptor(); 1093 } 1094 END 1095 push(@implContentDecls, "}\n\n"); 1096 } 1097 1098 sub GenerateFunctionCallback 1099 { 1100 my $function = shift; 1101 my $dataNode = shift; 1102 my $implClassName = shift; 1103 1010 1104 my $interfaceName = $dataNode->name; 1011 1105 my $name = $function->signature->name; 1106 1107 if (@{$function->{overloads}} > 1) { 1108 # Append a number to an overloaded method's name to make it unique: 1109 $name = $name . $function->{overloadIndex}; 1110 } 1012 1111 1013 1112 # Adding and removing event listeners are not standard callback behavior, … … 1044 1143 } 1045 1144 1046 # Check domain security if needed1145 # Check domain security if needed 1047 1146 if (($dataNode->extendedAttributes->{"CheckDomainSecurity"} 1048 1147 || $interfaceName eq "DOMWindow") … … 1562 1661 } 1563 1662 1663 LinkOverloadedFunctions($dataNode); 1664 1564 1665 my $indexer; 1565 1666 my $namedPropertyGetter; … … 1568 1669 if (!($function->signature->extendedAttributes->{"Custom"} || $function->signature->extendedAttributes->{"V8Custom"})) { 1569 1670 GenerateFunctionCallback($function, $dataNode, $implClassName); 1671 if ($function->{overloadIndex} > 1 && $function->{overloadIndex} == @{$function->{overloads}}) { 1672 GenerateOverloadedFunctionCallback($function, $dataNode, $implClassName); 1673 } 1570 1674 } 1571 1675 … … 1625 1729 $has_callbacks = 0; 1626 1730 foreach my $function (@{$dataNode->functions}) { 1731 # Only one table entry is needed for overloaded methods: 1732 next if $function->{overloadIndex} > 1; 1733 1627 1734 my $attrExt = $function->signature->extendedAttributes; 1628 1735 # Don't put any nonstandard functions into this table: … … 1786 1893 $total_functions = 0; 1787 1894 foreach my $function (@{$dataNode->functions}) { 1895 # Only one accessor is needed for overloaded methods: 1896 next if $function->{overloadIndex} > 1; 1897 1788 1898 $total_functions++; 1789 1899 my $attrExt = $function->signature->extendedAttributes; -
trunk/WebCore/bindings/v8/test/TestObj.idl
r57378 r57653 62 62 void methodWithNonOptionalArgAndOptionalArg(in long nonOpt, in [Optional] long opt); 63 63 void methodWithNonOptionalArgAndTwoOptionalArgs(in long nonOpt, in [Optional] long opt1, in long opt2); 64 65 // Overloads 66 void overloadedMethod(in TestObj objArg, in DOMString strArg); 67 void overloadedMethod(in TestObj objArg, in [Optional] long intArg); 68 void overloadedMethod(in DOMString strArg); 69 void overloadedMethod(in long intArg); 64 70 }; 65 71 } -
trunk/WebCore/bindings/v8/test/V8TestObj.cpp
r57378 r57653 264 264 imp->methodWithNonOptionalArgAndTwoOptionalArgs(nonOpt, opt1, opt2); 265 265 return v8::Handle<v8::Value>(); 266 } 267 268 static v8::Handle<v8::Value> overloadedMethod1Callback(const v8::Arguments& args) { 269 INC_STATS("DOM.TestObj.overloadedMethod1"); 270 TestObj* imp = V8TestObj::toNative(args.Holder()); 271 TestObj* objArg = V8TestObj::HasInstance(args[0]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; 272 V8Parameter<> strArg = args[1]; 273 imp->overloadedMethod(objArg, strArg); 274 return v8::Handle<v8::Value>(); 275 } 276 277 static v8::Handle<v8::Value> overloadedMethod2Callback(const v8::Arguments& args) { 278 INC_STATS("DOM.TestObj.overloadedMethod2"); 279 TestObj* imp = V8TestObj::toNative(args.Holder()); 280 TestObj* objArg = V8TestObj::HasInstance(args[0]) ? V8TestObj::toNative(v8::Handle<v8::Object>::Cast(args[0])) : 0; 281 if (args.Length() <= 1) { 282 imp->overloadedMethod(objArg); 283 return v8::Handle<v8::Value>(); 284 } 285 int intArg = toInt32(args[1]); 286 imp->overloadedMethod(objArg, intArg); 287 return v8::Handle<v8::Value>(); 288 } 289 290 static v8::Handle<v8::Value> overloadedMethod3Callback(const v8::Arguments& args) { 291 INC_STATS("DOM.TestObj.overloadedMethod3"); 292 TestObj* imp = V8TestObj::toNative(args.Holder()); 293 V8Parameter<> strArg = args[0]; 294 imp->overloadedMethod(strArg); 295 return v8::Handle<v8::Value>(); 296 } 297 298 static v8::Handle<v8::Value> overloadedMethod4Callback(const v8::Arguments& args) { 299 INC_STATS("DOM.TestObj.overloadedMethod4"); 300 TestObj* imp = V8TestObj::toNative(args.Holder()); 301 int intArg = toInt32(args[0]); 302 imp->overloadedMethod(intArg); 303 return v8::Handle<v8::Value>(); 304 } 305 306 static v8::Handle<v8::Value> overloadedMethodCallback(const v8::Arguments& args) { 307 INC_STATS("DOM.TestObj.overloadedMethod"); 308 if ((args.Length() == 2 && V8TestObj::HasInstance(args[0]) && (args[1].IsNull() || args[1].IsUndefined() || args[1].IsString()))) { 309 return overloadedMethod1Callback(args); 310 } else if ((args.Length() == 1 && V8TestObj::HasInstance(args[0])) || (args.Length() == 2 && V8TestObj::HasInstance(args[0]))) { 311 return overloadedMethod2Callback(args); 312 } else if ((args.Length() == 1 && (args[0].IsNull() || args[0].IsUndefined() || args[0].IsString()))) { 313 return overloadedMethod3Callback(args); 314 } else if (args.Length() == 1) { 315 return overloadedMethod4Callback(args); 316 } else { 317 V8Proxy::setDOMException(SYNTAX_ERR); 318 return notHandledByInterceptor(); 319 } 266 320 } 267 321 … … 408 462 proto->Set(v8::String::New("objMethodWithArgs"), v8::FunctionTemplate::New(TestObjInternal::objMethodWithArgsCallback, v8::Handle<v8::Value>(), objMethodWithArgs_signature)); 409 463 464 // Custom Signature 'overloadedMethod' 465 const int overloadedMethod_argc = 2; 466 v8::Handle<v8::FunctionTemplate> overloadedMethod_argv[overloadedMethod_argc] = { V8TestObj::GetRawTemplate(), v8::Handle<v8::FunctionTemplate>() }; 467 v8::Handle<v8::Signature> overloadedMethod_signature = v8::Signature::New(desc, overloadedMethod_argc, overloadedMethod_argv); 468 proto->Set(v8::String::New("overloadedMethod"), v8::FunctionTemplate::New(TestObjInternal::overloadedMethodCallback, v8::Handle<v8::Value>(), overloadedMethod_signature)); 469 410 470 // Custom toString template 411 471 desc->Set(getToStringName(), getToStringTemplate());
Note: See TracChangeset
for help on using the changeset viewer.