Update. The demo was previously broken, now it's fixed.
Let me show you;
- Take a screenshot using an utility that dumps the image directly to your clipboard, so you can paste it. Like the
PrintScreen
key on Windows/Linux orCmd+Shift+3
on macOS. - Open this up https://eivfjo.csb.app.
- Paste with
Ctrl+V
on Windows/Linux orCmd+V
on macOS. - Now copy an existing image from your computer—perhaps a screenshot saved to disk.
- Go back to the page and paste it.
- See any difference?
Here's how it worked out for me (I'm using Chrome on Windows, by the way);
- The first paste, of the screenshot just taken, took about 500ms—I'm on a 4k display, your mileage may vary.
- The second one, of a file from my computer, took 0ms.
Now I'll reveal it to you. We're doing nothing. Okay, it's not technically nothing. But we're not really doing anything useful or that should take too long for that matter.
So what gives?
Below there's the whole code you just tested. You can also check it over on CodeSandbox.
document.addEventListener("paste", (event) => {
const now = performance.now();
void event.clipboardData.files; // This line is the culprit.
document.body.textContent = `It took ${performance.now() - now}ms`;
});
If you're not familiar or need a refresher, void
simply evaluates the expression and returns undefined. That's it. We might as well omit it. I only added it for dramatic purposes. The important bit is you have to access the files
property on the clipboardData
object carried by the event.
If you're curious why that is it's because the files
array is a shim, its content is gathered in the property accessor get files()
in the DataTransfer
interface. You can read more on the spec.
The odd part is why the difference between pasting a screenshot and pasting a file.
MDN doesn't say anything. The spec has some curious bits but didn't explain it either.
My wild guess is that it isn't the browser's fault. Perhaps the underlying implementation on the OS captures the screen as a simple bitmap and then lazily encodes it to more suited format line PNG as it's read? I don't know.
It's a problem in any case because for one I can't even show the user some feedback that something's going on since event handlers block—the next frame doesn't start until it returns, so any changes to DOM, like adding a loading
class to an element, will have to wait—but it's also freezing up the whole page for that period. Yikes! :(
Any ideas?
Top comments (0)