nightmare icon indicating copy to clipboard operation
nightmare copied to clipboard

Cannot assign to read only property 'onbeforeunload' of object '#<Window>'

Open entrptaher opened this issue 7 years ago • 20 comments

Any script I Run through medium.com does not work. The site does not load properly. If I open devtools, I can see an error, This error does not happen with normal browsers. I am using latest nodejs, nightmarejs and electron.

The code I am using simply goes to the site so I can check what went wrong.

var Nightmare = require('nightmare');
var nightmare = Nightmare({
	  openDevTools:{
    	  mode:'detach'
    	},
	  show: true,
	  
	  webPreferences: {
	  	partition: "persist:xyz",
        devTools: true,
        nodeIntegration: false,
        webSecurity: false,
        allowRunningInsecureContent: true
      }})

nightmare.goto('https://medium.com/search?q=nightmarejs&ref=opensearch').then()

Error on version 2.9.0 or above

image

No error on nightmare 2.8.0 (which uses electron-prebuilt)

image

entrptaher avatar Apr 11 '17 07:04 entrptaher

Similar problem here. Have you found a solution?

dzcpy avatar Apr 27 '17 11:04 dzcpy

Using old nightmare is just a temporary solution.

entrptaher avatar Apr 27 '17 11:04 entrptaher

I experienced a Cannot assign to read only property 'onunload' of object '#<Window>' error, I somehow got a workaround by opening a new window to run the same code, and it doesn't have any errors. It's so weird.

dzcpy avatar Apr 27 '17 11:04 dzcpy

Care to share your workaround code?

entrptaher avatar Apr 27 '17 12:04 entrptaher

@entrptaher It might not work under all circumstances

const Nightmare = require('nightmare');
require('nightmare-window-manager')(Nightmare);
nightmare
  .windowManager()
  .useragent('Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36')
  .goto('about:blank')
  .evaluate(() => window.open('https://example.com'))
  .waitWindowLoad()
  .currentWindow()
  .then((windows) => {
    console.log(windows.title);
  })

dzcpy avatar Apr 27 '17 12:04 dzcpy

+1 same here with 2.10.0

matusferko avatar May 14 '17 21:05 matusferko

I found a workaround

Object.defineProperty(window, 'onbeforeunload', { writable: true });
Object.defineProperty(window, 'onunload', { writable: true });

w01fgang avatar Jun 08 '17 15:06 w01fgang

This is a regression introduced by #825 .

The fix is trivial. The preload.js script needs to be modified to:

  // prevent 'onunload' and 'onbeforeunload' from being set
  Object.defineProperties(window, {
    onunload: {
      enumerable: true,
      writable: true,
      value: null,
      set: function() {}
    },
    onbeforeunload: {
      enumerable: true,
      writable: true,
      value: null,
      set: function() {}
    }
  });

Perhaps someone else would be so kind as to put this into a PR? :-)

bwbuchanan avatar Jun 29 '17 21:06 bwbuchanan

Unfortunately, this isn't a regression, #825 resolves #824. Maybe this needs to be documented well. Or someone will add a method that allows changing window properties. Example:

nightmare.writableWindow(true).goto('http://...')

w01fgang avatar Jun 30 '17 10:06 w01fgang

You're right, it's not a regression; it's a bug introduced by #825 when fixing #824.

I think that my fix accomplishes the intent of #825 without breaking pages that try to set onunload / onbeforeunload.

bwbuchanan avatar Jun 30 '17 10:06 bwbuchanan

+1 same here with 2.10.0

tomjamescn avatar Aug 17 '17 01:08 tomjamescn

@bwbuchanan, I tried putting that preload.js, however, it was not fixed in.

entrptaher avatar Aug 18 '17 11:08 entrptaher

I tested your solution, @bwbuchanan. And the result is as you can see.

image

Codes:

var Nightmare = require('nightmare'),
  path = require('path'),
  nightmare = Nightmare({
    show: true,
    webPreferences: {
      preload: path.resolve(__dirname + '/preload.js')
    }
  });

nightmare.goto('http://www.medium.com')
  .url()
  .then((url) => {
    console.log(`Navigated to ${url}`);
  })
  .catch((error) => {
    console.log(error)
  })
window.__nightmare = {};
__nightmare.ipc = require('electron').ipcRenderer;

// prevent 'onunload' and 'onbeforeunload' from being set
Object.defineProperties(window, {
  onunload: {
    enumerable: true,
    writable: true,
    value: null,
    set: function() {}
  },
  onbeforeunload: {
    enumerable: true,
    writable: true,
    value: null,
    set: function() {}
  }
});

This worked which is similar to @w01fgang solution:

Object.defineProperties(window, {
  onunload: {
    writable: true
  },
  onbeforeunload: {
    writable: true
  }
});

Maybe we can turn this into a plugin/action.

entrptaher avatar Aug 18 '17 12:08 entrptaher

You must have a different version of something than I do. Try removing "value: null" and replacing with "get: function() { return null; }"

Simply making it writable defeats the purpose of #825

bwbuchanan avatar Aug 18 '17 13:08 bwbuchanan

I can confirm that setting the below values to true resolves the issue: https://github.com/segmentio/nightmare/blob/f49265c2d16f66ef86d8fb7bef661b36cbe09073/lib/preload.js#L50

https://github.com/segmentio/nightmare/blob/f49265c2d16f66ef86d8fb7bef661b36cbe09073/lib/preload.js#L55

@matthewmueller Would you accept a pull request with these changes to the preload script?

Would this change brake the other resolved issue previously mentioned above? If so, then I think this shouldn't be part of the default preload script at all. What do you think?

kireerik avatar Mar 15 '18 21:03 kireerik

This happened to me with 3.0.1 just now, just fyi

edit: @kireerik's solution fixed it for me :) thanks!

kvz avatar Aug 29 '18 13:08 kvz

The way to avoid this problem: Step 1: Copy node_modules/nightmare/lib/preload.js somewhere into your project, and replace

https://github.com/segmentio/nightmare/blob/25467e5a1071c05dcbce7f58e137f89c4b8fdd93/lib/preload.js#L47-L58 to

   writable: true,

Step 2: When you init nightmare, webPreferences.preload uses files that have just been modified.

var Nightmare = require('nightmare');
var nightmare = Nightmare({
	  webPreferences: {
               ...,
	        preload: path.resolve(__dirname, 'mypreload.js')
     }})

sosohime avatar Nov 02 '18 02:11 sosohime

This issue is apparently pretty old but I ran into the same problem.

It appears the fix is simple, although modifying preload.js manually is not a viable solution for automated testing

felipemullen avatar Nov 28 '18 22:11 felipemullen

Today I ran into the same issue. It doesn't work! And when I change writable to true I get Name: TypeError. Message: this.nightmare.writableWindow is not a function

iblessedi avatar Jun 19 '19 13:06 iblessedi

When I downgrade to Nightmare 2.8.1 - I can edit writable. But in the newest version I cannot :(

iblessedi avatar Jun 19 '19 13:06 iblessedi