提交 25d50e80 编写于 作者: A Adam Barth

Merge pull request #2204 from abarth/rm_idl_compiler

Remove IDL compiler
#
# This file describes all Blink IDL extended attributes and allowed values.
# If any IDL file uses an extended attribute or values not listed below, the
# build will fail.
# If you would like to add a new extended attribute or value, please:
# (1) add the extended attribute or value to this file
# (2) add an explanation to the Blink IDL extended attributes document:
# http://www.chromium.org/blink/webidl/blink-idl-extended-attributes
# (3) add appropriate test cases to run-bindings-tests
#
# The syntax of this file is as follows:
# - One extended attribute per one line: Name and (optionally) Values.
# - "Attr" means that the Attr does not take a value, i.e. [Attr].
# - "Attr=X" means that Attr takes a required value, which must be X;
# i.e. [Attr=X].
# - "Attr=X|Y|Z" means that Attr takes a required value, and the valid
# values are X, Y, and Z, and combinations thereof;
# e.g. [Attr=X], [Attr=Y], [Attr=X|Z].
# The separator must be | or &, so [Attr=X&Z] is also valid; the
# separator makes a difference for Conditional, but otherwise is simply
# a style convention.
# - "Attr=|X|Y|Z" means that Attr takes an optional value, whose valid
# values (if present) are X, Y, and Z, and combinations thereof; e.g.
# [Attr], [Attr=X], [Attr=Y], [Attr=X|Z], [Attr=X|Y|Z], [Attr=X&Z].
# Note that including an empty value in the list, as in [Attr=X||Y],
# is NOT valid: the value is optional, but empty values are not allowed.
# - "Attr=*" means that Attr takes a required value, which can be
# arbitrary, and combinations thereof, e.g. [Attr=IndexedDB],
# [Attr=DeleteFunction], [Attr=X|Y].
# - "Attr=|*" means that Attr takes an optional value, which can be
# arbitrary, e.g. [Attr], [Attr=X].
# - "Attr=X|*" means that Attr takes an required value, which can be
# arbitrary, but that "X" is standard, e.g. [Attr=X], [Attr=Foo].
#
CachedAttribute=*
CallWith=ScriptState|ScriptArguments|ActiveWindow|FirstWindow|ThisValue
Constructor
Custom=|Getter|Setter|VisitDOMWrapper|Wrap|PropertyGetter|PropertyEnumerator|PropertyQuery
CustomConstructor
Default=Undefined
DependentLifetime
DoNotCheckConstants
EnforceRange
EventConstructor
Exposed=*
Global=|*
Immutable
ImplementedAs=*
InitializedByEventConstructor
Iterable
LegacyTreatAsPartialInterface
Named
NamedConstructor=*
NoImplHeader
NoInterfaceObject
NotEnumerable
NotScriptWrappable
OverrideBuiltins
PartialInterfaceImplementedAs=*
# If present, the generated interface will be prefixed with underscores so
# that it's private to the dart:ui module.
PrivateDart
PutForwards=*
RaisesException=|Getter|Setter|Constructor
Replaceable
SetterCallWith=ExecutionContext|ScriptArguments|ActiveWindow|FirstWindow
SetWrapperReferenceFrom=*
SetWrapperReferenceTo=*
SpecialWrapFor=*
TreatNullAs=NullString|EmptyString
TreatReturnedNullStringAs=Null|Undefined
TreatUndefinedAs=NullString
TypeChecking=Interface|Unrestricted
URL
......@@ -4,7 +4,6 @@
import("//mojo/dart/packages/mojo/sdk_ext_sources.gni")
bindings_scripts_dir = "//sky/engine/bindings/scripts"
bindings_output_dir = "$root_gen_dir/sky/bindings"
dart_host_toolchain = host_toolchain
......
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Lexer for Blink IDL.
The lexer uses the PLY (Python Lex-Yacc) library to build a tokenizer which
understands the Blink dialect of Web IDL and produces a token stream suitable
for the Blink IDL parser.
Blink IDL is identical to Web IDL at the token level, but the base lexer
does not discard comments. We need to override (and not include comments in
the token stream), as otherwise comments must be explicitly included in the
phrase grammar of the parser.
FIXME: Change base lexer to discard comments, and simply used the base
lexer, eliminating this separate lexer.
Web IDL:
http://www.w3.org/TR/WebIDL/
Web IDL Grammar:
http://www.w3.org/TR/WebIDL/#idl-grammar
PLY:
http://www.dabeaz.com/ply/
Design doc:
http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Front-end
"""
# Disable attribute validation, as lint can't import parent class to check
# pylint: disable=E1101
import os.path
import sys
# PLY is in Chromium src/third_party/ply
module_path, module_name = os.path.split(__file__)
third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir)
# Insert at front to override system libraries, and after path[0] == script dir
sys.path.insert(1, third_party)
from ply import lex
# Base lexer is in Chromium src/tools/idl_parser
tools_dir = os.path.join(third_party, os.pardir, 'tools')
sys.path.append(tools_dir)
from idl_parser.idl_lexer import IDLLexer
LEXTAB = 'lextab'
REMOVE_TOKENS = ['COMMENT']
class BlinkIDLLexer(IDLLexer):
# ignore comments
def t_COMMENT(self, t):
r'(/\*(.|\n)*?\*/)|(//.*(\n[ \t]*//.*)*)'
self.AddLines(t.value.count('\n'))
# Analogs to _AddToken/_AddTokens in base lexer
# Needed to remove COMMENT token, since comments ignored
def _RemoveToken(self, token):
if token in self.tokens:
self.tokens.remove(token)
def _RemoveTokens(self, tokens):
for token in tokens:
self._RemoveToken(token)
def __init__(self, debug=False, optimize=True, outputdir=None,
rewrite_tables=False):
if debug:
# Turn off optimization and caching to help debugging
optimize = False
outputdir = None
if outputdir:
# Need outputdir in path because lex imports the cached lex table
# as a Python module
sys.path.append(outputdir)
if rewrite_tables:
tablefile_root = os.path.join(outputdir, LEXTAB)
# Also remove the .pyc/.pyo files, or they'll be used even if
# the .py file doesn't exist.
for ext in ('.py', '.pyc', '.pyo'):
try:
os.unlink(tablefile_root + ext)
except OSError:
pass
IDLLexer.__init__(self)
# Overrides to parent class
self._RemoveTokens(REMOVE_TOKENS)
# Optimized mode substantially decreases startup time (by disabling
# error checking), and also allows use of Python's optimized mode.
# See: Optimized Mode
# http://www.dabeaz.com/ply/ply.html#ply_nn15
self._lexobj = lex.lex(object=self,
debug=debug,
optimize=optimize,
lextab=LEXTAB,
outputdir=outputdir)
################################################################################
def main(argv):
# If file itself executed, build and cache lex table
try:
outputdir = argv[1]
except IndexError as err:
print 'Usage: %s OUTPUT_DIR' % argv[0]
return 1
# Important: rewrite_tables=True causes the cache file to be deleted if it
# exists, thus making sure that PLY doesn't load it instead of regenerating
# the parse table.
lexer = BlinkIDLLexer(outputdir=outputdir, rewrite_tables=True)
if __name__ == '__main__':
sys.exit(main(sys.argv))
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Parser for Blink IDL.
The parser uses the PLY (Python Lex-Yacc) library to build a set of parsing
rules which understand the Blink dialect of Web IDL.
It derives from a standard Web IDL parser, overriding rules where Blink IDL
differs syntactically or semantically from the base parser, or where the base
parser diverges from the Web IDL standard.
Web IDL:
http://www.w3.org/TR/WebIDL/
Web IDL Grammar:
http://www.w3.org/TR/WebIDL/#idl-grammar
PLY:
http://www.dabeaz.com/ply/
Design doc:
http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Front-end
"""
# Disable check for line length and Member as Function due to how grammar rules
# are defined with PLY
#
# pylint: disable=R0201
# pylint: disable=C0301
#
# Disable attribute validation, as lint can't import parent class to check
# pylint: disable=E1101
import os.path
import sys
# PLY is in Chromium src/third_party/ply
module_path, module_name = os.path.split(__file__)
third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir, 'third_party')
# Insert at front to override system libraries, and after path[0] == script dir
sys.path.insert(1, third_party)
from ply import yacc
# Base parser is in Chromium src/tools/idl_parser
tools_dir = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir, 'tools')
sys.path.append(tools_dir)
from idl_parser.idl_parser import IDLParser, ListFromConcat
from idl_parser.idl_parser import ParseFile as parse_file
from blink_idl_lexer import BlinkIDLLexer
import blink_idl_lexer
# Explicitly set starting symbol to rule defined only in base parser.
# BEWARE that the starting symbol should NOT be defined in both the base parser
# and the derived one, as otherwise which is used depends on which line number
# is lower, which is fragile. Instead, either use one in base parser or
# create a new symbol, so that this is unambiguous.
# FIXME: unfortunately, this doesn't work in PLY 3.4, so need to duplicate the
# rule below.
STARTING_SYMBOL = 'Definitions'
# We ignore comments (and hence don't need 'Top') but base parser preserves them
# FIXME: Upstream: comments should be removed in base parser
REMOVED_RULES = ['Top', # [0]
'Comments', # [0.1]
'CommentsRest', # [0.2]
]
# Remove rules from base class
# FIXME: add a class method upstream: @classmethod IDLParser._RemoveRules
for rule in REMOVED_RULES:
production_name = 'p_' + rule
delattr(IDLParser, production_name)
class BlinkIDLParser(IDLParser):
# [1]
# FIXME: Need to duplicate rule for starting symbol here, with line number
# *lower* than in the base parser (idl_parser.py).
# This is a bug in PLY: it determines starting symbol by lowest line number.
# This can be overridden by the 'start' parameter, but as of PLY 3.4 this
# doesn't work correctly.
def p_Definitions(self, p):
"""Definitions : ExtendedAttributeList Definition Definitions
| """
if len(p) > 1:
p[2].AddChildren(p[1])
p[0] = ListFromConcat(p[2], p[3])
# Below are grammar rules used by yacc, given by functions named p_<RULE>.
# * The docstring is the production rule in BNF (grammar).
# * The body is the yacc action (semantics).
#
# The PLY framework builds the actual low-level parser by introspecting this
# parser object, selecting all attributes named p_<RULE> as grammar rules.
# It extracts the docstrings and uses them as the production rules, building
# the table of a LALR parser, and uses the body of the functions as actions.
#
# Reference:
# http://www.dabeaz.com/ply/ply.html#ply_nn23
#
# Review of yacc:
# Yacc parses a token stream, internally producing a Concrete Syntax Tree
# (CST), where each node corresponds to a production rule in the grammar.
# At each node, it runs an action, which is usually "produce a node in the
# Abstract Syntax Tree (AST)" or "ignore this node" (for nodes in the CST
# that aren't included in the AST, since only needed for parsing).
#
# The rules use pseudo-variables; in PLY syntax:
# p[0] is the left side: assign return value to p[0] instead of returning,
# p[1] ... p[n] are the right side: the values can be accessed, and they
# can be modified.
# (In yacc these are $$ and $1 ... $n.)
#
# The rules can look cryptic at first, but there are a few standard
# transforms from the CST to AST. With these in mind, the actions should
# be reasonably legible.
#
# * Ignore production
# Discard this branch. Primarily used when one alternative is empty.
#
# Sample code:
# if len(p) > 1:
# p[0] = ...
# # Note no assignment if len(p) == 1
#
# * Eliminate singleton production
# Discard this node in the CST, pass the next level down up the tree.
# Used to ignore productions only necessary for parsing, but not needed
# in the AST.
#
# Sample code:
# p[0] = p[1]
#
# * Build node
# The key type of rule. In this parser, produces object of class IDLNode.
# There are several helper functions:
# * BuildProduction: actually builds an IDLNode, based on a production.
# * BuildAttribute: builds an IDLAttribute, which is a temporary
# object to hold a name-value pair, which is then
# set as a Property of the IDLNode when the IDLNode
# is built.
# * BuildNamed: Same as BuildProduction, and sets the 'NAME' property.
# * BuildTrue: BuildAttribute with value True, for flags.
# See base idl_parser.py for definitions and more examples of use.
#
# Sample code:
# # Build node of type NodeType, with value p[1], and children.
# p[0] = self.BuildProduction('NodeType', p, 1, children)
#
# # Build named node of type NodeType, with name and value p[1].
# # (children optional)
# p[0] = self.BuildNamed('NodeType', p, 1)
#
# # Make a list
# # Used if one node has several children.
# children = ListFromConcat(p[2], p[3])
# p[0] = self.BuildProduction('NodeType', p, 1, children)
#
# # Also used to collapse the right-associative tree
# # produced by parsing a list back into a single list.
# """Foos : Foo Foos
# |"""
# if len(p) > 1:
# p[0] = ListFromConcat(p[1], p[2])
#
# # Add children.
# # Primarily used to add attributes, produced via BuildTrue.
# # p_StaticAttribute
# """StaticAttribute : STATIC Attribute"""
# p[2].AddChildren(self.BuildTrue('STATIC'))
# p[0] = p[2]
#
# Numbering scheme for the rules is:
# [1] for Web IDL spec (or additions in base parser)
# These should all be upstreamed to the base parser.
# [b1] for Blink IDL changes (overrides Web IDL)
# [b1.1] for Blink IDL additions, auxiliary rules for [b1]
# Numbers are as per Candidate Recommendation 19 April 2012:
# http://www.w3.org/TR/2012/CR-WebIDL-20120419/
# [3] Override action, since we distinguish callbacks
# FIXME: Upstream
def p_CallbackOrInterface(self, p):
"""CallbackOrInterface : CALLBACK CallbackRestOrInterface
| Interface"""
if len(p) > 2:
p[2].AddChildren(self.BuildTrue('CALLBACK'))
p[0] = p[2]
else:
p[0] = p[1]
# [b27] Add strings, more 'Literal' productions
# 'Literal's needed because integers and strings are both internally strings
def p_ConstValue(self, p):
"""ConstValue : BooleanLiteral
| FloatLiteral
| IntegerLiteral
| StringLiteral
| null"""
# Standard is (no 'string', fewer 'Literal's):
# ConstValue : BooleanLiteral
# | FloatLiteral
# | integer
# | NULL
p[0] = p[1]
# [b27.1]
def p_IntegerLiteral(self, p):
"""IntegerLiteral : integer"""
p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'integer'),
self.BuildAttribute('NAME', p[1]))
# [b27.2]
def p_StringLiteral(self, p):
"""StringLiteral : string"""
p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'DOMString'),
self.BuildAttribute('NAME', p[1]))
# [b47]
def p_ExceptionMember(self, p):
"""ExceptionMember : Const
| ExceptionField
| Attribute
| ExceptionOperation"""
# Standard is (no Attribute, no ExceptionOperation):
# ExceptionMember : Const
# | ExceptionField
# FIXME: In DOMException.idl, Attributes should be changed to
# ExceptionFields, and Attribute removed from this rule.
p[0] = p[1]
# [b47.1] FIXME: rename to ExceptionAttribute
def p_Attribute(self, p):
"""Attribute : ReadOnly ATTRIBUTE Type identifier ';'"""
p[0] = self.BuildNamed('Attribute', p, 4,
ListFromConcat(p[1], p[3]))
# [b47.2]
def p_ExceptionOperation(self, p):
"""ExceptionOperation : Type identifier '(' ')' ';'"""
# Needed to handle one case in DOMException.idl:
# // Override in a Mozilla compatible format
# [NotEnumerable] DOMString toString();
# Limited form of Operation to prevent others from being added.
# FIXME: Should be a stringifier instead.
p[0] = self.BuildNamed('ExceptionOperation', p, 2, p[1])
# Extended attributes
# [b49] Override base parser: remove comment field, since comments stripped
# FIXME: Upstream
def p_ExtendedAttributeList(self, p):
"""ExtendedAttributeList : '[' ExtendedAttribute ExtendedAttributes ']'
| '[' ']'
| """
if len(p) > 3:
items = ListFromConcat(p[2], p[3])
p[0] = self.BuildProduction('ExtAttributes', p, 1, items)
# Error handling for ExtendedAttributeList.
# We can't upstream this because we override ExtendedAttributeList.
def p_ExtendedAttributeListError(self, p):
"""ExtendedAttributeList : '[' ExtendedAttribute ',' error"""
p[0] = self.BuildError(p, "ExtendedAttributeList")
# [b50] Allow optional trailing comma
# Blink-only, marked as WONTFIX in Web IDL spec:
# https://www.w3.org/Bugs/Public/show_bug.cgi?id=22156
def p_ExtendedAttributes(self, p):
"""ExtendedAttributes : ',' ExtendedAttribute ExtendedAttributes
| ','
|"""
if len(p) > 3:
p[0] = ListFromConcat(p[2], p[3])
# [b51] Add ExtendedAttributeStringLiteral and ExtendedAttributeStringLiteralList
def p_ExtendedAttribute(self, p):
"""ExtendedAttribute : ExtendedAttributeNoArgs
| ExtendedAttributeArgList
| ExtendedAttributeIdent
| ExtendedAttributeIdentList
| ExtendedAttributeNamedArgList
| ExtendedAttributeStringLiteral
| ExtendedAttributeStringLiteralList"""
p[0] = p[1]
# [59]
# FIXME: Upstream UnionType
def p_UnionType(self, p):
"""UnionType : '(' UnionMemberType OR UnionMemberType UnionMemberTypes ')'"""
members = ListFromConcat(p[2], p[4], p[5])
p[0] = self.BuildProduction('UnionType', p, 1, members)
# [60]
def p_UnionMemberType(self, p):
"""UnionMemberType : NonAnyType
| UnionType TypeSuffix
| ANY '[' ']' TypeSuffix"""
if len(p) == 2:
p[0] = self.BuildProduction('Type', p, 1, p[1])
elif len(p) == 3:
p[0] = self.BuildProduction('Type', p, 1, ListFromConcat(p[1], p[2]))
else:
any_node = ListFromConcat(self.BuildProduction('Any', p, 1), p[4])
p[0] = self.BuildProduction('Type', p, 1, any_node)
# [61]
def p_UnionMemberTypes(self, p):
"""UnionMemberTypes : OR UnionMemberType UnionMemberTypes
|"""
if len(p) > 2:
p[0] = ListFromConcat(p[2], p[3])
# [70] Override base parser to remove non-standard sized array
# FIXME: Upstream
def p_TypeSuffix(self, p):
"""TypeSuffix : '[' ']' TypeSuffix
| '?' TypeSuffixStartingWithArray
|"""
if len(p) == 4:
p[0] = self.BuildProduction('Array', p, 1, p[3])
elif len(p) == 3:
p[0] = ListFromConcat(self.BuildTrue('NULLABLE'), p[2])
# Blink extension: Add support for string literal Extended Attribute values
def p_ExtendedAttributeStringLiteral(self, p):
"""ExtendedAttributeStringLiteral : identifier '=' StringLiteral """
def unwrap_string(ls):
"""Reach in and grab the string literal's "NAME"."""
return ls[1].value
value = self.BuildAttribute('VALUE', unwrap_string(p[3]))
p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
# Blink extension: Add support for compound Extended Attribute values over string literals ("A","B")
def p_ExtendedAttributeStringLiteralList(self, p):
"""ExtendedAttributeStringLiteralList : identifier '=' '(' StringLiteralList ')' """
value = self.BuildAttribute('VALUE', p[4])
p[0] = self.BuildNamed('ExtAttribute', p, 1, value)
# Blink extension: one or more string literals. The values aren't propagated as literals,
# but their by their value only.
def p_StringLiteralList(self, p):
"""StringLiteralList : StringLiteral ',' StringLiteralList
| StringLiteral"""
def unwrap_string(ls):
"""Reach in and grab the string literal's "NAME"."""
return ls[1].value
if len(p) > 3:
p[0] = ListFromConcat(unwrap_string(p[1]), p[3])
else:
p[0] = ListFromConcat(unwrap_string(p[1]))
def __init__(self,
# common parameters
debug=False,
# local parameters
rewrite_tables=False,
# idl_parser parameters
lexer=None, verbose=False, mute_error=False,
# yacc parameters
outputdir='', optimize=True, write_tables=False,
picklefile=None):
if debug:
# Turn off optimization and caching, and write out tables,
# to help debugging
optimize = False
outputdir = None
picklefile = None
write_tables = True
if outputdir:
picklefile = picklefile or os.path.join(outputdir, 'parsetab.pickle')
if rewrite_tables:
try:
os.unlink(picklefile)
except OSError:
pass
lexer = lexer or BlinkIDLLexer(debug=debug,
outputdir=outputdir,
optimize=optimize)
self.lexer = lexer
self.tokens = lexer.KnownTokens()
# Using SLR (instead of LALR) generates the table faster,
# but produces the same output. This is ok b/c Web IDL (and Blink IDL)
# is an SLR grammar (as is often the case for simple LL(1) grammars).
#
# Optimized mode substantially decreases startup time (by disabling
# error checking), and also allows use of Python's optimized mode.
# See: Using Python's Optimized Mode
# http://www.dabeaz.com/ply/ply.html#ply_nn38
#
# |picklefile| allows simpler importing than |tabmodule| (parsetab.py),
# as we don't need to modify sys.path; virtually identical speed.
# See: CHANGES, Version 3.2
# http://ply.googlecode.com/svn/trunk/CHANGES
self.yaccobj = yacc.yacc(module=self,
start=STARTING_SYMBOL,
method='SLR',
debug=debug,
optimize=optimize,
write_tables=write_tables,
picklefile=picklefile)
self.parse_debug = debug
self.verbose = verbose
self.mute_error = mute_error
self._parse_errors = 0
self._parse_warnings = 0
self._last_error_msg = None
self._last_error_lineno = 0
self._last_error_pos = 0
################################################################################
def main(argv):
# If file itself executed, cache lex/parse tables
try:
outputdir = argv[1]
except IndexError as err:
print 'Usage: %s OUTPUT_DIR' % argv[0]
return 1
blink_idl_lexer.main(argv)
# Important: rewrite_tables=True causes the cache file to be deleted if it
# exists, thus making sure that PLY doesn't load it instead of regenerating
# the parse table.
parser = BlinkIDLParser(outputdir=outputdir, rewrite_tables=True)
if __name__ == '__main__':
sys.exit(main(sys.argv))
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Generate Blink C++ bindings (.h and .cpp files) for use by Dart:HTML.
If run itself, caches Jinja templates (and creates dummy file for build,
since cache filenames are unpredictable and opaque).
This module is *not* concurrency-safe without care: bytecode caching creates
a race condition on cache *write* (crashes if one process tries to read a
partially-written cache). However, if you pre-cache the templates (by running
the module itself), then you can parallelize compiling individual files, since
cache *reading* is safe.
Input: An object of class IdlDefinitions, containing an IDL interface X
Output: DartX.h and DartX.cpp
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
"""
import os
import cPickle as pickle
import re
import sys
import logging
# Path handling for libraries and templates
# Paths have to be normalized because Jinja uses the exact template path to
# determine the hash used in the cache filename, and we need a pre-caching step
# to be concurrency-safe. Use absolute path because __file__ is absolute if
# module is imported, and relative if executed directly.
# If paths differ between pre-caching and individual file compilation, the cache
# is regenerated, which causes a race condition and breaks concurrent build,
# since some compile processes will try to read the partially written cache.
module_path, module_filename = os.path.split(os.path.realpath(__file__))
third_party_dir = os.path.normpath(os.path.join(
module_path, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir))
templates_dir = os.path.normpath(os.path.join(module_path, 'templates'))
# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching
module_pyname = os.path.splitext(module_filename)[0] + '.py'
# jinja2 is in chromium's third_party directory.
# Insert at 1 so at front to override system libraries, and
# after path[0] == invoking script dir
sys.path.insert(1, third_party_dir)
import jinja2
import idl_types
from idl_types import IdlType
import dart_callback_interface
import dart_interface
import dart_types
from dart_utilities import DartUtilities
from utilities import write_pickle_file, idl_filename_to_interface_name
from v8_globals import includes, interfaces
class CodeGeneratorDart(object):
def __init__(self, interfaces_info, cache_dir):
interfaces_info = interfaces_info or {}
self.interfaces_info = interfaces_info
self.jinja_env = initialize_jinja_env(cache_dir)
# Set global type info
idl_types.set_ancestors(dict(
(interface_name, interface_info['ancestors'])
for interface_name, interface_info in interfaces_info.iteritems()
if interface_info['ancestors']))
IdlType.set_callback_interfaces(set(
interface_name
for interface_name, interface_info in interfaces_info.iteritems()
if interface_info['is_callback_interface']))
IdlType.set_implemented_as_interfaces(dict(
(interface_name, interface_info['implemented_as'])
for interface_name, interface_info in interfaces_info.iteritems()
if interface_info['implemented_as']))
dart_types.set_component_dirs(dict(
(interface_name, interface_info['component_dir'])
for interface_name, interface_info in interfaces_info.iteritems()))
def generate_code(self, definitions, interface_name,
idl_filename, idl_pickle_filename, only_if_changed):
"""Returns .h/.cpp/.dart code as (header_text, cpp_text, dart_text)."""
try:
interface = definitions.interfaces[interface_name]
except KeyError:
raise Exception('%s not in IDL definitions' % interface_name)
# Store other interfaces for introspection
interfaces.update(definitions.interfaces)
# Set local type info
IdlType.set_callback_functions(definitions.callback_functions.keys())
IdlType.set_enums((enum.name, enum.values)
for enum in definitions.enumerations.values())
# Select appropriate Jinja template and contents function
if interface.is_callback:
header_template_filename = 'callback_interface_h.template'
cpp_template_filename = 'callback_interface_cpp.template'
dart_template_filename = 'callback_interface_dart.template'
generate_contents = dart_callback_interface.generate_callback_interface
else:
header_template_filename = 'interface_h.template'
cpp_template_filename = 'interface_cpp.template'
dart_template_filename = 'interface_dart.template'
generate_contents = dart_interface.interface_context
header_template = self.jinja_env.get_template(header_template_filename)
cpp_template = self.jinja_env.get_template(cpp_template_filename)
dart_template = self.jinja_env.get_template(dart_template_filename)
# Generate contents (input parameters for Jinja)
template_contents = generate_contents(interface)
template_contents['code_generator'] = module_pyname
# Add includes for interface itself and any dependencies
interface_info = self.interfaces_info[interface_name]
template_contents['header_includes'].add(interface_info['include_path'])
template_contents['header_includes'] = sorted(template_contents['header_includes'])
includes.update(interface_info.get('dependencies_include_paths', []))
template_contents['cpp_includes'] = sorted(includes)
# If PrivateDart is set, read the custom dart file and add it to our
# template parameters.
if 'PrivateDart' in interface.extended_attributes:
template_contents['private_dart'] = True
idl_world = {'interface': None, 'callback': None}
# Load the pickle file for this IDL.
if os.path.isfile(idl_pickle_filename):
with open(idl_pickle_filename) as idl_pickle_file:
idl_global_data = pickle.load(idl_pickle_file)
idl_pickle_file.close()
idl_world['interface'] = idl_global_data['interface']
idl_world['callback'] = idl_global_data['callback']
if 'interface_name' in template_contents:
interface_global = {'component_dir': interface_info['component_dir'],
'name': template_contents['interface_name'],
'parent_interface': template_contents['parent_interface'],
'has_resolver': template_contents['interface_name'],
'native_entries': sorted(template_contents['native_entries'], key=lambda(x): x['blink_entry']),
}
idl_world['interface'] = interface_global
else:
callback_global = {'name': template_contents['cpp_class']}
idl_world['callback'] = callback_global
write_pickle_file(idl_pickle_filename, idl_world, only_if_changed)
# Render Jinja templates
header_text = header_template.render(template_contents)
cpp_text = cpp_template.render(template_contents)
dart_text = dart_template.render(template_contents)
return header_text, cpp_text, dart_text
def load_global_pickles(self, global_entries):
# List of all interfaces and callbacks for global code generation.
world = {'interfaces': [], 'callbacks': []}
# Load all pickled data for each interface.
for (directory, file_list) in global_entries:
for filename in file_list:
if os.path.splitext(filename)[1] == '.dart':
# Special case: any .dart files in the list should be added
# to dart_ui.dart directly, but don't need to be processed.
interface_name = os.path.splitext(os.path.basename(filename))[0]
world['interfaces'].append({'name': "Custom" + interface_name})
continue
interface_name = idl_filename_to_interface_name(filename)
idl_pickle_filename = interface_name + "_globals.pickle"
idl_pickle_filename = os.path.join(directory, idl_pickle_filename)
if not os.path.exists(idl_pickle_filename):
logging.warn("Missing %s" % idl_pickle_filename)
continue
with open(idl_pickle_filename) as idl_pickle_file:
idl_world = pickle.load(idl_pickle_file)
if 'interface' in idl_world:
# FIXME: Why are some of these None?
if idl_world['interface']:
world['interfaces'].append(idl_world['interface'])
if 'callback' in idl_world:
# FIXME: Why are some of these None?
if idl_world['callback']:
world['callbacks'].append(idl_world['callback'])
world['interfaces'] = sorted(world['interfaces'], key=lambda (x): x['name'])
world['callbacks'] = sorted(world['callbacks'], key=lambda (x): x['name'])
return world
# Generates global file for all interfaces.
def generate_globals(self, global_entries):
template_contents = self.load_global_pickles(global_entries)
template_contents['code_generator'] = module_pyname
header_template_filename = 'global_h.template'
header_template = self.jinja_env.get_template(header_template_filename)
header_text = header_template.render(template_contents)
cpp_template_filename = 'global_cpp.template'
cpp_template = self.jinja_env.get_template(cpp_template_filename)
cpp_text = cpp_template.render(template_contents)
return header_text, cpp_text
# Generates global dart blink file for all interfaces.
def generate_dart_blink(self, global_entries):
template_contents = self.load_global_pickles(global_entries)
template_contents['code_generator'] = module_pyname
template_filename = 'dart_blink.template'
template = self.jinja_env.get_template(template_filename)
text = template.render(template_contents)
return text
def initialize_jinja_env(cache_dir):
jinja_env = jinja2.Environment(
loader=jinja2.FileSystemLoader(templates_dir),
# Bytecode cache is not concurrency-safe unless pre-cached:
# if pre-cached this is read-only, but writing creates a race condition.
# bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir),
keep_trailing_newline=True, # newline-terminate generated files
lstrip_blocks=True, # so can indent control flow tags
trim_blocks=True)
jinja_env.filters.update({
'blink_capitalize': DartUtilities.capitalize,
})
return jinja_env
################################################################################
def main(argv):
# If file itself executed, cache templates
try:
cache_dir = argv[1]
dummy_filename = argv[2]
except IndexError as err:
print 'Usage: %s OUTPUT_DIR DUMMY_FILENAME' % argv[0]
return 1
# Cache templates
jinja_env = initialize_jinja_env(cache_dir)
template_filenames = [filename for filename in os.listdir(templates_dir)
# Skip .svn, directories, etc.
if filename.endswith(('.cpp', '.h', '.template'))]
for template_filename in template_filenames:
jinja_env.get_template(template_filename)
# Create a dummy file as output for the build system,
# since filenames of individual cache files are unpredictable and opaque
# (they are hashes of the template path, which varies based on environment)
with open(dummy_filename, 'w') as dummy_file:
pass # |open| creates or touches the file
if __name__ == '__main__':
sys.exit(main(sys.argv))
#!/usr/bin/python
# Copyright (C) 2014 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Compile an .idl file to Dart bindings (.h and .cpp files).
Design doc: ??????
"""
from optparse import OptionParser
import os
import sys
from dart_compiler import IdlCompiler
from code_generator_dart import CodeGeneratorDart
def parse_options():
parser = OptionParser()
parser.add_option('--output-directory')
parser.add_option('--interfaces-info-file')
parser.add_option('--write-file-only-if-changed', type='int', default='1')
parser.add_option('--generate-dart-blink',
action='append',
type='string',
dest='blink_global_entries',
nargs=2,
help="Pickle file directory and idl file list (dart:blink)")
parser.add_option('--generate-globals',
action='append',
type='string',
dest='global_entries',
nargs=2,
help="Pickle file directory and idl file list (global class table)")
# ensure output comes last, so command line easy to parse via regexes
parser.disable_interspersed_args()
options, args = parser.parse_args()
if options.output_directory is None:
parser.error('Must specify output directory using --output-directory.')
options.write_file_only_if_changed = bool(options.write_file_only_if_changed)
if bool(options.global_entries) or bool(options.blink_global_entries):
return options, None
if len(args) != 1:
parser.error('Must specify exactly 1 input file as argument, but %d given.' % len(args))
filename = os.path.realpath(args[0])
return options, filename
def idl_filename_to_interface_name(idl_filename):
basename = os.path.basename(idl_filename)
interface_name, _ = os.path.splitext(basename)
return interface_name
class IdlCompilerDart(IdlCompiler):
def __init__(self, *args, **kwargs):
IdlCompiler.__init__(self, *args, **kwargs)
interfaces_info = self.interfaces_info
self.output_directory = self.output_directory
self.code_generator = CodeGeneratorDart(interfaces_info, self.output_directory)
def compile_file(self, idl_filename):
interface_name = idl_filename_to_interface_name(idl_filename)
header_filename = os.path.join(self.output_directory,
'Dart%s.h' % interface_name)
cpp_filename = os.path.join(self.output_directory,
'Dart%s.cpp' % interface_name)
dart_filename = os.path.join(self.output_directory,
'%s.dart' % interface_name)
output_paths = (header_filename, cpp_filename, dart_filename)
self.compile_and_write(idl_filename, output_paths)
def generate_global(self, global_entries):
expanded_global_entries = []
for (directory, file_list_file) in global_entries:
with open(file_list_file) as input_file:
idl_file_list = sorted([line.rstrip('\n')
for line in input_file])
expanded_global_entries.append((directory, idl_file_list))
global_header_filename = os.path.join(self.output_directory, 'DartGlobal.h')
global_cpp_filename = os.path.join(self.output_directory, 'DartGlobal.cpp')
self.generate_global_and_write(expanded_global_entries,
(global_header_filename, global_cpp_filename))
def generate_dart_blink(self, global_entries):
global_dart_blink_filename = os.path.join(self.output_directory,
'dart_ui.dart')
expanded_global_entries = []
for (directory, file_list_file) in global_entries:
with open(file_list_file) as input_file:
idl_file_list = sorted([line.rstrip('\n')
for line in input_file])
expanded_global_entries.append((directory, idl_file_list))
self.generate_dart_blink_and_write(expanded_global_entries,
global_dart_blink_filename)
def main():
options, filename = parse_options()
idl_compiler = IdlCompilerDart(options.output_directory,
interfaces_info_filename=options.interfaces_info_file,
only_if_changed=options.write_file_only_if_changed)
if bool(options.global_entries):
idl_compiler.generate_global(options.global_entries)
elif bool(options.blink_global_entries):
idl_compiler.generate_dart_blink(options.blink_global_entries)
else:
idl_compiler.compile_file(filename)
if __name__ == '__main__':
sys.exit(main())
#!/usr/bin/python
#
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Compute global interface information for individual IDL files.
Auxiliary module for compute_interfaces_info_overall, which consolidates
this individual information, computing info that spans multiple files
(dependencies and ancestry).
This distinction is so that individual interface info can be computed
separately for each component (avoiding duplicated reading of individual
files), then consolidated using *only* the info visible to a given component.
Design doc: http://www.chromium.org/developers/design-documents/idl-build
"""
from collections import defaultdict
import optparse
import os
import posixpath
import sys
from utilities import get_file_contents, read_file_to_list, idl_filename_to_interface_name, write_pickle_file, get_interface_extended_attributes_from_idl, is_callback_interface_from_idl, get_partial_interface_name_from_idl, get_implements_from_idl, get_parent_interface, get_put_forward_interfaces_from_idl
module_path = os.path.dirname(__file__)
source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir))
# Global variables (filled in and exported)
interfaces_info = {}
partial_interface_files = defaultdict(lambda: {
'full_paths': [],
'include_paths': [],
})
def parse_options():
usage = 'Usage: %prog [options] [generated1.idl]...'
parser = optparse.OptionParser(usage=usage)
parser.add_option('--component-dir', help='component directory')
parser.add_option('--idl-files-list', help='file listing IDL files')
parser.add_option('--interfaces-info-file', help='output pickle file')
parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja')
options, args = parser.parse_args()
if options.component_dir is None:
parser.error('Must specify a component directory using --component-dir.')
if options.interfaces_info_file is None:
parser.error('Must specify an output file using --interfaces-info-file.')
if options.idl_files_list is None:
parser.error('Must specify a file listing IDL files using --idl-files-list.')
if options.write_file_only_if_changed is None:
parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.')
options.write_file_only_if_changed = bool(options.write_file_only_if_changed)
return options, args
################################################################################
# Computations
################################################################################
def relative_dir_posix(idl_filename):
"""Returns relative path to the directory of idl_file in POSIX format."""
relative_path_local = os.path.relpath(idl_filename, source_path)
relative_dir_local = os.path.dirname(relative_path_local)
return relative_dir_local.replace(os.path.sep, posixpath.sep)
def include_path(idl_filename, implemented_as=None):
"""Returns relative path to header file in POSIX format; used in includes.
POSIX format is used for consistency of output, so reference tests are
platform-independent.
"""
relative_dir = relative_dir_posix(idl_filename)
# IDL file basename is used even if only a partial interface file
idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename))
cpp_class_name = implemented_as or idl_file_basename
return posixpath.join(relative_dir, cpp_class_name + '.h')
def add_paths_to_partials_dict(partial_interface_name, full_path, this_include_path=None):
paths_dict = partial_interface_files[partial_interface_name]
paths_dict['full_paths'].append(full_path)
if this_include_path:
paths_dict['include_paths'].append(this_include_path)
def compute_info_individual(idl_filename, component_dir):
full_path = os.path.realpath(idl_filename)
idl_file_contents = get_file_contents(full_path)
extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents)
implemented_as = extended_attributes.get('ImplementedAs')
relative_dir = relative_dir_posix(idl_filename)
this_include_path = None if 'NoImplHeader' in extended_attributes else include_path(idl_filename, implemented_as)
# Handle partial interfaces
partial_interface_name = get_partial_interface_name_from_idl(idl_file_contents)
if partial_interface_name:
add_paths_to_partials_dict(partial_interface_name, full_path, this_include_path)
return
# If not a partial interface, the basename is the interface name
interface_name = idl_filename_to_interface_name(idl_filename)
# 'implements' statements can be included in either the file for the
# implement*ing* interface (lhs of 'implements') or implement*ed* interface
# (rhs of 'implements'). Store both for now, then merge to implement*ing*
# interface later.
left_interfaces, right_interfaces = get_implements_from_idl(idl_file_contents, interface_name)
interfaces_info[interface_name] = {
'component_dir': component_dir,
'extended_attributes': extended_attributes,
'full_path': full_path,
'implemented_as': implemented_as,
'implemented_by_interfaces': left_interfaces, # private, merged to next
'implements_interfaces': right_interfaces,
'include_path': this_include_path,
'is_callback_interface': is_callback_interface_from_idl(idl_file_contents),
# FIXME: temporary private field, while removing old treatement of
# 'implements': http://crbug.com/360435
'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterface' in extended_attributes,
'parent': get_parent_interface(idl_file_contents),
# Interfaces that are referenced (used as types) and that we introspect
# during code generation (beyond interface-level data ([ImplementedAs],
# is_callback_interface, ancestors, and inherited extended attributes):
# deep dependencies.
# These cause rebuilds of referrers, due to the dependency, so these
# should be minimized; currently only targets of [PutForwards].
'referenced_interfaces': get_put_forward_interfaces_from_idl(idl_file_contents),
'relative_dir': relative_dir,
}
def info_individual():
"""Returns info packaged as a dict."""
return {
'interfaces_info': interfaces_info,
# Can't pickle defaultdict, convert to dict
'partial_interface_files': dict(partial_interface_files),
}
################################################################################
def main():
options, args = parse_options()
# Static IDL files are passed in a file (generated at GYP time), due to OS
# command line length limits
idl_files = read_file_to_list(options.idl_files_list)
# Generated IDL files are passed at the command line, since these are in the
# build directory, which is determined at build time, not GYP time, so these
# cannot be included in the file listing static files
idl_files.extend(args)
# Compute information for individual files
# Information is stored in global variables interfaces_info and
# partial_interface_files.
for idl_filename in idl_files:
compute_info_individual(idl_filename, options.component_dir)
write_pickle_file(options.interfaces_info_file,
info_individual(),
options.write_file_only_if_changed)
if __name__ == '__main__':
sys.exit(main())
#!/usr/bin/python
#
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Compute global interface information, including public information, dependencies, and inheritance.
Computed data is stored in a global variable, |interfaces_info|, and written as
output (concretely, exported as a pickle). This is then used by the IDL compiler
itself, so it does not need to compute global information itself, and so that
inter-IDL dependencies are clear, since they are all computed here.
The |interfaces_info| pickle is a *global* dependency: any changes cause a full
rebuild. This is to avoid having to compute which public data is visible by
which IDL files on a file-by-file basis, which is very complex for little
benefit.
|interfaces_info| should thus only contain data about an interface that
contains paths or is needed by *other* interfaces, e.g., path data (to abstract
the compiler from OS-specific file paths) or public data (to avoid having to
read other interfaces unnecessarily).
It should *not* contain full information about an interface (e.g., all
extended attributes), as this would cause unnecessary rebuilds.
|interfaces_info| is a dict, keyed by |interface_name|.
Current keys are:
* dependencies:
'implements_interfaces': targets of 'implements' statements
'referenced_interfaces': reference interfaces that are introspected
(currently just targets of [PutForwards])
* inheritance:
'ancestors': all ancestor interfaces
'inherited_extended_attributes': inherited extended attributes
(all controlling memory management)
* public:
'is_callback_interface': bool, callback interface or not
'implemented_as': value of [ImplementedAs=...] on interface (C++ class name)
* paths:
'full_path': path to the IDL file, so can lookup an IDL by interface name
'include_path': path for use in C++ #include directives
'dependencies_full_paths': paths to dependencies (for merging into main)
'dependencies_include_paths': paths for use in C++ #include directives
Note that all of these are stable information, unlikely to change without
moving or deleting files (hence requiring a full rebuild anyway) or significant
code changes (for inherited extended attributes).
Design doc: http://www.chromium.org/developers/design-documents/idl-build
"""
from collections import defaultdict
import cPickle as pickle
import optparse
import sys
from utilities import read_pickle_files, write_pickle_file
INHERITED_EXTENDED_ATTRIBUTES = set([
'DependentLifetime',
'NotScriptWrappable',
])
# Main variable (filled in and exported)
interfaces_info = {}
# Auxiliary variables (not visible to future build steps)
partial_interface_files = defaultdict(lambda: {
'full_paths': [],
'include_paths': [],
})
parent_interfaces = {}
inherited_extended_attributes_by_interface = {} # interface name -> extended attributes
class IdlInterfaceFileNotFoundError(Exception):
"""Raised if the IDL file implementing an interface cannot be found."""
pass
def parse_options():
usage = 'Usage: %prog [InfoIndividual.pickle]... [Info.pickle]'
parser = optparse.OptionParser(usage=usage)
parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja')
options, args = parser.parse_args()
if options.write_file_only_if_changed is None:
parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.')
options.write_file_only_if_changed = bool(options.write_file_only_if_changed)
return options, args
def dict_of_dicts_of_lists_update_or_append(existing, other):
"""Updates an existing dict of dicts of lists, or appends to lists if key already present.
Needed for merging partial_interface_files across components.
"""
for key, value in other.iteritems():
if key not in existing:
existing[key] = value
continue
existing_value = existing[key]
for inner_key, inner_value in value.iteritems():
existing_value[inner_key].extend(inner_value)
################################################################################
# Computations
################################################################################
def compute_inheritance_info(interface_name):
"""Compute inheritance information, namely ancestors and inherited extended attributes."""
def generate_ancestors(interface_name):
while interface_name in parent_interfaces:
interface_name = parent_interfaces[interface_name]
yield interface_name
ancestors = list(generate_ancestors(interface_name))
inherited_extended_attributes = inherited_extended_attributes_by_interface[interface_name]
for ancestor in ancestors:
# Ancestors may not be present, notably if an ancestor is a generated
# IDL file and we are running this script from run-bindings-tests,
# where we don't generate these files.
ancestor_extended_attributes = inherited_extended_attributes_by_interface.get(ancestor, {})
inherited_extended_attributes.update(ancestor_extended_attributes)
interfaces_info[interface_name].update({
'ancestors': ancestors,
'inherited_extended_attributes': inherited_extended_attributes,
})
def compute_interfaces_info_overall(info_individuals):
"""Compute information about IDL files.
Information is stored in global interfaces_info.
"""
for info in info_individuals:
# No overlap between interface names, so ok to use dict.update
interfaces_info.update(info['interfaces_info'])
# Interfaces in one component may have partial interfaces in
# another component. This is ok (not a layering violation), since
# partial interfaces are used to *extend* interfaces.
# We thus need to update or append if already present
dict_of_dicts_of_lists_update_or_append(
partial_interface_files, info['partial_interface_files'])
# Record inheritance information individually
for interface_name, interface_info in interfaces_info.iteritems():
extended_attributes = interface_info['extended_attributes']
inherited_extended_attributes_by_interface[interface_name] = dict(
(key, value)
for key, value in extended_attributes.iteritems()
if key in INHERITED_EXTENDED_ATTRIBUTES)
parent = interface_info['parent']
if parent:
parent_interfaces[interface_name] = parent
# Once all individual files handled, can compute inheritance information
# and dependencies
# Compute inheritance info
for interface_name in interfaces_info:
compute_inheritance_info(interface_name)
# Compute dependencies
# Move implements info from implement*ed* interface (rhs of 'implements')
# to implement*ing* interface (lhs of 'implements').
# Note that moving an 'implements' statement between implementing and
# implemented files does not change the info (or hence cause a rebuild)!
for right_interface_name, interface_info in interfaces_info.iteritems():
for left_interface_name in interface_info['implemented_by_interfaces']:
interfaces_info[left_interface_name]['implements_interfaces'].append(right_interface_name)
del interface_info['implemented_by_interfaces']
# An IDL file's dependencies are partial interface files that extend it,
# and files for other interfaces that this interfaces implements.
for interface_name, interface_info in interfaces_info.iteritems():
partial_interface_paths = partial_interface_files[interface_name]
partial_interfaces_full_paths = partial_interface_paths['full_paths']
# Partial interface definitions each need an include, as they are
# implemented in separate classes from the main interface.
partial_interfaces_include_paths = partial_interface_paths['include_paths']
implemented_interfaces = interface_info['implements_interfaces']
try:
implemented_interfaces_info = [
interfaces_info[interface]
for interface in implemented_interfaces]
except KeyError as key_name:
raise IdlInterfaceFileNotFoundError('Could not find the IDL file where the following implemented interface is defined: %s' % key_name)
implemented_interfaces_full_paths = [
implemented_interface_info['full_path']
for implemented_interface_info in implemented_interfaces_info]
# Implemented interfaces don't need includes, as this is handled in
# the Blink implementation (they are implemented on |impl| itself,
# hence header is included in implementing class).
# However, they are needed for legacy implemented interfaces that
# are being treated as partial interfaces, until we remove these.
# http://crbug.com/360435
implemented_interfaces_include_paths = []
for implemented_interface_info in implemented_interfaces_info:
if (implemented_interface_info['is_legacy_treat_as_partial_interface'] and
implemented_interface_info['include_path']):
implemented_interfaces_include_paths.append(implemented_interface_info['include_path'])
interface_info.update({
'dependencies_full_paths': (partial_interfaces_full_paths +
implemented_interfaces_full_paths),
'dependencies_include_paths': (partial_interfaces_include_paths +
implemented_interfaces_include_paths),
})
# Clean up temporary private information
for interface_info in interfaces_info.itervalues():
del interface_info['extended_attributes']
del interface_info['is_legacy_treat_as_partial_interface']
del interface_info['parent']
################################################################################
def main():
options, args = parse_options()
# args = Input1, Input2, ..., Output
interfaces_info_filename = args.pop()
info_individuals = read_pickle_files(args)
compute_interfaces_info_overall(info_individuals)
write_pickle_file(interfaces_info_filename,
interfaces_info,
options.write_file_only_if_changed)
if __name__ == '__main__':
sys.exit(main())
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Generate template values for attributes.
Extends IdlType with property |constructor_type_name|.
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
"""
import idl_types
import dart_types
from dart_utilities import DartUtilities
from v8_globals import interfaces
import v8_attributes
def attribute_context(interface, attribute):
# Call v8's implementation.
context = v8_attributes.attribute_context(interface, attribute)
extended_attributes = attribute.extended_attributes
# Augment's Dart's information to context.
idl_type = attribute.idl_type
base_idl_type = idl_type.base_type
# TODO(terry): Work around for DOMString[] base should be IDLTypeArray
if base_idl_type == None:
# Returns Array or Sequence.
base_idl_type = idl_type.inner_name
# [Custom]
has_custom_getter = ('Custom' in extended_attributes and
extended_attributes['Custom'] in [None, 'Getter'])
has_custom_setter = (not attribute.is_read_only and
(('Custom' in extended_attributes and
extended_attributes['Custom'] in [None, 'Setter'])))
is_call_with_script_state = DartUtilities.has_extended_attribute_value(attribute, 'CallWith', 'ScriptState')
is_auto_scope = not 'DartNoAutoScope' in extended_attributes
context.update({
'has_custom_getter': has_custom_getter,
'has_custom_setter': has_custom_setter,
'is_auto_scope': is_auto_scope, # Used internally (outside of templates).
'is_call_with_script_state': is_call_with_script_state,
'auto_scope': DartUtilities.bool_to_cpp(is_auto_scope),
'dart_type': dart_types.idl_type_to_dart_type(idl_type),
})
if v8_attributes.is_constructor_attribute(attribute):
v8_attributes.constructor_getter_context(interface, attribute, context)
return context
if not v8_attributes.has_custom_getter(attribute):
getter_context(interface, attribute, context)
if (not attribute.is_read_only):
# FIXME: We did not previously support the PutForwards attribute, so I am
# disabling it here for now to get things compiling.
# We may wish to revisit this.
# if (not has_custom_setter(attribute) and
# (not attribute.is_read_only or 'PutForwards' in extended_attributes)):
setter_context(interface, attribute, context)
native_entry_getter = \
DartUtilities.generate_native_entry(
interface.name, attribute.name, 'Getter', attribute.is_static, 0)
native_entry_setter = \
DartUtilities.generate_native_entry(
interface.name, attribute.name, 'Setter', attribute.is_static, 1)
context.update({
'native_entry_getter': native_entry_getter,
'native_entry_setter': native_entry_setter,
})
return context
################################################################################
# Getter
################################################################################
def getter_context(interface, attribute, context):
v8_attributes.getter_context(interface, attribute, context)
idl_type = attribute.idl_type
base_idl_type = idl_type.base_type
extended_attributes = attribute.extended_attributes
cpp_value = getter_expression(interface, attribute, context)
# Normally we can inline the function call into the return
# statement to avoid the overhead of using a Ref<> temporary, but
# for some cases (nullable types, [CachedAttribute], or if there
# are exceptions), we need to use a local variable.
# FIXME: check if compilers are smart enough to inline this, and if so,
# always use a local variable (for readability and CG simplicity).
release = False
if (idl_type.is_nullable or
'CachedAttribute' in extended_attributes or
context['is_getter_raises_exception']):
context['cpp_value_original'] = cpp_value
cpp_value = 'result'
if idl_type.is_interface_type:
release = True
dart_set_return_value = \
idl_type.dart_set_return_value(cpp_value,
extended_attributes=extended_attributes,
script_wrappable='impl',
release=release,
for_main_world=False,
auto_scope=context['is_auto_scope'])
context.update({
'cpp_value': cpp_value,
'dart_set_return_value': dart_set_return_value,
})
def getter_expression(interface, attribute, context):
v8_attributes.getter_expression(interface, attribute, context)
arguments = []
this_getter_base_name = v8_attributes.getter_base_name(interface, attribute, arguments)
getter_name = DartUtilities.scoped_name(interface, attribute, this_getter_base_name)
arguments.extend(DartUtilities.call_with_arguments(
attribute.extended_attributes.get('CallWith')))
if ('PartialInterfaceImplementedAs' in attribute.extended_attributes and
not attribute.is_static):
# Pass by reference.
arguments.append('*receiver')
if attribute.idl_type.is_explicit_nullable:
arguments.append('is_null')
if context['is_getter_raises_exception']:
arguments.append('es')
return '%s(%s)' % (getter_name, ', '.join(arguments))
################################################################################
# Setter
################################################################################
def setter_context(interface, attribute, context):
v8_attributes.setter_context(interface, attribute, context)
def target_attribute():
target_interface_name = attribute.idl_type.base_type
target_attribute_name = extended_attributes['PutForwards']
target_interface = interfaces[target_interface_name]
try:
return next(attribute
for attribute in target_interface.attributes
if attribute.name == target_attribute_name)
except StopIteration:
raise Exception('[PutForward] target not found:\n'
'Attribute "%s" is not present in interface "%s"' %
(target_attribute_name, target_interface_name))
extended_attributes = attribute.extended_attributes
if 'PutForwards' in extended_attributes:
# Use target attribute in place of original attribute
attribute = target_attribute()
this_cpp_type = 'DartStringAdapter'
else:
this_cpp_type = context['cpp_type']
idl_type = attribute.idl_type
context.update({
'has_setter_exception_state': (
context['is_setter_raises_exception'] or context['has_type_checking_interface'] or
idl_type.is_integer_type),
'setter_lvalue': dart_types.check_reserved_name(attribute.name),
'cpp_type': this_cpp_type,
'local_cpp_type': idl_type.cpp_type_args(attribute.extended_attributes, raw_type=True),
'dart_value_to_local_cpp_value':
attribute.idl_type.dart_value_to_local_cpp_value(
extended_attributes, attribute.name, False,
context['has_type_checking_interface'], 1,
context['is_auto_scope']),
})
# setter_expression() depends on context values we set above.
context['cpp_setter'] = setter_expression(interface, attribute, context)
def setter_expression(interface, attribute, context):
extended_attributes = attribute.extended_attributes
arguments = DartUtilities.call_with_arguments(
extended_attributes.get('SetterCallWith') or
extended_attributes.get('CallWith'))
this_setter_base_name = v8_attributes.setter_base_name(interface, attribute, arguments)
setter_name = DartUtilities.scoped_name(interface, attribute, this_setter_base_name)
if ('PartialInterfaceImplementedAs' in extended_attributes and
not attribute.is_static):
arguments.append('*receiver')
idl_type = attribute.idl_type
attribute_name = dart_types.check_reserved_name(attribute.name)
arguments.append(attribute_name)
if context['is_setter_raises_exception']:
arguments.append('es')
return '%s(%s)' % (setter_name, ', '.join(arguments))
################################################################################
# Attribute configuration
################################################################################
# [Replaceable]
def setter_callback_name(interface, attribute):
cpp_class_name = DartUtilities.cpp_name(interface)
extended_attributes = attribute.extended_attributes
if (('Replaceable' in extended_attributes and
'PutForwards' not in extended_attributes) or
v8_attributes.is_constructor_attribute(attribute)):
# FIXME: rename to ForceSetAttributeOnThisCallback, since also used for Constructors
return '{0}V8Internal::{0}ReplaceableAttributeSetterCallback'.format(cpp_class_name)
# FIXME:disabling PutForwards for now since we didn't support it before
# if attribute.is_read_only and 'PutForwards' not in extended_attributes:
if attribute.is_read_only:
return '0'
return '%sV8Internal::%sAttributeSetterCallback' % (cpp_class_name, attribute.name)
################################################################################
# Constructors
################################################################################
idl_types.IdlType.constructor_type_name = property(
# FIXME: replace this with a [ConstructorAttribute] extended attribute
lambda self: DartUtilities.strip_suffix(self.base_type, 'Constructor'))
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Generate template values for a callback interface.
Extends IdlType with property |callback_cpp_type|.
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
"""
from idl_types import IdlType, IdlTypeBase
import dart_types
from dart_utilities import DartUtilities
from v8_globals import includes
CALLBACK_INTERFACE_H_INCLUDES = frozenset([
'bindings/dart_callback.h',
])
CALLBACK_INTERFACE_CPP_INCLUDES = frozenset([
'wtf/GetPtr.h',
'wtf/RefPtr.h',
])
def cpp_type(idl_type):
# FIXME: remove this function by making callback types consistent
# (always use usual v8_types.cpp_type)
idl_type_name = idl_type.name
if idl_type_name == 'String':
return 'const String&'
if idl_type_name == 'void':
return 'void'
# Callbacks use raw pointers, so raw_type=True
usual_cpp_type = idl_type.cpp_type_args(raw_type=True)
if usual_cpp_type.startswith(('Vector', 'HeapVector', 'WillBeHeapVector')):
return 'const %s&' % usual_cpp_type
return usual_cpp_type
IdlTypeBase.callback_cpp_type = property(cpp_type)
def generate_callback_interface(callback_interface):
includes.clear()
includes.update(CALLBACK_INTERFACE_CPP_INCLUDES)
name = callback_interface.name
methods = [generate_method(operation)
for operation in callback_interface.operations]
template_contents = {
'cpp_class': name,
'dart_class': dart_types.dart_type(callback_interface.name),
'header_includes': set(CALLBACK_INTERFACE_H_INCLUDES),
'methods': methods,
}
return template_contents
def add_includes_for_operation(operation):
operation.idl_type.add_includes_for_type()
for argument in operation.arguments:
argument.idl_type.add_includes_for_type()
def generate_method(operation):
extended_attributes = operation.extended_attributes
idl_type = operation.idl_type
idl_type_str = str(idl_type)
if idl_type_str not in ['boolean', 'void']:
raise Exception('We only support callbacks that return boolean or void values.')
is_custom = 'Custom' in extended_attributes
if not is_custom:
add_includes_for_operation(operation)
call_with = extended_attributes.get('CallWith')
call_with_this_handle = DartUtilities.extended_attribute_value_contains(call_with, 'ThisValue')
contents = {
'call_with_this_handle': call_with_this_handle,
'cpp_type': idl_type.callback_cpp_type,
'custom': is_custom,
'idl_type': idl_type_str,
'name': operation.name,
}
contents.update(generate_arguments_contents(operation.arguments, call_with_this_handle))
return contents
def generate_arguments_contents(arguments, call_with_this_handle):
def generate_argument(argument):
creation_context = ''
if argument.idl_type.native_array_element_type is not None:
creation_context = '<Dart%s>' % argument.idl_type.native_array_element_type
return {
'handle': '%sHandle' % argument.name,
'cpp_value_to_dart_value': argument.idl_type.cpp_value_to_dart_value(argument.name,
creation_context=creation_context),
}
argument_declarations = [
'%s %s' % (argument.idl_type.callback_cpp_type, argument.name)
for argument in arguments]
if call_with_this_handle:
argument_declarations.insert(0, 'ScriptValue thisValue')
dart_argument_declarations = [
'%s %s' % (dart_types.idl_type_to_dart_type(argument.idl_type), argument.name)
for argument in arguments]
return {
'argument_declarations': argument_declarations,
'dart_argument_declarations': dart_argument_declarations,
'arguments': [generate_argument(argument) for argument in arguments],
}
#!/usr/bin/python
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Compile an .idl file to Blink C++ bindings (.h and .cpp files) for Dart:HTML.
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
"""
import abc
import os.path
import cPickle as pickle
from idl_reader import IdlReader
from utilities import write_file
def idl_filename_to_interface_name(idl_filename):
basename = os.path.basename(idl_filename)
interface_name, _ = os.path.splitext(basename)
return interface_name
class IdlCompiler(object):
"""Abstract Base Class for IDL compilers.
In concrete classes:
* self.code_generator must be set, implementing generate_code()
(returning a list of output code), and
* compile_file() must be implemented (handling output filenames).
"""
__metaclass__ = abc.ABCMeta
def __init__(self, output_directory, code_generator=None,
interfaces_info=None, interfaces_info_filename='',
only_if_changed=False):
"""
Args:
interfaces_info:
interfaces_info dict
(avoids auxiliary file in run-bindings-tests)
interfaces_info_file: filename of pickled interfaces_info
"""
self.code_generator = code_generator
if interfaces_info_filename:
with open(interfaces_info_filename) as interfaces_info_file:
interfaces_info = pickle.load(interfaces_info_file)
self.interfaces_info = interfaces_info
self.only_if_changed = only_if_changed
self.output_directory = output_directory
self.reader = IdlReader(interfaces_info, output_directory)
def compile_and_write(self, idl_filename, output_filenames):
interface_name = idl_filename_to_interface_name(idl_filename)
idl_pickle_filename = os.path.join(self.output_directory,
'%s_globals.pickle' % interface_name)
definitions = self.reader.read_idl_definitions(idl_filename)
output_code_list = self.code_generator.generate_code(definitions,
interface_name,
idl_filename,
idl_pickle_filename,
self.only_if_changed)
for output_code, output_filename in zip(output_code_list, output_filenames):
write_file(output_code, output_filename, self.only_if_changed)
def generate_global_and_write(self, global_entries, output_filenames):
output_code_list = self.code_generator.generate_globals(global_entries)
for output_code, output_filename in zip(output_code_list, output_filenames):
write_file(output_code, output_filename, self.only_if_changed)
def generate_dart_blink_and_write(self, global_entries, output_filename):
output_code = self.code_generator.generate_dart_blink(global_entries)
write_file(output_code, output_filename, self.only_if_changed)
@abc.abstractmethod
def compile_file(self, idl_filename):
pass
此差异已折叠。
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Generate template values for methods.
Extends IdlType and IdlUnionType with property |union_arguments|.
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
"""
from idl_types import inherits_interface
import dart_types
from dart_utilities import DartUtilities
from v8_globals import includes
import v8_methods
def method_context(interface, method):
context = v8_methods.method_context(interface, method)
arguments = method.arguments
extended_attributes = method.extended_attributes
idl_type = method.idl_type
# idl_type.add_includes_for_type()
this_cpp_value = cpp_value(interface, method, len(arguments))
if context['is_call_with_script_state']:
includes.add('bindings/core/dart/DartScriptState.h')
if idl_type.union_arguments and len(idl_type.union_arguments) > 0:
this_cpp_type = []
for cpp_type in idl_type.member_types:
this_cpp_type.append("RefPtr<%s>" % cpp_type)
else:
this_cpp_type = idl_type.cpp_type
is_auto_scope = not 'DartNoAutoScope' in extended_attributes
arguments_data = [argument_context(interface, method, argument, index)
for index, argument in enumerate(arguments)]
union_arguments = []
if idl_type.union_arguments:
union_arguments.extend([union_arg['cpp_value']
for union_arg in idl_type.union_arguments])
is_custom = 'Custom' in extended_attributes or 'DartCustom' in extended_attributes
context.update({
'arguments': arguments_data,
'cpp_type': this_cpp_type,
'cpp_value': this_cpp_value,
'dart_type': dart_types.idl_type_to_dart_type(idl_type),
'dart_name': extended_attributes.get('DartName'),
'has_exception_state':
context['is_raises_exception'] or
any(argument for argument in arguments
if argument.idl_type.name == 'SerializedScriptValue' or
argument.idl_type.is_integer_type),
'is_auto_scope': is_auto_scope,
'auto_scope': DartUtilities.bool_to_cpp(is_auto_scope),
'is_custom': is_custom,
'is_custom_dart': 'DartCustom' in extended_attributes,
'is_custom_dart_new': DartUtilities.has_extended_attribute_value(method, 'DartCustom', 'New'),
# FIXME(terry): DartStrictTypeChecking no longer supported; TypeChecking is
# new extended attribute.
'is_strict_type_checking':
'DartStrictTypeChecking' in extended_attributes or
'DartStrictTypeChecking' in interface.extended_attributes,
'union_arguments': union_arguments,
'dart_set_return_value': dart_set_return_value(interface.name, method, this_cpp_value),
})
return context
def argument_context(interface, method, argument, index):
context = v8_methods.argument_context(interface, method, argument, index)
extended_attributes = argument.extended_attributes
idl_type = argument.idl_type
this_cpp_value = cpp_value(interface, method, index)
auto_scope = not 'DartNoAutoScope' in extended_attributes
arg_index = index + 1 if not method.is_static else index
preprocessed_type = str(idl_type.preprocessed_type)
local_cpp_type = idl_type.cpp_type_args(argument.extended_attributes, raw_type=True)
default_value = argument.default_cpp_value
if context['has_default']:
default_value = (argument.default_cpp_value or
dart_types.default_cpp_value_for_cpp_type(idl_type))
dart_type = dart_types.idl_type_to_dart_type(idl_type)
dart_default_value = dart_types.dart_default_value(dart_type, argument)
context.update({
'cpp_type': idl_type.cpp_type_args(extended_attributes=extended_attributes,
raw_type=True,
used_in_cpp_sequence=False),
'dart_type': dart_type,
'implemented_as': idl_type.implemented_as,
'cpp_value': this_cpp_value,
'local_cpp_type': local_cpp_type,
# FIXME: check that the default value's type is compatible with the argument's
'default_value': default_value,
'is_named': 'Named' in extended_attributes,
'dart_default_value': dart_default_value,
'enum_validation_expression': idl_type.enum_validation_expression,
'preprocessed_type': preprocessed_type,
'is_array_or_sequence_type': not not idl_type.native_array_element_type,
'is_strict_type_checking': 'DartStrictTypeChecking' in extended_attributes,
'dart_set_return_value_for_main_world': dart_set_return_value(interface.name, method,
this_cpp_value, for_main_world=True),
'dart_set_return_value': dart_set_return_value(interface.name, method, this_cpp_value),
'arg_index': arg_index,
'dart_value_to_local_cpp_value': dart_value_to_local_cpp_value(interface,
context['has_type_checking_interface'],
argument, arg_index, auto_scope),
})
return context
################################################################################
# Value handling
################################################################################
def cpp_value(interface, method, number_of_arguments):
def cpp_argument(argument):
argument_name = dart_types.check_reserved_name(argument.name)
idl_type = argument.idl_type
if idl_type.is_typed_array_type:
return '%s.get()' % argument_name
# TODO(eseidel): This should check cpp_type.endswith('Handle')
if idl_type.name == 'MojoDataPipeConsumer':
return '%s.Pass()' % argument_name
if idl_type.is_callback_interface:
return '%s.release()' % argument_name
return argument_name
# Truncate omitted optional arguments
arguments = method.arguments[:number_of_arguments]
if method.is_constructor:
call_with_values = interface.extended_attributes.get('ConstructorCallWith')
else:
call_with_values = method.extended_attributes.get('CallWith')
cpp_arguments = DartUtilities.call_with_arguments(call_with_values)
if ('PartialInterfaceImplementedAs' in method.extended_attributes and not method.is_static):
cpp_arguments.append('*receiver')
cpp_arguments.extend(cpp_argument(argument) for argument in arguments)
this_union_arguments = method.idl_type and method.idl_type.union_arguments
if this_union_arguments:
cpp_arguments.extend([member_argument['cpp_value']
for member_argument in this_union_arguments])
if ('RaisesException' in method.extended_attributes or
(method.is_constructor and
DartUtilities.has_extended_attribute_value(interface, 'RaisesException', 'Constructor'))):
cpp_arguments.append('es')
if method.name == 'Constructor':
base_name = 'create'
elif method.name == 'NamedConstructor':
base_name = 'createForJSConstructor'
else:
base_name = DartUtilities.cpp_name(method)
cpp_method_name = DartUtilities.scoped_name(interface, method, base_name)
return '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments))
def dart_set_return_value(interface_name, method, cpp_value, for_main_world=False):
idl_type = method.idl_type
extended_attributes = method.extended_attributes
if not idl_type or idl_type.name == 'void':
# Constructors and void methods don't have a return type
return None
release = False
if idl_type.is_union_type:
release = idl_type.release
# [CallWith=ScriptState], [RaisesException]
# TODO(terry): Disable ScriptState temporarily need to handle.
# if (has_extended_attribute_value(method, 'CallWith', 'ScriptState') or
# 'RaisesException' in extended_attributes or
# idl_type.is_union_type):
# cpp_value = 'result' # use local variable for value
# release = idl_type.release
auto_scope = not 'DartNoAutoScope' in extended_attributes
script_wrappable = 'impl' if inherits_interface(interface_name, 'Node') else ''
return idl_type.dart_set_return_value(cpp_value, extended_attributes,
script_wrappable=script_wrappable,
release=release,
for_main_world=for_main_world,
auto_scope=auto_scope)
def dart_value_to_local_cpp_value(interface, has_type_checking_interface,
argument, index, auto_scope=True):
extended_attributes = argument.extended_attributes
idl_type = argument.idl_type
name = argument.name
# TODO(ianh): why don't we need to null-check everything?
# https://github.com/domokit/mojo/issues/280
null_check = ((argument.is_optional and idl_type.is_callback_interface) or
(argument.default_value and argument.default_value.is_null))
return idl_type.dart_value_to_local_cpp_value(
extended_attributes, name, null_check, has_type_checking_interface,
index=index, auto_scope=auto_scope)
此差异已折叠。
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Functions shared by various parts of the code generator.
Extends IdlType and IdlUnion type with |enum_validation_expression| property.
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
"""
################################################################################
# Utility function exposed for Dart CodeGenerator. Only 6 methods are special
# to Dart the rest delegate to the v8_utilities functions.
################################################################################
import v8_types # Required
import v8_utilities
def _scoped_name(interface, definition, base_name):
# partial interfaces are implemented as separate classes, with their members
# implemented as static member functions
partial_interface_implemented_as = definition.extended_attributes.get('PartialInterfaceImplementedAs')
if partial_interface_implemented_as:
return '%s::%s' % (partial_interface_implemented_as, base_name)
if (definition.is_static or
definition.name in ('Constructor', 'NamedConstructor')):
return '%s::%s' % (v8_utilities.cpp_name(interface), base_name)
return 'receiver->%s' % base_name
def _bool_to_cpp(tf):
return "true" if tf else "false"
# [CallWith]
_CALL_WITH_ARGUMENTS = {
'ScriptState': 'state',
'ExecutionContext': 'context',
'ScriptArguments': 'scriptArguments.release()',
'ActiveWindow': 'DOMDartState::CurrentWindow()',
'FirstWindow': 'DOMDartState::CurrentWindow()',
}
# List because key order matters, as we want arguments in deterministic order
_CALL_WITH_VALUES = [
'ScriptState',
'ExecutionContext',
'ScriptArguments',
'ActiveWindow',
'FirstWindow',
]
def _call_with_arguments(call_with_values):
if not call_with_values:
return []
return [_CALL_WITH_ARGUMENTS[value]
for value in _CALL_WITH_VALUES
if v8_utilities.extended_attribute_value_contains(call_with_values, value)]
def _generate_native_entry(interface_name, name, kind, is_static, arity):
if kind == 'Getter':
suffix = "_Getter"
elif kind == 'Setter':
suffix = "_Setter"
elif kind == 'Constructor':
name = "constructor"
suffix = "Callback"
elif kind == 'Method':
suffix = "_Callback"
tag = "%s%s" % (name, suffix)
native_entry = "_".join([interface_name, tag])
argument_names = ['__arg_%d' % i for i in range(0, arity)]
return {'blink_entry': name,
'argument_names': argument_names,
'resolver_string': native_entry}
################################################################################
# This is the monkey patched methods most delegate to v8_utilities but some are
# overridden in dart_utilities.
################################################################################
class dart_utilities_monkey():
def __init__(self):
self.base_class_name = 'dart_utilities'
DartUtilities = dart_utilities_monkey()
DartUtilities.bool_to_cpp = _bool_to_cpp
DartUtilities.call_with_arguments = _call_with_arguments
DartUtilities.capitalize = v8_utilities.capitalize
DartUtilities.cpp_name = v8_utilities.cpp_name
DartUtilities.extended_attribute_value_contains = v8_utilities.extended_attribute_value_contains
DartUtilities.generate_native_entry = _generate_native_entry
DartUtilities.has_extended_attribute = v8_utilities.has_extended_attribute
DartUtilities.has_extended_attribute_value = v8_utilities.has_extended_attribute_value
DartUtilities.scoped_name = _scoped_name
DartUtilities.strip_suffix = v8_utilities.strip_suffix
DartUtilities.uncapitalize = v8_utilities.uncapitalize
#!/usr/bin/python
#
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Generate event interfaces .in file (EventInterfaces.in).
The event interfaces .in file contains a list of all Event interfaces, i.e.,
all interfaces that inherit from Event, including Event itself,
together with certain extended attributes.
Paths are in POSIX format, and relative to engine/.
This list is used in core/ to generate EventFactory and EventNames.
The .in format is documented in build/scripts/in_file.py.
"""
from optparse import OptionParser
import os
import posixpath
import sys
from utilities import get_file_contents, read_file_to_list, write_file, get_interface_extended_attributes_from_idl
EXPORTED_EXTENDED_ATTRIBUTES = (
'ImplementedAs',
)
module_path = os.path.dirname(os.path.realpath(__file__))
source_dir = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir))
def parse_options():
parser = OptionParser()
parser.add_option('--event-idl-files-list', help='file listing event IDL files')
parser.add_option('--event-interfaces-file', help='output file')
parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja')
parser.add_option('--suffix', help='specify a suffix to the namespace, i.e., "Modules". Default is None.')
options, args = parser.parse_args()
if options.event_idl_files_list is None:
parser.error('Must specify a file listing event IDL files using --event-idl-files-list.')
if options.event_interfaces_file is None:
parser.error('Must specify an output file using --event-interfaces-file.')
if options.write_file_only_if_changed is None:
parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.')
options.write_file_only_if_changed = bool(options.write_file_only_if_changed)
if args:
parser.error('No arguments allowed, but %d given.' % len(args))
return options
def write_event_interfaces_file(event_idl_files, destination_filename, only_if_changed, suffix):
def extended_attribute_string(name, value):
return name + '=' + value
def interface_line(full_path):
relative_path_local, _ = os.path.splitext(os.path.relpath(full_path, source_dir))
relative_path_posix = relative_path_local.replace(os.sep, posixpath.sep)
idl_file_contents = get_file_contents(full_path)
extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents)
extended_attributes_list = [
extended_attribute_string(name, extended_attributes[name])
for name in EXPORTED_EXTENDED_ATTRIBUTES
if name in extended_attributes]
return '%s %s\n' % (relative_path_posix,
', '.join(extended_attributes_list))
lines = ['namespace="Event"\n']
if suffix:
lines.append('suffix="' + suffix + '"\n')
lines.append('\n')
interface_lines = [interface_line(event_idl_file)
for event_idl_file in event_idl_files]
interface_lines.sort()
lines.extend(interface_lines)
write_file(''.join(lines), destination_filename, only_if_changed)
################################################################################
def main():
options = parse_options()
event_idl_files = read_file_to_list(options.event_idl_files_list)
write_event_interfaces_file(event_idl_files,
options.event_interfaces_file,
options.write_file_only_if_changed,
options.suffix)
if __name__ == '__main__':
sys.exit(main())
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Read an IDL file or complete IDL interface, producing an IdlDefinitions object.
Design doc:
http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Front-end
"""
import os
import blink_idl_parser
from blink_idl_parser import BlinkIDLParser
from idl_definitions import IdlDefinitions
from idl_validator import EXTENDED_ATTRIBUTES_RELATIVE_PATH, IDLInvalidExtendedAttributeError, IDLExtendedAttributeValidator
from interface_dependency_resolver import InterfaceDependencyResolver
class IdlReader(object):
def __init__(self, interfaces_info=None, outputdir=''):
self.extended_attribute_validator = IDLExtendedAttributeValidator()
if interfaces_info:
self.interface_dependency_resolver = InterfaceDependencyResolver(interfaces_info, self)
else:
self.interface_dependency_resolver = None
self.parser = BlinkIDLParser(outputdir=outputdir)
def read_idl_definitions(self, idl_filename):
"""Returns an IdlDefinitions object for an IDL file, including all dependencies."""
definitions = self.read_idl_file(idl_filename)
if not self.interface_dependency_resolver:
return definitions
self.interface_dependency_resolver.resolve_dependencies(definitions)
return definitions
def read_idl_file(self, idl_filename):
"""Returns an IdlDefinitions object for an IDL file, without any dependencies.
The IdlDefinitions object is guaranteed to contain a single
IdlInterface; it may also contain other definitions, such as
callback functions and enumerations."""
ast = blink_idl_parser.parse_file(self.parser, idl_filename)
if not ast:
raise Exception('Failed to parse %s' % idl_filename)
idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename))
definitions = IdlDefinitions(idl_file_basename, ast)
# Validate file contents with filename convention
# The Blink IDL filenaming convention is that the file
# <definition_name>.idl MUST contain exactly 1 definition
# (interface, dictionary or exception), and the definition name must
# agree with the file's basename, unless it is a partial definition.
# (e.g., 'partial interface Foo' can be in FooBar.idl).
targets = (definitions.interfaces.values() +
definitions.dictionaries.values())
number_of_targets = len(targets)
if number_of_targets != 1:
raise Exception(
'Expected exactly 1 definition in file {0}, but found {1}'
.format(idl_filename, number_of_targets))
target = targets[0]
if not target.is_partial and target.name != idl_file_basename:
raise Exception(
'Definition name "{0}" disagrees with IDL file basename "{1}".'
.format(target.name, idl_file_basename))
# Validate extended attributes
if not self.extended_attribute_validator:
return definitions
try:
self.extended_attribute_validator.validate_extended_attributes(definitions)
except IDLInvalidExtendedAttributeError as error:
raise IDLInvalidExtendedAttributeError("""
IDL ATTRIBUTE ERROR in file:
%s:
%s
If you want to add a new IDL extended attribute, please add it to:
%s
and add an explanation to the Blink IDL documentation at:
http://www.chromium.org/blink/webidl/blink-idl-extended-attributes
""" % (idl_filename, str(error), EXTENDED_ATTRIBUTES_RELATIVE_PATH))
return definitions
# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""IDL type handling.
Classes:
IdlTypeBase
IdlType
IdlUnionType
IdlArrayOrSequenceType
IdlArrayType
IdlSequenceType
IdlNullableType
"""
from collections import defaultdict
################################################################################
# IDL types
################################################################################
INTEGER_TYPES = frozenset([
# http://www.w3.org/TR/WebIDL/#dfn-integer-type
'byte',
'octet',
'short',
'unsigned short',
# int and unsigned are not IDL types
'long',
'unsigned long',
'long long',
'unsigned long long',
])
NUMERIC_TYPES = (INTEGER_TYPES | frozenset([
# http://www.w3.org/TR/WebIDL/#dfn-numeric-type
'float',
'unrestricted float',
'double',
'unrestricted double',
]))
# http://www.w3.org/TR/WebIDL/#dfn-primitive-type
PRIMITIVE_TYPES = (frozenset(['boolean']) | NUMERIC_TYPES)
BASIC_TYPES = (PRIMITIVE_TYPES | frozenset([
# Built-in, non-composite, non-object data types
# http://heycam.github.io/webidl/#idl-types
'DOMString',
'ByteString',
'Date',
# http://heycam.github.io/webidl/#es-type-mapping
'void',
# http://encoding.spec.whatwg.org/#type-scalarvaluestring
'ScalarValueString',
]))
TYPE_NAMES = {
# http://heycam.github.io/webidl/#dfn-type-name
'any': 'Any',
'boolean': 'Boolean',
'byte': 'Byte',
'octet': 'Octet',
'short': 'Short',
'unsigned short': 'UnsignedShort',
'long': 'Long',
'unsigned long': 'UnsignedLong',
'long long': 'LongLong',
'unsigned long long': 'UnsignedLongLong',
'float': 'Float',
'unrestricted float': 'UnrestrictedFloat',
'double': 'Double',
'unrestricted double': 'UnrestrictedDouble',
'DOMString': 'String',
'ByteString': 'ByteString',
'ScalarValueString': 'ScalarValueString',
'object': 'Object',
'Date': 'Date',
}
STRING_TYPES = frozenset([
# http://heycam.github.io/webidl/#es-interface-call (step 10.11)
# (Interface object [[Call]] method's string types.)
'String',
'ByteString',
'ScalarValueString',
])
################################################################################
# Inheritance
################################################################################
ancestors = defaultdict(list) # interface_name -> ancestors
def inherits_interface(interface_name, ancestor_name):
return (interface_name == ancestor_name or
ancestor_name in ancestors[interface_name])
def set_ancestors(new_ancestors):
ancestors.update(new_ancestors)
class IdlTypeBase(object):
"""Base class for IdlType, IdlUnionType, IdlArrayOrSequenceType and IdlNullableType."""
def __str__(self):
raise NotImplementedError(
'__str__() should be defined in subclasses')
def __getattr__(self, name):
# Default undefined attributes to None (analogous to Jinja variables).
# This allows us to not define default properties in the base class, and
# allows us to relay __getattr__ in IdlNullableType to the inner type.
return None
def resolve_typedefs(self, typedefs):
raise NotImplementedError(
'resolve_typedefs should be defined in subclasses')
################################################################################
# IdlType
################################################################################
class IdlType(IdlTypeBase):
# FIXME: incorporate Nullable, etc.
# to support types like short?[] vs. short[]?, instead of treating these
# as orthogonal properties (via flags).
callback_functions = set()
callback_interfaces = set()
dictionaries = set()
enums = {} # name -> values
def __init__(self, base_type, is_unrestricted=False):
super(IdlType, self).__init__()
if is_unrestricted:
self.base_type = 'unrestricted %s' % base_type
else:
self.base_type = base_type
def __str__(self):
return self.base_type
@property
def is_basic_type(self):
return self.base_type in BASIC_TYPES
@property
def is_callback_function(self):
return self.base_type in IdlType.callback_functions
@property
def is_callback_interface(self):
return self.base_type in IdlType.callback_interfaces
@property
def is_enum(self):
# FIXME: add an IdlEnumType class and a resolve_enums step at end of
# IdlDefinitions constructor
return self.name in IdlType.enums
@property
def enum_values(self):
return IdlType.enums[self.name]
@property
def is_integer_type(self):
return self.base_type in INTEGER_TYPES
@property
def is_numeric_type(self):
return self.base_type in NUMERIC_TYPES
@property
def is_primitive_type(self):
return self.base_type in PRIMITIVE_TYPES
@property
def is_interface_type(self):
# Anything that is not another type is an interface type.
# http://www.w3.org/TR/WebIDL/#idl-types
# http://www.w3.org/TR/WebIDL/#idl-interface
# In C++ these are RefPtr or PassRefPtr types.
return not(self.is_basic_type or
self.is_callback_function or
self.is_enum or
self.name == 'Any' or
self.name == 'Object' or
self.name == 'Promise') # Promise will be basic in future
@property
def is_string_type(self):
return self.name in STRING_TYPES
@property
def may_raise_exception_on_conversion(self):
return (self.is_integer_type or
self.name in ('ByteString', 'ScalarValueString'))
@property
def is_union_type(self):
return isinstance(self, IdlUnionType)
@property
def name(self):
"""Return type name
http://heycam.github.io/webidl/#dfn-type-name
"""
base_type = self.base_type
return TYPE_NAMES.get(base_type, base_type)
@classmethod
def set_callback_functions(cls, new_callback_functions):
cls.callback_functions.update(new_callback_functions)
@classmethod
def set_callback_interfaces(cls, new_callback_interfaces):
cls.callback_interfaces.update(new_callback_interfaces)
@classmethod
def set_dictionaries(cls, new_dictionaries):
cls.dictionaries.update(new_dictionaries)
@classmethod
def set_enums(cls, new_enums):
cls.enums.update(new_enums)
def resolve_typedefs(self, typedefs):
# This function either returns |self| or a different object.
# FIXME: Rename typedefs_resolved().
return typedefs.get(self.base_type, self)
################################################################################
# IdlUnionType
################################################################################
class IdlUnionType(IdlTypeBase):
# http://heycam.github.io/webidl/#idl-union
def __init__(self, member_types):
super(IdlUnionType, self).__init__()
self.member_types = member_types
@property
def is_union_type(self):
return True
@property
def name(self):
"""Return type name (or inner type name if nullable)
http://heycam.github.io/webidl/#dfn-type-name
"""
return 'Or'.join(member_type.name for member_type in self.member_types)
def resolve_typedefs(self, typedefs):
self.member_types = [
typedefs.get(member_type, member_type)
for member_type in self.member_types]
return self
################################################################################
# IdlArrayOrSequenceType, IdlArrayType, IdlSequenceType
################################################################################
class IdlArrayOrSequenceType(IdlTypeBase):
"""Base class for IdlArrayType and IdlSequenceType."""
def __init__(self, element_type):
super(IdlArrayOrSequenceType, self).__init__()
self.element_type = element_type
def resolve_typedefs(self, typedefs):
self.element_type = self.element_type.resolve_typedefs(typedefs)
return self
class IdlArrayType(IdlArrayOrSequenceType):
def __init__(self, element_type):
super(IdlArrayType, self).__init__(element_type)
def __str__(self):
return '%s[]' % self.element_type
@property
def name(self):
return self.element_type.name + 'Array'
class IdlSequenceType(IdlArrayOrSequenceType):
def __init__(self, element_type):
super(IdlSequenceType, self).__init__(element_type)
def __str__(self):
return 'sequence<%s>' % self.element_type
@property
def name(self):
return self.element_type.name + 'Sequence'
################################################################################
# IdlNullableType
################################################################################
class IdlNullableType(IdlTypeBase):
def __init__(self, inner_type):
super(IdlNullableType, self).__init__()
self.inner_type = inner_type
def __str__(self):
# FIXME: Dictionary::ConversionContext::setConversionType can't
# handle the '?' in nullable types (passes nullability separately).
# Update that function to handle nullability from the type name,
# simplifying its signature.
# return str(self.inner_type) + '?'
return str(self.inner_type)
def __getattr__(self, name):
return getattr(self.inner_type, name)
@property
def is_nullable(self):
return True
@property
def name(self):
return self.inner_type.name
def resolve_typedefs(self, typedefs):
self.inner_type = self.inner_type.resolve_typedefs(typedefs)
return self
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Validate extended attributes.
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Extended-attribute-validation
"""
import os.path
import re
module_path = os.path.dirname(__file__)
source_path = os.path.join(module_path, os.pardir, os.pardir)
EXTENDED_ATTRIBUTES_RELATIVE_PATH = os.path.join('bindings',
'IDLExtendedAttributes.txt')
EXTENDED_ATTRIBUTES_FILENAME = os.path.join(source_path,
EXTENDED_ATTRIBUTES_RELATIVE_PATH)
class IDLInvalidExtendedAttributeError(Exception):
pass
class IDLExtendedAttributeValidator(object):
def __init__(self):
self.valid_extended_attributes = read_extended_attributes_file()
def validate_extended_attributes(self, definitions):
# FIXME: this should be done when parsing the file, rather than after.
for interface in definitions.interfaces.itervalues():
self.validate_extended_attributes_node(interface)
for attribute in interface.attributes:
self.validate_extended_attributes_node(attribute)
for operation in interface.operations:
self.validate_extended_attributes_node(operation)
for argument in operation.arguments:
self.validate_extended_attributes_node(argument)
def validate_extended_attributes_node(self, node):
for name, values_string in node.extended_attributes.iteritems():
self.validate_name_values_string(name, values_string)
def validate_name_values_string(self, name, values_string):
if name not in self.valid_extended_attributes:
raise IDLInvalidExtendedAttributeError(
'Unknown extended attribute [%s]' % name)
valid_values = self.valid_extended_attributes[name]
if values_string is None and None not in valid_values:
raise IDLInvalidExtendedAttributeError(
'Missing required argument for extended attribute [%s]' % name)
if '*' in valid_values: # wildcard, any (non-empty) value ok
return
if values_string is None:
values = set([None])
elif isinstance(values_string, list):
values = set(values_string)
else:
values = set([values_string])
invalid_values = values - valid_values
if invalid_values:
invalid_value = invalid_values.pop()
raise IDLInvalidExtendedAttributeError(
'Invalid value "%s" found in extended attribute [%s=%s]' %
(invalid_value, name, values_string))
def read_extended_attributes_file():
def extended_attribute_name_values():
with open(EXTENDED_ATTRIBUTES_FILENAME) as extended_attributes_file:
for line in extended_attributes_file:
line = line.strip()
if not line or line.startswith('#'):
continue
name, _, values_string = map(str.strip, line.partition('='))
value_list = [value.strip() for value in values_string.split('|')]
yield name, value_list
valid_extended_attributes = {}
for name, value_list in extended_attribute_name_values():
if not value_list:
valid_extended_attributes[name] = set([None])
continue
valid_extended_attributes[name] = set([value if value else None
for value in value_list])
return valid_extended_attributes
此差异已折叠。
# Copyright (C) 2013 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Resolve interface dependencies, producing a merged IdlDefinitions object.
This library computes interface dependencies (partial interfaces and
implements), reads the dependency files, and merges them to the IdlDefinitions
for the main IDL file, producing an IdlDefinitions object representing the
entire interface.
Design doc: http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Dependency-resolution
"""
import os.path
# The following extended attributes can be applied to a dependency interface,
# and are then applied to the individual members when merging.
# Note that this moves the extended attribute from the interface to the member,
# which changes the semantics and yields different code than the same extended
# attribute on the main interface.
DEPENDENCY_EXTENDED_ATTRIBUTES = set([
])
class InterfaceDependencyResolver(object):
def __init__(self, interfaces_info, reader):
"""Initialize dependency resolver.
Args:
interfaces_info:
dict of interfaces information, from compute_dependencies.py
reader:
IdlReader, used for reading dependency files
"""
self.interfaces_info = interfaces_info
self.reader = reader
def resolve_dependencies(self, definitions):
"""Resolve dependencies, merging them into IDL definitions of main file.
Dependencies consist of 'partial interface' for the same interface as
in the main file, and other interfaces that this interface 'implements'.
These are merged into the main IdlInterface, as the main IdlInterface
implements all these members.
Referenced interfaces are added to IdlDefinitions, but not merged into
the main IdlInterface, as these are only referenced (their members are
introspected, but not implemented in this interface).
Inherited extended attributes are also added to the main IdlInterface.
Modifies definitions in place by adding parsed dependencies.
Args:
definitions: IdlDefinitions object, modified in place
"""
if not definitions.interfaces:
# This definitions should have a dictionary. Nothing to do for it.
return
target_interface = next(definitions.interfaces.itervalues())
interface_name = target_interface.name
interface_info = self.interfaces_info[interface_name]
if 'inherited_extended_attributes' in interface_info:
target_interface.extended_attributes.update(
interface_info['inherited_extended_attributes'])
merge_interface_dependencies(definitions,
target_interface,
interface_info['dependencies_full_paths'],
self.reader)
for referenced_interface_name in interface_info['referenced_interfaces']:
referenced_definitions = self.reader.read_idl_definitions(
self.interfaces_info[referenced_interface_name]['full_path'])
definitions.update(referenced_definitions)
def merge_interface_dependencies(definitions, target_interface, dependency_idl_filenames, reader):
"""Merge dependencies ('partial interface' and 'implements') in dependency_idl_filenames into target_interface.
No return: modifies target_interface in place.
"""
# Sort so order consistent, so can compare output from run to run.
for dependency_idl_filename in sorted(dependency_idl_filenames):
dependency_definitions = reader.read_idl_file(dependency_idl_filename)
dependency_interface = next(dependency_definitions.interfaces.itervalues())
dependency_interface_basename, _ = os.path.splitext(os.path.basename(dependency_idl_filename))
transfer_extended_attributes(dependency_interface,
dependency_interface_basename)
definitions.update(dependency_definitions) # merges partial interfaces
if not dependency_interface.is_partial:
# Implemented interfaces (non-partial dependencies) are also merged
# into the target interface, so Code Generator can just iterate
# over one list (and not need to handle 'implements' itself).
target_interface.merge(dependency_interface)
def transfer_extended_attributes(dependency_interface, dependency_interface_basename):
"""Transfer extended attributes from dependency interface onto members.
Merging consists of storing certain interface-level data in extended
attributes of the *members* (because there is no separate dependency
interface post-merging).
The data storing consists of:
* applying certain extended attributes from the dependency interface
to its members
* storing the C++ class of the implementation in an internal
extended attribute of each member, [PartialInterfaceImplementedAs]
No return: modifies dependency_interface in place.
"""
merged_extended_attributes = dict(
(key, value)
for key, value in dependency_interface.extended_attributes.iteritems()
if key in DEPENDENCY_EXTENDED_ATTRIBUTES)
# A partial interface's members are implemented as static member functions
# in a separate C++ class. This class name is stored in
# [PartialInterfaceImplementedAs] which defaults to the basename of
# dependency IDL file.
# This class name can be overridden by [ImplementedAs] on the partial
# interface definition.
#
# Note that implemented interfaces do *not* need [ImplementedAs], since
# they are implemented on the C++ object |impl| itself, just like members of
# the main interface definition, so the bindings do not need to know in
# which class implemented interfaces are implemented.
#
# Currently [LegacyTreatAsPartialInterface] can be used to have partial
# interface behavior on implemented interfaces, but this is being removed
# as legacy cruft:
# FIXME: Remove [LegacyTreatAsPartialInterface]
# http://crbug.com/360435
#
# Note that [ImplementedAs] is used with different meanings on interfaces
# and members:
# for Blink class name and function name (or constant name), respectively.
# Thus we do not want to copy this from the interface to the member, but
# instead extract it and handle it separately.
if (dependency_interface.is_partial or
'LegacyTreatAsPartialInterface' in dependency_interface.extended_attributes):
merged_extended_attributes['PartialInterfaceImplementedAs'] = (
dependency_interface.extended_attributes.get(
'ImplementedAs', dependency_interface_basename))
for attribute in dependency_interface.attributes:
attribute.extended_attributes.update(merged_extended_attributes)
for constant in dependency_interface.constants:
constant.extended_attributes.update(merged_extended_attributes)
for operation in dependency_interface.operations:
operation.extended_attributes.update(merged_extended_attributes)
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
{# The warning below applies to the code generated by this template, not this file. #}
// WARNING: Do not edit - generated code.
part of dart_ui;
typedef void {{cpp_class}}({{methods[0].dart_argument_declarations | join(', ')}});
\ No newline at end of file
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
{# The warning below applies to the code generated by this template, not this file. #}
// WARNING: Do not edit - generated code.
library dart_ui;
import 'dart:async';
import 'dart:nativewrappers';
import 'dart:typed_data';
import 'dart:math' as math;
{% for interface in interfaces %}
part '{{interface.name}}.dart';
{% endfor %}
{% for callback in callbacks %}
part '{{callback.name}}.dart';
{% endfor %}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册