Skip to content

Commit

Permalink
[JS/TS] Don't generate the setter code if a property is decorated wit…
Browse files Browse the repository at this point in the history
…h `[<Erase>]` (#3997)

Fix #3948
  • Loading branch information
MangelMaxime authored Jan 3, 2025
1 parent b4eb58f commit e98cf5e
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 1 deletion.
1 change: 1 addition & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* [TS] Make discriminated union `.Is*` properties works (@MangelMaxime)
* [JS/TS/Python] Fix `h` in `DateTime.ToString` (@MangelMaxime)
* [JS/TS] Fix `hh` in `DateTime.ToString` (@MangelMaxime)
* [JS/TS] Don't generate the setter code if a property is decorated with `[<Erase>]` (@MangelMaxime)

## 5.0.0-alpha.3 - 2024-12-18

Expand Down
22 changes: 21 additions & 1 deletion src/Fable.Transforms/FSharp2Fable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1899,6 +1899,22 @@ let private transformMemberDecl
UsedNamesInDeclarationScope = HashSet()
}

let isErasedPropertySetter (memb: FSharpMemberOrFunctionOrValue) =
if memb.IsPropertySetterMethod then
match memb.DeclaringEntity with
| Some ent ->
// Remove the "set_" prefix
let logicalName = memb.LogicalName.Substring(4)

ent.MembersFunctionsAndValues
|> Seq.tryFind (fun (m: FSharpMemberOrFunctionOrValue) ->
m.LogicalName = logicalName && hasAttrib Atts.erase m.Attributes
)
|> Option.isSome
| _ -> false
else
false

if isIgnoredNonAttachedMember memb then
if memb.IsMutable && isNotPrivate memb && hasAttrib Atts.global_ memb.Attributes then
"Global members cannot be mutable and public, please make it private: "
Expand All @@ -1921,7 +1937,11 @@ let private transformMemberDecl
elif isCompilerGenerated memb args then
[]
// Ignore members that are decorated with [<Erase>]
elif hasAttrib Atts.erase memb.Attributes then
elif
hasAttrib Atts.erase memb.Attributes || isErasedPropertySetter memb
// Attributes are not universally propagated so for setter properties we need
// to check the declaring entity, https://github.com/fable-compiler/Fable/issues/3948
then
[]
elif memb.IsOverrideOrExplicitInterfaceImplementation then
if not memb.IsCompilerGenerated then
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module ErasedProperty

open Fable.Core


// This test is to make sure that we are retrieving the Erase attribute from the erased property
// and not the declaring type

type internal LanguageInjectionAttribute() =

[<Erase>]
member val Prefix = "" with get, set
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { class_type } from "./fable_modules/fable-library-js.5.0.0-alpha.3/Reflection.js";

export class LanguageInjectionAttribute {
constructor() {
this["Prefix@"] = "";
}
}

export function LanguageInjectionAttribute_$reflection() {
return class_type("ErasedProperty.LanguageInjectionAttribute", undefined, LanguageInjectionAttribute);
}

export function LanguageInjectionAttribute_$ctor() {
return new LanguageInjectionAttribute();
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module ErasedTypeWithProperty

open Fable.Core

[<Erase>]
type internal LanguageInjectionAttribute() =

[<Erase>]
member val Prefix = "" with get, set

// Force Fable to generate a file, otherwise because everything is erased, it will not generate anything
let a = 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

export const a = 0;

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

<ItemGroup>
<Compile Include="Members.fs" />
<Compile Include="ErasedTypeWithProperty.fs" />
<Compile Include="ErasedProperty.fs" />
</ItemGroup>

<ItemGroup>
Expand Down

0 comments on commit e98cf5e

Please sign in to comment.