Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'catch' is not supported as a method name in object literals #2640

Closed
vlukashov opened this issue Sep 3, 2017 · 3 comments
Closed

'catch' is not supported as a method name in object literals #2640

vlukashov opened this issue Sep 3, 2017 · 3 comments

Comments

@vlukashov
Copy link

In certain cases Google Closure Compiler incorrectly removes the method called catch from object literals.

Example (sample.js):

(function () {
  'use strict';

  function MyPromise(resolver) {
  }

  MyPromise.prototype = {
    constructor: MyPromise,
    then: function() {},
    catch(onRejection) {
      return this.then(null, onRejection);
    }
  };

  let p = new MyPromise();
  console.log(`typeof promise.catch = ${typeof p['catch']}`);
}());

Executing an unprocessed file yields:

$ node sample.js
typeof promise.catch = function

Executing a compiled file yields an incorrect result:

$ java -jar node_modules/google-closure-compiler/compiler.jar \
        --new_type_inf=true \
        --compilation_level=ADVANCED \
        --language_in=ES6_STRICT \
        --language_out=ES5_STRICT \
        --isolation_mode=IIFE \
        --assume_function_wrapper=true \
        --js_output_file=sample.min.js \
        --warning_level=VERBOSE \
        --rewrite_polyfills=false \
        sample.js
$ node sample.min.js
typeof promise.catch = undefined

The issue appears with the last released version of the compiler:

$ java -jar node_modules/google-closure-compiler/compiler.jar --version
Closure Compiler (http://github.com/google/closure-compiler)
Version: v20170806
Built on: 2017-08-09 13:35

The code sample above is reduced from es6-promise polyfill which is used among others in the WebComponents polyfill.

@ChadKillingsworth
Copy link
Collaborator

This looks correct to me. There is nothing to tell the compiler that MyPromise is attempting to be the Promise type. Catch isn't referenced/used, therefore it is removed.

@vlukashov
Copy link
Author

I see what you mean. I must have oversimplified the actual case and removed too much.

The actual code also exports MyPromise into the global scope. Still simplified it looks like that:

(function () {
  'use strict';

  function MyPromise(resolver) {
  }

  MyPromise.prototype = {
    constructor: MyPromise,
    then: function() {},
    catch(onRejection) {
      return this.then(null, onRejection);
    }
  };

  let local;
  try {
      local = Function('return this')();
  } catch (e) {
      throw new Error('polyfill failed because global object is unavailable in this environment');
  }

  local.Promise = MyPromise;

  let p = new Promise();
  console.log(`typeof promise.catch = ${typeof p['catch']}`);
}());

The actual (non simplified) file where the issue occurs is attached as well.
es6-promise-test.js.zip

@ChadKillingsworth
Copy link
Collaborator

exports MyPromise into the global scope

That's still not enough for advanced mode. catch will still be removed if there are no references.
This isn't a bug in closure-compiler. It's a bug in the polyfill. The method the es6-promise library uses to polyfill a promise is not compatible with advanced mode compilations.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants