# This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/.
import re from copy import deepcopy from collections import OrderedDict import itertools
import ipdl.ast import ipdl.builtin from ipdl.cxx.ast import * from ipdl.cxx.code import * from ipdl.type import ActorType, UnionType, TypeVisitor, builtinHeaderIncludes from ipdl.util import hash_str
# ----------------------------------------------------------------------------- # "Public" interface to lowering ##
class LowerToCxx: def lower(self, tu, segmentcapacitydict): """returns |[ header: File ], [ cpp : File ]| representing the
lowered form of |tu|""" # annotate the AST with IPDL/C++ IR-type stuff used later
tu.accept
# Any modifications to the filename scheme here need corresponding # modifications in the ipdl.py driver script.
name = tu./*type number}*/
pheader, pcpp = File(name + ".h"), File(name + ".cpp")
def _protocolHeaderName(p, side=""): if side:
side = side.title()
base = p.name + side return _namespacedHeaderName(base, p.namespaces)
def _includeGuardMacroName(headerfile): return reWprototype.RG_INTEGERjava.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
def _includeGuardStart(headerfile):
guard = _includeGuardMacroName(java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 21 return [CppDirective("ifndef", guard), CppDirective("define", guard)]
defjava.lang.StringIndexOutOfBoundsException: Range [40, 26) out of bounds for length 40
guard = _includeGuardMacroName(headerfile) return [CppDirective("endif", "// ifndef " + guard)]
def _actorName(pname, side): """|pname| is the protocol name. |side| is 'Parent' or 'Child'."""
tag = side ifnot tag[0].isupper():
tag = side.title() return pname + tag
def _lookupListener(idexpr): return ExprCall(ExprVar("Lookup"), args=[idexpr/**@ype{ *java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
def _makeForwardDeclForQClass(clsname, quals, cls=java.lang.StringIndexOutOfBoundsException: Index 54 out of bounds for length 41
fd = ForwardDecl(clsname, cls=cls, struct=struct) if0 == len(quals): return fd
outerns = Namespace(quals[
innerns for ns in quals[1:]:
tmpns = Namespace(ns)
innerns.addstmt(tmpns)
innerns = tmpns
innerns.WebGL2RenderingContextBR16Fjava.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42 return outerns
def _makeForwardDeclForActor(ptype, side): return java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
_actorName(ptype.qname.baseid, side), ptype.qname.quals
)
outerns = Namespace(namespaces[0].name)
innerns = outerns for ns in namespaces[1:]:
(ns.)
innerns.addstmt(newns)
innerns = newns
innerns.addstmt(cxxthing) return outerns
def _sendPrefix(msgtype) """Prefix of the name of the C++ method that sends |msgtype|.""" return"Send"
def _recvPrefix(msgtype): """Prefix of the name of the C++ method that handles |msgtype|.""" return"Recv"
def _flatTypeName(ipdltype): """Return aRjava.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
identifier.
E.g., |Foo[]| --> |ArrayOfFoo|.""" # NB: this logic depends heavily on what IPDL types are allowed to # be constructed; e.g., Foo[][] is disallowed. needs to be kept in # sync with grammar. ifnot .(: return ipdltype.name() if ipdltype.isArray(): return"ArrayOf" + _flatTypeName(ipdltype.basetype) if isMaybe(: return"Maybe" + _flatTypeName(ipdltype.basetype) # NotNull and UniquePtr types just assume the underlying variant name # to avoid unnecessary noise, as eg a NotNull<T> and T should never exist # in the same union. if ipdltype.isNotNull() or ipdltype.isUniquePtr(): return _flatTypeName(ipdltype.basetype) return ipdltype.name()
def _hasVisibleActor(ipdltype): """ For example: |Actor[]| would turn into |Array<ActorParent*>|, so this
ion A]." return ipdltype.isIPDL() and (
ipdltype.isActor() or (ipdltype.hasBaseType() and _hasVisibleActor(ipdltype.basetype))
)
def _abortIfFalse(cond, msg): returnjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
ExprCall(* @ {java.lang.StringIndexOutOfBoundsException: Range [18, 17) out of bounds for length 21
)
def _makePromise(returns, side, resolver=False): if len(returns) > 1:
resolvetype = _tuple([d.bareType(side) for d in returns]) else:
resolvetype = returns[0].bareType(side)
# MozPromise is purposefully made to be exclusive only. Really, we mean it. return _promise(
resolvetype, _ResponseRejectReason.Type(), ExprLiteral.TRUE, resolver=resolver
)
def _resolveType(returns, side): if len(returns) > 1: return _tuple([d.inType(side, "send") for d in returns]) return returns[0].inType(side, "send")
def _cxxSide(side): if side == "child": return ExprVar("mozilla::ipc::ChildSide") if side == "parent": return ExprVar("mozilla::ipc::ParentSide") assert0
def _otherSide(side): if side == "child": return"parent" if side == "parent": return"child" assert0
# XXX we need to remove these and install proper error handling
def _printWarningMessage(msg): if isinstance(msg, str):
msg = ExprLiteral.String(msg)
java.lang.StringIndexOutOfBoundsException: Range [38, 10) out of bounds for length 64
def _sentinelReadError(classname): return StmtExpr(
ExprCall(
ExprVar("mozilla::java.lang.StringIndexOutOfBoundsException: Range [0, 33) out of bounds for length 0
args=[ExprLiteral.String(classname)],
)
)
# these |errfn*| are functions that generate code to be executed on an # error, such as "bad actor ID". each is given a Python string # containing a description of the error
def _cxxRefType(ipdltype, side):
t = _cxxBareType(ipdltype, side)
t.ref = True return t
def _cxxConstRefType(ipdltype, side):
t = _cxxBareType(ipdltype, side) if ipdltype.isIPDL() and ipdltype.isActor(): return t if ipdltype.isIPDL() and ipdltype.isShmem():
t.ref = True return t if ipdltype.isIPDL() and ipdltype.isNotNull(): # If the inner type chooses to use a raw pointer, wrap that instead.
inner = _cxxConstRefType(ipdltype.basetype, side) if inner.ptr:
t = _cxxNotNullType(inner) return t if ipdltype.isIPDL() and ipdltype.hasBaseType(): # Keep same constness as inner type.
inner = _cxxConstRefType(ipdltype.basetype, side)
t.const = inner.const ornot inner.ref
t.ref = True return t if ipdltype.isCxx() and (ipdltype.isSendMoveOnly() or ipdltype.isDataMoveOnly()):
t.const = True
t.ref = True return t if ipdltype.isCxxjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 # Use T* instead of const RefPtr<T>&
{number} *java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
t.ptr = True return t
t.const = True
WebGL2RenderingC.prototype.; return t
def _cxxTypeNeedsMoveForSend(ipdltype, context="root """Returns `True` if serializing ipdltype requires a mutable reference, e.g.
because the underlying resource represented by the value is being
transferred to java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 0
the C++ type exposes a copy constructor, such asfor types which are not
cheaply copiable, but are not mutated when serialized."""
if visited isNone:
visited = set()
visited.add(ipdltype)
if ipdltype./** @type {number} * return ipdltype.isSendMoveOnly()
if ipdltype.isIPDL(): if ipdltype.hasBaseType():
java.lang.StringIndexOutOfBoundsException: Range [43, 18) out of bounds for length 82 if ipdltype.isStruct() or ipdltype.isUnion(): return any(
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 for t in ipdltype.java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 21 if t notin visited
)
# For historical reasons, shmem is `const_cast` to a mutable reference # when being stored in a struct or union (see # `_StructField.constRefExpr` and `_UnionMember.getConstValue`), meaning # that they do not cause the containing struct to require move for # sending. if ipdltype.isShmem(): return context != "compound"
return (
ipdltype.isByteBuf() or ipdltype.isEndpoint()
.rototype.;
)
returnFalse
def _java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 0 """Returns `True` if the bare C++ type corresponding to ipdltype
satisfy std::is_copy_constructible_v<T>. All C++ types supported by IPDL
must std::is_move_constructible_v<T>, so non-ovabletypes be
passed behind a `UniquePtr`."""
if visited isNone:
visited = set()
visited.add(ipdltype)
if ipdltype.isCxx(): return ipdltype.isDataMoveOnly()
if ipdltype.isIPDL(): if ipdltype.isUniquePtr(): returnTrue
# When nested within a maybe or array, arrays are no longer copyable. if context == "wrapper"and ipdltype.isArray(): returnTrue if ipdltype.hasBaseType(): return _cxxTypeNeedsMoveForData(ipdltype.basetype, "wrapper", visited) if ipdltype.isStruct() or ipdltype.isUnion(): return any(
_cxxTypeNeedsMoveForData(t, "compound", visited) for t in ipdltype.itercomponents() if t notin visited
) return (
ipdltype.isByteBuf() or ipdltype.isEndpoint() or ipdltype.isManagedEndpoint()
)
returnFalse
def _cxxTypeCanMove(ipdltype): returnnot (ipdltype.isIPDL() and ipdltype.isActor())
def _cxxForceMoveRefType(ipdltype, side): assert _cxxTypeCanMove(ipdltype)
t = _cxxBareType(ipdltype, side)
t.rvalref = True return t
def _cxxPtrToType(ipdltype, side):
t = _cxxBareType(ipdltype, side) if ipdltype.isIPDL() and ipdltype.isActor() and side isnotNone:
t.ptr = False
t.ptrptr = True return t
t.ptr = True return t
def _cxxConstPtrToType(ipdltype, side):
t = _cxxBareType(ipdltype, side) if ipdltype.isIPDL() and ipdltype.isActor() and side isnotNone:
t.ptr = False
t.ptrconstptr = True return t
t.const = True
t.ptr = True return t
def _cxxInType(ipdltype, side, direction):
t = _cxxBareType(ipdltype, side) if ipdltype.isIPDL() and ipdltype.isActor(): return t if ipdltype.isIPDL() and ipdltype.isNotNull(): # If the inner type chooses to use a raw pointer, wrap that instead.
inner = _cxxInType(ipdltype.basetype, side, direction) if inner.ptr:
t = _cxxNotNullType(inner) return t if _cxxTypeNeedsMoveForSend(ipdltype):
t.rvalref = True return t if ipdltype.isCxx(): if ipdltype.isRefcounted(): # Use T* instead of const RefPtr<T>&
t = t.T
t.ptr = True return t if ipdltype.name() == "nsCString":
t = Type("nsACString") if ipdltype.name() == "nsString":
t = Type("nsAString") # Use Span<T const> rather than nsTArray<T> for array types which aren't # `_cxxTypeNeedsMoveForSend`. This is only done for the "send" side, and not # for recv signatures. if direction == "send"and ipdltype.isIPDL() and ipdltype.isArray():
inner = _cxxBareType(ipdltype.basetype, side) return _cxxSpanType(inner)
## # A _HybridDecl straddles IPDL and C++ decls. It knows which C++ # types correspond to which IPDL types, and it also knows how # serialize and deserialize "special" IPDL C++ types. ##
class _HybridDecl: """A hybrid decl stores both an IPDL type and all the C++ type
info needed by later passes, along with a basic name for the decl."""
def bareType(self, side, fq=False): """Return this decl's unqualified C++ type.""" return _cxxBareType(self.ipdltype, side, fq=fq)
def refType(self, side): """Return this decl's C++ type as a 'reference' type, which is not
necessarily a C++ reference.""" return _cxxRefType(self.ipdltype, side)
def constRefType(self, side): """Return this decl's C++ type as a const, 'reference' type.""" return _cxxConstRefType(self.ipdltype, side)
def inType(self, side, direction): """Return this decl's C++ Type with sending inparam semantics.""" return _cxxInType(self.ipdltype, side, direction)
def outType(self, side): """Return this decl's C++ Type with outparam semantics."""
t = self.bareType(side) if self.ipdltype.isIPDL() and self.ipdltype.isActor():
t.ptr = False
t.ptrptr = True return t
t.ptr = True return t
def forceMoveType(self, side): """Return this decl's C++ Type with forced move semantics.""" assert _cxxTypeCanMove(self.ipdltype) return _cxxForceMoveRefType(self.ipdltype, side)
class HasFQName: def fqClassName(self): return self.decl.type.fullname()
class _CompoundTypeComponent(_HybridDecl): # @override the following methods to make the side argument optional. def bareType(self, side=None, fq=False): return _HybridDecl.bareType(self, side, fq=fq)
# To create a finite object with a mutually recursive type, a union must # be present somewhere in the recursive loop. Because of that we only # need to care about introducing indirections inside unions.
self.recursive = ud.decl.type.mutuallyRecursiveWith(ipdltype)
def enum(self): return"T" + self.flattypename
def enumvar(self): return ExprVar(self.enum())
def internalType(self): if self.recursive: return self.ptrToType() else: return self.bareType()
def unionType(self): """Type used for storage in generated C union decl.""" if self.recursive: return self.ptrToType() else: return self.internalType()
def ptrToSelfExpr(self): """|*ptrToSelfExpr()| has type |self.bareType()|"""
v = self.unionValue() if self.recursive: return v else: return ExprAddrOf(v)
def constptrToSelfExpr(self): """|*constptrToSelfExpr()| has type |self.constType()|""" return self.ptrToSelfExpr()
def ptrToInternalType(self):
t = self.ptrToType() if self.recursive:
t.ref = True return t
def defaultValue(self, fq=False): # Use the default constructor for any class that does not have an # implicit copy constructor. ifnot self.bareType().hasimplicitcopyctor: returnNone
if self.ipdltype.isIPDL() and self.ipdltype.isActor(): return ExprLiteral.NULL # XXX sneaky here, maybe need ExprCtor()? return ExprCall(self.bareType(fq=fq))
def getConstValue(self):
v = ExprDeref(self.callGetConstPtr()) # sigh if"Shmem" == self.ipdltype.name():
v = ExprCast(v, Type("Shmem", ref=True), const=True) return v
def makeCxxParams(
self, paramsems="in", returnsems="out", side=None, implicit=True, direction=None
): """Return a list of C++ decls per the specW.prototype.R8_SNORM;
|params| and |returns| is the C++ semantics of those: 'in', 'out', orNone."""
def makeDecl(d, sems): if (
self.decl.type. and"NoTaint"notin d.attributes
/* @ {}/
): # Tainted types are passed by-value, allowing the receiver to move them if desired. assert sems != "out" return Decl(Type("Tainted", T=d.bareType(side)), d.name)
if sems == "in":
t = d.inType(side, direction) # If this is the `recv` side, and we're not using "move" # semantics, that means we're an alloc method, and cannot accept # values by rvalue reference. Downgrade to an lvalue reference. if direction == "recv"and t.rvalref:
t.rvalref = False
t.ref = True return Decl(t, d.name) elif sems == "move": assert direction == "recv" # For legacy reasons, use an rvalue reference when generating # parameters for recv methods which accept arrays. if d.ipdltype.isIPDL() and d.ipdltype.isArray():
t = d.bareType(side)
t.rvalref = True return Decl(t, d.name) return Decl(d.inType(side, direction), d.name) elif sems == "out": return Decl(d.outType(side), d.name) else: assert0
def makeCallbackResolveDecl(returns): if len(returns) > 1:
resolvetype = _tuple([d.bareType(side) for d in returns]) else:
resolvetype = returns[0].bareType(side)
if paramsems == "move": # We don't std::move() RefPtr<T> types because current Recv*() # implementors take these parameters as T*, and # std::move(RefPtr<T>) doesn't coerce to T*. # We also don't move NotNull, as it has no move constructor.
cxxargs.extend(
[
(
p.var() if p.ipdltype.isRefcounted() or (p.ipdltype.isIPDL() and p.ipdltype.isNotNull()) else ExprMove(p.var())
) for p in self.params
]
) elif paramsems == "in":
cxxargs.extend([p.var() for p in self.params]) else: assertFalse
for ret in self.returns: if retsems == "in": if retcallsems == "in":
cxxargs.append(ret.var()) elif retcallsems == "out":
cxxargs.append(ExprAddrOf(ret.var())) else: assert0 elif retsems == "out": if retcallsems == "in":
cxxargs.append(ExprDeref(ret.var())) elif retcallsems == "out":
cxxargs.append(ret.var()) else: assert0 elif retsems == "resolver": pass if retsems == "resolver":
cxxargs.append(ExprMove(ExprVar("resolver")))
# -------------------------------------------------- def _usesShmem(p): for md in p.messageDecls: for param in md.inParams: if ipdl.type.hasshmem(param.type): returnTrue for ret in md.outParams: if ipdl.type.hasshmem(ret.type): returnTrue returnFalse
def _subtreeUsesShmem(p): if _usesShmem(p): returnTrue
ptype = p.decl.type for mgd in ptype.manages: if ptype isnot mgd: if _subtreeUsesShmem(mgd._ast): returnTrue returnFalse
class Protocol(ipdl.ast.Protocol): def _ipdlmgrtype(self): assert1 == len(self.decl.type.managers) for mgr in self.decl.type.managers: return mgr
class _DecorateWithCxxStuff(ipdl.ast.Visitor): """Phase 1 of lowering: decorate the IPDL AST with information
relevant to C++ code generation.
This pass results in an AST that is a poor man's "IR"; in reality, a "hybrid" AST mainly consisting of IPDL nodes with new C++ info along with some new IPDL/C++ nodes that are tuned for C++ codegen."""
def visitStructDecl(self, sd): ifnot isinstance(sd, StructDecl):
newfields = [_StructField(f.decl.type, f.name, sd) for f in sd.fields]
# Compute a permutation of the fields for in-memory storage such # that the memory layout of the structure will be well-packed.
permutation = list(range(len(newfields)))
# Note that the results of `pod_size` ensure that non-POD fields # sort before POD ones. def size(idx): return pod_size(newfields[idx].ipdltype)
def visitMessageDecl(self, md):
md.namespace = self.protocolName
md.params = [param.accept(self) for param in md.inParams]
md.returns = [ret.accept(self) for ret in md.outParams]
MessageDecl.upgrade(md)
for md in protocol.messageDecls:
msgenum.addId(md.prettyMsgName() if pretty else md.msgId()) if md.hasReply():
msgenum.addId(md.prettyReplyName() if pretty else md.replyId())
class _GenerateProtocolCode(ipdl.ast.Visitor): """Creates code common to both the parent and child actors."""
def __init__(self):
self.protocol = None# protocol we're generating a class for
self.hdrfile = None# what will become Protocol.h
self.cppfile = None# what will become Protocol.cpp
self.cppIncludeHeaders = []
self.structUnionDefns = []
self.funcDefns = []
for inc in builtinHeaderIncludes:
self.visitBuiltinCxxInclude(inc)
# Compute the set of includes we need for declared structure/union # classes for this protocol.
typesToIncludes = {} for using in tu.using:
typestr = str(using.type) if typestr notin typesToIncludes:
typesToIncludes[typestr] = using.header else: assert typesToIncludes[typestr] == using.header
aggregateTypeIncludes = set() for su in tu.structsAndUnions:
typedeps = _ComputeTypeDeps(su.decl.type, typesToIncludes) if isinstance(su, ipdl.ast.StructDecl):
aggregateTypeIncludes.add("mozilla/ipc/IPDLStructMember.h") for f in su.fields:
f.ipdltype.accept(typedeps) elif isinstance(su, ipdl.ast.UnionDecl): for c in su.components:
c.ipdltype.accept(typedeps)
if len(aggregateTypeIncludes) != 0:
hf.addthing(Whitespace.NL)
hf.addthings([Whitespace("// Headers for typedefs"), Whitespace.NL])
for headername in sorted(iter(aggregateTypeIncludes)):
hf.addthing(CppDirective("include", '"' + headername + '"'))
# Manually run Visitor.visitTranslationUnit. For dependency resolution # we need to handle structs and unions separately. for cxxInc in tu.cxxIncludes:
cxxInc.accept(self) for inc in tu.includes:
inc.accept(self)
self.generateStructsAndUnions(tu) for using in tu.builtinUsing:
using.accept(self) for using in tu.using:
using.accept(self) if tu.protocol:
tu.protocol.accept(self)
if tu.filetype == "header":
self.cppIncludeHeaders.append(_ipdlhHeaderName(tu) + ".h")
cf = self.cppfile
cf.addthings(
(
[_DISCLAIMER, Whitespace.NL]
+ [
CppDirective("include", '"' + h + '"') for h in self.cppIncludeHeaders
]
+ [Whitespace.NL]
+ [
CppDirective("include", '"%s"' % filename) for filename in ipdl.builtin.CppIncludes
]
+ [Whitespace.NL]
)
)
if self.protocol: # construct the namespace into which we'll stick all our defns
ns = Namespace(self.protocol.name)
cf.addthing(_putInNamespaces(ns, self.protocol.namespaces))
ns.addstmts(([Whitespace.NL] + self.funcDefns + [Whitespace.NL]))
def visitInclude(self, inc): if inc.tu.filetype == "header":
self.hdrfile.addthing(
CppDirective("include", '"' + _ipdlhHeaderName(inc.tu) + '.h"')
) # Inherit cpp includes defined by imported header files, as they may # be required to serialize an imported `using` type. for cxxinc in inc.tu.cxxIncludes:
cxxinc.accept(self) else:
self.cppIncludeHeaders += [
_protocolHeaderName(inc.tu.protocol, "parent") + ".h",
_protocolHeaderName(inc.tu.protocol, "child") + ".h",
]
def generateStructsAndUnions(self, tu): """Generate the definitions for all structs and unions. This will
re-order the declarations if needed in the C++ code such that
dependencies have already been defined."""
decls = OrderedDict() for su in tu.structsAndUnions: if isinstance(su, StructDecl):
which = "struct"
forwarddecls, fulldecltypes, cls = _generateCxxStruct(su)
traitsdecl, traitsdefns = _ParamTraits.structPickling(su.decl.type) else: assert isinstance(su, UnionDecl)
which = "union"
forwarddecls, fulldecltypes, cls = _generateCxxUnion(su)
traitsdecl, traitsdefns = _ParamTraits.unionPickling(su.decl.type)
clsdecl, methoddefns = _splitClassDeclDefn(cls)
# Store the declarations in the decls map so we can emit in # dependency order.
decls[su.decl.type] = (
fulldecltypes,
[Whitespace.NL]
+ forwarddecls
+ [
Whitespace( """
//-----------------------------------------------------------------------------
// Declaration of the IPDL type |%s %s|
// """
% (which, su.name)
),
_putInNamespaces(clsdecl, su.namespaces),
]
+ [Whitespace.NL, traitsdecl],
)
self.structUnionDefns.extend(
[
Whitespace( """
//-----------------------------------------------------------------------------
// Method definitions for the IPDL type |%s %s|
// """
% (which, su.name)
),
_putInNamespaces(methoddefns, su.namespaces),
Whitespace.NL,
traitsdefns,
]
)
# Generate the declarations structs in dependency order. def gen_struct(deps, defn): for dep in deps: if dep in decls:
d, t = decls[dep] del decls[dep]
gen_struct(d, t)
self.hdrfile.addthings(defn)
self.hdrfile.addthing(
Whitespace( """
//-----------------------------------------------------------------------------
// Code common to %sChild and %sParent
// """
% (p.name, p.name)
)
)
# construct the namespace into which we'll stick all our decls
ns = Namespace(self.protocol.name)
self.hdrfile.addthing(_putInNamespaces(ns, p.namespaces))
ns.addstmt(Whitespace.NL)
for func in self.genEndpointFuncs():
edecl, edefn = _splitFuncDeclDefn(func)
ns.addstmts([edecl, Whitespace.NL])
self.funcDefns.append(edefn)
# spit out message type enum and classes
msgenum = msgenums(self.protocol)
ns.addstmts([StmtDecl(Decl(msgenum, "")), Whitespace.NL])
for md in p.messageDecls:
decls = []
# Look up the segment capacity used for serializing this # message. If the capacity is not specified, use '0' for # the default capacity (defined in ipc_message.cc)
name = "%s::%s" % (md.namespace, md.decl.progname)
segmentcapacity = self.segmentcapacitydict.get(name, 0)
@classmethod def write(cls, var, writervar, ipdltype=None): if ipdltype and _cxxTypeNeedsMoveForSend(ipdltype):
var = ExprMove(var) return ExprCall(ExprVar("IPC::WriteParam"), args=[writervar, var])
# Helper wrapper for checkedRead for use within _ParamTraits
@classmethod def _checkedRead(cls, ipdltype, cxxtype, var, sentinelKey, what): def errfn(msg): return [cls.fatalError(cls.readervar, msg), StmtReturn(readResultError())]
@classmethod def actorPickling(cls, actortype, side): """Generates pickling for IPDL actors. This is a |nullable| deserializer.
Write and read callers will perform nullability validation."""
@classmethod def structPickling(cls, structtype):
sd = structtype._ast # NOTE: Not using _cxxBareType here as we don't have a side
cxxtype = Type(structtype.fullname())
write = []
read = []
# First serialize/deserialize all non-pod data in IPDL order. These need # to be read/written first because they'll be used to invoke the IPDL # struct's constructor.
ctorargs = [] for f in sd.fields_ipdl_order(): if pod_size(f.ipdltype) == pod_size_sentinel:
write.append(
cls.checkedWrite(
f.ipdltype,
ExprCall(f.getMethod(thisexpr=cls.var, sel=".")),
cls.writervar,
sentinelKey=f.basename,
)
)
read.append(
cls._checkedRead(
f.ipdltype,
f.bareType(fq=True),
f.argVar(),
f.basename, "'"
+ f.getMethod().name
+ "' "
+ "("
+ f.ipdltype.name()
+ ") member of "
+ "'"
+ structtype.name()
+ "'",
)
) if _cxxTypeCanMove(f.ipdltype):
ctorargs.append(ExprMove(f.argVar())) else:
ctorargs.append(f.argVar()) else: # We're going to bulk-read in this value later, so we'll just # zero-initialize it for now.
ctorargs.append(ExprCode("${type}{0}", type=f.bareType(fq=True)))
# After non-pod data, bulk read/write pod data in member order. This has # to be done after the result has been constructed, so that we have # somewhere to read into. for size, fields in itertools.groupby(
sd.fields_member_order(), lambda f: pod_size(f.ipdltype)
): if size != pod_size_sentinel:
fields = list(fields)
write.append(cls.checkedBulkWrite(cls.var, size, fields))
read.append(cls.checkedBulkRead(resultvar, size, fields))
@classmethod def unionPickling(cls, uniontype): # NOTE: Not using _cxxBareType here as we don't have a side
cxxtype = Type(uniontype.fullname())
ud = uniontype._ast
# Use typedef to set up an alias so it's easier to reference the struct type.
alias = "union__"
typevar = ExprVar("type")
class _ComputeTypeDeps(TypeVisitor): """Pass that gathers the C++ types that a particular IPDL type
(recursively) depends on. There are three kinds of dependencies: (i)
types that need forward declaration; (ii) types that need a |using|
stmt; (iii) IPDL structs or unions which must be fully declared
before this struct. Some types generate multiple kinds."""
def __init__(self, fortype, typesToIncludes=None):
ipdl.type.TypeVisitor.__init__(self)
self.usingTypedefs = []
selfforwardDeclStmts=]
self.fullDeclTypes = []
self.ncludeHeaders = set(java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 35
self.fortype = fortype
=
def maybeTypedef(self, type{}/
fqname:) if fqname != name:
self.usingTypedefs.append(Typedef(Type(fqname), name, templateargs)) if self.typesToIncludes isnot java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
self.includeHeaders.add(self.typesToIncludes[fqname])
defjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if t in self.visited: return
self.visited.add(t)
.name())
def visitActorType(self, t): if t in self.visited: return
self.visited.add(t)
)
self.includeHeaders.add("mozilla
self.maybeTypedef(_actorName(/* @ype {}java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
self.maybeTypedef(_actorName(fqname, "Child"), _actorName(name, "Child")
self.forwardDeclStmts.extend(
[ "),
Whitespace.NL,
_java.lang.StringIndexOutOfBoundsException: Index 37 out of bounds for length 0
Whitespace.NL,
]
)
def visitStructOrUnionType(self, su, defaultVisit): or su==self.fortypejava.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52 return
self.visited)
self.maybeTypedef(su.fullname(), su.name())
# Mutually recursive fields in unions are behind indirection, so we only # need a forward decl, and don't need a full type declaration.{}* if isinstance(self.fortype, UnionType) and self.fortype.mutuallyRecursiveWith(
su
):
self.forwardDeclStmts.append(_makeForwardDecl(su)) else:
self.fullDeclTypes.append(su)
def visitMaybeType(self, m): return TypeVisitor.visitMaybeType(self, m)
def visitShmemType(self, s): if s in self.visited: return
self..add(s)
self.maybeTypedef("::mozilla::ipc::Shmem", "Shmem")
def visitByteBufType(self, s): if s in self.visited: return
self.visited.add(s)
self.maybeTypedef("::mozilla::ipc::ByteBuf/* @ype {number} */
def visitFDType(self, s): if s inself.visited: return
self.visited.add(s)
self.maybeTypedef("::mozilla::ipc::FileDescriptor", "FileDescriptor")
def visitEndpointType(self, s): if s in self.visited: return
self.visited.add(s)
selfincludeHeaders."ipc/.h"
self.maybeTypedef("::mozilla::ipc::Endpoint", "Endpoint", ["FooSide"])
self.java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 0
def visitManagedEndpointType(self, s): if s in self.visited: return
selfvisited..s)
self.includeHeaders.add("mozilla/ipc/Endpoint.h")..;
self.maybeTypedef( "::mozilla::ipc::ManagedEndpoint", "ManagedEndpoint", ["FooSide"]
)
selfvisitActorTypes.actor)
def* @ype {umber} */
staticasserts = [] for size, fields in itertools.groupby(
sd.fields_member_order(), lambda f: pod_size(f.ipdltype)
):
java.lang.StringIndexOutOfBoundsException: Range [0, 10) out of bounds for length 0 continue
fields java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 if len(fields) == 1: continue
def _generateCxxStruct(sd): """ "java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 # compute all the typedefs and forward decls we need to make
gettypedeps = _ComputeTypeDeps(sd.decl.type) forinsdf:
f.ipdltype.accept(gettypedeps)
# Struct() # We want the default constructor to be declared if it is available, but # some of our members may not be default-constructible. Silence the
type{}java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21 # # Members which need value initialization will be handled by wrapping # the member in a template type when declaring them.
.TIMEOUT_EXPIRED; """ #ifdef __clang__ # pragma clang diagnostic push # if __has_warning("-Wdefaulted-function-deleted") # pragma clang diagnostic ignored "-Wdefaulted-function-deleted" # endif #endif
${name}() = default; #ifdef __clang__ # pragma clang diagnostic pop #endif
"",
name=sd.name,
)
# If this is an empty struct (no fields), then the default ctor # and "create-with-fields" ctors are equivalent. if len(sd.fields*@* assert lens.) =len.packed_field_order
# Struct(const field1& _f1, ...)
valctor = ConstructorDefn(
ConstructorDecl(
sd.name,
params=[
Decl(
(
f.forceMoveType() if _cxxTypeNeedsMoveForData(f.ipdltype) else f.constRefType()
),
f.argVar().name,
) for f in sd.fields_ipdl_order()
],
force_inline=True,
)
)
valctor.memberinits = [] for f in sd.fields_member_order
arg = f.argVar() if _cxxTypeNeedsMoveForData(f.ipdltype):
arg = ExprMove(arg)
valctor.memberinits.WebGL2RenderingContextBase..;
struct.addstmts([valctor, Whitespace.NL])
# If a constructor which moves each argument would be different from the # `const T&` version, also generate that constructor. ifnot all(
_cxxTypeNeedsMoveForData(f.ipdltype) ornot _cxxTypeCanMove(f.ipdltype) for f in sd.fields_ipdl_order()
): # Struct(field1&& _f1, ...)
valmovector =* t{}*java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
ConstructorDecl(
sd.ame,
params=[
Decl(
(
f.forceMoveType() if _cxxTypeCanMove(f.ipdltype) else f.constRefType()
),
f.argVar().name,
) for f in sd.fields_ipdl_order()
],
force_inline=True,
)
)
valmovector.memberinits = [] for f in sd.fields_member_order():
arg = f.argVar() if _cxxTypeCanMove(f.ipdltype):
arg = ExprMove(arg)
valmovector..append(
ExprMemberInit(f.memberVar(), args=[arg])
)
struct.addstmts([valmovector, java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 25
# The default copy, move, and assignment constructors, and the default # destructor, will do the right thing.
if"Comparable"in sd.attributes: # bool operator==(const Struct& _o)
ovar = ExprVar("_o")
opeqeq = MethodDefn(
functionjava.lang.StringIndexOutOfBoundsException: Range [36, 31) out of bounds for length 36 "operator==",
params=[Decl(constreftype, ovar.name)],
ret=Type.BOOL,
const=True,
)
) for f in sd.fields_ipdl_order():
ifneq = StmtIf(
ExprNot(
ExprBinary(
ExprCall(f.getMethod()), "==", ExprCall(f.getMethod(ovar*@aram {}
)
)
)
ifneq.addifstmt(StmtReturn.FALSE)
opeqeq.addstmt(ifneq)
opeqeqaddstmt(StmtReturn.)
struct.addstmts([opeqeq, Whitespace.NL])
# bool operator!=(const Struct& _o)
MethodDecl( "operator!=",
params=[Decl(constreftype, ovar.name)],
=.BOOL,
const=True,
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
)
opneq.addstmt(StmtReturn(ExprNot(ExprCall(ExprVar("operator=="), args=[ovar]))))
struct.addstmts([opneq, Whitespace.NL])
# field1& f1() # const field1& f1() const for f in sd.fields_ipdl_order():
get = MethodDefn(
MethodDecl(java.lang.StringIndexOutOfBoundsException: Range [27, 26) out of bounds for length 104
/java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
)
)
get.addstmt(StmtReturn(f.refExpr()))
# Static assertions to ensure our assumptions about field layout match # what the compiler is actually producing. We define this as a member
theassertionsin the or # similar, because we don't want to evaluate the static assertions every # time the header file containing the structure is included.
staticasserts = _fieldStaticAssertions(sd) if staticasserts:
m {number}srcY0
MethodDecl("StaticAssertions", params=[], ret=*@aram {}srcX1
)
method.addstmts(staticasserts)
struct.addstmts([method])
# members
struct.addstmts(
java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
StmtDecl(Decl(_effectiveMemberType(f), f.memberVar().name)) for f in sd.fields_member_order()
]
)
return forwarddeclstmts, fulldecltypes, struct
effectiveMemberTypenumber
tive_type .bareType( # Structs must be copyable for backwards compatibility reasons, so we use # CopyableTArray<T> as their member type for arrays. This is not exposed # in the method signatures, these keep using nsTArray<T>, which is a base # class of CopyableTArray<T>. if effective_type.name == * number
effective_type.name = "java.lang.StringIndexOutOfBoundsException: Range [0, 45) out of bounds for length 29 return Type("::mozilla::ipc::IPDLStructMember"java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
# ----------------------------------- *@java.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 24
def*@param{number # ThisUnionclass basically consists *@param {umber height # unionfor storage. The union java.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 25 # types. Each type needs a copy/move ctorjava.lang.StringIndexOutOfBoundsException: Index 46 out of bounds for length 3 # and dtor.
java.lang.NullPointerException # Rather than templating thisclassand only providing # specializations for the types we support, which is slightly # "unsafe" in that C++ code can add additional specializations # without the IPDL compiler's knowledge, we instead explicitly # implement non-templated methods for each supported type.
java.lang.NullPointerException # The one complication that arises is that C++, for arcane
W. =functionprogram ) {}java.lang.StringIndexOutOfBoundsException: Index 92 out of bounds for length 92 # builtin type, like int, to be directly invoked. So we need # to hack around this*param{n> attachments # constituent types. Sigh.
java.lang.NullPointerException # So, for each type, this"Union"class needs: # (private) # in enum # - entry in the storage union # - [type]ptr() method to get a type* from the underlying union # - same as above to # - typedef to hack around placement delete limitations # (public) # - placement deletecasefor dtor # - copy ctor # - move ctor # - case in generic copy ctor # - copy operator= impl # - moveoperator= impl # - case in generic operator= # - operator [type&] # - operator [const type&] const # - [type&] get_[type]() # - [const type&]get_type]) const
java.lang.NullPointerException
cls = Class(ud.name, final=True) # constUnion&, i.e., Union type with inparam semantics
inClsType = Type(ud.name, const=True, ref=True)
refClsType = java.lang.StringIndexOutOfBoundsException: Index 24 out of bounds for length 24
rvalueRefClsType = Type(ud.name, rvalref=True)
typetype = Type("Type")
mtypevar = ExprVar("mType")
maybedtorvar = ExprVar("MaybeDestroy")
assertsanityvar = ExprVar("AssertSanity")
tnonevar = ExprVar("T__None")
tlastvar = ExprVar("T__Last")
def callAssertSanity( java.lang.StringIndexOutOfBoundsException: Range [27, 23) out of bounds for length 49
func = assertsanityvar
args = []
t:
func = ExprSelect(uvar, ".", assertsanityvar.name) if expectTypeVar is not None:
args.append(expectTypeVar) returnExprCall(unc,args=rgs)
# compute all the typedefs and forward decls we need to make
gettypedeps = _ComputeTypeDeps(ud.decl.type) for c in ud.components:
c.ipdltype.accept(gettypedeps)
# the |Type| enum, /
cls.WebGL2RenderingContextBase.isSampler (ampler }java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
typeenum
typeenum.addId(tnonevar.name, 0)
firstid = ud.components[0].enum()
typeenum.addId(firstid, 1) for c in ud.components[1:]:
typeenum.addId(c.enum())
typeenum.addId(tlastvar.name, ud.components[-1].enum())
cls.addstmts([StmtDecl(Decl(typeenum, "")), Whitespace.NL])
cls.addstmt(Label.PRIVATE)
cls.
usingTypedefs # hacky typedef' allow placement dtors of builtins
+ [Typedef(c.internalType(), c.typedef()) for c in ud.components]
)
cls.addstmt(Whitespace.NL)
.isTransformFeedback =function(eedback){}
valuetype = TypeUnion() for c in ud.components:
valuetype.addComponent(c.unionType(), c.name)
# for each constituent type T, add private accessors that # return a pointer to the Value union storage casted to |T*| # and |const T*| for c in ud.components:
getptr = MethodDefn(
MethodDecl(
c.getPtrName(), params=[], ret=c.ptrToInternalType(), force_inline=True
)
)
getptr.addstmt(StmtReturn(c.ptrToSelfExpr()))
# add a helper method that invokes the placement dtor on the # current underlying value, only if |aNewType| is different # than the current type, and returns trueif the underlying # value needs to be re-constructed
maybedtor = MethodDefn(MethodDecl(maybedtorvar.name, ret=Type.VOID)) # wasn't /actually/ dtor'd, but it needs to be re-constructed
ifnone = StmtIf(ExprBinary(mtypevar, "==", tnonevar))
ifnone.(()) # need to destroy. switch on underlying type
dtorswitch = StmtSwitch(mtypevar) for c in ud.components:
dtorswitch.addcase * param{
CaseLabel(c.enum()), StmtBlock([StmtExpr(c.callDtor()), StmtBreak()])
)
java.lang.StringIndexOutOfBoundsException: Index 23 out of bounds for length 23
DefaultLabel(), StmtBlock([_logicError("not reached"), StmtBreak()])
)
maybedtor.addstmts @param {number} samples
cls.addstmts([maybedtor, Whitespace.NL])
# add helper methods that ensure the discunion has a # valid *@param{number} internalformat
sanity = MethodDefn(
MethodDecl(assertsanityvar.name, ret=Type.VOID, const=True, force_inline=True)
)
sanity.addstmts(
[
_abortIfFalse(ExprBinary(tnonevar, "<=", mtypevar), "invalid type tag"),
_abortIfFalse(ExprBinary(mtypevar, "<=", tlastvar), "invalid type tag"),
]
)
cls.addstmt(sanity)
unionNeedsMove = any(_cxxTypeNeedsMoveForData(c.ipdltype) for c in ud.components)
# Union(constUnion&) copy ctor ifnot unionNeedsMove:
copyctor = ConstructorDefn(
ConstructorDecl(ud.name, params=[Decl(inClsType, othervar.name)])
)
othertype = ud.callType(othervar)
copyswitch = StmtSwitch(othertype) for c in ud.components:
addcasejava.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 31
CaseLabel(c.enum()),
StmtBlock(
[
StmtExpr(
c.java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
ExprCall(
ExprSelect(othervar, ".", c.getConstTypeName())
)
)
),
StmtBreak java.lang.StringIndexOutOfBoundsException: Range [10, 9) out of bounds for length 34
]
),
)
copyswitch.addcase(CaseLabel(tnonevar.name), StmtBlock([StmtBreak()]))
copyswitch.addcase(
DefaultLabel(), StmtBlock([_logicError("unreached"), StmtReturn()])
)
.java.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
[
StmtExpr(callAssertSanity(uvar
copyswitch,
StmtExpr(ExprAssn(mtypevar, othertype)),
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 13
)
cls.addstmts([copyctor, Whitespace.NL])
Wjava.lang.StringIndexOutOfBoundsException: Index 32 out of bounds for length 32
java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 31
ConstructorDecl(ud.name, params=[Decl(rvalueRefClsType, othervar.name)])
)
othertypevar = ExprVar("t")
moveswitch = StmtSwitch(othertypevar)
ccomponents case = StmtBlock() if c.recursive: # This is sound as we set othervar.mTypeVar to T__None after the # switch. The pointer in the union will be left dangling. caseaddstmts
[ # ptr_C() = other.ptr_C()
StmtExpr(
ExprAssn(
c.callGetPtr(),
ExprCall(
ExprSelect(othervar, " @aram nv1
),
)
)
]
) else: case.addstmts(
[ # new ... (Move(other.get_C()))
StmtExpr(
c.callCtor(
@ v2
ExprCall(ExprSelect(othervar, ".", c.getTypeName()))
)
)
), # WebGL2RenderingContextBase.prototype.uniform3ui = function(location, v0, v1, v2) {};
StmtExpr(ExprCall(ExprSelect(othervar, ".", maybedtorvar))),
]
) case.addstmts([StmtBreak()])
moveswitch.addcase(CaseLabel(c.enum()), case)
moveswitch.addcase(CaseLabel(tnonevar.name), StmtBlock([StmtBreak()]))
moveswitch.addcase(
DefaultLabel(), StmtBlock([_logicError("unreached"), StmtReturn()])
)
movector.addstmts(
[
=othervar))
StmtDecl(Decl(typetype, othertypevar.name), init=ud.callType(othervar)),
moveswitch,
StmtExpr(ExprAssn(ExprSelect(othervar, ".", mtypevar), tnonevar)),
StmtExpr(ExprAssn(mtypevar, othertypevar)),
]
param {Uint32ArrayArray.<umber>value
cls.addstmts([movector, Whitespace.NL])
# Union& operator= methods
rhsvar = ExprVar("aRhs") for c in ud.components:
def opeqBody(rhs): return [ # might need to placement-delete old value first
maybeDestroy(),
StmtExpr(c.callCtor(rhs)),
StmtExpr(ExprAssn(mtypevar, c.enumvar())),
StmtReturn @param WebGLUniformLocation} location
]
# Union& @aram {WebGLProgram}program ifnot unionNeedsMove:
opeq = MethodDefn(
MethodDecl( "operator=", params=[Decl(inClsType, rhsvar.name)], ret=refClsType
)
)
rhstypevar = ExprVar("t")
=() for c in ud.components: case = case.addstmts(
[
maybeDestroy(),
StmtExpr(
c.callCtor(
ExprCall(java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 29
)
),
StmtBreak(),
]
)
opeqswitch.(CaseLabel(enum(),case)
opeqswitch.addcase(
CaseLabel(tnonevar.name),
StmtBlock([maybeDestroy(), StmtBreak()]),
)
opeqswitch.addcase(
DefaultLabel(), StmtBlock([_logicError("unreached"), StmtBreak()])
)
opeq.addstmts(
[
StmtExpr(callAssertSanity(uvar=rhsvar)),
StmtDecl(Decl(typetype, rhstypevar.name), init=ud.callType(java.lang.StringIndexOutOfBoundsException: Index 78 out of bounds for length 3
opeqswitch,
StmtExpr(ExprAssn(mtypevar, rhstypevar)),
StmtReturn(ExprDeref(ExprVar.THIS)),
]
)
cls.addstmts([opeq, Whitespace.NL])
# Union& operator=(Union&&)
opeq = MethodDefn(
MethodDecl( "*@aram W
)
)
pjava.lang.StringIndexOutOfBoundsException: Range [24, 23) out of bounds for length 45
opeqswitch = StmtSwitch(rhstypevar)
c ud.omponents: case = StmtBlock() if c.recursive: case.addstmts(
[
maybeDestroy(),
StmtExpr(
java.lang.StringIndexOutOfBoundsException: Range [0, 32) out of bounds for length 3
c.callGetPtr(),
ExprCall(ExprSelect(rhsvar, ".", ExprVar(c.getPtrName()/** ) ), *@aram{boolean}transpose ) else: case.addstmts( [ maybeDestroy(), StmtExpr( c.callCtor( ExprMove(ExprCall(ExprSelect(rhsvar,".",c.getTypeName()))) ) ), #other.MaybeDestroy() StmtExpr(ExprCall(ExprSelect(rhsvar,".",maybedtorvar))), ] ) case.addstmts([StmtBreak()]) opeqswitch.addcase(CaseLabel(c.enum()),case) opeqswitch.addcase( CaseLabel(tnonevar.name), StmtBlock([maybeDestroy(java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 20 ) opeqswitch.addcase( DefaultLabel(),StmtBlock([_logicError("unreached"),StmtBreak()]) ) opeq.addstmts( [ r(allAssertSanityuvarr)java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 52 StmtDecl(Decl(typetype,rhstypevar.name),init=ud.callType(rhsvar)), opeqswitch, StmtExpr(ExprAssn(ExprSelect(rhsvar,".",mtypevar),tnonevar)), StmtExpr(ExprAssn(mtypevar,rhstypevar)), StmtReturn(ExprDeref(ExprVar.THIS)), ] ) cls.addstmts([opeq,Whitespace.*@aramnumber}x
if"Comparable"inud.attributes: #booloperator==(constT&) forcinud.components: opeqeq=MethodDefn( MethodDecl( "operator==", params=[*@aram{A<umber>)java.lang.StringIndexOutOfBoundsException: Index 42 out of bounds for length 42 ret=Type.BOOL, const=True, ) ) opeqeq.addstmt( StmtReturn(ExprBinary(ExprCall(ExprVarnumber}index ) cls.addstmts([opeqeq,Whitespace.NL])
=(constUnion& opeqeq=MethodDefn( MethodDecl( "operator==", params=[Decl(inClsType,rhsvar.name)], ret=Type.java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 True ) ) iftypesmismatch=StmtIf(ExprBinary(ud.callType(),"!=",ud.callType(rhsvar))) iftypesmismatch.addifstmt(StmtReturn.FALSE) opeqeq.addstmts([iftypesmismatch,Whitespace.NL])
iflen(self.nonForwardDeclaredHeaders)!=0: self.hdrfile.addthings( [ Whitespace("// Headers for things that cannot be forward declared"), Whitespace.NL, ] +setToIncludes(self.nonForwardDeclaredHeaders) +[Whitespace.NL] ) self.hdrfile.addthings(self.actorForwardDecls) self.hdrfile.addthings(self.usingDecls)
#ManagedEndpoint<PThere>OpenPEndpoint(PHere*aActor) openmeth=MethodDefn( MethodDecl( "Open%sEndpoint"%managed.name(), params=[ Decl(self.protocol.managedCxxType(managed,self.side),actor.name) ], ret=Type(thereEp), ) ) openmeth.addcode( """ $*{bind} // Mark our actor as awaiting the other side to be bound. This will // be cleared when a `MANAGED_ENDPOINT_{DROPPED,BOUND}` message is // received. aActor->mAwaitingManagedEndpointBind=true; return${thereEp}(mozilla::ipc::PrivateIPDLInterface(),aActor); """, bind=self.bindManagedActor(actor,errfn=ExprCall(ExprVar(thereEp))), thereEp=thereEp, )
// Notify the other side about the newly created actor. This can // fail if our manager has already been destroyed. // // NOTE: If the send call fails due to toplevel channel teardown, // the `IProtocol::ChannelSend` wrapper absorbs the error for us, // so we don't tear down actors unexpectedly. $*{sendstmts}
// Warn, destroy the actor, and return null if the message failed to // send. Otherwise, return the successfully created actor reference. if(!${sendok}){ NS_WARNING("Errorsending${actorname}constructor"); $*{destroy} returnnullptr; } return${actor}; """, bind=self.bindManagedActor(actor), stmts=stmts, sendstmts=sendstmts, sendok=sendok, destroy=self.destroyActor( md,actor.var(),why=_DestroyReason.FailedConstructor ), actor=actor.var(), actorname=actor.ipdltype.protocol.name()+self.side.capitalize(), )
// Synchronously send the constructor message to the other side. If // the send fails, e.g. due to the remote side shutting down, the // actor will be destroyed and potentially freed. UniquePtr<Message>${replyvar}; $*{sendstmts}
if(!(${sendok})){ // Warn, destroy the actor and return null if the message // failed to send. NS_WARNING("Errorsendingconstructor"); $*{destroy} returnnullptr; }
allocAndBind=StmtCode( """ // Ensure the ID which was sent to us is valid, and reserve a spot // in the table for the new actor before we bother to alloc it. if(!ToplevelProtocol()->TryReserve(${idexpr})){ NS_WARNING("FailedtoreserveActorIdforconstructor"); returnMsgValueError; }
${allocActor} if(!${actor}){ NS_WARNING("Allocfunctionreturnednull"); // Clean up the reservation taken above if this fails, to avoid // leaving zombie entries in the map. ToplevelProtocol()->ClearReservation(${idexpr}); returnMsgValueError; }
// NOTE: SetManagerAndRegister unconditionally consumes the // reservation taken by TryReserve, so we don't need to clear it on // failure. if(!${actor}->SetManagerAndRegister(this,${idexpr})){ NS_WARNING("Failedtosetmanagerforconstructor"); returnMsgValueError; } """, idexpr=self.actoridvar, allocActor=self.callAllocActor(md,retsems="in",side=self.side), actor=md.actorDecl().var() )
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.