Skip to content

Fix JavaScript Programming tab issues (#2453)#2460

Merged
sensei-hacker merged 1 commit intoiNavFlight:maintenance-9.xfrom
sensei-hacker:fix-javascript-programming-issues
Dec 6, 2025
Merged

Fix JavaScript Programming tab issues (#2453)#2460
sensei-hacker merged 1 commit intoiNavFlight:maintenance-9.xfrom
sensei-hacker:fix-javascript-programming-issues

Conversation

@sensei-hacker
Copy link
Member

@sensei-hacker sensei-hacker commented Dec 6, 2025

User description

Summary

Fixes multiple bugs in the JavaScript Programming tab reported in issue #2453.

Issues Fixed

1. IntelliSense Contamination with Browser APIs ✓

Problem: Monaco editor autocomplete was suggesting browser-only APIs like navigator, document, window which are not available in the INAV JavaScript runtime.

Solution: Configured Monaco editor TypeScript compiler to use only ES2020 core library, excluding DOM/browser APIs while preserving standard JavaScript features like Math.

Files: js/transpiler/editor/monaco_loader.js

2. Override Property Validation Errors ✓

Problem: Using override.vtx.power and other override properties caused "Cannot read properties of undefined" errors in IntelliSense.

Solution:

  • Restored override.js API definitions that were previously deleted
  • Updated all hardcoded operation numbers to use OPERATION constants from inav_constants.js
  • Added override interface to TypeScript definitions generator

Files:

  • js/transpiler/api/definitions/override.js (restored and updated)
  • js/transpiler/api/definitions/index.js
  • js/transpiler/api/types.js

3. Unsaved Changes Warning Behavior ✓

Problem:

  • Warning dialog appeared multiple times when disconnecting
  • Clicking "Cancel" didn't prevent disconnect
  • Tab switching became stuck after cancelling warning

Solution:

  • Check for unsaved changes BEFORE disconnect/tab switch begins (not during cleanup)
  • Clear isDirty flag after user confirms to prevent duplicate warnings during subsequent tab switches
  • Simplified cleanup function to only dispose editor resources

Files:

  • js/serial_backend.js - Check before disconnect
  • js/configurator_main.js - Check before tab switch
  • tabs/javascript_programming.js - Simplified cleanup

Implementation Details

Monaco Editor Configuration

lib: ['es2020']  // Only ES2020 core library (excludes DOM/browser APIs)

Override API Definitions

  • Restored from git history (commit 17b470b)
  • Updated all operations to use constants: OPERATION.OVERRIDE_THROTTLE_SCALE, etc.
  • Proper TypeScript interface generation for IntelliSense

Unsaved Changes Flow

Disconnect:

  1. User clicks disconnect → Check isDirty in serial_backend.js
  2. If dirty → Show warning
  3. If cancelled → Return early, disconnect never starts
  4. If confirmed → Clear isDirty flag, proceed with disconnect

Tab Switch:

  1. User clicks tab → Check isDirty in configurator_main.js
  2. If dirty → Show warning
  3. If cancelled → Return early, tab switch never starts
  4. If confirmed → Proceed with tab switch

Cleanup:

  • No longer shows dialogs
  • Only disposes Monaco editor resources
  • Called after user has already confirmed

Testing Performed

✅ IntelliSense no longer suggests navigator, document, window
✅ IntelliSense correctly validates override.vtx.power, override.throttle, etc.
✅ Math and standard JavaScript features still available
✅ Unsaved changes warning appears exactly once on disconnect
✅ Clicking "Cancel" prevents disconnect
✅ Unsaved changes warning appears exactly once on tab switch
✅ Clicking "Cancel" prevents tab switch
✅ Subsequent disconnect/tab switch attempts work correctly after cancel

Files Changed

  • js/transpiler/editor/monaco_loader.js - Monaco configuration
  • js/transpiler/api/definitions/override.js - Restored API definitions
  • js/transpiler/api/definitions/index.js - Export override definitions
  • js/transpiler/api/types.js - Generate override TypeScript interface
  • js/serial_backend.js - Check unsaved changes before disconnect
  • js/configurator_main.js - Check unsaved changes before tab switch
  • tabs/javascript_programming.js - Simplified cleanup function

Related Issues

Closes #2453


PR Type

Bug fix


Description

  • Fixed IntelliSense contamination by configuring Monaco editor to use ES2020 library only, excluding browser APIs

  • Restored and updated override API definitions with OPERATION constants for proper IntelliSense validation

  • Fixed unsaved changes warning behavior by checking before disconnect/tab switch, preventing duplicate dialogs

  • Simplified cleanup function to only dispose editor resources after user confirmation


Diagram Walkthrough

flowchart LR
  A["User Action<br/>Disconnect/Tab Switch"] --> B["Check isDirty<br/>in serial_backend.js<br/>or configurator_main.js"]
  B --> C{"Unsaved<br/>Changes?"}
  C -->|No| D["Proceed with Action"]
  C -->|Yes| E["Show Warning Dialog"]
  E --> F{"User<br/>Confirms?"}
  F -->|Cancel| G["Return Early<br/>Action Cancelled"]
  F -->|Confirm| H["Clear isDirty Flag"]
  H --> D
  D --> I["cleanup() Disposes<br/>Editor Resources"]
Loading

File Walkthrough

Relevant files
Bug fix
configurator_main.js
Check unsaved changes before tab switch                                   

js/configurator_main.js

  • Added check for unsaved changes in JavaScript Programming tab before
    tab switch
  • Shows confirmation dialog if isDirty flag is set
  • Returns early if user cancels, preventing tab switch
  • Logs user actions for debugging
+15/-0   
serial_backend.js
Check unsaved changes before disconnect                                   

js/serial_backend.js

  • Added check for unsaved changes in JavaScript Programming tab before
    disconnect
  • Shows confirmation dialog if isDirty flag is set
  • Returns early if user cancels, preventing disconnect
  • Clears isDirty flag after user confirms to prevent duplicate warnings
  • Logs user actions for debugging
+18/-1   
monaco_loader.js
Configure Monaco to exclude browser APIs                                 

js/transpiler/editor/monaco_loader.js

  • Added lib: ['es2020'] to Monaco compiler options
  • Restricts TypeScript library to ES2020 core only, excluding
    DOM/browser APIs
  • Prevents IntelliSense from suggesting browser-only APIs like
    navigator, document, window
  • Preserves standard JavaScript features like Math
+2/-1     
javascript_programming.js
Simplify cleanup and improve dirty tracking                           

tabs/javascript_programming.js

  • Moved dirty tracking setup to after initial load to prevent marking as
    dirty during decompilation
  • Added editor content change listener that sets isDirty flag when code
    is modified
  • Simplified cleanup function to only dispose editor resources
  • Removed unsaved changes confirmation from cleanup since it now happens
    before cleanup is called
  • Added comments explaining that unsaved changes are checked in
    serial_backend.js and configurator_main.js
+13/-11 
Enhancement
override.js
Restore and define override API operations                             

js/transpiler/api/definitions/override.js

  • Restored override API definitions file with complete writable override
    operations
  • Defined throttle control properties (throttleScale, throttle)
  • Defined VTX control nested object with power, band, channel properties
  • Defined additional overrides for arming safety, OSD layout, RC
    channel, loiter radius, and min ground speed
  • All operations reference OPERATION constants from inav_constants.js
+116/-0 
index.js
Export override API definitions                                                   

js/transpiler/api/definitions/index.js

  • Added import for restored override.js API definitions
  • Exported override in the main API definitions object
  • Removed inline comments to simplify export structure
  • Cleaned up formatting (trailing whitespace)
+5/-14   
types.js
Generate TypeScript interface for override API                     

js/transpiler/api/types.js

  • Added generation of TypeScript interface for override API definitions
  • Enables IntelliSense support for override properties in Monaco editor
  • Generates proper type definitions from override.js API definition
+1/-0     

Resolves multiple bugs in the JavaScript Programming tab mentioned in iNavFlight#2453

1. IntelliSense contamination with browser APIs
   - Configured Monaco editor to use ES2020 lib only
   - Excludes DOM/browser APIs (navigator, document, etc.)
   - Preserves Math and standard JavaScript features

2. Override property validation errors
   - Restored override.js API definitions
   - Updated to use OPERATION constants from inav_constants.js
   - Enables proper IntelliSense for override.vtx.power, etc.

3. Unsaved changes warning behavior

Implementation details:
- monaco_loader.js: Added lib: ['es2020'] to compiler options
- override.js: Restored from git history, updated with OPERATION constants
- serial_backend.js: Check isDirty before disconnect, clear flag after confirm
- configurator_main.js: Check isDirty before tab switch
- javascript_programming.js: Simplified cleanup() to only dispose editor

Testing:
- IntelliSense no longer suggests browser APIs
- Override properties validate correctly
- Unsaved changes warning shows exactly once
- Cancel properly prevents disconnect/tab switch
- Subsequent actions work correctly after cancel

Files changed:
- js/transpiler/editor/monaco_loader.js
- js/transpiler/api/definitions/override.js (restored)
- js/transpiler/api/definitions/index.js
- js/transpiler/api/types.js
- js/serial_backend.js
- js/configurator_main.js
- tabs/javascript_programming.js
@qodo-code-review
Copy link
Contributor

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
Unsafe override input

Description: The override.rcChannel function is exposed without evident input validation, which could
allow scripts to set arbitrary channel indices/values leading to unsafe behavior if not
constrained elsewhere.
override.js [83-89]

Referred Code
rcChannel: {
  type: 'function',
  desc: 'Override RC channel value. Usage: override.rcChannel(channel, value)',
  readonly: false,
  inavOperation: OPERATION.RC_CHANNEL_OVERRIDE
  // Note: This requires special handling in codegen as it takes channel number as operandA
},
Navigation prompt risks

Description: Reliance on the global confirm() for navigation gating without debouncing may enable
clickjacking-style repeated prompts; ensure dialogs are trusted UI and actions are
single-shot.
configurator_main.js [149-151]

Referred Code
if (!confirm(confirmMsg)) {
    console.log('[Tab Switch] User cancelled tab switch');
    return; // Cancel tab switch
Ticket Compliance
🟡
🎫 #2453
🟢 IntelliSense should not suggest browser-only APIs (e.g., navigator, document, window) in
the JS Programming editor.
Fix examples where override.* access throws "Cannot read properties of undefined (reading
'targets')" and ensure override.vtx.power and similar work outside only arrow functions.
🔴 Update examples to use current properties (flight.gpsNumSat -> flight.gpsSats,
waypoint.distanceToHome -> waypoint.distance).
After pressing Clear, the editor should remain usable for text input without requiring a
restart.
The unsaved changes confirmation when leaving the tab should appear exactly once when
appropriate and should prevent navigation/disconnect when cancelled.
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status:
Action not logged: Disconnect cancellation/confirmation is only sent to console and not to a structured audit
log with user, timestamp, action and outcome.

Referred Code
// Check for unsaved changes in JavaScript Programming tab
if (GUI.active_tab === 'javascript_programming' &&
    TABS.javascript_programming &&
    TABS.javascript_programming.isDirty) {
    console.log('[Disconnect] Checking for unsaved changes in JavaScript Programming tab');
    const confirmMsg = i18n.getMessage('unsavedChanges') ||
        'You have unsaved changes. Leave anyway?';

    if (!confirm(confirmMsg)) {
        console.log('[Disconnect] User cancelled disconnect due to unsaved changes');
        return; // Cancel disconnect
    }
    console.log('[Disconnect] User confirmed, proceeding with disconnect');
    // Clear isDirty flag so tab switch during disconnect doesn't show warning again
    TABS.javascript_programming.isDirty = false;
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Generic confirm: The confirm flow for unsaved changes does not handle i18n lookup failure beyond a static
fallback nor provide contextual logging of the operation, user, or state for debugging.

Referred Code
// Check for unsaved changes in current tab before switching
if (GUI.active_tab === 'javascript_programming' &&
    TABS.javascript_programming &&
    TABS.javascript_programming.isDirty) {
    console.log('[Tab Switch] Checking for unsaved changes in JavaScript Programming tab');
    const confirmMsg = i18n.getMessage('unsavedChanges') ||
        'You have unsaved changes. Leave anyway?';

    if (!confirm(confirmMsg)) {
        console.log('[Tab Switch] User cancelled tab switch');
        return; // Cancel tab switch
    }
    console.log('[Tab Switch] User confirmed tab switch');
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status:
Unstructured logs: Newly added console.log statements are unstructured and not routed through a secure
logging mechanism, reducing auditability.

Referred Code
// Set up dirty tracking AFTER initial load to avoid marking as dirty during decompilation
self.editor.onDidChangeModelContent(function() {
    if (!self.isDirty) {
        console.log('[JavaScript Programming] Editor marked as dirty (unsaved changes)');
    }
    self.isDirty = true;
});

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link
Contributor

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Prevent data loss on disconnect

Remove the GUI.active_tab === 'javascript_programming' condition when checking
for unsaved changes before a disconnect. This ensures the user is always warned
about unsaved work, regardless of the currently active tab.

js/serial_backend.js [206-221]

 // Check for unsaved changes in JavaScript Programming tab
-if (GUI.active_tab === 'javascript_programming' &&
-    TABS.javascript_programming &&
-    TABS.javascript_programming.isDirty) {
+if (TABS.javascript_programming && TABS.javascript_programming.isDirty) {
     console.log('[Disconnect] Checking for unsaved changes in JavaScript Programming tab');
     const confirmMsg = i18n.getMessage('unsavedChanges') ||
         'You have unsaved changes. Leave anyway?';
 
     if (!confirm(confirmMsg)) {
         console.log('[Disconnect] User cancelled disconnect due to unsaved changes');
         return; // Cancel disconnect
     }
     console.log('[Disconnect] User confirmed, proceeding with disconnect');
     // Clear isDirty flag so tab switch during disconnect doesn't show warning again
     TABS.javascript_programming.isDirty = false;
 }
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly identifies a potential data loss scenario where unsaved changes are ignored if the user disconnects from a different tab, making a crucial improvement to the PR's logic.

Medium
  • More

@sensei-hacker sensei-hacker merged commit f0b47a3 into iNavFlight:maintenance-9.x Dec 6, 2025
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant