10

Chrome complains when I try to copy inside setTimeout.

setTimeout(function () { copy('a') }, 0)

Uncaught ReferenceError: copy is not defined
    at <anonymous>:1:26

It doesn't work with the window scope as well.

setTimeout(function () { window.copy('a') }, 0)

Uncaught TypeError: window.copy is not a function

Interestingly, if I keep the reference to copy and reuse it, it works

cc = copy;
setTimeout(function () { cc('a') }, 0);

In Firefox, it doesn't throw any error, but it doesn't work even with the saved reference.

Why copy function doesn't work inside setTimeout, is it a bug?

Sanghyun Lee
  • 21,644
  • 19
  • 100
  • 126
  • https://stackoverflow.com/questions/18432072/x-function-is-not-defined-inside-a-chrome-extension-content-script/18434955 https://stackoverflow.com/questions/48934462/why-getting-uncaught-referenceerror-is-not-defined-error-on-chrome-dev-cons/48935107 – Josh Lee Feb 28 '18 at 12:11
  • Fun game: Add a Watch for `window.copy`. It's `undefined`. Now type `debugger` into the console and Watch it show up! – Josh Lee Feb 28 '18 at 12:43

2 Answers2

9

Inspired by the mention of with in this answer, I discovered that you can use it to make copy() available in setTimeout() and other callbacks, instead of having to create a global reference to it:

with ({ copy }) { setTimeout(() => copy("copied!"), 0) }

copied! will now be on your clipboard. Unfortunately, this trick doesn't seem to work in Firefox's console.

jdunning
  • 1,356
  • 1
  • 14
  • 26
  • Excellent answer! I used it inside a callback function that iterates over a the selected checkboxes and copies a list of their values to the clipboard. – marlar Nov 03 '20 at 10:55
8

copy is part of the developer tools' Command Line API and is not available outside the browser console. For example, trying to execute the command in a JavaScript file that's part of a normal web page you'd get the same error.

When you invoke the command inside the setTimeout callback, the execution context is no longer the console so copy doesn't exist anymore.

JJJ
  • 32,902
  • 20
  • 89
  • 102
  • If you like to copy DOM input element value to clipboard then you can execute copy command using this javascript code document.exeCommand("Copy") after selecting input element as mentioned in this sample code https://www.w3schools.com/howto/howto_js_copy_clipboard.asp – Raja Rathinam Feb 28 '18 at 12:20
  • But then why `console.log` is working inside `setTimeout`? – Sanghyun Lee Feb 28 '18 at 12:42
  • 1
    `console` is not exclusively a console command. It's available everywhere, `copy` is not. – JJJ Feb 28 '18 at 12:46