1

I have an upgrade / hybrid AngularJS / Angular 2 app and I'm getting this error:

Unhandled Promise rejection: Cannot add property resumeBootstrap, object is not extensible ; Zone: ; Task: Promise.then ; Value: TypeError: Cannot add property resumeBootstrap, object is not extensible at UpgradeModule.bootstrap (upgrade_module.ts:259)

The source code at that location is:

// Make sure resumeBootstrap() only exists if the current bootstrap is deferred
const windowAngular = (window as any)['angular'];
windowAngular.resumeBootstrap = undefined;

My code was working fine. Pulling in the latest Angular changes seemed to cause this.

Here's my bootstrapping code:

import {platformBrowser} from '@angular/platform-browser';
import {UpgradeModule} from '@angular/upgrade/static';

import {AppModuleNgFactory} from './app_module.ngfactory';

angular.element(document.body).ready(() => {
  platformBrowser()
      .bootstrapModuleFactory(AppModuleNgFactory)
      .then(platformRef => {
        const upgrade =
            platformRef.injector.get(UpgradeModule) as UpgradeModule;
        // This is the line that fails:
        upgrade.bootstrap(document.body, ['foo-obfuscated'], {strictDi: false});
});

Update: I tried moving upgrade.bootstrap call to ngDoBootstrap in my AppModule like in the Angular upgrade docs example, but that didn't change anything.

Alexander Taylor
  • 16,574
  • 14
  • 62
  • 83

2 Answers2

0

Workaround: just before bootstrapping, clone the window.angular object so it will be extensible again:

function clone(original: any) {
  const clone: any = {};
  const keys = Object.keys(original);
  for (let i = 0; i < keys.length; i++) {
    clone[keys[i]] = original[keys[i]];
  }
  return clone;
}
(window as any)['angular'] = clone((window as any)['angular']);

platformBrowser().bootstrapModuleFactory(AppModuleNgFactory);
Alexander Taylor
  • 16,574
  • 14
  • 62
  • 83
0

Needed to make my page run this code before Closure loads:

// Closure Defines specific to AngularJS that must be set before Closure's
// base.js is loaded. See documentation in base.js.

// Sealing classes & modules is incompatible with AngularJS' $inject property.
var CLOSURE_DEFINES = {
  'goog.defineClass.SEAL_CLASS_INSTANCES': false,
  'goog.SEAL_MODULE_EXPORTS': false
};
Alexander Taylor
  • 16,574
  • 14
  • 62
  • 83