diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-09-01 19:18:36 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-09-01 19:18:36 (GMT) |
commit | fd0778237785840ec754f98e847a524590cbf61c (patch) | |
tree | ebf4609be11843f9657810515d47faa3873c2db8 /contrib | |
parent | 99d2c52f1068b2dd4bd16b8c1c8231beeb94a649 (diff) | |
download | uscxml-fd0778237785840ec754f98e847a524590cbf61c.zip uscxml-fd0778237785840ec754f98e847a524590cbf61c.tar.gz uscxml-fd0778237785840ec754f98e847a524590cbf61c.tar.bz2 |
More work on TypedArrays
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/dom/idl/TypedArray.idl | 43 | ||||
-rw-r--r-- | contrib/dom/scripts/CodeGenerator.pm | 4 | ||||
-rw-r--r-- | contrib/dom/scripts/CodeGeneratorArabicaJSC.pm | 302 | ||||
-rw-r--r-- | contrib/dom/scripts/CodeGeneratorArabicaV8.pm | 394 | ||||
-rw-r--r-- | contrib/dom/scripts/IDLParser.pm | 8 |
5 files changed, 570 insertions, 181 deletions
diff --git a/contrib/dom/idl/TypedArray.idl b/contrib/dom/idl/TypedArray.idl index 17df5c3..5774a73 100644 --- a/contrib/dom/idl/TypedArray.idl +++ b/contrib/dom/idl/TypedArray.idl @@ -8,7 +8,10 @@ * https://www.khronos.org/registry/typedarray/specs/latest/ */ -[ Constructor(unsigned long length) ] +[ CustomIndexedGetter, + CustomIndexedSetter, + Constructor(unsigned long length) +] interface ArrayBuffer { readonly attribute unsigned long byteLength; ArrayBuffer slice(long begin, optional long end); @@ -26,13 +29,15 @@ interface ArrayBufferView { // The 'byte' type does not currently exist in Web IDL. // In this IDL, it should be a signed 8 bit type. [ + CustomIndexedGetter, + CustomIndexedSetter, Constructor(unsigned long length), Constructor(Int8Array array), Constructor(byte[] array), Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length) ] -interface Int8Array { +interface Int8Array : ArrayBufferView { const long BYTES_PER_ELEMENT = 1; readonly attribute unsigned long length; @@ -49,13 +54,15 @@ Int8Array implements ArrayBufferView; // The 'unsigned byte' type does not currently exist in Web IDL, though // 'octet' is equivalent. [ + CustomIndexedGetter, + CustomIndexedSetter, Constructor(unsigned long length), Constructor(Uint8Array array), Constructor(octet[] array), Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length) ] -interface Uint8Array { +interface Uint8Array : ArrayBufferView{ const long BYTES_PER_ELEMENT = 1; readonly attribute unsigned long length; @@ -70,13 +77,15 @@ Uint8Array implements ArrayBufferView; [ + CustomIndexedGetter, + CustomIndexedSetter, Constructor(unsigned long length), Constructor(Uint8ClampedArray array), Constructor(octet[] array), Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length) ] -interface Uint8ClampedArray { +interface Uint8ClampedArray : ArrayBufferView { const long BYTES_PER_ELEMENT = 1; readonly attribute unsigned long length; @@ -91,13 +100,15 @@ Uint8ClampedArray implements ArrayBufferView; [ + CustomIndexedGetter, + CustomIndexedSetter, Constructor(unsigned long length), Constructor(Int16Array array), Constructor(short[] array), Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length) ] -interface Int16Array { +interface Int16Array : ArrayBufferView { const long BYTES_PER_ELEMENT = 2; readonly attribute unsigned long length; @@ -112,13 +123,15 @@ Int16Array implements ArrayBufferView; [ + CustomIndexedGetter, + CustomIndexedSetter, Constructor(unsigned long length), Constructor(Uint16Array array), Constructor(unsigned short[] array), Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length) ] -interface Uint16Array { +interface Uint16Array : ArrayBufferView { const long BYTES_PER_ELEMENT = 2; readonly attribute unsigned long length; @@ -133,13 +146,15 @@ Uint16Array implements ArrayBufferView; [ + CustomIndexedGetter, + CustomIndexedSetter, Constructor(unsigned long length), Constructor(Int32Array array), Constructor(long[] array), Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length) ] -interface Int32Array { +interface Int32Array : ArrayBufferView { const long BYTES_PER_ELEMENT = 4; readonly attribute unsigned long length; @@ -154,13 +169,15 @@ Int32Array implements ArrayBufferView; [ + CustomIndexedGetter, + CustomIndexedSetter, Constructor(unsigned long length), Constructor(Uint32Array array), Constructor(unsigned long[] array), Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length) ] -interface Uint32Array { +interface Uint32Array : ArrayBufferView { const long BYTES_PER_ELEMENT = 4; readonly attribute unsigned long length; @@ -175,13 +192,15 @@ Uint32Array implements ArrayBufferView; [ + CustomIndexedGetter, + CustomIndexedSetter, Constructor(unsigned long length), Constructor(Float32Array array), Constructor(float[] array), Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length) ] -interface Float32Array { +interface Float32Array : ArrayBufferView { const long BYTES_PER_ELEMENT = 4; readonly attribute unsigned long length; @@ -196,13 +215,15 @@ Float32Array implements ArrayBufferView; [ + CustomIndexedGetter, + CustomIndexedSetter, Constructor(unsigned long length), Constructor(Float64Array array), Constructor(double[] array), Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length) ] -interface Float64Array { +interface Float64Array : ArrayBufferView { const long BYTES_PER_ELEMENT = 8; readonly attribute unsigned long length; @@ -221,7 +242,7 @@ Float64Array implements ArrayBufferView; optional unsigned long byteOffset, optional unsigned long byteLength) ] -interface DataView { +interface DataView : ArrayBufferView{ // Gets the value of the given type at the specified byte offset // from the start of the view. There is no alignment constraint; // multi-byte values may be fetched from any offset. diff --git a/contrib/dom/scripts/CodeGenerator.pm b/contrib/dom/scripts/CodeGenerator.pm index 232cfda..fba0093 100644 --- a/contrib/dom/scripts/CodeGenerator.pm +++ b/contrib/dom/scripts/CodeGenerator.pm @@ -277,8 +277,12 @@ sub IDLFileForInterface $File::Find::prune = 1 if /^\../; }; find($wanted, @directories); + $idlFiles->{"ArrayBufferView"} = "../idl/TypedArray.idl" } + # print Dumper($object); + # print Dumper($interfaceName); + return $idlFiles->{$interfaceName}; } diff --git a/contrib/dom/scripts/CodeGeneratorArabicaJSC.pm b/contrib/dom/scripts/CodeGeneratorArabicaJSC.pm index 8fc67ce..f9a2d25 100644 --- a/contrib/dom/scripts/CodeGeneratorArabicaJSC.pm +++ b/contrib/dom/scripts/CodeGeneratorArabicaJSC.pm @@ -127,7 +127,7 @@ sub GenerateHeader my $interface = shift; my $interfaceName = $interface->name; my $extensions = $interface->extendedAttributes; - #print Dumper($interface); +# print Dumper($interface); # Copy contents of parent interfaces except the first parent. my @parents; @@ -196,6 +196,10 @@ END } push(@headerContent, "\n"); + if ($extensions->{'Constructors'}) { + push(@headerContent, "\n static JSObjectRef jsConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);"); + } + # attribute getter and setters foreach my $attribute (@{$interface->attributes}) { my $name = $attribute->signature->name; @@ -221,7 +225,7 @@ END push(@headerContent, "\n static JSValueRef getPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);"); } if ($extensions->{'CustomIndexedSetter'}) { - push(@headerContent, "\n static JSValueRef setPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception);"); + push(@headerContent, "\n static bool setPropertyCustomCallback(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception);"); } push(@headerContent, "\n"); @@ -246,6 +250,9 @@ END if ($extensions->{'CustomIndexedSetter'}) { push(@headerContent, " classDef.setProperty = setPropertyCustomCallback;\n"); } + if ($extensions->{'Constructors'}) { + push(@headerContent, " classDef.callAsConstructor = jsConstructor;\n"); + } if (@{$interface->parents}) { my $parent = @{$interface->parents}[0]; push(@headerContent, " classDef.parentClass = JSC${parent}::getTmpl();\n"); @@ -302,12 +309,15 @@ sub GenerateClassDefStatics push(@implContent, "\n};\n"); push(@implContent, "\nJSStaticFunction JSC${interfaceName}::staticFunctions[] = {"); + my %generated; foreach my $function (@{$interface->functions}) { my $name = $function->signature->name; my $attrExt = $function->signature->extendedAttributes; my $custom = ($attrExt->{'Custom'} ? "Custom" : ""); my $callback = ${name}.${custom}."Callback"; my $flags = "kJSPropertyAttributeDontDelete"; + next if (exists $generated{"${name}"}); + $generated{"${name}"} = 1; push(@implContent, "\n { \"${name}\", ${callback}, ${flags} },"); } @@ -361,7 +371,7 @@ END retPrivData->dom = privData->dom; retPrivData->nativeObj = arabicaRet; - JSObjectRef arbaicaRetObj = JSObjectMake(ctx, arbaicaRetClass, arabicaRet); + JSObjectRef arbaicaRetObj = JSObjectMake(ctx, arbaicaRetClass, retPrivData); return arbaicaRetObj; END } else { @@ -441,6 +451,130 @@ sub GenerateConditionalUndefReturn return "if (!$getterExpression) return JSValueMakeUndefined(ctx);"; } +sub GenerateConstructor +{ + my $interface = shift; + my $interfaceName = $interface->name; + my $extensions = $interface->extendedAttributes; + my $wrapperType = IdlToWrapperType($interfaceName); + + if ($extensions->{'Constructors'}) { + push(@implContent, <<END); + +JSObjectRef JSC${interfaceName}::jsConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { + ${wrapperType}* localInstance = NULL; +END + + + # dispatch the actual constructor + push(@implContent, "\n if (false) {\n}"); + my @variants; + foreach my $fullCons (@{$extensions->{'Constructors'}}) { + push (@variants, $fullCons); + + for (my $i = @{$fullCons}; $i > 0; $i--) { + my $variant = @{$fullCons}[$i]; + if ($variant->{'domSignature::isOptional'}) { + my $slice; + for (my $j = 0; $j < $i; $j++) { + push(@{$slice}, @{$fullCons}[$j]); + } + push (@variants, $slice); + } + } + + # sort to put most determinate signatures first + @variants = sort { + if (@{$b} != @{$a}) { + # more arguments are more determinant + @{$b} <=> @{$a}; + } else { + my @aWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$a}); + my @bWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$b}); + @bWrap <=> @aWrap; + } + } @variants; + } + foreach my $constructor (@variants) { + push(@implContent, " else if (argumentCount == " . @{$constructor}); + for (my $i = 0; $i < @{$constructor}; $i++) { + my $type = $constructor->[$i]->{'domSignature::type'}; + AddToImplIncludes("JSC".$type.".h") if (IsWrapperType($type)); + push(@implContent, " &&\n " . IdlToTypeChecker($type, "arguments[$i]")); + + } + + push(@implContent, ") {\n"); + my $constructorArgs; + my $constructorSep = ""; + for (my $i = 0; $i < @{$constructor}; $i++) { + my $type = $constructor->[$i]->{'domSignature::type'}; + my $name = $constructor->[$i]->{'domSignature::name'}; + my ($handle, $deref) = IdlToArgHandle($type, "local".ucfirst($name), "arguments[$i]", $interfaceName); + $constructorArgs .= ${constructorSep}.${deref}; + $constructorSep = ", "; + push(@implContent, "\n $handle"); + + } + push(@implContent, "\n localInstance = new ".IdlToWrapperType($interfaceName)."(${constructorArgs});"); + push(@implContent, "\n\n }"); + + } + push(@implContent, "\n"); + + push(@implContent, <<END); + if (!localInstance) { + JSStringRef exceptionString = JSStringCreateWithUTF8CString("Parameter mismatch while calling constructor for ${interfaceName}"); + *exception = JSValueMakeString(ctx, exceptionString); + JSStringRelease(exceptionString); + return (JSObjectRef)JSValueMakeNull(ctx); + } + + JSClassRef retClass = JSC${interfaceName}::getTmpl(); + + struct JSC${interfaceName}::JSC${interfaceName}Private* retPrivData = new JSC${interfaceName}::JSC${interfaceName}Private(); + retPrivData->nativeObj = localInstance; + + JSObjectRef retObj = JSObjectMake(ctx, retClass, retPrivData); + return retObj; + } +END + } +} + +sub IdlToTypeChecker +{ + my $idlType = shift; + my $attr = shift; + + return "JSValueIsString(ctx, ${attr})" if ($idlType eq "DOMString"); + return "JSValueIsBoolean(ctx, ${attr})" if ($idlType eq "boolean"); + return "JSValueIsNumber(ctx, ${attr})" if ($idlType eq "short"); + return "JSValueIsNumber(ctx, ${attr})" if ($idlType eq "long"); + return "JSValueIsObject(ctx, ${attr})" if ($idlType eq "long[]"); + return "JSValueIsNumber(ctx, ${attr})" if ($idlType eq "unsigned short"); + return "JSValueIsNumber(ctx, ${attr})" if ($idlType eq "unsigned long"); + return "JSValueIsNumber(ctx, ${attr})" if ($idlType eq "byte"); + return "JSValueIsNumber(ctx, ${attr})" if ($idlType eq "octet"); + return "JSValueIsNumber(ctx, ${attr})" if ($idlType eq "double"); + return "JSValueIsObject(ctx, ${attr})" if ($idlType eq "double[]"); + return "JSValueIsNumber(ctx, ${attr})" if ($idlType eq "float"); + return "JSValueIsObject(ctx, ${attr})" if ($idlType eq "float[]"); + return "JSValueIsObject(ctx, ${attr})" if ($idlType eq "short[]"); + return "JSValueIsObject(ctx, ${attr})" if ($idlType eq "unsigned short[]"); + return "JSValueIsObject(ctx, ${attr})" if ($idlType eq "unsigned long[]"); + return "JSValueIsObject(ctx, ${attr})" if ($idlType eq "byte[]"); + return "JSValueIsObject(ctx, ${attr})" if ($idlType eq "octet[]"); + return "true" if ($idlType eq "any"); + + return "JSValueIsObject(ctx, ${attr}) && JSValueIsObjectOfClass(ctx, ${attr}, JSC${idlType}::getTmpl())" if (IsWrapperType($idlType)); + + print $idlType."\n"; + die(); + +} + + sub GenerateImplementationFunctionCallbacks { my $interface = shift; @@ -459,22 +593,65 @@ sub GenerateImplementationFunctionCallbacks next if (exists $generated{"${name}Callback"}); $generated{"${name}Callback"} = 1; + # get all functions with this name + my @sameFunctions = grep($_->signature->name eq $name, @{$interface->functions}); + # signature push(@implContent, <<END); + JSValueRef JSC${interfaceName}::${name}Callback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj, size_t argumentCount, const JSValueRef* arguments, JSValueRef* exception) { END # arguments count and type checking - push(@implContent, GenerateArgumentsCountCheck($function, $interface)); - my $argCheckExpr = GenerateArgumentsTypeCheck($function, $interface); + # push(@implContent, GenerateArgumentsCountCheck($function, $interface)); + # my $argCheckExpr = GenerateArgumentsTypeCheck($function, $interface); # get this push(@implContent, "\n struct JSC${interfaceName}Private* privData = (struct JSC${interfaceName}Private*)JSObjectGetPrivate(thisObj);\n"); + + # establish all variants + my @variants; + foreach my $functionVar (@sameFunctions) { + push (@variants, $functionVar->parameters); + + for (my $i = @{$functionVar->parameters}; $i > 0; $i--) { + my $variant = @{$functionVar->parameters}[$i]; + if ($variant->{'domSignature::isOptional'}) { + my $slice; + for (my $j = 0; $j < $i; $j++) { + push(@{$slice}, @{$functionVar->parameters}[$j]); + } + push (@variants, $slice); + } + } + } # arguments to local handles - my $parameterIndex = 0; - my @argList; - foreach my $parameter (@{$function->parameters}) { + push(@implContent, "\n if (false) {"); + + # sort to put most determinate signatures first + @variants = sort { + if (@{$b} != @{$a}) { + # more arguments are more determinant + @{$b} <=> @{$a}; + } else { + my @aWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$a}); + my @bWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$b}); + @bWrap <=> @aWrap; + } + } @variants; + + foreach my $variant (@variants) { + my $parameterIndex = 0; + my @argList; + + push(@implContent, "\n } else if (argumentCount == " . @{$variant}); + for (my $i = 0; $i < @{$variant}; $i++) { + my $type = $variant->[$i]->{'domSignature::type'}; + push(@implContent, " &&\n " . IdlToTypeChecker($type, "arguments[$i]")); + } + push(@implContent, ")\n {"); + foreach my $parameter (@{$variant}) { my $type = $parameter->type; AddToImplIncludes("JSC".$type.".h") if (IsWrapperType($type)); @@ -484,40 +661,49 @@ END push(@argList, $deref); $parameterIndex++; - } + } - # invoke native function with argument handles - my $retNativeType = IdlToNativeType($retType); - my $wrapperFunctionName = IdlToWrapperFunction($interface, $function); - if (IsWrapperType($retType)) { - push(@implContent, "\n\n ${retNativeType}* retVal = new $wrapperRetType(privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . "));\n"); - } elsif ($retNativeType eq "void") { - push(@implContent, "\n\n privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); - } else { - push(@implContent, "\n\n ${retNativeType} retVal = privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); - } + # invoke native function with argument handles + my $retNativeType = IdlToNativeType($retType); + my $wrapperFunctionName = IdlToWrapperFunction($interface, $function); + if (IsWrapperType($retType)) { + push(@implContent, "\n\n ${retNativeType}* retVal = new $wrapperRetType(privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . "));\n"); + } elsif ($retNativeType eq "void") { + push(@implContent, "\n\n privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); + } else { + push(@implContent, "\n\n ${retNativeType} retVal = privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); + } - # wrap return type if needed - if (IsWrapperType($retType)) { - AddToImplIncludes("JSC".$retType.".h"); + # wrap return type if needed + if (IsWrapperType($retType)) { + AddToImplIncludes("JSC".$retType.".h"); - push(@implContent, <<END); - JSClassRef retClass = JSC${retType}::getTmpl(); + push(@implContent, <<END); + JSClassRef retClass = JSC${retType}::getTmpl(); - struct JSC${retType}::JSC${retType}Private* retPrivData = new JSC${retType}::JSC${retType}Private(); - retPrivData->dom = privData->dom; - retPrivData->nativeObj = retVal; + struct JSC${retType}::JSC${retType}Private* retPrivData = new JSC${retType}::JSC${retType}Private(); + retPrivData->dom = privData->dom; + retPrivData->nativeObj = retVal; - JSObjectRef retObj = JSObjectMake(ctx, retClass, retPrivData); + JSObjectRef retObj = JSObjectMake(ctx, retClass, retPrivData); - return retObj; + return retObj; END - } else { - my $toHandleString = NativeToHandle($retNativeType, "retVal", "jscRetVal"); - push(@implContent, "${toHandleString}\n return jscRetVal;"); + } else { + my $toHandleString = NativeToHandle($retNativeType, "retVal", "jscRetVal"); + push(@implContent, "${toHandleString}\n return jscRetVal;"); + } } + push(@implContent, <<END); - push(@implContent, "\n }\n\n"); + } + + JSStringRef exceptionString = JSStringCreateWithUTF8CString("Parameter mismatch while calling ${name}"); + *exception = JSValueMakeString(ctx, exceptionString); + JSStringRelease(exceptionString); + return JSValueMakeUndefined(ctx); + } +END } } @@ -547,6 +733,9 @@ sub GenerateImplementation push(@implContent, "JSClassRef JSC${interfaceName}::Tmpl;\n"); GenerateClassDefStatics($interface); + if ($interface->extendedAttributes->{'Constructors'}) { + GenerateConstructor($interface); + } GenerateImplementationAttributes($interface); GenerateImplementationFunctionCallbacks($interface); @@ -654,7 +843,7 @@ sub IdlToNativeType return "unsigned long" if ($idlType eq "unsigned long"); return "void" if ($idlType eq "void"); return "char" if ($idlType eq "byte"); - return "char" if ($idlType eq "octet"); + return "unsigned char" if ($idlType eq "octet"); return "double" if ($idlType eq "double"); return "float" if ($idlType eq "float"); die(${idlType}); @@ -671,6 +860,7 @@ sub NativeToHandle return ("\n JSValueRef ${paramName} = JSValueMakeNumber(ctx, ${nativeName});") if ($nativeType eq "float"); return ("\n JSValueRef ${paramName} = JSValueMakeNumber(ctx, ${nativeName});") if ($nativeType eq "short"); return ("\n JSValueRef ${paramName} = JSValueMakeNumber(ctx, ${nativeName});") if ($nativeType eq "char"); + return ("\n JSValueRef ${paramName} = JSValueMakeNumber(ctx, ${nativeName});") if ($nativeType eq "unsigned char"); return ("\n JSValueRef ${paramName} = JSValueMakeNumber(ctx, ${nativeName});") if ($nativeType eq "unsigned short"); return ("\n JSValueRef ${paramName} = JSValueMakeNumber(ctx, ${nativeName});") if ($nativeType eq "unsigned long"); return ("\n JSValueRef ${paramName} = JSValueMakeNumber(ctx, ${nativeName});") if ($nativeType eq "long"); @@ -731,16 +921,41 @@ sub IdlToArgHandle return ("double ${localName} = (double)JSValueToNumber(ctx, ${paramName}, exception);", ${localName}) if ($type eq "double"); return ("short ${localName} = (short)JSValueToNumber(ctx, ${paramName}, exception);", ${localName}) if ($type eq "short"); return ("char ${localName} = (char)JSValueToNumber(ctx, ${paramName}, exception);", ${localName}) if ($type eq "byte"); - return ("unsigned char ${localName} = (char)JSValueToNumber(ctx, ${paramName}, exception);", ${localName}) if ($type eq "octet"); + return ("unsigned char ${localName} = (unsigned char)JSValueToNumber(ctx, ${paramName}, exception);", ${localName}) if ($type eq "octet"); return ("bool ${localName} = JSValueToBoolean(ctx, ${paramName});", ${localName}) if ($type eq "boolean"); - return ("float[] ${localName} = JSObjectGetPrivate(JSValueToObject(ctx, ${paramName}, exception))->getFloatArray();", ${localName}) if ($type eq "float[]"); - return ("double[] ${localName} = JSObjectGetPrivate(JSValueToObject(ctx, ${paramName}, exception))->getDoubleArray();", ${localName}) if ($type eq "double[]"); - return ("long[] ${localName} = JSObjectGetPrivate(JSValueToObject(ctx, ${paramName}, exception))->getLongArray();", ${localName}) if ($type eq "long[]"); return ("void* ${localName} = JSObjectGetPrivate(JSValueToObject(ctx, ${paramName}, exception));", ${localName}) if ($type eq "any"); + + if ($type =~ /(.*)\[\]$/) { + my $nativeType = $1; + $nativeType = "char" if ($nativeType =~ /^byte$/); + $nativeType = "unsigned char" if ($nativeType =~ /^octet$/); + return ("\ + std::vector<${nativeType}> ${localName};\n\ + JSValueRef ${localName}Item; + unsigned int ${localName}Index = 0; + while((${localName}Item = JSObjectGetPropertyAtIndex(ctx, JSValueToObject(ctx, ${paramName}, exception), ${localName}Index, exception))) {\ + if (JSValueIsUndefined(ctx, ${localName}Item))\ + break;\ + if (JSValueIsNumber(ctx,${localName}Item))\ + ${localName}.push_back(JSValueToNumber(ctx, ${localName}Item, exception));\ + ${localName}Index++;\ + }", "${localName}"); + } + # return ("std::vector<float> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToNumber()->Value());\n}", "${localName}") if ($type eq "float[]"); + # return ("std::vector<double> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToNumber()->Value());\n}", "${localName}") if ($type eq "double[]"); + # return ("std::vector<char> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToInt32()->Value());\n}", "${localName}") if ($type eq "byte[]"); + # return ("std::vector<short> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToInt32()->Value());\n}", "${localName}") if ($type eq "short[]"); + # return ("std::vector<unsigned short> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "unsigned short[]"); + # return ("std::vector<unsigned long> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "unsigned long[]"); + # return ("std::vector<unsigned char> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "octet[]"); if (IsWrapperType($type)) { my $wrapperType = IdlToWrapperType($type); - return ("${wrapperType}* ${localName} = ((struct JSC${type}::JSC${type}Private*)JSObjectGetPrivate(JSValueToObject(ctx, ${paramName}, exception)))->nativeObj;", "*${localName}"); + if ($wrapperType =~ /^Arabica.*/) { + return ("${wrapperType}* ${localName} = ((struct JSC${type}::JSC${type}Private*)JSObjectGetPrivate(JSValueToObject(ctx, ${paramName}, exception)))->nativeObj;", "*${localName}"); + } else { + return ("${wrapperType}* ${localName} = ((struct JSC${type}::JSC${type}Private*)JSObjectGetPrivate(JSValueToObject(ctx, ${paramName}, exception)))->nativeObj;", "${localName}"); + } } print $type."\n"; @@ -832,7 +1047,7 @@ sub GenerateArgumentsTypeCheck my $parameterIndex = 0; foreach my $parameter (@{$function->parameters}) { - my $value = "args[$parameterIndex]"; + my $value = "arguments[$parameterIndex]"; my $type = $parameter->type; # Only DOMString or wrapper types are checked. @@ -895,18 +1110,23 @@ my %non_wrapper_types = ( 'long' => 1, 'long[]' => 1, 'short' => 1, + 'short[]' => 1, 'void' => 1, 'byte' => 1, 'octet' => 1, 'char' => 1, 'float[]' => 1, + 'byte[]' => 1, 'float' => 1, 'double[]' => 1, 'double' => 1, 'unsigned int' => 1, 'unsigned long long' => 1, 'unsigned long' => 1, - 'unsigned short' => 1 + 'unsigned long[]' => 1, + 'unsigned short' => 1, + 'unsigned short[]' => 1, + 'octet[]' => 1 ); sub IsWrapperType diff --git a/contrib/dom/scripts/CodeGeneratorArabicaV8.pm b/contrib/dom/scripts/CodeGeneratorArabicaV8.pm index 8623694..08a5805 100644 --- a/contrib/dom/scripts/CodeGeneratorArabicaV8.pm +++ b/contrib/dom/scripts/CodeGeneratorArabicaV8.pm @@ -84,6 +84,8 @@ sub GenerateInterface my $object = shift; my $interface = shift; +# print Dumper($interface); + # Start actual generation if ($interface->extendedAttributes->{"Callback"}) { die(); @@ -184,7 +186,6 @@ END push(@headerContent, "\n static bool hasInstance(v8::Handle<v8::Value>);"); push(@headerContent, "\n"); - # callbacks for actual functions my %generated; foreach my $function (@{$interface->functions}) { @@ -233,6 +234,22 @@ sub GenerateClassPrototypeHeader my $interfaceName = $interface->name; my $extensions = $interface->extendedAttributes; + if ($extensions->{'Constructors'}) { + + push(@headerContent, "\n"); + push(@headerContent, " static v8::Handle<v8::Value> constructor(const v8::Arguments&);\n"); + push(@headerContent, " static v8::Persistent<v8::FunctionTemplate> Constr;\n"); + push(@headerContent, <<END); + static v8::Handle<v8::FunctionTemplate> getConstructor() { + if (Constr.IsEmpty()) { + v8::Handle<v8::FunctionTemplate> constr = v8::FunctionTemplate::New(constructor); + Constr = v8::Persistent<v8::FunctionTemplate>::New(constr); + } + return Constr; + } +END + } + push(@headerContent, "\n static v8::Persistent<v8::FunctionTemplate> Tmpl;\n"); push(@headerContent, <<END); static v8::Handle<v8::FunctionTemplate> getTmpl() { @@ -269,10 +286,13 @@ END } push(@headerContent, "\n"); + my %generated; foreach my $function (@{$interface->functions}) { my $name = $function->signature->name; my $attrExt = $function->signature->extendedAttributes; my $custom = ($attrExt->{'Custom'} ? "Custom" : ""); + next if (exists $generated{"${name}"}); + $generated{"${name}"} = 1; push(@headerContent, <<END); prototype->Set(v8::String::NewSymbol("${name}"), v8::FunctionTemplate::New(V8${interfaceName}::${name}${custom}Callback, v8::Undefined()), static_cast<v8::PropertyAttribute>(v8::DontDelete)); @@ -379,7 +399,7 @@ END push(@implContent, "\n v8::Local<v8::Object> self = info.Holder();"); push(@implContent, "\n struct V8${interfaceName}Private* privData = V8DOM::toClassPtr<V8${interfaceName}Private >(self->GetInternalField(0));"); - my ($handle, $deref) = IdlToArgHandle($attribute->signature->type, "local".ucfirst($attribute->signature->name), "value"); + my ($handle, $deref) = IdlToArgHandle($attribute->signature->type, "local".ucfirst($attribute->signature->name), "value", $interfaceName); push(@implContent, "\n $handle"); push(@implContent, "\n privData->nativeObj->${wrapperSetter}(${deref});"); @@ -401,12 +421,108 @@ sub GenerateConditionalUndefReturn return "if (!$getterExpression) return v8::Undefined();"; } +sub GenerateConstructor +{ + my $interface = shift; + my $interfaceName = $interface->name; + my $wrapperType = IdlToWrapperType($interfaceName); + my $extensions = $interface->extendedAttributes; + + if ($extensions->{'Constructors'}) { + + push(@implContent, "\n v8::Handle<v8::Value> V8${interfaceName}::constructor(const v8::Arguments& args) {"); + push(@implContent, <<END); + + if (!args.IsConstructCall()) + return v8::ThrowException(v8::String::New("Cannot call constructor as function")); +END + + push(@implContent, "\n ".IdlToWrapperType($interfaceName)."* localInstance = NULL;"); + # dispatch the actual constructor + push(@implContent, "\n if (false) {\n}"); + my @variants; + foreach my $fullCons (@{$extensions->{'Constructors'}}) { + push (@variants, $fullCons); + + for (my $i = @{$fullCons}; $i > 0; $i--) { + my $variant = @{$fullCons}[$i]; + if ($variant->{'domSignature::isOptional'}) { + my $slice; + for (my $j = 0; $j < $i; $j++) { + push(@{$slice}, @{$fullCons}[$j]); + } + push (@variants, $slice); + } + } + + # sort to put most determinate signatures first + @variants = sort { + if (@{$b} != @{$a}) { + # more arguments are more determinant + @{$b} <=> @{$a}; + } else { + my @aWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$a}); + my @bWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$b}); + @bWrap <=> @aWrap; + } + } @variants; + } + foreach my $constructor (@variants) { + push(@implContent, " else if (args.Length() == " . @{$constructor}); + + for (my $i = 0; $i < @{$constructor}; $i++) { + my $type = $constructor->[$i]->{'domSignature::type'}; + AddToImplIncludes("V8".$type.".h") if (IsWrapperType($type)); + push(@implContent, " &&\n " . IdlToTypeChecker($type, "args[$i]")); + + } + push(@implContent, ") {\n"); + my $constructorArgs; + my $constructorSep = ""; + for (my $i = 0; $i < @{$constructor}; $i++) { + my $type = $constructor->[$i]->{'domSignature::type'}; + my $name = $constructor->[$i]->{'domSignature::name'}; + my ($handle, $deref) = IdlToArgHandle($type, "local".ucfirst($name), "args[$i]", $interfaceName); + $constructorArgs .= ${constructorSep}.${deref}; + $constructorSep = ", "; + push(@implContent, "\n $handle"); + + } + push(@implContent, "\n localInstance = new ".IdlToWrapperType($interfaceName)."(${constructorArgs});"); + push(@implContent, "\n\n }"); + } + push(@implContent, "\n"); + + push(@implContent, <<END); + if (!localInstance) { + throw V8Exception("Parameter mismatch while calling constructor for ${interfaceName}"); + return v8::Undefined(); + } + + v8::Handle<v8::Function> retCtor = V8${interfaceName}::getTmpl()->GetFunction(); + v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance()); + + struct V8${interfaceName}::V8${interfaceName}Private* retPrivData = new V8${interfaceName}::V8${interfaceName}Private(); + retPrivData->nativeObj = localInstance; + + retObj->SetInternalField(0, V8DOM::toExternal(retPrivData)); + + retObj.MakeWeak(0, V8${interfaceName}::jsDestructor); + return retObj; + } +END + } + +} + sub GenerateImplementationFunctionCallbacks { my $interface = shift; my $interfaceName = $interface->name; my $wrapperType = IdlToWrapperType($interfaceName); + my $extensions = $interface->extendedAttributes; + # Generate methods for functions. my %generated; foreach my $function (@{$interface->functions}) { @@ -419,73 +535,112 @@ sub GenerateImplementationFunctionCallbacks next if (exists $generated{"${name}Callback"}); $generated{"${name}Callback"} = 1; + # get all functions with this name + my @sameFunctions = grep($_->signature->name eq $name, @{$interface->functions}); + # signature push(@implContent, <<END); - v8::Handle<v8::Value> V8${interfaceName}::${name}Callback(const v8::Arguments& args) { -END - - # arguments count and type checking - push(@implContent, GenerateArgumentsCountCheck($function, $interface)); - my $argCheckExpr = GenerateArgumentsTypeCheck($function, $interface); - push(@implContent, <<END) if ($argCheckExpr); - if (!${argCheckExpr}) - throw V8Exception(\"Parameter mismatch while calling ${name}\"); + v8::Handle<v8::Value> V8${interfaceName}::${name}Callback(const v8::Arguments& args) { END # get this push(@implContent, "\n v8::Local<v8::Object> self = args.Holder();"); push(@implContent, "\n struct V8${interfaceName}Private* privData = V8DOM::toClassPtr<V8${interfaceName}Private >(self->GetInternalField(0));"); - # arguments to local handles - my $parameterIndex = 0; - my @argList; - foreach my $parameter (@{$function->parameters}) { - my $value = "args[$parameterIndex]"; - my $type = $parameter->type; - AddToImplIncludes("V8".$type.".h") if (IsWrapperType($type)); - - my ($handle, $deref) = IdlToArgHandle($parameter->type, "local".ucfirst($parameter->name), "args[${parameterIndex}]"); - push(@implContent, "\n ${handle}"); - push(@argList, $deref); - - $parameterIndex++; + # establish all variants + my @variants; + foreach my $functionVar (@sameFunctions) { + push (@variants, $functionVar->parameters); + + for (my $i = @{$functionVar->parameters}; $i > 0; $i--) { + my $variant = @{$functionVar->parameters}[$i]; + if ($variant->{'domSignature::isOptional'}) { + my $slice; + for (my $j = 0; $j < $i; $j++) { + push(@{$slice}, @{$functionVar->parameters}[$j]); + } + push (@variants, $slice); + } + } } - # invoke native function with argument handles - my $retNativeType = IdlToNativeType($retType); - my $wrapperFunctionName = IdlToWrapperFunction($interface, $function); - if (IsWrapperType($retType)) { - push(@implContent, "\n\n ${retNativeType}* retVal = new $wrapperRetType(privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . "));\n"); - } elsif ($retNativeType eq "void") { - push(@implContent, "\n\n privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); - } else { - push(@implContent, "\n\n ${retNativeType} retVal = privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); - } + # arguments to local handles + push(@implContent, "\n if (false) {"); + + # sort to put most determinate signatures first + @variants = sort { + if (@{$b} != @{$a}) { + # more arguments are more determinant + @{$b} <=> @{$a}; + } else { + my @aWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$a}); + my @bWrap = grep(IsWrapperType($_->{'domSignature::type'}), @{$b}); + @bWrap <=> @aWrap; + } + } @variants; + + foreach my $variant (@variants) { + my $parameterIndex = 0; + my @argList; + + push(@implContent, "\n } else if (args.Length() == " . @{$variant}); + for (my $i = 0; $i < @{$variant}; $i++) { + my $type = $variant->[$i]->{'domSignature::type'}; + push(@implContent, " &&\n " . IdlToTypeChecker($type, "args[$i]")); + } + push(@implContent, ")\n {"); + foreach my $parameter (@{$variant}) { + my $value = "args[$parameterIndex]"; + my $type = $parameter->type; + AddToImplIncludes("V8".$type.".h") if (IsWrapperType($type)); + + my ($handle, $deref) = IdlToArgHandle($parameter->type, "local".ucfirst($parameter->name), "args[${parameterIndex}]", $interfaceName); + push(@implContent, "\n ${handle}"); + push(@argList, $deref); + $parameterIndex++; + } - # wrap return type if needed - if (IsWrapperType($retType)) { - AddToImplIncludes("V8".$retType.".h"); + # invoke native function with argument handles + my $retNativeType = IdlToNativeType($retType); + my $wrapperFunctionName = IdlToWrapperFunction($interface, $function); + if (IsWrapperType($retType)) { + push(@implContent, "\n\n ${retNativeType}* retVal = new $wrapperRetType(privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . "));\n"); + } elsif ($retNativeType eq "void") { + push(@implContent, "\n\n privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); + } else { + push(@implContent, "\n\n ${retNativeType} retVal = privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); + } - push(@implContent, <<END); - v8::Handle<v8::Function> retCtor = V8${retType}::getTmpl()->GetFunction(); - v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance()); + # wrap return type if needed + if (IsWrapperType($retType)) { + AddToImplIncludes("V8".$retType.".h"); - struct V8${retType}::V8${retType}Private* retPrivData = new V8${retType}::V8${retType}Private(); - retPrivData->dom = privData->dom; - retPrivData->nativeObj = retVal; + push(@implContent, <<END); + v8::Handle<v8::Function> retCtor = V8${retType}::getTmpl()->GetFunction(); + v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance()); - retObj->SetInternalField(0, V8DOM::toExternal(retPrivData)); + struct V8${retType}::V8${retType}Private* retPrivData = new V8${retType}::V8${retType}Private(); + retPrivData->dom = privData->dom; + retPrivData->nativeObj = retVal; - retObj.MakeWeak(0, V8${retType}::jsDestructor); - return retObj; + retObj->SetInternalField(0, V8DOM::toExternal(retPrivData)); + + retObj.MakeWeak(0, V8${retType}::jsDestructor); + return retObj; END - } else { - my $toHandleString = NativeToHandle($retNativeType, "retVal"); - push(@implContent, "\n return ${toHandleString};"); + } else { + my $toHandleString = NativeToHandle($retNativeType, "retVal"); + push(@implContent, "\n return ${toHandleString};"); + } } - - push(@implContent, "\n }\n\n"); + push(@implContent, <<END); + + } + throw V8Exception("Parameter mismatch while calling ${name}"); + return v8::Undefined(); + } +END } } @@ -498,6 +653,7 @@ sub GenerateImplementation my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface); my $v8InterfaceName = "V8$interfaceName"; my $wrapperType = IdlToWrapperType($interfaceName); + my $extensions = $interface->extendedAttributes; AddToImplIncludes("V8${interfaceName}.h"); @@ -512,11 +668,17 @@ sub GenerateImplementation } push(@implContent, "namespace Arabica {\n"); push(@implContent, "namespace DOM {\n\n"); - push(@implContent, " v8::Persistent<v8::FunctionTemplate> V8${interfaceName}::Tmpl;\n\n"); + push(@implContent, " v8::Persistent<v8::FunctionTemplate> V8${interfaceName}::Tmpl;\n"); + if ($extensions->{'Constructors'}) { + push(@implContent, " v8::Persistent<v8::FunctionTemplate> V8${interfaceName}::Constr;\n"); + GenerateConstructor($interface); + } + GenerateImplementationAttributes($interface); GenerateImplementationFunctionCallbacks($interface); + push(@implContent, <<END); bool V8${interfaceName}::hasInstance(v8::Handle<v8::Value> value) { return getTmpl()->HasInstance(value); @@ -624,7 +786,7 @@ sub IdlToNativeType return "unsigned long" if ($idlType eq "unsigned long"); return "void" if ($idlType eq "void"); return "char" if ($idlType eq "byte"); - return "char" if ($idlType eq "octet"); + return "unsigned char" if ($idlType eq "octet"); return "double" if ($idlType eq "double"); return "float" if ($idlType eq "float"); die(${idlType}); @@ -643,6 +805,7 @@ sub NativeToHandle return ("v8::Number::New(${nativeName})") if ($nativeType eq "char"); return ("v8::Number::New(${nativeName})") if ($nativeType eq "unsigned short"); return ("v8::Number::New(${nativeName})") if ($nativeType eq "unsigned long"); + return ("v8::Number::New(${nativeName})") if ($nativeType eq "unsigned char"); return ("v8::Number::New(${nativeName})") if ($nativeType eq "long"); return ("v8::String::New(${nativeName}.c_str())") if ($nativeType eq "std::string"); return ("v8::Undefined()") if ($nativeType eq "void"); @@ -679,6 +842,7 @@ sub IdlToArgHandle my $type = shift; my $localName = shift; my $paramName = shift; + my $thisType = shift; return ("v8::String::AsciiValue ${localName}(${paramName});", "*${localName}") if ($type eq "DOMString"); return ("unsigned long ${localName} = ${paramName}->ToNumber()->Uint32Value();", ${localName}) if ($type eq "unsigned long"); @@ -691,12 +855,21 @@ sub IdlToArgHandle return ("short ${localName} = ${paramName}->ToNumber()->Int32Value();", ${localName}) if ($type eq "short"); return ("unsigned char ${localName} = ${paramName}->ToNumber()->Uint32Value();", ${localName}) if ($type eq "octet"); return ("void* ${localName} = v8::External::Unwrap(${paramName}->ToObject()->GetInternalField(0));", ${localName}) if ($type eq "any"); - return ("long[] ${localName} = V8DOM::toClassPtr<V8${type}::V8${type}Private >(${paramName}->ToObject()->GetInternalField(0))->nativeObj->getLongArray();", "${localName}") if ($type eq "long[]"); - return ("float[] ${localName} = V8DOM::toClassPtr<V8${type}::V8${type}Private >(${paramName}->ToObject()->GetInternalField(0))->nativeObj->getFloatArray();", "${localName}") if ($type eq "float[]"); - return ("double[] ${localName} = V8DOM::toClassPtr<V8${type}::V8${type}Private >(${paramName}->ToObject()->GetInternalField(0))->nativeObj->getDoubleArray();", "${localName}") if ($type eq "double[]"); + return ("std::vector<long> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToInteger()->Value());\n}", "${localName}") if ($type eq "long[]"); + return ("std::vector<float> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToNumber()->Value());\n}", "${localName}") if ($type eq "float[]"); + return ("std::vector<double> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToNumber()->Value());\n}", "${localName}") if ($type eq "double[]"); + return ("std::vector<char> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToInt32()->Value());\n}", "${localName}") if ($type eq "byte[]"); + return ("std::vector<short> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToInt32()->Value());\n}", "${localName}") if ($type eq "short[]"); + return ("std::vector<unsigned short> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "unsigned short[]"); + return ("std::vector<unsigned long> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "unsigned long[]"); + return ("std::vector<unsigned char> ${localName};\nv8::Handle<v8::Array> ${localName}Array(v8::Array::Cast(*args[0]));\nfor (int i = 0; i < ${localName}Array->Length(); i++) {\n ${localName}.push_back(${localName}Array->Get(i)->ToUint32()->Value());\n}", "${localName}") if ($type eq "octet[]"); if (IsWrapperType($type)) { my $wrapperType = IdlToWrapperType($type); + if ($type =~ /.*Array$/ or $type =~ /^ArrayBuffer.*/) { + return ("${wrapperType}* ${localName} = V8DOM::toClassPtr<V8${type}::V8${type}Private >(${paramName}->ToObject()->GetInternalField(0))->nativeObj;", "${localName}"); + } + return ("${wrapperType}* ${localName} = V8DOM::toClassPtr<V8${type}::V8${type}Private >(${paramName}->ToObject()->GetInternalField(0))->nativeObj;", "*${localName}"); } @@ -704,6 +877,38 @@ sub IdlToArgHandle die(); } +sub IdlToTypeChecker +{ + my $idlType = shift; + my $attr = shift; + + return $attr."->IsString()" if ($idlType eq "DOMString"); + return $attr."->IsBoolean()" if ($idlType eq "boolean"); + return $attr."->IsInt32()" if ($idlType eq "short"); + return $attr."->IsInt32()" if ($idlType eq "long"); + return $attr."->IsArray()" if ($idlType eq "long[]"); + return $attr."->IsUint32()" if ($idlType eq "unsigned short"); + return $attr."->IsUint32()" if ($idlType eq "unsigned long"); + return $attr."->IsInt32()" if ($idlType eq "byte"); + return $attr."->IsUint32()" if ($idlType eq "octet"); + return $attr."->IsNumber()" if ($idlType eq "double"); + return $attr."->IsArray()" if ($idlType eq "double[]"); + return $attr."->IsNumber()" if ($idlType eq "float"); + return $attr."->IsArray()" if ($idlType eq "float[]"); + return $attr."->IsArray()" if ($idlType eq "short[]"); + return $attr."->IsArray()" if ($idlType eq "unsigned short[]"); + return $attr."->IsArray()" if ($idlType eq "unsigned long[]"); + return $attr."->IsArray()" if ($idlType eq "byte[]"); + return $attr."->IsArray()" if ($idlType eq "octet[]"); + return "true" if ($idlType eq "any"); + + return $attr."->IsObject() && V8".$idlType."::hasInstance(".$attr.")" if (IsWrapperType($idlType)); + + print $idlType."\n"; + die(); + +} + sub IdlToWrapperAttrGetter { my $interface = shift; @@ -749,76 +954,6 @@ sub IsReadonly } -sub GenerateArgumentsCountCheck -{ - my $function = shift; - my $interface = shift; - - my $numMandatoryParams = 0; - my $allowNonOptional = 1; - foreach my $param (@{$function->parameters}) { - if ($param->extendedAttributes->{"Optional"} or $param->isVariadic) { - $allowNonOptional = 0; - } else { - die "An argument must not be declared to be optional unless all subsequent arguments to the operation are also optional." if !$allowNonOptional; - $numMandatoryParams++; - } - } - - my $argumentsCountCheckString = ""; - if ($numMandatoryParams >= 1) { - $argumentsCountCheckString .= " if (args.Length() < $numMandatoryParams)\n"; - $argumentsCountCheckString .= " throw V8Exception(\"Wrong number of arguments in " . $function->signature->name . "\");\n"; - } - return $argumentsCountCheckString; -} - -sub GenerateArgumentsTypeCheck -{ - my $function = shift; - my $interface = shift; - - my @andExpression = (); - - my $parameterIndex = 0; - foreach my $parameter (@{$function->parameters}) { - my $value = "args[$parameterIndex]"; - my $type = $parameter->type; - - # Only DOMString or wrapper types are checked. - # For DOMString with StrictTypeChecking only Null, Undefined and Object - # are accepted for compatibility. Otherwise, no restrictions are made to - # match the non-overloaded behavior. - # FIXME: Implement WebIDL overload resolution algorithm. - if ($codeGenerator->IsStringType($type)) { - if ($parameter->extendedAttributes->{"StrictTypeChecking"}) { - push(@andExpression, "(${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject())"); - } - } elsif ($parameter->extendedAttributes->{"Callback"}) { - # For Callbacks only checks if the value is null or object. - push(@andExpression, "(${value}->IsNull() || ${value}->IsFunction())"); - } elsif ($codeGenerator->IsArrayType($type) || $codeGenerator->GetSequenceType($type)) { - if ($parameter->isNullable) { - push(@andExpression, "(${value}->IsNull() || ${value}->IsArray())"); - } else { - push(@andExpression, "(${value}->IsArray())"); - } - } elsif (IsWrapperType($type)) { - if ($parameter->isNullable) { - push(@andExpression, "(${value}->IsNull() || V8${type}::hasInstance($value))"); - } else { - push(@andExpression, "(V8${type}::hasInstance($value))"); - } - } - - $parameterIndex++; - } - my $res = join(" && ", @andExpression); - $res = "($res)" if @andExpression > 1; - return $res; -} - - my %non_wrapper_types = ( 'CompareHow' => 1, 'DOMObject' => 1, @@ -844,18 +979,23 @@ my %non_wrapper_types = ( 'long' => 1, 'long[]' => 1, 'short' => 1, + 'short[]' => 1, 'void' => 1, 'byte' => 1, + 'byte[]' => 1, 'octet' => 1, 'char' => 1, 'float[]' => 1, 'float' => 1, 'double[]' => 1, + 'octet[]' => 1, 'double' => 1, 'unsigned int' => 1, 'unsigned long long' => 1, 'unsigned long' => 1, - 'unsigned short' => 1 + 'unsigned long[]' => 1, + 'unsigned short' => 1, + 'unsigned short[]' => 1 ); sub IsWrapperType diff --git a/contrib/dom/scripts/IDLParser.pm b/contrib/dom/scripts/IDLParser.pm index 654c920..61fab7b 100644 --- a/contrib/dom/scripts/IDLParser.pm +++ b/contrib/dom/scripts/IDLParser.pm @@ -25,6 +25,7 @@ use strict; use preprocessor; use Class::Struct; +use Data::Dumper; use constant StringToken => 0; use constant IntegerToken => 1; @@ -75,6 +76,7 @@ struct( domSignature => { type => '$', # Variable type extendedAttributes => '$', # Extended attributes isNullable => '$', # Is variable type Nullable (T?) + isOptional => '$', # Is variable optional (T?) isVariadic => '$' # Is variable variadic (long... numbers) }); @@ -1282,6 +1284,8 @@ sub parseOptionalOrRequiredArgument $paramDataNode->type($type); $paramDataNode->name($self->parseArgumentName()); $self->parseDefault(); + $paramDataNode->isOptional(1); +# print Dumper($paramDataNode); return $paramDataNode; } if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { @@ -2431,8 +2435,8 @@ sub applyExtendedAttributeList $constructor->{overloadedIndex} = $index++; push(@{$interface->constructors}, $constructor); } - delete $extendedAttributeList->{"Constructors"}; - $extendedAttributeList->{"Constructor"} = "VALUE_IS_MISSING"; + # delete $extendedAttributeList->{"Constructors"}; + # $extendedAttributeList->{"Constructor"} = "VALUE_IS_MISSING"; } elsif (defined $extendedAttributeList->{"NamedConstructor"}) { my $newDataNode = domFunction->new(); $newDataNode->signature(domSignature->new()); |