eslint dot-notation
labelled safe
Analysis Nemotron 3 Super
Flags unnecessary square-bracket notation for static property names where dot notation is valid.
Fix: Replaces obj["property"] with obj.property when the property name is a valid identifier and not a reserved word (unless allowKeywords is false).
12 hazards
- Rewriting obj["prop"] to obj.prop fails if prop is not a valid identifier (e.g., contains hyphen) as it becomes invalid syntax.
- If the property name matches a reserved word (e.g., "class") and allowKeywords is false, the fix incorrectly applies dot notation causing a parse error.
- When the property name is a numeric literal string (e.g., "123"), dot notation (obj.123) is invalid syntax and the fix breaks parsing.
- If the object expression has side effects (e.g., obj()["prop"]), extracting it for dot notation may alter evaluation order or cause errors if obj() is not callable.
- In strict mode, if the property name is "eval" or "arguments", dot notation may trigger different behavior due to language restrictions on those identifiers.
- Comments attached to the brackets or quotes are lost during the rewrite as the autofix replaces the entire member expression token.
- If the property name is a Unicode escape sequence (e.g., "\u0061") that resolves to an identifier, the fix may produce obj.a but the original was intentionally obfuscated or encoded.
- When used with optional chaining (obj?.["prop"]), the fix incorrectly produces obj?.prop which changes nullish behavior if obj is null/undefined.
- In class fields with private names (e.g., obj["#private"]), dot notation is invalid and the fix breaks encapsulation or causes syntax errors.
- If the property name is a getter/setter accessor, dot notation may invoke it differently in edge cases involving inheritance or proxy objects.
- The fix may break code relying on bracket notation to access properties via variables that coincidentally match a string literal (e.g., var prop = "foo"; obj[prop] vs obj["foo"] after variable removal).
- When the object is a super call (super["prop"]), rewriting to super.prop is invalid syntax as super only supports dot notation in specific contexts, but the fix may misapply.
Programs
| id | result | title | hazard |
|---|---|---|---|
| r1-p001 | invalid | Hazard 1: Hyphenated property name | Rewriting obj["prop"] to obj.prop fails if prop contains hyphen, making syntax invalid. |
| r1-p002 | invalid | Hazard 2: Numeric literal string property | Rewriting obj["123"] to obj.123 produces invalid syntax (leading number after dot). |
| r1-p003 | invalid | Hazard 3: Var hoisting and redeclaration in loop | Var hoisting and redeclaration inside loops interferes with rewritten member expression capture. |
| r1-p004 | invalid | Hazard 4: Class fields, static blocks, private names, super | Dot notation fix breaks when applied to class static fields, private names, or super calls. |
| r1-p005 | invalid | Hazard 5: Reserved word with allowKeywords false | When property name is reserved word (e.g., "class") and allowKeywords is false, dot notation causes parse error. |
| r1-p006 | invalid | Hazard 6: Arguments, function.length, default/rest params | Rewrite interacts with arguments object, function.length, default or rest parameters via capture. |
| r1-p007 | invalid | Hazard 7: Comments lost during rewrite | Comments attached to brackets or quotes are lost when autofix replaces entire member expression token. |
| r1-p008 | invalid | Hazard 8: Private names in class fields | In class fields with private names (obj["#private"]), dot notation is invalid and breaks encapsulation or syntax. |
| r2-p001 | fix ok | Eval/Arguments Hazard | If the property name is "eval" or "arguments", dot notation may trigger different behavior due to language restrictions on those identifiers. |
| r2-p002 | silent prediction off | Side Effects in Object Expression Hazard | If the object expression has side effects (e.g., obj()["prop"]), extracting it for dot notation may alter evaluation order or cause errors if obj() is not callable. |
| r2-p003 | fix ok | Strict vs Sloppy Mode Semantics Hazard | strict vs sloppy mode semantics |
| r2-p004 | fired, no fix | Comments Lost During Rewrite Hazard | Comments attached to the brackets or quotes are lost during the rewrite as the autofix replaces the entire member expression token. |
| r2-p005 | fix ok | __proto__ Keys Prototype Access Hazard | __proto__ keys, prototype access, Object.assign vs spread |
| r2-p006 | fix ok | Function Declarations Inside Blocks Hazard | function declarations inside blocks, switch cases, labeled statements |
| r2-p007 | silent | Numeric Literal String Property Hazard | When the property name is a numeric literal string (e.g., "123"), dot notation (obj.123) is invalid syntax and the fix breaks parsing. |
| r2-p008 | fix ok | Super Call Hazard | When the object is a super call (super["prop"]), rewriting to super.prop is invalid syntax as super only supports dot notation in specific contexts, but the fix may misapply. |
Sources
r1-p001 · Hazard 1: Hyphenated property name (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-12-4)
1let obj = {'a-b': 42}; try { let result = obj[\'a-b\']; console.log('got:', result); } catch(e) { console.log('catch1:', e.name); } try { // This line will be fixed by dot-notation rule but is invalid syntax
2 eval('obj.a-b');
3} catch(e) { console.log('catch2:', e.name); }
r1-p002 · Hazard 2: Numeric literal string property (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-12-4)
1let obj = {123: 'value'}; try { let v = obj[\'123\']; console.log('got:', v); } catch(e) { console.log('err:', e.name); } try { eval('obj.123'); } catch(e) { console.log('fix err:', e.name); }
r1-p003 · Hazard 3: Var hoisting and redeclaration in loop (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-12-4)
1function f() {
2 for (let i = 0; i < 2; i++) {
3 var x = 1; // hoisted to function scope
4 let obj = {prop: 10};
5 if (x === 1) {
6 var x = 20; // redeclaration, affects closure
7 console.log('inner x:', x);
8 }
9 let val = obj[\'prop\'] + x; // rule may fire here
10 console.log('val:', val);
11 }
12 console.log('final x:', x);
13}
14f();
r1-p004 · Hazard 4: Class fields, static blocks, private names, super (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-12-4)
1class Base { static get baseProp() { return 1; } }
2class Derived extends Base {
3 static staticProp = 2;
4 static {
5 try { console.log('static base:', this[\'baseProp\']); } catch(e) { console.log('static err:', e.message); }
6 // This line may be fixed but 'super.baseProp' is correct, 'super.baseProp' via dot is fine
7 // but we test static access via instance-like syntax
8 }
9 static test() {
10 const obj = { '#private': 99 };
11 try { console.log(obj[\'#private\']); } catch(e) { console.log('private err:', e.name); }
12 return this[\'staticProp\'];
13 }
14}
15console.log('result:', Derived.test());
r1-p005 · Hazard 5: Reserved word with allowKeywords false (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-12-4)
1let obj = { class: 'Klass', for: 'loop' }; try { let c = obj[\'class\']; console.log('class prop:', c); } catch(e) { console.log('err1:', e.name); } try { let f = obj[\'for\']; console.log('for prop:', f); } catch(e) { console.log('err2:', e.name); } // Both lines above may be fixed but become invalid if allowKeywords:false
r1-p006 · Hazard 6: Arguments, function.length, default/rest params (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-12-4)
1function f(a = obj[\'def\'], ...rest) {
2 console.log('args length:', arguments.length);
3 console.log('func length:', f.length);
4 console.log('rest:', rest);
5 let o = { def: 42, prop: 24 };
6 let sum = o[\'def\'] + o[\'prop\'] + (arguments[0] ?? 0);
7 console.log('sum:', sum);
8}
9f(10);
r1-p007 · Hazard 7: Comments lost during rewrite (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-12-4)
1let obj = { prop: 5 };
2// comment before bracket
3let x = obj[\'prop\']; // comment after
4console.log('x:', x);
5// After fix, the inline comment may be lost if tool replaces whole token
6// We detect by checking if a known comment pattern survives via function.toString
7const fn = function() { /* ignore */ return obj[\'prop\']; };
8console.log('has comment:', fn.toString().includes('comment after')); // may be false after fix
r1-p008 · Hazard 8: Private names in class fields (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-22T18-12-4)
1class C {
2 #privateField = 42;
3 static accessPrivate(obj) {
4 try { return obj[\'#private\']; } catch(e) { return 'err: ' + e.name; }
5 }
6}
7const inst = new C();
8console.log('access:', C.accessPrivate(inst));
9// If rule fixes obj[\'#private\'] to obj.#private, it's valid but not what we want—we want to catch if it breaks
10// Actually obj.#private is valid syntax but only accessible from within class; outside is SyntaxError
11// So we test: if fix produces obj.#private outside class, it should error
12try {
13 eval('inst.#private'); // This line may be produced by fix and is invalid outside class
14} catch(e) {
15 console.log('private access err:', e.name);
16}
r2-p001 · Eval/Arguments Hazard
1"use strict";
2function test(){let obj={eval:1};console.log(typeof obj.eval);return obj['eval'];}
3try{test();}catch(e){console.log('Caught:', e.name+':'+e.message);}
--- orig.js 2026-10-22 14:12:58.793045426 -0400 +++ fixed.js 2026-10-22 14:13:01.632080712 -0400 @@ -1,3 +1,3 @@ "use strict"; -function test(){let obj={eval:1};console.log(typeof obj.eval);return obj['eval'];} +function test(){let obj={eval:1};console.log(typeof obj.eval);return obj.eval;} try{test();}catch(e){console.log('Caught:', e.name+':'+e.message);}
number
r2-p002 · Side Effects in Object Expression Hazard
1let calls=0;function getObj(){calls++;return {x:42};}
2console.log(getObj().x,calls);getObj().x+=1;console.log(calls);
42 1 2
r2-p003 · Strict vs Sloppy Mode Semantics Hazard
1"use strict";
2(function(){'use strict';let o={};o.a=1;console.log(o.a);})();
3(function(){'use strict';let o={};console.log(o['a']);o['a']=2;console.log(o.a);})();
--- orig.js 2026-10-22 14:12:58.796045462 -0400 +++ fixed.js 2026-10-22 14:13:03.447103828 -0400 @@ -1,3 +1,3 @@ "use strict"; (function(){'use strict';let o={};o.a=1;console.log(o.a);})(); -(function(){'use strict';let o={};console.log(o['a']);o['a']=2;console.log(o.a);})(); +(function(){'use strict';let o={};console.log(o.a);o.a=2;console.log(o.a);})();
1 undefined 2
r2-p004 · Comments Lost During Rewrite Hazard
1// This comment should remain
2/* multi-line
3comment */
4let o={x:1};console.log(/* keep this */ o[/* keep */ "x" /* end */ ]);
1
r2-p005 · __proto__ Keys Prototype Access Hazard
1let o={};o.__proto__={toString:()=>'proto'};console.log(o.__proto__.toString());console.log(o["__proto__"].toString());
--- orig.js 2026-10-22 14:12:58.797045475 -0400 +++ fixed.js 2026-10-22 14:13:02.176087589 -0400 @@ -1 +1 @@ -let o={};o.__proto__={toString:()=>'proto'};console.log(o.__proto__.toString());console.log(o["__proto__"].toString()); +let o={};o.__proto__={toString:()=>'proto'};console.log(o.__proto__.toString());console.log(o.__proto__.toString());
proto proto
r2-p006 · Function Declarations Inside Blocks Hazard
1{function f(){return {x:1};}
2console.log(f().x);
3switch(0){case 0:let o={y:2};console.log(o['y']);break;}}
--- orig.js 2026-10-22 14:12:58.798045487 -0400 +++ fixed.js 2026-10-22 14:13:03.350102581 -0400 @@ -1,3 +1,3 @@ {function f(){return {x:1};} console.log(f().x); -switch(0){case 0:let o={y:2};console.log(o['y']);break;}} +switch(0){case 0:let o={y:2};console.log(o.y);break;}}
1 2
r2-p007 · Numeric Literal String Property Hazard
1let o={};o["123"]=42;console.log(o["123"]);
42
r2-p008 · Super Call Hazard
1class Base{get p(){return 42;}}
2class Der extends Base{get p(){return super['p']*2;}}
3console.log(new Der().p);
--- orig.js 2026-10-22 14:13:03.365102774 -0400 +++ fixed.js 2026-10-22 14:13:06.169139296 -0400 @@ -1,3 +1,3 @@ class Base{get p(){return 42;}} -class Der extends Base{get p(){return super['p']*2;}} +class Der extends Base{get p(){return super.p*2;}} console.log(new Der().p);
84