javascriptgoogle-closure-compilergoogle-closure-library

Javascript Dot-Syntax function disappears in listen callback


I'm trying to update Annotorious (https://annotorious.github.io/#) to the latest version of Closure / Javascript.

When I compile it with "SIMPLE" optimizations, dot-syntax functions seem to disappear when goog.events.listen callbacks are invoked. Here's an example:

Here's the "main":

goog.provide('annotorious.Annotorious');
...
/**
 * The main entrypoint to the application. The Annotorious class is instantiated exactly once,
 * and added to the global window object as 'window.anno'. It exposes the external JavaScript API
 * and internally manages the 'modules'. (Each module is responsible for one particular media
 * type - image, OpenLayers, etc.)
 * @constructor
 */
annotorious.Annotorious = function() {
  /** @private **/
  this._isInitialized = false;

  /** @private **/
  this._modules = [ new annotorious.mediatypes.image.ImageModule() ];
...

In another file (they're all compiled together), we have this:

goog.provide('annotorious.Annotation');

goog.require('annotorious.shape');

/**
 * A 'domain class' implementation of the external annotation interface.
 * @param {string} src the source URL of the annotated object
 * @param {string} text the annotation text
 * @param {annotorious.shape.Shape} shape the annotated fragment shape
 * @constructor
 */
annotorious.Annotation = function(src, text, shape) {
  this.src = src;
  this.text = text;
  this.shapes = [ shape ];
  this['context'] = document.URL; // Prevents dead code removal
}

So we start up the code, and at some point we end in the editor for the annotation, listening for a "Save" button:

goog.provide('annotorious.Editor');

....

/**
 * Annotation edit form.
 * @param {Object} annotator reference to the annotator
 * @constructor
 */
annotorious.Editor = function(annotator) {
  this.element = goog.soy.renderAsElement(annotorious.templates.editform);

....
  /** @private **/
  //this._btnSave = goog.dom.query('.annotorious-editor-button-save', this.element)[0];
  this._btnSave = this.element.querySelector('.annotorious-editor-button-save');
...
  goog.events.listen(this._btnSave, goog.events.EventType.CLICK, function(event) {
    event.preventDefault();
    var annotation = self.getAnnotation();
    annotator.addAnnotation(annotation);
    annotator.stopSelection();

    if (self._original_annotation)
      annotator.fireEvent(annotorious.events.EventType.ANNOTATION_UPDATED, annotation, annotator.getItem());
    else
      annotator.fireEvent(annotorious.events.EventType.ANNOTATION_CREATED, annotation, annotator.getItem());
    self.close();
  });

If I put a breakpoint at "goog.events.listen(this._btnSave...", and type "annotorious.Annotation", I get what I expect:

"annotorious.Annotation" before callback

In fact, it has all kinds of methods:

"annotorious." methods/properties before callback

Then I let the code go, and break in the listener (event.preventDefault();, etc, above):

Now, all the dot-syntax methods are gone.

"annotorious." method/properties in callback

This of course causes crashes later on.

All of these files are compiled together.

This happens for all callbacks - 'load' events, other ux callbacks, etc.

This must have worked in prior versions of Closure / JS.

What could be causing this?

Thanks!


Solution

  • Ok, I was able to resolve the problem by adding "--assume_function_wrapper" to the closure compiler command line.

    Previously, I was compiling the package using Plovr. However, since Plovr hasn't been updated in a long time, I switched to using the closure compiler natively.

    Apparently either Plovr provided '--assume_function_wrapper' internally or the version of the compiler Plovr used didn't break the functions as described.

    As @john suggests above I'll bet '--assume_function_wrapper' keeps goog.provide from "destroying" namespaces by re-declaring them.