Skip to content

Commit

Permalink
#1301 Add InternalProxy attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
Jand42 committed Dec 19, 2022
1 parent b186ee2 commit b390239
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/compiler/WebSharper.Compiler.CSharp/ProjectReader.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1367,7 +1367,7 @@ let transformAssembly (comp : Compilation) (config: WsConfig) (rcomp: CSharpComp
// register all proxies for signature redirection
for TypeWithAnnotation(_, def, annot) in allTypes do
match annot.ProxyOf with
| Some p -> comp.AddProxy(def, p)
| Some p -> comp.AddProxy(def, p, annot.IsProxyInteral)
| _ -> ()

for TypeWithAnnotation(t, d, a) in allTypes do
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/WebSharper.Compiler.FSharp/ProjectReader.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1346,7 +1346,7 @@ let transformAssembly (logger: LoggerBase) (comp : Compilation) assemblyName (co
// register all proxies for signature redirection
for (def, annot) in classAnnotations.Values do
match annot.ProxyOf with
| Some p -> comp.AddProxy(def, p)
| Some p -> comp.AddProxy(def, p, annot.IsProxyInteral)
| _ -> ()

for t in topLevelTypes do
Expand Down
17 changes: 11 additions & 6 deletions src/compiler/WebSharper.Compiler/AttributeReader.fs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ module M = WebSharper.Core.Metadata
[<RequireQualifiedAccess>]
type private Attribute =
| Macro of TypeDefinition * option<obj>
| Proxy of TypeDefinition * TypeDefinition[]
| Proxy of TypeDefinition * TypeDefinition[] * bool
| Inline of option<string> * dollarVars: string[]
| Direct of string * dollarVars: string[]
| Pure
Expand Down Expand Up @@ -62,6 +62,7 @@ type TypeAnnotation =
{
ProxyOf : option<TypeDefinition>
ProxyExtends : list<TypeDefinition>
IsProxyInteral : bool
IsJavaScript : bool
IsJavaScriptExport : bool
IsForcedNotJavaScript : bool
Expand All @@ -81,6 +82,7 @@ type TypeAnnotation =
{
ProxyOf = None
ProxyExtends = []
IsProxyInteral = false
IsJavaScript = false
IsJavaScriptExport = false
IsForcedNotJavaScript = false
Expand Down Expand Up @@ -249,7 +251,7 @@ type AttributeReader<'A>() =
| Some (:? System.Array as a) ->
a |> Seq.cast<obj> |> Seq.map this.GetTypeDef |> Array.ofSeq
| _ -> [||]
A.Proxy (p, intfTypes)
A.Proxy (p, intfTypes, false)
| "InlineAttribute" ->
A.Inline (this.CtorArgOption(attr), this.DollarVars(attr))
| "DirectAttribute" ->
Expand Down Expand Up @@ -323,6 +325,7 @@ type AttributeReader<'A>() =
let mutable stub = false
let mutable proxy = None
let mutable proxyExt = []
let mutable proxyInt = false
let mutable prot = None
for a in attrs do
match this.GetAssemblyName a with
Expand All @@ -341,9 +344,10 @@ type AttributeReader<'A>() =
js <- Some true
jse <- true
| A.Stub -> stub <- true
| A.Proxy (t, i) ->
| A.Proxy (t, i, ip) ->
proxy <- Some t
proxyExt <- List.ofArray i
proxyInt <- ip
| A.Prototype p -> prot <- Some p
| A.OtherAttribute -> ()
| ar -> attrArr.Add ar
Expand Down Expand Up @@ -373,13 +377,14 @@ type AttributeReader<'A>() =
jse <- true
if parent.OptionalFields then
if not (attrArr.Contains(A.OptionalField)) then attrArr.Add A.OptionalField
attrArr |> Seq.distinct |> Seq.toArray, macros.ToArray(), name, proxy, proxyExt, isJavaScript, js = Some false, jsOpts, jse, prot, isStub, List.ofSeq reqs
attrArr |> Seq.distinct |> Seq.toArray, macros.ToArray(), name, proxy, proxyExt, proxyInt, isJavaScript, js = Some false, jsOpts, jse, prot, isStub, List.ofSeq reqs

member this.GetTypeAnnot (parent: TypeAnnotation, attrs: seq<'A>) =
let attrArr, macros, name, proxyOf, proxyExt, isJavaScript, isForcedNotJavaScript, _, isJavaScriptExport, prot, isStub, reqs = this.GetAttrs (parent, attrs)
let attrArr, macros, name, proxyOf, proxyExt, proxyInt, isJavaScript, isForcedNotJavaScript, _, isJavaScriptExport, prot, isStub, reqs = this.GetAttrs (parent, attrs)
{
ProxyOf = proxyOf
ProxyExtends = proxyExt
IsProxyInteral = proxyInt
IsJavaScript = isJavaScript
IsJavaScriptExport = isJavaScriptExport
IsForcedNotJavaScript = isForcedNotJavaScript
Expand All @@ -402,7 +407,7 @@ type AttributeReader<'A>() =
}

member this.GetMemberAnnot (parent: TypeAnnotation, attrs: seq<'A>) =
let attrArr, macros, name, _, _, isJavaScript, _, jsOptions, isJavaScriptExport, _, isStub, reqs = this.GetAttrs (parent, attrs)
let attrArr, macros, name, _, _, _, isJavaScript, _, jsOptions, isJavaScriptExport, _, isStub, reqs = this.GetAttrs (parent, attrs)
let isEp = attrArr |> Array.contains A.SPAEntryPoint
let isPure = attrArr |> Array.contains A.Pure
let warning = attrArr |> Array.tryPick (function A.Warn w -> Some w | _ -> None)
Expand Down
19 changes: 14 additions & 5 deletions src/compiler/WebSharper.Compiler/Compilation.fs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ type Compilation(meta: Info, ?hasGraph) =
let notResolvedInterfaces = Dictionary<TypeDefinition, NotResolvedInterface>()
let notResolvedClasses = Dictionary<TypeDefinition, NotResolvedClass>()
let proxies = Dictionary<TypeDefinition, TypeDefinition>()
let internalProxies = HashSet<TypeDefinition>()

let classes = MergedDictionary meta.Classes
let interfaces = MergedDictionary meta.Interfaces
Expand Down Expand Up @@ -384,19 +385,21 @@ type Compilation(meta: Info, ?hasGraph) =
member this.ToCurrentMetadata(?ignoreErrors) =
if errors.Count > 0 && not (ignoreErrors = Some true) then
failwith "This compilation has errors"
let withoutInternalProxies d =
d |> Dict.filter (fun t _ -> not (internalProxies.Contains(t)))
{
SiteletDefinition = this.SiteletDefinition
Dependencies = if hasGraph then graph.GetData() else GraphData.Empty
Interfaces = interfaces.Current
Interfaces = interfaces.Current |> withoutInternalProxies
Classes =
classes.Current |> Dict.map (fun c ->
classes.Current |> withoutInternalProxies |> Dict.map (fun c ->
match c.Methods with
| :? MergedDictionary<Method, CompiledMember * Optimizations * Expression> as m ->
{ c with Methods = m.Current }
| _ -> c
)
CustomTypes =
customTypes.Current |> Dict.filter (fun _ v -> v <> NotCustomType)
customTypes.Current |> withoutInternalProxies |> Dict.filter (fun _ v -> v <> NotCustomType)
MacroEntries = macroEntries.Current
Quotations = quotations.Current
ResourceHashes = Dictionary()
Expand All @@ -416,8 +419,14 @@ type Compilation(meta: Info, ?hasGraph) =
ExtraBundles = this.AllExtraBundles
}

member this.AddProxy(tProxy, tTarget) =
proxies.Add(tProxy, tTarget)
member this.AddProxy(tProxy, tTarget, isInternal) =
// if the proxy is for internal use only, drop it with a warning if a proxy for target type already exists
if isInternal && (classes.Original.ContainsKey tTarget || interfaces.Original.ContainsKey tTarget || customTypes.Original.ContainsKey tTarget) then
this.AddWarning (None, SourceWarning (sprintf "Proxy for internal proxy target type '%s' already exists, ignoring the internal proxy." tTarget.Value.FullName))
else
proxies.Add(tProxy, tTarget)
if isInternal then
internalProxies.Add(tTarget) |> ignore

member this.ResolveProxySignature (meth: Method) =
if proxies.Count = 0 then meth else
Expand Down
16 changes: 16 additions & 0 deletions src/compiler/WebSharper.Core/Attributes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,22 @@ type ProxyAttribute private () =
/// Constructs a new proxy link using a type directly and allows adding inherited interfaces.
new (proxiedType: Type, interfaces: Type[]) = ProxyAttribute()

/// Declares a type to be a proxy for another type, identified directly or
/// by using an assembly-qualified name.
/// Proxy exists only for use in current project.
[<Sealed; U(T.Class|||T.Interface|||T.Struct)>]
type InternalProxyAttribute private () =
inherit A()

/// Constructs a new proxy link using a type directly.
new (proxiedType: Type) = InternalProxyAttribute()

/// Constructs a new proxy link using an assembly-qualified name.
new (assemblyQualifiedName: string) = InternalProxyAttribute()

/// Constructs a new proxy link using a type directly and allows adding inherited interfaces.
new (proxiedType: Type, interfaces: Type[]) = InternalProxyAttribute()

/// Marks a server-side function to be invokable remotely from the client-side.
[<Sealed; U(T.Method)>]
type RemoteAttribute() =
Expand Down

0 comments on commit b390239

Please sign in to comment.