1
0
mirror of https://github.com/webrecorder/pywb.git synced 2025-03-15 00:03:28 +01:00

Added window.Text override to wombat.js to account for css in JS (#382)

frameworks that like to append a single text node as a child to a style
node modifying and then only modify that text node to add/remove css
dynamically via:
- initTextNodeOverrides (entry point)
- overrideTextProtoFunction (overrides the appendData, insertData, and replaceData functions of inherited by Text)
- overrideTextProtoGetSet (overrides property getters and setters of data and wholeText)
Added window.CSSStyleSheet.insertRule override
- dynamically adds a raw css rule (text) to an existing stylesheet
This commit is contained in:
John Berlin 2018-10-04 13:41:48 -04:00 committed by Ilya Kreymer
parent ec0df7b9ae
commit e7098522b2

View File

@ -1617,12 +1617,12 @@ var _WBWombat = function($wbwindow, wbinfo) {
}
//============================================
function style_replacer(match, n1, n2, n3, offset, string) {
return n1 + rewrite_url(n2) + n3;
}
function rewrite_style(value)
{
function style_replacer(match, n1, n2, n3, offset, string) {
return n1 + rewrite_url(n2) + n3;
}
if (!value) {
return value;
}
@ -2118,8 +2118,17 @@ var _WBWombat = function($wbwindow, wbinfo) {
override_style_attr(style_proto, "borderImageSource", "border-image-source");
override_style_setProp(style_proto);
if ($wbwindow.CSSStyleSheet && $wbwindow.CSSStyleSheet.prototype) {
// https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule
// ruleText is a string of raw css....
var oInsertRule = $wbwindow.CSSStyleSheet.prototype.insertRule;
$wbwindow.CSSStyleSheet.prototype.insertRule = function (ruleText, index) {
return oInsertRule.call(this, rewrite_style(ruleText), index);
};
}
}
//============================================
function override_style_setProp(style_proto) {
var orig_setProp = style_proto.setProperty;
@ -2329,7 +2338,75 @@ var _WBWombat = function($wbwindow, wbinfo) {
Object.defineProperty($wbwindow.FontFace.prototype, "constructor", {value: $wbwindow.FontFace});
$wbwindow.FontFace.__wboverriden__ = true;
}
//============================================
function overrideTextProtoGetSet(textProto, whichProp) {
var orig_getter = get_orig_getter(textProto, whichProp);
var setter;
// data, from CharacterData, is both readable and writable whereas wholeText, from Text, is not
if (whichProp === 'data') {
var orig_setter = get_orig_setter(textProto, whichProp);
setter = function (orig) {
var res = orig;
if (!this._no_rewrite && this.parentElement && this.parentElement.tagName === 'STYLE') {
res = rewrite_style(orig);
}
return orig_setter.call(this, res);
};
}
var getter = function () {
var res = orig_getter.call(this);
if (!this._no_rewrite && this.parentElement && this.parentElement.tagName === 'STYLE') {
res = res.replace(wb_unrewrite_rx, "");
}
return res;
};
def_prop(textProto, whichProp, setter, getter);
}
function overrideTextProtoFunction(textProto, whichFN) {
var original = textProto[whichFN];
textProto[whichFN] = function () {
var args;
if (arguments.length > 0 && this.parentElement && this.parentElement.tagName === 'STYLE') {
// appendData(DOMString data); dataIndex = 0
// insertData(unsigned long offset, DOMString data); dataIndex = 1
// replaceData(unsigned long offset, unsigned long count, DOMString data); dataIndex = 2
args = new Array(arguments.length);
var dataIndex = arguments.length - 1;
if (dataIndex === 2) {
args[0] = arguments[0];
args[1] = arguments[1];
} else if (dataIndex === 1) {
args[0] = arguments[0];
}
args[dataIndex] = rewrite_style(arguments[dataIndex]);
} else {
args = arguments;
}
if (original.__WB_orig_apply) {
return original.__WB_orig_apply(this, args);
}
return original.apply(this, args);
};
}
function initTextNodeOverrides($wbwindow) {
if (!$wbwindow.Text || !$wbwindow.Text.prototype) return;
// https://dom.spec.whatwg.org/#characterdata and https://dom.spec.whatwg.org/#interface-text
// depending on the JS frameworks used some pages include JS that will append a single text node child
// to a style tag and then progressively modify that text nodes data for changing the css values that
// style tag contains
var textProto = $wbwindow.Text.prototype;
// override inherited CharacterData functions
overrideTextProtoFunction(textProto, 'appendData');
overrideTextProtoFunction(textProto, 'insertData');
overrideTextProtoFunction(textProto, 'replaceData');
// override property getters and setters
overrideTextProtoGetSet(textProto, 'data');
overrideTextProtoGetSet(textProto, 'wholeText');
}
//============================================
function init_wombat_loc(win) {
@ -3662,8 +3739,10 @@ var _WBWombat = function($wbwindow, wbinfo) {
init_web_worker_override();
init_service_worker_override();
initSharedWorkerOverride();
// text node overrides for js frameworks doing funky things with CSS
initTextNodeOverrides($wbwindow);
// innerHTML can be overriden on prototype!
override_html_assign($wbwindow.HTMLElement, "innerHTML", true);
override_html_assign($wbwindow.HTMLElement, "outerHTML", true);