diff --git a/components/script_bindings/codegen/codegen.py b/components/script_bindings/codegen/codegen.py index 39a8fe0c75a..d6840f79278 100644 --- a/components/script_bindings/codegen/codegen.py +++ b/components/script_bindings/codegen/codegen.py @@ -15,6 +15,7 @@ from itertools import groupby from typing import cast, Optional, Any, Generic, TypeVar, TypeGuard from collections.abc import Generator, Callable, Iterator, Iterable from abc import abstractmethod +from enum import IntEnum import operator import os @@ -1498,9 +1499,16 @@ def wrapForType(jsvalRef: str, result: str = 'result', successCode: str = 'true' return wrap -def typeNeedsCx(type: IDLType | None, retVal: bool = False) -> bool: +class Context(IntEnum): + No = 0 + OldCx = 1 + Cx = 2 + CurrentRealm = 3 + + +def typeNeedsCx(type: IDLType | None, retVal: bool = False) -> Context: if type is None: - return False + return Context.No if type.nullable(): assert isinstance(type, IDLNullableType) type = type.inner @@ -1512,10 +1520,10 @@ def typeNeedsCx(type: IDLType | None, retVal: bool = False) -> bool: flatMemberTypes = type.unroll().flatMemberTypes assert flatMemberTypes is not None - return any(typeNeedsCx(t) for t in flatMemberTypes) + return max(typeNeedsCx(t) for t in flatMemberTypes) if retVal and type.isSpiderMonkeyInterface(): - return True - return type.isAny() or type.isObject() + return Context.OldCx + return Context.OldCx if type.isAny() or type.isObject() else Context.No def returnTypeNeedsOutparam(type: IDLType | None) -> bool: @@ -4114,10 +4122,8 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod): ) -def needCx(returnType: IDLType | None, arguments: Iterable[IDLArgument | FakeArgument], considerTypes: bool) -> bool: - return (considerTypes - and (typeNeedsCx(returnType, True) - or any(typeNeedsCx(a.type) for a in arguments))) +def needCx(returnType: IDLType | None, arguments: Iterable[IDLArgument | FakeArgument], considerTypes: bool) -> Context: + return max([typeNeedsCx(a.type) for a in arguments] + [typeNeedsCx(returnType, True)]) if considerTypes else Context.No class CGCallGenerator(CGThing): @@ -4163,7 +4169,16 @@ class CGCallGenerator(CGThing): name = f"&{name}" args.append(CGGeneric(name)) - needsCx = needCx(returnType, (a for (a, _) in arguments), True) + needsCx = False + match needCx(returnType, (a for (a, _) in arguments), True): + case Context.Cx: + descriptor.cxMethods.append(nativeMethodName) + case Context.CurrentRealm: + descriptor.realmMethods.append(nativeMethodName) + case Context.OldCx: + needsCx = True + case Context.No: + pass # Build up our actual call self.cgRoot = CGList([], "\n") @@ -8328,6 +8343,16 @@ def method_arguments(descriptorProvider: DescriptorProvider, inRealm: bool = False, canGc: bool = False ) -> Iterator[tuple[str, str]]: + old_cx = False + match needCx(returnType, arguments, passJSBits): + case Context.Cx: + cx = True + case Context.CurrentRealm: + realm = True + case Context.OldCx: + old_cx = True + case Context.No: + pass if cx_no_gc: yield "cx", "&JSContext" elif cx: @@ -8337,7 +8362,7 @@ def method_arguments(descriptorProvider: DescriptorProvider, safe_cx = cx or cx_no_gc or realm - if needCx(returnType, arguments, passJSBits) and not safe_cx: + if old_cx and not safe_cx: yield "cx", "SafeJSContext" for argument in arguments: