0
# Unsafe Transforms
1
2
Unsafe transforms should be applied with caution. They either use heuristics which can't guarantee equivalent code, or they have significant bugs which can break your code.
3
4
## Capabilities
5
6
### Let/Const Variables
7
8
Converts `var` to `let`/`const` based on usage patterns.
9
10
```javascript { .api }
11
// Transform name: "let"
12
```
13
14
**What it transforms:**
15
16
- Never-modified variables to `const`
17
- Block-scoped variables to `let`
18
- Properly recognizes block-scoping rules
19
- Splits single var declarations to multiple let/const if needed
20
- Recognizes destructuring assignments
21
22
**Limitations and Bugs:**
23
24
- BUG: Fails with repeated variable definitions that use destructuring
25
- BUG: Fails with closure over a loop variable
26
- BUG: Fails when function closes over variable declared after function is called
27
- Variables that conflict with block-scoping are not converted
28
- Repeated declarations of the same var are not converted
29
30
**Usage Example:**
31
32
```javascript
33
// Before
34
var name = 'John'; // Never modified
35
var age = 25; // Modified later
36
age = 26;
37
var items = [1, 2, 3]; // Never modified
38
39
// After
40
const name = 'John'; // Converted to const
41
let age = 25; // Converted to let
42
age = 26;
43
const items = [1, 2, 3]; // Converted to const
44
```
45
46
### ES6 Classes
47
48
Converts function constructors and prototypes to ES6 classes.
49
50
```javascript { .api }
51
// Transform name: "class"
52
```
53
54
**What it transforms:**
55
56
- `Foo.prototype.method = function(){}` to class methods
57
- `Foo.prototype = { ...methods... }` to class body
58
- Static methods like `Foo.method = function(){}`
59
- Getters/setters defined with `Object.defineProperty()`
60
- Inheritance with `Child.prototype = new Parent()`
61
- Inheritance with `util.inherits(Child, Parent)`
62
- Superclass constructor calls to `super()`
63
- Superclass method calls to `super.method()`
64
65
**Limitations:**
66
67
- Does not require `super()` call in subclass constructor
68
- Does not enforce `super()` call position in subclass constructor
69
- Does not support namespaced classes
70
71
**Usage Example:**
72
73
```javascript
74
// Before
75
function Person(name) {
76
this.name = name;
77
}
78
79
Person.prototype.greet = function() {
80
return 'Hello, ' + this.name;
81
};
82
83
Person.prototype.getName = function() {
84
return this.name;
85
};
86
87
// After
88
class Person {
89
constructor(name) {
90
this.name = name;
91
}
92
93
greet() {
94
return 'Hello, ' + this.name;
95
}
96
97
getName() {
98
return this.name;
99
}
100
}
101
```
102
103
### ES6 Modules
104
105
Converts CommonJS modules to ES6 import/export syntax.
106
107
```javascript { .api }
108
// Transform name: "commonjs"
109
```
110
111
**What it transforms:**
112
113
- `var foo = require("foo")` to `import foo from "foo"`
114
- `var bar = require("foo").bar` to `import {bar} from "foo"`
115
- `var {bar} = require("foo")` to `import {bar} from "foo"`
116
- `module.exports = <anything>` to `export default <anything>`
117
- `exports.foo = function(){}` to `export function foo(){}`
118
- `exports.Foo = class {}` to `export class Foo {}`
119
- `exports.foo = 123` to `export var foo = 123`
120
- `exports.foo = bar` to `export {bar as foo}`
121
122
**Limitations:**
123
124
- Does not check if named export conflicts with existing variable names
125
- Ignores imports/exports inside nested blocks/functions
126
- Only handles `require()` calls in `var` declarations
127
- Does not ensure that imported variable is treated as `const`
128
- Does not ensure named exports are imported with correct ES6 syntax
129
130
**Usage Example:**
131
132
```javascript
133
// Before
134
var fs = require('fs');
135
var {readFile} = require('fs');
136
var express = require('express');
137
138
exports.readData = function() {
139
return fs.readFileSync('data.txt');
140
};
141
142
module.exports = {
143
version: '1.0.0'
144
};
145
146
// After
147
import fs from 'fs';
148
import {readFile} from 'fs';
149
import express from 'express';
150
151
export function readData() {
152
return fs.readFileSync('data.txt');
153
}
154
155
export default {
156
version: '1.0.0'
157
};
158
```
159
160
### Template Literals
161
162
Converts string concatenation to template literals.
163
164
```javascript { .api }
165
// Transform name: "template"
166
```
167
168
**What it transforms:**
169
170
- String concatenation using `+` to template literals
171
- Variables and expressions to `${...}` syntax
172
173
**Limitations and Bugs:**
174
175
- BUG: Removes indentation of multi-line strings
176
- LIMITATION: Ignores difference between `.toString()` and `.valueOf()`
177
178
**Usage Example:**
179
180
```javascript
181
// Before
182
var message = 'Hello ' + name + ', you have ' + count + ' messages';
183
var url = 'https://api.example.com/users/' + userId + '/profile';
184
185
// After
186
var message = `Hello ${name}, you have ${count} messages`;
187
var url = `https://api.example.com/users/${userId}/profile`;
188
```
189
190
### Default Parameters
191
192
Converts default parameter patterns to ES6 default parameters.
193
194
```javascript { .api }
195
// Transform name: "default-param"
196
```
197
198
**What it transforms:**
199
200
- `a = a || 2` patterns to default parameters
201
- `a = a ? a : 2` patterns to default parameters
202
- `a = typeof a !== 'undefined' ? a : 2` patterns
203
204
**Usage Example:**
205
206
```javascript
207
// Before
208
function greet(name, greeting) {
209
name = name || 'World';
210
greeting = greeting || 'Hello';
211
return greeting + ', ' + name + '!';
212
}
213
214
// After
215
function greet(name = 'World', greeting = 'Hello') {
216
return greeting + ', ' + name + '!';
217
}
218
```
219
220
### Destructuring Parameters
221
222
Converts parameter patterns to destructuring syntax.
223
224
```javascript { .api }
225
// Transform name: "destruct-param"
226
```
227
228
**What it transforms:**
229
230
- Functions that access object properties to destructuring parameters
231
- Parameter object property access patterns
232
233
**Usage Example:**
234
235
```javascript
236
// Before
237
function processUser(user) {
238
var name = user.name;
239
var age = user.age;
240
var email = user.email;
241
242
console.log(name, age, email);
243
}
244
245
// After
246
function processUser({name, age, email}) {
247
console.log(name, age, email);
248
}
249
```
250
251
### Array Includes
252
253
Converts `indexOf()` usage to `includes()` method.
254
255
```javascript { .api }
256
// Transform name: "includes"
257
```
258
259
**What it transforms:**
260
261
- `array.indexOf(item) !== -1` to `array.includes(item)`
262
- `array.indexOf(item) >= 0` to `array.includes(item)`
263
- `array.indexOf(item) > -1` to `array.includes(item)`
264
- `array.indexOf(item) === -1` to `!array.includes(item)`
265
266
**Usage Example:**
267
268
```javascript
269
// Before
270
if (items.indexOf('apple') !== -1) {
271
console.log('Found apple');
272
}
273
274
if (users.indexOf(currentUser) >= 0) {
275
console.log('User exists');
276
}
277
278
// After
279
if (items.includes('apple')) {
280
console.log('Found apple');
281
}
282
283
if (users.includes(currentUser)) {
284
console.log('User exists');
285
}
286
```