diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-01-21 23:47:54 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2013-01-21 23:47:54 (GMT) |
commit | 3be96d1aa3024c1acc129e587f5d3165c9434e48 (patch) | |
tree | fae65a932b899ed9424a5a76b9b98562d979fe40 /contrib | |
parent | 3bda299c6d2efce71d76b44dea8e732a073304f3 (diff) | |
download | uscxml-3be96d1aa3024c1acc129e587f5d3165c9434e48.zip uscxml-3be96d1aa3024c1acc129e587f5d3165c9434e48.tar.gz uscxml-3be96d1aa3024c1acc129e587f5d3165c9434e48.tar.bz2 |
See detailed commitlog
- Started DirectoryMonitor invoker
- Refactored Invoker / IOProcessor interface
- Started with JavaScriptCore bindings
- Embedding applications can now use setParentQueue to receive events
sent to #_parent
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/dom/idl/SCXMLEvent.idl | 18 | ||||
-rw-r--r-- | contrib/dom/scripts/CodeGeneratorArabicaJSC.pm | 786 | ||||
-rw-r--r-- | contrib/dom/scripts/CodeGeneratorArabicaV8.pm | 89 | ||||
-rw-r--r-- | contrib/dom/scripts/make_jsc.sh | 1 |
4 files changed, 862 insertions, 32 deletions
diff --git a/contrib/dom/idl/SCXMLEvent.idl b/contrib/dom/idl/SCXMLEvent.idl new file mode 100644 index 0000000..f70c4d4 --- /dev/null +++ b/contrib/dom/idl/SCXMLEvent.idl @@ -0,0 +1,18 @@ +[ + AttributesArePublic, + DontDestroyWrapped +] interface SCXMLEvent { + + // NodeType + const unsigned short INTERNAL = 1; + const unsigned short EXTERNAL = 2; + const unsigned short PLATFORM = 3; + + readonly attribute unsigned short type; + readonly attribute DOMString name; + readonly attribute DOMString origin; + readonly attribute DOMString origintype; + readonly attribute Node dom; + readonly attribute DOMString sendid; + readonly attribute DOMString invokeid; +}; diff --git a/contrib/dom/scripts/CodeGeneratorArabicaJSC.pm b/contrib/dom/scripts/CodeGeneratorArabicaJSC.pm new file mode 100644 index 0000000..affa51f --- /dev/null +++ b/contrib/dom/scripts/CodeGeneratorArabicaJSC.pm @@ -0,0 +1,786 @@ +# 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 CodeGeneratorArabicaJSC; + +use strict; +use Data::Dumper; +use Carp qw/longmess cluck confess/; + +use constant FileNamePrefix => "JSC"; + +my $codeGenerator; + + +my @headerContent = (); +my @implContentHeader = (); +my @implContent = (); +my @implContentDecls = (); +my %implIncludes = (); +my %headerIncludes = (); + +# Default .h template +my $headerTemplate = << "EOF"; +/* + This file is part of the Arabica open source project. + This file has been generated by generate-bindings.pl. DO NOT MODIFY! + + 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. +*/ +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; + + # 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 "JSCbool.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{"uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom/JSCDOM.h"} = 1; + $headerIncludes{"DOM/Node.hpp"} = 1; + $headerIncludes{"JavaScriptCore/JavaScriptCore.h"} = 1; + + foreach (@{$interface->parents}) { + my $parent = $_; + $headerIncludes{"JSC${parent}.h"} = 1; + } + + foreach my $headerInclude (sort keys(%headerIncludes)) { + if ($headerInclude =~ /wtf|JavaScriptCore\/JavaScriptCore\.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 JSC${interfaceName} {"); + push(@headerContent, "\npublic:"); + + my $arabicaType = IdlToArabicaType($interfaceName); + push(@headerContent, <<END); + + struct JSC${interfaceName}Private { + JSCDOM* dom; + ${arabicaType}* arabicaThis; + }; +END + + push(@headerContent, "\n JSC_DESTRUCTOR(JSC${interfaceName}Private);"); + push(@headerContent, "\n"); + + + # callbacks for actual functions + foreach my $function (@{$interface->functions}) { + my $name = $function->signature->name; + my $attrExt = $function->signature->extendedAttributes; + my $custom = ($attrExt->{'Custom'} ? "Custom" : ""); + push(@headerContent, "\n static JSValueRef ${name}${custom}Callback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObj, size_t argumentCount, const JSValueRef* arguments, JSValueRef* exception);"); + } + 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 JSValueRef ${name}${customGetter}AttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception);"); + if (!IsReadonly($attribute)) { + push(@headerContent, "\n static bool ${name}${customSetter}AttrSetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef value, JSValueRef* exception);"); + } + } + + push(@headerContent, "\n"); + # constant getters + foreach my $constant (@{$interface->constants}) { + my $name = $constant->name; + push(@headerContent, "\n static JSValueRef ${name}ConstGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception);"); + } + + # if ($extensions->{'CustomIndexedGetter'}) { + # push(@headerContent, "\n static v8::Handle<v8::Value> indexedPropertyCustomGetter(uint32_t, const v8::AccessorInfo&);"); + # } + # if ($extensions->{'CustomIndexedSetter'}) { + # push(@headerContent, "\n static v8::Handle<v8::Value> indexedPropertyCustomSetter(uint32_t, v8::Local<v8::Value>, const v8::AccessorInfo&);"); + # } + # push(@headerContent, "\n"); + +# GenerateClassPrototypeHeader($interface); + + push(@headerContent, <<END); + + + static JSStaticValue staticValues[]; + static JSStaticFunction staticFunctions[]; + + static JSClassRef Tmpl; + static JSClassRef getTmpl() { + if (Tmpl == NULL) { + JSClassDefinition classDef = kJSClassDefinitionEmpty; + classDef.staticValues = staticValues; + classDef.staticFunctions = staticFunctions; + classDef.finalize = jsDestructor; + + Tmpl = JSClassCreate(&classDef); + JSClassRetain(Tmpl); + } + return Tmpl; + } + +END + + push(@headerContent, "\n};\n\n}\n}\n\n"); + push(@headerContent, "#endif // JSC${interfaceName}" . "_h\n"); + +} + +# +# Write class template prototype constructor +# +sub GenerateClassDefStatics +{ + my $interface = shift; + my $interfaceName = $interface->name; + my $extensions = $interface->extendedAttributes; + + push(@implContent, "\nJSStaticValue JSC${interfaceName}::staticValues[] = {"); + 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 = "${name}${customGetter}AttrGetter"; + my $setter = (IsReadonly($attribute) ? "0" : "${name}${customSetter}AttrSetter"); + my $flags = "kJSPropertyAttributeDontDelete"; + $flags .= " | kJSPropertyAttributeReadOnly" if (IsReadonly($attribute)); + push(@implContent, "\n { \"${name}\", ${getter}, ${setter}, ${flags} },"); + + } + + push(@implContent, "\n"); + foreach my $constant (@{$interface->constants}) { + my $name = $constant->name; + my $value = $constant->value; + my $getter = "${name}ConstGetter"; + my $flags = "kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly"; + push(@implContent, "\n { \"${name}\", ${getter}, 0, ${flags} },"); + } + + push(@implContent, "\n { 0, 0, 0, 0 }"); + push(@implContent, "\n};\n"); + + push(@implContent, "\nJSStaticFunction JSC${interfaceName}::staticFunctions[] = {"); + 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"; + push(@implContent, "\n { \"${name}\", ${callback}, ${flags} },"); + + } + push(@implContent, "\n { 0, 0, 0 }"); + push(@implContent, "\n};\n"); + +} + +sub GenerateImplementationAttributes +{ + my $interface = shift; + my $interfaceName = $interface->name; + + # 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 $arabicaRetType = IdlToArabicaType($attrType); + my $arabicaType = IdlToArabicaType($interfaceName); + my $arabicaGetter = IdlToArabicaAttrGetter($interface, $attribute); + + next if ($attrExt->{'Custom'}); + + # getter + if (!$attrExt->{'CustomGetter'}) { + push(@implContent, <<END); + +JSValueRef JSC${interfaceName}::${attrName}AttrGetter(JSContextRef ctx, JSObjectRef thisObj, JSStringRef propertyName, JSValueRef* exception) { + struct JSC${interfaceName}Private* privData = static_cast<JSC${interfaceName}::JSC${interfaceName}Private* >(JSObjectGetPrivate(thisObj)); +END + if (IsWrapperType($attrType)) { + AddToImplIncludes("JSC".$attrType.".h"); + push(@implContent, <<END); + ${arabicaRetType}* arbaicaRet = new ${arabicaRetType}(privData->arabicaThis->${arabicaGetter}()); + + struct JSC${attrType}::JSC${attrType}Private* retPrivData = new JSC${attrType}::JSC${attrType}Private(); + retPrivData->dom = privData->dom; + retPrivData->arabicaThis = arbaicaRet; + + JSObjectRef arbaicaRetObj = JSObjectMake(ctx, JSC${attrType}::getTmpl(), retPrivData); + return arbaicaRetObj; +END + } else { + my $jscType = IdlToJSCType($attrType); + if ($attrType eq "DOMString") { + push(@implContent, <<END); + JSStringRef retString = JSStringCreateWithUTF8CString(privData->arabicaThis->${arabicaGetter}().c_str()); + JSValueRef retObj = JSValueMakeString(ctx, retString); + JSStringRelease(retString); + return retObj; +END + } else { + push(@implContent, "\n return ${jscType}(ctx, privData->arabicaThis->${arabicaGetter}());"); + } + } + push(@implContent, "\n}\n"); + } + + if (!$attrExt->{'CustomSetter'}) { + # setter + if (!IsReadonly($attribute) && 0) { + my $arabicaSetter = IdlToArabicaAttrSetter($attrName); + push(@implContent, "\n void JSC${interfaceName}::${attrName}AttrSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) {"); + push(@implContent, "\n v8::Local<v8::Object> self = info.Holder();"); + push(@implContent, "\n struct JSC${interfaceName}Private* privData = JSCDOM::toClassPtr<JSC${interfaceName}Private >(self->GetInternalField(0));"); + + my ($handle, $deref) = IdlToArgHandle($attribute->signature->type, "local".ucfirst($attribute->signature->name), "value"); + + push(@implContent, "\n $handle"); + push(@implContent, "\n privData->arabicaThis->${arabicaSetter}(${deref});"); + push(@implContent, "\n }\n"); + + } + } + } +} + +sub GenerateImplementationFunctionCallbacks +{ + my $interface = shift; + my $interfaceName = $interface->name; + my $arabicaType = IdlToArabicaType($interfaceName); + + # Generate methods for functions. + foreach my $function (@{$interface->functions}) { + my $name = $function->signature->name; + my $attrExt = $function->signature->extendedAttributes; + my $retType = $function->signature->type; + my $arabicaRetType = IdlToArabicaType($retType); + + next if ($attrExt->{'Custom'}); + + # signature + push(@implContent, <<END); + v8::Handle<v8::Value> JSC${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 JSCException(\"Parameter mismatch while calling ${name}\"); +END + + # get this + push(@implContent, "\n v8::Local<v8::Object> self = args.Holder();"); + push(@implContent, "\n struct JSC${interfaceName}Private* privData = JSCDOM::toClassPtr<JSC${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("JSC".$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++; + } + + # invoke native function with argument handles + my $retNativeType = IdlToNativeType($retType); + my $arabicaFunctionName = IdlToArabicaFunction($interface, $function); + if (IsWrapperType($retType)) { + push(@implContent, "\n\n ${retNativeType}* retVal = new $arabicaRetType(privData->arabicaThis->${arabicaFunctionName}(" . join(", ", @argList) . "));\n"); + } elsif ($retNativeType eq "void") { + push(@implContent, "\n\n privData->arabicaThis->${arabicaFunctionName}(" . join(", ", @argList) . ");\n"); + } else { + push(@implContent, "\n\n ${retNativeType} retVal = privData->arabicaThis->${arabicaFunctionName}(" . join(", ", @argList) . ");\n"); + } + + # wrap return type if needed + if (IsWrapperType($retType)) { + AddToImplIncludes("JSC".$retType.".h"); + + push(@implContent, <<END); + v8::Handle<v8::Function> retCtor = JSC${retType}::getTmpl()->GetFunction(); + v8::Persistent<v8::Object> retObj = v8::Persistent<v8::Object>::New(retCtor->NewInstance()); + + struct JSC${retType}::JSC${retType}Private* retPrivData = new JSC${retType}::JSC${retType}Private(); + retPrivData->dom = privData->dom; + retPrivData->arabicaThis = retVal; + + retObj->SetInternalField(0, JSCDOM::toExternal(retPrivData)); + + retObj.MakeWeak(0, JSC${retType}::jsDestructor); + return retObj; +END + } else { + my $toHandleString = NativeToHandle($retNativeType, "retVal"); + push(@implContent, "\n return ${toHandleString};"); + } + + push(@implContent, "\n }\n\n"); + } + +} + +sub GenerateImplementation +{ + my $object = shift; + my $interface = shift; + my $interfaceName = $interface->name; + my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface); + my $v8InterfaceName = "JSC$interfaceName"; + my $arabicaType = IdlToArabicaType($interfaceName); + + AddToImplIncludes("JSC${interfaceName}.h"); + + # Find the super descriptor. + my $parentClass = ""; + my $parentClassTemplate = ""; + foreach (@{$interface->parents}) { + my $parent = $_; + AddToImplIncludes("JSC${parent}.h"); + $parentClass = "JSC" . $parent; + last; + } + push(@implContent, "namespace Arabica {\n"); + push(@implContent, "namespace DOM {\n\n"); + + GenerateClassDefStatics($interface); + GenerateImplementationAttributes($interface); +# GenerateImplementationFunctionCallbacks($interface); + + push(@implContent, <<END); + +} +} +END +} + +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 = 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 IdlToJSCType +{ + my $idlType = shift; + return "JSValueMakeNumber" if ($idlType eq "unsigned short"); + return "JSValueMakeNumber" if ($idlType eq "short"); + return "JSValueMakeNumber" if ($idlType eq "unsigned long"); + return "JSValueMakeNumber" if ($idlType eq "long"); + return "JSValueMakeString" if ($idlType eq "DOMString"); + return "JSValueMakeBoolean" if ($idlType eq "boolean"); + return "JSValueMakeNumber" if ($idlType eq "double"); + die($idlType); +} + +sub IdlToNativeType +{ + my $idlType = shift; + + return IdlToArabicaType($idlType) if (IsWrapperType($idlType)); + + return "std::string" if ($idlType eq "DOMString"); + return "bool" if ($idlType eq "boolean"); + return "void" if ($idlType eq "void"); + return "double" if ($idlType eq "double"); + die(${idlType}); +} + +sub NativeToHandle +{ + my $nativeType = shift; + my $nativeName = shift; + + return ("v8::Boolean::New(${nativeName})") if ($nativeType eq "bool"); + return ("v8::Number::New(${nativeName})") if ($nativeType eq "double"); + return ("v8::String::New(${nativeName}.c_str())") if ($nativeType eq "std::string"); + return ("v8::Undefined()") if ($nativeType eq "void"); + + die($nativeType); +} + +sub IdlToArabicaType +{ + 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 "Arabica::DOM::${idlType}<std::string>"; +} + +sub IdlToArgHandle +{ + my $type = shift; + my $localName = shift; + my $paramName = 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"); + return ("unsigned short ${localName} = ${paramName}->ToNumber()->Uint32Value();", ${localName}) if ($type eq "unsigned short"); + return ("bool ${localName} = ${paramName}->ToBoolean()->BooleanValue();", ${localName}) if ($type eq "boolean"); + + if (IsWrapperType($type)) { + my $arabicaType = IdlToArabicaType($type); + return ("${arabicaType}* ${localName} = JSCDOM::toClassPtr<JSC${type}::JSC${type}Private >(${paramName}->ToObject()->GetInternalField(0))->arabicaThis;", "*${localName}"); + } + + print $type."\n"; + die(); +} + +sub IdlToArabicaAttrGetter +{ + 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 IdlToArabicaFunction +{ + 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 IdlToArabicaAttrSetter +{ + my $idlAttr = shift; + return "set" . ucfirst($idlAttr); +} + + +sub IsReadonly +{ + my $attribute = shift; + my $attrExt = $attribute->signature->extendedAttributes; + return ($attribute->type =~ /readonly/ || $attrExt->{"JSCReadOnly"}) && !$attrExt->{"Replaceable"}; +} + + +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 JSCException(\"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() || JSC${type}::hasInstance($value))"); + } else { + push(@andExpression, "(JSC${type}::hasInstance($value))"); + } + } + + $parameterIndex++; + } + my $res = join(" && ", @andExpression); + $res = "($res)" if @andExpression > 1; + return $res; +} + + +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, + 'SerializedScriptValue' => 1, + 'any' => 1, + 'boolean' => 1, + 'double' => 1, + 'float' => 1, + 'int' => 1, + 'long long' => 1, + 'long' => 1, + 'short' => 1, + 'void' => 1, + 'unsigned int' => 1, + 'unsigned long long' => 1, + 'unsigned long' => 1, + 'unsigned short' => 1 +); + +sub IsWrapperType +{ + my $type = shift; + return !($non_wrapper_types{$type}); +} + +sub GenerateHeaderContentHeader +{ + my $interface = shift; + my $v8InterfaceName = "JSC" . $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; diff --git a/contrib/dom/scripts/CodeGeneratorArabicaV8.pm b/contrib/dom/scripts/CodeGeneratorArabicaV8.pm index 3382c24..738e981 100644 --- a/contrib/dom/scripts/CodeGeneratorArabicaV8.pm +++ b/contrib/dom/scripts/CodeGeneratorArabicaV8.pm @@ -47,7 +47,7 @@ my %headerIncludes = (); # Default .h template my $headerTemplate = << "EOF"; /* - This file is part of the Arabica open source project. + This file is part of the Wrapper open source project. This file has been generated by generate-bindings.pl. DO NOT MODIFY! This library is free software; you can redistribute it and/or @@ -161,16 +161,20 @@ sub GenerateHeader push(@headerContent, "\nclass V8${interfaceName} {"); push(@headerContent, "\npublic:"); - my $arabicaType = IdlToArabicaType($interfaceName); + my $wrapperType = IdlToWrapperType($interfaceName); push(@headerContent, <<END); struct V8${interfaceName}Private { V8DOM* dom; - ${arabicaType}* arabicaThis; + ${wrapperType}* nativeObj; }; END - push(@headerContent, "\n V8_DESTRUCTOR(V8${interfaceName}Private);"); + 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"); @@ -270,8 +274,8 @@ END my $value = $constant->value; my $type = IdlToV8Type($constant->type); push(@headerContent, <<END); - tmpl->Set(v8::String::NewSymbol("${name}"), ${type}::New(${value}), v8::ReadOnly); - prototype->Set(v8::String::NewSymbol("${name}"), ${type}::New(${value}), v8::ReadOnly); + tmpl->Set(v8::String::NewSymbol("${name}"), ${type}::New(${value}), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum)); + prototype->Set(v8::String::NewSymbol("${name}"), ${type}::New(${value}), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontEnum)); END } @@ -294,6 +298,7 @@ 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++) { @@ -302,11 +307,16 @@ sub GenerateImplementationAttributes my $attrName = $attribute->signature->name; my $attrExt = $attribute->signature->extendedAttributes; - my $arabicaRetType = IdlToArabicaType($attrType); - my $arabicaType = IdlToArabicaType($interfaceName); - my $arabicaGetter = IdlToArabicaAttrGetter($interface, $attribute); - - next if ($attrExt->{'Custom'}); + 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'}) { @@ -318,15 +328,18 @@ sub GenerateImplementationAttributes END if (IsWrapperType($attrType)) { AddToImplIncludes("V8".$attrType.".h"); + push(@implContent, "\n ".GenerateConditionalUndefReturn($interface, $attribute, "privData->nativeObj->${wrapperGetter}")); + push(@implContent, <<END); - ${arabicaRetType}* arbaicaRet = new ${arabicaRetType}(privData->arabicaThis->${arabicaGetter}()); + + ${wrapperRetType}* arbaicaRet = new ${wrapperRetType}(privData->nativeObj->${wrapperGetter}); v8::Handle<v8::Function> arbaicaRetCtor = V8${attrType}::getTmpl()->GetFunction(); v8::Persistent<v8::Object> arbaicaRetObj = v8::Persistent<v8::Object>::New(arbaicaRetCtor->NewInstance()); struct V8${attrType}::V8${attrType}Private* retPrivData = new V8${attrType}::V8${attrType}Private(); retPrivData->dom = privData->dom; - retPrivData->arabicaThis = arbaicaRet; + retPrivData->nativeObj = arbaicaRet; arbaicaRetObj->SetInternalField(0, V8DOM::toExternal(retPrivData)); arbaicaRetObj.MakeWeak(0, V8${attrType}::jsDestructor); @@ -335,9 +348,9 @@ END } else { my $v8Type = IdlToV8Type($attrType); if ($attrType eq "DOMString") { - push(@implContent, "\n return ${v8Type}::New(privData->arabicaThis->${arabicaGetter}().c_str());"); + push(@implContent, "\n return ${v8Type}::New(privData->nativeObj->${wrapperGetter}.c_str());"); } else { - push(@implContent, "\n return ${v8Type}::New(privData->arabicaThis->${arabicaGetter}());"); + push(@implContent, "\n return ${v8Type}::New(privData->nativeObj->${wrapperGetter});"); } } push(@implContent, "\n }\n"); @@ -346,7 +359,7 @@ END if (!$attrExt->{'CustomSetter'}) { # setter if (!IsReadonly($attribute)) { - my $arabicaSetter = IdlToArabicaAttrSetter($attrName); + my $wrapperSetter = IdlToWrapperAttrSetter($attrName); push(@implContent, "\n void V8${interfaceName}::${attrName}AttrSetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info) {"); 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));"); @@ -354,7 +367,7 @@ END my ($handle, $deref) = IdlToArgHandle($attribute->signature->type, "local".ucfirst($attribute->signature->name), "value"); push(@implContent, "\n $handle"); - push(@implContent, "\n privData->arabicaThis->${arabicaSetter}(${deref});"); + push(@implContent, "\n privData->nativeObj->${wrapperSetter}(${deref});"); push(@implContent, "\n }\n"); } @@ -362,18 +375,29 @@ END } } +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();"; +} + sub GenerateImplementationFunctionCallbacks { my $interface = shift; my $interfaceName = $interface->name; - my $arabicaType = IdlToArabicaType($interfaceName); + my $wrapperType = IdlToWrapperType($interfaceName); # Generate methods for functions. foreach my $function (@{$interface->functions}) { my $name = $function->signature->name; my $attrExt = $function->signature->extendedAttributes; my $retType = $function->signature->type; - my $arabicaRetType = IdlToArabicaType($retType); + my $wrapperRetType = IdlToWrapperType($retType); next if ($attrExt->{'Custom'}); @@ -412,13 +436,13 @@ END # invoke native function with argument handles my $retNativeType = IdlToNativeType($retType); - my $arabicaFunctionName = IdlToArabicaFunction($interface, $function); + my $wrapperFunctionName = IdlToWrapperFunction($interface, $function); if (IsWrapperType($retType)) { - push(@implContent, "\n\n ${retNativeType}* retVal = new $arabicaRetType(privData->arabicaThis->${arabicaFunctionName}(" . join(", ", @argList) . "));\n"); + push(@implContent, "\n\n ${retNativeType}* retVal = new $wrapperRetType(privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . "));\n"); } elsif ($retNativeType eq "void") { - push(@implContent, "\n\n privData->arabicaThis->${arabicaFunctionName}(" . join(", ", @argList) . ");\n"); + push(@implContent, "\n\n privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); } else { - push(@implContent, "\n\n ${retNativeType} retVal = privData->arabicaThis->${arabicaFunctionName}(" . join(", ", @argList) . ");\n"); + push(@implContent, "\n\n ${retNativeType} retVal = privData->nativeObj->${wrapperFunctionName}(" . join(", ", @argList) . ");\n"); } # wrap return type if needed @@ -431,7 +455,7 @@ END struct V8${retType}::V8${retType}Private* retPrivData = new V8${retType}::V8${retType}Private(); retPrivData->dom = privData->dom; - retPrivData->arabicaThis = retVal; + retPrivData->nativeObj = retVal; retObj->SetInternalField(0, V8DOM::toExternal(retPrivData)); @@ -455,7 +479,7 @@ sub GenerateImplementation my $interfaceName = $interface->name; my $visibleInterfaceName = $codeGenerator->GetVisibleInterfaceName($interface); my $v8InterfaceName = "V8$interfaceName"; - my $arabicaType = IdlToArabicaType($interfaceName); + my $wrapperType = IdlToWrapperType($interfaceName); AddToImplIncludes("V8${interfaceName}.h"); @@ -572,7 +596,7 @@ sub IdlToNativeType { my $idlType = shift; - return IdlToArabicaType($idlType) if (IsWrapperType($idlType)); + return IdlToWrapperType($idlType) if (IsWrapperType($idlType)); return "std::string" if ($idlType eq "DOMString"); return "bool" if ($idlType eq "boolean"); @@ -594,13 +618,14 @@ sub NativeToHandle die($nativeType); } -sub IdlToArabicaType +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 "Arabica::DOM::${idlType}<std::string>"; } @@ -616,15 +641,15 @@ sub IdlToArgHandle return ("bool ${localName} = ${paramName}->ToBoolean()->BooleanValue();", ${localName}) if ($type eq "boolean"); if (IsWrapperType($type)) { - my $arabicaType = IdlToArabicaType($type); - return ("${arabicaType}* ${localName} = V8DOM::toClassPtr<V8${type}::V8${type}Private >(${paramName}->ToObject()->GetInternalField(0))->arabicaThis;", "*${localName}"); + my $wrapperType = IdlToWrapperType($type); + return ("${wrapperType}* ${localName} = V8DOM::toClassPtr<V8${type}::V8${type}Private >(${paramName}->ToObject()->GetInternalField(0))->nativeObj;", "*${localName}"); } print $type."\n"; die(); } -sub IdlToArabicaAttrGetter +sub IdlToWrapperAttrGetter { my $interface = shift; my $attribute = shift; @@ -638,7 +663,7 @@ sub IdlToArabicaAttrGetter return "get" . ucfirst($attribute->signature->name); } -sub IdlToArabicaFunction +sub IdlToWrapperFunction { my $interface = shift; my $function = shift; @@ -654,7 +679,7 @@ sub IdlToArabicaFunction } -sub IdlToArabicaAttrSetter +sub IdlToWrapperAttrSetter { my $idlAttr = shift; return "set" . ucfirst($idlAttr); diff --git a/contrib/dom/scripts/make_jsc.sh b/contrib/dom/scripts/make_jsc.sh new file mode 100644 index 0000000..97ced82 --- /dev/null +++ b/contrib/dom/scripts/make_jsc.sh @@ -0,0 +1 @@ +find ../idl/ -name *.idl -exec ./generate-bindings.pl --outputDir=/Users/sradomski/Documents/TK/Code/uscxml/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/dom --include=../idl/ --generator=ArabicaJSC {} \; |