Errors when dynamically adding language extension.

If you add a language extension dynamically, then very time you focus in the editor, it gives an error “this is null”. However, if you add the language extension as one of the original extension, then you don’t get any error.

I noticed this error migrating from View 6.17.1 to 6.20.0 and Language 6.9.0 to 6.9.1.

Due to a build issue on my server the sandbox didn’t have @lezer/common 1.1.0, which was causing this error. In a setup with the proper dependencies installed, this works without problem.

That’s strange because in my environment I see the problem even though @lezer/common is 1.1.0. I’ll keep checking the sandbox to see if the error goes away.

The sandbox was fixed for me after I did a rebuild just now.

That’s weird. I see the same bug using the same link as before. (and I’ve cleared cache)

That is weird. That link run without errors for me. I saw the error there before. Try opening the devtools, making sure they are configured to disable cache when open, and reloading.

I was tracing the errors, and *I think* I might have found the problem (sorry I don’t know how to embed code properly):

It creates the PluginInstance here, and it creates the event handlers right below it. However, at this time, plugin.value is still null. It isn’t until afterwards that the plugin is updated for the first time and value is set.

When creating the handlers, it goes through ensureHandlers then computeHandlers then bindHandler. It passes plugin.value into bindHandler, but at this point, plugin.value is still null. bindHandler will bind the event handler to plugin.value which is null and so referring to this throws the error.

Long story short, first update the new plugins before you create the event handlers.

Question remains why I cannot reproduce this. I open your sandbox link and click the editor, and there’s no error in the console.

(The thing I saw and fixed before was probably a different error from what you are describing.)

Very strange indeed. Here’s a gif of me recreating the bug (no caching is happening according to the network tab):
codemirror_bug

I also see this bug on the website I am developing after I updated my CodeMirror packages. However, if I go into node_modules/@codemirror/view/dist/index.js and make a minor modification to updatePlugins() (by calling ensureHandlers() at the end of the function), then the error goes away:

updatePlugins(update) {
    let prevSpecs = update.startState.facet(viewPlugin), specs = update.state.facet(viewPlugin);
    if (prevSpecs != specs) {
        let newPlugins = [];
        for (let spec of specs) {
            let found = prevSpecs.indexOf(spec);
            if (found < 0) {
                const newplug = new PluginInstance(spec);
                newPlugins.push(newplug);
            }
            else {
                let plugin = this.plugins[found];
                plugin.mustUpdate = update;
                newPlugins.push(plugin);
            }
        }
        for (let plugin of this.plugins)
            if (plugin.mustUpdate != update)
                plugin.destroy(this);
        this.plugins = newPlugins;
        this.pluginMap.clear();
    }
    else {
        for (let p of this.plugins)
            p.mustUpdate = update;
    }
    for (let i = 0; i < this.plugins.length; i++)
        this.plugins[i].update(this);

    // Call ensureHandlers after updating the newly created plugins
    if (prevSpecs != specs) {
        this.inputState.ensureHandlers(this.plugins);
    }
}

Current issues aside, am I wrong to say that we should be calling ensureHandlers() after updating the plugins?

Never mind, I’m an idiot (was focusing the wrong editor). I can reproduce this very well. Attached patch should solve it.

1 Like