function createScripts(polyfillsConfig, polyfills, entries, needsLoader) {
  /** @type {ASTNode[]} */
  const scripts = [];

  /**
   * If dynamic imports need to be polyfilled we need to feature detect them.
   * import() is not a regular function, which makes polyfilling complex.
   *
   * This script will fail on browsers which don't support dynamic imports with
   * a syntax error. On browsers which do support it, it will create a function
   * which calls native import(). Later we can check if window.importShim
   * is defined to know if it is natively supported.
   */
  if (polyfillsConfig.dynamicImport) {
    scripts.push(
      createScript(
        null,
        "window.importShim = src => import(src.startsWith('.') ? new URL(src, document.baseURI) : src)",
      ),
    );
  }

  polyfills.forEach(polyfill => {
    if (polyfill.test) {
      return;
    }

    const args = { src: `polyfills/${polyfillFilename(polyfill, polyfillsConfig)}.js` };
    if (polyfill.nomodule) {
      args.nomodule = '';
    }
    scripts.push(createScript(args));
  });

  if (!needsLoader) {
    entries.files.forEach(entry => {
      scripts.push(
        createScript({
          src: cleanImportPath(entry),
          type: entries.type === 'module' ? 'module' : undefined,
        }),
      );
    });
  }

  return scripts;
}
Creates script nodes for polyfills and entries which should be loaded on startup. For example
core-js polyfills with a 'nomodule' attribute, and the entry point if don't need to inject
a loader.

@param {PolyfillsConfig} polyfillsConfig
@param {Polyfill[]} polyfills
@param {EntriesConfig} entries
@param {boolean} needsLoader
@returns {ASTNode[]}