NativeScript / nativescript-cli

Command-line interface for building NativeScript apps
https://www.npmjs.com/package/nativescript
Apache License 2.0
1.04k stars 196 forks source link

[socket.io.js] document.createElement is not a function #2770

Open dtopuzov opened 7 years ago

dtopuzov commented 7 years ago

From @warren-bank on September 21, 2016 23:48

(edit: you can jump ahead to my final comment.. to see the very minor code patch I would suggest be applied, which would fix this issue)

I was super pleased to discover that the karma test runner could be used in conjunction with the interactive debugger: tns test android --debug-brk

However, I did want to raise one small issue..

The application crashed because of an uncaught exception. You can look at "stackTrace" or "nativeException" for more detailed information about the exception.
com.tns.NativeScriptException: 
Calling js method run failed

TypeError: document.createElement is not a function
File: "/data/data/org.nativescript.ExampleProject/files/app/tns_modules/zone.js/dist/zone-node.js, line: 201, column: 25

StackTrace: 
    Frame: function:'JSONPPolling.doPoll', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/nativescript-unit-test-runner/socket.io.js', line: 1085, column: 25
    Frame: function:'Polling.poll', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/nativescript-unit-test-runner/socket.io.js', line: 1740, column: 8
    Frame: function:'Polling.doOpen', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/nativescript-unit-test-runner/socket.io.js', line: 1684, column: 8
    Frame: function:'Transport.open', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/nativescript-unit-test-runner/socket.io.js', line: 827, column: 10
    Frame: function:'Socket.open', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/nativescript-unit-test-runner/socket.io.js', line: 248, column: 13
    Frame: function:'Socket', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/nativescript-unit-test-runner/socket.io.js', line: 129, column: 8
    Frame: function:'Socket', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/nativescript-unit-test-runner/socket.io.js', line: 55, column: 41
    Frame: function:'Manager.open.Manager.connect', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/nativescript-unit-test-runner/socket.io.js', line: 4549, column: 17
    Frame: function:'', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/nativescript-unit-test-runner/socket.io.js', line: 4859, column: 12
    Frame: function:'ZoneDelegate.invokeTask', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/zone.js/dist/zone-node.js', line: 323, column: 38
    Frame: function:'Zone.runTask', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/zone.js/dist/zone-node.js', line: 223, column: 48
    Frame: function:'ZoneTask.invoke', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/zone.js/dist/zone-node.js', line: 391, column: 34
    Frame: function:'ZoneDelegate.invoke', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/zone.js/dist/zone-node.js', line: 290, column: 29
    Frame: function:'Zone.runGuarded', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/zone.js/dist/zone-node.js', line: 197, column: 48
    Frame: function:'', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/zone.js/dist/zone-node.js', line: 173, column: 30
    Frame: function:'java.lang.Runnable.run', file:'/data/data/org.nativescript.ExampleProject/files/app/tns_modules/timer/timer.js', line: 17, column: 13

the file nativescript-unit-test-runner/socket.io.js is pretty much littered with references to the DOM, and attempts to perform DOM updates.

in particular:

I haven't done any digging into this. I'm not aware of the low-level details of precisely how socket.io is used by the test runner, or why the debugger would trigger additional polling, or why this error didn't occur while either:

and only occurs while debugging these unit tests.

Maybe this is nothing more than pilot error (on my part).. I wouldn't rule it out, though I don't think that I've done anything wrong.

In any case, I just wanted to share my observations.. in case somebody who knows the code and how things are glued together.. might read this and mutter: "oh shoot, yep.. easy fix"

Copied from original issue: NativeScript/nativescript-unit-test-runner#17

dtopuzov commented 7 years ago

From @warren-bank on September 22, 2016 0:55

wait.. there's a chance this is the result of something I did wrong (pilot error).. I'm re-running some tests now, and will report back shortly..

dtopuzov commented 7 years ago

From @warren-bank on September 22, 2016 1:48

ok.. it's a legit issue.. has nothing to do with a bit of zone.js error-catching trickery that I had in place.

dtopuzov commented 7 years ago

From @warren-bank on September 22, 2016 1:57

incidentally.. and feel free to completely ignore this suggestion.. which has very little to do with the issue at hand (though it may actually help to catch this and other uncaught exceptions, and conditionally ignore them).. but is just a feature that you may want to consider including.. possibly as an optional feature that could be toggled on/off with a boolean flag in karma.conf.js

and please keep in mind that this code is very rough.. and I'm still working on getting it right.. but something along the lines of:

/* ------------------------------------------------------------------
 * summary:
 * --------
 * all tests are passed to the testing framework
 * using the function signature:
 *     it('Do this and then do that', function (done) {...}
 *
 * when timers (ex: setTimeout) are called by the code under test,
 * Exceptions that may occur when the timer triggers will NOT
 * be caught by the testing framework,
 * and will result in the test suite ending prematurely,
 * with a terse error message about an "uncaught Exception".
 *
 * the purpose of this file is to use "zone.js"
 * to wrap the "it" function,
 * in such a way that Exceptions raised by asynchronous timers
 * will NOT result in an "uncaught Exception".
 *
 * the Zone will report the error to mocha,
 * which will then fail the particular test,
 * and then continue processing the remainder of the test suite.
 * ------------------------------------------------------------------
 * references:
 * -----------
 * https://github.com/angular/zone.js/
 * https://github.com/angular/zone.js/issues/418
 * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length
 * ------------------------------------------------------------------
 */

require('zone.js/dist/zone-node');

var old_it = global.it;

var new_it = function(desc, test){
  // it.skip()
  if (test === undefined){
    return old_it(desc);
  }

  var my_done;
  var my_zone = global.Zone.current.fork({
    onHandleError: function(){
      var error = arguments[3];
      my_done(error);

      // zone-node.js, lines: 201, 292
      // return value serves as a boolean flag for whether or not to throw the exception.
      //   - truthy: throw, which will be uncaught and crash the test runner.
      return false;
    }
  });

  return old_it(desc, function(done){
    my_done = done;

    my_zone.run(function(){
      test(done);

      if (test.length === 0){
        done();
      }
    });
  });
};

new_it.skip    = old_it.skip;
new_it.only    = old_it.only;
new_it.retries = old_it.retries;

global.it = new_it;
...
    files: [
      'app/components/**/*.js',
      'app/*.js',
      'app/tests/*.js'
    ],
    frameworks: ['mocha', 'chai'],
    reporters: ['mocha'],
    colors: false,
    singleRun: true,
    captureTimeout             : 300000,  // default: 60,000
    browserDisconnectTimeout   :  10000,  // default:  2,000
    browserDisconnectTolerance :      1,  // default:      0
    browserNoActivityTimeout   :  50000,  // default: 10,000
...
require('./lib/zones.js');

global.mocha.setup({
  timeout: 300000
});

global.chai.config.includeStack      = true;
global.chai.config.truncateThreshold = 0;

global.chai.use( require('./lib/chai-as-promised.js') );

describe('test suite', function () {
  require('./units/test.01.js');
  require('./units/test.02.js');
  require('./units/test.03.js');
});
dtopuzov commented 7 years ago

From @warren-bank on September 22, 2016 5:29

sorry for being so verbose, but i have a few additional observations regarding the issue..

...
function enableSocketIoDebugging() {
    console.log('enabling socket.io debugging');
    global.localStorage = {
        debug: "*"
    };
    global.window = global;
}
var config = require('./config');
...
if (config.options.debugTransport) {
    enableSocketIoDebugging();
}
...
var io = require('./socket.io');
var socket = this.socket = io.connect(this.baseUrl, {forceBase64: true});
...
if (config.options.debugBrk) {
    debugger;
}
...
module.exports = exports = lookup;
exports.connect = lookup;

function lookup(uri, opts) {
  ...
  io = Manager(source, opts);
  ...
  return io.socket(parsed.path);
}

Manager.prototype.socket = function(nsp){
  ...
  socket = new Socket(this, nsp);
  ...
};

function Socket(uri, opts){
  ...
  this.transports = opts.transports || ['polling', 'websocket'];
  ...
}
dtopuzov commented 7 years ago

From @warren-bank on September 22, 2016 6:36

(update: please disregard the information in this comment)

yeah, looks good now.

I'm stepping through an enormous test suite.. giving it plenty of time to poll or do whatever else might cause a problem.. I left the breakpoint in "socket.io.js" but it hasn't been hit at all.. it may be premature to call this patch a fix, but it certainly appears to be.

short tldr; version

dtopuzov commented 7 years ago

From @warren-bank on September 22, 2016 7:36

(update: please disregard the information in this comment)

I have another observation, which is loosely related and most-likely a fairly minor issue..

NSUTR-socket.io: transport close
    /data/data/org.nativescript.ExampleProject/files/app/tns_modules/nativescript-unit-test-runner/main-view-model.js:90

NSUTR-socket.io: 1
    /data/data/org.nativescript.ExampleProject/files/app/tns_modules/nativescript-unit-test-runner/main-view-model.js:90

so..

dtopuzov commented 7 years ago

From @warren-bank on September 22, 2016 8:56

ok, this is embarrassing..

here's what I'm seeing now:

took a while, but we got there :)

dtopuzov commented 7 years ago

From @warren-bank on September 22, 2016 9:1

updated:

short tldr; version

dtopuzov commented 7 years ago

From @warren-bank on September 22, 2016 22:31

a few closing comments regarding reconnect attempts..

pkoleva commented 7 years ago

Hey @warren-bank ,

Do you still have an issue with that or you've found a workaround to the problem?

warren-bank commented 7 years ago

Hi,

Wish I could offer additional insight beyond the original thread of code/observations, but I haven't used NativeScript in quite a while.. so I'm not sure if this has been addressed/solved in the time since then.

As for a workaround, please refer to the 2 comments that precede yours. That's what I ended up doing at the time, and it worked just fine. Specifically:

I'm a big fan of what you guys are building. When I swing back around to doing mobile UI, I'm sure I'll start using it again.

Sorry I couldn't be more helpful.

warren-bank commented 7 years ago

Hi again,

I just took a quick peek at the repo. Here is the current version of the (above mentioned) file (before being transpiled to js). Looks like that line of code hasn't been changed.

etabakov commented 7 years ago

Hi @warren-bank, Thanks for the kind words and the detailed analysis on the problem that you provided. We are currently in a process of figuring out what is the best way to further develop our testing story. Once we are done, we will be able to follow up with more information.

lambourn commented 6 years ago

I'm experiencing the same thing...

@etabakov do you have any insight in the new testing story? Is the current one broken?

fhackenb commented 6 years ago

@dtopuzov I have a similar issue, though it isn't related to websockets in my case. I'm using aws-appsync and when I try to require it I get:

JavaScript error: file:///app/tns_modules/setimmediate/setImmediate.js:175:64: JS ERROR TypeError: doc.createElement is not a function. (In 'doc.createElement("script")', 'doc.createElement' is undefined)

Error-causing code: const AWSAppSyncClient = require('aws-appsync');