1 package minify 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 8 "vimagination.zapto.org/javascript" 9 "vimagination.zapto.org/javascript/scope" 10 "vimagination.zapto.org/parser" 11 ) 12 13 func TestOrderedScope(t *testing.T) { 14 for n, test := range [...]struct { 15 Input string 16 Bindings []string 17 }{ 18 { // 1 19 "", 20 []string{}, 21 }, 22 { // 2 23 "let a = 1", 24 []string{ 25 "a", 26 }, 27 }, 28 { // 3 29 "let a = 1, b = 2;a", 30 []string{ 31 "a", 32 "b", 33 }, 34 }, 35 { // 4 36 "let a = 1, b = 2;b", 37 []string{ 38 "b", 39 "a", 40 }, 41 }, 42 { // 5 43 "function b() { a()} function c() {b()} function a(){} b()", 44 []string{ 45 "b", 46 "a", 47 "c", 48 }, 49 }, 50 { // 6 51 "window", 52 []string{}, 53 }, 54 { // 7 55 "console.log(1);function a() {console.log(2)}", 56 []string{"a"}, 57 }, 58 } { 59 tk := parser.NewStringTokeniser(test.Input) 60 m, err := javascript.ParseModule(&tk) 61 if err != nil { 62 t.Errorf("test %d: unexpected error: %s", n+1, err) 63 } else if s, err := scope.ModuleScope(m, nil); err != nil { 64 t.Errorf("test %d: unexpected error: %s", n+1, err) 65 } else { 66 bs := orderedScope(s) 67 bindings := make([]string, 0, len(bs)) 68 for _, b := range bs { 69 if !b.NameSet { 70 bindings = append(bindings, b.Name) 71 } 72 } 73 if !reflect.DeepEqual(bindings, test.Bindings) { 74 t.Errorf("test %d: expecting bindings: %v, got %v", n+1, test.Bindings, bindings) 75 } 76 } 77 } 78 } 79 80 func init() { 81 startChars = []byte{'_', '$'} 82 extraChars = []byte{'a', 'b'} 83 } 84 85 func TestUniqueName(t *testing.T) { 86 used := make(map[string]struct{}) 87 for n, next := range []string{"_", "$", "_a", "_b", "$a", "$b", "_aa"} { 88 if name := makeUniqueName(used); name != next { 89 t.Errorf("test %d: expecting name %s, got %s", n+1, next, name) 90 } 91 used[next] = struct{}{} 92 } 93 } 94 95 func TestRename(t *testing.T) { 96 for n, test := range [...]struct { 97 Input, Output string 98 }{ 99 { // 1 100 }, 101 { // 2 102 "let value = 1;", 103 "let _ = 1;", 104 }, 105 { // 3 106 "let value = 1, anotherValue = 2;", 107 "let $ = 1, _ = 2;", 108 }, 109 { // 4 110 "const bValue = 1;function aFunction(aValue, bValue) {aValue}", 111 "const $ = 1;\n\nfunction _(_, $) {\n _;\n}", 112 }, 113 { // 5 114 "const aValue = 1;aValue;aValue;function aFunction(aValue, bValue){aValue}", 115 "const _ = 1;\n\n_;\n\n_;\n\nfunction $(_, $) {\n _;\n}", 116 }, 117 { // 6 118 "const aValue = 1;{const aValue = 2;{const aValue = 3}}", 119 "const _ = 1;\n\n{\n const _ = 2;\n {\n const _ = 3;\n }\n}", 120 }, 121 { // 7 122 "let aValue = 1;{let bValue = 2;{aValue = 3}}", 123 "let _ = 1;\n\n{\n let $ = 2;\n {\n _ = 3;\n }\n}", 124 }, 125 { // 8 126 "function aFunction(){}", 127 "function _() {}", 128 }, 129 { // 9 130 "class aClass {}", 131 "class _ {}", 132 }, 133 { // 9 134 "class aClass {}\nclass bClass extends aClass {}", 135 "class _ {}\n\nclass $ extends _ {}", 136 }, 137 } { 138 tk := parser.NewStringTokeniser(test.Input) 139 m, err := javascript.ParseModule(&tk) 140 if err != nil { 141 t.Errorf("test %d: unexpected error: %s", n+1, err) 142 } else if err = renameIdentifiers(m); err != nil { 143 t.Errorf("test %d: unexpected error: %s", n+1, err) 144 } else if str := fmt.Sprintf("%s", m); str != test.Output { 145 t.Errorf("test %d: expecting output:\n%s\n, got:\n%s", n+1, test.Output, str) 146 } 147 } 148 } 149