| #!/usr/bin/python |
| # |
| # Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| # for details. All rights reserved. Use of this source code is governed by a |
| # BSD-style license that can be found in the LICENSE file. |
| |
| """Generates sdk/lib/_blink/dartium/_blink_dartium.dart file.""" |
| |
| import os |
| |
| from generator import AnalyzeOperation, AnalyzeConstructor |
| |
| HEADER = """/* Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| * for details. All rights reserved. Use of this source code is governed by a |
| * BSD-style license that can be found in the LICENSE file. |
| * |
| * DO NOT EDIT |
| * Auto-generated _blink library. |
| */ |
| library dart.dom._blink; |
| |
| import 'dart:js' as js; |
| import 'dart:html' show DomException; |
| // This is a place to put custom renames if we need them. |
| final resolverMap = { |
| }; |
| |
| dynamic resolver(String s) { |
| """ |
| |
| END_RESOLVER = """ |
| // Failed to find it, check for custom renames |
| dynamic obj = resolverMap[s]; |
| if (obj != null) return obj; |
| throw("No such interface exposed in blink: ${s}"); |
| } |
| |
| """ |
| |
| BLINK_UTILS = """ |
| // _Utils native entry points |
| class Blink_Utils { |
| static window() native "Utils_window"; |
| |
| static forwardingPrint(message) native "Utils_forwardingPrint"; |
| |
| static spawnDomUri(uri) native "Utils_spawnDomUri"; |
| |
| static void spawnDomHelper(Function f, int replyTo) native "Utils_spawnDomHelper"; |
| |
| static register(document, tag, customType, extendsTagName) native "Utils_register"; |
| |
| static createElement(document, tagName) native "Utils_createElement"; |
| |
| static constructElement(element_type, jsObject) native "Utils_constructor_create"; |
| |
| static initializeCustomElement(element) native "Utils_initializeCustomElement"; |
| |
| static changeElementWrapper(element, type) native "Utils_changeElementWrapper"; |
| } |
| |
| class Blink_DOMWindowCrossFrame { |
| // FIXME: Return to using explicit cross frame entry points after roll to M35 |
| static get_history(_DOMWindowCrossFrame) native "Window_history_cross_frame_Getter"; |
| |
| static get_location(_DOMWindowCrossFrame) native "Window_location_cross_frame_Getter"; |
| |
| static get_closed(_DOMWindowCrossFrame) native "Window_closed_Getter"; |
| |
| static get_opener(_DOMWindowCrossFrame) native "Window_opener_Getter"; |
| |
| static get_parent(_DOMWindowCrossFrame) native "Window_parent_Getter"; |
| |
| static get_top(_DOMWindowCrossFrame) native "Window_top_Getter"; |
| |
| static close(_DOMWindowCrossFrame) native "Window_close_Callback"; |
| |
| static postMessage(_DOMWindowCrossFrame, message, targetOrigin, [messagePorts]) native "Window_postMessage_Callback"; |
| } |
| |
| class Blink_HistoryCrossFrame { |
| // _HistoryCrossFrame native entry points |
| static back(_HistoryCrossFrame) native "History_back_Callback"; |
| |
| static forward(_HistoryCrossFrame) native "History_forward_Callback"; |
| |
| static go(_HistoryCrossFrame, distance) native "History_go_Callback"; |
| } |
| |
| class Blink_LocationCrossFrame { |
| // _LocationCrossFrame native entry points |
| static set_href(_LocationCrossFrame, h) native "Location_href_Setter"; |
| } |
| |
| class Blink_DOMStringMap { |
| // _DOMStringMap native entry points |
| static containsKey(_DOMStringMap, key) native "DOMStringMap_containsKey_Callback"; |
| |
| static item(_DOMStringMap, key) native "DOMStringMap_item_Callback"; |
| |
| static setItem(_DOMStringMap, key, value) native "DOMStringMap_setItem_Callback"; |
| |
| static remove(_DOMStringMap, key) native "DOMStringMap_remove_Callback"; |
| |
| static get_keys(_DOMStringMap) native "DOMStringMap_getKeys_Callback"; |
| } |
| |
| // Calls through JsNative but returns DomException instead of error strings. |
| class Blink_JsNative_DomException { |
| static getProperty(js.JsObject o, name) { |
| try { |
| return js.JsNative.getProperty(o, name); |
| } catch (e) { |
| // Re-throw any errors (returned as a string) as a DomException. |
| throw new DomException.jsInterop(e); |
| } |
| } |
| |
| static callMethod(js.JsObject o, String method, List args) { |
| try { |
| return js.JsNative.callMethod(o, method, args); |
| } catch (e) { |
| // Re-throw any errors (returned as a string) as a DomException. |
| throw new DomException.jsInterop(e); |
| } |
| } |
| }""" |
| |
| CLASS_DEFINITION = """class Blink%s { |
| static final instance = new Blink%s(); |
| |
| """ |
| |
| CLASS_DEFINITION_EXTENDS = """class Blink%s extends Blink%s { |
| static final instance = new Blink%s(); |
| |
| """ |
| |
| #(interface_name) |
| CONSTRUCTOR_0 = ' constructorCallback_0_() => new js.JsObject(Blink_JsNative_DomException.getProperty(js.context, "%s"), []);\n\n' |
| |
| #(argument_count, arguments, interface_name, arguments) |
| CONSTRUCTOR_ARGS = ' constructorCallback_%s_(%s) => new js.JsObject(Blink_JsNative_DomException.getProperty(js.context, "%s"), [%s]);\n\n' |
| |
| #(attribute_name, attribute_name) |
| ATTRIBUTE_GETTER = ' %s_Getter_(mthis) => Blink_JsNative_DomException.getProperty(mthis, "%s");\n\n' |
| ATTRIBUTE_SETTER = ' %s_Setter_(mthis, __arg_0) => mthis["%s"] = __arg_0;\n\n' |
| |
| #(operation_name, operationName) |
| OPERATION_0 = ' %s_Callback_0_(mthis) => Blink_JsNative_DomException.callMethod(mthis, "%s", []);\n\n' |
| |
| # getter, setter, deleter and propertyQuery code |
| OPERATION_1 = ' $%s_Callback_1_(mthis, __arg_0) => Blink_JsNative_DomException.callMethod(mthis, "%s", [__arg_0]);\n\n' |
| OPERATION_2 = ' $%s_Callback_2_(mthis, __arg_0, __arg_1) => Blink_JsNative_DomException.callMethod(mthis, "%s", [__arg_0, __arg_1]);\n\n' |
| OPERATION_PQ = ' $%s_Callback_1_(mthis, __arg_0) => mthis[__arg_0];\n\n' |
| |
| #(operation_name, argument_count, arguments, operation_name, arguments) |
| ARGUMENT_NUM = "__arg_%s" |
| OPERATION_ARGS = ' %s_Callback_%s_(mthis, %s) => Blink_JsNative_DomException.callMethod(mthis, "%s", [%s]);\n\n' |
| |
| # get class property to make static call. |
| CLASS_STATIC = 'Blink_JsNative_DomException.getProperty(js.context, "%s")' |
| |
| # name, classname_getproperty, name |
| STATIC_ATTRIBUTE_GETTER = ' %s_Getter_() => Blink_JsNative_DomException.getProperty(%s, "%s");\n\n' |
| |
| # name, classname_getproperty, name |
| STATIC_OPERATION_0 = ' %s_Callback_0_() => Blink_JsNative_DomException.callMethod(%s, "%s", []);\n\n' |
| |
| # name, argsCount, args, classname_getproperty, name, args |
| STATIC_OPERATION_ARGS = ' %s_Callback_%s_(%s) => Blink_JsNative_DomException.callMethod(%s, "%s", [%s]);\n\n' |
| |
| CLASS_DEFINITION_END = """} |
| |
| """ |
| |
| def ConstantOutputOrder(a, b): |
| """Canonical output ordering for constants.""" |
| return cmp(a.id, b.id) |
| |
| def generate_parameter_entries(param_infos): |
| optional_default_args = 0; |
| for argument in param_infos: |
| if argument.is_optional: |
| optional_default_args += 1 |
| |
| arg_count = len(param_infos) |
| min_arg_count = arg_count - optional_default_args |
| lb = min_arg_count - 2 if min_arg_count > 2 else 0 |
| return (lb, arg_count + 1) |
| |
| constructor_renames = { |
| 'RTCPeerConnection': 'webkitRTCPeerConnection', |
| 'SpeechRecognition': 'webkitSpeechRecognition', |
| } |
| |
| def rename_constructor(name): |
| return constructor_renames[name] if name in constructor_renames else name |
| |
| def Generate_Blink(output_dir, database, type_registry): |
| blink_filename = os.path.join(output_dir, '_blink_dartium.dart') |
| blink_file = open(blink_filename, 'w') |
| |
| blink_file.write(HEADER); |
| |
| interfaces = database.GetInterfaces() |
| for interface in interfaces: |
| name = interface.id |
| resolver_entry = ' if (s == "%s") return Blink%s.instance;\n' % (name, name) |
| blink_file.write(resolver_entry) |
| |
| blink_file.write(END_RESOLVER); |
| |
| for interface in interfaces: |
| name = interface.id |
| |
| if interface.parents and len(interface.parents) > 0 and interface.parents[0].id: |
| extends = interface.parents[0].id |
| class_def = CLASS_DEFINITION_EXTENDS % (name, extends, name) |
| else: |
| class_def = CLASS_DEFINITION % (name, name) |
| blink_file.write(class_def); |
| |
| analyzed_constructors = AnalyzeConstructor(interface) |
| if analyzed_constructors: |
| _Emit_Blink_Constructors(blink_file, analyzed_constructors) |
| elif 'Constructor' in interface.ext_attrs: |
| # Zero parameter constructor. |
| blink_file.write(CONSTRUCTOR_0 % rename_constructor(name)) |
| |
| _Process_Attributes(blink_file, interface, interface.attributes) |
| _Process_Operations(blink_file, interface, interface.operations) |
| |
| secondary_parents = database.TransitiveSecondaryParents(interface, False) |
| for secondary in secondary_parents: |
| _Process_Attributes(blink_file, secondary, secondary.attributes) |
| _Process_Operations(blink_file, secondary, secondary.operations) |
| |
| blink_file.write(CLASS_DEFINITION_END); |
| |
| blink_file.write(BLINK_UTILS) |
| |
| blink_file.close() |
| |
| def _Emit_Blink_Constructors(blink_file, analyzed_constructors): |
| (arg_min_count, arg_max_count) = generate_parameter_entries(analyzed_constructors.param_infos) |
| name = analyzed_constructors.js_name |
| if not(name): |
| name = analyzed_constructors.type_name |
| |
| for callback_index in range(arg_min_count, arg_max_count): |
| if callback_index == 0: |
| blink_file.write(CONSTRUCTOR_0 % (rename_constructor(name))) |
| else: |
| arguments = [] |
| for i in range(0, callback_index): |
| arguments.append(ARGUMENT_NUM % i) |
| argument_list = ', '.join(arguments) |
| blink_file.write(CONSTRUCTOR_ARGS % (callback_index, argument_list, rename_constructor(name), argument_list)) |
| |
| def _Process_Attributes(blink_file, interface, attributes): |
| # Emit an interface's attributes and operations. |
| for attribute in sorted(attributes, ConstantOutputOrder): |
| name = attribute.id |
| if attribute.is_read_only: |
| if attribute.is_static: |
| class_property = CLASS_STATIC % interface.id |
| blink_file.write(STATIC_ATTRIBUTE_GETTER % (name, class_property, name)) |
| else: |
| blink_file.write(ATTRIBUTE_GETTER % (name, name)) |
| else: |
| blink_file.write(ATTRIBUTE_GETTER % (name, name)) |
| blink_file.write(ATTRIBUTE_SETTER % (name, name)) |
| |
| def _Process_Operations(blink_file, interface, operations): |
| analyzeOperations = [] |
| |
| for operation in sorted(operations, ConstantOutputOrder): |
| if len(analyzeOperations) == 0: |
| analyzeOperations.append(operation) |
| else: |
| if analyzeOperations[0].id == operation.id: |
| # Handle overloads |
| analyzeOperations.append(operation) |
| else: |
| _Emit_Blink_Operation(blink_file, interface, analyzeOperations) |
| analyzeOperations = [operation] |
| if len(analyzeOperations) > 0: |
| _Emit_Blink_Operation(blink_file, interface, analyzeOperations) |
| |
| def _Emit_Blink_Operation(blink_file, interface, analyzeOperations): |
| analyzed = AnalyzeOperation(interface, analyzeOperations) |
| (arg_min_count, arg_max_count) = generate_parameter_entries(analyzed.param_infos) |
| name = analyzed.js_name |
| |
| operation = analyzeOperations[0] |
| if (name.startswith('__') and \ |
| ('getter' in operation.specials or \ |
| 'setter' in operation.specials or \ |
| 'deleter' in operation.specials)): |
| if name == '__propertyQuery__': |
| blink_file.write(OPERATION_PQ % (name)) |
| else: |
| arg_min_count = arg_max_count |
| if arg_max_count == 2: |
| blink_file.write(OPERATION_1 % (name, name)) |
| elif arg_max_count == 3: |
| blink_file.write(OPERATION_2 % (name, name)) |
| else: |
| print "FATAL ERROR: _blink emitter operator %s.%s" % (interface.id, name) |
| exit |
| |
| return |
| |
| for callback_index in range(arg_min_count, arg_max_count): |
| if callback_index == 0: |
| if operation.is_static: |
| class_property = CLASS_STATIC % interface.id |
| blink_file.write(STATIC_OPERATION_0 % (name, class_property, name)) |
| else: |
| blink_file.write(OPERATION_0 % (name, name)) |
| else: |
| arguments = [] |
| for i in range(0, callback_index): |
| arguments.append(ARGUMENT_NUM % i) |
| argument_list = ', '.join(arguments) |
| if operation.is_static: |
| class_property = CLASS_STATIC % interface.id |
| blink_file.write(STATIC_OPERATION_ARGS % (name, callback_index, argument_list, class_property, name, argument_list)) |
| else: |
| blink_file.write(OPERATION_ARGS % (name, callback_index, argument_list, name, argument_list)) |