Why file in ClipboardEvent is not an 'instanceof File' for notes "Opened in new window"?

Hi

There is something I’m struggling to understand. Consider the following minimal plugin code:

import { Plugin } from 'obsidian'

export default class MyPlugin extends Plugin {
  onload() {
    this.registerEvent(
      this.app.workspace.on('editor-paste', (evt: ClipboardEvent) => {
        const { files } = evt.clipboardData
        console.log('Is it a `File` in your clipboard?: ' + (files[0] instanceof File)) // <--- 'false' for notes "Opened in new window"

        evt.preventDefault()
      }),
    )
  }
}

Copy something to your clipboard and try to paste it to your note. You will get an expected true unless you “Open in new window” your note. In a separate window you will get false, and I can not understand what is the difference. I console.log prototypes of the file in a normal window and “new window”, try to compare them, but do not see any difference. Both refer to some File() function which is a native code (which is expected)

This actually causes a bug in my plugin, because clipboard files which get pasted to a note in a “new window” do not pass the check for File.

What’s wrong with this “new window” or my understanding of instanceof?

It seems like the note opened in a “new window” is a separate V8 instance, which has it’s own copy of all prototypes, c-tors etc.

  • On the screenshot I try to paste an image to the main Obsidian window first to populate holderVar.
  • Then I clear the console and do one more paste in the main window.
    • The “Is c-tor same as the previous one” replies true, which is expected.
  • Then I open the same note in a “new window” and try to paste image from clipboard again.
    • It will always say that the content of your clipboard is not a File or Blob (which is not expected)
    • and the comparison of Blob c-tor in prototype chain with the one from the main windows (stored in holderVar) will reply false too (not expected too)
    • also notice that the console of the “new window” is empty, everything gets printed to the console of the main Obsidian window

How am I supposed to work with “new windows”? Should I change my file instanceof File to file.constructor.name === 'File' or is it a problem of Obsidian’s "new window"s?

We attach the current window to the evt for this reason. You should be able to do something like this:

let FileCls = evt.win.File;
if (files[0] instanceof FileCls) { ... }

The API provides an .instanceOf function for nodes and Events which abstracts the multi-window logic a bit, but that won’t work for File specifically.

2 Likes