twolfson / karma-electron

Karma launcher and preprocessor for Electron
The Unlicense
59 stars 21 forks source link

Uncaught TypeError: Function.prototype.toString is not generic #20

Closed GProst closed 7 years ago

GProst commented 7 years ago

Full stacktrace:

Uncaught TypeError: Function.prototype.toString is not generic
at http://localhost:9876/context.js:23

In context.js file I console.info() that function name and it shows electron's internal remoteMemberFunction function.

In my app I use electron's remote.require('moduleName') several times. I think it may be important cause remoteMemberFunction is defined in electron'srenderer/api/remote.js file.

I start karma via karma start. After replacing return obj.toString().replace(/\{[\s\S]*\}/, '{ ... }') line in content.js with return; karma seems to work fine (this is my temporal decision of solving problem).

Here is my karma.conf:

module.exports = function(config) {
  config.set({
    basePath: './',
    frameworks: ['jasmine'],

    files: [
      'app/app.js', // this is a webpack app bundle with angular.js
      'node_modules/angular-mocks/angular-mocks.js',
      'src/**/*.html',
      'src/**/*spec.js'
    ],

    client: {
      useIframe: false
    },

    exclude: [
      'src/node_modules/**/*spec.js',
      'src/node_modules/**/*.html''
    ],

    preprocessors: {
      'src/**/*.html': ['ng-html2js'],
      'app/app.js': ['electron']
    },

    ngHtml2JsPreprocessor: {
      stripPrefix: 'src/',
      moduleName: 'appTemplates'
    },

    reporters: ['progress'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    singleRun: false,
    concurrency: Infinity,

    browsers: ['Electron'],

    plugins: [
      'karma-electron',
      'karma-jasmine',
      'karma-ng-html2js-preprocessor'
    ]
  });
};

Thank you in advance!

GProst commented 7 years ago

Packages versions: electron: 1.6.2 karma: 1.5.0 karma-electron: 5.1.1 karma-jasmine: 1.1.0 karma-ng-html2js-preprocessor: 1.0.0 angular: 1.6.2 angular-mocks: 1.6.2

twolfson commented 7 years ago

Thanks for the detailed bug report. I'm not sure what would cause this so we'll definitely need to triage. I'll perform a triage by the end of the weekend

twolfson commented 7 years ago

We have successfully reproduced the error. We were able to reproduce with something as simple as:

var electron = require('electron');
console.log(electron);

My hunch is this is an issue in Karma's serializer due to Electron using some native modules but I'll keep on digging

twolfson commented 7 years ago

Okay, we've traced down the source of this issue. electron is using a Proxy constructor for its remote functions:

https://github.com/electron/electron/blob/v1.6.3/lib/renderer/api/remote.js#L170-L190

Proxies cannot be serialized without causing a TypeError:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString

new Proxy(function x () {}, {}).toString()
// VM594:1 Uncaught TypeError: Function.prototype.toString is not generic
//    at Proxy.toString (<anonymous>)
//    at <anonymous>:1:33

Unfortunately, proxies can't be detected either (due to them being proxies -- intentionally transparent). However, we can detect them having serialization issues and provide a fallback.

case 'function':
  try {
    return obj.toString().replace(/\{[\s\S]*\}/, '{ ... }')
  } catch (err) {
    if (err instanceof TypeError) {
      return 'Proxy(function ' + (obj.name || '') + '(...) { ... })';
    } else {
      throw err;
    }
  }

which yields:

Object{clipboard: Object{availableFormats: Proxy(function remoteMemberFunction(...) { ... }), has: Proxy(function remoteMemberFunction(...) { ... }), 

Our plan of action is 2 part:

new Proxy(function x () {}, {get: function () { return function () { return x.toString() }; }}).toString()
// "function x() {}"
twolfson commented 7 years ago

As a workaround for you, you should be able to use a fork of Karma with the patched serializer (which it seems you're already doing). This can be formalized by a git+ssh URL but whatever works for you :+1:

https://docs.npmjs.com/files/package.json#git-urls-as-dependencies

twolfson commented 7 years ago

Okay, 1 PR down -- Karma https://github.com/karma-runner/karma/issues/2595. 1 PR to go

twolfson commented 7 years ago

Finally got the repo locally bootstrapped. Took a lot longer than I expected because I missed the quick bootstrap notes again:

https://github.com/electron/electron/blob/v1.6.3/docs/development/build-system-overview.md#minimal-bootstrapping

twolfson commented 7 years ago

Alright, second PR is open: https://github.com/electron/electron/pull/8890

Since this issue is not specific to our repo at all, we are going to close it. Thanks for the bug report and finding that edge case =)

GProst commented 7 years ago

Great! Thanks for being quick to react, I will look forward for your PR's to be merged and released.