I am working on a GWT project where the host page has scripts that add properties to String.prototype. The host page scripts rely on the existence of these properties in order to run correctly, so I need to make sure that whenever I pass a string from GWT to “host code”, the extra properties are present in the object.
I thought that by calling $wnd.String in a non-constructor context, the extra properties would be there, but this appears to not be the case. In this mock-GWT setup, for example:
test.html:
<!DOCTYPE html>
<html>
<head>
<script>
String.prototype.myStartsWith = function String_myStartsWith(prefix) {
prefix = String(prefix);
return (this.indexOf(prefix) === 0);
};
function onLoad() {
var iframe = document.createElement("IFRAME");
iframe.src = "javascript:''";
iframe.id = "myFrame";
document.body.appendChild(iframe);
iframe.contentWindow.location.replace("myFrame.html");
}
</script>
</head>
<body onload="onLoad()">
</body>
</html>
myFrame.html:
<!DOCTYPE html>
<html><head><script>
var $wnd = parent;
var $doc = $wnd.document;
debugger;
</script></head></html>
When execution hits the debugger line, the following results are obtained using the JS debugger console:
> $wnd.String !== String
true
> new $wnd.String("test").myStartsWith === undefined
false
> $wnd.String.prototype.myStartsWith === undefined
false
> $wnd.String("test").myStartsWith === undefined
true
The results are the same in Firefox 18.0, Safari 6.0.2, and Opera 12.12.
The first three are expected, but I did not expect the fourth check, $wnd.String("test").myStartsWith === undefined, to be true.
Why is it that myStartsWith is not available in string objects returned by calling $wnd.String in a non-constructor context?
Because the non-constructor String function just applies
ToStringand returns a primitive string value. If you access a property of that, the String constructor of the current global context is used – the one without a modified prototype. Sois evaluated to
and is equivalent to
which is
undefinedof course.