Nativescript-angular: Global 'document' polyfill causes crashes when used with some node packages

Created on 29 Dec 2017  路  8Comments  路  Source: NativeScript/nativescript-angular

With 5.0.0, a dependency I was using now causes an exception. Switching back to 4.*.* fixes the issue. In my case I'm using fuzzball, whose default module has a dependency tree with node standard modules that are not available in Nativescript. Instead, I'm using the minified umd version which has worked up until nativescript-angular: 5.0.0 and Angular 5. Here is the stack trace for iOS:

***** Fatal JavaScript exception - application has been terminated. *****
Native stack trace:
1   0x10fce57b4 -[TNSRuntime executeModule:referredBy:]
2   0x10f7dbc71 main
3   0x11377565d start
JavaScript stack trace:
1   @file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:5:14902
2   @file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:5:15068
3   @file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:5:15147
4   s@file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:1:693
5   @file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:1:741
6   @file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:1:1893
7   @file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:1:17113
8   s@file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:1:693
9   e@file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:1:861
10  @file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:1:877
11  @file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:1:159
12  anonymous@file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:1:392
13  evaluate@[native code]
14  moduleEvaluation@[native code]
15  @[native code]
16  promiseReactionJob@[native code]
17  require@[native code]
18  anonymous@file:///app/app.component.js:4:23
19  evaluate@[native code]
20  moduleEvaluation@[native code]
21  @[native code]
22  promiseReactionJob@[native code]
23  require@[native code]
24  anonymous@file:///app/app.module.js:6:30
25  evaluate@[native code]
26  moduleEvaluation@[native code]
27  @[native code]
28  promiseReactionJob@[native code]
29  require@[native code]
30  anonymous@file:///app/main.js:5:27
31  evaluate@[native code]
32  moduleEvaluation@[native code]
33  @[native code]
34  promiseReactionJob@[native code]
JavaScript error:
file:///app/tns_modules/fuzzball/dist/fuzzball.umd.min.js:5:14902: JS ERROR TypeError: doc.createElement is not a function. (In 'doc.createElement("script")', 'doc.createElement' is undefined)

I'm including a sample project whose package.json you can change to the following in order to no longer get this error:

{
  "description": "NativeScript Application",
  "license": "SEE LICENSE IN <your-license-filename>",
  "readme": "NativeScript Application",
  "repository": "<fill-your-repository-here>",
  "nativescript": {
    "id": "org.nativescript.dependencyerror",
    "tns-ios": {
      "version": "3.4.0"
    }
  },
  "dependencies": {
    "@angular/animations": "~4.4.6",
    "@angular/common": "~4.4.6",
    "@angular/compiler": "~4.4.6",
    "@angular/core": "~4.4.6",
    "@angular/forms": "~4.4.6",
    "@angular/http": "~4.4.6",
    "@angular/platform-browser": "~4.4.6",
    "@angular/platform-browser-dynamic": "~4.4.6",
    "@angular/router": "~4.4.6",
    "allow-publish": "^1.0.4",
    "fuzzball": "^0.13.6",
    "nativescript-angular": "~4.4.1",
    "nativescript-theme-core": "~1.0.4",
    "reflect-metadata": "~0.1.8",
    "rxjs": "~5.5.2",
    "tns-core-modules": "~3.4.0",
    "zone.js": "~0.8.2"
  },
  "devDependencies": {
    "nativescript-dev-typescript": "~0.5.0",
    "typescript": "~2.4.2"
  }
}

Finally, here is the unminified version of the block that fails:

if ({}.toString.call(global.process) === "[object process]") {
    installNextTickImplementation()
} else if (canUsePostMessage()) {
    installPostMessageImplementation()
} else if (global.MessageChannel) {
    installMessageChannelImplementation()
} else if (doc && "onreadystatechange" in doc.createElement("script")) {
    installReadyStateChangeImplementation()
} else {
    installSetTimeoutImplementation()
}

Edit:
Attaching project. Also, this error can be fixed by changing the line
else if (doc && "onreadystatechange" in doc.createElement("script"))
to
else if (doc && document.createElement && "onreadystatechange" in doc.createElement("script"))
dependency-error.zip

backlog

Most helpful comment

@david-quadpro That's it. The sample-Groceries tutorial app is using following import inside user.service.ts:
import { Observable } from 'rxjs/Rx';
changing to import { Observable } from 'rxjs/Observable'; makes it work. It makes sense because rxjs/Rx imports the whole package including the Immediate.js file.

Problem solved.
Thanks!

All 8 comments

Hey @vcooley,
In v5.0 of nativescript-angular we had to attach a polyfill of the document object to the global object. Code.
That's because of a code inside Angular animations that uses the document object.
We'll work on removing the polyfill for later versions of the plugin as it obviously causes problems with node packages that try to detect a document object.

Is there a solution / work around?

I am getting the stack trace below. This is the first part, it repeats the same TypeError: document.createElement is not a function several times, each time in reference to rxjs/util/Immediate.js

System.err: TypeError: document.createElement is not a function
System.err: File: "file:///data/data/com.quadpro.qplusrequest/files/app/tns_modules/rxjs/util/Immediate.js, line: 56, column: 68
System.err:
System.err: StackTrace:
System.err: Frame: function:'ImmediateDefinition.canUseReadyStateChange', file:'file:///data/data/com.quadpro.qplusrequest/files/app/tns_modules/rxjs/util/Immediate.js', line: 56, column: 69
System.err: Frame: function:'ImmediateDefinition', file:'file:///data/data/com.quadpro.qplusrequest/files/app/tns_modules/rxjs/util/Immediate.js', line: 30, column: 27
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/tns_modules/rxjs/util/Immediate.js', line: 208, column: 21
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/tns_modules/rxjs/scheduler/AsapAction.js', line: 7, column: 19
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/tns_modules/rxjs/scheduler/asap.js', line: 2, column: 20
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/tns_modules/rxjs/observable/SubscribeOnObservable.js', line: 8, column: 14
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/tns_modules/rxjs/operators/subscribeOn.js', line: 2, column: 31
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/tns_modules/rxjs/operator/subscribeOn.js', line: 2, column: 21
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/tns_modules/rxjs/add/operator/subscribeOn.js', line: 3, column: 21
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/tns_modules/rxjs/Rx.js', line: 121, column: 1 System.err: Frame: function:'require', file:'', line: 1, column: 266 System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/shared/services/navigation.service.js', line: 5, column: 14
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/shared/services/index.js', line: 6, column: 10 System.err: Frame: function:'require', file:'', line: 1, column: 266 System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/shared/components/action-bar.component.js', line: 5, column: 18
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/shared/components/index.js', line: 6, column: 10
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/shared/index.js', line: 8, column: 10
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/navigation/tabstrip/tabstrip.component.js', line: 5, column: 14
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/navigation/tabstrip/tabstrip.routes.js', line: 4, column: 28
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/navigation/tabstrip/tabstrip.module.js', line: 6, column: 25
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/app.module.js', line: 12, column: 25
System.err: Frame: function:'require', file:'', line: 1, column: 266
System.err: Frame: function:'', file:'file:///data/data/com.quadpro.qplusrequest/files/app/main.js', line: 5, column: 20
System.err: Frame: function:'require', file:'', line: 1, column: 266

My package.json is:
{ "description": "Q+ Requests", "nativescript": { "id": "com.quadpro.qplusrequest", "tns-android": { "version": "3.4.0" }, "tns-ios": { "version": "3.4.0" } }, "dependencies": { "@angular/animations": "~5.0.0", "@angular/common": "~5.0.0", "@angular/compiler": "~5.0.0", "@angular/core": "~5.0.0", "@angular/forms": "~5.0.0", "@angular/http": "~5.0.0", "@angular/platform-browser": "~5.0.0", "@angular/platform-browser-dynamic": "~5.0.0", "@angular/router": "~5.0.0", "everlive-sdk": "^1.9.4", "nativescript-angular": "5.0.0", "nativescript-barcodescanner": "^2.7.4", "nativescript-mapbox": "^3.1.3", "nativescript-pro-ui": "^3.3.0", "nativescript-theme-core": "1.0.4", "reflect-metadata": "0.1.10", "rxjs": "^5.5.0", "tns-core-modules": "3.4.0", "zone.js": "^0.8.4" }, "devDependencies": { "@angular/compiler-cli": "~5.0.0", "@ngtools/webpack": "~1.8.2", "babel-traverse": "6.4.5", "babel-types": "6.4.5", "babylon": "6.4.5", "codelyzer": "3.2.2", "copy-webpack-plugin": "~4.0.1", "css-loader": "~0.28.7", "extract-text-webpack-plugin": "~3.0.0", "lazy": "1.0.11", "nativescript-css-loader": "~0.26.0", "nativescript-dev-typescript": "^0.6.0", "nativescript-dev-webpack": "^0.9.0", "nativescript-worker-loader": "~0.8.1", "raw-loader": "~0.5.1", "resolve-url-loader": "~2.1.0", "tslint": "5.8.0", "typescript": "~2.4.2", "webpack": "~3.8.1", "webpack-bundle-analyzer": "^2.8.2", "webpack-sources": "~1.0.1" } }

Sorry, I found a import { BehaviorSubject } from "rxjs"; that I changed to import { BehaviorSubject } from "rxjs/BehaviorSubject"; and it now launches. Solution found at #1137 and Unable to create application com.tns.NativeScriptApplication #3290

I then had a problem with Observable.fromPromise. I found here that I was missing import 'rxjs/add/observable/fromPromise';

I'm getting the same error as @david-quadpro
I've double checked and there is no import from 'rxjs'. I've also tried the tns platform remove android & tns platform add android but no luck.

package.json:

{
    "description": "NativeScript Application",
    "license": "SEE LICENSE IN <your-license-filename>",
    "readme": "NativeScript Application",
    "repository": "<fill-your-repository-here>",
    "nativescript": {
        "id": "org.nativescript.nsgroceries",
        "tns-android": {
            "version": "3.4.1"
        }
    },
    "dependencies": {
        "@angular/animations": "5.1.3",
        "@angular/common": "5.1.3",
        "@angular/compiler": "5.1.3",
        "@angular/core": "5.1.3",
        "@angular/forms": "5.1.3",
        "@angular/http": "5.1.3",
        "@angular/platform-browser": "5.1.3",
        "@angular/platform-browser-dynamic": "5.1.3",
        "@angular/router": "5.1.3",
        "nativescript-angular": "5.1.0",
        "nativescript-theme-core": "1.0.4",
        "reflect-metadata": "0.1.10",
        "rxjs": "5.5.6",
        "tns-core-modules": "3.4.0",
        "zone.js": "0.8.2"
    },
    "devDependencies": {
        "babel-traverse": "6.4.5",
        "babel-types": "6.4.5",
        "babylon": "6.4.5",
        "lazy": "1.0.11",
        "codelyzer": "4.0.1",
        "nativescript-dev-sass": "1.3.5",
        "nativescript-dev-typescript": "0.6.0",
        "typescript": "2.6.2"
    }
}

I spoke to someone yesterday on Slack that had Import { Observable } from "rxjs/Rx". When they changed it to import { Observable } from "rxjs/Observable" it worked. Perhaps you have a variation of the direct rxjs import?

@david-quadpro That's it. The sample-Groceries tutorial app is using following import inside user.service.ts:
import { Observable } from 'rxjs/Rx';
changing to import { Observable } from 'rxjs/Observable'; makes it work. It makes sense because rxjs/Rx imports the whole package including the Immediate.js file.

Problem solved.
Thanks!

HI all,
The problem is related to the issue #22093 logged in the angular repository. To remove the polyfill, we should wait for #22093 to be resolved.

Was this page helpful?
0 / 5 - 0 ratings