-
Notifications
You must be signed in to change notification settings - Fork 83
/
Context.js
104 lines (88 loc) · 2.62 KB
/
Context.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/**
* Context
* @lastModified 2019086
* @forwardCompatibleTo 2019086
* @createAt 2019086
*/
import Window from './Window';
import Document from './Document';
import Location from './Location';
import History from './History';
import { getFetchCredentials } from './utils/credentials';
class Context {
constructor( conf, frame ){
this.location = new Location(frame.contentWindow.location);
this.history = new History(conf.id, frame.contentWindow);
this.window = new Window( conf, this, frame, location);
this.allowResources = conf.allowResources || [];
let body = conf.body;
if (conf.disableBody) {
body = document.body;
} else if (!conf.body) {
body = document.createElement( 'body' );
document.documentElement.appendChild( body );
}
this.body = body;
this.document = new Document( {
enableScriptEscape: true,
...conf
}, this, frame, location );
this.baseFrame = frame;
this._listenerMap = new Map();
this.window.__IS_CONSOLE_OS_CONTEXT__ = true
}
async loadScripts(url) {
const resp = await fetch(url, {credentials: getFetchCredentials(url)});
const code = await resp.text();
this.evalScript(code, url);
}
evalScript(code, url="") {
const resolver = new Function(`
return function ({window, location, history, document}){
with(window.__CONSOLE_OS_GLOBAL_VARS_) {
try {
${code}
}
catch(e) {
console.log(e)
}
}
}//@ sourceMappingURL=${url}`)
resolver().call(this.window, {...this})
}
updateBody(dom) {
this.body = dom;
}
remove(){
this.document.removeEventListeners();
if( this.baseFrame ){
if( this.baseFrame.parentNode ){
this.baseFrame.parentNode.removeChild( this.baseFrame );
}else{
this.baseFrame.setAttribute( 'src', 'about:blank' );
}
}
}
static create( conf ){
return new Promise((resolve) => {
const iframe = document.createElement( 'iframe' );
// TODO: change src to a reasonable value.
iframe.setAttribute( 'src', conf.url ? conf.url : '/api.json');
iframe.style.cssText = 'position: absolute; top: -20000px; width: 100%; height: 1px;';
document.body.appendChild( iframe );
// the onload will no trigger when src is about:blank
if (conf.url === 'about:blank') {
return resolve(new this( conf, iframe ));
}
iframe.onload = () => {
resolve(new this( conf, iframe ));
}
})
}
static async remove( context ){
if( context.remove ){
context.remove();
}
}
}
export default Context;