Skip to content

Commit d4419d9

Browse files
committed
createlement object wrapper:
- when creating a new <object> element in service-worker mode, instead create a proxy object which wraps the <object> element - if the type is a PDF or SVG, convert to an iframe instead of creating an <object>, since <object> are not handled by service workers
1 parent 7af8bdc commit d4419d9

File tree

2 files changed

+92
-3
lines changed

2 files changed

+92
-3
lines changed

src/objectwrapper.js

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
export const OBJECT_TO_IFRAME_TYPES = ['application/pdf', 'image/svg+xml'];
2+
3+
export function createObjectWrapper(object) {
4+
var listeners = {};
5+
var props = {};
6+
var iframeElem;
7+
8+
function addListener(name, func) {
9+
listeners[name] = func;
10+
}
11+
12+
var proxy = new Proxy(object, {
13+
set(target, prop, value) {
14+
props[prop] = value;
15+
target[prop] = value;
16+
if (iframeElem && prop === "data") {
17+
iframeElem.src = value;
18+
}
19+
return true;
20+
},
21+
22+
get(target, prop, receiver) {
23+
if (prop === "addEventListener") {
24+
addListener.bind(target);
25+
} else if (prop === "__WBProxyRealObj__") {
26+
return toElem(target);
27+
} else if (prop === "__WB_object_proxy__") {
28+
return true;
29+
} else if (prop === "contentDocument" && iframeElem) {
30+
return iframeElem.contentDocument;
31+
}
32+
33+
return target[prop];
34+
},
35+
});
36+
37+
function toElem(objectElem) {
38+
if (iframeElem) {
39+
return iframeElem;
40+
}
41+
42+
if (!OBJECT_TO_IFRAME_TYPES.includes(objectElem.getAttribute("type"))) {
43+
return objectElem;
44+
}
45+
46+
iframeElem = objectElem.ownerDocument.createElement("iframe");
47+
48+
for (const key of Object.keys(props)) {
49+
iframeElem[key] = props[key];
50+
}
51+
52+
for (const key of Object.keys(listeners)) {
53+
iframeElem.addEventListener(key, listeners[key]);
54+
}
55+
56+
return iframeElem;
57+
}
58+
59+
return proxy;
60+
}
61+

src/wombat.js

+31-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { createStorage, Storage } from './customStorage.js';
44
import WombatLocation from './wombatLocation.js';
55
import AutoFetcher from './autoFetcher.js';
66
import { wrapEventListener, wrapSameOriginEventListener } from './listeners.js';
7+
import { OBJECT_TO_IFRAME_TYPES, createObjectWrapper } from "./objectwrapper.js";
78
import {
89
addToStringTagToClass,
910
autobind,
@@ -1637,7 +1638,12 @@ Wombat.prototype.rewriteNodeFuncArgs = function(
16371638
if (newNode) {
16381639
switch (newNode.nodeType) {
16391640
case Node.ELEMENT_NODE:
1640-
this.rewriteElemComplete(newNode);
1641+
if (this.wb_info.isSW && !newNode.parentElement &&
1642+
newNode.tagName === "OBJECT" && newNode.__WB_object_proxy__) {
1643+
newNode = newNode.__WBProxyRealObj__;
1644+
} else {
1645+
this.rewriteElemComplete(newNode);
1646+
}
16411647
break;
16421648
case Node.TEXT_NODE:
16431649
// newNode is the new child of fnThis (the parent node)
@@ -1993,7 +1999,7 @@ Wombat.prototype.rewriteAttr = function(elem, name, absUrlOnly) {
19931999
return changed;
19942000
}
19952001

1996-
var value = this.wb_getAttribute.call(elem, name);
2002+
var value = this.wb_getAttribute.call(this.proxyToObj(elem), name);
19972003

19982004
if (!value || this.startsWith(value, 'javascript:')) return changed;
19992005

@@ -2216,7 +2222,7 @@ Wombat.prototype.rewriteElem = function(elem) {
22162222
}
22172223
break;
22182224
case 'OBJECT':
2219-
if (this.wb_info.isSW && elem.parentElement && elem.getAttribute('type') === 'application/pdf') {
2225+
if (this.wb_info.isSW && elem.parentElement && OBJECT_TO_IFRAME_TYPES.includes(elem.getAttribute('type'))) {
22202226
var iframe = this.$wbwindow.document.createElement('IFRAME');
22212227
for (var i = 0; i < elem.attributes.length; i++) {
22222228
var attr = elem.attributes[i];
@@ -4772,6 +4778,26 @@ Wombat.prototype.initCreateElementNSFix = function() {
47724778
this.$wbwindow.document.createElementNS = createElementNS;
47734779
};
47744780

4781+
4782+
Wombat.prototype.initCreateElement = function() {
4783+
var orig_createElement = this.$wbwindow.document.createElement;
4784+
var wombat = this;
4785+
4786+
var createElement = function createElement(tagName, opts) {
4787+
var result = orig_createElement.call(
4788+
wombat.proxyToObj(this), tagName, opts
4789+
);
4790+
if (tagName === "object") {
4791+
return createObjectWrapper(result);
4792+
}
4793+
4794+
return result;
4795+
};
4796+
4797+
this.$wbwindow.Document.prototype.createElement = createElement;
4798+
this.$wbwindow.document.createElement = createElement;
4799+
}
4800+
47754801
/**
47764802
* Applies an override to Element.insertAdjacentHTML in order to ensure
47774803
* that the strings of HTML to be inserted are rewritten and to
@@ -6710,6 +6736,8 @@ Wombat.prototype.wombatInit = function() {
67106736
// ensure namespace urls are NOT rewritten
67116737
this.initCreateElementNSFix();
67126738

6739+
this.initCreateElement();
6740+
67136741
// DOM
67146742
// OPT skip
67156743
if (!this.wb_opts.skip_dom) {

0 commit comments

Comments
 (0)