question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[Rhino] Setting (function () {}).__proto__ broken in recent version of HtmlUnit

See original GitHub issue

Problem in brief

Setting of (function () {}).__proto__ is a no-op in recent versions of HtmlUnit breaking some libraries.

Setting of new Object().__proto__ still works as expected.

This problem affects the Knockout library of at least v3.3.0 and the current version v3.5.1.

Details

When Rhino is running in ES6 mode, setting of _proto__ on a function object is denied by this condition in SpecialRef that only allows setting on objects. This behaviour is incompatible with major browsers (Chrome / FF / Edge / IE11) and breaks libraries that rely on this.

Test case

<html>
<head>
<script>
function test() {
	var proto = { foo: function (n) { console.log('foo'); } }
	proto.foo();

	var obj = function () {}
	console.log("Original __proto__:", obj.__proto__);

	obj.__proto__ = proto;
	console.log("Modified __proto__:", obj.__proto__);

	console.log("obj.foo:", obj.foo);

	try {
		obj.foo();
	} catch (e) {
		console.log(e);
	}
}
</script>
</head>
<body onload="test()">
</body>
</html>

Expected:

foo
Original __proto__: function () {[native code]}
Modified __proto__: ({foo: (function (n) { console.log("foo"); })})
obj.foo: (function (n) { console.log("foo"); })
foo

HtmlUnit 2.46.0 fails with the following:

foo
Original __proto__: function () {[native code]}
Modified __proto__: function () {[native code]}
obj.foo: net.sourceforge.htmlunit.corejs.javascript.Undefined@0
TypeError: Cannot find function foo in object function () {...}.

Suggested fix

The documentation for Function’s __proto__ (Object.prototype__proto__) doesn’t seem to make any distinction between the state of support for objects and function objects so it seems they should be equally supported, if supported at all.

Out of the possible values returned by typeof, it seems “function” and “object” are the only ones that make sense:

[undefined, null, true, 123, 123n, "abc", Symbol(), function () {}, {}].forEach(x => {
    try {
        var proto = {}
        var r = (x.__proto__ = proto);
        console.log(typeof x + ": returned=" + (r === proto) + " changed=" + (x.__proto__ === proto))
    } catch (e) {
        console.log(typeof x + ": " + e);
    }
})

/* Output of Chrome / FF:
undefined: TypeError: Cannot set property '__proto__' of undefined
object: TypeError: Cannot set property '__proto__' of null
boolean: returned=true changed=false
number: returned=true changed=false
bigint: returned=true changed=false
string: returned=true changed=false
symbol: returned=true changed=false
function: returned=true changed=true
object: returned=true changed=true
*/

(This can be run in HtmlUnit 2.46.0 by removing 123n (BigInt(123)) which is not supported.)

In lieu of this, my suggestion is for this condition in SpecialRef be changed as follows:

 if (cx.getLanguageVersion() >= Context.VERSION_ES6) {
-    if ((value != null && !"object".equals(ScriptRuntime.typeof(value))) ||
-        !"object".equals(ScriptRuntime.typeof(target))) {
-        return Undefined.instance;
-    }
+    if (value != null && !"object".equals(ScriptRuntime.typeof(value))) {
+        return obj;
+    }
+    switch (ScriptRuntime.typeof(target)) {
+    case "object":
+    case "function":
+        break;
+    default:
+        return obj;
+    }
     target.setPrototype(obj);
 } else {
     target.setPrototype(obj);
 }

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
rbricommented, Jan 11, 2021

PR https://github.com/mozilla/rhino/pull/822 - hopefully this find a way into Rhino soon

0reactions
rbricommented, Jan 17, 2021

Available with the latest SNAPSHOT.

Thanks for your support.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Changes - HtmlUnit - SourceForge
New web client option setFetchPolyfillEnabled() to automatically load a polyfill for the fetch api into the client. rbri. Fix, FileReader readAsArrayBuffer() ...
Read more >
Turn off "RHINO USAGE WARNING" for HtmlUnit
I'm using HtmlUnit 2.27 and I currently have the following settings LogFactory.getFactory().setAttribute("org.apache.commons.logging.
Read more >
HTMLUnit doesn't handle Object array's in javascript properly
I was able to get the error without using jquery: List<WebElement> els = driver.findElements(By.tagName("div")); Object[] args = new Object[] { ...
Read more >
October 2015 - arm - Fedora Mailing-Lists
... Add a new function lr_log_librepo_summary() - Doc: Add log_set_file ... Update to 0.12.10 - Add python scripts and .proto files used to ......
Read more >
14 safari 卡死源码调试 - CSDN
onResourceRequested = function(request){ ... onResourceReceived = function(response){ ... var req_time = new Date(req[i]['time']).getTime();.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found