Skip to content

Commit 4817021

Browse files
committed
docs(minifier): clarify assumptions (#13950)
Follow up to #13938. Make the assumption docs are bit more clear.
1 parent 7eead3b commit 4817021

File tree

1 file changed

+43
-96
lines changed

1 file changed

+43
-96
lines changed

crates/oxc_minifier/docs/ASSUMPTIONS.md

Lines changed: 43 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ These assumptions are validated using ECMAScript operations from [`oxc_ecmascrip
66

77
## Core Assumptions
88

9-
### 1. No Monkey-Patching Built-ins
9+
These assumptions are held regardless of the options.
1010

11-
Built-in objects and their methods behave as specified in ECMAScript.
11+
### No Monkey-Patching Built-ins
12+
13+
[Built-in objects and their methods and properties](https://tc39.es/ecma262/multipage/global-object.html#sec-global-object) behave as specified in ECMAScript.
1214

1315
```javascript
1416
// The minifier assumes this never happens:
@@ -18,17 +20,17 @@ Array.prototype.push = function() {
1820
Object.defineProperty(Number.prototype, 'toString', { value: () => 'hijacked!' });
1921
```
2022

21-
### 2. No `document.all` Usage
23+
### No `document.all` Usage
2224

23-
The deprecated `document.all` with its special typeof behavior is not used.
25+
The deprecated [`document.all`](https://tc39.es/ecma262/multipage/additional-ecmascript-features-for-web-browsers.html#sec-IsHTMLDDA-internal-slot) with its special typeof behavior is not used.
2426

2527
```javascript
2628
// The minifier assumes this never happens:
2729
typeof document.all === 'undefined'; // true in browsers
2830
document.all && console.log('exists but falsy');
2931
```
3032

31-
### 3. No `with` Statement
33+
### No `with` Statement
3234

3335
Code does not use `with` statements which create ambiguous scope.
3436

@@ -39,43 +41,7 @@ with (obj) {
3941
}
4042
```
4143

42-
### 4. No Direct `eval` or `Function` Constructor
43-
44-
Code doesn't dynamically evaluate strings as code.
45-
46-
```javascript
47-
// The minifier assumes this never happens:
48-
eval('var x = 1');
49-
new Function('return x');
50-
```
51-
52-
### 5. No Arguments Aliasing
53-
54-
The `arguments` object is not aliased or modified in ways that affect parameters.
55-
56-
```javascript
57-
// The minifier assumes this never happens:
58-
function f(a) {
59-
arguments[0] = 2;
60-
return a; // Would be affected by arguments modification
61-
}
62-
```
63-
64-
### 6. Getters/Setters Are Pure
65-
66-
Property getters and setters have no side effects.
67-
68-
```javascript
69-
// The minifier assumes this never happens:
70-
const obj = {
71-
get prop() {
72-
console.log('side effect!');
73-
return 1;
74-
},
75-
};
76-
```
77-
78-
### 7. Coercion Methods Are Pure
44+
### Coercion Methods Are Pure
7945

8046
`.toString()`, `.valueOf()`, and `[Symbol.toPrimitive]()` have no side effects. The minifier uses `oxc_ecmascript` type conversion utilities that assume standard coercion behavior.
8147

@@ -90,95 +56,76 @@ const obj = {
9056
String(obj); // Would trigger side effect
9157
```
9258

93-
### 8. No Reliance on Function.prototype.name
94-
95-
Code doesn't depend on function names being preserved.
96-
97-
```javascript
98-
// The minifier assumes this never happens:
99-
function myFunc() {}
100-
if (myFunc.name !== 'myFunc') throw Error();
101-
```
102-
103-
### 9. No Reliance on Function.length
59+
### No TDZ Violation
10460

105-
Code doesn't depend on function arity.
61+
Code doesn't violate Temporal Dead Zones.
10662

10763
```javascript
10864
// The minifier assumes this never happens:
109-
function f(a, b, c) {}
110-
if (f.length !== 3) throw Error();
65+
console.log(x); // TDZ violation
66+
let x = 1;
11167
```
11268

113-
### 10. Regular Prototype Chains
69+
### No errors from Array/String Maximum Length
11470

115-
Objects have standard prototype chains without modifications.
71+
Creating strings or arrays that exceed maximum length can be moved or removed.
11672

11773
```javascript
118-
// The minifier assumes this never happens:
119-
Object.setPrototypeOf(obj, null);
120-
obj.__proto__ = weird_proto;
74+
// The minifier may change when this error occurs:
75+
try {
76+
new Array(2 ** 32); // RangeError
77+
} catch {
78+
console.log('caught');
79+
}
12180
```
12281

123-
### 11. Special Handling of `__proto__` Property
82+
### No side effects from extending a class
12483

125-
The minifier correctly handles `__proto__` as a special property name when inlining variables.
84+
Extending a class does not have a side effect.
12685

12786
```javascript
128-
// Before optimization:
129-
function wrapper() {
130-
var __proto__ = [];
131-
return { __proto__ };
132-
}
133-
134-
// After optimization:
135-
function wrapper() {
136-
return { ['__proto__']: [] };
137-
}
87+
const v = [];
88+
class A extends v {} // TypeError
13889
```
13990

140-
The minifier converts shorthand `__proto__` properties to computed form to preserve semantics.
141-
142-
### 12. No TDZ Violation
91+
### No Direct `eval` or `Function` Constructor
14392

144-
Code doesn't violate Temporal Dead Zones.
93+
Code doesn't dynamically evaluate strings as code. We intend to change this assumption to optional in the future.
14594

14695
```javascript
14796
// The minifier assumes this never happens:
148-
console.log(x); // TDZ violation
149-
let x = 1;
97+
eval('var x = 1');
98+
new Function('return x');
15099
```
151100

152-
### 13. typeof-Guarded Global Access
101+
### `arguments` is always [the arguments object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments)
153102

154-
The minifier optimizes `typeof`-guarded global variable access by removing unnecessary checks.
103+
`arguments` variables are only accessed inside functions and not assigned with a different value. We intend to change this assumption to optional in the future.
155104

156105
```javascript
157-
// Before optimization:
158-
typeof x !== 'undefined' && x;
159-
160-
// After optimization:
161-
// (removed entirely if x is known to be undefined)
106+
// The minifier assumes this never happens:
107+
console.log(arguments); // This is not the arguments object
108+
function f(a) {
109+
arguments = 2; // This makes the arguments variable point not to point to the arguments object
110+
return a;
111+
}
162112
```
163113

164-
This assumes that `typeof`-guarded expressions are used defensively and can be safely removed when the variable is provably undefined.
114+
## Optional Assumptions
165115

166-
### 14. Errors from Array/String Maximum Length
116+
### No Reliance on Function.prototype.name
167117

168-
Creating strings or arrays that exceed maximum length can be moved or removed.
118+
Code doesn't depend on function names being preserved. This assumption is held by default. This can be changed by settings `keepNames` option.
169119

170120
```javascript
171-
// The minifier may change when this error occurs:
172-
try {
173-
new Array(2 ** 32); // RangeError
174-
} catch {
175-
console.log('caught');
176-
}
121+
// The minifier assumes this never happens:
122+
function myFunc() {}
123+
if (myFunc.name !== 'myFunc') throw Error();
177124
```
178125

179126
## Configuration
180127

181-
These assumptions can be configured in the minifier options if your code requires different behavior.
128+
Optional assumptions can be configured in the minifier options if your code requires different behavior.
182129

183130
```rust
184131
pub struct CompressOptions {

0 commit comments

Comments
 (0)