Search code examples
sapui5content-security-policyamdsap-fiori

How to detect `eval` calls when addressing UI5 modules at runtime?


As part of the preparation for the "Asynchronous Module Loading" enablement in FLP, one of its prerequisites is making sure that no eval call is triggered due to the HTML document being served with the response header Content-Security-Policy and its directive script-src omitting unsafe-eval.

Is there a feature in UI5 that logs all eval calls during runtime triggered by incorrectly addressed modules?


Solution

  • Resolution

    1. Open the browser console (F12) and ensure that "Warnings" logs are visible.
    2. Start the app with the UI5 config URL parameter sap-ui-xx-debugModuleLoading=true and make sure that the debug mode is not unnecessarily enabled.
    3. In the browser console, filter by "(using eval)".

    Example

    Given

    sap.ui.define([
      "sap/ui/core/mvc/Controller",
      "sap/ui/comp/library",
    ], (Controller, sapUiCompLib) => {
      // ...
      const ValueHelpRangeOperation = sapUiCompLib.valuehelpdialog.ValueHelpRangeOperation; // enum from module "sap/ui/comp/library"
      const ValueHelpDialog = sapUiCompLib.valuehelpdialog.ValueHelpDialog; // control from module "sap/ui/comp/valuehelpdialog/ValueHelpDialog"
      return Controller.extend("my.controller.MyController", {
        onSomething: function () {
          const vhDialog = new ValueHelpDialog(/*...*/);
          sap.ushell.Container/*...*/;
          // ...
        },
        // ...
      });
    });
    

    Logs

    UI5 - debugModuleLoading 'Using Eval' reports

    Solution

    Declare the missing dependency to "sap/ui/comp/valuehelpdialog/ValueHelpDialog".
    No need to declare transitive dependencies that were also logged ( : ...).

    sap.ui.define([
      "sap/ui/core/mvc/Controller",
      "sap/ui/comp/library",
      "sap/ui/comp/valuehelpdialog/ValueHelpDialog" // <-- Declare the module dependency
    ], (Controller, sapUiCompLib, ValueHelpDialog) => {
      // ...
      const ValueHelpRangeOperation = sapUiCompLib.valuehelpdialog.ValueHelpRangeOperation; // enum from module "sap/ui/comp/library"
      // const ValueHelpDialog = sapUiCompLib.valuehelpdialog.ValueHelpDialog; <-- Remove
      return Controller.extend("my.controller.MyController", {
        onSomething: function () {
          const vhDialog = new ValueHelpDialog(/*...*/);
          sap.ui.require([
            "sap/ushell/Container"
          ], Container => Container/*...*/);
          // ...
        },
        // ...
      });
    });
    

    Module name to declare as dependency can be seen in the UI5 API reference:

    Value Help Dialog API Refrence


    Other guidelines can be found in the UI5 documentation topic Best Practices for Developers.