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

Error when reloading page: TypeError: Cannot read property 'firstChild' of null #38

Closed
yinso opened this issue Feb 20, 2016 · 8 comments

Comments

@yinso
Copy link
Contributor

yinso commented Feb 20, 2016

Using nw.js 0.12.3, and the error happens on reload of the page.

The calling code looks like this:

player = new wcjs("#player").addPlayer({ autoplay: true }); // <div id="player"></div> is defined

It occurs at index.js line 75 as the query of getElementById returns null, but it happens due to a switch of context at line 72, where the code $(this.context).hasClass("webchimeras") returns true, and $(this.context).find(".wcp-wrapper")[0].id returns webchimeras, which causes this.context to be set to #webchimeras instead of staying at #player.

For some reason the copy of <div id="player" /> found by jQuery has been adorned with class="webchimeras" and a child element of <div class="wcp-wrapper">, but those don't exist in windows.document's copy of <div id="player" /> when viewed in devtools.

1 - where are the above attributes and elements being set? By wcjs-renderer?
2 - could they be set to a different copy of the element, i.e. jQuery isn't referring to the same document as window.document upon refreshing the page?

@jaruba
Copy link
Owner

jaruba commented Feb 20, 2016

1 - where are the above attributes and elements being set? By wcjs-renderer?

wcjs-renderer doesn't mess with any elements, you just give it a canvas and it renders the video on it, nothing else. So everything is set in wcjs-player.

2 - could they be set to a different copy of the element, i.e. jQuery isn't referring to the same document as window.document upon refreshing the page?

I've heard about this issue time and again, some manage to fix it in strange ways, some don't.. It happens almost 100% if you try to start wcjs-player in a second window.

Personally I consider it a really bad NW.js bug.. NW.js should always give the right window.document, but it doesn't..

It's like it was meant to be used with just one window, without refreshing.. I've even seen window.localStorage get totally lost after a page refresh.

@jaruba
Copy link
Owner

jaruba commented Feb 20, 2016

You can check out these tickets too if you want to dig into it further: #29 , #34 , #6

All of them had your error at one point or another, the situations defer.

@jaruba
Copy link
Owner

jaruba commented Feb 20, 2016

I think that the reason this happens is because of the way NW.js works.

require() is persistent through page changes, reload, etc. so the modules are actually loaded the first time on a different page, and you only get it's reference from the global.require object after the first time you require them.

I imagine that the issue is in jQuery in this case, as it was first loaded with a different document, and it never refreshes.

It might be possible to solve it by removing jQuery from the node.js cache, like I do with wcjs-player on page changes:
https://github.com/jaruba/wcjs-player/blob/master/index.js#L53-L62

You could try to tweak it to remove jQuery too then require() it again, it might fix your issue.

@yinso
Copy link
Contributor Author

yinso commented Feb 21, 2016

Thanks for the explanations. I suspect the same that jQuery might be holding onto a previous version of the document. I will give it a shot and see what happens.

@jaruba
Copy link
Owner

jaruba commented Feb 21, 2016

Try it with:

    // clear wcjs-player from require cache when page changes
    if (global.require.cache) {
        for (module in global.require.cache) {
            if (global.require.cache.hasOwnProperty(module) && (module.indexOf("wcjs-player") > -1 || module.indexOf("jquery") > -1)) delete global.require.cache[module];
        }
    } else if (require.cache) {
        for (module in require.cache) {
            if (require.cache.hasOwnProperty(module) && (module.indexOf("wcjs-player") > -1 || module.indexOf("jquery") > -1)) delete require.cache[module];
        }
    }

Instead of the code i linked above, as it's on unload event, it should re-require jquery on the next page load. And make sure the event is triggered on refresh.

@yinso
Copy link
Contributor Author

yinso commented Feb 21, 2016

The combo of above with window.unload works! I can see the player getting painted, although I then ran into what looks like nw.js #3342 so couldn't see further, but that's a different issue.

Thanks!

@yinso yinso closed this as completed Feb 21, 2016
@jaruba
Copy link
Owner

jaruba commented Feb 21, 2016

@yinso make a PR for it, you found it, tested it, should also push it :)

@yinso
Copy link
Contributor Author

yinso commented Feb 21, 2016

Yeah sure - will take care of this ;)

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