summaryrefslogtreecommitdiffstats
path: root/contrib/dom/scripts/CodeGeneratorArabicaV8.post3.14.pm
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/dom/scripts/CodeGeneratorArabicaV8.post3.14.pm')
-rw-r--r--contrib/dom/scripts/CodeGeneratorArabicaV8.post3.14.pm1021
1 files changed, 1021 insertions, 0 deletions
diff --git a/contrib/dom/scripts/CodeGeneratorArabicaV8.post3.14.pm b/contrib/dom/scripts/CodeGeneratorArabicaV8.post3.14.pm
new file mode 100644
index 0000000..e913aaa
--- /dev/null
+++ b/contrib/dom/scripts/CodeGeneratorArabicaV8.post3.14.pm
@@ -0,0 +1,1021 @@
+# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
+# Copyright (C) 2006 Anders Carlsson <andersca@mac.com>
+# Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org>
+# Copyright (C) 2006 Apple Computer, Inc.
+# Copyright (C) 2007, 2008, 2009, 2012 Google Inc.
+# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au>
+# Copyright (C) Research In Motion Limited 2010. All rights reserved.
+# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
+# Copyright (C) 2012 Ericsson AB. All rights reserved.
+# Copyright (C) 2013 Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public License
+# along with this library; see the file COPYING.LIB. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+package CodeGeneratorArabicaV8;
+
+use strict;
+use Data::Dumper;
+use Carp qw/longmess cluck confess/;
+
+use constant FileNamePrefix => "V8";
+
+my $codeGenerator;
+
+
+my @headerContent = ();
+my @implContentHeader = ();
+my @implContent = ();
+my @implContentDecls = ();
+my %implIncludes = ();
+my %headerIncludes = ();
+
+# Default .h template
+my $headerTemplate = << 'EOF';
+/**
+ * @file
+ * @author This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+EOF
+
+# Default constructor
+sub new
+{
+ my $object = shift;
+ my $reference = { };
+
+ $codeGenerator = shift;
+
+ bless($reference, $object);
+ return $reference;
+}
+
+sub GenerateInterface
+{
+ my $object = shift;
+ my $interface = shift;
+
+# print Dumper($interface);
+
+ # Start actual generation
+ if ($interface->extendedAttributes->{"Callback"}) {
+ die();
+ $object->GenerateCallbackHeader($interface);
+ $object->GenerateCallbackImplementation($interface);
+ } else {
+ $object->GenerateHeader($interface);
+ $object->GenerateImplementation($interface);
+ }
+}
+
+sub AddToImplIncludes
+{
+ my $header = shift;
+ my $conditional = shift;
+
+ if ($header eq "V8bool.h") {
+ confess();
+ }
+
+ if (not $conditional) {
+ $implIncludes{$header} = 1;
+ } elsif (not exists($implIncludes{$header})) {
+ $implIncludes{$header} = $conditional;
+ } else {
+ my $oldValue = $implIncludes{$header};
+ if ($oldValue ne 1) {
+ my %newValue = ();
+ $newValue{$conditional} = 1;
+ foreach my $condition (split(/\|/, $oldValue)) {
+ $newValue{$condition} = 1;
+ }
+ $implIncludes{$header} = join("|", sort keys %newValue);
+ }
+ }
+}
+
+sub GenerateHeader
+{
+ my $object = shift;
+ my $interface = shift;
+ my $interfaceName = $interface->name;
+ my $extensions = $interface->extendedAttributes;
+# print Dumper($extensions);
+
+ # Copy contents of parent interfaces except the first parent.
+ my @parents;
+ $codeGenerator->AddMethodsConstantsAndAttributesFromParentInterfaces($interface, \@parents, 1);
+ $codeGenerator->LinkOverloadedFunctions($interface);
+
+ # - Add default header template
+ push(@headerContent, GenerateHeaderContentHeader($interface));
+
+ $headerIncludes{"string"} = 1;
+ $headerIncludes{"uscxml/plugins/datamodel/ecmascript/v8/V8DOM.h"} = 1;
+ $headerIncludes{"DOM/Node.hpp"} = 1;
+ $headerIncludes{"v8.h"} = 1;
+
+ if ($interfaceName =~ /.*Array$/ or $interfaceName =~ /^ArrayBuffer.*/) {
+ $headerIncludes{"../../TypedArray.h"} = 1;
+ }
+
+ foreach (@{$interface->parents}) {
+ my $parent = $_;
+ $headerIncludes{"V8${parent}.h"} = 1;
+ }
+
+ push(@headerContent, "#include \<string\>\n");
+ foreach my $headerInclude (sort keys(%headerIncludes)) {
+ if ($headerInclude =~ /wtf|v8\.h/) {
+ push(@headerContent, "#include \<${headerInclude}\>\n");
+ } else {
+ push(@headerContent, "#include \"${headerInclude}\"\n");
+ }
+ }
+
+ push(@headerContent, "");
+ push(@headerContent, "\nnamespace Arabica {");
+ push(@headerContent, "\nnamespace DOM {\n");
+
+ push(@headerContent, "\nclass V8${interfaceName} {");
+ push(@headerContent, "\npublic:");
+
+ my $wrapperType = IdlToWrapperType($interfaceName);
+ push(@headerContent, <<END);
+
+ struct V8${interfaceName}Private {
+ V8DOM* dom;
+ ${wrapperType}* nativeObj;
+ };
+END
+
+ if ($extensions->{'DontDestroyWrapped'}) {
+ push(@headerContent, "\n V8_DESTRUCTOR_KEEP_WRAPPED(V8${interfaceName}Private);");
+ } else {
+ push(@headerContent, "\n V8_DESTRUCTOR(V8${interfaceName}Private);");
+ }
+ push(@headerContent, "\n static bool hasInstance(v8::Handle<v8::Value>);");
+ push(@headerContent, "\n");
+
+ # callbacks for actual functions
+ 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}${custom}Callback"});
+ push(@headerContent, "\n static void ${name}${custom}Callback(const v8::FunctionCallbackInfo<v8::Value>&);");
+ $generated{"${name}${custom}Callback"} = 1;
+ }
+ push(@headerContent, "\n");
+
+ # attribute getter and setters
+ foreach my $attribute (@{$interface->attributes}) {
+ my $name = $attribute->signature->name;
+ my $attrExt = $attribute->signature->extendedAttributes;
+ my $customGetter = ($attrExt->{'CustomGetter'} ? "Custom" : "");
+ my $customSetter = ($attrExt->{'CustomSetter'} ? "Custom" : "");
+ push(@headerContent, "\n static void ${name}${customGetter}AttrGetter(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info);");
+ if (!IsReadonly($attribute)) {
+ push(@headerContent, "\n static void ${name}${customSetter}AttrSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info);");
+ }
+ }
+
+ if ($extensions->{'CustomIndexedGetter'}) {
+ push(@headerContent, "\n static void indexedPropertyCustomGetter(uint32_t, const v8::PropertyCallbackInfo<v8::Value>&);");
+ }
+ if ($extensions->{'CustomIndexedSetter'}) {
+ push(@headerContent, "\n static void indexedPropertyCustomSetter(uint32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);");
+ }
+ push(@headerContent, "\n");
+
+ GenerateClassPrototypeHeader($interface);
+
+ push(@headerContent, "\n};\n\n}\n}\n\n");
+ push(@headerContent, "#endif // V8${interfaceName}" . "_h\n");
+
+}
+
+#
+# Write class template prototype constructor
+#
+sub GenerateClassPrototypeHeader
+{
+ my $interface = shift;
+ my $interfaceName = $interface->name;
+ my $extensions = $interface->extendedAttributes;
+
+ if ($extensions->{'Constructors'}) {
+
+ push(@headerContent, "\n");
+ push(@headerContent, " static void constructor(const v8::FunctionCallbackInfo<v8::Value>&);\n");
+ push(@headerContent, <<END);
+ static v8::Handle<v8::FunctionTemplate> getConstructor(v8::Isolate* isolate) {
+ return v8::FunctionTemplate::New(isolate, constructor);
+ }
+END
+ }
+
+ push(@headerContent, <<END);
+ static v8::Handle<v8::FunctionTemplate> getTmpl(v8::Isolate* isolate) {
+ v8::Handle<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(isolate);
+ tmpl->SetClassName(v8::String::NewFromUtf8(isolate, "${interfaceName}"));
+ tmpl->ReadOnlyPrototype();
+
+ v8::Local<v8::ObjectTemplate> instance = tmpl->InstanceTemplate();
+ v8::Local<v8::ObjectTemplate> prototype = tmpl->PrototypeTemplate();
+ (void)prototype; // surpress unused warnings
+
+ instance->SetInternalFieldCount(1);
+END
+
+ push(@headerContent, "\n");
+ foreach my $attribute (@{$interface->attributes}) {
+ my $name = $attribute->signature->name;
+ my $attrExt = $attribute->signature->extendedAttributes;
+ my $customGetter = ($attrExt->{'CustomGetter'} ? "Custom" : "");
+ my $customSetter = ($attrExt->{'CustomSetter'} ? "Custom" : "");
+ my $getter = "V8${interfaceName}::${name}${customGetter}AttrGetter";
+ my $setter = (IsReadonly($attribute) ? "0" : "V8${interfaceName}::${name}${customSetter}AttrSetter");
+ push(@headerContent, <<END);
+ instance->SetAccessor(v8::String::NewFromUtf8(isolate, "${name}"), ${getter}, ${setter},
+ v8::External::New(isolate, 0), static_cast<v8::AccessControl>(v8::DEFAULT), static_cast<v8::PropertyAttribute>(v8::None));
+END
+ }
+
+ if ($extensions->{'CustomIndexedGetter'} || $extensions->{'CustomIndexedSetter'}) {
+ my $indexedGetter = ($extensions->{'CustomIndexedGetter'} ? "V8${interfaceName}::indexedPropertyCustomGetter" : 0);
+ my $indexedSetter = ($extensions->{'CustomIndexedSetter'} ? "V8${interfaceName}::indexedPropertyCustomSetter" : 0);
+ push(@headerContent, "\n instance->SetIndexedPropertyHandler(${indexedGetter}, ${indexedSetter});");
+ }
+
+ 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::NewFromUtf8(isolate, "${name}"),
+ v8::FunctionTemplate::New(isolate, V8${interfaceName}::${name}${custom}Callback, v8::Undefined(isolate)), static_cast<v8::PropertyAttribute>(v8::DontDelete));
+END
+ }
+
+ push(@headerContent, "\n");
+ foreach my $constant (@{$interface->constants}) {
+ my $name = $constant->name;
+ my $value = $constant->value;
+ my $type = IdlToV8Type($constant->type);
+ push(@headerContent, <<END);
+ tmpl->Set(v8::String::NewFromUtf8(isolate, "${name}"), ${type}::New(isolate, ${value}), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+ prototype->Set(v8::String::NewFromUtf8(isolate, "${name}"), ${type}::New(isolate, ${value}), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum));
+END
+ }
+
+ push(@headerContent, "\n");
+ if (@{$interface->parents}) {
+ my $parent = @{$interface->parents}[0];
+ push(@headerContent, " tmpl->Inherit(V8${parent}::getTmpl(isolate));\n");
+ }
+ push(@headerContent, <<END);
+ return tmpl;
+ }
+
+END
+
+}
+
+sub GenerateImplementationAttributes
+{
+ my $interface = shift;
+ my $interfaceName = $interface->name;
+ my $extensions = $interface->extendedAttributes;
+
+ # Generate property accessors for attributes.
+ for (my $index = 0; $index < @{$interface->attributes}; $index++) {
+ my $attribute = @{$interface->attributes}[$index];
+ my $attrType = $attribute->signature->type;
+ my $attrName = $attribute->signature->name;
+ my $attrExt = $attribute->signature->extendedAttributes;
+
+ my $wrapperRetType = IdlToWrapperType($attrType);
+ my $wrapperType = IdlToWrapperType($interfaceName);
+ my $wrapperGetter;
+
+ if ($attrExt->{'AttributeIsPublic'} || $extensions->{'AttributesArePublic'}) {
+ $wrapperGetter = $attrName;
+ } else {
+ $wrapperGetter = IdlToWrapperAttrGetter($interface, $attribute)."()";
+
+ }
+
+ # getter
+ if (!$attrExt->{'CustomGetter'}) {
+ push(@implContent, <<END);
+
+ void V8${interfaceName}::${attrName}AttrGetter(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ v8::Local<v8::Object> self = info.Holder();
+ struct V8${interfaceName}Private* privData = V8DOM::toClassPtr<V8${interfaceName}Private >(self->GetInternalField(0));
+END
+ if (IsWrapperType($attrType)) {
+ AddToImplIncludes("V8".$attrType.".h");
+ push(@implContent, "\n ".GenerateConditionalUndefReturn($interface, $attribute, "privData->nativeObj->${wrapperGetter}"));
+
+ push(@implContent, <<END);
+
+ ${wrapperRetType}* arbaicaRet = new ${wrapperRetType}(privData->nativeObj->${wrapperGetter});
+
+ v8::Handle<v8::Function> arbaicaRetCtor = V8${attrType}::getTmpl(isolate)->GetFunction();
+ v8::Persistent<v8::Object> arbaicaRetObj(isolate, arbaicaRetCtor->NewInstance());
+
+ struct V8${attrType}::V8${attrType}Private* retPrivData = new V8${attrType}::V8${attrType}Private();
+ retPrivData->dom = privData->dom;
+ retPrivData->nativeObj = arbaicaRet;
+
+ arbaicaRetObj.Get(isolate)->SetInternalField(0, V8DOM::toExternal(retPrivData));
+ arbaicaRetObj.SetWeak<V8${attrType}::V8${attrType}Private>(0, V8${attrType}::jsDestructor);
+ info.GetReturnValue().Set(arbaicaRetObj);
+ // return arbaicaRetObj;
+END
+ } else {
+ my $v8Type = IdlToV8Type($attrType);
+ if ($attrType eq "DOMString") {
+ if ($attrExt->{'EmptyAsNull'}) {
+ push(@implContent, "\n if (privData->nativeObj->${wrapperGetter}.length() == 0)");
+ push(@implContent, "\n return; //v8::Undefined(isolate);");
+ }
+ push(@implContent, "\n info.GetReturnValue().Set(${v8Type}::NewFromUtf8(isolate, privData->nativeObj->${wrapperGetter}.c_str()));");
+ # push(@implContent, "\n return ${v8Type}::New(privData->nativeObj->${wrapperGetter}.c_str());");
+ } else {
+ push(@implContent, "\n info.GetReturnValue().Set(${v8Type}::New(isolate, privData->nativeObj->${wrapperGetter}));");
+ }
+ }
+ push(@implContent, "\n }\n");
+ }
+
+ if (!$attrExt->{'CustomSetter'}) {
+ # setter
+ if (!IsReadonly($attribute)) {
+ my $wrapperSetter = IdlToWrapperAttrSetter($attrName);
+ push(@implContent, "\n void V8${interfaceName}::${attrName}AttrSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) {");
+ push(@implContent, "\n v8::Isolate* isolate = info.GetIsolate();");
+ 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", $interfaceName);
+
+ push(@implContent, "\n $handle");
+ push(@implContent, "\n privData->nativeObj->${wrapperSetter}(${deref});");
+ push(@implContent, "\n }\n");
+
+ }
+ }
+ }
+}
+
+sub GenerateConditionalUndefReturn
+{
+ my $interface = shift;
+ my $attribute = shift;
+ my $getterExpression = shift;
+
+ return "" if ($attribute->signature->type eq "NamedNodeMap");
+ return "" if ($attribute->signature->type eq "NodeList");
+ return "if (!$getterExpression) return; //v8::Undefined(isolate);";
+}
+
+sub GenerateConstructor
+{
+ my $interface = shift;
+ my $interfaceName = $interface->name;
+ my $wrapperType = IdlToWrapperType($interfaceName);
+ my $extensions = $interface->extendedAttributes;
+
+ if ($extensions->{'Constructors'}) {
+
+ push(@implContent, "\n void V8${interfaceName}::constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {");
+ push(@implContent, <<END);
+
+ v8::Isolate* isolate = info.GetIsolate();
+ if (!info.IsConstructCall()) {
+ isolate->ThrowException(v8::String::NewFromUtf8(isolate, "Cannot call constructor as function"));
+ return;
+ }
+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 (info.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, "info[$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), "info[$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}");
+ }
+
+ v8::Handle<v8::Function> retCtor = V8${interfaceName}::getTmpl(isolate)->GetFunction();
+ v8::Persistent<v8::Object> retObj(isolate, retCtor->NewInstance());
+
+ struct V8${interfaceName}::V8${interfaceName}Private* retPrivData = new V8${interfaceName}::V8${interfaceName}Private();
+ retPrivData->nativeObj = localInstance;
+
+ retObj.Get(isolate)->SetInternalField(0, V8DOM::toExternal(retPrivData));
+ retObj.SetWeak<V8${interfaceName}::V8${interfaceName}Private>(0, V8${interfaceName}::jsDestructor);
+
+ info.GetReturnValue().Set(retObj);
+ return;
+ }
+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}) {
+ my $name = $function->signature->name;
+ my $attrExt = $function->signature->extendedAttributes;
+ my $retType = $function->signature->type;
+ my $wrapperRetType = IdlToWrapperType($retType);
+
+ next if ($attrExt->{'Custom'});
+ 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);
+
+ void V8${interfaceName}::${name}Callback(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+END
+
+ # get this
+ 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));");
+
+ # 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
+ 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 (info.Length() == " . @{$variant});
+ for (my $i = 0; $i < @{$variant}; $i++) {
+ my $type = $variant->[$i]->{'domSignature::type'};
+ push(@implContent, " &&\n " . IdlToTypeChecker($type, "info[$i]"));
+ }
+ push(@implContent, ")\n {");
+ foreach my $parameter (@{$variant}) {
+ my $value = "info[$parameterIndex]";
+ my $type = $parameter->type;
+ AddToImplIncludes("V8".$type.".h") if (IsWrapperType($type));
+
+ my ($handle, $deref) = IdlToArgHandle($parameter->type, "local".ucfirst($parameter->name), "info[${parameterIndex}]", $interfaceName);
+ push(@implContent, "\n ${handle}");
+ 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");
+ }
+
+ # wrap return type if needed
+ if (IsWrapperType($retType)) {
+ AddToImplIncludes("V8".$retType.".h");
+
+ push(@implContent, <<END);
+ v8::Handle<v8::Function> retCtor = V8${retType}::getTmpl(isolate)->GetFunction();
+ v8::Persistent<v8::Object> retObj(isolate, retCtor->NewInstance());
+
+ struct V8${retType}::V8${retType}Private* retPrivData = new V8${retType}::V8${retType}Private();
+ retPrivData->dom = privData->dom;
+ retPrivData->nativeObj = retVal;
+
+ retObj.Get(isolate)->SetInternalField(0, V8DOM::toExternal(retPrivData));
+ retObj.SetWeak<V8${retType}::V8${retType}Private>(0, V8${retType}::jsDestructor);
+ info.GetReturnValue().Set(retObj);
+ //return retObj;
+END
+ } else {
+ my $toHandleString = NativeToHandle($retNativeType, "retVal");
+ push(@implContent, "\n info.GetReturnValue().Set(${toHandleString});");
+ }
+ }
+ push(@implContent, <<END);
+
+ }
+ throw V8Exception("Parameter mismatch while calling ${name}");
+ // return v8::Undefined(isolate);
+ }
+END
+ }
+
+}
+
+sub GenerateImplementation
+{
+ my $object = shift;
+ my $interface = shift;
+ my $interfaceName = $interface->name;
+ my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface);
+ my $v8InterfaceName = "V8$interfaceName";
+ my $wrapperType = IdlToWrapperType($interfaceName);
+ my $extensions = $interface->extendedAttributes;
+
+ AddToImplIncludes("V8${interfaceName}.h");
+
+ # Find the super descriptor.
+ my $parentClass = "";
+ my $parentClassTemplate = "";
+ foreach (@{$interface->parents}) {
+ my $parent = $_;
+ AddToImplIncludes("V8${parent}.h");
+ $parentClass = "V8" . $parent;
+ last;
+ }
+
+ push(@implContent, "namespace Arabica {\n");
+ push(@implContent, "namespace DOM {\n\n");
+
+ if ($extensions->{'Constructors'}) {
+ GenerateConstructor($interface);
+ }
+
+ GenerateImplementationAttributes($interface);
+ GenerateImplementationFunctionCallbacks($interface);
+
+
+ push(@implContent, <<END);
+ bool V8${interfaceName}::hasInstance(v8::Handle<v8::Value> value) {
+ return getTmpl(v8::Isolate::GetCurrent())->HasInstance(value);
+ }
+
+}
+}
+END
+
+ # We've already added the header for this file in implContentHeader, so remove
+ # it from implIncludes to ensure we don't #include it twice.
+# delete $implIncludes{"${v8InterfaceName}.h"};
+}
+
+sub WriteData
+{
+ my $object = shift;
+ my $interface = shift;
+ my $outputDir = shift;
+ my $outputHeadersDir = shift;
+
+ my $name = $interface->name;
+ my $prefix = FileNamePrefix;
+ my $headerFileName = "$outputHeadersDir/$prefix$name.h";
+ my $implFileName = "$outputDir/$prefix$name.cpp";
+
+ # print "WriteData\n";
+ # print Dumper($interface);
+ # exit();
+
+ # Update a .cpp file if the contents are changed.
+ my $contents = $headerTemplate;
+ $contents .= join "", @implContentHeader;
+
+ my @includes = ();
+ my %implIncludeConditions = ();
+ foreach my $include (keys %implIncludes) {
+ my $condition = $implIncludes{$include};
+ my $checkType = $include;
+ $checkType =~ s/\.h//;
+ next if $codeGenerator->IsSVGAnimatedType($checkType);
+
+ if ($include =~ /wtf/) {
+ $include = "\<$include\>";
+ } else {
+ $include = "\"$include\"";
+ }
+
+ if ($condition eq 1) {
+ push @includes, $include;
+ } else {
+ push @{$implIncludeConditions{$condition}}, $include;
+ }
+ }
+ foreach my $include (sort @includes) {
+ $contents .= "#include $include\n";
+ }
+ foreach my $condition (sort keys %implIncludeConditions) {
+ $contents .= "\n#if " . $codeGenerator->GenerateConditionalStringFromAttributeValue($condition) . "\n";
+ foreach my $include (sort @{$implIncludeConditions{$condition}}) {
+ $contents .= "#include $include\n";
+ }
+ $contents .= "#endif\n";
+ }
+
+ $contents .= "\n";
+ $contents .= join "", @implContentDecls, @implContent;
+ $codeGenerator->UpdateFile($implFileName, $contents);
+
+ %implIncludes = ();
+ @implContentHeader = ();
+ @implContentDecls = ();
+ @implContent = ();
+
+ # Update a .h file if the contents are changed.
+ $contents = join "", @headerContent;
+ $codeGenerator->UpdateFile($headerFileName, $contents);
+
+ @headerContent = ();
+}
+
+sub IdlToV8Type
+{
+ my $idlType = shift;
+ return "v8::Integer" if ($idlType eq "unsigned short");
+ return "v8::Integer" if ($idlType eq "short");
+ return "v8::Integer" if ($idlType eq "unsigned long");
+ return "v8::Integer" if ($idlType eq "long");
+ return "v8::String" if ($idlType eq "DOMString");
+ return "v8::Boolean" if ($idlType eq "boolean");
+ return "v8::Number" if ($idlType eq "double");
+ die($idlType);
+}
+
+sub IdlToNativeType
+{
+ my $idlType = shift;
+
+ return IdlToWrapperType($idlType) if (IsWrapperType($idlType));
+
+ return "std::string" if ($idlType eq "DOMString");
+ return "bool" if ($idlType eq "boolean");
+ return "short" if ($idlType eq "short");
+ return "long" if ($idlType eq "long");
+ return "unsigned short" if ($idlType eq "unsigned short");
+ return "unsigned long" if ($idlType eq "unsigned long");
+ return "void" if ($idlType eq "void");
+ return "char" if ($idlType eq "byte");
+ return "unsigned char" if ($idlType eq "octet");
+ return "double" if ($idlType eq "double");
+ return "float" if ($idlType eq "float");
+ die(${idlType});
+}
+
+sub NativeToHandle
+{
+ my $nativeType = shift;
+ my $nativeName = shift;
+
+ return ("v8::Boolean::New(isolate, ${nativeName})") if ($nativeType eq "bool");
+ return ("v8::Number::New(isolate, ${nativeName})") if ($nativeType eq "double");
+ return ("v8::Number::New(isolate, ${nativeName})") if ($nativeType eq "double");
+ return ("v8::Number::New(isolate, ${nativeName})") if ($nativeType eq "float");
+ return ("v8::Number::New(isolate, ${nativeName})") if ($nativeType eq "short");
+ return ("v8::Number::New(isolate, ${nativeName})") if ($nativeType eq "char");
+ return ("v8::Number::New(isolate, ${nativeName})") if ($nativeType eq "unsigned short");
+ return ("v8::Number::New(isolate, ${nativeName})") if ($nativeType eq "unsigned long");
+ return ("v8::Number::New(isolate, ${nativeName})") if ($nativeType eq "unsigned char");
+ return ("v8::Number::New(isolate, ${nativeName})") if ($nativeType eq "long");
+ return ("v8::String::NewFromUtf8(isolate, ${nativeName}.c_str())") if ($nativeType eq "std::string");
+ return ("v8::Undefined(isolate)") if ($nativeType eq "void");
+
+ die($nativeType);
+}
+
+sub IdlToWrapperType
+{
+ my $idlType = shift;
+ return "Arabica::XPath::XPathValue<std::string>" if ($idlType eq "XPathResult");
+ return "Arabica::XPath::NodeSet<std::string>" if ($idlType eq "NodeSet");
+ return "Arabica::DOM::Node<std::string>" if ($idlType eq "Node");
+ return "Arabica::DOM::Element<std::string>" if ($idlType eq "Element");
+ return "uscxml::Event" if ($idlType eq "SCXMLEvent");
+ return "uscxml::Storage" if ($idlType eq "Storage");
+ return "uscxml::ArrayBuffer" if ($idlType eq "ArrayBuffer");
+ return "uscxml::ArrayBufferView" if ($idlType eq "ArrayBufferView");
+ return "uscxml::Int8Array" if ($idlType eq "Int8Array");
+ return "uscxml::Uint8Array" if ($idlType eq "Uint8Array");
+ return "uscxml::Uint8ClampedArray" if ($idlType eq "Uint8ClampedArray");
+ return "uscxml::Int16Array" if ($idlType eq "Int16Array");
+ return "uscxml::Uint16Array" if ($idlType eq "Uint16Array");
+ return "uscxml::Int32Array" if ($idlType eq "Int32Array");
+ return "uscxml::Uint32Array" if ($idlType eq "Uint32Array");
+ return "uscxml::Float32Array" if ($idlType eq "Float32Array");
+ return "uscxml::Float64Array" if ($idlType eq "Float64Array");
+ return "uscxml::DataView" if ($idlType eq "DataView");
+ return "Arabica::DOM::${idlType}<std::string>";
+}
+
+sub IdlToArgHandle
+{
+ my $type = shift;
+ my $localName = shift;
+ my $paramName = shift;
+ my $thisType = shift;
+
+ return ("v8::String::Utf8Value ${localName}(${paramName});", "*${localName}") if ($type eq "DOMString");
+ return ("unsigned long ${localName} = ${paramName}->ToNumber()->Uint32Value();", ${localName}) if ($type eq "unsigned long");
+ return ("long ${localName} = ${paramName}->ToNumber()->Int32Value();", ${localName}) if ($type eq "long");
+ return ("double ${localName} = ${paramName}->ToNumber()->Value();", ${localName}) if ($type eq "double");
+ return ("float ${localName} = ${paramName}->ToNumber()->Value();", ${localName}) if ($type eq "float");
+ return ("unsigned short ${localName} = ${paramName}->ToNumber()->Uint32Value();", ${localName}) if ($type eq "unsigned short");
+ return ("bool ${localName} = ${paramName}->ToBoolean()->BooleanValue();", ${localName}) if ($type eq "boolean");
+ return ("char ${localName} = ${paramName}->ToNumber()->Int32Value();", ${localName}) if ($type eq "byte");
+ 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 ("void* ${localName} = v8::Handle<v8::External>::Cast(${paramName}->ToObject()->GetInternalField(0))->Value();", ${localName}) if ($type eq "any");
+ return ("std::vector<long> ${localName};\nv8::Handle<v8::Array> ${localName}Array = v8::Array::New(isolate, v8::Array::Cast(*info[0])->Length());\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::New(isolate, v8::Array::Cast(*info[0])->Length());\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::New(isolate, v8::Array::Cast(*info[0])->Length());\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::New(isolate, v8::Array::Cast(*info[0])->Length());\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::New(isolate, v8::Array::Cast(*info[0])->Length());\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::New(isolate, v8::Array::Cast(*info[0])->Length());\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::New(isolate, v8::Array::Cast(*info[0])->Length());\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::New(isolate, v8::Array::Cast(*info[0])->Length());\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}");
+ }
+
+ print $type."\n";
+ 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;
+ my $attribute = shift;
+
+ return $attribute->signature->name if ($interface->name eq "NodeSet" && $attribute->signature->name eq "size");
+ return $attribute->signature->name if ($interface->name eq "NodeSet" && $attribute->signature->name eq "empty");
+ return "asString" if ($interface->name eq "XPathResult" && $attribute->signature->name eq "stringValue");
+ return "asBool" if ($interface->name eq "XPathResult" && $attribute->signature->name eq "booleanValue");
+ return "asNumber" if ($interface->name eq "XPathResult" && $attribute->signature->name eq "numberValue");
+
+ return "get" . ucfirst($attribute->signature->name);
+}
+
+sub IdlToWrapperFunction
+{
+ my $interface = shift;
+ my $function = shift;
+
+ # if ($interface->name eq "NodeSet" && $function->signature->name eq "toDocumentOrder") {
+ # print Dumper($interface);
+ # print Dumper($function);
+ # }
+
+ return "to_document_order" if ($interface->name eq "NodeSet" && $function->signature->name eq "toDocumentOrder");
+
+ return $function->signature->name;
+
+}
+
+sub IdlToWrapperAttrSetter
+{
+ my $idlAttr = shift;
+ return "set" . ucfirst($idlAttr);
+}
+
+
+sub IsReadonly
+{
+ my $attribute = shift;
+ my $attrExt = $attribute->signature->extendedAttributes;
+ return ($attribute->type =~ /readonly/ || $attrExt->{"V8ReadOnly"}) && !$attrExt->{"Replaceable"};
+}
+
+
+my %non_wrapper_types = (
+ 'CompareHow' => 1,
+ 'DOMObject' => 1,
+ 'DOMString' => 1,
+ 'DOMString[]' => 1,
+ 'DOMTimeStamp' => 1,
+ 'Date' => 1,
+ 'Dictionary' => 1,
+ 'EventListener' => 1,
+ # FIXME: When EventTarget is an interface and not a mixin, fix this so that
+ # EventTarget is treated as a wrapper type.
+ 'EventTarget' => 1,
+ 'IDBKey' => 1,
+ 'JSObject' => 1,
+ 'MediaQueryListListener' => 1,
+ 'NodeFilter' => 1,
+ 'any' => 1,
+ 'boolean' => 1,
+ 'double' => 1,
+ 'float' => 1,
+ 'int' => 1,
+ 'long long' => 1,
+ '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 long[]' => 1,
+ 'unsigned short' => 1,
+ 'unsigned short[]' => 1
+);
+
+sub IsWrapperType
+{
+ my $type = shift;
+ return !($non_wrapper_types{$type});
+}
+
+sub GenerateHeaderContentHeader
+{
+ my $interface = shift;
+ my $v8InterfaceName = "V8" . $interface->name;
+ my $conditionalString = $codeGenerator->GenerateConditionalString($interface);
+
+ my @headerContentHeader = split("\r", $headerTemplate);
+
+ push(@headerContentHeader, "\n#if ${conditionalString}\n") if $conditionalString;
+ push(@headerContentHeader, "\n#ifndef ${v8InterfaceName}" . "_h");
+ push(@headerContentHeader, "\n#define ${v8InterfaceName}" . "_h\n\n");
+ return @headerContentHeader;
+}
+
+1;