From a1a2edd67e359f5d14ee5f230e63342c010bfefc Mon Sep 17 00:00:00 2001 From: Alfonso Garcia-Caro Date: Fri, 4 May 2018 23:46:40 +0200 Subject: [PATCH] Fix #1397: import modules beginning with a number --- src/dotnet/Fable.Core/Util.fs | 30 ++++++++++++++++++++++-------- tests/Main/ImportTests.fs | 12 ++++++------ tests/Main/Util/Util.fs | 6 +++--- tests/Main/js/{foo.js => 1foo.js} | 0 tests_external/Util4.fs | 2 +- 5 files changed, 32 insertions(+), 18 deletions(-) rename tests/Main/js/{foo.js => 1foo.js} (100%) diff --git a/src/dotnet/Fable.Core/Util.fs b/src/dotnet/Fable.Core/Util.fs index 34dddbb9ae..9a927e1e5d 100644 --- a/src/dotnet/Fable.Core/Util.fs +++ b/src/dotnet/Fable.Core/Util.fs @@ -103,27 +103,41 @@ module Naming = let umdModules = set ["commonjs"; "amd"; "umd"] - let isIdentChar c = System.Char.IsLetterOrDigit (c) || c = '_' + // Dollar sign is reserved by Fable as a special character + // to encode other characters, unique var names and as a separator + let isIdentChar i (c: char) = + let code = int c + c = '_' + || (65 <= code && code <= 90) // a-z + || (97 <= code && code <= 122) // A-Z + // Digits are not allowed in first position, see #1397 + || (i > 0 && 48 <= code && code <= 57) // 0-9 let hasIdentForbiddenChars (ident: string) = let mutable i = 0 - while i < ident.Length && (isIdentChar ident.[i]) do i <- i + 1 + while i < ident.Length && (isIdentChar i ident.[i]) do i <- i + 1 i < ident.Length let replaceIdentForbiddenChars (ident: string) = System.String.Concat(seq { - for c in ident -> - if isIdentChar c then string c - else sprintf "$%X$" (int c) + for i = 0 to (ident.Length - 1) do + let c = ident.[i] + if isIdentChar i c + then yield string c + else yield sprintf "$%X$" (int c) }) let sanitizeIdentForbiddenChars (ident: string) = System.String( - [| for c in ident -> if isIdentChar c then c else '_' |] ) + [| for i = 0 to (ident.Length - 1) do + let c = ident.[i] + if isIdentChar i c + then yield c else + yield '_' |] ) let hasGenericPlaceholder (ident: string) = let i = ident.IndexOf(@"\$'") - i >= 0 && i + 2 < ident.Length && (isIdentChar ident.[i + 2]) + i >= 0 && i + 2 < ident.Length && (isIdentChar (i + 2) ident.[i + 2]) let replacePattern (prefix: string) (cond: char->bool) (repl: string->string) (str: string) = let rec replace (acc: string) (s: string) = @@ -138,7 +152,7 @@ module Naming = replace "" str let replaceGenericPlaceholder (ident: string, onMatch: string -> string) = - replacePattern @"\$'" isIdentChar onMatch ident + replacePattern @"\$'" (isIdentChar 1) onMatch ident let replaceGenericArgsCount (ident: string, replacement: string) = replacePattern @"`" System.Char.IsDigit (fun _ -> replacement) ident diff --git a/tests/Main/ImportTests.fs b/tests/Main/ImportTests.fs index 2bb5c03e57..9d1b64f9e0 100644 --- a/tests/Main/ImportTests.fs +++ b/tests/Main/ImportTests.fs @@ -10,13 +10,13 @@ type IFooImported = abstract foo: string #if FABLE_COMPILER -[] +[] let fooAll: IFooImported = failwith "JS only" [] let ``Import with relative paths works``() = fooAll.foo |> equal "foo" - let fooAll2: IFooImported = Fable.Core.JsInterop.importAll "./js/foo.js" + let fooAll2: IFooImported = Fable.Core.JsInterop.importAll "./js/1foo.js" fooAll2.foo |> equal "foo" [] @@ -99,7 +99,7 @@ let ``Identifiers are encoded correctly``() = // See #482 #if FABLE_COMPILER open Fable.Core -[] +[] type MyClass() = new (v: string) = MyClass() member x.value: string = jsNative @@ -130,7 +130,7 @@ type FooOptional = [] let ``Only omitted optional arguments are removed``() = // See #231, #640 - let x: FooOptional = Fable.Core.JsInterop.import "fooOptional" "./js/foo.js" + let x: FooOptional = Fable.Core.JsInterop.import "fooOptional" "./js/1foo.js" x.Foo1(5) |> equal 1 x.Foo1(5, "3") |> equal 2 x.Foo2(5, None) |> equal 2 @@ -139,12 +139,12 @@ let ``Only omitted optional arguments are removed``() = // See #231, #640 x.Foo2(5,Some "3") |> equal 2 x.Foo3(5, "3") |> equal 2 -let square : int -> int = JsInterop.importMember "./js/foo.js" +let square : int -> int = JsInterop.importMember "./js/1foo.js" [] let ``Importing curried functions via `importMember` without naming arguments works`` () = // See #1185 square 2 |> equal 4 -let add : int -> int -> int = JsInterop.importMember "./js/foo.js" +let add : int -> int -> int = JsInterop.importMember "./js/1foo.js" [] let ``Importing curried functions with multiple arguments via `importMember` without naming arguments works`` () = add 40 2 |> equal 42 diff --git a/tests/Main/Util/Util.fs b/tests/Main/Util/Util.fs index 9e01a20e17..8f8b9c09b2 100644 --- a/tests/Main/Util/Util.fs +++ b/tests/Main/Util/Util.fs @@ -16,12 +16,12 @@ module Testing = open Testing #if FABLE_COMPILER -let foo: string = Fable.Core.JsInterop.importMember "../js/foo.js" +let foo: string = Fable.Core.JsInterop.importMember "../js/1foo.js" -[] +[] let foo2: string = failwith "JS only" -let apply (f:Func) (x:int) (y:int) = Fable.Core.JsInterop.importMember "../js/foo.js" +let apply (f:Func) (x:int) (y:int) = Fable.Core.JsInterop.importMember "../js/1foo.js" #else let foo = "foo" let foo2 = "foo" diff --git a/tests/Main/js/foo.js b/tests/Main/js/1foo.js similarity index 100% rename from tests/Main/js/foo.js rename to tests/Main/js/1foo.js diff --git a/tests_external/Util4.fs b/tests_external/Util4.fs index 3758cf689a..4af1b27028 100644 --- a/tests_external/Util4.fs +++ b/tests_external/Util4.fs @@ -3,7 +3,7 @@ module Fable.Tests.Util4 open Fable.Core #if FABLE_COMPILER -let foo: string = JsInterop.importMember "../tests/Main/js/foo.js" +let foo: string = JsInterop.importMember "../tests/Main/js/1foo.js" let bar: int = JsInterop.importMember "./bar.js"