rbuckton / reflect-metadata

Prototype for a Metadata Reflection API for ECMAScript
https://rbuckton.github.io/reflect-metadata
Apache License 2.0
3.15k stars 180 forks source link

Exception when used in Firefox webextension content script #94

Open frankier opened 5 years ago

frankier commented 5 years ago

Using this in a Firefox webextension content script will cause an error on the 4th line of makeExporter "Not allowed to define cross-origin object as property on [Object] or [Array] XrayWrapper". The exception is not displayed by default. You can only see it if you "pause on exceptions" in the debugger.

The problem is to do with trying to install an object on window. I think it's to do with the particular pattern here. Simple patching of window should work as desired with Firefox's X-Ray vision (visible to the content script, but not with the web page). Possibly it's the use of defineProperty which causes problems?

Here's some background information: https://github.com/ricardoquesada/Spidermonkey/blob/master/js/xpconnect/wrappers/XrayWrapper.cpp https://developer.mozilla.org/en-US/docs/Mozilla/Tech/Xray_vision https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Sharing_objects_with_page_scripts https://stackoverflow.com/questions/41704263/error-not-allowed-to-define-cross-origin-object-as-property-on-object-or-arr

The specific issue here seems to relate to whether Reflect is modified on the actual window object, or whether a Sandbox object is used. It's not very well documented, but someone has tried to discover the different behaviours here: https://stackoverflow.com/questions/44671610/sandboxed-this-in-firefox-webextension-content-script

I have created a pull request with a workaround at https://github.com/rbuckton/reflect-metadata/pull/93 . This fixes it, but I'm not sure how good a solution it is.

Since it's quite a niche issue, I also tried seeing if it was possible to work around it in another way. I tried to use a shim in webpack like so:

      {
        test: require.resolve("reflect-metadata"),
        use: "imports-loader?global=>require('global-shim').global"
      }

With global-shim.js being

var global = (function(win) {
  win.__make_sandbox = true;
  return win;
})(window);
export { global };

Or

var global = (function() {
  return this !== window && this.wrappedJSObject === window.wrappedJSObject
    ? this
    : window;
}).call(window);

Neither works. Any input on this slightly mysterious issue is very welcome.

conoremclaughlin commented 3 years ago

I've run into this as well. It's particularly deadly since Firefox silently swallows the error and you can't see what stops a normal webpack bootstrap process. Compiled require statement for reflect-metadata halt the entire bootstrapping process without clear reason. Given reflect-metadata is a requirement of many TS libraries with decorators becoming increasingly popular, any help merging the above-mentioned fix into master would be enormously helpful.

Edit: I've now created my own fork that merges this PR and 1.0.13. Hope it helps someone else that bumps into this nasty bug! It includes a fix for Node environments as well. Good luck!

https://github.com/conoremclaughlin/reflect-metadata/commit/9a5223f018c7dde66278f0a30a9fb4901e7aa7d4

envil commented 1 year ago

For people who ran into this issue, I used @abraham/reflection as a replacement and it worked for me.

For it to work, instead of:

import 'reflect-metadata';

Use this instead:

import '@abraham/reflection';