esupgrade 2025.3.0 → 2025.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,274 +1,291 @@
1
1
  import { describe, test } from "node:test"
2
- import assert from "node:assert"
2
+ import assert from "node:assert/strict"
3
3
  import { transform } from "../src/index.js"
4
4
 
5
- describe("index", () => {
6
- describe("transform function", () => {
7
- test("should return TransformResult with correct structure", () => {
8
- const input = `var x = 1;`
9
- const result = transform(input)
10
-
11
- assert.ok(result.hasOwnProperty("code"))
12
- assert.ok(result.hasOwnProperty("modified"))
13
- assert.ok(result.hasOwnProperty("changes"))
14
- assert.strictEqual(typeof result.code, "string")
15
- assert.strictEqual(typeof result.modified, "boolean")
16
- assert.ok(Array.isArray(result.changes))
17
- })
18
-
19
- test("should handle empty string", () => {
20
- const input = ``
21
- const result = transform(input)
22
-
23
- assert.strictEqual(result.modified, false)
24
- assert.strictEqual(result.changes.length, 0)
25
- assert.strictEqual(result.code, "")
26
- })
27
-
28
- test("should handle whitespace-only string", () => {
29
- const input = ` \n\n `
30
- const result = transform(input)
5
+ describe("transform", () => {
6
+ test("return TransformResult with correct structure", () => {
7
+ const result = transform(`var x = 1;`)
8
+ assert(result.hasOwnProperty("code"), "result has code property")
9
+ assert(result.hasOwnProperty("modified"), "result has modified property")
10
+ assert(result.hasOwnProperty("changes"), "result has changes property")
11
+ assert(typeof result.code === "string", "code is string")
12
+ assert(typeof result.modified === "boolean", "modified is boolean")
13
+ assert(Array.isArray(result.changes), "changes is array")
14
+ })
31
15
 
32
- assert.strictEqual(result.modified, false)
33
- assert.strictEqual(result.changes.length, 0)
34
- })
16
+ test("handle empty string", () => {
17
+ const result = transform(``)
18
+ assert(!result.modified, "modified is false for empty string")
19
+ assert(result.changes.length === 0, "changes length is 0")
20
+ assert(result.code === "", "code is empty")
21
+ })
35
22
 
36
- test("should handle comments only", () => {
37
- const input = `// This is a comment\n/* Another comment */`
38
- const result = transform(input)
23
+ test("handle whitespace-only string", () => {
24
+ const result = transform(` \n\n `)
25
+ assert(!result.modified, "modified is false for whitespace")
26
+ assert(result.changes.length === 0, "changes length is 0")
27
+ })
39
28
 
40
- assert.strictEqual(result.modified, false)
41
- assert.strictEqual(result.changes.length, 0)
42
- })
29
+ test("handle comments only", () => {
30
+ const result = transform(`// This is a comment\n/* Another comment */`)
31
+ assert(!result.modified, "modified is false for comments")
32
+ assert(result.changes.length === 0, "changes length is 0")
33
+ })
43
34
 
44
- test("should apply multiple transformations and track all changes", () => {
45
- const input = `
35
+ test("apply multiple transformations and track all changes", () => {
36
+ const result = transform(`
46
37
  var x = 1;
47
38
  var y = 'Hello ' + name;
48
39
  var obj = Object.assign({}, data);
49
- `
50
- const result = transform(input)
51
-
52
- assert.strictEqual(result.modified, true)
53
- assert.ok(result.changes.length > 0)
54
-
55
- // Should have changes from varToConst (which does track line numbers)
56
- const changeTypes = result.changes.map((c) => c.type)
57
- assert.ok(changeTypes.includes("varToConst"))
58
-
59
- // Verify the transformations happened even if not all are tracked
60
- assert.match(result.code, /const/)
61
- assert.match(result.code, /`Hello/)
62
- assert.match(result.code, /\.\.\.data/)
63
- })
40
+ `)
41
+ assert(result.modified, "modified is true")
42
+ assert(result.changes.length > 0, "changes length greater than 0")
43
+ const changeTypes = result.changes.map((c) => c.type)
44
+ assert(changeTypes.includes("varToConst"), "changes include varToConst")
45
+ assert.match(result.code, /const/, "code contains const")
46
+ assert.match(result.code, /`Hello/, "code contains template literal")
47
+ assert.match(result.code, /\.\.\.data/, "code contains spread")
48
+ })
64
49
 
65
- test("should aggregate changes from multiple transformers", () => {
66
- const input = `
50
+ test("aggregate changes from multiple transformers", () => {
51
+ const result = transform(
52
+ `
67
53
  var a = 1;
68
54
  var b = 'Hello ' + world;
69
55
  Array.from(items).forEach(item => console.log(item));
70
- `
71
- const result = transform(input, "widely-available")
72
-
73
- assert.strictEqual(result.modified, true)
74
-
75
- // Should track line numbers for all changes
76
- assert.ok(result.changes.every((c) => c.hasOwnProperty("line")))
77
- assert.ok(result.changes.every((c) => c.hasOwnProperty("type")))
78
- })
79
-
80
- test("should use widely-available transformers by default", () => {
81
- const input = `var x = 1;`
82
- const result = transform(input)
56
+ `,
57
+ "widely-available",
58
+ )
59
+ assert(result.modified, "modified is true")
60
+ assert(
61
+ result.changes.every((c) => c.hasOwnProperty("line")),
62
+ "all changes have line property",
63
+ )
64
+ assert(
65
+ result.changes.every((c) => c.hasOwnProperty("type")),
66
+ "all changes have type property",
67
+ )
68
+ })
83
69
 
84
- assert.strictEqual(result.modified, true)
85
- assert.strictEqual(result.changes[0].type, "varToConst")
86
- })
70
+ test("use widely-available transformers by default", () => {
71
+ const result = transform(`var x = 1;`)
72
+ assert(result.modified, "modified is true")
73
+ assert(result.changes[0].type === "varToConst", "first change type is varToConst")
74
+ })
87
75
 
88
- test("should include newly-available transformers when specified", () => {
89
- const input = `
76
+ test("include newly-available transformers when specified", () => {
77
+ const result = transform(
78
+ `
90
79
  var x = 1;
91
80
  const p = new Promise((resolve) => resolve(getData()));
92
- `
93
- const result = transform(input, "newly-available")
94
-
95
- assert.strictEqual(result.modified, true)
96
-
97
- const changeTypes = result.changes.map((c) => c.type)
98
- assert.ok(changeTypes.includes("varToConst"))
99
- assert.ok(changeTypes.includes("promiseTry"))
100
- })
81
+ `,
82
+ "newly-available",
83
+ )
84
+ assert(result.modified, "modified is true")
85
+ const changeTypes = result.changes.map((c) => c.type)
86
+ assert(changeTypes.includes("varToConst"), "changes include varToConst")
87
+ assert(changeTypes.includes("promiseTry"), "changes include promiseTry")
88
+ })
101
89
 
102
- test("should handle complex nested structures", () => {
103
- const input = `
90
+ test("handle complex nested structures", () => {
91
+ const result = transform(`
104
92
  function test() {
105
93
  var result = Object.assign({}, {
106
94
  message: 'Hello ' + name
107
95
  });
108
96
  return result;
109
97
  }
110
- `
111
- const result = transform(input)
112
-
113
- assert.strictEqual(result.modified, true)
114
- assert.match(result.code, /const result/)
115
- assert.match(result.code, /\.\.\./)
116
- assert.match(result.code, /`Hello/)
117
- })
98
+ `)
99
+ assert(result.modified, "modified is true")
100
+ assert.match(result.code, /const result/, "code contains const result")
101
+ assert.match(result.code, /\.\.\./, "code contains spread")
102
+ assert.match(result.code, /`Hello/, "code contains template literal")
103
+ })
118
104
 
119
- test("should handle JSX syntax", () => {
120
- const input = `
105
+ test("handle JSX syntax", () => {
106
+ const result = transform(`
121
107
  var Component = () => {
122
108
  var title = 'Hello ' + name;
123
109
  return <div>{title}</div>;
124
110
  };
125
- `
126
- const result = transform(input)
127
-
128
- assert.strictEqual(result.modified, true)
129
- assert.match(result.code, /const/)
130
- assert.match(result.code, /<div>/)
131
- })
111
+ `)
112
+ assert(result.modified, "modified is true")
113
+ assert.match(result.code, /const/, "code contains const")
114
+ assert.match(result.code, /<div>/, "code contains JSX")
115
+ })
132
116
 
133
- test("should handle TypeScript syntax", () => {
134
- const input = `
117
+ test("handle TypeScript syntax", () => {
118
+ const result = transform(`
135
119
  var x: number = 1;
136
120
  const greeting: string = 'Hello ' + name;
137
- `
138
- const result = transform(input)
121
+ `)
122
+ assert(result.modified, "modified is true")
123
+ assert.match(result.code, /const x: number/, "code contains const x: number")
124
+ assert.match(result.code, /`Hello/, "code contains template literal")
125
+ })
139
126
 
140
- assert.strictEqual(result.modified, true)
141
- assert.match(result.code, /const x: number/)
142
- assert.match(result.code, /`Hello/)
143
- })
127
+ test("preserve code formatting structure", () => {
128
+ const result = transform(`var x = 1;
129
+ var y = 2;`)
130
+ assert.match(result.code, /const x = 1/, "code contains const x = 1")
131
+ assert.match(result.code, /const y = 2/, "code contains const y = 2")
132
+ })
144
133
 
145
- test("should preserve code formatting structure", () => {
146
- const input = `var x = 1;
147
- var y = 2;`
148
- const result = transform(input)
134
+ test("handle very large code", () => {
135
+ const lines = []
136
+ for (let i = 0; i < 100; i++) {
137
+ lines.push(`var x${i} = ${i};`)
138
+ }
139
+ const result = transform(lines.join("\n"))
140
+ assert(result.modified, "modified is true")
141
+ assert(result.changes.length === 100, "changes length is 100")
142
+ assert.match(result.code, /const x0 = 0/, "code contains const x0 = 0")
143
+ assert.match(result.code, /const x99 = 99/, "code contains const x99 = 99")
144
+ })
149
145
 
150
- // Should maintain separation between statements
151
- assert.match(result.code, /const x = 1/)
152
- assert.match(result.code, /const y = 2/)
153
- })
146
+ test("handle code with special characters", () => {
147
+ const result = transform(`var msg = 'Hello \\n' + 'World\\t!';`)
148
+ assert(result.modified, "modified is true")
149
+ assert.match(result.code, /const msg/, "code contains const msg")
150
+ assert.match(result.code, /`Hello/, "code contains template literal")
151
+ })
154
152
 
155
- test("should handle very large code", () => {
156
- // Generate a large input with many var declarations
157
- const lines = []
158
- for (let i = 0; i < 100; i++) {
159
- lines.push(`var x${i} = ${i};`)
160
- }
161
- const input = lines.join("\n")
153
+ test("handle code with unicode characters", () => {
154
+ const result = transform(`var msg = 'Hello ' + '世界' + '!';`)
155
+ assert(result.modified, "modified is true")
156
+ assert.match(result.code, /const msg/, "code contains const msg")
157
+ })
162
158
 
163
- const result = transform(input)
159
+ test("handle all transformers returning no changes", () => {
160
+ const result = transform(`const x = 1; const y = 2;`)
161
+ assert(!result.modified, "modified is false")
162
+ assert(result.changes.length === 0, "changes length is 0")
163
+ })
164
164
 
165
- assert.strictEqual(result.modified, true)
166
- assert.strictEqual(result.changes.length, 100)
167
- assert.match(result.code, /const x0 = 0/)
168
- assert.match(result.code, /const x99 = 99/)
169
- })
165
+ test("handle baseline parameter case sensitivity", () => {
166
+ const result1 = transform(`var x = 1;`, "widely-available")
167
+ assert(result1.modified, "modified is true for widely-available")
168
+ const result2 = transform(`var x = 1;`, "newly-available")
169
+ assert(result2.modified, "modified is true for newly-available")
170
+ })
170
171
 
171
- test("should handle code with special characters", () => {
172
- const input = `var msg = 'Hello \\n' + 'World\\t!';`
173
- const result = transform(input)
172
+ test("merge transformers correctly for newly-available", () => {
173
+ const result = transform(
174
+ `
175
+ var x = 1;
176
+ var obj = Object.assign({}, data);
177
+ const p = new Promise((resolve) => resolve(getData()));
178
+ `,
179
+ "newly-available",
180
+ )
181
+ assert(result.modified, "modified is true")
182
+ const changeTypes = result.changes.map((c) => c.type)
183
+ assert(changeTypes.includes("varToConst"), "changes include varToConst")
184
+ assert(changeTypes.includes("promiseTry"), "changes include promiseTry")
185
+ assert.match(result.code, /const/, "code contains const")
186
+ assert.match(result.code, /\.\.\.data/, "code contains spread")
187
+ assert.match(result.code, /Promise\.try/, "code contains Promise.try")
188
+ })
174
189
 
175
- assert.strictEqual(result.modified, true)
176
- assert.match(result.code, /const msg/)
177
- // Template literals preserve the escape sequences
178
- assert.match(result.code, /`Hello/)
179
- })
190
+ test("handle code without location info gracefully", () => {
191
+ const result = transform(`var x = 1;`)
192
+ assert(result.modified, "modified is true")
193
+ })
180
194
 
181
- test("should handle code with unicode characters", () => {
182
- const input = `var msg = 'Hello ' + '世界' + '!';`
183
- const result = transform(input)
195
+ test("generate valid JavaScript output", () => {
196
+ const result = transform(`
197
+ var x = 1;
198
+ var greeting = 'Hello ' + name;
199
+ Array.from(items).forEach(item => console.log(item));
200
+ `)
201
+ assert.doesNotThrow(() => {
202
+ new Function(result.code)
203
+ }, "code is valid JavaScript")
204
+ })
184
205
 
185
- assert.strictEqual(result.modified, true)
186
- assert.match(result.code, /const msg/)
187
- })
206
+ test("handle single-line code", () => {
207
+ const result = transform(`var x = 1; var y = 2; var z = 3;`)
208
+ assert(result.modified, "modified is true")
209
+ assert.match(result.code, /const x = 1/, "code contains const x = 1")
210
+ assert.match(result.code, /const y = 2/, "code contains const y = 2")
211
+ assert.match(result.code, /const z = 3/, "code contains const z = 3")
212
+ })
188
213
 
189
- test("should handle all transformers returning no changes", () => {
190
- const input = `const x = 1; const y = 2;`
191
- const result = transform(input)
214
+ test("handle code with existing template literals", () => {
215
+ const result = transform(`
216
+ var msg = \`Hello \${name}\`;
217
+ var other = 'Test ' + value;
218
+ `)
219
+ assert(result.modified, "modified is true")
220
+ assert.match(result.code, /const msg/, "code contains const msg")
221
+ assert.match(result.code, /const other/, "code contains const other")
222
+ })
223
+ })
192
224
 
193
- assert.strictEqual(result.modified, false)
194
- assert.strictEqual(result.changes.length, 0)
225
+ describe("transformers", () => {
226
+ describe("varToConst", () => {
227
+ test("transform var to const", () => {
228
+ assert(transform(`var x = 1;`).modified)
229
+ assert.match(transform(`var x = 1;`).code, /const/)
195
230
  })
196
231
 
197
- test("should handle baseline parameter case sensitivity", () => {
198
- const input = `var x = 1;`
199
-
200
- // Should accept exact strings
201
- const result1 = transform(input, "widely-available")
202
- assert.strictEqual(result1.modified, true)
203
-
204
- const result2 = transform(input, "newly-available")
205
- assert.strictEqual(result2.modified, true)
232
+ test("transform multiple vars to consts", () => {
233
+ const result = transform(`var x = 1; var y = 2;`)
234
+ assert(result.modified)
235
+ assert.match(result.code, /const x = 1/)
236
+ assert.match(result.code, /const y = 2/)
206
237
  })
238
+ })
207
239
 
208
- test("should merge transformers correctly for newly-available", () => {
209
- const input = `
210
- var x = 1;
211
- var obj = Object.assign({}, data);
212
- const p = new Promise((resolve) => resolve(getData()));
213
- `
214
- const result = transform(input, "newly-available")
215
-
216
- assert.strictEqual(result.modified, true)
217
-
218
- // Should have changes from transformers that track line numbers
219
- const changeTypes = result.changes.map((c) => c.type)
220
- assert.ok(changeTypes.includes("varToConst")) // from widely-available
221
- assert.ok(changeTypes.includes("promiseTry")) // from newly-available
222
-
223
- // Verify all transformations happened
224
- assert.match(result.code, /const/)
225
- assert.match(result.code, /\.\.\.data/)
226
- assert.match(result.code, /Promise\.try/)
240
+ describe("stringConcatToTemplate", () => {
241
+ test("transform string concat to template literal", () => {
242
+ const result = transform(`var msg = 'Hello ' + name;`)
243
+ assert(result.modified)
244
+ assert.match(result.code, /const msg/)
245
+ assert.match(result.code, /`Hello/)
227
246
  })
228
247
 
229
- test("should handle code without location info gracefully", () => {
230
- // Even if some transformations don't have location info, should still work
231
- const input = `var x = 1;`
232
- const result = transform(input)
233
-
234
- assert.strictEqual(result.modified, true)
235
- // Should handle missing loc info gracefully
248
+ test("transform complex concat to template", () => {
249
+ const result = transform(`var greeting = 'Hello ' + name + '!';`)
250
+ assert(result.modified)
251
+ assert.match(result.code, /const greeting/)
252
+ assert.match(result.code, /`Hello/)
236
253
  })
254
+ })
237
255
 
238
- test("should generate valid JavaScript output", () => {
239
- const input = `
240
- var x = 1;
241
- var greeting = 'Hello ' + name;
242
- Array.from(items).forEach(item => console.log(item));
243
- `
244
- const result = transform(input)
245
-
246
- // Try to parse the output to ensure it's valid JS
247
- assert.doesNotThrow(() => {
248
- new Function(result.code)
249
- })
256
+ describe("objectAssignToSpread", () => {
257
+ test("transform Object.assign to spread", () => {
258
+ const result = transform(`var obj = Object.assign({}, data);`)
259
+ assert(result.modified)
260
+ assert.match(result.code, /const obj/)
261
+ assert.match(result.code, /\.\.\.data/)
250
262
  })
251
263
 
252
- test("should handle single-line code", () => {
253
- const input = `var x = 1; var y = 2; var z = 3;`
254
- const result = transform(input)
255
-
256
- assert.strictEqual(result.modified, true)
257
- assert.match(result.code, /const x = 1/)
258
- assert.match(result.code, /const y = 2/)
259
- assert.match(result.code, /const z = 3/)
264
+ test("transform nested Object.assign", () => {
265
+ const result = transform(`var result = Object.assign({}, { message: 'test' });`)
266
+ assert(result.modified)
267
+ assert.match(result.code, /const result/)
268
+ assert.match(result.code, /\.\.\./)
260
269
  })
270
+ })
261
271
 
262
- test("should handle code with existing template literals", () => {
263
- const input = `
264
- var msg = \`Hello \${name}\`;
265
- var other = 'Test ' + value;
266
- `
267
- const result = transform(input)
272
+ describe("promiseTry", () => {
273
+ test("transform Promise constructor to Promise.try", () => {
274
+ const result = transform(
275
+ `const p = new Promise((resolve) => resolve(getData()));`,
276
+ "newly-available",
277
+ )
278
+ assert(result.modified)
279
+ assert.match(result.code, /Promise\.try/)
280
+ })
268
281
 
269
- assert.strictEqual(result.modified, true)
270
- assert.match(result.code, /const msg/)
271
- assert.match(result.code, /const other/)
282
+ test("transform Promise with resolve", () => {
283
+ const result = transform(
284
+ `const p = new Promise((resolve) => resolve(data));`,
285
+ "newly-available",
286
+ )
287
+ assert(result.modified)
288
+ assert.match(result.code, /Promise\.try/)
272
289
  })
273
290
  })
274
291
  })