#How would you replace `this` in the root of Window with `globalThis`?

1 messages · Page 1 of 1 (latest)

rich python
#

Dear Developers,

Thank you for the marvel!

For example, we have the following case: https://stackblitz.com/edit/vitejs-vite-ujkc7hrt?file=src%2Ftest.js&terminal=dev

As you may see, there's this that is not transpiled into globalThis on build nor dev mode, and how would you handle such a case?

Let's consider the source of this in the root of a script or Window a legacy dependency that was minified, obfuscated, and therefore, a rewrite of it may not be possible.

Best and kind regards

faint zinc
#

I think a plugin like this would be the way. I'm assuming that the code doesn't include any ESM syntax (import, export) as in that case, this should be undefined and is a bug in that code.

export default {
  plugins: [
    {
      name: 'this-as-globalThis',
      transform: {
        filter: { id: '**/test.js' },
        handler(code) {
          return '(function () {' + code + '}).call(globalThis)';
        },
      },
    },
  ],
};

https://stackblitz.com/edit/vitejs-vite-veqcqe5z?file=vite.config.js&terminal=dev

rich python
# faint zinc I think a plugin like this would be the way. I'm assuming that the code doesn't ...

Thank you very much for the response and an awesome idea, @faint zinc!

I will try now! It's a project out there with some legacy code, indeed.

The legacy script in question has some packaging leftovers it seems, yet, it seems like someone, before Vite and globalThis, just got its built and minified version and imported as raw!

Some excerpt from that script in the source that uses the root this, and we may see handles for export and AMD cases:

// ...
return this.each(function() {
            f.init.call(i, n)
        })
    }
}(jQuery, window, document),
function(t, e) {
    "use strict";
    "function" == typeof define && define.amd ? define(["jquery"], e) : "object" == typeof exports ? module.exports = e(require("jquery")) : t.bootbox = e(t.jQuery)
}(this, function t(e, n) { // <- Here
    "use strict";
    function o(t) {
        var e = m[f.locale];
        return e ? e[t] : m.en[t]
    }
    function i(t, n, o) {
        t.stopPropagation(),
        t.preventDefault();
        var i = e.isFunction(o) && o(t) === !1;
        i || n.modal("hide")
    }
    function l(t) {
// ...
faint zinc
#

That code looks like a UMD module. I'd expect the commonjs plugin + the optimizer to handle that automatically and correctly.

rich python
#

Vite Plugin

File :/resources/js/vite/plugins/thisAsGlobalThisVitePlugin.js:

import { createFilter } from '@rollup/pluginutils';

/** @typedef {import('@rollup/pluginutils').FilterPattern} FilterPattern */

/**
 * @typedef Options
 * @property {?FilterPattern} include
 * @property {?FilterPattern} exclude
 * @property {string | false | null} resolve
 *
 * @see import('@rollup/pluginutils').createFilter
 */

/**
 * Replace root `this` with `globalThis`.
 *
 * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this#global_context
 * @see https://github.com/vitejs/vite/issues/12340
 *
 * @param {Options} options
 *
 * @returns {import('vite').Plugin}
 */
export default function thisAsGlobalThisVitePlugin(options) {
    const filter = createFilter(options.include || [], options.exclude || [], {
        resolve: options.resolve || null,
    });

    return {
        name: 'this_as_globalThis',

        transform(code, id) {
            if (!filter(id)) return;

            return '(function () {' + code + '}).call(globalThis)';
        },
    };
}
#

Usage Example

File: :/vite.config.js

import path from 'path';
import { defineConfig } from 'vite';
import thisAsGlobalThisVitePlugin from './resources/js/vite/plugins/thisAsGlobalThisVitePlugin';

export default defineConfig(({ command }) => {
    // ...
    plugins: [
        thisAsGlobalThisVitePlugin({
            include: ['**/web/assets/js/legacy/test.js'],
            resolve: path.resolve(__dirname),
        }),
    ],
    // ...
});
#

@faint zinc, thank you heartfelt, and please stay astronomical and safe! sparkles_1