UNPKG

@danielkalen/simplybind

Version:

Magically simple, framework-less one-way/two-way data binding for frontend/backend in ~5kb.

1,780 lines (1,477 loc) 1.17 MB
(function (require, global) { require = (function (cache, modules, cx) { return function (r) { if (!modules[r]) throw new Error(r + ' is not a module'); return cache[r] ? cache[r].exports : ((cache[r] = { exports: {} }, cache[r].exports = modules[r].call(cx, require, cache[r], cache[r].exports))); }; })({}, { 74: function (require, module, exports) { "use strict"; module.exports = { injectIntoThis: true, injectInto: null, properties: ["spy", "stub", "mock", "clock", "server", "requests"], useFakeTimers: true, useFakeServer: true }; ; return module.exports; }, 87: function (require, module, exports) { "use strict"; var color = require(99); var timesInWords = require(82); var sinonFormat = require(76); var sinonMatch = require(11); var jsDiff = require(100); var push = Array.prototype.push; function colorSinonMatchText(matcher, calledArg, calledArgMessage) { if (!matcher.test(calledArg)) { matcher.message = color.red(matcher.message); if (calledArgMessage) { calledArgMessage = color.green(calledArgMessage); } } return calledArgMessage + " " + matcher.message; } function colorDiffText(diff) { var objects = diff.map(function (part) { var text = part.value; if (part.added) { text = color.green(text); } else if (part.removed) { text = color.red(text); } if (diff.length === 2) { text += " "; // format simple diffs } return text; }); return objects.join(""); } module.exports = { c: function (spyInstance) { return timesInWords(spyInstance.callCount); }, n: function (spyInstance) { return spyInstance.toString(); }, D: function (spyInstance, args) { var message = ""; for (var i = 0, l = spyInstance.callCount; i < l; ++i) { // describe multiple calls if (l > 1) { if (i > 0) { message += "\n"; } message += "Call " + (i + 1) + ":"; } var calledArgs = spyInstance.getCall(i).args; for (var j = 0; j < calledArgs.length || j < args.length; ++j) { message += "\n"; var calledArgMessage = j < calledArgs.length ? sinonFormat(calledArgs[j]) : ""; if (sinonMatch.isMatcher(args[j])) { message += colorSinonMatchText(args[j], calledArgs[j], calledArgMessage); } else { var expectedArgMessage = j < args.length ? sinonFormat(args[j]) : ""; var diff = jsDiff.diffJson(calledArgMessage, expectedArgMessage); message += colorDiffText(diff); } } } return message; }, C: function (spyInstance) { var calls = []; for (var i = 0, l = spyInstance.callCount; i < l; ++i) { var stringifiedCall = " " + spyInstance.getCall(i).toString(); if (/\n/.test(calls[i - 1])) { stringifiedCall = "\n" + stringifiedCall; } push.call(calls, stringifiedCall); } return calls.length > 0 ? "\n" + calls.join("\n") : ""; }, t: function (spyInstance) { var objects = []; for (var i = 0, l = spyInstance.callCount; i < l; ++i) { push.call(objects, sinonFormat(spyInstance.thisValues[i])); } return objects.join(", "); }, "*": function (spyInstance, args) { return args.map(function (arg) { return sinonFormat(arg); }).join(", "); } }; ; return module.exports; }, 90: function (require, module, exports) { "use strict"; var deprecated = require(13); var spy = require(17); var wrapMethod = require(84); // This is deprecated and will be removed in a future version of sinon. // We will only consider pull requests that fix serious bugs in the implementation function stubDescriptor(object, property, descriptor) { var wrapper; deprecated.printWarning( "sinon.stub(obj, 'meth', fn) is deprecated and will be removed from " + "the public API in a future version of sinon." + "\n Use stub(obj, 'meth').callsFake(fn)." + "\n Codemod available at https://github.com/hurrymaplelad/sinon-codemod" ); if (!!descriptor && typeof descriptor !== "function" && typeof descriptor !== "object") { throw new TypeError("Custom stub should be a property descriptor"); } if (typeof descriptor === "object" && Object.keys(descriptor).length === 0) { throw new TypeError("Expected property descriptor to have at least one key"); } if (typeof descriptor === "function") { wrapper = spy && spy.create ? spy.create(descriptor) : descriptor; } else { wrapper = descriptor; if (spy && spy.create) { Object.keys(wrapper).forEach(function (type) { wrapper[type] = spy.create(wrapper[type]); }); } } return wrapMethod(object, property, wrapper); } module.exports = stubDescriptor; ; return module.exports; }, 93: function (require, module, exports) { // This is free and unencumbered software released into the public domain. // See LICENSE.md for more information. var encoding = require(102); module.exports = { TextEncoder: encoding.TextEncoder, TextDecoder: encoding.TextDecoder, }; ; return module.exports; }, 28: function (require, module, exports) { "use strict"; var extend = require(75); var functionName = require(68); var valueToString = require(71); var slice = Array.prototype.slice; var join = Array.prototype.join; var useLeftMostCallback = -1; var useRightMostCallback = -2; var nextTick = (function () { if (typeof process === "object" && typeof process.nextTick === "function") { return process.nextTick; } if (typeof setImmediate === "function") { return setImmediate; } return function (callback) { setTimeout(callback, 0); }; })(); function getCallback(behavior, args) { var callArgAt = behavior.callArgAt; if (callArgAt >= 0) { return args[callArgAt]; } var argumentList; if (callArgAt === useLeftMostCallback) { argumentList = args; } if (callArgAt === useRightMostCallback) { argumentList = slice.call(args).reverse(); } var callArgProp = behavior.callArgProp; for (var i = 0, l = argumentList.length; i < l; ++i) { if (!callArgProp && typeof argumentList[i] === "function") { return argumentList[i]; } if (callArgProp && argumentList[i] && typeof argumentList[i][callArgProp] === "function") { return argumentList[i][callArgProp]; } } return null; } function getCallbackError(behavior, func, args) { if (behavior.callArgAt < 0) { var msg; if (behavior.callArgProp) { msg = functionName(behavior.stub) + " expected to yield to '" + valueToString(behavior.callArgProp) + "', but no object with such a property was passed."; } else { msg = functionName(behavior.stub) + " expected to yield, but no callback was passed."; } if (args.length > 0) { msg += " Received [" + join.call(args, ", ") + "]"; } return msg; } return "argument at index " + behavior.callArgAt + " is not a function: " + func; } function callCallback(behavior, args) { if (typeof behavior.callArgAt === "number") { var func = getCallback(behavior, args); if (typeof func !== "function") { throw new TypeError(getCallbackError(behavior, func, args)); } if (behavior.callbackAsync) { nextTick(function () { func.apply(behavior.callbackContext, behavior.callbackArguments); }); } else { func.apply(behavior.callbackContext, behavior.callbackArguments); } } } var proto = { create: function create(stub) { var behavior = extend({}, proto); delete behavior.create; delete behavior.addBehavior; delete behavior.createBehavior; behavior.stub = stub; return behavior; }, isPresent: function isPresent() { return (typeof this.callArgAt === "number" || this.exception || typeof this.returnArgAt === "number" || this.returnThis || typeof this.throwArgAt === "number" || this.fakeFn || this.returnValueDefined); }, invoke: function invoke(context, args) { callCallback(this, args); if (this.exception) { throw this.exception; } else if (typeof this.returnArgAt === "number") { return args[this.returnArgAt]; } else if (this.returnThis) { return context; } else if (typeof this.throwArgAt === "number") { if (args.length < this.throwArgAt) { throw new TypeError( "throwArgs failed: " + this.throwArgAt + " arguments required but only " + args.length + " present" ); } throw args[this.throwArgAt]; } else if (this.fakeFn) { return this.fakeFn.apply(context, args); } else if (this.resolve) { return (this.promiseLibrary || Promise).resolve(this.returnValue); } else if (this.reject) { return (this.promiseLibrary || Promise).reject(this.returnValue); } else if (this.callsThrough) { return this.stub.wrappedMethod.apply(context, args); } return this.returnValue; }, onCall: function onCall(index) { return this.stub.onCall(index); }, onFirstCall: function onFirstCall() { return this.stub.onFirstCall(); }, onSecondCall: function onSecondCall() { return this.stub.onSecondCall(); }, onThirdCall: function onThirdCall() { return this.stub.onThirdCall(); }, withArgs: function withArgs(/* arguments */) { throw new Error( "Defining a stub by invoking \"stub.onCall(...).withArgs(...)\" " + "is not supported. Use \"stub.withArgs(...).onCall(...)\" " + "to define sequential behavior for calls with certain arguments." ); } }; function createAsyncVersion(syncFnName) { return function () { var result = this[syncFnName].apply(this, arguments); this.callbackAsync = true; return result; }; } // create asynchronous versions of callsArg* and yields* methods Object.keys(proto).forEach(function (method) { // need to avoid creating anotherasync versions of the newly added async methods if (method.match(/^(callsArg|yields)/) && !method.match(/Async/)) { proto[method + "Async"] = createAsyncVersion(method); } }); function createBehavior(behaviorMethod) { return function () { this.defaultBehavior = this.defaultBehavior || proto.create(this); this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments); return this; }; } function addBehavior(stub, name, fn) { proto[name] = function () { fn.apply(this, [this].concat([].slice.call(arguments))); return this.stub || this; }; stub[name] = createBehavior(name); } proto.addBehavior = addBehavior; proto.createBehavior = createBehavior; module.exports = proto; ; return module.exports; }, 86: function (require, module, exports) { "use strict"; var walk = require(83); var getPropertyDescriptor = require(79); function collectMethod(methods, object, prop, propOwner) { if ( typeof getPropertyDescriptor(propOwner, prop).value === "function" && object.hasOwnProperty(prop) ) { methods.push(object[prop]); } } // This function returns an array of all the own methods on the passed object function collectOwnMethods(object) { var methods = []; walk(object, collectMethod.bind(null, methods, object)); return methods; } module.exports = collectOwnMethods; ; return module.exports; }, 26: function (require, module, exports) { "use strict"; var fakeXhr = require(25); var push = [].push; var format = require(76); var configureLogError = require(73); var pathToRegexp = require(95); function responseArray(handler) { var response = handler; if (Object.prototype.toString.call(handler) !== "[object Array]") { response = [200, {}, handler]; } if (typeof response[2] !== "string") { throw new TypeError("Fake server response body should be string, but was " + typeof response[2]); } return response; } function getDefaultWindowLocation() { return { "host": "localhost", "protocol": "http" }; } function getWindowLocation() { if (typeof window === "undefined") { // Fallback return getDefaultWindowLocation(); } if (typeof window.location !== "undefined") { // Browsers place location on window return window.location; } if ((typeof window.window !== "undefined") && (typeof window.window.location !== "undefined")) { // React Native on Android places location on window.window return window.window.location; } return getDefaultWindowLocation(); } var wloc = getWindowLocation(); var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host); function matchOne(response, reqMethod, reqUrl) { var rmeth = response.method; var matchMethod = !rmeth || rmeth.toLowerCase() === reqMethod.toLowerCase(); var url = response.url; var matchUrl = !url || url === reqUrl || (typeof url.test === "function" && url.test(reqUrl)); return matchMethod && matchUrl; } function match(response, request) { var requestUrl = request.url; if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) { requestUrl = requestUrl.replace(rCurrLoc, ""); } if (matchOne(response, this.getHTTPMethod(request), requestUrl)) { if (typeof response.response === "function") { var ru = response.url; var args = [request].concat(ru && typeof ru.exec === "function" ? ru.exec(requestUrl).slice(1) : []); return response.response.apply(response, args); } return true; } return false; } function incrementRequestCount() { var count = ++this.requestCount; this.requested = true; this.requestedOnce = count === 1; this.requestedTwice = count === 2; this.requestedThrice = count === 3; this.firstRequest = this.getRequest(0); this.secondRequest = this.getRequest(1); this.thirdRequest = this.getRequest(2); this.lastRequest = this.getRequest(count - 1); } var fakeServer = { create: function (config) { var server = Object.create(this); server.configure(config); this.xhr = fakeXhr.useFakeXMLHttpRequest(); server.requests = []; server.requestCount = 0; server.queue = []; server.responses = []; this.xhr.onCreate = function (xhrObj) { xhrObj.unsafeHeadersEnabled = function () { return !(server.unsafeHeadersEnabled === false); }; server.addRequest(xhrObj); }; return server; }, configure: function (config) { var self = this; var whitelist = { "autoRespond": true, "autoRespondAfter": true, "respondImmediately": true, "fakeHTTPMethods": true, "logger": true, "unsafeHeadersEnabled": true }; config = config || {}; Object.keys(config).forEach(function (setting) { if (setting in whitelist) { self[setting] = config[setting]; } }); self.logError = configureLogError(config); }, addRequest: function addRequest(xhrObj) { var server = this; push.call(this.requests, xhrObj); incrementRequestCount.call(this); xhrObj.onSend = function () { server.handleRequest(this); if (server.respondImmediately) { server.respond(); } else if (server.autoRespond && !server.responding) { setTimeout(function () { server.responding = false; server.respond(); }, server.autoRespondAfter || 10); server.responding = true; } }; }, getHTTPMethod: function getHTTPMethod(request) { if (this.fakeHTTPMethods && /post/i.test(request.method)) { var matches = (request.requestBody || "").match(/_method=([^\b;]+)/); return matches ? matches[1] : request.method; } return request.method; }, handleRequest: function handleRequest(xhr) { if (xhr.async) { push.call(this.queue, xhr); } else { this.processRequest(xhr); } }, logger: function () { // no-op; override via configure() }, logError: configureLogError({}), log: function log(response, request) { var str; str = "Request:\n" + format(request) + "\n\n"; str += "Response:\n" + format(response) + "\n\n"; if (typeof this.logger === "function") { this.logger(str); } }, respondWith: function respondWith(method, url, body) { if (arguments.length === 1 && typeof method !== "function") { this.response = responseArray(method); return; } if (arguments.length === 1) { body = method; url = method = null; } if (arguments.length === 2) { body = url; url = method; method = null; } push.call(this.responses, { method: method, url: typeof url === "string" && url !== "" ? pathToRegexp(url) : url, response: typeof body === "function" ? body : responseArray(body) }); }, respond: function respond() { if (arguments.length > 0) { this.respondWith.apply(this, arguments); } var queue = this.queue || []; var requests = queue.splice(0, queue.length); var self = this; requests.forEach(function (request) { self.processRequest(request); }); }, processRequest: function processRequest(request) { try { if (request.aborted) { return; } var response = this.response || [404, {}, ""]; if (this.responses) { for (var l = this.responses.length, i = l - 1; i >= 0; i--) { if (match.call(this, this.responses[i], request)) { response = this.responses[i].response; break; } } } if (request.readyState !== 4) { this.log(response, request); request.respond(response[0], response[1], response[2]); } } catch (e) { this.logError("Fake server request processing", e); } }, restore: function restore() { return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments); }, getRequest: function getRequest(index) { return this.requests[index] || null; }, reset: function reset() { this.resetBehavior(); this.resetHistory(); }, resetBehavior: function resetBehavior() { this.responses.length = this.queue.length = 0; }, resetHistory: function resetHistory() { this.requests.length = this.requestCount = 0; this.requestedOnce = this.requestedTwice = this.requestedThrice = this.requested = false; this.firstRequest = this.secondRequest = this.thirdRequest = this.lastRequest = null; } }; module.exports = fakeServer; ; return module.exports; }, 95: function (require, module, exports) { var isarray = require(103) /** * Expose `pathToRegexp`. */ module.exports = pathToRegexp module.exports.parse = parse module.exports.compile = compile module.exports.tokensToFunction = tokensToFunction module.exports.tokensToRegExp = tokensToRegExp /** * The main path matching regexp utility. * * @type {RegExp} */ var PATH_REGEXP = new RegExp([ // Match escaped characters that would otherwise appear in future matches. // This allows the user to escape special characters that won't transform. '(\\\\.)', // Match Express-style parameters and un-named parameters with a prefix // and optional suffixes. Matches appear as: // // "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?", undefined] // "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined, undefined] // "/*" => ["/", undefined, undefined, undefined, undefined, "*"] '([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))' ].join('|'), 'g') /** * Parse a string for the raw tokens. * * @param {string} str * @param {Object=} options * @return {!Array} */ function parse (str, options) { var tokens = [] var key = 0 var index = 0 var path = '' var defaultDelimiter = options && options.delimiter || '/' var res while ((res = PATH_REGEXP.exec(str)) != null) { var m = res[0] var escaped = res[1] var offset = res.index path += str.slice(index, offset) index = offset + m.length // Ignore already escaped sequences. if (escaped) { path += escaped[1] continue } var next = str[index] var prefix = res[2] var name = res[3] var capture = res[4] var group = res[5] var modifier = res[6] var asterisk = res[7] // Push the current path onto the tokens. if (path) { tokens.push(path) path = '' } var partial = prefix != null && next != null && next !== prefix var repeat = modifier === '+' || modifier === '*' var optional = modifier === '?' || modifier === '*' var delimiter = res[2] || defaultDelimiter var pattern = capture || group tokens.push({ name: name || key++, prefix: prefix || '', delimiter: delimiter, optional: optional, repeat: repeat, partial: partial, asterisk: !!asterisk, pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?') }) } // Match any characters still remaining. if (index < str.length) { path += str.substr(index) } // If the path exists, push it onto the end. if (path) { tokens.push(path) } return tokens } /** * Compile a string to a template function for the path. * * @param {string} str * @param {Object=} options * @return {!function(Object=, Object=)} */ function compile (str, options) { return tokensToFunction(parse(str, options)) } /** * Prettier encoding of URI path segments. * * @param {string} * @return {string} */ function encodeURIComponentPretty (str) { return encodeURI(str).replace(/[\/?#]/g, function (c) { return '%' + c.charCodeAt(0).toString(16).toUpperCase() }) } /** * Encode the asterisk parameter. Similar to `pretty`, but allows slashes. * * @param {string} * @return {string} */ function encodeAsterisk (str) { return encodeURI(str).replace(/[?#]/g, function (c) { return '%' + c.charCodeAt(0).toString(16).toUpperCase() }) } /** * Expose a method for transforming tokens into the path function. */ function tokensToFunction (tokens) { // Compile all the tokens into regexps. var matches = new Array(tokens.length) // Compile all the patterns before compilation. for (var i = 0; i < tokens.length; i++) { if (typeof tokens[i] === 'object') { matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$') } } return function (obj, opts) { var path = '' var data = obj || {} var options = opts || {} var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent for (var i = 0; i < tokens.length; i++) { var token = tokens[i] if (typeof token === 'string') { path += token continue } var value = data[token.name] var segment if (value == null) { if (token.optional) { // Prepend partial segment prefixes. if (token.partial) { path += token.prefix } continue } else { throw new TypeError('Expected "' + token.name + '" to be defined') } } if (isarray(value)) { if (!token.repeat) { throw new TypeError('Expected "' + token.name + '" to not repeat, but received `' + JSON.stringify(value) + '`') } if (value.length === 0) { if (token.optional) { continue } else { throw new TypeError('Expected "' + token.name + '" to not be empty') } } for (var j = 0; j < value.length; j++) { segment = encode(value[j]) if (!matches[i].test(segment)) { throw new TypeError('Expected all "' + token.name + '" to match "' + token.pattern + '", but received `' + JSON.stringify(segment) + '`') } path += (j === 0 ? token.prefix : token.delimiter) + segment } continue } segment = token.asterisk ? encodeAsterisk(value) : encode(value) if (!matches[i].test(segment)) { throw new TypeError('Expected "' + token.name + '" to match "' + token.pattern + '", but received "' + segment + '"') } path += token.prefix + segment } return path } } /** * Escape a regular expression string. * * @param {string} str * @return {string} */ function escapeString (str) { return str.replace(/([.+*?=^!:${}()[\]|\/\\])/g, '\\$1') } /** * Escape the capturing group by escaping special characters and meaning. * * @param {string} group * @return {string} */ function escapeGroup (group) { return group.replace(/([=!:$\/()])/g, '\\$1') } /** * Attach the keys as a property of the regexp. * * @param {!RegExp} re * @param {Array} keys * @return {!RegExp} */ function attachKeys (re, keys) { re.keys = keys return re } /** * Get the flags for a regexp from the options. * * @param {Object} options * @return {string} */ function flags (options) { return options.sensitive ? '' : 'i' } /** * Pull out keys from a regexp. * * @param {!RegExp} path * @param {!Array} keys * @return {!RegExp} */ function regexpToRegexp (path, keys) { // Use a negative lookahead to match only capturing groups. var groups = path.source.match(/\((?!\?)/g) if (groups) { for (var i = 0; i < groups.length; i++) { keys.push({ name: i, prefix: null, delimiter: null, optional: false, repeat: false, partial: false, asterisk: false, pattern: null }) } } return attachKeys(path, keys) } /** * Transform an array into a regexp. * * @param {!Array} path * @param {Array} keys * @param {!Object} options * @return {!RegExp} */ function arrayToRegexp (path, keys, options) { var parts = [] for (var i = 0; i < path.length; i++) { parts.push(pathToRegexp(path[i], keys, options).source) } var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options)) return attachKeys(regexp, keys) } /** * Create a path regexp from string input. * * @param {string} path * @param {!Array} keys * @param {!Object} options * @return {!RegExp} */ function stringToRegexp (path, keys, options) { return tokensToRegExp(parse(path, options), keys, options) } /** * Expose a function for taking tokens and returning a RegExp. * * @param {!Array} tokens * @param {(Array|Object)=} keys * @param {Object=} options * @return {!RegExp} */ function tokensToRegExp (tokens, keys, options) { if (!isarray(keys)) { options = /** @type {!Object} */ (keys || options) keys = [] } options = options || {} var strict = options.strict var end = options.end !== false var route = '' // Iterate over the tokens and create our regexp string. for (var i = 0; i < tokens.length; i++) { var token = tokens[i] if (typeof token === 'string') { route += escapeString(token) } else { var prefix = escapeString(token.prefix) var capture = '(?:' + token.pattern + ')' keys.push(token) if (token.repeat) { capture += '(?:' + prefix + capture + ')*' } if (token.optional) { if (!token.partial) { capture = '(?:' + prefix + '(' + capture + '))?' } else { capture = prefix + '(' + capture + ')?' } } else { capture = prefix + '(' + capture + ')' } route += capture } } var delimiter = escapeString(options.delimiter || '/') var endsWithDelimiter = route.slice(-delimiter.length) === delimiter // In non-strict mode we allow a slash at the end of match. If the path to // match already ends with a slash, we remove it for consistency. The slash // is valid at the end of a path match, not in the middle. This is important // in non-ending mode, where "/test/" shouldn't match "/test//route". if (!strict) { route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?' } if (end) { route += '$' } else { // In non-ending mode, we need the capturing groups to match as much as // possible by using a positive lookahead to the end or next path segment. route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)' } return attachKeys(new RegExp('^' + route, flags(options)), keys) } /** * Normalize the given path string, returning a regular expression. * * An empty array can be passed in for the keys, which will hold the * placeholder key descriptions. For example, using `/user/:id`, `keys` will * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`. * * @param {(string|RegExp|Array)} path * @param {(Array|Object)=} keys * @param {Object=} options * @return {!RegExp} */ function pathToRegexp (path, keys, options) { if (!isarray(keys)) { options = /** @type {!Object} */ (keys || options) keys = [] } options = options || {} if (path instanceof RegExp) { return regexpToRegexp(path, /** @type {!Array} */ (keys)) } if (isarray(path)) { return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options) } return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options) } ; return module.exports; }, 21: function (require, module, exports) { "use strict"; var extend = require(75); var sinonCollection = require(16); var sinonMatch = require(11); var sinonAssert = require(15); var sinonClock = require(23); var fakeServer = require(26); var fakeXhr = require(25); var fakeServerWithClock = require(27); var push = [].push; var sinonSandbox = Object.create(sinonCollection); function exposeValue(sandbox, config, key, value) { if (!value) { return; } if (config.injectInto && !(key in config.injectInto)) { config.injectInto[key] = value; sandbox.injectedKeys.push(key); } else { push.call(sandbox.args, value); } } function prepareSandboxFromConfig(config) { var sandbox = Object.create(sinonSandbox); if (config.useFakeServer) { if (typeof config.useFakeServer === "object") { sandbox.serverPrototype = config.useFakeServer; } sandbox.useFakeServer(); } if (config.useFakeTimers) { if (typeof config.useFakeTimers === "object") { sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers); } else { sandbox.useFakeTimers(); } } return sandbox; } extend(sinonSandbox, { useFakeTimers: function useFakeTimers() { this.clock = sinonClock.useFakeTimers.apply(null, arguments); return this.add(this.clock); }, serverPrototype: fakeServerWithClock, useFakeServer: function useFakeServer() { var proto = this.serverPrototype || fakeServer; if (!proto || !proto.create) { return null; } this.server = proto.create(); return this.add(this.server); }, useFakeXMLHttpRequest: function useFakeXMLHttpRequest() { var xhr = fakeXhr.useFakeXMLHttpRequest(); return this.add(xhr); }, inject: function (obj) { sinonCollection.inject.call(this, obj); if (this.clock) { obj.clock = this.clock; } if (this.server) { obj.server = this.server; obj.requests = this.server.requests; } obj.match = sinonMatch; return obj; }, usingPromise: function (promiseLibrary) { this.promiseLibrary = promiseLibrary; return this; }, restore: function () { if (arguments.length) { throw new Error("sandbox.restore() does not take any parameters. Perhaps you meant stub.restore()"); } sinonCollection.restore.apply(this, arguments); this.restoreContext(); }, restoreContext: function () { var injectedKeys = this.injectedKeys; var injectInto = this.injectInto; if (!injectedKeys) { return; } injectedKeys.forEach(function (injectedKey) { delete injectInto[injectedKey]; }); injectedKeys = []; }, create: function (config) { if (!config) { return Object.create(sinonSandbox); } var sandbox = prepareSandboxFromConfig(config); sandbox.args = sandbox.args || []; sandbox.injectedKeys = []; sandbox.injectInto = config.injectInto; var exposed = sandbox.inject({}); if (config.properties) { config.properties.forEach(function (prop) { var value = exposed[prop] || prop === "sandbox" && sandbox; exposeValue(sandbox, config, prop, value); }); } else { exposeValue(sandbox, config, "sandbox"); } return sandbox; }, match: sinonMatch, assert: sinonAssert }); module.exports = sinonSandbox; ; return module.exports; }, 25: function (require, module, exports) { "use strict"; var TextEncoder = require(93).TextEncoder; var configureLogError = require(73); var sinonEvent = require(24); var extend = require(75); function getWorkingXHR(globalScope) { var supportsXHR = typeof globalScope.XMLHttpRequest !== "undefined"; if (supportsXHR) { return globalScope.XMLHttpRequest; } var supportsActiveX = typeof globalScope.ActiveXObject !== "undefined"; if (supportsActiveX) { return function () { return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0"); }; } return false; } var supportsProgress = typeof ProgressEvent !== "undefined"; var supportsCustomEvent = typeof CustomEvent !== "undefined"; var supportsFormData = typeof FormData !== "undefined"; var supportsArrayBuffer = typeof ArrayBuffer !== "undefined"; var supportsBlob = require(94).isSupported; var isReactNative = global.navigator && global.navigator.product === "ReactNative"; var sinonXhr = { XMLHttpRequest: global.XMLHttpRequest }; sinonXhr.GlobalXMLHttpRequest = global.XMLHttpRequest; sinonXhr.GlobalActiveXObject = global.ActiveXObject; sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject !== "undefined"; sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest !== "undefined"; sinonXhr.workingXHR = getWorkingXHR(global); sinonXhr.supportsCORS = isReactNative || (sinonXhr.supportsXHR && "withCredentials" in (new sinonXhr.GlobalXMLHttpRequest())); var unsafeHeaders = { "Accept-Charset": true, "Accept-Encoding": true, "Connection": true, "Content-Length": true, "Cookie": true, "Cookie2": true, "Content-Transfer-Encoding": true, "Date": true, "Expect": true, "Host": true, "Keep-Alive": true, "Referer": true, "TE": true, "Trailer": true, "Transfer-Encoding": true, "Upgrade": true, "User-Agent": true, "Via": true }; function EventTargetHandler() { var self = this; var events = ["loadstart", "progress", "abort", "error", "load", "timeout", "loadend"]; function addEventListener(eventName) { self.addEventListener(eventName, function (event) { var listener = self["on" + eventName]; if (listener && typeof listener === "function") { listener.call(this, event); } }); } events.forEach(addEventListener); } EventTargetHandler.prototype = sinonEvent.EventTarget; // Note that for FakeXMLHttpRequest to work pre ES5 // we lose some of the alignment with the spec. // To ensure as close a match as possible, // set responseType before calling open, send or respond; function FakeXMLHttpRequest(config) { EventTargetHandler.call(this); this.readyState = FakeXMLHttpRequest.UNSENT; this.requestHeaders = {}; this.requestBody = null; this.status = 0; this.statusText = ""; this.upload = new EventTargetHandler(); this.responseType = ""; this.response = ""; this.logError = configureLogError(config); if (sinonXhr.supportsCORS) { this.withCredentials = false; } if (typeof FakeXMLHttpRequest.onCreate === "function") { FakeXMLHttpRequest.onCreate(this); } } function verifyState(xhr) { if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { throw new Error("INVALID_STATE_ERR"); } if (xhr.sendFlag) { throw new Error("INVALID_STATE_ERR"); } } function getHeader(headers, header) { var foundHeader = Object.keys(headers).filter(function (h) { return h.toLowerCase() === header.toLowerCase(); }); return foundHeader[0] || null; } function excludeSetCookie2Header(header) { return !/^Set-Cookie2?$/i.test(header); } // largest arity in XHR is 5 - XHR#open var apply = function (obj, method, args) { switch (args.length) { case 0: return obj[method](); case 1: return obj[method](args[0]); case 2: return obj[method](args[0], args[1]); case 3: return obj[method](args[0], args[1], args[2]); case 4: return obj[method](args[0], args[1], args[2], args[3]); case 5: return obj[method](args[0], args[1], args[2], args[3], args[4]); default: throw new Error("Unhandled case"); } }; FakeXMLHttpRequest.filters = []; FakeXMLHttpRequest.addFilter = function addFilter(fn) { this.filters.push(fn); }; FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) { var xhr = new sinonXhr.workingXHR(); // eslint-disable-line new-cap [ "open", "setRequestHeader", "send", "abort", "getResponseHeader", "getAllResponseHeaders", "addEventListener", "overrideMimeType", "removeEventListener" ].forEach(function (method) { fakeXhr[method] = function () { return apply(xhr, method, arguments); }; }); var copyAttrs = function (args) { args.forEach(function (attr) { fakeXhr[attr] = xhr[attr]; }); }; var stateChange = function stateChange() { fakeXhr.readyState = xhr.readyState; if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) { copyAttrs(["status", "statusText"]); } if (xhr.readyState >= FakeXMLHttpRequest.LOADING) { copyAttrs(["responseText", "response"]); } if (xhr.readyState === FakeXMLHttpRequest.DONE) { copyAttrs(["responseXML"]); } if (fakeXhr.onreadystatechange) { fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr }); } }; if (xhr.addEventListener) { Object.keys(fakeXhr.eventListeners).forEach(function (event) { /*eslint-disable no-loop-func*/ fakeXhr.eventListeners[event].forEach(function (handler) { xhr.addEventListener(event, handler); }); /*eslint-enable no-loop-func*/ }); xhr.addEventListener("readystatechange", stateChange); } else { xhr.onreadystatechange = stateChange; } apply(xhr, "open", xhrArgs); }; FakeXMLHttpRequest.useFilters = false; function verifyRequestOpened(xhr) { if (xhr.readyState !== FakeXMLHttpRequest.OPENED) { throw new Error("INVALID_STATE_ERR - " + xhr.readyState); } } function verifyRequestSent(xhr) { if (xhr.readyState === FakeXMLHttpRequest.DONE) { throw new Error("Request done"); } } function verifyHeadersReceived(xhr) { if (xhr.async && xhr.readyState !== FakeXMLHttpRequest.HEADERS_RECEIVED) { throw new Error("No headers received"); } } function verifyResponseBodyType(body) { if (typeof body !== "string") { var error = new Error("Attempted to respond to fake XMLHttpRequest with " + body + ", which is not a string."); error.name = "InvalidBodyException"; throw error; } } function convertToArrayBuffer(body, encoding) { return new TextEncoder(encoding || "utf-8").encode(body).buffer; } function isXmlContentType(contentType) { return !contentType || /(text\/xml)|(application\/xml)|(\+xml)/.test(contentType); } function convertResponseBody(responseType, contentType, body) { if (responseType === "" || responseType === "text") { return body; } else if (supportsArrayBuffer && responseType === "arraybuffer") { return convertToArrayBuffer(body); } else if (responseType === "json") { try { return JSON.parse(body); } catch (e) { // Return parsing failure as null return null; } } else if (supportsBlob && responseType === "blob") { var blobOptions = {}; if (contentType) { blobOptions.type = contentType; } return new Blob([convertToArrayBuffer(body)], blobOptions); } else if (responseType === "document") { if (isXmlContentType(contentType)) { return FakeXMLHttpRequest.parseXML(body); } return null; } throw new Error("Invalid responseType " + responseType); } function clearResponse(xhr) { if (xhr.responseType === "" || xhr.responseType === "text") { xhr.response = xhr.responseText = ""; } else { xhr.response = xhr.responseText = null; } xhr.responseXML = null; } FakeXMLHttpRequest.parseXML = function parseXML(text) { // Treat empty string as parsing failure if (text !== "") { try { if (typeof DOMParser !== "undefined") { var parser = new DOMParser(); return parser.parseFromString(text, "text/xml"); } var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM"); xmlDoc.async = "false"; xmlDoc.loadXML(text); return xmlDoc; } catch (e) { // Unable to parse XML - no biggie } } return null; }; FakeXMLHttpRequest.statusCodes = { 100: "Continue", 101: "Switching Protocols", 200: "OK", 201: "Created", 202: "Accepted", 203: "Non-Authoritative Information", 204: "No Content", 205: "Reset Content", 206: "Partial Content", 207: "Multi-Status", 300: "Multiple Choice", 301: "Moved Permanently", 302: "Found", 303: "See Other", 304: "Not Modified", 305: "Use Proxy", 307: "Temporary Redirect", 400: "Bad Request", 401: "Unauthorized", 402: "Payment Required", 403: "Forbidden", 404: "Not Found", 405: "Method Not Allowed", 406: "Not Acceptable", 407: "Proxy Authentication Required", 408: "Request Timeout", 409: "Conflict", 410: "Gone", 411: "Length Required", 412: "Precondition Failed", 413: "Request Entity Too Large", 414: "Request-URI Too Long", 415: "Unsupported Media Type", 416: "Requested Range Not Satisfiable", 417: "Expectation Failed", 422: "Unprocessable Entity", 500: "Internal Server Error", 501: "Not Implemented", 502: "Bad Gateway", 503: "Service Unavailable", 504: "Gateway Timeout", 505: "HTTP Version Not Supported" }; extend(FakeXMLHttpRequest.prototype, sinonEvent.EventTarget, { async: true, open: function open(method, url, async, username, password) { this.method = method; this.url = url; this.async = typeof async === "boolean" ? async : true; this.username = username; this.password = password; clearResponse(this); this.requestHeaders = {}; this.sendFlag = false; if (FakeXMLHttpRequest.useFilters === true) { var xhrArgs = arguments; var defake = FakeXMLHttpRequest.filters.some(function (filter) { return filter.apply(this, xhrArgs); }); if (defake) { FakeXMLHttpRequest.defake(this, arguments); return; } } this.readyStateChange(FakeXMLHttpRequest.OPENED); }, readyStateChange: function readyStateChange(state) { this.readyState = state; var readyStateChangeEvent = new sinonEvent.Event("readystatechange", false, false, this); var event, progress; if (typeof this.onreadystatechange === "function") { try { this.onreadystatechange(readyStateChangeEvent); } catch (e) { this.logError("Fake XHR onreadystatechange handler", e); } } if (this.readyState === FakeXMLHttpRequest.DONE) { if (this.aborted || this.status === 0) { progress = {loaded: 0, total: 0}; event = this.aborted ? "abort" : "error"; } else { progress = {loaded: 100, total: 100}; event = "load"; } if (supportsProgress) { this.upload.dispatchEvent(new sinonEvent.ProgressEvent("progress", progress, this)); this.upload.dispatchEvent(new sinonEvent.ProgressEvent(event, progress, this)); this.upload.dispatchEvent(new sinonEvent.ProgressEvent("loadend", progress, this)); } this.dispatchEvent(new sinonEvent.ProgressEvent("progress", progress, this)); this.dispatchEvent(new sinonEvent.ProgressEvent(event, progress, this)); this.dispatchEvent(new sinonEvent.ProgressEvent("loadend", progress, this)); } this.dispatchEvent(readyStateChangeEvent); }, setRequestHeader: function setRequestHeader(header, value) { verifyState(this); var checkUnsafeHeaders = true; if (typeof this.unsafeHeadersEnabled === "function") { checkUnsafeHeaders = this.unsafeHeadersEnabled(); } if (checkUnsafeHeaders && (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header))) { throw new Error("Refused to set unsafe header \"" + header + "\""); } if (this.requestHeaders[header]) { this.requestHeaders[header] += "," + value; } else { this.requestHeaders[header] = value; } }, setStatus: function setStatus(status) { var sanitizedStatus = typeof status === "number" ? status : 200; verifyRequestOpened(this); this.status = sanitizedStatus; this.statusText = FakeXMLHttpRequest.statusCodes[sanitizedStatus]; }, // Helps testing setResponseHeaders: function setResponseHeaders(headers) { verifyRequestOpened(this); var responseHeaders = this.responseHeaders = {}; Object.keys(headers).forEach(function (header) { responseHeaders[header] = headers[header]; }); if (this.async) { this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED); } else { this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED; } }, // Currently treats ALL data as a DOMString (i.e. no Document) send: function send(data) { verifyState(this); if (!/^(head)$/i.test(this.method)) { var contentType = getHeader(this.requestHeaders, "Content-Type"); if (this.requestHeaders[contentType]) { var value = this.requestHeaders[contentType].split(";"); this.requestHeaders[contentType] = value[0] + ";charset=utf-8"; } else if (supportsFormData && !(data instanceof FormData)) { this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8"; } this.requestBody = data; } this.errorFlag = false; this.sendFlag = this.async; clearResponse(this); this.readyStateChange(FakeXMLHttpRequest.OPENED); if (typeof this.onSend === "function") { this.onSend(this); } this.dispatchEvent(new sinonEvent.Event("loadstart", false, false, this)); }, abort: function abort() { this.aborted = true; clearResponse(this);