@@ -1080,7 +1080,7 @@ def generate_code(self):
10801080 name = self ._ctor .identifier .name
10811081 nativeName = MakeNativeName (self .descriptor .binaryNames .get (name , name ))
10821082 callGenerator = CGMethodCall (nativeName , True , self .descriptor ,
1083- self ._ctor )
1083+ self ._ctor , isConstructor = True )
10841084 return preamble + callGenerator .define ();
10851085
10861086class CGClassConstructHookHolder (CGGeneric ):
@@ -4031,6 +4031,93 @@ class MethodNotCreatorError(Exception):
40314031 def __init__ (self , typename ):
40324032 self .typename = typename
40334033
4034+ # A counter for making sure that when we're wrapping up things in
4035+ # nested sequences we don't use the same variable name to iterate over
4036+ # different sequences.
4037+ sequenceWrapLevel = 0
4038+
4039+ def wrapTypeIntoCurrentCompartment (type , value ):
4040+ """
4041+ Take the thing named by "value" and if it contains "any",
4042+ "object", or spidermonkey-interface types inside return a CGThing
4043+ that will wrap them into the current compartment.
4044+ """
4045+ if type .isAny ():
4046+ assert not type .nullable ()
4047+ return CGGeneric ("if (!JS_WrapValue(cx, &%s)) {\n "
4048+ " return false;\n "
4049+ "}" % value )
4050+
4051+ if type .isObject ():
4052+ if not type .nullable ():
4053+ value = "%s.Slot()" % value
4054+ else :
4055+ value = "&%s" % value
4056+ return CGGeneric ("if (!JS_WrapObject(cx, %s)) {\n "
4057+ " return false;\n "
4058+ "}" % value )
4059+
4060+ if type .isSpiderMonkeyInterface ():
4061+ raise TypeError ("Can't handle wrapping of spidermonkey interfaces in "
4062+ "constructor arguments yet" )
4063+
4064+ if type .isSequence ():
4065+ if type .nullable ():
4066+ type = type .inner
4067+ value = "%s.AsMutable().Value()" % value
4068+ global sequenceWrapLevel
4069+ index = "indexName%d" % sequenceWrapLevel
4070+ sequenceWrapLevel += 1
4071+ wrapElement = wrapTypeIntoCurrentCompartment (type .inner ,
4072+ "%s[%s]" % (value , index ))
4073+ sequenceWrapLevel -= 1
4074+ if not wrapElement :
4075+ return None
4076+ return CGWrapper (CGIndenter (wrapElement ),
4077+ pre = ("for (uint32_t %s = 0; %s < %s.Length(); ++%s) {\n " %
4078+ (index , index , value , index )),
4079+ post = "\n }" )
4080+
4081+ if type .isDictionary ():
4082+ assert not type .nullable ()
4083+ value = "%s.AsMutable()" % value
4084+ myDict = type .inner
4085+ memberWraps = []
4086+ while myDict :
4087+ for member in myDict .members :
4088+ memberWrap = wrapArgIntoCurrentCompartment (
4089+ member ,
4090+ "%s.%s" % (value , CGDictionary .makeMemberName (member .identifier .name )))
4091+ if memberWrap :
4092+ memberWraps .append (memberWrap )
4093+ myDict = myDict .parent
4094+ return CGList (memberWraps , "\n " ) if len (memberWraps ) != 0 else None
4095+
4096+ if type .isUnion ():
4097+ raise TypeError ("Can't handle wrapping of unions in constructor "
4098+ "arguments yet" )
4099+
4100+ if (type .isString () or type .isPrimitive () or type .isEnum () or
4101+ type .isGeckoInterface () or type .isCallback ()):
4102+ # All of these don't need wrapping
4103+ return None
4104+
4105+ raise TypeError ("Unknown type; we don't know how to wrap it in constructor "
4106+ "arguments: %s" % type )
4107+
4108+ def wrapArgIntoCurrentCompartment (arg , value ):
4109+ """
4110+ As wrapTypeIntoCurrentCompartment but handles things being optional
4111+ """
4112+ origValue = value
4113+ isOptional = arg .optional and not arg .defaultValue
4114+ if isOptional :
4115+ value = value + ".AsMutable().Value()"
4116+ wrap = wrapTypeIntoCurrentCompartment (arg .type , value )
4117+ if wrap and isOptional :
4118+ wrap = CGIfWrapper (wrap , "%s.WasPassed()" % origValue )
4119+ return wrap
4120+
40344121class CGPerSignatureCall (CGThing ):
40354122 """
40364123 This class handles the guts of generating code for a particular
@@ -4056,7 +4143,7 @@ class CGPerSignatureCall(CGThing):
40564143
40574144 def __init__ (self , returnType , arguments , nativeMethodName , static ,
40584145 descriptor , idlNode , argConversionStartsAt = 0 , getter = False ,
4059- setter = False ):
4146+ setter = False , isConstructor = False ):
40604147 assert idlNode .isMethod () == (not getter and not setter )
40614148 assert idlNode .isAttr () == (getter or setter )
40624149
@@ -4117,6 +4204,30 @@ def __init__(self, returnType, arguments, nativeMethodName, static,
41174204 lenientFloatCode = lenientFloatCode ) for
41184205 i in range (argConversionStartsAt , self .argCount )])
41194206
4207+ if isConstructor :
4208+ # If we're called via an xray, we need to enter the underlying
4209+ # object's compartment and then wrap up all of our arguments into
4210+ # that compartment as needed. This is all happening after we've
4211+ # already done the conversions from JS values to WebIDL (C++)
4212+ # values, so we only need to worry about cases where there are 'any'
4213+ # or 'object' types, or other things that we represent as actual
4214+ # JSAPI types, present. Effectively, we're emulating a
4215+ # CrossCompartmentWrapper, but working with the C++ types, not the
4216+ # original list of JS::Values.
4217+ cgThings .append (CGGeneric ("Maybe<JSAutoCompartment> ac;" ))
4218+ xraySteps = [
4219+ CGGeneric ("obj = js::CheckedUnwrap(obj);\n "
4220+ "if (!obj) {\n "
4221+ " return false;\n "
4222+ "}\n "
4223+ "ac.construct(cx, obj);" ) ]
4224+ xraySteps .extend (
4225+ wrapArgIntoCurrentCompartment (arg , argname )
4226+ for (arg , argname ) in self .getArguments ())
4227+ cgThings .append (
4228+ CGIfWrapper (CGList (xraySteps , "\n " ),
4229+ "xpc::WrapperFactory::IsXrayWrapper(obj)" ))
4230+
41204231 cgThings .append (CGCallGenerator (
41214232 self .getErrorReport () if self .isFallible () else None ,
41224233 self .getArguments (), argsPre , returnType ,
@@ -4221,7 +4332,8 @@ class CGMethodCall(CGThing):
42214332 A class to generate selection of a method signature from a set of
42224333 signatures and generation of a call to that signature.
42234334 """
4224- def __init__ (self , nativeMethodName , static , descriptor , method ):
4335+ def __init__ (self , nativeMethodName , static , descriptor , method ,
4336+ isConstructor = False ):
42254337 CGThing .__init__ (self )
42264338
42274339 methodName = '"%s.%s"' % (descriptor .interface .identifier .name , method .identifier .name )
@@ -4238,7 +4350,9 @@ def requiredArgCount(signature):
42384350 def getPerSignatureCall (signature , argConversionStartsAt = 0 ):
42394351 return CGPerSignatureCall (signature [0 ], signature [1 ],
42404352 nativeMethodName , static , descriptor ,
4241- method , argConversionStartsAt )
4353+ method ,
4354+ argConversionStartsAt = argConversionStartsAt ,
4355+ isConstructor = isConstructor )
42424356
42434357
42444358 signatures = method .signatures ()
@@ -7086,6 +7200,10 @@ def declare(self):
70867200 " NS_ENSURE_TRUE(cx, false);\n "
70877201 " return Init(cx, json.ref());\n "
70887202 " }\n " if not self .workers else "" ) +
7203+ " ${selfName}& AsMutable() const\n "
7204+ " {\n "
7205+ " return *const_cast<${selfName}*>(this);\n "
7206+ " }\n "
70897207 "\n " +
70907208 "\n " .join (memberDecls ) + "\n "
70917209 "private:\n "
0 commit comments