
class SafariRemoteNotification {
	toString() {
		return "[object SafariRemoteNotification]"
	}
};

window.safari = new SafariRemoteNotification();
safari = {};
safari.pushNotification = new SafariRemoteNotification();

class AudioParam {
	
	linearRampToValueAtTime(value, endTime) { return this; }
	exponentialRampToValueAtTime(value, endTime) { return this; }
	setTargetAtTime(target, startTime, timeConstant) { return this; }
	setValueCurveAtTime(values, startTime, duration) { return this; }
	cancelScheduledValues(startTime) { return this; }
	cancelAndHoldAtTime(cancelTime) { return this; }
	setValueAtTime() {}
	
	constructor() {
		this.defaultValue = 0;
		this.maxValue = 1000;
		this.minValue = 0;
		this.value = 0;
	}
	
};

class AudioContextBuffer {
	getChannelData(n) { return [0,0]; }
	constructor() {
		this.numberOfChannels = 2;
	}
}

class AudioContextGain {
	setValueAtTime(x1, x2) {};
	connect(dest) {};
	disconnect() {};
	constructor(){
		this.gain = this;
	}
};

class AudioContextCompressor {
	connect(x1) {}
		
	constructor() {
	  this.threshold = new AudioParam();
	  this.knee = new AudioParam();
	  this.ratio = new AudioParam();
	  this.reduction = new AudioParam();
	  this.attack = new AudioParam();
	  this.release = new AudioParam();
	}
};

class AudioContext {
	createBuffer() { return new AudioContextBuffer(); }
	createGain() { return new AudioContextGain(); }
	createGainNode() { return new AudioContextGain(); }
	decodeAudioData(x1, x2, x3) { x3(); }
	createDynamicsCompressor() { return new AudioContextCompressor(); }
	createOscillator() { return new OscillatorNode(); }
	createScriptProcessor(bufferSize, numberOfInputChannels, numberOfOutputChannels) {
		return new ScriptProcessorNode();
	}
	
	toString() {
		return "[object AudioContext]"
	}

	constructor() {
		this.sampleRate = 0;
	}
};

class AudioNode {
	
	constructor() {
		this.context = new AudioContext();
		this.numberOfInputs = 1;
		this.numberOfOutputs = 1;
		this.channelCount = 2;
		this.channelCountMode = "max";
		this.channelInterpretation = "speakers";
	}
	
	connect(destination, outputIndex) { return this; }
	disconnect(destination, output, input) { }
	
}

class OscillatorNode extends AudioNode {
	
	constructor() {
		super();
		
		this.frequency = new AudioParam();
		this.detune = new AudioParam();
		this.type = "square"
	}
	
	setPeriodicWave(x1) { }
	start(x1) { }
	stop(x1) { }
};

class ScriptProcessorNode extends AudioNode {
	
	constructor() {
		super();
		
		this.bufferSize = 256;
	}
	
	addEventListener(type, listener, options) {}
	
};

class ResizeObserver {
	
	observe(x1) {};
	unobserve(x1) {};
	disconnect() {};
	
	constructor(x1) {
		
	}
};

window.ResizeObserver = ResizeObserver;

class IntersectionObserver {
	
	disconnect() {};
	observe(x1) {
		return true;
	};
	unobserve(x1) {};

	constructor(callback, options) {		
	}
	
};

window.AudioContext = AudioContext;

window.performance.clearMarks = function (name) {};
window.performance.clearMeasures = function (name) {};
window.performance.mark = function (name) {};
window.performance.measure = function (x1, x2, x3) {};
window.performance.getEntriesByType = function (name) {
	return [];
};
window.performance.getEntriesByName = function (name) {
	return [];
};

window.performance.getEntries = function () {
	return [];
}

window.performance.clearResourceTimings = function () {
	
}

window.performance.setResourceTimingBufferSize = function (size) {
	
}

document.requestFullscreen = function() {};
document.exitFullscreen = function() {};
document.fullscreenElement = document.createElement("script");
document.fullscreenEnabled = function() {};
document.fullscreenchange = function() {};
document.fullscreenerror = function() {};

