diff --git a/apps/oxlint/conformance/snapshot.md b/apps/oxlint/conformance/snapshot.md index 5c155c8f54358..85abbb21fd611 100644 --- a/apps/oxlint/conformance/snapshot.md +++ b/apps/oxlint/conformance/snapshot.md @@ -6,9 +6,9 @@ | Status | Count | % | | ----------------- | ----- | ------ | -| Total rules | 277 | 100.0% | -| Fully passing | 222 | 80.1% | -| Partially passing | 55 | 19.9% | +| Total rules | 292 | 100.0% | +| Fully passing | 232 | 79.5% | +| Partially passing | 60 | 20.5% | | Fully failing | 0 | 0.0% | | Load errors | 0 | 0.0% | | No tests run | 0 | 0.0% | @@ -17,16 +17,17 @@ | Status | Count | % | | ----------- | ----- | ------ | -| Total tests | 29765 | 100.0% | -| Passing | 28968 | 97.3% | -| Failing | 690 | 2.3% | -| Skipped | 107 | 0.4% | +| Total tests | 33090 | 100.0% | +| Passing | 32189 | 97.3% | +| Failing | 794 | 2.4% | +| Skipped | 107 | 0.3% | ## Fully Passing Rules - `accessor-pairs` (302 tests) - `array-bracket-newline` (209 tests) - `array-bracket-spacing` (143 tests) (4 skipped) +- `array-callback-return` (216 tests) - `array-element-newline` (155 tests) - `arrow-body-style` (87 tests) - `arrow-parens` (109 tests) (21 skipped) @@ -38,7 +39,10 @@ - `class-methods-use-this` (156 tests) - `comma-spacing` (173 tests) - `comma-style` (96 tests) +- `complexity` (165 tests) - `computed-property-spacing` (125 tests) +- `consistent-return` (44 tests) +- `constructor-super` (82 tests) - `curly` (216 tests) - `default-case-last` (37 tests) - `default-case` (23 tests) @@ -54,6 +58,7 @@ - `function-call-argument-newline` (58 tests) - `function-paren-newline` (177 tests) (2 skipped) - `generator-star-spacing` (201 tests) +- `getter-return` (70 tests) - `global-require` (22 tests) - `grouped-accessor-pairs` (150 tests) - `guard-for-in` (12 tests) @@ -99,6 +104,7 @@ - `no-confusing-arrow` (30 tests) - `no-console` (44 tests) - `no-const-assign` (33 tests) +- `no-constructor-return` (20 tests) - `no-continue` (6 tests) - `no-control-regex` (36 tests) - `no-debugger` (2 tests) @@ -177,6 +183,7 @@ - `no-tabs` (11 tests) - `no-template-curly-in-string` (22 tests) - `no-ternary` (4 tests) +- `no-this-before-super` (63 tests) - `no-throw-literal` (41 tests) - `no-unassigned-vars` (23 tests) - `no-undef-init` (28 tests) @@ -184,6 +191,8 @@ - `no-unexpected-multiline` (56 tests) (4 skipped) - `no-unmodified-loop-condition` (37 tests) - `no-unneeded-ternary` (47 tests) (2 skipped) +- `no-unreachable-loop` (1628 tests) +- `no-unreachable` (67 tests) - `no-unsafe-finally` (28 tests) - `no-unsafe-negation` (29 tests) - `no-unsafe-optional-chaining` (187 tests) @@ -196,6 +205,7 @@ - `no-useless-constructor` (49 tests) (1 skipped) - `no-useless-escape` (288 tests) - `no-useless-rename` (163 tests) (1 skipped) +- `no-useless-return` (49 tests) - `no-var` (52 tests) (1 skipped) - `no-void` (12 tests) - `no-warning-comments` (61 tests) @@ -265,9 +275,11 @@ - `no-constant-condition` - 305 / 307 (99.3%) - `no-eval` - 76 / 101 (75.2%) - `no-extra-parens` - 1068 / 1072 (99.6%) +- `no-fallthrough` - 86 / 87 (98.9%) - `no-global-assign` - 12 / 18 (66.7%) - `no-implicit-globals` - 153 / 245 (62.4%) - `no-implied-eval` - 83 / 138 (60.1%) +- `no-invalid-this` - 520 / 562 (92.5%) - `no-irregular-whitespace` - 279 / 280 (99.6%) - `no-lone-blocks` - 49 / 50 (98.0%) - `no-misleading-character-class` - 185 / 190 (97.4%) @@ -278,6 +290,7 @@ - `no-new-wrappers` - 9 / 11 (81.8%) - `no-obj-calls` - 73 / 107 (68.2%) - `no-object-constructor` - 55 / 56 (98.2%) +- `no-promise-executor-return` - 66 / 124 (53.2%) - `no-redeclare` - 51 / 75 (68.0%) - `no-restricted-globals` - 143 / 166 (86.1%) - `no-restricted-imports` - 253 / 254 (99.6%) @@ -290,6 +303,7 @@ - `no-unused-expressions` - 120 / 124 (96.8%) - `no-unused-vars` - 340 / 436 (78.0%) - `no-use-before-define` - 323 / 347 (93.1%) +- `no-useless-assignment` - 83 / 85 (97.6%) - `no-useless-backreference` - 188 / 190 (98.9%) - `prefer-const` - 136 / 138 (98.6%) - `prefer-exponentiation-operator` - 164 / 167 (98.2%) @@ -298,6 +312,7 @@ - `prefer-object-spread` - 82 / 87 (94.3%) - `prefer-regex-literals` - 239 / 251 (95.2%) - `radix` - 33 / 54 (61.1%) +- `require-atomic-updates` - 62 / 63 (98.4%) - `require-unicode-regexp` - 76 / 79 (96.2%) - `semi` - 307 / 308 (99.7%) - `strict` - 106 / 126 (84.1%) @@ -6167,6 +6182,47 @@ AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ at apps/oxlint/dist/index.js +### `no-fallthrough` + +Pass: 86 / 87 (98.9%) +Fail: 1 / 87 (1.1%) +Skip: 0 / 87 (0.0%) + +#### no-fallthrough > valid + +```js +switch (foo) { case 0: a(); +// eslint-disable-next-line rule-to-test/no-fallthrough + case 1: } +``` + +```json +{} +``` + +AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ + { + ruleId: 'rule-to-test/no-fallthrough', + message: "Expected a 'break' statement before 'case'.", + messageId: 'case', + severity: 1, + nodeType: 'SwitchCase', + line: 3, + column: 1, + endLine: 3, + endColumn: 8, + suggestions: null + } +] + +1 !== 0 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertValidTestCasePasses (apps/oxlint/dist/index.js) + at runValidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + ### `no-global-assign` Pass: 12 / 18 (66.7%) @@ -49401,33 +49457,37 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] at apps/oxlint/dist/index.js -### `no-irregular-whitespace` +### `no-invalid-this` -Pass: 279 / 280 (99.6%) -Fail: 1 / 280 (0.4%) -Skip: 0 / 280 (0.0%) +Pass: 520 / 562 (92.5%) +Fail: 42 / 562 (7.5%) +Skip: 0 / 562 (0.0%) -#### no-irregular-whitespace > valid +#### no-invalid-this > valid ```js -ο»Ώconsole.log('hello BOM'); +function foo() { 'use strict'; this.eval(); } ``` ```json -{} +{ + "languageOptions": { + "ecmaVersion": 3 + } +} ``` AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ { - ruleId: 'rule-to-test/no-irregular-whitespace', - message: 'Irregular whitespace not allowed.', - messageId: 'noIrregularWhitespace', + ruleId: 'rule-to-test/no-invalid-this', + message: "Unexpected 'this'.", + messageId: 'unexpectedThis', severity: 1, - nodeType: null, + nodeType: 'ThisExpression', line: 1, - column: 0, + column: 31, endLine: 1, - endColumn: 1, + endColumn: 35, suggestions: null } ] @@ -49440,42 +49500,31 @@ AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ at apps/oxlint/dist/index.js -### `no-lone-blocks` - -Pass: 47 / 50 (94.0%) -Fail: 1 / 50 (2.0%) -Skip: 2 / 50 (4.0%) - -#### no-lone-blocks > valid +#### no-invalid-this > valid ```js -{ function bar() {} } +"use strict"; function foo() { 'use strict'; this.eval(); } ``` ```json { "languageOptions": { - "ecmaVersion": 6, - "parserOptions": { - "ecmaFeatures": { - "impliedStrict": true - } - } + "ecmaVersion": 3 } } ``` AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ { - ruleId: 'rule-to-test/no-lone-blocks', - message: 'Block is redundant.', - messageId: 'redundantBlock', + ruleId: 'rule-to-test/no-invalid-this', + message: "Unexpected 'this'.", + messageId: 'unexpectedThis', severity: 1, - nodeType: 'BlockStatement', + nodeType: 'ThisExpression', line: 1, - column: 0, + column: 45, endLine: 1, - endColumn: 21, + endColumn: 49, suggestions: null } ] @@ -49488,23 +49537,20 @@ AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ at apps/oxlint/dist/index.js -### `no-misleading-character-class` - -Pass: 185 / 190 (97.4%) -Fail: 5 / 190 (2.6%) -Skip: 0 / 190 (0.0%) - -#### no-misleading-character-class > valid +#### no-invalid-this > valid ```js -new RegExp('[πŸ‘]') +/* implied strict mode */ function foo() { 'use strict'; this.eval(); } ``` ```json { "languageOptions": { - "globals": { - "RegExp": "off" + "ecmaVersion": 3, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } } } } @@ -49512,15 +49558,15 @@ new RegExp('[πŸ‘]') AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ { - ruleId: 'rule-to-test/no-misleading-character-class', - message: "Unexpected surrogate pair in character class. Use 'u' flag.", - messageId: 'surrogatePairWithoutUFlag', + ruleId: 'rule-to-test/no-invalid-this', + message: "Unexpected 'this'.", + messageId: 'unexpectedThis', severity: 1, - nodeType: 'Literal', + nodeType: 'ThisExpression', line: 1, - column: 13, + column: 57, endLine: 1, - endColumn: 15, + endColumn: 61, suggestions: null } ] @@ -49533,31 +49579,36 @@ AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ at apps/oxlint/dist/index.js -#### no-misleading-character-class > invalid +#### no-invalid-this > invalid ```js -var r = new globalThis.RegExp("[❇️]", "") +"use strict"; console.log(this); z(x => console.log(x, this)); /* should error */ ``` ```json { "languageOptions": { - "ecmaVersion": 2020 + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "globalReturn": true + } + } }, "errors": [ { - "column": 33, - "endColumn": 35, - "messageId": "combiningClass", - "suggestions": null + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" } ] } ``` -AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] -0 !== 1 +0 !== 2 at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) @@ -49565,31 +49616,37 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] at apps/oxlint/dist/index.js -#### no-misleading-character-class > invalid +#### no-invalid-this > invalid ```js -var r = new globalThis.RegExp("[πŸ‘ΆπŸ»]", "u") +/* implied strict mode */ console.log(this); z(x => console.log(x, this)); /* should error */ ``` ```json { "languageOptions": { - "ecmaVersion": 2020 + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "globalReturn": true, + "impliedStrict": true + } + } }, "errors": [ { - "column": 33, - "endColumn": 37, - "messageId": "emojiModifier", - "suggestions": null + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" } ] } ``` -AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] -0 !== 1 +0 !== 2 at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) @@ -49597,39 +49654,28 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] at apps/oxlint/dist/index.js -#### no-misleading-character-class > invalid +#### no-invalid-this > invalid ```js -var r = new globalThis.RegExp("[πŸ‡―πŸ‡΅]", "") +/* implied strict mode */ (function() { console.log(this); z(x => console.log(x, this)); })(); /* should error */ ``` ```json { "languageOptions": { - "ecmaVersion": 2020 + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } }, "errors": [ { - "column": 33, - "endColumn": 35, - "messageId": "surrogatePairWithoutUFlag", - "suggestions": [ - { - "messageId": "suggestUnicodeFlag", - "output": "var r = new globalThis.RegExp(\"[πŸ‡―πŸ‡΅]\", \"u\")" - } - ] + "messageId": "unexpectedThis" }, { - "column": 35, - "endColumn": 37, - "messageId": "surrogatePairWithoutUFlag", - "suggestions": [ - { - "messageId": "suggestUnicodeFlag", - "output": "var r = new globalThis.RegExp(\"[πŸ‡―πŸ‡΅]\", \"u\")" - } - ] + "messageId": "unexpectedThis" } ] } @@ -49645,31 +49691,36 @@ AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] at apps/oxlint/dist/index.js -#### no-misleading-character-class > invalid +#### no-invalid-this > invalid ```js -var r = new globalThis.RegExp("[\\u{1F468}\\u{200D}\\u{1F469}\\u{200D}\\u{1F466}]", "u") +/* implied strict mode */ function foo() { console.log(this); z(x => console.log(x, this)); } /* should error */ ``` ```json { "languageOptions": { - "ecmaVersion": 2020 + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } }, "errors": [ { - "column": 33, - "endColumn": 81, - "messageId": "zwj", - "suggestions": null + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" } ] } ``` -AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] -0 !== 1 +0 !== 2 at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) @@ -49677,319 +49728,1905 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] at apps/oxlint/dist/index.js -### `no-multiple-empty-lines` +#### no-invalid-this > invalid -Pass: 45 / 46 (97.8%) -Fail: 1 / 46 (2.2%) -Skip: 0 / 46 (0.0%) +```js +/* implied strict mode */ function foo() { console.log(this); z(x => console.log(x, this)); } /* should error */ +``` -#### no-multiple-empty-lines > invalid +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "options": [ + { + "capIsConstructor": false + } + ], + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid ```js -foo - +/* implied strict mode */ function Foo() { console.log(this); z(x => console.log(x, this)); } /* should error */ ``` ```json { - "output": "foo\n", + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, "options": [ { - "max": 1, - "maxEOF": 0 + "capIsConstructor": false } ], "errors": [ { - "messageId": "blankEndOfFile", - "data": { - "max": 0 - }, - "column": 1 + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" } ] } ``` -RangeError: Line number out of range (line 3 requested). Line numbers should be 1-based, and less than or equal to number of lines in file (2). - at getOffsetFromLineColumn (apps/oxlint/dist/lint.js) - at report (apps/oxlint/dist/lint.js) - at Object.report (apps/oxlint/dist/lint.js) - at apps/oxlint/conformance/submodules/eslint/lib/rules/no-multiple-empty-lines.js:157:17 +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] +0 !== 2 -### `no-native-reassign` + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js -Pass: 12 / 18 (66.7%) -Fail: 6 / 18 (33.3%) -Skip: 0 / 18 (0.0%) -#### no-native-reassign > invalid +#### no-invalid-this > invalid ```js -top = 0; +/* implied strict mode */ return function() { console.log(this); z(x => console.log(x, this)); }; /* should error */ ``` ```json { "languageOptions": { - "globals": { - "AbortController": false, - "AbortSignal": false, - "AbsoluteOrientationSensor": false, - "AbstractRange": false, - "Accelerometer": false, - "addEventListener": false, - "ai": false, - "AI": false, - "AICreateMonitor": false, - "AITextSession": false, - "alert": false, - "AnalyserNode": false, - "Animation": false, - "AnimationEffect": false, - "AnimationEvent": false, - "AnimationPlaybackEvent": false, - "AnimationTimeline": false, - "AsyncDisposableStack": false, - "atob": false, - "Attr": false, - "Audio": false, - "AudioBuffer": false, - "AudioBufferSourceNode": false, - "AudioContext": false, - "AudioData": false, - "AudioDecoder": false, - "AudioDestinationNode": false, - "AudioEncoder": false, - "AudioListener": false, - "AudioNode": false, - "AudioParam": false, - "AudioParamMap": false, - "AudioProcessingEvent": false, - "AudioScheduledSourceNode": false, - "AudioSinkInfo": false, - "AudioWorklet": false, - "AudioWorkletGlobalScope": false, - "AudioWorkletNode": false, - "AudioWorkletProcessor": false, - "AuthenticatorAssertionResponse": false, - "AuthenticatorAttestationResponse": false, - "AuthenticatorResponse": false, - "BackgroundFetchManager": false, - "BackgroundFetchRecord": false, - "BackgroundFetchRegistration": false, - "BarcodeDetector": false, - "BarProp": false, - "BaseAudioContext": false, - "BatteryManager": false, - "BeforeUnloadEvent": false, - "BiquadFilterNode": false, - "Blob": false, - "BlobEvent": false, - "Bluetooth": false, - "BluetoothCharacteristicProperties": false, - "BluetoothDevice": false, - "BluetoothRemoteGATTCharacteristic": false, - "BluetoothRemoteGATTDescriptor": false, - "BluetoothRemoteGATTServer": false, - "BluetoothRemoteGATTService": false, - "BluetoothUUID": false, - "blur": false, - "BroadcastChannel": false, - "BrowserCaptureMediaStreamTrack": false, - "btoa": false, - "ByteLengthQueuingStrategy": false, - "Cache": false, - "caches": false, - "CacheStorage": false, - "cancelAnimationFrame": false, - "cancelIdleCallback": false, - "CanvasCaptureMediaStream": false, - "CanvasCaptureMediaStreamTrack": false, - "CanvasGradient": false, - "CanvasPattern": false, - "CanvasRenderingContext2D": false, - "CaptureController": false, - "CaretPosition": false, - "CDATASection": false, - "ChannelMergerNode": false, - "ChannelSplitterNode": false, - "ChapterInformation": false, - "CharacterBoundsUpdateEvent": false, - "CharacterData": false, - "clearInterval": false, - "clearTimeout": false, - "clientInformation": false, - "Clipboard": false, - "ClipboardChangeEvent": false, - "ClipboardEvent": false, - "ClipboardItem": false, - "close": false, - "closed": false, - "CloseEvent": false, - "CloseWatcher": false, - "CommandEvent": false, - "Comment": false, - "CompositionEvent": false, - "CompressionStream": false, - "confirm": false, - "console": false, - "ConstantSourceNode": false, - "ContentVisibilityAutoStateChangeEvent": false, - "ConvolverNode": false, - "CookieChangeEvent": false, - "CookieDeprecationLabel": false, - "cookieStore": false, - "CookieStore": false, - "CookieStoreManager": false, - "CountQueuingStrategy": false, - "createImageBitmap": false, - "CreateMonitor": false, - "Credential": false, - "credentialless": false, - "CredentialsContainer": false, - "CropTarget": false, - "crossOriginIsolated": false, - "crypto": false, - "Crypto": false, - "CryptoKey": false, - "CSPViolationReportBody": false, - "CSS": false, - "CSSAnimation": false, - "CSSConditionRule": false, - "CSSContainerRule": false, - "CSSCounterStyleRule": false, - "CSSFontFaceRule": false, - "CSSFontFeatureValuesRule": false, - "CSSFontPaletteValuesRule": false, - "CSSFunctionDeclarations": false, - "CSSFunctionDescriptors": false, - "CSSFunctionRule": false, - "CSSGroupingRule": false, - "CSSImageValue": false, - "CSSImportRule": false, - "CSSKeyframeRule": false, - "CSSKeyframesRule": false, - "CSSKeywordValue": false, - "CSSLayerBlockRule": false, - "CSSLayerStatementRule": false, - "CSSMarginRule": false, - "CSSMathClamp": false, - "CSSMathInvert": false, - "CSSMathMax": false, - "CSSMathMin": false, - "CSSMathNegate": false, - "CSSMathProduct": false, - "CSSMathSum": false, - "CSSMathValue": false, - "CSSMatrixComponent": false, - "CSSMediaRule": false, - "CSSNamespaceRule": false, - "CSSNestedDeclarations": false, - "CSSNumericArray": false, - "CSSNumericValue": false, - "CSSPageDescriptors": false, - "CSSPageRule": false, - "CSSPerspective": false, - "CSSPositionTryDescriptors": false, - "CSSPositionTryRule": false, - "CSSPositionValue": false, - "CSSPropertyRule": false, - "CSSRotate": false, - "CSSRule": false, - "CSSRuleList": false, - "CSSScale": false, - "CSSScopeRule": false, - "CSSSkew": false, - "CSSSkewX": false, - "CSSSkewY": false, - "CSSStartingStyleRule": false, - "CSSStyleDeclaration": false, - "CSSStyleRule": false, - "CSSStyleSheet": false, - "CSSStyleValue": false, - "CSSSupportsRule": false, - "CSSTransformComponent": false, - "CSSTransformValue": false, - "CSSTransition": false, - "CSSTranslate": false, - "CSSUnitValue": false, - "CSSUnparsedValue": false, - "CSSVariableReferenceValue": false, - "CSSViewTransitionRule": false, - "currentFrame": false, - "currentTime": false, - "CustomElementRegistry": false, - "customElements": false, - "CustomEvent": false, - "CustomStateSet": false, - "DataTransfer": false, - "DataTransferItem": false, - "DataTransferItemList": false, - "DecompressionStream": false, - "DelayNode": false, - "DelegatedInkTrailPresenter": false, - "DeviceMotionEvent": false, - "DeviceMotionEventAcceleration": false, - "DeviceMotionEventRotationRate": false, - "DeviceOrientationEvent": false, - "devicePixelRatio": false, - "DevicePosture": false, - "DigitalCredential": false, - "dispatchEvent": false, - "DisposableStack": false, - "document": false, - "Document": false, - "DocumentFragment": false, - "documentPictureInPicture": false, - "DocumentPictureInPicture": false, - "DocumentPictureInPictureEvent": false, - "DocumentTimeline": false, - "DocumentType": false, - "DOMError": false, - "DOMException": false, - "DOMImplementation": false, - "DOMMatrix": false, - "DOMMatrixReadOnly": false, - "DOMParser": false, - "DOMPoint": false, - "DOMPointReadOnly": false, - "DOMQuad": false, - "DOMRect": false, - "DOMRectList": false, - "DOMRectReadOnly": false, - "DOMStringList": false, - "DOMStringMap": false, - "DOMTokenList": false, - "DragEvent": false, - "DynamicsCompressorNode": false, - "EditContext": false, - "Element": false, - "ElementInternals": false, - "EncodedAudioChunk": false, - "EncodedVideoChunk": false, - "ErrorEvent": false, - "event": false, - "Event": false, - "EventCounts": false, - "EventSource": false, - "EventTarget": false, - "external": false, - "External": false, - "EyeDropper": false, - "FeaturePolicy": false, - "FederatedCredential": false, - "fence": false, - "Fence": false, - "FencedFrameConfig": false, - "fetch": false, - "fetchLater": false, - "FetchLaterResult": false, - "File": false, - "FileList": false, - "FileReader": false, - "FileSystem": false, + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "globalReturn": true, + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ var foo = (function() { console.log(this); z(x => console.log(x, this)); }).bar(obj); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ var obj = {foo: function() { function foo() { console.log(this); z(x => console.log(x, this)); } foo(); }}; /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ var obj = {foo() { function foo() { console.log(this); z(x => console.log(x, this)); } foo(); }}; /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ var obj = {foo: function() { return function() { console.log(this); z(x => console.log(x, this)); }; }}; /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ obj.foo = function() { return function() { console.log(this); z(x => console.log(x, this)); }; }; /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ obj.foo = (function() { return () => { console.log(this); z(x => console.log(x, this)); }; })(); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ var foo = function() { console.log(this); z(x => console.log(x, this)); }.bind(null); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ (function() { console.log(this); z(x => console.log(x, this)); }).call(undefined); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ (function() { console.log(this); z(x => console.log(x, this)); }).apply(void 0); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ Array.from([], function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ foo.every(function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ foo.filter(function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ foo.find(function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ foo.findIndex(function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ foo.findLast(function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ foo.findLastIndex(function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ foo.flatMap(function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ foo.forEach(function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ foo.map(function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ foo.some(function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ foo.forEach(function() { console.log(this); z(x => console.log(x, this)); }, null); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ /** @returns {void} */ function foo() { console.log(this); z(x => console.log(x, this)); } /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ /** @this Obj */ foo(function() { console.log(this); z(x => console.log(x, this)); }); /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ var Ctor = function() { console.log(this); z(x => console.log(x, this)); } /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "options": [ + { + "capIsConstructor": false + } + ], + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ var func = function() { console.log(this); z(x => console.log(x, this)); } /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ var func = function() { console.log(this); z(x => console.log(x, this)); } /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "options": [ + { + "capIsConstructor": false + } + ], + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ Ctor = function() { console.log(this); z(x => console.log(x, this)); } /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "options": [ + { + "capIsConstructor": false + } + ], + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ func = function() { console.log(this); z(x => console.log(x, this)); } /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ func = function() { console.log(this); z(x => console.log(x, this)); } /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "options": [ + { + "capIsConstructor": false + } + ], + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ function foo(func = function() { console.log(this); z(x => console.log(x, this)); }) {} /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > invalid + +```js +/* implied strict mode */ [func = function() { console.log(this); z(x => console.log(x, this)); }] = a /* should error */ +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + }, + "errors": [ + { + "messageId": "unexpectedThis" + }, + { + "messageId": "unexpectedThis" + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-invalid-this > valid + +```js + + z(function (x, this: context) { + console.log(x, this); + }); + +``` + +```json +{} +``` + +Error: Parsing failed + at parse (apps/oxlint/dist/index.js) + at lint (apps/oxlint/dist/index.js) + at assertValidTestCasePasses (apps/oxlint/dist/index.js) + at runValidTestCase (apps/oxlint/dist/index.js) + + +### `no-irregular-whitespace` + +Pass: 279 / 280 (99.6%) +Fail: 1 / 280 (0.4%) +Skip: 0 / 280 (0.0%) + +#### no-irregular-whitespace > valid + +```js +ο»Ώconsole.log('hello BOM'); +``` + +```json +{} +``` + +AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ + { + ruleId: 'rule-to-test/no-irregular-whitespace', + message: 'Irregular whitespace not allowed.', + messageId: 'noIrregularWhitespace', + severity: 1, + nodeType: null, + line: 1, + column: 0, + endLine: 1, + endColumn: 1, + suggestions: null + } +] + +1 !== 0 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertValidTestCasePasses (apps/oxlint/dist/index.js) + at runValidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +### `no-lone-blocks` + +Pass: 47 / 50 (94.0%) +Fail: 1 / 50 (2.0%) +Skip: 2 / 50 (4.0%) + +#### no-lone-blocks > valid + +```js +{ function bar() {} } +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6, + "parserOptions": { + "ecmaFeatures": { + "impliedStrict": true + } + } + } +} +``` + +AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ + { + ruleId: 'rule-to-test/no-lone-blocks', + message: 'Block is redundant.', + messageId: 'redundantBlock', + severity: 1, + nodeType: 'BlockStatement', + line: 1, + column: 0, + endLine: 1, + endColumn: 21, + suggestions: null + } +] + +1 !== 0 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertValidTestCasePasses (apps/oxlint/dist/index.js) + at runValidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +### `no-misleading-character-class` + +Pass: 185 / 190 (97.4%) +Fail: 5 / 190 (2.6%) +Skip: 0 / 190 (0.0%) + +#### no-misleading-character-class > valid + +```js +new RegExp('[πŸ‘]') +``` + +```json +{ + "languageOptions": { + "globals": { + "RegExp": "off" + } + } +} +``` + +AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ + { + ruleId: 'rule-to-test/no-misleading-character-class', + message: "Unexpected surrogate pair in character class. Use 'u' flag.", + messageId: 'surrogatePairWithoutUFlag', + severity: 1, + nodeType: 'Literal', + line: 1, + column: 13, + endLine: 1, + endColumn: 15, + suggestions: null + } +] + +1 !== 0 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertValidTestCasePasses (apps/oxlint/dist/index.js) + at runValidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-misleading-character-class > invalid + +```js +var r = new globalThis.RegExp("[❇️]", "") +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 2020 + }, + "errors": [ + { + "column": 33, + "endColumn": 35, + "messageId": "combiningClass", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-misleading-character-class > invalid + +```js +var r = new globalThis.RegExp("[πŸ‘ΆπŸ»]", "u") +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 2020 + }, + "errors": [ + { + "column": 33, + "endColumn": 37, + "messageId": "emojiModifier", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-misleading-character-class > invalid + +```js +var r = new globalThis.RegExp("[πŸ‡―πŸ‡΅]", "") +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 2020 + }, + "errors": [ + { + "column": 33, + "endColumn": 35, + "messageId": "surrogatePairWithoutUFlag", + "suggestions": [ + { + "messageId": "suggestUnicodeFlag", + "output": "var r = new globalThis.RegExp(\"[πŸ‡―πŸ‡΅]\", \"u\")" + } + ] + }, + { + "column": 35, + "endColumn": 37, + "messageId": "surrogatePairWithoutUFlag", + "suggestions": [ + { + "messageId": "suggestUnicodeFlag", + "output": "var r = new globalThis.RegExp(\"[πŸ‡―πŸ‡΅]\", \"u\")" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-misleading-character-class > invalid + +```js +var r = new globalThis.RegExp("[\\u{1F468}\\u{200D}\\u{1F469}\\u{200D}\\u{1F466}]", "u") +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 2020 + }, + "errors": [ + { + "column": 33, + "endColumn": 81, + "messageId": "zwj", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +### `no-multiple-empty-lines` + +Pass: 45 / 46 (97.8%) +Fail: 1 / 46 (2.2%) +Skip: 0 / 46 (0.0%) + +#### no-multiple-empty-lines > invalid + +```js +foo + +``` + +```json +{ + "output": "foo\n", + "options": [ + { + "max": 1, + "maxEOF": 0 + } + ], + "errors": [ + { + "messageId": "blankEndOfFile", + "data": { + "max": 0 + }, + "column": 1 + } + ] +} +``` + +RangeError: Line number out of range (line 3 requested). Line numbers should be 1-based, and less than or equal to number of lines in file (2). + at getOffsetFromLineColumn (apps/oxlint/dist/lint.js) + at report (apps/oxlint/dist/lint.js) + at Object.report (apps/oxlint/dist/lint.js) + at apps/oxlint/conformance/submodules/eslint/lib/rules/no-multiple-empty-lines.js:157:17 + + +### `no-native-reassign` + +Pass: 12 / 18 (66.7%) +Fail: 6 / 18 (33.3%) +Skip: 0 / 18 (0.0%) + +#### no-native-reassign > invalid + +```js +top = 0; +``` + +```json +{ + "languageOptions": { + "globals": { + "AbortController": false, + "AbortSignal": false, + "AbsoluteOrientationSensor": false, + "AbstractRange": false, + "Accelerometer": false, + "addEventListener": false, + "ai": false, + "AI": false, + "AICreateMonitor": false, + "AITextSession": false, + "alert": false, + "AnalyserNode": false, + "Animation": false, + "AnimationEffect": false, + "AnimationEvent": false, + "AnimationPlaybackEvent": false, + "AnimationTimeline": false, + "AsyncDisposableStack": false, + "atob": false, + "Attr": false, + "Audio": false, + "AudioBuffer": false, + "AudioBufferSourceNode": false, + "AudioContext": false, + "AudioData": false, + "AudioDecoder": false, + "AudioDestinationNode": false, + "AudioEncoder": false, + "AudioListener": false, + "AudioNode": false, + "AudioParam": false, + "AudioParamMap": false, + "AudioProcessingEvent": false, + "AudioScheduledSourceNode": false, + "AudioSinkInfo": false, + "AudioWorklet": false, + "AudioWorkletGlobalScope": false, + "AudioWorkletNode": false, + "AudioWorkletProcessor": false, + "AuthenticatorAssertionResponse": false, + "AuthenticatorAttestationResponse": false, + "AuthenticatorResponse": false, + "BackgroundFetchManager": false, + "BackgroundFetchRecord": false, + "BackgroundFetchRegistration": false, + "BarcodeDetector": false, + "BarProp": false, + "BaseAudioContext": false, + "BatteryManager": false, + "BeforeUnloadEvent": false, + "BiquadFilterNode": false, + "Blob": false, + "BlobEvent": false, + "Bluetooth": false, + "BluetoothCharacteristicProperties": false, + "BluetoothDevice": false, + "BluetoothRemoteGATTCharacteristic": false, + "BluetoothRemoteGATTDescriptor": false, + "BluetoothRemoteGATTServer": false, + "BluetoothRemoteGATTService": false, + "BluetoothUUID": false, + "blur": false, + "BroadcastChannel": false, + "BrowserCaptureMediaStreamTrack": false, + "btoa": false, + "ByteLengthQueuingStrategy": false, + "Cache": false, + "caches": false, + "CacheStorage": false, + "cancelAnimationFrame": false, + "cancelIdleCallback": false, + "CanvasCaptureMediaStream": false, + "CanvasCaptureMediaStreamTrack": false, + "CanvasGradient": false, + "CanvasPattern": false, + "CanvasRenderingContext2D": false, + "CaptureController": false, + "CaretPosition": false, + "CDATASection": false, + "ChannelMergerNode": false, + "ChannelSplitterNode": false, + "ChapterInformation": false, + "CharacterBoundsUpdateEvent": false, + "CharacterData": false, + "clearInterval": false, + "clearTimeout": false, + "clientInformation": false, + "Clipboard": false, + "ClipboardChangeEvent": false, + "ClipboardEvent": false, + "ClipboardItem": false, + "close": false, + "closed": false, + "CloseEvent": false, + "CloseWatcher": false, + "CommandEvent": false, + "Comment": false, + "CompositionEvent": false, + "CompressionStream": false, + "confirm": false, + "console": false, + "ConstantSourceNode": false, + "ContentVisibilityAutoStateChangeEvent": false, + "ConvolverNode": false, + "CookieChangeEvent": false, + "CookieDeprecationLabel": false, + "cookieStore": false, + "CookieStore": false, + "CookieStoreManager": false, + "CountQueuingStrategy": false, + "createImageBitmap": false, + "CreateMonitor": false, + "Credential": false, + "credentialless": false, + "CredentialsContainer": false, + "CropTarget": false, + "crossOriginIsolated": false, + "crypto": false, + "Crypto": false, + "CryptoKey": false, + "CSPViolationReportBody": false, + "CSS": false, + "CSSAnimation": false, + "CSSConditionRule": false, + "CSSContainerRule": false, + "CSSCounterStyleRule": false, + "CSSFontFaceRule": false, + "CSSFontFeatureValuesRule": false, + "CSSFontPaletteValuesRule": false, + "CSSFunctionDeclarations": false, + "CSSFunctionDescriptors": false, + "CSSFunctionRule": false, + "CSSGroupingRule": false, + "CSSImageValue": false, + "CSSImportRule": false, + "CSSKeyframeRule": false, + "CSSKeyframesRule": false, + "CSSKeywordValue": false, + "CSSLayerBlockRule": false, + "CSSLayerStatementRule": false, + "CSSMarginRule": false, + "CSSMathClamp": false, + "CSSMathInvert": false, + "CSSMathMax": false, + "CSSMathMin": false, + "CSSMathNegate": false, + "CSSMathProduct": false, + "CSSMathSum": false, + "CSSMathValue": false, + "CSSMatrixComponent": false, + "CSSMediaRule": false, + "CSSNamespaceRule": false, + "CSSNestedDeclarations": false, + "CSSNumericArray": false, + "CSSNumericValue": false, + "CSSPageDescriptors": false, + "CSSPageRule": false, + "CSSPerspective": false, + "CSSPositionTryDescriptors": false, + "CSSPositionTryRule": false, + "CSSPositionValue": false, + "CSSPropertyRule": false, + "CSSRotate": false, + "CSSRule": false, + "CSSRuleList": false, + "CSSScale": false, + "CSSScopeRule": false, + "CSSSkew": false, + "CSSSkewX": false, + "CSSSkewY": false, + "CSSStartingStyleRule": false, + "CSSStyleDeclaration": false, + "CSSStyleRule": false, + "CSSStyleSheet": false, + "CSSStyleValue": false, + "CSSSupportsRule": false, + "CSSTransformComponent": false, + "CSSTransformValue": false, + "CSSTransition": false, + "CSSTranslate": false, + "CSSUnitValue": false, + "CSSUnparsedValue": false, + "CSSVariableReferenceValue": false, + "CSSViewTransitionRule": false, + "currentFrame": false, + "currentTime": false, + "CustomElementRegistry": false, + "customElements": false, + "CustomEvent": false, + "CustomStateSet": false, + "DataTransfer": false, + "DataTransferItem": false, + "DataTransferItemList": false, + "DecompressionStream": false, + "DelayNode": false, + "DelegatedInkTrailPresenter": false, + "DeviceMotionEvent": false, + "DeviceMotionEventAcceleration": false, + "DeviceMotionEventRotationRate": false, + "DeviceOrientationEvent": false, + "devicePixelRatio": false, + "DevicePosture": false, + "DigitalCredential": false, + "dispatchEvent": false, + "DisposableStack": false, + "document": false, + "Document": false, + "DocumentFragment": false, + "documentPictureInPicture": false, + "DocumentPictureInPicture": false, + "DocumentPictureInPictureEvent": false, + "DocumentTimeline": false, + "DocumentType": false, + "DOMError": false, + "DOMException": false, + "DOMImplementation": false, + "DOMMatrix": false, + "DOMMatrixReadOnly": false, + "DOMParser": false, + "DOMPoint": false, + "DOMPointReadOnly": false, + "DOMQuad": false, + "DOMRect": false, + "DOMRectList": false, + "DOMRectReadOnly": false, + "DOMStringList": false, + "DOMStringMap": false, + "DOMTokenList": false, + "DragEvent": false, + "DynamicsCompressorNode": false, + "EditContext": false, + "Element": false, + "ElementInternals": false, + "EncodedAudioChunk": false, + "EncodedVideoChunk": false, + "ErrorEvent": false, + "event": false, + "Event": false, + "EventCounts": false, + "EventSource": false, + "EventTarget": false, + "external": false, + "External": false, + "EyeDropper": false, + "FeaturePolicy": false, + "FederatedCredential": false, + "fence": false, + "Fence": false, + "FencedFrameConfig": false, + "fetch": false, + "fetchLater": false, + "FetchLaterResult": false, + "File": false, + "FileList": false, + "FileReader": false, + "FileSystem": false, "FileSystemDirectoryEntry": false, "FileSystemDirectoryHandle": false, "FileSystemDirectoryReader": false, @@ -57012,14 +58649,1676 @@ var foo = window.Intl; new foo; "XRWebGLLayer": false, "XSLTProcessor": false } - }, + }, + "errors": [ + { + "messageId": "unexpectedRefCall", + "data": { + "name": "foo", + "ref": "Intl" + } + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-obj-calls > invalid + +```js +var x = globalThis?.Reflect(); +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 2020 + }, + "errors": [ + { + "messageId": "unexpectedCall", + "data": { + "name": "Reflect" + } + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-obj-calls > invalid + +```js +var x = (globalThis?.Reflect)(); +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 2020 + }, + "errors": [ + { + "messageId": "unexpectedCall", + "data": { + "name": "Reflect" + } + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +### `no-object-constructor` + +Pass: 55 / 56 (98.2%) +Fail: 1 / 56 (1.8%) +Skip: 0 / 56 (0.0%) + +#### no-object-constructor > valid + +```js +new Object() +``` + +```json +{ + "languageOptions": { + "globals": { + "Object": "off" + } + } +} +``` + +AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ + { + ruleId: 'rule-to-test/no-object-constructor', + message: 'The object literal notation {} is preferable.', + messageId: 'preferLiteral', + severity: 1, + nodeType: 'NewExpression', + line: 1, + column: 0, + endLine: 1, + endColumn: 12, + suggestions: null + } +] + +1 !== 0 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertValidTestCasePasses (apps/oxlint/dist/index.js) + at runValidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +### `no-promise-executor-return` + +Pass: 66 / 124 (53.2%) +Fail: 58 / 124 (46.8%) +Skip: 0 / 124 (0.0%) + +#### no-promise-executor-return > invalid + +```js +new Promise(function (resolve, reject) { return 1; }) +``` + +```json +{ + "errors": [ + { + "message": "Return values from promise executor functions cannot be read.", + "column": 42, + "endColumn": 51, + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise((resolve, reject) => resolve(1)) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "message": "Return values from promise executor functions cannot be read.", + "column": 34, + "endColumn": 44, + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise((resolve, reject) => void resolve(1))" + }, + { + "messageId": "wrapBraces", + "output": "new Promise((resolve, reject) => {resolve(1)})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise((resolve, reject) => { return 1 }) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "message": "Return values from promise executor functions cannot be read.", + "column": 36, + "endColumn": 44, + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise((resolve, reject) => { return void 1 })" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => 1) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r => void 1)" + }, + { + "messageId": "wrapBraces", + "output": "new Promise(r => {1})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => 1 ? 2 : 3) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r => void (1 ? 2 : 3))" + }, + { + "messageId": "wrapBraces", + "output": "new Promise(r => {1 ? 2 : 3})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => (1 ? 2 : 3)) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r => void (1 ? 2 : 3))" + }, + { + "messageId": "wrapBraces", + "output": "new Promise(r => {(1 ? 2 : 3)})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => (1)) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r => void (1))" + }, + { + "messageId": "wrapBraces", + "output": "new Promise(r => {(1)})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => () => {}) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r => void (() => {}))" + }, + { + "messageId": "wrapBraces", + "output": "new Promise(r => {() => {}})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => null) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r => void null)" + }, + { + "messageId": "wrapBraces", + "output": "new Promise(r => {null})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => null) +``` + +```json +{ + "options": [ + { + "allowVoid": false + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "new Promise(r => {null})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => /*hi*/ ~0) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r => /*hi*/ void ~0)" + }, + { + "messageId": "wrapBraces", + "output": "new Promise(r => /*hi*/ {~0})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => /*hi*/ ~0) +``` + +```json +{ + "options": [ + { + "allowVoid": false + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "new Promise(r => /*hi*/ {~0})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => { return 0 }) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r => { return void 0 })" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => { return 0 }) +``` + +```json +{ + "options": [ + { + "allowVoid": false + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => { if (foo) { return void 0 } return 0 }) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r => { if (foo) { return void 0 } return void 0 })" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(resolve => { return (foo = resolve(1)); }) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(resolve => { return void (foo = resolve(1)); })" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(resolve => r = resolve) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(resolve => void (r = resolve))" + }, + { + "messageId": "wrapBraces", + "output": "new Promise(resolve => {r = resolve})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => { return(1) }) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r => { return void (1) })" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r =>1) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r =>void 1)" + }, + { + "messageId": "wrapBraces", + "output": "new Promise(r =>{1})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(r => ((1))) +``` + +```json +{ + "options": [ + { + "allowVoid": true + } + ], + "errors": [ + { + "messageId": "returnsValue", + "suggestions": [ + { + "messageId": "prependVoid", + "output": "new Promise(r => void ((1)))" + }, + { + "messageId": "wrapBraces", + "output": "new Promise(r => {((1))})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(function foo(resolve, reject) { return 1; }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise((resolve, reject) => { return 1; }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(function (resolve, reject) { return undefined; }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise((resolve, reject) => { return null; }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(function (resolve, reject) { return false; }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise((resolve, reject) => resolve) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 34, + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "new Promise((resolve, reject) => {resolve})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise((resolve, reject) => null) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 34, + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "new Promise((resolve, reject) => {null})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(function (resolve, reject) { return resolve(foo); }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise((resolve, reject) => { return reject(foo); }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise((resolve, reject) => x + y) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 34, + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "new Promise((resolve, reject) => {x + y})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise((resolve, reject) => { return Promise.resolve(42); }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(function (resolve, reject) { if (foo) { return 1; } }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise((resolve, reject) => { try { return 1; } catch(e) {} }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(function (resolve, reject) { while (foo){ if (bar) break; else return 1; } }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(() => { return void 1; }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(() => (1)) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 20, + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "new Promise(() => {(1)})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +() => new Promise(() => ({})); +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 26, + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "() => new Promise(() => {({})});" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(function () { return 1; }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(() => { return 1; }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(() => 1) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 19, + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "new Promise(() => {1})" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +function foo() {} new Promise(function () { return 1; }); +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 45, + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +function foo() { return; } new Promise(() => { return 1; }); +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 48, + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +function foo() { return 1; } new Promise(() => { return 2; }); +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 50, + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +function foo () { return new Promise(function () { return 1; }); } +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 52, + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +function foo() { return new Promise(() => { bar(() => { return 1; }); return false; }); } +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 71, + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +() => new Promise(() => { if (foo) { return 0; } else bar(() => { return 1; }); }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 38, + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +function foo () { return 1; return new Promise(function () { return 2; }); return 3;} +``` + +```json +{ "errors": [ { - "messageId": "unexpectedRefCall", - "data": { - "name": "foo", - "ref": "Intl" - } + "messageId": "returnsValue", + "column": 62, + "suggestions": null } ] } @@ -57035,23 +60334,19 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] at apps/oxlint/dist/index.js -#### no-obj-calls > invalid +#### no-promise-executor-return > invalid ```js -var x = globalThis?.Reflect(); +() => 1; new Promise(() => { return 1; }) ``` ```json { - "languageOptions": { - "ecmaVersion": 2020 - }, "errors": [ { - "messageId": "unexpectedCall", - "data": { - "name": "Reflect" - } + "messageId": "returnsValue", + "column": 30, + "suggestions": null } ] } @@ -57067,23 +60362,149 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] at apps/oxlint/dist/index.js -#### no-obj-calls > invalid +#### no-promise-executor-return > invalid ```js -var x = (globalThis?.Reflect)(); +new Promise(function () { return 1; }); function foo() { return 1; } +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 27, + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +() => new Promise(() => { return 1; }); +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 27, + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +() => new Promise(() => 1); +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 25, + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "() => new Promise(() => {1});" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +() => new Promise(() => () => 1); +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 25, + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "() => new Promise(() => {() => 1});" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +() => new Promise(() => async () => 1); ``` ```json { "languageOptions": { - "ecmaVersion": 2020 + "ecmaVersion": 2017 }, "errors": [ { - "messageId": "unexpectedCall", - "data": { - "name": "Reflect" - } + "messageId": "returnsValue", + "column": 25, + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "() => new Promise(() => {async () => 1});" + } + ] } ] } @@ -57099,48 +60520,151 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] at apps/oxlint/dist/index.js -### `no-object-constructor` +#### no-promise-executor-return > invalid -Pass: 55 / 56 (98.2%) -Fail: 1 / 56 (1.8%) -Skip: 0 / 56 (0.0%) +```js +() => new Promise(() => function () {}); +``` -#### no-object-constructor > valid +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 25, + "suggestions": [] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid ```js -new Object() +() => new Promise(() => function foo() {}); ``` ```json { - "languageOptions": { - "globals": { - "Object": "off" + "errors": [ + { + "messageId": "returnsValue", + "column": 25, + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "() => new Promise(() => {function foo() {}});" + } + ] } - } + ] } ``` -AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ - { - ruleId: 'rule-to-test/no-object-constructor', - message: 'The object literal notation {} is preferable.', - messageId: 'preferLiteral', - severity: 1, - nodeType: 'NewExpression', - line: 1, - column: 0, - endLine: 1, - endColumn: 12, - suggestions: null - } -] +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] -1 !== 0 +0 !== 1 at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) - at assertValidTestCasePasses (apps/oxlint/dist/index.js) - at runValidTestCase (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +() => new Promise(() => []); +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "column": 25, + "suggestions": [ + { + "messageId": "wrapBraces", + "output": "() => new Promise(() => {[]});" + } + ] + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise((Promise) => { return 1; }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-promise-executor-return > invalid + +```js +new Promise(function Promise(resolve, reject) { return 1; }) +``` + +```json +{ + "errors": [ + { + "messageId": "returnsValue", + "suggestions": null + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) at apps/oxlint/dist/index.js @@ -95406,66 +98930,229 @@ a(); var a=function() {}; ```json { "options": [ - "nofunc" - ], - "errors": [ - { - "messageId": "usedBeforeDefined", - "data": { - "name": "a" - } - } - ] -} -``` - -AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] - -0 !== 1 - - at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) - at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) - at runInvalidTestCase (apps/oxlint/dist/index.js) - at apps/oxlint/dist/index.js - - -#### no-use-before-define > invalid - -```js -"use strict"; a(); { function a() {} } -``` - -```json -{ - "errors": [ + "nofunc" + ], + "errors": [ + { + "messageId": "usedBeforeDefined", + "data": { + "name": "a" + } + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-use-before-define > invalid + +```js +"use strict"; a(); { function a() {} } +``` + +```json +{ + "errors": [ + { + "messageId": "usedBeforeDefined", + "data": { + "name": "a" + } + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-use-before-define > invalid + +```js +a(); try { throw new Error() } catch (foo) {var a;} +``` + +```json +{ + "errors": [ + { + "messageId": "usedBeforeDefined", + "data": { + "name": "a" + } + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-use-before-define > invalid + +```js +var f = () => a; var a; +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6 + }, + "errors": [ + { + "messageId": "usedBeforeDefined", + "data": { + "name": "a" + } + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-use-before-define > invalid + +```js +new A(); var A = class {}; +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6 + }, + "errors": [ + { + "messageId": "usedBeforeDefined", + "data": { + "name": "A" + } + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-use-before-define > invalid + +```js +function foo() { new A(); } var A = class {}; +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6 + }, + "errors": [ + { + "messageId": "usedBeforeDefined", + "data": { + "name": "A" + } + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-use-before-define > invalid + +```js +a++; { var a; } +``` + +```json +{ + "languageOptions": { + "ecmaVersion": 6 + }, + "errors": [ + { + "messageId": "usedBeforeDefined", + "data": { + "name": "a" + } + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] + +0 !== 1 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + +#### no-use-before-define > invalid + +```js +a(); var a=function() {}; +``` + +```json +{ + "options": [ { - "messageId": "usedBeforeDefined", - "data": { - "name": "a" - } + "functions": false, + "classes": false } - ] -} -``` - -AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] - -0 !== 1 - - at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) - at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) - at runInvalidTestCase (apps/oxlint/dist/index.js) - at apps/oxlint/dist/index.js - - -#### no-use-before-define > invalid - -```js -a(); try { throw new Error() } catch (foo) {var a;} -``` - -```json -{ + ], "errors": [ { "messageId": "usedBeforeDefined", @@ -95490,43 +99177,16 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] #### no-use-before-define > invalid ```js -var f = () => a; var a; +new A(); var A = class {}; ``` ```json { - "languageOptions": { - "ecmaVersion": 6 - }, - "errors": [ + "options": [ { - "messageId": "usedBeforeDefined", - "data": { - "name": "a" - } + "classes": false } - ] -} -``` - -AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] - -0 !== 1 - - at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) - at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) - at runInvalidTestCase (apps/oxlint/dist/index.js) - at apps/oxlint/dist/index.js - - -#### no-use-before-define > invalid - -```js -new A(); var A = class {}; -``` - -```json -{ + ], "languageOptions": { "ecmaVersion": 6 }, @@ -95559,38 +99219,11 @@ function foo() { new A(); } var A = class {}; ```json { - "languageOptions": { - "ecmaVersion": 6 - }, - "errors": [ + "options": [ { - "messageId": "usedBeforeDefined", - "data": { - "name": "A" - } + "classes": false } - ] -} -``` - -AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] - -0 !== 1 - - at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) - at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) - at runInvalidTestCase (apps/oxlint/dist/index.js) - at apps/oxlint/dist/index.js - - -#### no-use-before-define > invalid - -```js -a++; { var a; } -``` - -```json -{ + ], "languageOptions": { "ecmaVersion": 6 }, @@ -95598,7 +99231,7 @@ a++; { var a; } { "messageId": "usedBeforeDefined", "data": { - "name": "a" + "name": "A" } } ] @@ -95618,17 +99251,11 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] #### no-use-before-define > invalid ```js -a(); var a=function() {}; +var a = a; ``` ```json { - "options": [ - { - "functions": false, - "classes": false - } - ], "errors": [ { "messageId": "usedBeforeDefined", @@ -95653,16 +99280,11 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] #### no-use-before-define > invalid ```js -new A(); var A = class {}; +var {a = a} = []; ``` ```json { - "options": [ - { - "classes": false - } - ], "languageOptions": { "ecmaVersion": 6 }, @@ -95670,7 +99292,7 @@ new A(); var A = class {}; { "messageId": "usedBeforeDefined", "data": { - "name": "A" + "name": "a" } } ] @@ -95690,48 +99312,14 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] #### no-use-before-define > invalid ```js -function foo() { new A(); } var A = class {}; +var [a = a] = []; ``` ```json { - "options": [ - { - "classes": false - } - ], "languageOptions": { "ecmaVersion": 6 }, - "errors": [ - { - "messageId": "usedBeforeDefined", - "data": { - "name": "A" - } - } - ] -} -``` - -AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] - -0 !== 1 - - at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) - at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) - at runInvalidTestCase (apps/oxlint/dist/index.js) - at apps/oxlint/dist/index.js - - -#### no-use-before-define > invalid - -```js -var a = a; -``` - -```json -{ "errors": [ { "messageId": "usedBeforeDefined", @@ -95756,7 +99344,7 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] #### no-use-before-define > invalid ```js -var {a = a} = []; +var {b = a, a} = {}; ``` ```json @@ -95788,7 +99376,7 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] #### no-use-before-define > invalid ```js -var [a = a] = []; +var [b = a, a] = {}; ``` ```json @@ -95820,7 +99408,7 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] #### no-use-before-define > invalid ```js -var {b = a, a} = {}; +var {a = 0} = a; ``` ```json @@ -95852,7 +99440,7 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] #### no-use-before-define > invalid ```js -var [b = a, a] = {}; +var [a = 0] = a; ``` ```json @@ -95884,14 +99472,11 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] #### no-use-before-define > invalid ```js -var {a = 0} = a; +for (var a in a) {} ``` ```json { - "languageOptions": { - "ecmaVersion": 6 - }, "errors": [ { "messageId": "usedBeforeDefined", @@ -95916,7 +99501,7 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] #### no-use-before-define > invalid ```js -var [a = 0] = a; +for (var a of a) {} ``` ```json @@ -95948,16 +99533,21 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] #### no-use-before-define > invalid ```js -for (var a in a) {} +foo; var foo; ``` ```json { + "options": [ + { + "variables": false + } + ], "errors": [ { "messageId": "usedBeforeDefined", "data": { - "name": "a" + "name": "foo" } } ] @@ -95974,69 +99564,86 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] at apps/oxlint/dist/index.js -#### no-use-before-define > invalid +### `no-useless-assignment` + +Pass: 83 / 85 (97.6%) +Fail: 2 / 85 (2.4%) +Skip: 0 / 85 (0.0%) + +#### no-useless-assignment > valid ```js -for (var a of a) {} +/* exported foo */ + let foo = 'used'; + console.log(foo); + foo = 'unused like but exported with directive'; ``` ```json { "languageOptions": { - "ecmaVersion": 6 - }, - "errors": [ - { - "messageId": "usedBeforeDefined", - "data": { - "name": "a" - } - } - ] + "sourceType": "script" + } } ``` -AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] +AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ + { + ruleId: 'rule-to-test/no-useless-assignment', + message: 'This assigned value is not used in subsequent statements.', + messageId: 'unnecessaryAssignment', + severity: 1, + nodeType: 'Identifier', + line: 4, + column: 12, + endLine: 4, + endColumn: 15, + suggestions: null + } +] -0 !== 1 +1 !== 0 at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) - at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) - at runInvalidTestCase (apps/oxlint/dist/index.js) + at assertValidTestCasePasses (apps/oxlint/dist/index.js) + at runValidTestCase (apps/oxlint/dist/index.js) at apps/oxlint/dist/index.js -#### no-use-before-define > invalid +#### no-useless-assignment > valid ```js -foo; var foo; +/*eslint test/use-a:1*/ + let a = 'used'; + console.log(a); + a = 'unused like but marked by markVariableAsUsed()'; + ``` ```json -{ - "options": [ - { - "variables": false - } - ], - "errors": [ - { - "messageId": "usedBeforeDefined", - "data": { - "name": "foo" - } - } - ] -} +{} ``` -AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] +AssertionError [ERR_ASSERTION]: Should have no errors but had 1: [ + { + ruleId: 'rule-to-test/no-useless-assignment', + message: 'This assigned value is not used in subsequent statements.', + messageId: 'unnecessaryAssignment', + severity: 1, + nodeType: 'Identifier', + line: 4, + column: 8, + endLine: 4, + endColumn: 9, + suggestions: null + } +] -0 !== 1 +1 !== 0 at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) - at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) - at runInvalidTestCase (apps/oxlint/dist/index.js) + at assertValidTestCasePasses (apps/oxlint/dist/index.js) + at runValidTestCase (apps/oxlint/dist/index.js) at apps/oxlint/dist/index.js @@ -97735,6 +101342,67 @@ AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] at apps/oxlint/dist/index.js +### `require-atomic-updates` + +Pass: 62 / 63 (98.4%) +Fail: 1 / 63 (1.6%) +Skip: 0 / 63 (0.0%) + +#### require-atomic-updates > invalid + +```js + + async () => { + opts.spec = process.stdin; + try { + const { exit_code } = await run(opts); + process.exitCode = exit_code; + } catch (e) { + process.exitCode = 1; + } + }; + +``` + +```json +{ + "languageOptions": { + "sourceType": "commonjs", + "globals": { + "process": "readonly" + } + }, + "errors": [ + { + "messageId": "nonAtomicObjectUpdate", + "data": { + "value": "process.exitCode", + "object": "process" + }, + "line": 6 + }, + { + "messageId": "nonAtomicObjectUpdate", + "data": { + "value": "process.exitCode", + "object": "process" + }, + "line": 8 + } + ] +} +``` + +AssertionError [ERR_ASSERTION]: Should have 2 errors but had 0: [] + +0 !== 2 + + at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) + at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) + at runInvalidTestCase (apps/oxlint/dist/index.js) + at apps/oxlint/dist/index.js + + ### `require-unicode-regexp` Pass: 76 / 79 (96.2%) diff --git a/apps/oxlint/conformance/src/filter.ts b/apps/oxlint/conformance/src/filter.ts index 9e1ca05e56ee0..1ac7483cb1520 100644 --- a/apps/oxlint/conformance/src/filter.ts +++ b/apps/oxlint/conformance/src/filter.ts @@ -10,21 +10,4 @@ export const FILTER_ONLY_RULE: Filter | null = null; export const FILTER_ONLY_CODE: Filter | null = null; // Filter out rules where test failures are expected -export const FILTER_EXCLUDE_RULE: Filter | null = [ - // Rules which use CFG - which we don't support yet - "array-callback-return", - "complexity", - "consistent-return", - "constructor-super", - "getter-return", - "no-constructor-return", - "no-fallthrough", - "no-invalid-this", - "no-promise-executor-return", - "no-this-before-super", - "no-unreachable-loop", - "no-unreachable", - "no-useless-assignment", - "no-useless-return", - "require-atomic-updates", -]; +export const FILTER_EXCLUDE_RULE: Filter | null = []; diff --git a/apps/oxlint/package.json b/apps/oxlint/package.json index f4d62ea0bf214..f70dace972e75 100644 --- a/apps/oxlint/package.json +++ b/apps/oxlint/package.json @@ -24,6 +24,7 @@ }, "devDependencies": { "@arethetypeswrong/core": "catalog:", + "@eslint/plugin-kit": "^0.5.0", "@napi-rs/cli": "catalog:", "@types/esquery": "^1.5.4", "@types/estree": "^1.0.8", diff --git a/apps/oxlint/src-js/generated/type_ids.ts b/apps/oxlint/src-js/generated/type_ids.ts index 0fa46b5f8fcf1..724762967fba5 100644 --- a/apps/oxlint/src-js/generated/type_ids.ts +++ b/apps/oxlint/src-js/generated/type_ids.ts @@ -168,6 +168,13 @@ export const NODE_TYPE_IDS_MAP = new Map([ ["TSTypeQuery", 162], ["TSTypeReference", 163], ["TSUnionType", 164], + ["onCodePathStart", 165], + ["onCodePathEnd", 166], + ["onCodePathSegmentStart", 167], + ["onCodePathSegmentEnd", 168], + ["onUnreachableCodePathSegmentStart", 169], + ["onUnreachableCodePathSegmentEnd", 170], + ["onCodePathSegmentLoop", 171], ]); /** Count of all node types (both leaf and non-leaf nodes) */ @@ -176,6 +183,9 @@ export const NODE_TYPES_COUNT = 165; /** Count of leaf node types */ export const LEAF_NODE_TYPES_COUNT = 27; +/** Total count of node types and CFG events */ +export const TYPE_IDS_COUNT = 172; + /** Type IDs which match `:statement` selector class */ export const STATEMENT_NODE_TYPE_IDS = [ 0, 1, 35, 36, 41, 44, 46, 47, 48, 49, 51, 52, 53, 54, 55, 58, 60, 65, 78, 83, 86, 87, 91, 93, 94, diff --git a/apps/oxlint/src-js/plugins/cfg.ts b/apps/oxlint/src-js/plugins/cfg.ts new file mode 100644 index 0000000000000..0a7f0b9a8d468 --- /dev/null +++ b/apps/oxlint/src-js/plugins/cfg.ts @@ -0,0 +1,229 @@ +/* + * CFG (control flow graph) aka Code Path Analysis (what ESLint calls it). + * + * Function to construct CFG, and walk AST and call visitors for CFG events. + */ + +// @ts-expect-error - internal module of ESLint with no types +import CodePathAnalyzer from "../../node_modules/eslint/lib/linter/code-path-analysis/code-path-analyzer.js"; +// @ts-expect-error - internal module of ESLint with no types +import Traverser from "../../node_modules/eslint/lib/shared/traverser.js"; + +import { VisitNodeStep, CallMethodStep } from "@eslint/plugin-kit"; +import visitorKeys from "../generated/keys.ts"; +import { LEAF_NODE_TYPES_COUNT, NODE_TYPE_IDS_MAP } from "../generated/type_ids.ts"; +import { ancestors } from "../generated/walk.js"; +import { debugAssert, typeAssertIs } from "../utils/asserts.ts"; + +import type { EnterExit, VisitFn } from "./visitor.ts"; +import type { Node, Program } from "../generated/types.d.ts"; +import type { CompiledVisitors } from "../generated/walk.js"; + +/** + * Step to walk AST. + */ +type Step = VisitNodeStep | CallMethodStep; + +const STEP_KIND_VISIT = 1; + +const STEP_PHASE_ENTER = 1; +const STEP_PHASE_EXIT = 2; + +// Array of steps to walk AST. +// Singleton array which is re-used for each walk, and emptied after each walk. +const steps: Step[] = []; + +/** + * Reset state for walking AST with CFG. + * + * If walking AST completes without error, `walkProgramWithCfg` will reset the state itself. + * So it's only necessary to call this function if an error occurs during AST walking. + */ +export function resetCfgWalk(): void { + steps.length = 0; +} + +/** + * Walk AST with CFG (control flow graph) events. + * + * Use this function to walk AST instead of `walkProgram`, when visitor listens for CFG events. + * + * It's much slower than `walkProgram`, so prefer `walkProgram` unless visitor includes handlers for CFG events. + * + * It walks the whole AST twice: + * + * 1. First time to build the CFG graph. + * In this first pass, it builds a list of steps to walk AST (including visiting nodes and CFG events). + * This list is stored in `steps` array. + * + * 2. Visit AST with provided visitor. + * Run through the steps, in order, calling visit functions for each step. + * + * TODO: This is copied from ESLint and is not very efficient. We could improve its performance in many ways. + * See TODO comments in the code below for some ideas for optimization. + * + * @param ast - AST + * @param visitors - Visitors array + */ +export function walkProgramWithCfg(ast: Program, visitors: CompiledVisitors): void { + // Get the steps that need to be run to walk the AST + prepareSteps(ast); + + // Walk the AST + const stepsLen = steps.length; + debugAssert(stepsLen > 0, "`steps` should not be empty"); + + for (let i = 0; i < stepsLen; i++) { + const step = steps[i]; + if (step.kind === STEP_KIND_VISIT) { + const node = step.target as Node; + + if (step.phase === STEP_PHASE_ENTER) { + // Enter node - can be leaf or non-leaf node + const typeId = NODE_TYPE_IDS_MAP.get(node.type)!; + const visit = visitors[typeId]; + if (typeId < LEAF_NODE_TYPES_COUNT) { + // Leaf node + if (visit !== null) { + typeAssertIs(visit); + visit(node); + } + // Don't add node to `ancestors`, because we don't visit them on exit + } else { + // Non-leaf node + if (visit !== null) { + typeAssertIs(visit); + const { enter } = visit; + if (enter !== null) enter(node); + } + + ancestors.unshift(node); + } + } else { + // Exit non-leaf node + ancestors.shift(); + + const typeId = NODE_TYPE_IDS_MAP.get(node.type)!; + const enterExit = visitors[typeId]; + if (enterExit !== null) { + typeAssertIs(enterExit); + const { exit } = enterExit; + if (exit !== null) exit(node); + } + } + } else { + const eventId = NODE_TYPE_IDS_MAP.get(step.target)!; + const visit = visitors[eventId]; + if (visit !== null) { + (visit as any).apply(undefined, step.args); + } + } + } + + // Reset `steps` array + steps.length = 0; +} + +/** + * Walk AST and put a list of all steps to walk AST into `steps` array. + * @param ast - AST + */ +function prepareSteps(ast: Program) { + debugAssert(steps.length === 0, "`steps` should be empty at start of `prepareSteps`"); + + // Length of `steps` array after entering each node. + // Used in debug build to check that no leaf nodes emit CFG events (see below). + // Minifier removes this var in release build. + let stepsLenAfterEnter = 0; + + // Create `CodePathAnalyzer`. + // It stores steps to walk AST. + // + // This is really inefficient code. + // We could improve it in several ways (in ascending order of complexity): + // + // * Get rid of the bloated `VisitNodeStep` and `CallMethodStep` classes. Just use plain objects. + // * Combine `step.kind` and `step.phase` into a single `step.type` property. + // * Reduce object creation by storing steps as 2 arrays (struct of arrays pattern): + // * Array 1: Step type (number). + // * Array 2: Step data - AST node object for enter/exit node steps, args for CFG events. + // * Alternatively, use a single array containing step objects as now, but recycle the objects + // (SoA option is probably better). + // * Avoid repeated conversions from `type` (string) to `typeId` (number) when iterating through steps. + // * Generate separate `enterNode` / `exitNode` functions for each node type. + // * Set them on `analyzer.original` before calling `analyzer.enterNode` / `analyzer.exitNode`. + // * These functions would know the type ID of the node already, and then could store type ID in steps. + // * When iterating through steps, use that type ID instead of converting `node.type` to `typeId` every time. + // * Copy `CodePathAnalyzer` code into this repo and rewrite it to work entirely with type IDs instead of strings. + // + // TODO: Apply these optimizations (or at least some of them). + const analyzer = new CodePathAnalyzer({ + enterNode(node: Node) { + steps.push( + new VisitNodeStep({ + target: node, + phase: STEP_PHASE_ENTER, + args: [node], + }), + ); + + if (DEBUG) stepsLenAfterEnter = steps.length; + }, + + leaveNode(node: Node) { + const typeId = NODE_TYPE_IDS_MAP.get(node.type)!; + + if (typeId >= LEAF_NODE_TYPES_COUNT) { + // Non-leaf node + steps.push( + new VisitNodeStep({ + target: node, + phase: STEP_PHASE_EXIT, + args: [node], + }), + ); + } else { + // Leaf node. + // Don't add a step. + + // In debug build, check that no CFG events were emitted between entering and exiting this leaf node. + // If they were, it would break our assumptions. + // We combine enter and exit visit functions for leaf nodes into a single function which runs on entering node. + // That's fine if there are no CFG events emitted between entering and exiting node. + // But if CFG events were emitted between entering node and exiting node, then the order the rule's + // visit functions are called in would be wrong. + // `exit` visit fn would be called before the CFG event handlers, instead of after. + if (DEBUG && steps.length !== stepsLenAfterEnter) { + const eventNames = steps.slice(stepsLenAfterEnter).map((step) => step.target) as string[]; + throw new Error( + `CFG events emitted during visiting leaf node \`${node.type}\`: ${eventNames.join(", ")}`, + ); + } + } + }, + + emit(eventName: string, args: any[]) { + steps.push( + new CallMethodStep({ + target: eventName, + args, + }), + ); + }, + }); + + // Walk AST passing enter and exit event to the `CodePathAnalyzer` + // + // TODO: Use a faster walker. + // Could use our own `walkProgram`, though that builds `ancestors` array unnecessarily, which is probably slow. + // Would be better to generate a separate walker for this purpose. + Traverser.traverse(ast, { + enter(node: Node) { + analyzer.enterNode(node); + }, + leave(node: Node) { + analyzer.leaveNode(node); + }, + visitorKeys, + }); +} diff --git a/apps/oxlint/src-js/plugins/lint.ts b/apps/oxlint/src-js/plugins/lint.ts index c319e85269f00..5c7e3ee15ea19 100644 --- a/apps/oxlint/src-js/plugins/lint.ts +++ b/apps/oxlint/src-js/plugins/lint.ts @@ -1,3 +1,4 @@ +import { walkProgramWithCfg, resetCfgWalk } from "./cfg.ts"; import { setupFileContext, resetFileContext } from "./context.ts"; import { registeredRules } from "./load.ts"; import { allOptions, DEFAULT_OPTIONS_ID } from "./options.ts"; @@ -13,6 +14,8 @@ import { compiledVisitor, finalizeCompiledVisitor, initCompiledVisitor, + VISITOR_EMPTY, + VISITOR_CFG, } from "./visitor.ts"; // Lazy implementation @@ -200,19 +203,23 @@ export function lintFileImpl( addVisitorToCompiled(visitor); } - const needsVisit = finalizeCompiledVisitor(); + const visitorState = finalizeCompiledVisitor(); // Visit AST. // Skip this if no visitors visit any nodes. // Some rules seen in the wild return an empty visitor object from `create` if some initial check fails // e.g. file extension is not one the rule acts on. - if (needsVisit) { + if (visitorState !== VISITOR_EMPTY) { if (ast === null) initAst(); debugAssertIsNonNull(ast); debugAssert(ancestors.length === 0, "`ancestors` should be empty before walking AST"); - walkProgram(ast, compiledVisitor); + if (visitorState === VISITOR_CFG) { + walkProgramWithCfg(ast, compiledVisitor); + } else { + walkProgram(ast, compiledVisitor); + } debugAssert(ancestors.length === 0, "`ancestors` should be empty after walking AST"); @@ -262,4 +269,5 @@ export function resetStateAfterError() { diagnostics.length = 0; ancestors.length = 0; resetFile(); + resetCfgWalk(); } diff --git a/apps/oxlint/src-js/plugins/selector.ts b/apps/oxlint/src-js/plugins/selector.ts index 630de5bfccde2..0a632b53296e2 100644 --- a/apps/oxlint/src-js/plugins/selector.ts +++ b/apps/oxlint/src-js/plugins/selector.ts @@ -7,6 +7,7 @@ import { EXPRESSION_NODE_TYPE_IDS, FUNCTION_NODE_TYPE_IDS, NODE_TYPE_IDS_MAP, + NODE_TYPES_COUNT, } from "../generated/type_ids.ts"; import { ancestors } from "../generated/walk.js"; import { debugAssert, typeAssertIs } from "../utils/asserts.ts"; @@ -234,7 +235,8 @@ function analyzeSelector( // If the type is invalid, just treat this selector as not matching any types. // But still increment identifier count. // This matches ESLint's behavior. - return typeId === undefined ? EMPTY_TYPE_IDS_ARRAY : [typeId]; + // Ignore when `typeId >= NODE_TYPES_COUNT` - those are names of CFG events. + return typeId === undefined || typeId >= NODE_TYPES_COUNT ? EMPTY_TYPE_IDS_ARRAY : [typeId]; } case "not": diff --git a/apps/oxlint/src-js/plugins/visitor.ts b/apps/oxlint/src-js/plugins/visitor.ts index 54564a42c77a2..ad7d4799c29fa 100644 --- a/apps/oxlint/src-js/plugins/visitor.ts +++ b/apps/oxlint/src-js/plugins/visitor.ts @@ -82,6 +82,7 @@ import { LEAF_NODE_TYPES_COUNT, NODE_TYPE_IDS_MAP, NODE_TYPES_COUNT, + TYPE_IDS_COUNT, } from "../generated/type_ids.ts"; import { parseSelector, @@ -126,21 +127,40 @@ interface CompilingNonLeafVisitorEntry { exit: VisitProp[]; } +// Visitor state. +// Returned by `finalizeCompiledVisitor`. +// This a "poor man's enum", which compiles down better than TS enums. +export type VisitorState = 0 | 1 | 2; + +export const VISITOR_EMPTY = 0; // Empty visitor (no need to walk AST) +export const VISITOR_NOT_EMPTY = 1; // Not empty visitor (need to walk AST) +export const VISITOR_CFG = 2; // Not empty visitor, and contains CFG event listeners (need to construct CFG) + +// Count of non-leaf node types +const NON_LEAF_NODE_TYPES_COUNT = NODE_TYPES_COUNT - LEAF_NODE_TYPES_COUNT; +// Count of CFG event types +const CFG_EVENTS_COUNT = TYPE_IDS_COUNT - NODE_TYPES_COUNT; + // During compilation, arrays of visitor props are stored in these arrays. // These arrays are initialized with empty arrays, and never modified thereafter. // Only the arrays they contain are modified - they're filled up during compilation, // and emptied at the end in `finalizeCompiledVisitor`, so can be reused for next compilation. const compilingLeafVisitor: VisitProp[][] = []; const compilingNonLeafVisitor: CompilingNonLeafVisitorEntry[] = []; +const compilingCfgVisitor: VisitProp[][] = []; for (let i = LEAF_NODE_TYPES_COUNT; i !== 0; i--) { compilingLeafVisitor.push([]); } -for (let i = NODE_TYPES_COUNT - LEAF_NODE_TYPES_COUNT; i !== 0; i--) { +for (let i = NON_LEAF_NODE_TYPES_COUNT; i !== 0; i--) { compilingNonLeafVisitor.push({ enter: [], exit: [] }); } +for (let i = CFG_EVENTS_COUNT; i !== 0; i--) { + compilingCfgVisitor.push([]); +} + // Compiled visitor used for visiting each file. // // * `VisitFn | null` for leaf nodes. @@ -154,7 +174,7 @@ for (let i = NODE_TYPES_COUNT - LEAF_NODE_TYPES_COUNT; i !== 0; i--) { // https://v8.dev/blog/elements-kinds export const compiledVisitor: (VisitFn | EnterExit | null)[] = []; -for (let i = NODE_TYPES_COUNT; i !== 0; i--) { +for (let i = TYPE_IDS_COUNT; i !== 0; i--) { compiledVisitor.push(null); } @@ -164,18 +184,24 @@ for (let i = NODE_TYPES_COUNT; i !== 0; i--) { // 1. These arrays never need to grow. // 2. V8 treats these arrays as "PACKED_SMI_ELEMENTS". const activeLeafVisitorTypeIds: number[] = [], - activeNonLeafVisitorTypeIds: number[] = []; + activeNonLeafVisitorTypeIds: number[] = [], + activeCfgVisitorTypeIds: number[] = []; for (let i = LEAF_NODE_TYPES_COUNT; i !== 0; i--) { activeLeafVisitorTypeIds.push(0); } -for (let i = NODE_TYPES_COUNT - LEAF_NODE_TYPES_COUNT; i !== 0; i--) { +for (let i = NON_LEAF_NODE_TYPES_COUNT; i !== 0; i--) { activeNonLeafVisitorTypeIds.push(0); } +for (let i = CFG_EVENTS_COUNT; i !== 0; i--) { + activeCfgVisitorTypeIds.push(0); +} + activeLeafVisitorTypeIds.length = 0; activeNonLeafVisitorTypeIds.length = 0; +activeCfgVisitorTypeIds.length = 0; // `true` if `addVisitor` has been called with a visitor which visits at least one AST type let hasActiveVisitors = false; @@ -205,7 +231,7 @@ let visitPropsCacheNextIndex = 0; */ export function initCompiledVisitor(): void { // Reset `compiledVisitor` array after previous compilation - for (let i = 0; i < NODE_TYPES_COUNT; i++) { + for (let i = 0; i < TYPE_IDS_COUNT; i++) { compiledVisitor[i] = null; } @@ -277,7 +303,15 @@ export function addVisitorToCompiled(visitor: Visitor): void { // Single type visit function e.g. `Program`. // Add a single identifier to `specificity`. Use `|=` to keep exit flag. visitProp.specificity |= IDENTIFIER_COUNT_INCREMENT; - addVisitFn(typeId, visitProp, isExit); + + if (typeId < LEAF_NODE_TYPES_COUNT) { + addLeafVisitFn(typeId, visitProp); + } else if (typeId < NODE_TYPES_COUNT) { + addNonLeafVisitFn(typeId, visitProp, isExit); + } else { + addCfgVisitFn(typeId, visitProp, isExit); + } + continue; } @@ -302,7 +336,13 @@ export function addVisitorToCompiled(visitor: Visitor): void { // Note: If `typeIds` is empty, `visitProp` will not be used. // We could return it to the cache, but this should be a very rare case, so don't bother. for (let i = 0, len = typeIds.length; i < len; i++) { - addVisitFn(typeIds[i], visitProp, isExit); + const typeId = typeIds[i]; + // `typeId` can't refer to a CFG event + if (typeId < LEAF_NODE_TYPES_COUNT) { + addLeafVisitFn(typeId, visitProp); + } else { + addNonLeafVisitFn(typeId, visitProp, isExit); + } } continue; } @@ -318,20 +358,6 @@ export function addVisitorToCompiled(visitor: Visitor): void { } } -/** - * Add visit function to compiled visitor. - * @param typeId - Node type ID - * @param visitProp - Visitor property - * @param isExit - `true` if is an exit visit fn - */ -function addVisitFn(typeId: number, visitProp: VisitProp, isExit: boolean): void { - if (typeId < LEAF_NODE_TYPES_COUNT) { - addLeafVisitFn(typeId, visitProp); - } else { - addNonLeafVisitFn(typeId, visitProp, isExit); - } -} - /** * Add visit function for a leaf node to compiled visitor. * @@ -368,6 +394,23 @@ function addNonLeafVisitFn(typeId: number, visitProp: VisitProp, isExit: boolean } } +/** + * Add visit function for a CFG event to compiled visitor. + * + * Stored as just 1 function, not enter+exit pair. + * + * @param typeId - Node type ID + * @param visitProp - Visitor property + * @param isExit - `true` if is an exit visit fn + */ +function addCfgVisitFn(typeId: number, visitProp: VisitProp, isExit: boolean): void { + if (isExit) throw new Error(`Invalid visitor key: \`${visitProp.selectorStr}:exit\``); + + const visitProps = compilingCfgVisitor[typeId - NODE_TYPES_COUNT]!; + if (visitProps.length === 0) activeCfgVisitorTypeIds.push(typeId); + visitProps.push(visitProp); +} + /** * Finalize compiled visitor. * @@ -375,8 +418,8 @@ function addNonLeafVisitFn(typeId: number, visitProp: VisitProp, isExit: boolean * * @returns - `true` if compiled visitor visits at least 1 AST type */ -export function finalizeCompiledVisitor(): boolean { - if (hasActiveVisitors === false) return false; +export function finalizeCompiledVisitor(): VisitorState { + if (hasActiveVisitors === false) return VISITOR_EMPTY; // Merge visitors for leaf nodes for (let i = activeLeafVisitorTypeIds.length - 1; i >= 0; i--) { @@ -411,6 +454,21 @@ export function finalizeCompiledVisitor(): boolean { compiledVisitor[typeId] = enterExit; } + // Merge visitors for CFG events + let visitState: VisitorState = VISITOR_NOT_EMPTY; + + if (activeCfgVisitorTypeIds.length > 0) { + visitState = VISITOR_CFG; + + for (let i = activeCfgVisitorTypeIds.length - 1; i >= 0; i--) { + const typeId = activeCfgVisitorTypeIds[i]!; + compiledVisitor[typeId] = mergeVisitFns(compilingCfgVisitor[typeId - NODE_TYPES_COUNT]!); + } + + // Reset state, ready for next time + activeCfgVisitorTypeIds.length = 0; + } + // Reset `visitPropsCache`. // Setting these properties to `null` is not necessary for correctness, but it allows them to be garbage collected. for (let i = visitPropsCacheNextIndex - 1; i >= 0; i--) { @@ -425,7 +483,7 @@ export function finalizeCompiledVisitor(): boolean { hasActiveVisitors = false; - return true; + return visitState; } // Array used by `mergeVisitFns` to store visit functions extracted from an array of `VisitProp`s. diff --git a/apps/oxlint/test/compile_visitor.test.ts b/apps/oxlint/test/compile_visitor.test.ts index 699563812dcad..a67129852e16b 100644 --- a/apps/oxlint/test/compile_visitor.test.ts +++ b/apps/oxlint/test/compile_visitor.test.ts @@ -1,12 +1,18 @@ // oxlint-disable jest/no-conditional-expect import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { LEAF_NODE_TYPES_COUNT, NODE_TYPE_IDS_MAP } from "../src-js/generated/type_ids.ts"; +import { + NODE_TYPES_COUNT, + LEAF_NODE_TYPES_COUNT, + NODE_TYPE_IDS_MAP, +} from "../src-js/generated/type_ids.ts"; import { addVisitorToCompiled, compiledVisitor, finalizeCompiledVisitor, initCompiledVisitor, + VISITOR_EMPTY, + VISITOR_NOT_EMPTY, } from "../src-js/plugins/visitor.ts"; import type { Mock } from "vitest"; @@ -21,6 +27,8 @@ const PROGRAM_TYPE_ID = NODE_TYPE_IDS_MAP.get("Program")!, FUNC_EXPR_TYPE_ID = NODE_TYPE_IDS_MAP.get("FunctionExpression")!, ARROW_FUNC_TYPE_ID = NODE_TYPE_IDS_MAP.get("ArrowFunctionExpression")!; +// TODO: Add tests for CFG events + const SPAN: Node = { start: 0, end: 0, @@ -61,14 +69,14 @@ describe("compile visitor", () => { it("for leaf node", () => { const enter = () => {}; addVisitorToCompiled({ EmptyStatement: enter }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); expect(compiledVisitor[EMPTY_STMT_TYPE_ID]).toBe(enter); }); it("for non-leaf node", () => { const enter = () => {}; addVisitorToCompiled({ Program: enter }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const enterExit = compiledVisitor[PROGRAM_TYPE_ID] as EnterExit; expect(enterExit).toEqual({ enter, exit: null }); @@ -80,14 +88,14 @@ describe("compile visitor", () => { it("for leaf node", () => { const exit = () => {}; addVisitorToCompiled({ "EmptyStatement:exit": exit }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); expect(compiledVisitor[EMPTY_STMT_TYPE_ID]).toBe(exit); }); it("for non-leaf node", () => { const exit = () => {}; addVisitorToCompiled({ "Program:exit": exit }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const enterExit = compiledVisitor[PROGRAM_TYPE_ID] as EnterExit; expect(enterExit).toEqual({ enter: null, exit }); @@ -101,7 +109,7 @@ describe("compile visitor", () => { const enter = vi.fn(() => {}); const exit = vi.fn(() => {}); addVisitorToCompiled({ EmptyStatement: enter, "EmptyStatement:exit": exit }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const node = { type: "EmptyStatement", ...SPAN }; (compiledVisitor[EMPTY_STMT_TYPE_ID] as VisitFn)(node); @@ -114,7 +122,7 @@ describe("compile visitor", () => { const enter = vi.fn(() => {}); const exit = vi.fn(() => {}); addVisitorToCompiled({ "EmptyStatement:exit": exit, EmptyStatement: enter }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const node = { type: "EmptyStatement", ...SPAN }; (compiledVisitor[EMPTY_STMT_TYPE_ID] as VisitFn)(node); @@ -129,7 +137,7 @@ describe("compile visitor", () => { const enter = () => {}; const exit = () => {}; addVisitorToCompiled({ Program: enter, "Program:exit": exit }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const enterExit = compiledVisitor[PROGRAM_TYPE_ID] as EnterExit; expect(enterExit).toEqual({ enter, exit }); @@ -141,7 +149,7 @@ describe("compile visitor", () => { const enter = () => {}; const exit = () => {}; addVisitorToCompiled({ "Program:exit": exit, Program: enter }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const enterExit = compiledVisitor[PROGRAM_TYPE_ID] as EnterExit; expect(enterExit).toEqual({ enter, exit }); @@ -162,7 +170,7 @@ describe("compile visitor", () => { const exit2 = vi.fn(() => {}); addVisitorToCompiled({ EmptyStatement: enter2, "EmptyStatement:exit": exit2 }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const node = { type: "EmptyStatement", ...SPAN }; (compiledVisitor[EMPTY_STMT_TYPE_ID] as VisitFn)(node); @@ -184,7 +192,7 @@ describe("compile visitor", () => { const exit2 = vi.fn(() => {}); addVisitorToCompiled({ "EmptyStatement:exit": exit2, EmptyStatement: enter2 }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const node = { type: "EmptyStatement", ...SPAN }; (compiledVisitor[EMPTY_STMT_TYPE_ID] as VisitFn)(node); @@ -206,7 +214,7 @@ describe("compile visitor", () => { const exit2 = vi.fn(() => {}); addVisitorToCompiled({ "EmptyStatement:exit": exit2, EmptyStatement: enter2 }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const node = { type: "EmptyStatement", ...SPAN }; (compiledVisitor[EMPTY_STMT_TYPE_ID] as VisitFn)(node); @@ -228,7 +236,7 @@ describe("compile visitor", () => { const exit2 = vi.fn(() => {}); addVisitorToCompiled({ EmptyStatement: enter2, "EmptyStatement:exit": exit2 }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const node = { type: "EmptyStatement", ...SPAN }; (compiledVisitor[EMPTY_STMT_TYPE_ID] as VisitFn)(node); @@ -252,7 +260,7 @@ describe("compile visitor", () => { const exit2 = vi.fn(() => {}); addVisitorToCompiled({ Program: enter2, "Program:exit": exit2 }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const enterExit = compiledVisitor[PROGRAM_TYPE_ID] as EnterExit; @@ -276,7 +284,7 @@ describe("compile visitor", () => { const exit2 = vi.fn(() => {}); addVisitorToCompiled({ "Program:exit": exit2, Program: enter2 }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const enterExit = compiledVisitor[PROGRAM_TYPE_ID] as EnterExit; @@ -300,7 +308,7 @@ describe("compile visitor", () => { const exit2 = vi.fn(() => {}); addVisitorToCompiled({ "Program:exit": exit2, Program: enter2 }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const enterExit = compiledVisitor[PROGRAM_TYPE_ID] as EnterExit; @@ -324,7 +332,7 @@ describe("compile visitor", () => { const exit2 = vi.fn(() => {}); addVisitorToCompiled({ Program: enter2, "Program:exit": exit2 }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const enterExit = compiledVisitor[PROGRAM_TYPE_ID] as EnterExit; @@ -365,7 +373,7 @@ describe("compile visitor", () => { const exit6 = vi.fn(() => {}); addVisitorToCompiled({ EmptyStatement: enter6, "EmptyStatement:exit": exit6 }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const node = { type: "EmptyStatement", ...SPAN }; (compiledVisitor[EMPTY_STMT_TYPE_ID] as VisitFn)(node); @@ -402,9 +410,11 @@ describe("compile visitor", () => { const exit = vi.fn(() => {}); addVisitorToCompiled({ "*": enter, "*:exit": exit }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); for (const [typeName, typeId] of NODE_TYPE_IDS_MAP) { + if (typeId >= NODE_TYPES_COUNT) continue; // Skip CFG events + if (typeId < LEAF_NODE_TYPES_COUNT) { const node = { type: typeName, ...SPAN }; (compiledVisitor[typeId] as VisitFn)(node); @@ -427,7 +437,7 @@ describe("compile visitor", () => { ":matches(Program, EmptyStatement, EmptyStatement):exit": exit, }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const enterExit = compiledVisitor[PROGRAM_TYPE_ID] as EnterExit; expect(enterExit.enter).toBe(enter); @@ -452,7 +462,7 @@ describe("compile visitor", () => { ":matches(Program, EmptyStatement[type]):exit": exit, }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const enterExit = compiledVisitor[PROGRAM_TYPE_ID] as EnterExit; expect(enterExit.enter).not.toBe(enter); @@ -485,9 +495,10 @@ describe("compile visitor", () => { "[name=foo]:exit": exit, }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); - for (const typeId of NODE_TYPE_IDS_MAP.values()) { + // Skip CFG events + for (let typeId = 0; typeId < NODE_TYPES_COUNT; typeId++) { if (typeId < LEAF_NODE_TYPES_COUNT) { expect(compiledVisitor[typeId]).toBeTypeOf("function"); } else { @@ -541,7 +552,7 @@ describe("compile visitor", () => { "Identifier[name=foo]:exit": exit, }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const identEnterExit = compiledVisitor[IDENTIFIER_TYPE_ID] as EnterExit; expect(identEnterExit.enter).toBeTypeOf("function"); @@ -615,9 +626,11 @@ describe("compile visitor", () => { ":function:exit": exitFunction, }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); for (const [typeName, typeId] of NODE_TYPE_IDS_MAP.entries()) { + if (typeId >= NODE_TYPES_COUNT) continue; // Skip CFG events + // Check that compiled visitor is set up correctly // Get classes that this node type matches @@ -768,7 +781,7 @@ describe("compile visitor", () => { ":FunCtioN:exit": exit2, }); - expect(finalizeCompiledVisitor()).toBe(true); + expect(finalizeCompiledVisitor()).toBe(VISITOR_NOT_EMPTY); const funcDeclEnterExit = compiledVisitor[FUNC_DECL_TYPE_ID] as EnterExit; expect(funcDeclEnterExit.enter).toBeTypeOf("function"); @@ -831,19 +844,19 @@ describe("compile visitor", () => { describe("`finalizeCompiledVisitor` returns false if all visitors empty", () => { it("no visitors", () => { - expect(finalizeCompiledVisitor()).toBe(false); + expect(finalizeCompiledVisitor()).toBe(VISITOR_EMPTY); }); it("1 visitor", () => { addVisitorToCompiled({}); - expect(finalizeCompiledVisitor()).toBe(false); + expect(finalizeCompiledVisitor()).toBe(VISITOR_EMPTY); }); it("multiple visitors", () => { addVisitorToCompiled({}); addVisitorToCompiled({}); addVisitorToCompiled({}); - expect(finalizeCompiledVisitor()).toBe(false); + expect(finalizeCompiledVisitor()).toBe(VISITOR_EMPTY); }); }); }); diff --git a/apps/oxlint/test/fixtures/cfg/.oxlintrc.json b/apps/oxlint/test/fixtures/cfg/.oxlintrc.json new file mode 100644 index 0000000000000..76b546efca906 --- /dev/null +++ b/apps/oxlint/test/fixtures/cfg/.oxlintrc.json @@ -0,0 +1,7 @@ +{ + "jsPlugins": ["./plugin.ts"], + "categories": { "correctness": "off" }, + "rules": { + "error-plugin/error": "error" + } +} diff --git a/apps/oxlint/test/fixtures/cfg/files/index.js b/apps/oxlint/test/fixtures/cfg/files/index.js new file mode 100644 index 0000000000000..1fa180e56531d --- /dev/null +++ b/apps/oxlint/test/fixtures/cfg/files/index.js @@ -0,0 +1 @@ +while (true) {} diff --git a/apps/oxlint/test/fixtures/cfg/options.json b/apps/oxlint/test/fixtures/cfg/options.json new file mode 100644 index 0000000000000..c6d966f1b525b --- /dev/null +++ b/apps/oxlint/test/fixtures/cfg/options.json @@ -0,0 +1,3 @@ +{ + "singleThread": true +} diff --git a/apps/oxlint/test/fixtures/cfg/output.snap.md b/apps/oxlint/test/fixtures/cfg/output.snap.md new file mode 100644 index 0000000000000..746534df0cdaa --- /dev/null +++ b/apps/oxlint/test/fixtures/cfg/output.snap.md @@ -0,0 +1,31 @@ +# Exit code +1 + +# stdout +``` + x error-plugin(error): Visited nodes: + | * onCodePathStart Program + | * onCodePathSegmentStart Program + | * onCodePathSegmentEnd Literal + | * onCodePathSegmentStart Literal + | * onCodePathSegmentEnd BlockStatement + | * onCodePathSegmentStart BlockStatement + | * onCodePathSegmentLoop WhileStatement + | * onCodePathSegmentEnd WhileStatement + | * onUnreachableCodePathSegmentStart WhileStatement + | * onUnreachableCodePathSegmentEnd Program + | * onCodePathEnd Program + ,-[files/index.js:1:1] + 1 | while (true) {} + : ^^^^^^^^^^^^^^^^ + `---- + +Found 0 warnings and 1 error. +Finished in Xms on 1 file using X threads. +``` + +# stderr +``` +WARNING: JS plugins are experimental and not subject to semver. +Breaking changes are possible while JS plugins support is under development. +``` diff --git a/apps/oxlint/test/fixtures/cfg/plugin.ts b/apps/oxlint/test/fixtures/cfg/plugin.ts new file mode 100644 index 0000000000000..e1fbe60f2b9ff --- /dev/null +++ b/apps/oxlint/test/fixtures/cfg/plugin.ts @@ -0,0 +1,56 @@ +import type { Plugin, Rule, ESTree } from "#oxlint"; + +type Node = ESTree.Node; + +// The output of this test looked wrong to me (@overlookmotel). +// `onCodePathSegmentEnd` gets called before `onCodePathSegmentStart` for `VariableDeclaration`. +// But have run the same test in ESLint, and it produces exactly the same output. Weird! + +const rule: Rule = { + // @ts-expect-error - TODO: Make the types for CFG events work + create(context) { + const events: [string, string][] = []; + + return { + onCodePathStart(codePath: any, node: Node) { + events.push(["onCodePathStart", node.type]); + }, + onCodePathEnd(codePath: any, node: Node) { + events.push(["onCodePathEnd", node.type]); + + if (node.type === "Program") { + context.report({ + message: `Visited nodes:\n* ${events.map(([eventName, type]) => `${eventName.padEnd(35)} ${type}`).join("\n* ")}`, + node, + }); + } + }, + onCodePathSegmentStart(segment: any, node: Node) { + events.push(["onCodePathSegmentStart", node.type]); + }, + onCodePathSegmentEnd(segment: any, node: Node) { + events.push(["onCodePathSegmentEnd", node.type]); + }, + onUnreachableCodePathSegmentStart(segment: any, node: Node) { + events.push(["onUnreachableCodePathSegmentStart", node.type]); + }, + onUnreachableCodePathSegmentEnd(segment: any, node: Node) { + events.push(["onUnreachableCodePathSegmentEnd", node.type]); + }, + onCodePathSegmentLoop(fromSegment: any, toSegment: any, node: Node) { + events.push(["onCodePathSegmentLoop", node.type]); + }, + }; + }, +}; + +const plugin: Plugin = { + meta: { + name: "error-plugin", + }, + rules: { + error: rule, + }, +}; + +export default plugin; diff --git a/apps/oxlint/test/fixtures/lint_visit_cfg_error/.oxlintrc.json b/apps/oxlint/test/fixtures/lint_visit_cfg_error/.oxlintrc.json new file mode 100644 index 0000000000000..76b546efca906 --- /dev/null +++ b/apps/oxlint/test/fixtures/lint_visit_cfg_error/.oxlintrc.json @@ -0,0 +1,7 @@ +{ + "jsPlugins": ["./plugin.ts"], + "categories": { "correctness": "off" }, + "rules": { + "error-plugin/error": "error" + } +} diff --git a/apps/oxlint/test/fixtures/lint_visit_cfg_error/files/1.js b/apps/oxlint/test/fixtures/lint_visit_cfg_error/files/1.js new file mode 100644 index 0000000000000..2756c24c45775 --- /dev/null +++ b/apps/oxlint/test/fixtures/lint_visit_cfg_error/files/1.js @@ -0,0 +1 @@ +let x; diff --git a/apps/oxlint/test/fixtures/lint_visit_cfg_error/files/2.js b/apps/oxlint/test/fixtures/lint_visit_cfg_error/files/2.js new file mode 100644 index 0000000000000..a5c1e6463879f --- /dev/null +++ b/apps/oxlint/test/fixtures/lint_visit_cfg_error/files/2.js @@ -0,0 +1 @@ +let y; diff --git a/apps/oxlint/test/fixtures/lint_visit_cfg_error/options.json b/apps/oxlint/test/fixtures/lint_visit_cfg_error/options.json new file mode 100644 index 0000000000000..c6d966f1b525b --- /dev/null +++ b/apps/oxlint/test/fixtures/lint_visit_cfg_error/options.json @@ -0,0 +1,3 @@ +{ + "singleThread": true +} diff --git a/apps/oxlint/test/fixtures/lint_visit_cfg_error/output.snap.md b/apps/oxlint/test/fixtures/lint_visit_cfg_error/output.snap.md new file mode 100644 index 0000000000000..942cb6210e42c --- /dev/null +++ b/apps/oxlint/test/fixtures/lint_visit_cfg_error/output.snap.md @@ -0,0 +1,31 @@ +# Exit code +1 + +# stdout +``` + x Error running JS plugin. + | File path: /files/1.js + | Error: Identifier in 1st file: x + | at Identifier (/plugin.ts:43:32) + + x error-plugin(error): onCodePathStart: Program + ,-[files/2.js:1:1] + 1 | let y; + : ^^^^^^^ + `---- + + x error-plugin(error): Identifier in 2nd file: y + ,-[files/2.js:1:5] + 1 | let y; + : ^ + `---- + +Found 0 warnings and 3 errors. +Finished in Xms on 2 files using X threads. +``` + +# stderr +``` +WARNING: JS plugins are experimental and not subject to semver. +Breaking changes are possible while JS plugins support is under development. +``` diff --git a/apps/oxlint/test/fixtures/lint_visit_cfg_error/plugin.ts b/apps/oxlint/test/fixtures/lint_visit_cfg_error/plugin.ts new file mode 100644 index 0000000000000..0d248ffb22296 --- /dev/null +++ b/apps/oxlint/test/fixtures/lint_visit_cfg_error/plugin.ts @@ -0,0 +1,69 @@ +import assert from "node:assert"; + +import type { Plugin, Rule, ESTree } from "#oxlint"; + +type Node = ESTree.Node; + +// Aim of this test is: +// +// 1. Check that errors thrown during AST visitation are handled correctly and shown to user as diagnostics. +// 2. Check that global state is reset after an error during visiting a file, so it's in correct initial state +// when Oxlint starts linting the next file. +// +// The 2nd is tricky to test because usually the order Oxlint lints files in is non-deterministic. +// To make this test deterministic, we run it with `oxlint --threads 1` +// (`options.json` file for this fixture contains `"singleThread": true`). +// This guarantees that `1.js` is linted before `2.js`. +// +// This rule throws an error during AST visitation when linting 1st file. If global state is not reset properly +// before linting 2nd file, debug assertions will throw an error on 2nd file. +// +// In particular, we want to check that `steps` used when creating CFG is cleared after an error while visiting a file. +// If `steps` is cleared after that error, then `onCodePathStart` visitor will be called only once. +// If it's not cleared then we'll get extra calls to `Identifier` and `onCodePathStart` visitors, +// because the steps from the 1st file are replayed again for the 2nd file. +// +// Actually `debugAssert(steps.length === 0)` at start of `prepareSteps` in `src-js/plugins/cfg.ts` should +// throw in this case before the AST even gets walked, but we have 2 ways to spot this error. + +let fileIndex = 0; + +const rule: Rule = { + // @ts-expect-error - TODO: Make the types for CFG events work + create(context) { + const isFirstFileLinted = fileIndex === 0; + fileIndex++; + + // Check the order files get linted in is what we expect + const isFirstFile = context.filename.endsWith("1.js"); + assert(isFirstFile === isFirstFileLinted); + + return { + Identifier(node) { + if (isFirstFile) throw new Error(`Identifier in 1st file: ${node.name}`); + + context.report({ + message: `Identifier in 2nd file: ${node.name}`, + node, + }); + }, + onCodePathStart(codePath: any, node: Node) { + context.report({ + message: `onCodePathStart: ${node.type}`, + node, + }); + }, + }; + }, +}; + +const plugin: Plugin = { + meta: { + name: "error-plugin", + }, + rules: { + error: rule, + }, +}; + +export default plugin; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a87ec2850a91b..2de98b10ca566 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -95,6 +95,9 @@ importers: '@arethetypeswrong/core': specifier: 'catalog:' version: 0.18.2 + '@eslint/plugin-kit': + specifier: ^0.5.0 + version: 0.5.0 '@napi-rs/cli': specifier: 'catalog:' version: 3.5.0(@emnapi/runtime@1.7.1)(@types/node@24.1.0) @@ -1002,6 +1005,10 @@ packages: resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/core@1.0.0': + resolution: {integrity: sha512-PRfWP+8FOldvbApr6xL7mNCw4cJcSTq4GA7tYbgq15mRb0kWKO/wEB2jr+uwjFH3sZvEZneZyCUGTxsv4Sahyw==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@eslint/eslintrc@3.3.3': resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1018,6 +1025,10 @@ packages: resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@eslint/plugin-kit@0.5.0': + resolution: {integrity: sha512-rSXBsAcmx80jI9OUevyNBU0f5pZRQJkNmk4bLX6hCbm1qKe5Z/TcU7vwXc2nR8814mhRlgbZIHL1+HSiYS0VkQ==} + engines: {node: ^20.19.0 || ^22.13.0 || >=24} + '@humanfs/core@0.19.1': resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} engines: {node: '>=18.18.0'} @@ -6056,6 +6067,10 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 + '@eslint/core@1.0.0': + dependencies: + '@types/json-schema': 7.0.15 + '@eslint/eslintrc@3.3.3': dependencies: ajv: 6.12.6 @@ -6079,6 +6094,11 @@ snapshots: '@eslint/core': 0.15.2 levn: 0.4.1 + '@eslint/plugin-kit@0.5.0': + dependencies: + '@eslint/core': 1.0.0 + levn: 0.4.1 + '@humanfs/core@0.19.1': {} '@humanfs/node@0.16.7': diff --git a/tasks/ast_tools/src/generators/estree_visit.rs b/tasks/ast_tools/src/generators/estree_visit.rs index 7b14ae60825e2..5516bbf18aba4 100644 --- a/tasks/ast_tools/src/generators/estree_visit.rs +++ b/tasks/ast_tools/src/generators/estree_visit.rs @@ -436,6 +436,25 @@ fn generate(codegen: &Codegen) -> Codes { function_node_ids, ) = selector_classes.into_vecs(); + // Add CFG event names to type ID map + let cfg_event_names = [ + "onCodePathStart", + "onCodePathEnd", + "onCodePathSegmentStart", + "onCodePathSegmentEnd", + "onUnreachableCodePathSegmentStart", + "onUnreachableCodePathSegmentEnd", + "onCodePathSegmentLoop", + ]; + + type_ids_map.push_str("/* IF LINTER */ // CFG selectors\n"); + let mut event_id = nodes_count; + for event_name in cfg_event_names { + write_it!(type_ids_map, "[\"{event_name}\", {event_id}],\n"); + event_id += 1; + } + type_ids_map.push_str("/* END_IF */\n"); + #[rustfmt::skip] write_it!(type_ids_map, " ]); @@ -448,6 +467,9 @@ fn generate(codegen: &Codegen) -> Codes { /* IF LINTER */ + /** Total count of node types and CFG events */ + export const TYPE_IDS_COUNT = {event_id}; + /** Type IDs which match `:statement` selector class */ export const STATEMENT_NODE_TYPE_IDS = {statement_node_ids:?};