7

Well, there is not really much to explain. https://jsbin.com/raqajelufu/edit?html,js,output Illegal invocation exception is raised on any File object property access after being copied with angular.copy.

Is there any workaround, which would make watching for File object possible, considering $watch is using angular.copy internally according to https://docs.angularjs.org/api/ng/type/$rootScope.Scope?

4
  • Have you tried with $watch or only calling copy explicitly as in your example? You can probably work around it by providing a destination to copy, as the problem seems to be when it tries to create one internally using Object.create(...), though I don't personally know how to workaround if you get the error with $watch when it calls copy itself.. Commented Jul 22, 2015 at 18:12
  • I think your problem isn't with copying but with instantiation, see stackoverflow.com/questions/8390855/… Commented Jul 22, 2015 at 18:43
  • 1
    Calling var f = new File([],"") and then f.name does not yield an error, so I still think the problem is with copying Commented Jul 22, 2015 at 19:15
  • @aw04, yes $watch throws that error as well. Here is an example to show that jsbin.com/gatumewuwa/edit?html,js,output Commented Jul 23, 2015 at 7:10

1 Answer 1

3

Which browser(s) are you seeing the issue on?

A similar question was asked a while ago which concluded that it could have to do with Chrome v43.

Some resources related to the issue:

Supposedly, Chrome v43 does not like the following in the angular.copy source:

var emptyObject = Object.create(Object.getPrototypeOf(source));

You could try any of the following to see if it suppresses your errors (regardless of your browser of choice):

  • Dont use angular.copy, by avoiding deep watches a la $scope.$watch('', fn, true)(jsbin) and go for something like _.cloneDeep(jsbin) from lodash when you need to make a deep copy of something.
  • Step back to Chrome v42 (if you are on v43).
  • Step back to Angular 1.2.28 where angular.copy does not call the above line. source (jsbin)

If you want to watch deeply but avoid angular.copy, I would do something like this (with the help of lodash.merge):

$scope.$watch(function () {
  return _.merge(src, dest);
}, callback);

yet another jsbin

That way you wouldn't call angular.copy and you would still have a 'deep watch' setup. Bare in mind, this is a very naive example and I have not tested it thoroughly but I think you could make it work very similarly to an angular deep watch with minimal effort.


Disclaimer: I haven't really dug that deep into what is actually going on the angular.copy source, the console and/or Chrome v43. It is somewhat of a gray area, but with the above suggestion(s) I have yet to trigger an Illegal Invocation.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.