/* Setup for the polyfill error-reporting test.
 *
 * Concatenated ahead of polyfill.js by run-jstests.sh, so it runs before the
 * polyfill IIFE and can both capture its warnings and arrange for one section
 * to fail. polyfill-report-check.js is concatenated after and asserts.
 *
 * The failure is arranged with a value that has NO callable toString: that is
 * the shape that used to make the report throw over the error it was naming
 * ("TypeError: not a function at section (polyfill.js:180)"), losing the
 * section and the cause both. */

/* polyfill.js patches these two at top level, outside its own try/catch,
 * because in the browser the bindings always exist. Off-browser they have to
 * be supplied or the file dies on a ReferenceError before the part under
 * test. Everything further down guards its own globals. */
globalThis.DOMTokenList = function () { };
globalThis.DOMSettableTokenList = function () { };

/* CSS.supports asks the engine rather than a table: it sets the declaration
 * on a throwaway element and sees whether it stuck. Stand in for libcss with
 * a style object that accepts a couple of known declarations and drops the
 * rest -- the same contract, so the polyfill's parsing and branching can be
 * checked without a CSS engine.
 *
 * CSS itself is a FUNCTION here, not a plain object: nsgenbind publishes every
 * IDL interface as an interface object, which is why `typeof CSS` guards did
 * not catch the missing operation on the guest. */
globalThis.CSS = function CSS() { };

var SUPPORTED = { 'display': ['grid', 'flex', 'block'], 'color': ['red'] };

/* selector() is answered the same way -- by handing the selector to the
 * selector engine. Stand in for it with one that throws on a couple of
 * shapes libcss would not parse, and takes everything else. */
function fakeQuerySelector(sel)
{
	if (/::-webkit-|:has\(/.test(sel) || sel.indexOf('%%%') >= 0)
		throw new SyntaxError('bad selector: ' + sel);
	return null;
}

globalThis.document = {
	querySelector: fakeQuerySelector,
	createElement: function () {
		var stored = {};
		return {
			querySelector: fakeQuerySelector,
			style: {
				setProperty: function (prop, val) {
					var allowed = SUPPORTED[prop];
					if (allowed && allowed.indexOf(val) >= 0)
						stored[prop] = val;
				},
				getPropertyValue: function (prop) {
					return stored[prop] || '';
				}
			}
		};
	}
};

var WARNINGS = [];

globalThis.console = {
	warn: function (msg) { WARNINGS.push(String(msg)); },
	error: function (msg) { WARNINGS.push(String(msg)); },
	log: function () { }
};

/* Object.create(null) has no prototype, so no toString: 'x: ' + POISON
 * throws TypeError inside ToString rather than producing a string. */
var POISON = Object.create(null);
POISON.marker = 'poison-marker';

/* A function-typed value whose .prototype throws POISON. The XHR body
 * serialisation section reads XMLHttpRequest.prototype after checking that
 * XMLHttpRequest is a function, so this fails that section and nothing else.
 * A Proxy is needed because a plain function's own `prototype` slot is
 * non-configurable and cannot be redefined as a throwing accessor. */
globalThis.XMLHttpRequest = new Proxy(function () { }, {
	get: function (target, key) {
		if (key === 'prototype') {
			throw POISON;
		}
		return target[key];
	}
});
