(function(global, env) {
	// jshint ignore:line
	if (typeof process === "undefined") {
		global.process = {
			argv: [],
			cwd: function() {
				return "";
			},
			browser: true,
			env: {
				NODE_ENV: env || "development"
			},
			version: "",
			platform:
				global.navigator &&
				global.navigator.userAgent &&
				/Windows/.test(global.navigator.userAgent)
					? "win"
					: ""
		};
	}
})(
	typeof self == "object" && self.Object == Object
		? self
		: typeof process === "object" &&
		  Object.prototype.toString.call(process) === "[object process]"
			? global
			: window,
	"development"
);

var canNamespace_1_0_0_canNamespace = {};

var supportsNativeSymbols = (function() {
	var symbolExists = typeof Symbol !== "undefined" && typeof Symbol.for === "function";

	if (!symbolExists) {
		return false;
	}

	var symbol = Symbol("a symbol for testing symbols");
	return typeof symbol === "symbol";
}());

var CanSymbol;
if(supportsNativeSymbols) {
	CanSymbol = Symbol;
} else {

	var symbolNum = 0;
	CanSymbol = function CanSymbolPolyfill(description){
		var symbolValue = "@@symbol"+(symbolNum++)+(description);

		var symbol = {}; // make it object type

		Object.defineProperties(symbol, {
			toString: {
				value: function(){
					return symbolValue;
				}
			}
		});

		return symbol;
	};

	var descriptionToSymbol = {};
	var symbolToDescription = {};

	/**
	 * @function can-symbol.for for
	 * @parent  can-symbol/methods
	 * @description  Get a symbol based on a known string identifier, or create it if it doesn't exist.
	 *
	 * @signature `canSymbol.for(String)`
	 *
	 * @param { String } description  The string value of the symbol
	 * @return { CanSymbol } The globally unique and consistent symbol with the given string value.
	 */
	CanSymbol.for = function(description){
		var symbol = descriptionToSymbol[description];
		if(!symbol) {
			symbol = descriptionToSymbol[description] = CanSymbol(description);
			symbolToDescription[symbol] = description;
		}
		return symbol;
	};
	/**
	 * @function can-symbol.keyFor keyFor
	 * @parent  can-symbol
	 * @description  Get the description for a symbol.
	 *
	 * @signature `canSymbol.keyFor(CanSymbol)`
	 *
	 * @param { String } description  The string value of the symbol
	 * @return { CanSymbol } The globally unique and consistent symbol with the given string value.
	 */
	CanSymbol.keyFor = function(symbol) {
		return symbolToDescription[symbol];
	};
	["hasInstance","isConcatSpreadable",
		"iterator","match","prototype","replace","search","species","split",
	"toPrimitive","toStringTag","unscopables"].forEach(function(name){
		CanSymbol[name] = CanSymbol("Symbol."+name);
	});
}

// Generate can. symbols.
[
	// ======= Type detection ==========
	"isMapLike",
	"isListLike",
	"isValueLike",
	"isFunctionLike",
	"isScopeLike",
	// ======= Shape detection =========
	"getOwnKeys",
	"getOwnKeyDescriptor",
	"proto",
	// optional
	"getOwnEnumerableKeys",
	"hasOwnKey",
	"hasKey",
	"size",
	"getName",
	"getIdentity",

	// shape manipulation
	"assignDeep",
	"updateDeep",

	// ======= GET / SET
	"getValue",
	"setValue",
	"getKeyValue",
	"setKeyValue",
	"updateValues",
	"addValue",
	"removeValues",
	// ======= Call =========
	"apply",
	"new",
	// ======= Observe =========
	"onValue",
	"offValue",
	"onKeyValue",
	"offKeyValue",
	"getKeyDependencies",
	"getValueDependencies",
	"keyHasDependencies",
	"valueHasDependencies",
	"onKeys",
	"onKeysAdded",
	"onKeysRemoved",
	"onPatches"
	].forEach(function(name){
	CanSymbol.for("can."+name);
});

var canSymbol_1_7_0_canSymbol = canNamespace_1_0_0_canNamespace.Symbol = CanSymbol;

var helpers = {
	makeGetFirstSymbolValue: function(symbolNames){
		var symbols = symbolNames.map(function(name){
			return canSymbol_1_7_0_canSymbol.for(name);
		});
		var length = symbols.length;

		return function getFirstSymbol(obj){
			var index = -1;

			while (++index < length) {
				if(obj[symbols[index]] !== undefined) {
					return obj[symbols[index]];
				}
			}
		};
	},
	// The `in` check is from jQuery’s fix for an iOS 8 64-bit JIT object length bug:
	// https://github.com/jquery/jquery/pull/2185
	hasLength: function(list){
		var type = typeof list;
		if(type === "string" || Array.isArray(list)) {
			return true;
		}
		var length = list && (type !== 'boolean' && type !== 'number' && "length" in list) && list.length;

		// var length = "length" in obj && obj.length;
		return typeof list !== "function" &&
			( length === 0 || typeof length === "number" && length > 0 && ( length - 1 ) in list );
	}
};

var plainFunctionPrototypePropertyNames = Object.getOwnPropertyNames((function(){}).prototype);
var plainFunctionPrototypeProto = Object.getPrototypeOf( (function(){}).prototype );
/**
 * @function can-reflect.isConstructorLike isConstructorLike
 * @parent can-reflect/type
 *
 * @description Test if a value looks like a constructor function.
 *
 * @signature `isConstructorLike(func)`
 *
 * Return `true` if `func` is a function and has a non-empty prototype, or implements
 *  [can-symbol/symbols/new `@@@@can.new`]; `false` otherwise.
 *
 * ```js
 * canReflect.isConstructorLike(function() {}); // -> false
 *
 * function Construct() {}
 * Construct.prototype = { foo: "bar" };
 * canReflect.isConstructorLike(Construct); // -> true
 *
 * canReflect.isConstructorLike({}); // -> false
 * !!canReflect.isConstructorLike({ [canSymbol.for("can.new")]: function() {} }); // -> true
 * ```
 *
 * @param  {*}  func maybe a function
 * @return {Boolean} `true` if a constructor; `false` if otherwise.
 */
function isConstructorLike(func){
	/* jshint unused: false */
	// if you can new it ... it's a constructor
	var value = func[canSymbol_1_7_0_canSymbol.for("can.new")];
	if(value !== undefined) {
		return value;
	}

	if(typeof func !== "function") {
		return false;
	}
	// If there are any properties on the prototype that don't match
	// what is normally there, assume it's a constructor
	var prototype = func.prototype;
	if(!prototype) {
		return false;
	}
	// Check if the prototype's proto doesn't point to what it normally would.
	// If it does, it means someone is messing with proto chains
	if( plainFunctionPrototypeProto !== Object.getPrototypeOf( prototype ) ) {
		return true;
	}

	var propertyNames = Object.getOwnPropertyNames(prototype);
	if(propertyNames.length === plainFunctionPrototypePropertyNames.length) {
		for(var i = 0, len = propertyNames.length; i < len; i++) {
			if(propertyNames[i] !== plainFunctionPrototypePropertyNames[i]) {
				return true;
			}
		}
		return false;
	} else {
		return true;
	}
}

/**
 * @function can-reflect.isFunctionLike isFunctionLike
 * @parent can-reflect/type
 * @description Test if a value looks like a function.
 * @signature `isFunctionLike(obj)`
 *
 *  Return `true` if `func` is a function, or implements
 *  [can-symbol/symbols/new `@@@@can.new`] or [can-symbol/symbols/apply `@@@@can.apply`]; `false` otherwise.
 *
 * ```js
 * canReflect.isFunctionLike(function() {}); // -> true
 * canReflect.isFunctionLike({}); // -> false
 * canReflect.isFunctionLike({ [canSymbol.for("can.apply")]: function() {} }); // -> true
 * ```
 *
 * @param  {*}  obj maybe a function
 * @return {Boolean}
 */
var getNewOrApply = helpers.makeGetFirstSymbolValue(["can.new","can.apply"]);
function isFunctionLike(obj){
	var result,
		symbolValue = !!obj && obj[canSymbol_1_7_0_canSymbol.for("can.isFunctionLike")];

	if (symbolValue !== undefined) {
		return symbolValue;
	}

	result = getNewOrApply(obj);
	if(result !== undefined) {
		return !!result;
	}

	return typeof obj === "function";
}

/**
 * @function can-reflect.isPrimitive isPrimitive
 * @parent can-reflect/type
 * @description Test if a value is a JavaScript primitive.
 * @signature `isPrimitive(obj)`
 *
 * Return `true` if `obj` is not a function nor an object via `typeof`, or is null; `false` otherwise.
 *
 * ```js
 * canReflect.isPrimitive(null); // -> true
 * canReflect.isPrimitive({}); // -> false
 * canReflect.isPrimitive(undefined); // -> true
 * canReflect.isPrimitive(1); // -> true
 * canReflect.isPrimitive([]); // -> false
 * canReflect.isPrimitive(function() {}); // -> false
 * canReflect.isPrimitive("foo"); // -> true
 *
 * ```
 *
 * @param  {*}  obj maybe a primitive value
 * @return {Boolean}
 */
function isPrimitive(obj){
	var type = typeof obj;
	if(obj == null || (type !== "function" && type !== "object") ) {
		return true;
	}
	else {
		return false;
	}
}

var coreHasOwn = Object.prototype.hasOwnProperty;
var funcToString = Function.prototype.toString;
var objectCtorString = funcToString.call(Object);

function isPlainObject(obj) {
	// Must be an Object.
	// Because of IE, we also have to check the presence of the constructor property.
	// Make sure that DOM nodes and window objects don't pass through, as well
	if (!obj || typeof obj !== 'object' ) {
		return false;
	}
	var proto = Object.getPrototypeOf(obj);
	if(proto === Object.prototype || proto === null) {
		return true;
	}
	// partially inspired by lodash: https://github.com/lodash/lodash
	var Constructor = coreHasOwn.call(proto, 'constructor') && proto.constructor;
	return typeof Constructor === 'function' && Constructor instanceof Constructor &&
    	funcToString.call(Constructor) === objectCtorString;
}

/**
 * @function can-reflect.isBuiltIn isBuiltIn
 * @parent can-reflect/type
 * @description Test if a value is a JavaScript built-in type.
 * @signature `isBuiltIn(obj)`
 *
 * Return `true` if `obj` is some type of JavaScript native built-in; `false` otherwise.
 *
 * ```js
 * canReflect.isBuiltIn(null); // -> true
 * canReflect.isBuiltIn({}); // -> true
 * canReflect.isBuiltIn(1); // -> true
 * canReflect.isBuiltIn([]); // -> true
 * canReflect.isBuiltIn(function() {}); // -> true
 * canReflect.isBuiltIn("foo"); // -> true
 * canReflect.isBuiltIn(new Date()); // -> true
 * canReflect.isBuiltIn(/[foo].[bar]/); // -> true
 * canReflect.isBuiltIn(new DefineMap); // -> false
 *
 * ```
 *
 * Not supported in browsers that have implementations of Map/Set where
 * `toString` is not properly implemented to return `[object Map]`/`[object Set]`.
 *
 * @param  {*}  obj maybe a built-in value
 * @return {Boolean}
 */
function isBuiltIn(obj) {

	// If primitive, array, or POJO return true. Also check if
	// it is not a POJO but is some type like [object Date] or
	// [object Regex] and return true.
	if (isPrimitive(obj) ||
		Array.isArray(obj) ||
		isPlainObject(obj) ||
		(Object.prototype.toString.call(obj) !== '[object Object]' &&
			Object.prototype.toString.call(obj).indexOf('[object ') !== -1)) {
		return true;
	}
	else {
		return false;
	}
}

/**
 * @function can-reflect.isValueLike isValueLike
 * @parent can-reflect/type
 * @description Test if a value represents a single value (as opposed to several values).
 *
 * @signature `isValueLike(obj)`
 *
 * Return `true` if `obj` is a primitive or implements [can-symbol/symbols/getValue `@@can.getValue`],
 * `false` otherwise.
 *
 * ```js
 * canReflect.isValueLike(null); // -> true
 * canReflect.isValueLike({}); // -> false
 * canReflect.isValueLike(function() {}); // -> false
 * canReflect.isValueLike({ [canSymbol.for("can.isValueLike")]: true}); // -> true
 * canReflect.isValueLike({ [canSymbol.for("can.getValue")]: function() {} }); // -> true
 * canReflect.isValueLike(canCompute()); // -> true
 * canReflect.isValueLike(new DefineMap()); // -> false
 *
 * ```
 *
 * @param  {*}  obj maybe a primitive or an object that yields a value
 * @return {Boolean}
 */
function isValueLike(obj) {
	var symbolValue;
	if(isPrimitive(obj)) {
		return true;
	}
	symbolValue = obj[canSymbol_1_7_0_canSymbol.for("can.isValueLike")];
	if( typeof symbolValue !== "undefined") {
		return symbolValue;
	}
	var value = obj[canSymbol_1_7_0_canSymbol.for("can.getValue")];
	if(value !== undefined) {
		return !!value;
	}
}

/**
 * @function can-reflect.isMapLike isMapLike
 * @parent can-reflect/type
 *
 * @description Test if a value represents multiple values.
 *
 * @signature `isMapLike(obj)`
 *
 * Return `true` if `obj` is _not_ a primitive, does _not_ have a falsy value for
 * [can-symbol/symbols/isMapLike `@@@@can.isMapLike`], or alternately implements
 * [can-symbol/symbols/getKeyValue `@@@@can.getKeyValue`]; `false` otherwise.
 *
 * ```js
 * canReflect.isMapLike(null); // -> false
 * canReflect.isMapLike(1); // -> false
 * canReflect.isMapLike("foo"); // -> false
 * canReflect.isMapLike({}); // -> true
 * canReflect.isMapLike(function() {}); // -> true
 * canReflect.isMapLike([]); // -> false
 * canReflect.isMapLike({ [canSymbol.for("can.isMapLike")]: false }); // -> false
 * canReflect.isMapLike({ [canSymbol.for("can.getKeyValue")]: null }); // -> false
 * canReflect.isMapLike(canCompute()); // -> false
 * canReflect.isMapLike(new DefineMap()); // -> true
 *
 * ```
 *
 * @param  {*}  obj maybe a Map-like
 * @return {Boolean}
 */
function isMapLike(obj) {
	if(isPrimitive(obj)) {
		return false;
	}
	var isMapLike = obj[canSymbol_1_7_0_canSymbol.for("can.isMapLike")];
	if(typeof isMapLike !== "undefined") {
		return !!isMapLike;
	}
	var value = obj[canSymbol_1_7_0_canSymbol.for("can.getKeyValue")];
	if(value !== undefined) {
		return !!value;
	}
	// everything else in JS is MapLike
	return true;
}

/**
 * @function can-reflect.isObservableLike isObservableLike
 * @parent can-reflect/type
 * @description Test if a value (or its keys) can be observed for changes.
 *
 * @signature `isObservableLike(obj)`
 *
 * Return  `true` if `obj` is _not_ a primitive and implements any of
 * [can-symbol/symbols/onValue `@@@@can.onValue`], [can-symbol/symbols/onKeyValue `@@@@can.onKeyValue`], or
 * [can-symbol/symbols/onPatches `@@@@can.onKeys`]; `false` otherwise.
 *
 * ```js
 * canReflect.isObservableLike(null); // -> false
 * canReflect.isObservableLike({}); // -> false
 * canReflect.isObservableLike([]); // -> false
 * canReflect.isObservableLike(function() {}); // -> false
 * canReflect.isObservableLike({ [canSymbol.for("can.onValue")]: function() {} }); // -> true
 * canReflect.isObservableLike({ [canSymbol.for("can.onKeyValue")]: function() {} }); // -> true
 * canReflect.isObservableLike(canCompute())); // -> true
 * canReflect.isObservableLike(new DefineMap())); // -> true
 * ```
 *
 * @param  {*}  obj maybe an observable
 * @return {Boolean}
 */

// Specially optimized
var onValueSymbol = canSymbol_1_7_0_canSymbol.for("can.onValue"),
	onKeyValueSymbol = canSymbol_1_7_0_canSymbol.for("can.onKeyValue"),
	onPatchesSymbol = canSymbol_1_7_0_canSymbol.for("can.onPatches");
function isObservableLike( obj ) {
	if(isPrimitive(obj)) {
		return false;
	}
	return Boolean(obj[onValueSymbol] || obj[onKeyValueSymbol] || obj[onPatchesSymbol]);
}

/**
 * @function can-reflect.isListLike isListLike
 * @parent can-reflect/type
 *
 * @description Test if a value looks like a constructor function.
 *
 * @signature `isListLike(list)`
 *
 * Return `true` if `list` is a `String`, <br>OR `list` is _not_ a primitive and implements `@@@@iterator`,
 * <br>OR `list` is _not_ a primitive and returns `true` for `Array.isArray()`, <br>OR `list` is _not_ a primitive and has a
 * numerical length and is either empty (`length === 0`) or has a last element at index `length - 1`; <br>`false` otherwise
 *
 * ```js
 * canReflect.isListLike(null); // -> false
 * canReflect.isListLike({}); // -> false
 * canReflect.isListLike([]); // -> true
 * canReflect.isListLike("foo"); // -> true
 * canReflect.isListLike(1); // -> false
 * canReflect.isListLike({ [canSymbol.for("can.isListLike")]: true }); // -> true
 * canReflect.isListLike({ [canSymbol.iterator]: function() {} }); // -> true
 * canReflect.isListLike({ length: 0 }); // -> true
 * canReflect.isListLike({ length: 3 }); // -> false
 * canReflect.isListLike({ length: 3, "2": true }); // -> true
 * canReflect.isListLike(new DefineMap()); // -> false
 * canReflect.isListLike(new DefineList()); // -> true
 * ```
 *
 * @param  {*}  list maybe a List-like
 * @return {Boolean}
 */
function isListLike( list ) {
	var symbolValue,
		type = typeof list;
	if(type === "string") {
		return true;
	}
	if( isPrimitive(list) ) {
		return false;
	}
	symbolValue = list[canSymbol_1_7_0_canSymbol.for("can.isListLike")];
	if( typeof symbolValue !== "undefined") {
		return symbolValue;
	}
	var value = list[canSymbol_1_7_0_canSymbol.iterator];
	if(value !== undefined) {
		return !!value;
	}
	if(Array.isArray(list)) {
		return true;
	}
	return helpers.hasLength(list);
}

/**
 * @function can-reflect.isSymbolLike isSymbolLike
 * @parent can-reflect/type
 *
 * @description Test if a value is a symbol or a [can-symbol].
 *
 * @signature `isSymbolLike(symbol)`
 *
 * Return `true` if `symbol` is a native Symbol, or evaluates to a String with a prefix
 * equal to that of CanJS's symbol polyfill; `false` otherwise.
 *
 * ```js
 * /* ES6 *\/ canReflect.isSymbolLike(Symbol.iterator); // -> true
 * canReflect.isSymbolLike(canSymbol.for("foo")); // -> true
 * canReflect.isSymbolLike("@@symbol.can.isSymbol"); // -> true (due to polyfill for non-ES6)
 * canReflect.isSymbolLike("foo"); // -> false
 * canReflect.isSymbolLike(null); // -> false
 * canReflect.isSymbolLike(1); // -> false
 * canReflect.isSymbolLike({}); // -> false
 * canReflect.isSymbolLike({ toString: function() { return "@@symbol.can.isSymbol"; } }); // -> true
 * ```
 *
 * @param  {*}  symbol maybe a symbol
 * @return {Boolean}
 */

var supportsNativeSymbols$1 = (function() {
	var symbolExists = typeof Symbol !== "undefined" && typeof Symbol.for === "function";

	if (!symbolExists) {
		return false;
	}

	var symbol = Symbol("a symbol for testing symbols");
	return typeof symbol === "symbol";
}());

var isSymbolLike;
if(supportsNativeSymbols$1) {
	isSymbolLike = function(symbol) {
		return typeof symbol === "symbol";
	};
} else {
	var symbolStart = "@@symbol";
	isSymbolLike = function(symbol) {
		if(typeof symbol === "object" && !Array.isArray(symbol)){
			return symbol.toString().substr(0, symbolStart.length) === symbolStart;
		} else {
			return false;
		}
	};
}

/**
 * @function can-reflect.isScopeLike isScopeLike
 * @parent can-reflect/type
 *
 * @description Test if a value represents a can.view.Scope or its API equivalent
 *
 * @signature `isScopeLike(obj)`
 *
 * Return `true` if `obj` is _not_ a primitive, does _not_ have a falsy value for
 * [can-symbol/symbols/isScopeLike `@@@@can.isScopeLike`], or implements the public 
 * API of [can-view-scope] along with `_context` and `_meta` objects; `false` otherwise.
 *
 * ```js
 * canReflect.isScopeLike(null); // -> false
 * canReflect.isScopeLike(1); // -> false
 * canReflect.isScopeLike("foo"); // -> false
 * canReflect.isScopeLike({}); // -> false
 * canReflect.isScopeLike(function() {}); // -> false
 * canReflect.isScopeLike([]); // -> false
 * canReflect.isScopeLike({ [canSymbol.for("can.isScopeLike")]: true }); // -> true
 * canReflect.isScopeLike({
 *   get(){}, set(){}, find(){}, peek(){}, computeData(){}, add(){}, getScope(){},
 *   getHelperOrPartial(){}, getTemplateContext(), addLetContext(){}, cloneFromRef(){},
 *   _meta: {}, _context: {}
 * }); // -> true
 * canReflect.isScopeLike(new can.view.Scope()); // -> true
 *
 * ```
 *
 * @param  {*}  obj maybe a Map-like
 * @return {Boolean}
 */
// note:  older can 2.x scopes do not implement find() or addLetContext() but these are required by later can-stache, so passing 
//   this function is not a guarantee of interoperability.
var fnKeys = ["get", "set", "peek", "computeData", "add", "getScope", "getHelperOrPartial", "getTemplateContext", "cloneFromRef"];
function isScopeLike(obj) {
	if(isPrimitive(obj)) {
		return false;
	}
	var isScopeLike = obj[canSymbol_1_7_0_canSymbol.for("can.isScopeLike")];
	if(typeof isScopeLike !== "undefined") {
		return !!isScopeLike;
	}
	return fnKeys.every(function(key) { return typeof obj[key] === "function"; }) &&
		"_context" in obj &&
		obj._meta && typeof obj._meta === "object";
}


var type = {
	isConstructorLike: isConstructorLike,
	isFunctionLike: isFunctionLike,
	isListLike: isListLike,
	isMapLike: isMapLike,
	isObservableLike: isObservableLike,
	isScopeLike: isScopeLike,
	isPrimitive: isPrimitive,
	isBuiltIn: isBuiltIn,
	isValueLike: isValueLike,
	isSymbolLike: isSymbolLike,
	/**
	 * @function can-reflect.isMoreListLikeThanMapLike isMoreListLikeThanMapLike
	 * @parent can-reflect/type
	 *
	 * @description Test if a value should be treated as a list instead of a map.
	 *
	 * @signature `isMoreListLikeThanMapLike(obj)`
	 *
	 * Return  `true` if `obj` is an Array, declares itself to be more ListLike with
	 * `@@@@can.isMoreListLikeThanMapLike`, or self-reports as ListLike but not as MapLike; `false` otherwise.
	 *
	 * ```js
	 * canReflect.isMoreListLikeThanMapLike([]); // -> true
	 * canReflect.isMoreListLikeThanMapLike(null); // -> false
	 * canReflect.isMoreListLikeThanMapLike({}); // -> false
	 * canReflect.isMoreListLikeThanMapLike(new DefineList()); // -> true
	 * canReflect.isMoreListLikeThanMapLike(new DefineMap()); // -> false
	 * canReflect.isMoreListLikeThanMapLike(function() {}); // -> false
	 * ```
	 *
	 * @param  {Object}  obj the object to test for ListLike against MapLike traits.
	 * @return {Boolean}
	 */
	isMoreListLikeThanMapLike: function(obj){
		if(Array.isArray(obj)) {
			return true;
		}
		if(obj instanceof Array) {
			return true;
		}
		if( obj == null ) {
			return false;
		}
		var value = obj[canSymbol_1_7_0_canSymbol.for("can.isMoreListLikeThanMapLike")];
		if(value !== undefined) {
			return value;
		}
		var isListLike = this.isListLike(obj),
			isMapLike = this.isMapLike(obj);
		if(isListLike && !isMapLike) {
			return true;
		} else if(!isListLike && isMapLike) {
			return false;
		}
	},
	/**
	 * @function can-reflect.isIteratorLike isIteratorLike
	 * @parent can-reflect/type
	 * @description Test if a value looks like an iterator.
	 * @signature `isIteratorLike(obj)`
	 *
	 * Return `true` if `obj` has a key `"next"` pointing to a zero-argument function; `false` otherwise
	 *
	 * ```js
	 * canReflect.isIteratorLike([][Symbol.iterator]()); // -> true
	 * canReflect.isIteratorLike(new DefineList()[canSymbol.iterator]()); // -> true
	 * canReflect.isIteratorLike(new DefineMap()[canSymbol.iterator]()); // -> true
	 * canReflect.isIteratorLike(null); // -> false
	 * canReflect.isIteratorLike({ next: function() {} }); // -> true
	 * canReflect.isIteratorLike({ next: function(foo) {} }); // -> false (iterator nexts do not take arguments)
	 * ```
	 *
	 * @param  {Object}  obj the object to test for Iterator traits
	 * @return {Boolean}
	 */
	isIteratorLike: function(obj){
		return obj &&
			typeof obj === "object" &&
			typeof obj.next === "function" &&
			obj.next.length === 0;
	},
	/**
	 * @function can-reflect.isPromise isPromise
	 * @parent can-reflect/type
	 * @description Test if a value is a promise.
	 *
	 * @signature `isPromise(obj)`
	 *
	 * Return `true` if `obj` is an instance of promise or `.toString` returns `"[object Promise]"`.
	 *
	 * ```js
	 * canReflect.isPromise(Promise.resolve()); // -> true
	 * ```
	 *
	 * @param  {*}  obj the object to test for Promise traits.
	 * @return {Boolean}
	 */
	isPromise: function(obj){
		return (obj instanceof Promise || (Object.prototype.toString.call(obj) === '[object Promise]'));
	},
	/**
	 * @function can-reflect.isPlainObject isPlainObject
	 * @parent can-reflect/type
	 * @description Test if a value is an object created with `{}` or `new Object()`.
	 *
	 * @signature `isPlainObject(obj)`
	 *
	 * Attempts to determine if an object is a plain object like those you would create using the curly braces syntax: `{}`. The following are not plain objects:
	 *
	 * 1. Objects with prototypes (created using the `new` keyword).
	 * 2. Booleans.
	 * 3. Numbers.
	 * 4. NaN.
	 *
	 * ```js
	 * var isPlainObject = require("can-reflect").isPlainObject;
	 *
	 * // Created with {}
	 * console.log(isPlainObject({})); // -> true
	 *
	 * // new Object
	 * console.log(isPlainObject(new Object())); // -> true
	 *
	 * // Custom object
	 * var Ctr = function(){};
	 * var obj = new Ctr();
	 *
	 * console.log(isPlainObject(obj)); // -> false
	 * ```
	 *
	 * @param  {Object}  obj the object to test.
	 * @return {Boolean}
	 */
	isPlainObject: isPlainObject
};

var call = {
	/**
	 * @function {function(...), Object, ...} can-reflect/call.call call
	 * @parent can-reflect/call
	 * @description  Call a callable, with a context object and parameters
	 *
	 * @signature `call(func, context, ...rest)`
	 *
	 * Call the callable `func` as if it were a function, bound to `context` and with any additional parameters
	 * occurring after `context` set to the positional parameters.
	 *
	 * Note that `func` *must* either be natively callable, implement [can-symbol/symbols/apply @@@@can.apply],
	 * or have a callable `apply` property to work with `canReflect.call`
	 *
	 * ```js
	 * var compute = canCompute("foo");
	 *
	 * canReflect.call(compute, null, "bar");
	 * canReflect.call(compute, null); // -> "bar"
	 * ```
	 *
	 * @param  {function(...)} func the function to call with the supplied arguments
	 * @param  {Object} context the context object to set as `this` on the function call
	 * @param  {*} rest any arguments after `context` will be passed to the function call
	 * @return {*}  return types and values are determined by the call to `func`
	 */
	call: function(func, context){
		var args = [].slice.call(arguments, 2);
		var apply = func[canSymbol_1_7_0_canSymbol.for("can.apply")];
		if(apply) {
			return apply.call(func, context, args);
		} else {
			return func.apply(context, args);
		}
	},
	/**
	 * @function {function(...), Object, ...} can-reflect/call.apply apply
	 * @parent can-reflect/call
	 * @description  Call a callable, with a context object and a list of parameters
	 *
	 * @signature `apply(func, context, args)`
	 *
	 * Call the callable `func` as if it were a function, bound to `context` and with any additional parameters
	 * contained in the Array-like `args`
	 *
	 * Note that `func` *must* either be natively callable, implement [can-symbol/symbols/apply @@@@can.apply],
	 * or have a callable `apply` property to work with `canReflect.apply`
	 *
	 * ```js
	 * var compute = canCompute("foo");
	 *
	 * canReflect.apply(compute, null, ["bar"]);
	 * canReflect.apply(compute, null, []); // -> "bar"
	 * ```
	 *
	 * @param  {function(...)} func the function to call
	 * @param  {Object} context the context object to set as `this` on the function call
	 * @param  {*} args arguments to be passed to the function call
	 * @return {*}  return types and values are determined by the call to `func`
	 */
	apply: function(func, context, args){
		var apply = func[canSymbol_1_7_0_canSymbol.for("can.apply")];
		if(apply) {
			return apply.call(func, context, args);
		} else {
			return func.apply(context, args);
		}
	},
	/**
	 * @function {function(...), ...} can-reflect/call.new new
	 * @parent can-reflect/call
	 * @description  Construct a new instance of a callable constructor
	 *
	 * @signature `new(func, ...rest)`
	 *
	 * Call the callable `func` as if it were a function, bound to a new instance of `func`, and with any additional
	 * parameters occurring after `func` set to the positional parameters.
	 *
	 * Note that `func` *must* either implement [can-symbol/symbols/new @@@@can.new],
	 * or have a callable `apply` property *and* a prototype to work with `canReflect.new`
	 *
	 * ```js
	 * canReflect.new(DefineList, ["foo"]); // -> ["foo"]<DefineList>
	 * ```
	 *
	 * @param  {function(...)} func a constructor
	 * @param  {*} rest arguments to be passed to the constructor
	 * @return {Object}  if `func` returns an Object, that returned Object; otherwise a new instance of `func`
	 */
	"new": function(func){
		var args = [].slice.call(arguments, 1);
		var makeNew = func[canSymbol_1_7_0_canSymbol.for("can.new")];
		if(makeNew) {
			return makeNew.apply(func, args);
		} else {
			var context = Object.create(func.prototype);
			var ret = func.apply(context, args);
			if(type.isPrimitive(ret)) {
				return context;
			} else {
				return ret;
			}
		}
	}
};

var setKeyValueSymbol = canSymbol_1_7_0_canSymbol.for("can.setKeyValue"),
	getKeyValueSymbol = canSymbol_1_7_0_canSymbol.for("can.getKeyValue"),
	getValueSymbol = canSymbol_1_7_0_canSymbol.for("can.getValue"),
	setValueSymbol = canSymbol_1_7_0_canSymbol.for("can.setValue");

var reflections = {
	/**
	 * @function {Object, String, *} can-reflect.setKeyValue setKeyValue
	 * @parent can-reflect/get-set
	 * @description Set the value of a named property on a MapLike object.
	 *
	 * @signature `setKeyValue(obj, key, value)`
	 *
	 * Set the property on Map-like `obj`, identified by the String, Symbol or Object value `key`, to the value `value`.
	 * The default behavior can be overridden on `obj` by implementing [can-symbol/symbols/setKeyValue @@@@can.setKeyValue],
	 * otherwise native named property access is used for string keys, and `Object.defineProperty` is used to set symbols.
	 *
	 * ```js
	 * var foo = new DefineMap({ bar: "baz" });
	 *
	 * canReflect.setKeyValue(foo, "bar", "quux");
	 * foo[bar]; // -> "quux"
	 * ```
	 * @param  {Object} obj   the object to set on
	 * @param  {String} key   the key for the property to set
	 * @param  {*} value      the value to set on the object
	 */
	setKeyValue: function(obj, key, value){
		if( type.isSymbolLike(key) ) {
			if(typeof key === "symbol") {
				obj[key] = value;
			} else {
				Object.defineProperty(obj, key, {
					enumerable: false,
					configurable: true,
					value: value,
					writable: true
				});
			}
			return;
		}
		var setKeyValue = obj[setKeyValueSymbol];
		if(setKeyValue !== undefined) {
			return setKeyValue.call(obj, key, value);
		} else {
			obj[key] = value;
		}
	},
	/**
	 * @function {Object, String} can-reflect.getKeyValue getKeyValue
	 * @parent can-reflect/get-set
	 * @description Get the value of a named property on a MapLike object.
	 *
	 * @signature `getKeyValue(obj, key)`
	 *
	 * Retrieve the property on Map-like `obj` identified by the String or Symbol value `key`.  The default behavior
	 * can be overridden on `obj` by implementing [can-symbol/symbols/getKeyValue @@@@can.getKeyValue],
	 * otherwise native named property access is used.
	 *
	 * ```js
	 * var foo = new DefineMap({ bar: "baz" });
	 *
	 * canReflect.getKeyValue(foo, "bar"); // -> "baz"
	 * ```
	 *
	 * @param  {Object} obj   the object to get from
	 * @param  {String} key   the key of the property to get
	 */
	getKeyValue: function(obj, key) {
		var getKeyValue = obj[getKeyValueSymbol];
		if(getKeyValue) {
			return getKeyValue.call(obj, key);
		}
		return obj[key];
	},
	/**
	 * @function {Object, String} can-reflect.deleteKeyValue deleteKeyValue
	 * @parent can-reflect/get-set
	 * @description Delete a named property from a MapLike object.
	 *
	 * @signature `deleteKeyValue(obj, key)`
	 *
	 * Remove the property identified by the String or Symbol `key` from the Map-like object `obj`, if possible.
	 * Property definitions may interfere with deleting key values; the behavior on `obj` if `obj[key]` cannot
	 * be deleted is undefined.  The default use of the native `delete` keyword can be overridden by `obj` if it
	 * implements [can-symbol/symbols/deleteKeyValue @@@@can.deleteKeyValue].
	 *
	 * ```js
	 * var foo = new DefineMap({ bar: "baz" });
	 * var quux = new CanMap({ thud: "jeek" });
	 *
	 * canReflect.deleteKeyValue(foo, "bar");
	 * canReflect.deleteKeyValue(quux, "thud");
	 *
	 * "bar" in foo; // ->  true  -- DefineMaps use property defs which cannot be un-defined
	 * foo.bar // -> undefined    --  but set values to undefined when deleting
	 *
	 * "thud" in quux; // -> false
	 * quux.thud; // -> undefined
	 * ```
	 *
	 * @param  {Object} obj   the object to delete on
	 * @param  {String} key   the key for the property to delete
	 */
	deleteKeyValue: function(obj, key) {
		var deleteKeyValue = obj[canSymbol_1_7_0_canSymbol.for("can.deleteKeyValue")];
		if(deleteKeyValue) {
			return deleteKeyValue.call(obj, key);
		}
		delete obj[key];
	},
	/**
	 * @function {Object} can-reflect.getValue getValue
	 * @parent can-reflect/get-set
	 * @description Get the value of an object with a gettable value
	 *
	 * @signature `getValue(obj)`
	 *
	 * Return the value of the Value-like object `obj`.  Unless `obj` implements
	 * [can-symbol/symbols/getValue @@@@can.getValue], the result of `getValue` on
	 * `obj` will always be `obj`.  Observable Map-like objects may want to implement
	 * `@@@@can.getValue` to return non-observable or plain representations of themselves.
	 *
	 * ```js
	 * var compute = canCompute("foo");
	 * var primitive = "bar";
	 *
	 * canReflect.getValue(compute); // -> "foo"
	 * canReflect.getValue(primitive); // -> "bar"
	 * ```
	 *
	 * @param  {Object} obj   the object to get from
	 * @return {*} the value of the object via `@@can.getValue`, or the value itself.
	 */
	getValue: function(value){
		if(type.isPrimitive(value)) {
			return value;
		}
		var getValue = value[getValueSymbol];
		if(getValue) {
			return getValue.call(value);
		}
		return value;
	},
	/**
	 * @function {Object, *} can-reflect.setValue setValue
	 * @parent can-reflect/get-set
	 * @description Set the value of a mutable object.
	 *
	 * @signature `setValue(obj, value)`
	 *
	 * Set the value of a Value-like object `obj` to the value `value`.  `obj` *must* implement
	 * [can-symbol/symbols/setValue @@@@can.setValue] to be used with `canReflect.setValue`.
	 * Map-like objects may want to implement `@@@@can.setValue` to merge objects of properties
	 * into themselves.
	 *
	 * ```js
	 * var compute = canCompute("foo");
	 * var plain = {};
	 *
	 * canReflect.setValue(compute, "bar");
	 * compute(); // -> bar
	 *
	 * canReflect.setValue(plain, { quux: "thud" }); // throws "can-reflect.setValue - Can not set value."
	 * ```
	 *
	 * @param  {Object} obj   the object to set on
	 * @param  {*} value      the value to set for the object
	 */
	setValue: function(item, value){
		var setValue = item && item[setValueSymbol];
		if(setValue) {
			return setValue.call(item, value);
		} else {
			throw new Error("can-reflect.setValue - Can not set value.");
		}
	},

	splice: function(obj, index, removing, adding){
		var howMany;
		if(typeof removing !== "number") {
			var updateValues = obj[canSymbol_1_7_0_canSymbol.for("can.updateValues")];
			if(updateValues) {
				return updateValues.call(obj, index, removing, adding);
			}
			howMany = removing.length;
		} else {
			howMany = removing;
		}

		if(arguments.length <= 3){
			adding = [];
		}

		var splice = obj[canSymbol_1_7_0_canSymbol.for("can.splice")];
		if(splice) {
			return splice.call(obj, index, howMany, adding);
		}
		return [].splice.apply(obj, [index, howMany].concat(adding) );
	},
	addValues: function(obj, adding, index) {
		var add = obj[canSymbol_1_7_0_canSymbol.for("can.addValues")];
		if(add) {
			return add.call(obj, adding, index);
		}
		if(Array.isArray(obj) && index === undefined) {
			return obj.push.apply(obj, adding);
		}
		return reflections.splice(obj, index, [], adding);
	},
	removeValues: function(obj, removing, index) {
		var removeValues = obj[canSymbol_1_7_0_canSymbol.for("can.removeValues")];
		if(removeValues) {
			return removeValues.call(obj, removing, index);
		}
		if(Array.isArray(obj) && index === undefined) {
			removing.forEach(function(item){
				var index = obj.indexOf(item);
				if(index >=0) {
					obj.splice(index, 1);
				}
			});
			return;
		}
		return reflections.splice(obj, index, removing, []);
	}
};
/**
 * @function {Object, String} can-reflect.get get
 * @hide
 * @description an alias for [can-reflect.getKeyValue getKeyValue]
 */
reflections.get = reflections.getKeyValue;
/**
 * @function {Object, String} can-reflect.set set
 * @hide
 * @description an alias for [can-reflect.setKeyValue setKeyValue]
 */
reflections.set = reflections.setKeyValue;
/**
 * @function {Object, String} can-reflect.delete delete
 * @hide
 * @description an alias for [can-reflect.deleteKeyValue deleteKeyValue]
 */
reflections["delete"] = reflections.deleteKeyValue;

var getSet = reflections;

var slice = [].slice;

function makeFallback(symbolName, fallbackName) {
	return function(obj, event, handler, queueName){
		var method = obj[canSymbol_1_7_0_canSymbol.for(symbolName)];
		if(method !== undefined) {
			return method.call(obj, event, handler, queueName);
		}
		return this[fallbackName].apply(this, arguments);
	};
}

function makeErrorIfMissing(symbolName, errorMessage){
	return function(obj){
		var method = obj[canSymbol_1_7_0_canSymbol.for(symbolName)];
		if(method !== undefined) {
			var args = slice.call(arguments, 1);
			return method.apply(obj, args);
		}
		throw new Error(errorMessage);
	};
}

var observe = {
	// KEY
	/**
	 * @function {Object, String, function(*, *), String} can-reflect/observe.onKeyValue onKeyValue
	 * @parent can-reflect/observe
	 * @description  Register an event handler on a MapLike object, based on a key change
	 *
	 * @signature `onKeyValue(obj, key, handler, [queueName])`
	 *
	 * Register a handler on the Map-like object `obj` to trigger when the property key `key` changes.
	 * `obj` *must* implement [can-symbol/symbols/onKeyValue @@@@can.onKeyValue] to be compatible with
	 * can-reflect.onKeyValue.  The function passed as `handler` will receive the new value of the property
	 * as the first argument, and the previous value of the property as the second argument.
	 *
	 * ```js
	 * var obj = new DefineMap({ foo: "bar" });
	 * canReflect.onKeyValue(obj, "foo", function(newVal, oldVal) {
	 * 	console.log("foo is now", newVal, ", was", oldVal);
	 * });
	 *
	 * obj.foo = "baz";  // -> logs "foo is now baz , was bar"
	 * ```
	 *
	 * @param {Object} obj an observable MapLike that can listen to changes in named properties.
	 * @param {String} key  the key to listen to
	 * @param {function(*, *)} handler a callback function that recieves the new value
	 * @param {String} [queueName]  the queue to dispatch events to
	 */
	onKeyValue: makeFallback("can.onKeyValue", "onEvent"),
	/**
	 * @function {Object, String, function(*), String} can-reflect/observe.offKeyValue offKeyValue
	 * @parent can-reflect/observe
	 * @description  Unregister an event handler on a MapLike object, based on a key change
	 *
	 * @signature `offKeyValue(obj, key, handler, [queueName])`
	 *
	 * Unregister a handler from the Map-like object `obj` that had previously been registered with
	 * [can-reflect/observe.onKeyValue onKeyValue]. The function passed as `handler` will no longer be called
	 * when the value of `key` on `obj` changes.
	 *
	 * ```js
	 * var obj = new DefineMap({ foo: "bar" });
	 * var handler = function(newVal, oldVal) {
	 * 	console.log("foo is now", newVal, ", was", oldVal);
	 * };
	 *
	 * canReflect.onKeyValue(obj, "foo", handler);
	 * canReflect.offKeyValue(obj, "foo", handler);
	 *
	 * obj.foo = "baz";  // -> nothing is logged
	 * ```
	 *
	 * @param {Object} obj an observable MapLike that can listen to changes in named properties.
	 * @param {String} key  the key to stop listening to
	 * @param {function(*)} handler the callback function that should be removed from the event handlers for `key`
	 * @param {String} [queueName]  the queue that the handler was set to receive events from
	 */
	offKeyValue: makeFallback("can.offKeyValue","offEvent"),

	/**
	 * @function {Object, function(Array)} can-reflect/observe.onKeys onKeys
	 * @parent can-reflect/observe
	 * @description  Register an event handler on a MapLike object, triggered on the key set changing
	 *
	 * @signature `onKeys(obj, handler)`
	 *
	 * Register an event handler on the Map-like object `obj` to trigger when `obj`'s keyset changes.
	 * `obj` *must* implement [can-symbol/symbols/onKeys @@@@can.onKeys] to be compatible with
	 * can-reflect.onKeys.  The function passed as `handler` will receive an Array of object diffs (see
	 * [can-util/js/diff-object/diff-object diffObject] for the format) as its one argument.
	 *
	 * ```js
	 * var obj = new DefineMap({ foo: "bar" });
	 * canReflect.onKeys(obj, function(diffs) {
	 * 	console.log(diffs);
	 * });
	 *
	 * obj.set("baz", "quux");  // -> logs '[{"property": "baz", "type": "add", "value": "quux"}]'
	 * ```
	 *
	 * @param {Object} obj an observable MapLike that can listen to changes in named properties.
	 * @param {function(Array)} handler the callback function to receive the diffs in the key set
	 */
	// any key change (diff would normally happen)
	onKeys: makeErrorIfMissing("can.onKeys","can-reflect: can not observe an onKeys event"),
	/**
	 * @function {Object, function(Array)} can-reflect/observe.onKeysAdded onKeysAdded
	 * @parent can-reflect/observe
	 * @description  Register an event handler on a MapLike object, triggered on new keys being added.
	 *
	 * @signature `onKeysAdded(obj, handler)`
	 *
	 * Register an event handler on the Map-like object `obj` to trigger when a new key or keys are set on
	 * `obj`. `obj` *must* implement [can-symbol/symbols/onKeysAdded @@@@can.onKeysAdded] to be compatible with
	 * can-reflect.onKeysAdded.  The function passed as `handler` will receive an Array of Strings as its one
	 * argument.
	 *
	 * ```js
	 * var obj = new DefineMap({ foo: "bar" });
	 * canReflect.onKeysAded(obj, function(newKeys) {
	 * 	console.log(newKeys);
	 * });
	 *
	 * foo.set("baz", "quux");  // -> logs '["baz"]'
	 * ```
	 *
	 * @param {Object} obj an observable MapLike that can listen to changes in named properties.
	 * @param {function(Array)} handler the callback function to receive the array of added keys
	 */
	// keys added at a certain point {key: 1}, index
	onKeysAdded: makeErrorIfMissing("can.onKeysAdded","can-reflect: can not observe an onKeysAdded event"),
	/**
	 * @function {Object, function(Array)} can-reflect/observe.onKeysRemoved onKeysRemoved
	 * @parent can-reflect/observe
	 * @description  Register an event handler on a MapLike object, triggered on keys being deleted.
	 *
	 * @signature `onKeysRemoved(obj, handler)`
	 *
	 * Register an event handler on the Map-like object `obj` to trigger when a key or keys are removed from
	 * `obj`'s keyset. `obj` *must* implement [can-symbol/symbols/onKeysRemoved @@@@can.onKeysRemoved] to be
	 * compatible with can-reflect.onKeysAdded.  The function passed as `handler` will receive an Array of
	 * Strings as its one argument.
	 *
	 * ```js
	 * var obj = new CanMap({ foo: "bar" });
	 * canReflect.onKeys(obj, function(diffs) {
	 * 	console.log(JSON.stringify(diffs));
	 * });
	 *
	 * foo.removeAttr("foo");  // -> logs '["foo"]'
	 * ```
	 *
	 * @param {Object} obj an observable MapLike that can listen to changes in named properties.
	 * @param {function(Array)} handler the callback function to receive the array of removed keys
	 */
	onKeysRemoved: makeErrorIfMissing("can.onKeysRemoved","can-reflect: can not unobserve an onKeysRemoved event"),

	/**
	 * @function {Object, String} can-reflect/observe.getKeyDependencies getKeyDependencies
	 * @parent can-reflect/observe
	 * @description  Return the observable objects that compute to the value of a named property on an object
	 *
	 * @signature `getKeyDependencies(obj, key)`
	 *
	 * Return the observable objects that provide input values to generate the computed value of the
	 * property `key` on Map-like object `obj`.  If `key` does not have dependencies on `obj`, returns `undefined`.
	 * Otherwise returns an object with up to two keys: `keyDependencies` is a [can-util/js/cid-map/cid-map CIDMap] that
	 * maps each Map-like object providing keyed values to an Array of the relevant keys; `valueDependencies` is a
	 * [can-util/js/cid-set/cid-set CIDSet] that contains all Value-like dependencies providing their own values.
	 *
	 * `obj` *must* implement [can-symbol/symbols/getKeyDependencies @@@@can.getKeyDependencies] to work with
	 * `canReflect.getKeyDependencies`.
	 *
	 *
	 * ```js
	 * var foo = new DefineMap({ "bar": "baz" })
	 * var obj = new (DefineMap.extend({
	 * 	 baz: {
	 * 	   get: function() {
	 * 	     return foo.bar;
	 * 	   }
	 * 	 }
	 * }))();
	 *
	 * canReflect.getKeyDependencies(obj, "baz");  // -> { valueDependencies: CIDSet }
	 * ```
	 *
	 * @param {Object} obj the object to check for key dependencies
	 * @param {String} key the key on the object to check
	 * @return {Object} the observable values that this keyed value depends on
	 */
	getKeyDependencies: makeErrorIfMissing("can.getKeyDependencies", "can-reflect: can not determine dependencies"),

	/**
	 * @function {Object, String} can-reflect/observe.getWhatIChange getWhatIChange
	 * @hide
	 * @parent can-reflect/observe
	 * @description Return the observable objects that derive their value from the
	 * obj, passed in.
	 *
	 * @signature `getWhatIChange(obj, key)`
	 *
	 * `obj` *must* implement `@@@@can.getWhatIChange` to work with
	 * `canReflect.getWhatIChange`.
	 *
	 * @param {Object} obj the object to check for what it changes
	 * @param {String} [key] the key on the object to check
	 * @return {Object} the observable values that derive their value from `obj`
	 */
	getWhatIChange: makeErrorIfMissing(
		"can.getWhatIChange",
		"can-reflect: can not determine dependencies"
	),

	/**
	 * @function {Function} can-reflect/observe.getChangesDependencyRecord getChangesDependencyRecord
	 * @hide
	 * @parent can-reflect/observe
	 * @description Return the observable objects that are mutated by the handler
	 * passed in as argument.
	 *
	 * @signature `getChangesDependencyRecord(handler)`
	 *
	 * `handler` *must* implement `@@@@can.getChangesDependencyRecord` to work with
	 * `canReflect.getChangesDependencyRecord`.
	 *
	 * ```js
	 * var one = new SimpleObservable("one");
	 * var two = new SimpleObservable("two");
	 *
	 * var handler = function() {
	 *	two.set("2");
	 * };
	 *
	 * canReflect.onValue(one, handler);
	 * canReflect.getChangesDependencyRecord(handler); // -> { valueDependencies: new Set([two]) }
	 * ```
	 *
	 * @param {Function} handler the event handler to check for what it changes
	 * @return {Object} the observable values that are mutated by the handler
	 */
	getChangesDependencyRecord: function getChangesDependencyRecord(handler) {
		var fn = handler[canSymbol_1_7_0_canSymbol.for("can.getChangesDependencyRecord")];

		if (typeof fn === "function") {
			return fn();
		}
	},

	/**
	 * @function {Object, String} can-reflect/observe.keyHasDependencies keyHasDependencies
	 * @parent can-reflect/observe
	 * @description  Determine whether the value for a named property on an object is bound to other events
	 *
	 * @signature `keyHasDependencies(obj, key)`
	 *
	 * Returns `true` if the computed value of the property `key` on Map-like object `obj` derives from other values.
	 * Returns `false` if `key` is computed on `obj` but does not have dependencies on other objects. If `key` is not
	 * a computed value on `obj`, returns `undefined`.
	 *
	 * `obj` *must* implement [can-symbol/symbols/keyHasDependencies @@@@can.keyHasDependencies] to work with
	 * `canReflect.keyHasDependencies`.
	 *
	 * ```js
	 * var foo = new DefineMap({ "bar": "baz" })
	 * var obj = new (DefineMap.extend({
	 * 	 baz: {
	 * 	   get: function() {
	 * 	     return foo.bar;
	 * 	   }
	 * 	 },
	 * 	 quux: {
	 * 	 	 get: function() {
	 * 	 	   return "thud";
	 * 	 	 }
	 * 	 }
	 * }))();
	 *
	 * canReflect.keyHasDependencies(obj, "baz");  // -> true
	 * canReflect.keyHasDependencies(obj, "quux");  // -> false
	 * canReflect.keyHasDependencies(foo, "bar");  // -> undefined
	 * ```
	 *
	 * @param {Object} obj the object to check for key dependencies
	 * @param {String} key the key on the object to check
	 * @return {Boolean} `true` if there are other objects that may update the keyed value; `false` otherwise
	 *
	 */
	// TODO: use getKeyDeps once we know what that needs to look like
	keyHasDependencies: makeErrorIfMissing("can.keyHasDependencies","can-reflect: can not determine if this has key dependencies"),

	// VALUE
	/**
	 * @function {Object, function(*)} can-reflect/observe.onValue onValue
	 * @parent can-reflect/observe
	 * @description  Register an event handler on an observable ValueLike object, based on a change in its value
	 *
	 * @signature `onValue(handler, [queueName])`
	 *
	 * Register an event handler on the Value-like object `obj` to trigger when its value changes.
	 * `obj` *must* implement [can-symbol/symbols/onValue @@@@can.onValue] to be compatible with
	 * can-reflect.onKeyValue.  The function passed as `handler` will receive the new value of `obj`
	 * as the first argument, and the previous value of `obj` as the second argument.
	 *
	 * ```js
	 * var obj = canCompute("foo");
	 * canReflect.onValue(obj, function(newVal, oldVal) {
	 * 	console.log("compute is now", newVal, ", was", oldVal);
	 * });
	 *
	 * obj("bar");  // -> logs "compute is now bar , was foo"
	 * ```
	 *
	 * @param {*} obj  any object implementing @@can.onValue
	 * @param {function(*, *)} handler  a callback function that receives the new and old values
	 */
	onValue: makeErrorIfMissing("can.onValue","can-reflect: can not observe value change"),
	/**
	 * @function {Object, function(*)} can-reflect/observe.offValue offValue
	 * @parent can-reflect/observe
	 * @description  Unregister an value change handler from an observable ValueLike object
	 *
	 * @signature `offValue(handler, [queueName])`
	 *
	 * Unregister an event handler from the Value-like object `obj` that had previously been registered with
	 * [can-reflect/observe.onValue onValue]. The function passed as `handler` will no longer be called
	 * when the value of `obj` changes.
	 *
	 * ```js
	 * var obj = canCompute( "foo" );
	 * var handler = function(newVal, oldVal) {
	 * 	console.log("compute is now", newVal, ", was", oldVal);
	 * };
	 *
	 * canReflect.onKeyValue(obj, handler);
	 * canReflect.offKeyValue(obj, handler);
	 *
	 * obj("baz");  // -> nothing is logged
	 * ```
	 *
	 * @param {*} obj
	 * @param {function(*)} handler
	 */
	offValue: makeErrorIfMissing("can.offValue","can-reflect: can not unobserve value change"),

	/**
	 * @function {Object} can-reflect/observe.getValueDependencies getValueDependencies
	 * @parent can-reflect/observe
	 * @description  Return all the events that bind to the value of an observable, Value-like object
	 *
	 * @signature `getValueDependencies(obj)`
	 *
	 * Return the observable objects that provide input values to generate the computed value of the
	 * Value-like object `obj`.  If `obj` does not have dependencies, returns `undefined`.
	 * Otherwise returns an object with up to two keys: `keyDependencies` is a [can-util/js/cid-map/cid-map CIDMap] that
	 * maps each Map-like object providing keyed values to an Array of the relevant keys; `valueDependencies` is a
	 * [can-util/js/cid-set/cid-set CIDSet] that contains all Value-like dependencies providing their own values.
	 *
	 * `obj` *must* implement [can-symbol/symbols/getValueDependencies @@@@can.getValueDependencies] to work with
	 * `canReflect.getValueDependencies`.
	 *
	 *
	 * ```js
	 * var foo = new DefineMap({ "bar": "baz" })
	 * var obj = canCompute(function() {
	 * 	 return foo.bar;
	 * });
	 *
	 * canReflect.getValueDependencies(obj);  // -> { valueDependencies: CIDSet } because `obj` is internally backed by
	 * a [can-observation]
	 * ```
	 *
	 * @param {Object} obj the object to check for value dependencies
	 * @return {Object} the observable objects that `obj`'s value depends on
	 *
	 */
	getValueDependencies: makeErrorIfMissing("can.getValueDependencies","can-reflect: can not determine dependencies"),

	/**
	 * @function {Object} can-reflect/observe.valueHasDependencies valueHasDependencies
	 * @parent can-reflect/observe
	 * @description  Determine whether the value of an observable object is bound to other events
	 *
	 * @signature `valueHasDependencies(obj)`
	 *
	 * Returns `true` if the computed value of the Value-like object `obj` derives from other values.
	 * Returns `false` if `obj` is computed but does not have dependencies on other objects. If `obj` is not
	 * a computed value, returns `undefined`.
	 *
	 * `obj` *must* implement [can-symbol/symbols/valueHasDependencies @@@@can.valueHasDependencies] to work with
	 * `canReflect.valueHasDependencies`.
	 *
	 * ```js
	 * var foo = canCompute( "bar" );
	 * var baz = canCompute(function() {
	 * 	 return foo();
	 * });
	 * var quux = "thud";
	 * var jeek = canCompute(function(plonk) {
	 * 	 if(argument.length) {
	 * 	 	  quux = plonk;
	 * 	 }
	 * 	 return quux;
	 * });
	 *
	 * canReflect.valueHasDependencies(baz);  // -> true
	 * canReflect.valueHasDependencies(jeek);  // -> false
	 * canReflect.valueHasDependencies(foo);  // -> undefined
	 * ```
	 *
	 * @param {Object} obj the object to check for dependencies
	 * @return {Boolean} `true` if there are other dependencies that may update the object's value; `false` otherwise
	 *
	 */
	valueHasDependencies: makeErrorIfMissing("can.valueHasDependencies","can-reflect: can not determine if value has dependencies"),

	// PATCHES
	/**
	 * @function {Object, function(*), String} can-reflect/observe.onPatches onPatches
	 * @parent can-reflect/observe
	 * @description  Register an handler on an observable that listens to any key changes
	 *
	 * @signature `onPatches(obj, handler, [queueName])`
	 *
	 * Register an event handler on the object `obj` that fires when anything changes on an object: a key value is added,
	 * an existing key has is value changed, or a key is deleted from the object.
	 *
	 * If object is an array-like and the changed property includes numeric indexes, patch sets will include array-specific
	 * patches in addition to object-style patches
	 *
	 * For more on the patch formats, see [can-util/js/diff-object/diff-object] and [can-util/js/diff-array/diff-array].
	 *
	 * ```js
	 * var obj = new DefineMap({});
	 * var handler = function(patches) {
	 * 	console.log(patches);
	 * };
	 *
	 * canReflect.onPatches(obj, handler);
	 * obj.set("foo", "bar");  // logs [{ type: "add", property: "foo", value: "bar" }]
	 * obj.set("foo", "baz");  // logs [{ type: "set", property: "foo", value: "baz" }]
	 *
	 * var arr = new DefineList([]);
	 * canReflect.onPatches(arr, handler);
	 * arr.push("foo");  // logs [{type: "add", property:"0", value: "foo"},
	 *                            {index: 0, deleteCount: 0, insert: ["foo"]}]
   * arr.pop();  // logs [{type: "remove", property:"0"},
	 *                            {index: 0, deleteCount: 1, insert: []}]
	 * ```
	 *
	 * @param {*} obj
	 * @param {function(*)} handler
	 * @param {String} [queueName] the name of a queue in [can-queues]; dispatches to `handler` will happen on this queue
	 */
	onPatches: makeErrorIfMissing("can.onPatches", "can-reflect: can not observe patches on object"),
	/**
	 * @function {Object, function(*), String} can-reflect/observe.offPatches offPatches
	 * @parent can-reflect/observe
	 * @description  Unregister an object patches handler from an observable object
	 *
	 * @signature `offPatches(obj, handler, [queueName])`
	 *
	 * Unregister an event handler from the object `obj` that had previously been registered with
	 * [can-reflect/observe.onPatches onPatches]. The function passed as `handler` will no longer be called
	 * when `obj` has key or index changes.
	 *
	 * ```js
	 * var obj = new DefineMap({});
	 * var handler = function(patches) {
	 * 	console.log(patches);
	 * };
	 *
	 * canReflect.onPatches(obj, handler);
	 * canReflect.offPatches(obj, handler);
	 *
	 * obj.set("foo", "bar");  // nothing is logged
	 * ```
	 *
	 * @param {*} obj
	 * @param {function(*)} handler
	 * @param {String} [queueName] the name of the queue in [can-queues] the handler was registered under
	 */
	offPatches: makeErrorIfMissing("can.offPatches", "can-reflect: can not unobserve patches on object"),

	/**
	 * @function {Object, function(*)} can-reflect/observe.onInstancePatches onInstancePatches
	 * @parent can-reflect/observe
	 *
	 * @description Registers a handler that listens to patch events on any instance
	 *
	 * @signature `onInstancePatches(Type, handler(instance, patches))`
	 *
	 * Listens to patch changes on any instance of `Type`. This is used by [can-connect]
	 * to know when a potentially `unbound` instance's `id` changes. If the `id` changes,
	 * the instance can be moved into the store while it is being saved. E.g:
	 *
	 * ```js
	 * canReflect.onInstancePatches(Map, function onInstancePatches(instance, patches) {
	 *	patches.forEach(function(patch) {
	 *		if (
	 *			(patch.type === "add" || patch.type === "set") &&
	 *			patch.key === connection.idProp &&
	 *			canReflect.isBound(instance)
	 *		) {
	 *			connection.addInstanceReference(instance);
	 *		}
	 *	});
	 *});
	 * ```
	 *
	 * @param {*} Type
	 * @param {function(*)} handler
	 */
	onInstancePatches: makeErrorIfMissing(
		"can.onInstancePatches",
		"can-reflect: can not observe onInstancePatches on Type"
	),

	/**
	 * @function {Object, function(*)} can-reflect/observe.offInstancePatches offInstancePatches
	 * @parent can-reflect/observe
	 *
	 * @description Unregisters a handler registered through [can-reflect/observe.onInstancePatches]
	 *
	 * @signature `offInstancePatches(Type, handler(instance, patches))`
	 *
	 * ```js
	 * canReflect.offInstancePatches(Map, onInstancePatches);
	 * ```
	 *
	 * @param {*} Type
	 * @param {function(*)} handler
	 */
	offInstancePatches: makeErrorIfMissing(
		"can.offInstancePatches",
		"can-reflect: can not unobserve onInstancePatches on Type"
	),

	// HAS BINDINGS VS DOES NOT HAVE BINDINGS
	/**
	 * @function {Object, function(*), String} can-reflect/observe.onInstanceBoundChange onInstanceBoundChange
	 * @parent can-reflect/observe
	 * @description Listen to when observables of a type are bound and unbound.
	 *
	 * @signature `onInstanceBoundChange(Type, handler, [queueName])`
	 *
	 * Register an event handler on the object `Type` that fires when instances of the type become bound (the first handler is added)
	 * or unbound (the last remaining handler is removed). The function passed as `handler` will be called
	 * with the `instance` as the first argument and `true` as the second argument when `instance` gains its first binding,
	 * and called with `false` when `instance` loses its
	 * last binding.
	 *
	 * ```js
	 * Person = DefineMap.extend({ ... });
	 *
	 * var person = Person({});
	 * var handler = function(instance, newVal) {
	 * 	console.log(instance, "bound state is now", newVal);
	 * };
	 * var keyHandler = function() {};
	 *
	 * canReflect.onInstanceBoundChange(Person, handler);
	 * canReflect.onKeyValue(obj, "name", keyHandler);  // logs person Bound state is now true
	 * canReflect.offKeyValue(obj, "name", keyHandler);  // logs person Bound state is now false
	 * ```
	 *
	 * @param {function} Type A constructor function
	 * @param {function(*,Boolean)} handler(instance,isBound) A function called with the `instance` whose bound status changed and the state of the bound status.
	 * @param {String} [queueName] the name of a queue in [can-queues]; dispatches to `handler` will happen on this queue
	 */
	onInstanceBoundChange: makeErrorIfMissing("can.onInstanceBoundChange", "can-reflect: can not observe bound state change in instances."),
	/**
	 * @function {Object, function(*), String} can-reflect/observe.offInstanceBoundChange offInstanceBoundChange
	 * @parent can-reflect/observe
	 * @description Stop listening to when observables of a type are bound and unbound.
	 *
	 * @signature `offInstanceBoundChange(Type, handler, [queueName])`
	 *
	 * Unregister an event handler from the type `Type` that had previously been registered with
	 * [can-reflect/observe.onInstanceBoundChange onInstanceBoundChange]. The function passed as `handler` will no longer be called
	 * when instances of `Type` gains its first or loses its last binding.
	 *
	 * ```js
	 * Person = DefineMap.extend({ ... });
	 *
	 * var person = Person({});
	 * var handler = function(instance, newVal) {
	 * 	console.log(instance, "bound state is now", newVal);
	 * };
	 * var keyHandler = function() {};
	 *
	 * canReflect.onInstanceBoundChange(Person, handler);
	 * canReflect.offInstanceBoundChange(Person, handler);
	 * canReflect.onKeyValue(obj, "name", keyHandler);  // nothing is logged
	 * canReflect.offKeyValue(obj, "name", keyHandler); // nothing is logged
	 * ```
	 *
	 * @param {function} Type A constructor function
	 * @param {function(*,Boolean)} handler(instance,isBound) The `handler` passed to `canReflect.onInstanceBoundChange`.
	 * @param {String} [queueName] the name of the queue in [can-queues] the handler was registered under
	 */
	offInstanceBoundChange: makeErrorIfMissing("can.offInstanceBoundChange", "can-reflect: can not unobserve bound state change"),
	/**
	 * @function {Object} can-reflect/observe.isBound isBound
	 * @parent can-reflect/observe
	 * @description  Determine whether any listeners are bound to the observable object
	 *
	 * @signature `isBound(obj)`
	 *
	 * `isBound` queries an observable object to find out whether any listeners have been set on it using
	 * [can-reflect/observe.onKeyValue onKeyValue] or [can-reflect/observe.onValue onValue]
	 *
	 * ```js
	 * var obj = new DefineMap({});
	 * var handler = function() {};
	 * canReflect.isBound(obj); // -> false
	 * canReflect.onKeyValue(obj, "foo", handler);
	 * canReflect.isBound(obj); // -> true
	 * canReflect.offKeyValue(obj, "foo", handler);
	 * canReflect.isBound(obj); // -> false
	 * ```
	 *
	 * @param {*} obj
	 * @return {Boolean} `true` if obj has at least one key-value or value listener, `false` otherwise
	 */
	isBound: makeErrorIfMissing("can.isBound", "can-reflect: cannot determine if object is bound"),

	// EVENT
	/**
	 * @function {Object, String, function(*)} can-reflect/observe.onEvent onEvent
	 * @parent can-reflect/observe
	 * @description  Register a named event handler on an observable object
	 *
	 * @signature `onEvent(obj, eventName, callback)`
	 *
	 *
	 * Register an event handler on the object `obj` to trigger when the event `eventName` is dispatched.
	 * `obj` *must* implement [can-symbol/symbols/onKeyValue @@@@can.onEvent] or `.addEventListener()` to be compatible
	 * with can-reflect.onKeyValue.  The function passed as `callback` will receive the event descriptor as the first
	 * argument, and any data passed to the event dispatch as subsequent arguments.
	 *
	 * ```js
	 * var obj = new DefineMap({ foo: "bar" });
	 * canReflect.onEvent(obj, "foo", function(ev, newVal, oldVal) {
	 * 	console.log("foo is now", newVal, ", was", oldVal);
	 * });
	 *
	 * canEvent.dispatch.call(obj, "foo", ["baz", "quux"]);  // -> logs "foo is now baz , was quux"
	 * ```
	 *
	 * @param {Object} obj the object to bind a new event handler to
	 * @param {String} eventName the name of the event to bind the handler to
	 * @param {function(*)} callback  the handler function to bind to the event
	 */
	onEvent: function(obj, eventName, callback, queue){
		if(obj) {
			var onEvent = obj[canSymbol_1_7_0_canSymbol.for("can.onEvent")];
			if(onEvent !== undefined) {
				return onEvent.call(obj, eventName, callback, queue);
			} else if(obj.addEventListener) {
				obj.addEventListener(eventName, callback, queue);
			}
		}
	},
	/**
	 * @function {Object, String, function(*)} can-reflect/observe.offValue offEvent
	 * @parent can-reflect/observe
	 * @description  Unregister an event handler on a MapLike object, based on a key change
	 *
	 * @signature `offEvent(obj, eventName, callback)`
	 *
	 * Unregister an event handler from the object `obj` that had previously been registered with
	 * [can-reflect/observe.onEvent onEvent]. The function passed as `callback` will no longer be called
	 * when the event named `eventName` is dispatched on `obj`.
	 *
	 * ```js
	 * var obj = new DefineMap({ foo: "bar" });
	 * var handler = function(ev, newVal, oldVal) {
	 * 	console.log("foo is now", newVal, ", was", oldVal);
	 * };
	 *
	 * canReflect.onEvent(obj, "foo", handler);
	 * canReflect.offEvent(obj, "foo", handler);
	 *
	 * canEvent.dispatch.call(obj, "foo", ["baz", "quux"]);  // -> nothing is logged
	 * ```
	 *
	 * @param {Object} obj the object to unbind an event handler from
	 * @param {String} eventName the name of the event to unbind the handler from
	 * @param {function(*)} callback the handler function to unbind from the event
	 */
	offEvent: function(obj, eventName, callback, queue){
		if(obj) {
			var offEvent = obj[canSymbol_1_7_0_canSymbol.for("can.offEvent")];
			if(offEvent !== undefined) {
				return offEvent.call(obj, eventName, callback, queue);
			}  else if(obj.removeEventListener) {
				obj.removeEventListener(eventName, callback, queue);
			}
		}

	},
	/**
	 * @function {function} can-reflect/setPriority setPriority
	 * @parent can-reflect/observe
	 * @description  Provide a priority for when an observable that derives its
	 * value should be re-evaluated.
	 *
	 * @signature `setPriority(obj, priority)`
	 *
	 * Calls an underlying `@@can.setPriority` symbol on `obj` if it exists with `priorty`.
	 * Returns `true` if a priority was set, `false` if otherwise.
	 *
	 * Lower priorities (`0` being the lowest), will be an indication to run earlier than
	 * higher priorities.
	 *
	 * ```js
	 * var obj = canReflect.assignSymbols({},{
	 *   "can.setPriority": function(priority){
	 *     return this.priority = priority;
	 *   }
	 * });
	 *
	 * canReflect.setPriority(obj, 0) //-> true
	 * obj.priority //-> 0
	 *
	 * canReflect.setPriority({},20) //-> false
	 * ```
	 *
	 * @param {Object} obj An observable that will update its priority.
	 * @param {Number} priority The priority number.  Lower priorities (`0` being the lowest),
	 * indicate to run earlier than higher priorities.
	 * @return {Boolean} `true` if a priority was able to be set, `false` if otherwise.
	 *
	 * @body
	 *
	 * ## Use
	 *
	 * There's often a need to specify the order of re-evaluation for
	 * __observables__ that derive (or compute) their value from other observables.
	 *
	 * This is needed by templates to avoid unnecessary re-evaluation.  Say we had the following template:
	 *
	 * ```js
	 * {{#if value}}
	 *   {{value}}
	 * {{/if}}
	 * ```
	 *
	 * If `value` became falsey, we'd want the `{{#if}}` to be aware of it before
	 * the `{{value}}` magic tags updated. We can do that by setting priorities:
	 *
	 * ```js
	 * canReflect.setPriority(magicIfObservable, 0);
	 * canReflect.setPriority(magicValueObservable,1);
	 * ```
	 *
	 * Internally, those observables will use that `priority` to register their
	 * re-evaluation with the `derive` queue in [can-queues].
	 *
	 */
	setPriority: function(obj, priority) {
		if(obj) {
			var setPriority =  obj[canSymbol_1_7_0_canSymbol.for("can.setPriority")];
			if(setPriority !== undefined) {
				setPriority.call(obj, priority);
			 	return true;
			}
		}
		return false;
	},
	/**
	 * @function {function} can-reflect/getPriority getPriority
	 * @parent can-reflect/observe
	 * @description  Read the priority for an observable that derives its
	 * value.
	 *
	 * @signature `getPriority(obj)`
	 *
	 * Calls an underlying `@@can.getPriority` symbol on `obj` if it exists
	 * and returns its value. Read [can-reflect/setPriority] for more information.
	 *
	 *
	 *
	 * @param {Object} obj An observable.
	 * @return {Undefined|Number} Returns the priority number if
	 * available, undefined if this object does not support the `can.getPriority`
	 * symbol.
	 *
	 * @body
	 *
	 */
	getPriority: function(obj) {
		if(obj) {
			var getPriority =  obj[canSymbol_1_7_0_canSymbol.for("can.getPriority")];
			if(getPriority !== undefined) {
				return getPriority.call(obj);
			}
		}
		return undefined;
	}
};

// IE-remove-start
var getPrototypeOfWorksWithPrimitives = true;
try {
} catch(e) {
	getPrototypeOfWorksWithPrimitives = false;
}
// IE-remove-end

var ArrayMap;
if(typeof Map === "function") {
	ArrayMap = Map;
} else {
	// IE-remove-start
	var isEven = function isEven(num) {
		return num % 2 === 0;
	};

	// A simple map that stores items in an array.
	// like [key, value]
	// You can find the value by searching for the key and then +1.
	ArrayMap = function(){
		this.contents = [];
	};

	ArrayMap.prototype = {
		/**
		 * Get an index of a key. Because we store boths keys and values in
		 * a flat array, we ensure we are getting a key by checking that it is an
		 * even number index (all keys are even number indexed).
		 **/
		_getIndex: function(key) {
			var idx;
			do {
				idx = this.contents.indexOf(key, idx);
			} while(idx !== -1 && !isEven(idx));
			return idx;
		},
		has: function(key){
			return this._getIndex(key) !== -1;
		},
		get: function(key){
			var idx = this._getIndex(key);
			if(idx !== -1) {
				return this.contents[idx + 1];
			}
		},
		set: function(key, value){
			var idx = this._getIndex(key);
			if(idx !== -1) {
				// Key already exists, replace the value.
				this.contents[idx + 1] = value;
			} else {
				this.contents.push(key);
				this.contents.push(value);
			}
		},
		"delete": function(key){
			var idx = this._getIndex(key);
			if(idx !== -1) {
				// Key already exists, replace the value.
				this.contents.splice(idx, 2);
			}
		}
	};
	// IE-remove-end
}

var hasOwnProperty = Object.prototype.hasOwnProperty;

var shapeReflections;

var shiftFirstArgumentToThis = function(func){
	return function(){
		var args = [this];
		args.push.apply(args, arguments);
		return func.apply(null,args);
	};
};

var getKeyValueSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.getKeyValue");
var shiftedGetKeyValue = shiftFirstArgumentToThis(getSet.getKeyValue);
var setKeyValueSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.setKeyValue");
var shiftedSetKeyValue = shiftFirstArgumentToThis(getSet.setKeyValue);

var sizeSymbol = canSymbol_1_7_0_canSymbol.for("can.size");

var hasUpdateSymbol = helpers.makeGetFirstSymbolValue(["can.updateDeep","can.assignDeep","can.setKeyValue"]);
var shouldUpdateOrAssign = function(obj){
	return type.isPlainObject(obj) || Array.isArray(obj) || !!hasUpdateSymbol(obj);
};

// is the value itself its serialized value
function isSerializedHelper(obj){
	if (type.isPrimitive(obj)) {
		return true;
	}
	if(hasUpdateSymbol(obj)) {
		return false;
	}
	return type.isBuiltIn(obj) && !type.isPlainObject(obj) && !Array.isArray(obj) && !type.isObservableLike(obj);
}

// IE11 doesn't support primitives
var Object_Keys;
try{
	Object_Keys = Object.keys;
} catch(e) {
	Object_Keys = function(obj){
		if(type.isPrimitive(obj)) {
			return [];
		} else {
			return Object.keys(obj);
		}
	};
}

function createSerializeMap(Type) {
	var MapType = Type || ArrayMap;
	return {
		unwrap: new MapType(),
		serialize: new MapType() ,
		isSerializing: {
			unwrap: new MapType(),
			serialize: new MapType()
		},
		circularReferenceIsSerializing: {
			unwrap: new MapType(),
			serialize: new MapType()
		}
	};
}

function makeSerializer(methodName, symbolsToCheck){
	// A local variable that is shared with all operations that occur withing a single
	// outer call to serialize()
	var serializeMap = null;

	// Holds the value of running serialize(), preserving the same map for all
	// internal instances.
	function SerializeOperation(MapType) {
		this.first = !serializeMap;

		if(this.first) {
			serializeMap = createSerializeMap(MapType);
		}

		this.map = serializeMap;
		this.result = null;
	}

	SerializeOperation.prototype.end = function(){
		// If this is the first, outer call, clean up the serializeMap.
		if(this.first) {
			serializeMap = null;
		}
		return this.result;
	};

	return function serializer(value, MapType){
		if (isSerializedHelper(value)) {
			return value;
		}

		var operation = new SerializeOperation(MapType);

		if(type.isValueLike(value)) {
			operation.result = this[methodName](getSet.getValue(value));

		} else {
			// Date, RegEx and other Built-ins are handled above
			// only want to do something if it's intended to be serialized
			// or do nothing for a POJO

			var isListLike = type.isIteratorLike(value) || type.isMoreListLikeThanMapLike(value);
			operation.result = isListLike ? [] : {};

			// handle maping to what is serialized
			if( operation.map[methodName].has(value) ) {
				// if we are in the process of serializing the first time, setup circular reference detection.
				if(operation.map.isSerializing[methodName].has(value)) {
					operation.map.circularReferenceIsSerializing[methodName].set(value, true);
				}
				return operation.map[methodName].get(value);
			} else {
				operation.map[methodName].set(value, operation.result);
			}

			for(var i = 0, len = symbolsToCheck.length ; i< len;i++) {
				var serializer = value[symbolsToCheck[i]];
				if(serializer) {
					// mark that we are serializing
					operation.map.isSerializing[methodName].set(value, true);
					var oldResult = operation.result;
					operation.result = serializer.call(value, oldResult);
					operation.map.isSerializing[methodName].delete(value);

					// if the result differs, but this was circular, blow up.
					if(operation.result !== oldResult) {
						// jshint -W073
						if(operation.map.circularReferenceIsSerializing[methodName].has(value)) {
							// Circular references should use a custom serializer
							// that sets the serialized value on the object
							// passed to it as the first argument e.g.
							// function(proto){
							//   return proto.a = canReflect.serialize(this.a);
							// }
							operation.end();
							throw new Error("Cannot serialize cirular reference!");
						}
						operation.map[methodName].set(value, operation.result);
					}
					return operation.end();
				}
			}

			if (typeof obj ==='function') {
				operation.map[methodName].set(value, value);

				operation.result = value;
			} else if( isListLike ) {
				this.eachIndex(value,function(childValue, index){
					operation.result[index] = this[methodName](childValue);
				},this);
			} else {
				this.eachKey(value,function(childValue, prop){
					operation.result[prop] = this[methodName](childValue);
				},this);
			}
		}

		return operation.end();
	};
}

// returns a Map type of the keys mapped to true
var makeMap;
if(typeof Map !== "undefined") {
	makeMap = function(keys) {
		var map = new Map();
		shapeReflections.eachIndex(keys, function(key){
			map.set(key, true);
		});
		return map;
	};
} else {
	makeMap = function(keys) {
		var map = {};
		keys.forEach(function(key){
			map[key] = true;
		});

		return {
			get: function(key){
				return map[key];
			},
			set: function(key, value) {
				map[key] = value;
			},
			keys: function(){
				return keys;
			}
		};
	};
}

// creates an optimized hasOwnKey lookup.
// If the object has hasOwnKey, then we just use that.
// Otherwise, try to put all keys in a map.
var fastHasOwnKey = function(obj){
	var hasOwnKey = obj[canSymbol_1_7_0_canSymbol.for("can.hasOwnKey")];
	if(hasOwnKey) {
		return hasOwnKey.bind(obj);
	} else {
		var map = makeMap( shapeReflections.getOwnEnumerableKeys(obj) );
		return function(key) {
			return map.get(key);
		};
	}
};


// combines patches if it makes sense
function addPatch(patches, patch) {
	var lastPatch = patches[patches.length -1];
	if(lastPatch) {
		// same number of deletes and counts as the index is back
		if(lastPatch.deleteCount === lastPatch.insert.length && (patch.index - lastPatch.index === lastPatch.deleteCount) ) {
			lastPatch.insert.push.apply(lastPatch.insert, patch.insert);
			lastPatch.deleteCount += patch.deleteCount;
			return;
		}
	}
	patches.push(patch);
}

function updateDeepList(target, source, isAssign) {
	var sourceArray = this.toArray(source); // jshint ignore:line

	var patches = [],
		lastIndex = -1;
	this.eachIndex(target, function(curVal, index){ // jshint ignore:line
		lastIndex = index;
		// If target has more items than the source.
		if(index >= sourceArray.length) {
			if(!isAssign) {
				// add a patch that removes the last items
				addPatch(patches, {index: index, deleteCount: target.length - index + 1, insert: []});
			}
			return false;
		}
		var newVal = sourceArray[index];
		if( type.isPrimitive(curVal) || type.isPrimitive(newVal) || shouldUpdateOrAssign(curVal) === false ) {
			addPatch(patches, {index: index, deleteCount: 1, insert: [newVal]});
		} else {
			if(isAssign === true) {
				this.assignDeep(curVal, newVal);
			} else {
				this.updateDeep(curVal, newVal);
			}

		}
	}, this); // jshint ignore:line
	// add items at the end
	if(sourceArray.length > lastIndex) {
		addPatch(patches, {index: lastIndex+1, deleteCount: 0, insert: sourceArray.slice(lastIndex+1)});
	}
	for(var i = 0, patchLen = patches.length; i < patchLen; i++) {
		var patch = patches[i];
		getSet.splice(target, patch.index, patch.deleteCount, patch.insert);
	}
	return target;
}

shapeReflections = {
	/**
	 * @function {Object, function(*), [Object]} can-reflect.each each
	 * @parent can-reflect/shape
	 * @description  Iterate a List-like or Map-like, calling `callback` on each keyed or indexed property
	 *
	 * @signature `each(obj, callback, context)`
	 *
	 * If `obj` is a List-like or an Iterator-like, `each` functions as [can-reflect.eachIndex eachIndex],
	 * iterating over numeric indexes from 0 to `obj.length - 1` and calling `callback` with each property and
	 * index, optionally with `context` as `this` (defaulting to `obj`).  If not, `each` functions as
	 * [can-reflect.eachKey eachKey],
	 * iterating over every key on `obj` and calling `callback` on each one.
	 *
	 * ```js
	 * var foo = new DefineMap({ bar: "baz" });
	 * var quux = new DefineList([ "thud", "jeek" ]);
	 *
	 * canReflect.each(foo, console.log, console); // -> logs 'baz bar {foo}'
	 * canReflect.each(quux, console.log, console); // -> logs 'thud 0 {quux}'; logs 'jeek 1 {quux}'
	 * ```
	 *
	 * @param  {Object}   obj     The object to iterate over
	 * @param  {Function(*, ValueLike)} callback a function that receives each item in the ListLike or MapLike
	 * @param  {[Object]}   context  an optional `this` context for calling the callback
	 * @return {Array} the result of calling [can-reflect.eachIndex `eachIndex`] if `obj` is a ListLike,
	 * or [can-reflect.eachKey `eachKey`] if a MapLike.
	 */
	each: function(obj, callback, context){

		// if something is more "list like" .. use eachIndex
		if(type.isIteratorLike(obj) || type.isMoreListLikeThanMapLike(obj) ) {
			return shapeReflections.eachIndex(obj,callback,context);
		} else {
			return shapeReflections.eachKey(obj,callback,context);
		}
	},

	/**
	 * @function {ListLike, function(*), [Object]} can-reflect.eachIndex eachIndex
	 * @parent can-reflect/shape
	 * @description  Iterate a ListLike calling `callback` on each numerically indexed element
	 *
	 * @signature `eachIndex(list, callback, context)`
	 *
	 * For each numeric index from 0 to `list.length - 1`, call `callback`, passing the current
	 * property value, the current index, and `list`, and optionally setting `this` as `context`
	 * if specified (otherwise use the current property value).
	 *
	 * ```js
	 * var foo = new DefineList([ "bar", "baz" ]);
	 *
	 * canReflect.eachIndex(foo, console.log, console); // -> logs 'bar 0 {foo}'; logs 'baz 1 {foo}'
	 * ```
	 *
	 * @param  {ListLike}   list     The list to iterate over
	 * @param  {Function(*, Number)} callback a function that receives each item
	 * @param  {[Object]}   context  an optional `this` context for calling the callback
	 * @return {ListLike}   the original list
	 */
	eachIndex: function(list, callback, context){
		// each index in something list-like. Uses iterator if it has it.
		if(Array.isArray(list)) {
			return shapeReflections.eachListLike(list, callback, context);
		} else {
			var iter, iterator = list[canSymbol_1_7_0_canSymbol.iterator];
			if(type.isIteratorLike(list)) {
				// we are looping through an iterator
				iter = list;
			} else if(iterator) {
				iter = iterator.call(list);
			}
			// fast-path arrays
			if(iter) {
				var res, index = 0;

				while(!(res = iter.next()).done) {
					if( callback.call(context || list, res.value, index++, list) === false ){
						break;
					}
				}
			} else {
				shapeReflections.eachListLike(list, callback, context);
			}
		}
		return list;
	},
	eachListLike: function(list, callback, context){
		var index = -1;
		var length = list.length;
		if( length === undefined ) {
			var size = list[sizeSymbol];
			if(size) {
				length = size.call(list);
			} else {
				throw new Error("can-reflect: unable to iterate.");
			}
		}

		while (++index < length) {
			var item = list[index];
			if (callback.call(context || item, item, index, list) === false) {
				break;
			}
		}

		return list;
	},
	/**
	 * @function can-reflect.toArray toArray
	 * @parent can-reflect/shape
	 * @description  convert the values of any MapLike or ListLike into an array
	 *
	 * @signature `toArray(obj)`
	 *
	 * Convert the values of any Map-like or List-like into a JavaScript Array.  If a Map-like,
	 * key data is discarded and only value data is preserved.
	 *
	 * ```js
	 * var foo = new DefineList(["bar", "baz"]);
	 * var quux = new DefineMap({ thud: "jeek" });
	 * ```
	 *
	 * canReflect.toArray(foo); // -> ["bar", "baz"]
	 * canReflect.toArray(quux): // -> ["jeek"]
	 *
	 * @param  {Object} obj Any object, whether MapLike or ListLike
	 * @return {Array}  an array of the values of `obj`
	 */
	toArray: function(obj){
		var arr = [];
		shapeReflections.each(obj, function(value){
			arr.push(value);
		});
		return arr;
	},
	/**
	 * @function can-reflect.eachKey eachKey
	 * @parent can-reflect/shape
	 * @description Iterate over a MapLike, calling `callback` on each enumerable property
	 *
	 * @signature `eachKey(obj, callback, context)`
	 *
	 * Iterate all own enumerable properties on Map-like `obj`
	 * (using [can-reflect/shape/getOwnEnumerableKeys canReflect.getOwnEnumerableKeys]), and call
	 * `callback` with the property value, the property key, and `obj`, and optionally setting
	 * `this` on the callback as `context` if provided, `obj` otherwise.
	 *
	 * ```js
	 * var foo = new DefineMap({ bar: "baz" });
	 *
	 * canReflect.eachKey(foo, console.log, console); // logs 'baz bar {foo}'
	 * ```
	 *
	 * @param  {Object}   obj   The object to iterate over
	 * @param  {Function(*, String)} callback The callback to call on each enumerable property value
	 * @param  {[Object]}   context  an optional `this` context for calling `callback`
	 * @return {Array}    the enumerable keys of `obj` as an Array
	 */
	eachKey: function(obj, callback, context){
		// each key in something map like
		// eachOwnEnumerableKey
		if(obj) {
			var enumerableKeys = shapeReflections.getOwnEnumerableKeys(obj);

			// cache getKeyValue method if we can
			var getKeyValue = obj[getKeyValueSymbol$1] || shiftedGetKeyValue;

			return shapeReflections.eachIndex(enumerableKeys, function(key){
				var value = getKeyValue.call(obj, key);
				return callback.call(context || obj, value, key, obj);
			});
		}
		return obj;
	},
	/**
	 * @function can-reflect.hasOwnKey hasOwnKey
	 * @parent can-reflect/shape
	 * @description  Determine whether an object contains a key on itself, not only on its prototype chain
	 *
	 * @signature `hasOwnKey(obj, key)`
	 *
	 * Return `true` if an object's own properties include the property key `key`, `false` otherwise.
	 * An object may implement [can-symbol/symbols/hasOwnKey @@@@can.hasOwnKey] to override default behavior.
	 * By default, `canReflect.hasOwnKey` will first look for
	 * [can-symbol/symbols/getOwnKey @@@@can.getOwnKey] on `obj`. If present, it will call `@@@@can.getOwnKey` and
	 * test `key` against the returned Array of keys.  If absent, `Object.prototype.hasOwnKey()` is used.
	 *
	 * ```js
	 * var foo = new DefineMap({ "bar": "baz" });
	 *
	 * canReflect.hasOwnKey(foo, "bar"); // -> true
	 * canReflect.hasOwnKey(foo, "each"); // -> false
	 * foo.each // -> function each() {...}
	 * ```
	 *
	 * @param  {Object} obj Any MapLike object
	 * @param  {String} key The key to look up on `obj`
	 * @return {Boolean} `true` if `obj`'s key set contains `key`, `false` otherwise
	 */
	"hasOwnKey": function(obj, key){
		// if a key or index
		// like has own property
		var hasOwnKey = obj[canSymbol_1_7_0_canSymbol.for("can.hasOwnKey")];
		if(hasOwnKey) {
			return hasOwnKey.call(obj, key);
		}
		var getOwnKeys = obj[canSymbol_1_7_0_canSymbol.for("can.getOwnKeys")];
		if( getOwnKeys ) {
			var found = false;
			shapeReflections.eachIndex(getOwnKeys.call(obj), function(objKey){
				if(objKey === key) {
					found = true;
					return false;
				}
			});
			return found;
		}
		return hasOwnProperty.call(obj, key);
	},
	/**
	 * @function can-reflect.getOwnEnumerableKeys getOwnEnumerableKeys
	 * @parent can-reflect/shape
	 * @description Return the list of keys which can be iterated over on an object
	 *
	 * @signature `getOwnEnumerableKeys(obj)`
	 *
	 * Return all keys on `obj` which have been defined as enumerable, either from explicitly setting
	 * `enumerable` on the property descriptor, or by using `=` to set the value of the property without
	 * a key descriptor, but excluding properties that only exist on `obj`'s prototype chain.  The
	 * default behavior can be overridden by implementing
	 * [can-symbol/symbols/getOwnEnumerableKeys @@@@can.getOwnEnumerableKeys] on `obj`.  By default,
	 * `canReflect.getOwnEnumerableKeys` will use [can-symbol/symbols/getOwnKeys @@@@can.getOwnKeys] to
	 * retrieve the set of keys and [can-symbol/symbols/getOwnKeyDescriptor @@@@can.getOwnKeyDescriptor]
	 * to filter for those which are enumerable.  If either symbol is absent from `obj`, `Object.keys`
	 * is used.
	 *
	 * ```js
	 * var foo = new DefineMap({ bar: "baz", [canSymbol.for("quux")]: "thud" });
	 * Object.defineProperty(foo, "jeek", {
	 *   enumerable: true,
	 *   value: "plonk"
	 * });
	 *
	 * canReflect.getOwnEnumerableKeys(foo); // -> ["bar", "jeek"]
	 * ```
	 *
	 * @param  {Object} obj Any Map-like object
	 * @return {Array} the Array of all enumerable keys from the object, either using
	 * [can-symbol/symbols/getOwnEnumerableKeys `@@@@can.getOwnEnumerableKeys`] from `obj`, or filtering
	 * `obj`'s own keys for those which are enumerable.
	 */
	getOwnEnumerableKeys: function(obj){
		// own enumerable keys (aliased as keys)
		var getOwnEnumerableKeys = obj[canSymbol_1_7_0_canSymbol.for("can.getOwnEnumerableKeys")];
		if(getOwnEnumerableKeys) {
			return getOwnEnumerableKeys.call(obj);
		}
		if( obj[canSymbol_1_7_0_canSymbol.for("can.getOwnKeys")] && obj[canSymbol_1_7_0_canSymbol.for("can.getOwnKeyDescriptor")] ) {
			var keys = [];
			shapeReflections.eachIndex(shapeReflections.getOwnKeys(obj), function(key){
				var descriptor =  shapeReflections.getOwnKeyDescriptor(obj, key);
				if(descriptor.enumerable) {
					keys.push(key);
				}
			}, this);

			return keys;
		} /*else if(obj[canSymbol.iterator]){
			var iter = obj[canSymbol.iterator](obj);
			var index = 0;
			var keys;
			return {
				next: function(){
					var res = iter.next();
					if(index++)
				}
			}
			while(!().done) {

				if( callback.call(context || list, res.value, index++, list) === false ){
					break;
				}
			}
		}*/ else {
			return Object_Keys(obj);
		}
	},
	/**
	 * @function can-reflect.getOwnKeys getOwnKeys
	 * @parent can-reflect/shape
	 * @description Return the list of keys on an object, whether or not they can be iterated over
	 *
	 * @signature `getOwnKeys(obj)`
	 *
	 * Return the Array of all String (not Symbol) keys from `obj`, whether they are enumerable or not.  If
	 * [can-symbol/symbols/getOwnKeys @@@@can.getOwnKeys] exists on `obj`, it is called to return
	 * the keys; otherwise, `Object.getOwnPropertyNames()` is used.
	 *
	 * ```js
	 * var foo = new DefineMap({ bar: "baz", [canSymbol.for("quux")]: "thud" });
	 * Object.defineProperty(foo, "jeek", {
	 *   enumerable: false,
	 *   value: "plonk"
	 * });
	 *
	 * canReflect.getOwnKeys(foo); // -> ["bar", "jeek"]
	 * ```
	 *
	 * @param  {Object} obj Any MapLike object
	 * @return {Array} the Array of all String keys from the object.
	 */
	getOwnKeys: function(obj){
		// own enumerable&non-enumerable keys (Object.getOwnPropertyNames)
		var getOwnKeys = obj[canSymbol_1_7_0_canSymbol.for("can.getOwnKeys")];
		if(getOwnKeys) {
			return getOwnKeys.call(obj);
		} else {
			return Object.getOwnPropertyNames(obj);
		}
	},
	/**
	 * @function can-reflect.getOwnKeyDescriptor getOwnKeyDescriptor
	 * @parent can-reflect/shape
	 * @description Return a property descriptor for a named property on an object.
	 *
	 * @signature `getOwnKeyDescriptor(obj, key)`
	 *
	 *	Return the key descriptor for the property key `key` on the Map-like object `obj`. A key descriptor
	 *	is specified in ECMAScript 5 and contains keys for the property's `configurable` and `enumerable` states,
	 *	as well as either `value` and `writable` for value properties, or `get` and `set` for getter/setter properties.
	 *
	 * The default behavior can be overridden by implementing [can-symbol/symbols/getOwnKeyDescriptor @@@@can.getOwnKeyDescriptor]
	 * on `obj`; otherwise the default is to call `Object.getOwnKeyDescriptor()`.
	 *
	 * ```js
	 * var foo = new DefineMap({ bar: "baz" });
	 *
	 * getOwnKeyDescriptor(foo, "bar"); // -> {configurable: true, writable: true, enumerable: true, value: "baz"}
	 * ```
	 *
	 * @param  {Object} obj Any object with named properties
	 * @param  {String} key The property name to look up on `obj`
	 * @return {Object}   A key descriptor object
	 */
	getOwnKeyDescriptor: function(obj, key){
		var getOwnKeyDescriptor = obj[canSymbol_1_7_0_canSymbol.for("can.getOwnKeyDescriptor")];
		if(getOwnKeyDescriptor) {
			return getOwnKeyDescriptor.call(obj, key);
		} else {
			return Object.getOwnPropertyDescriptor(obj, key);
		}
	},
	/**
	 * @function can-reflect.unwrap unwrap
	 * @parent can-reflect/shape
	 * @description Unwraps a map-like or array-like value into an object or array.
	 *
	 *
	 * @signature `unwrap(obj)`
	 *
	 * Recursively unwraps a map-like or list-like object.
	 *
	 * ```js
	 * import canReflect from "can-reflect";
	 *
	 * var map = new DefineMap({foo: "bar"});
	 * canReflect.unwrap(map) //-> {foo: "bar"}
	 * ```
	 *
	 * `unwrap` is similar to [can-reflect.serialize] except it does not try to provide `JSON.stringify()`-safe
	 * objects.  For example, an object with a `Date` instance property value will not be expected to
	 * serialize the date instance:
	 *
	 * ```js
	 * var date = new Date();
	 * var map = new DefineMap({date: date});
	 * canReflect.unwrap(map) //-> {date: date}
	 * ```
	 *
	 * @param {Object} obj A map-like or array-like object.
	 * @return {Object} Returns objects and arrays.
	 */
	unwrap: makeSerializer("unwrap",[canSymbol_1_7_0_canSymbol.for("can.unwrap")]),
	/**
	 * @function can-reflect.serialize serialize
	 * @parent can-reflect/shape
	 * @description Serializes an object to a value that can be passed to JSON.stringify.
	 *
	 *
	 * @signature `serialize(obj)`
	 *
	 * Recursively serializes a map-like or list-like object.
	 *
	 * ```js
	 * import canReflect from "can-reflect";
	 * canReflect.serialize({foo: "bar"}) //-> {foo: "bar"}
	 * ```
	 *
	 * It does this by recursively:
	 *
	 *  - Checking if `obj` is a primitive, if it is, returns the value.
	 *  - If `obj` is an object:
	 *    - calling the `@can.serialize` property on the value if it exists.
	 *    - If the `@can.serialize` value doesn't exist, walks through every key-value
	 *      on `obj` and copy to a new object.
	 *
	 * @param {Object} obj A map-like or array-like object.
	 * @return {Object} Returns a plain object or array.
	 */
	serialize: makeSerializer("serialize",[canSymbol_1_7_0_canSymbol.for("can.serialize"), canSymbol_1_7_0_canSymbol.for("can.unwrap")]),

	assignMap: function(target, source) {
		// read each key and set it on target
		var hasOwnKey = fastHasOwnKey(target);
		var getKeyValue = target[getKeyValueSymbol$1] || shiftedGetKeyValue;
		var setKeyValue = target[setKeyValueSymbol$1] || shiftedSetKeyValue;
		shapeReflections.eachKey(source,function(value, key){
			// if the target doesn't have this key or the keys are not the same
			if(!hasOwnKey(key) || getKeyValue.call(target, key) !==  value) {
				setKeyValue.call(target, key, value);
			}
		});
		return target;
	},
	assignList: function(target, source) {
		var inserting = shapeReflections.toArray(source);
		getSet.splice(target, 0, inserting, inserting );
		return target;
	},
	/**
	 * @function can-reflect.assign assign
	 * @parent can-reflect/shape
	 * @description Assign one objects values to another
	 *
	 * @signature `.assign(target, source)`
	 *
	 * Copies the values (and properties if map-like) from `source` onto `target`.
	 *
	 * For map-like objects, every enumerable property on `target` is copied:
	 *
	 * ```js
	 * var target = {};
	 * var source = {key : "value"};
	 * var restult = canReflect.assign(target, source);
	 * result === target //-> true
	 * target //-> {key : "value"}
	 * ```
	 *
	 * For Arrays, enumerated values are copied over, but the length of the array will not be
	 * trunkated.  Use [can-reflect.update] for trunkating.
	 *
	 * ```js
	 * var target = ["a","b","c"];
	 * var source = ["A","B"];
	 * canReflect.assign(target, source);
	 * target //-> ["A","B","c"]
	 * ```
	 *
	 * @param  {Object} target The value that will be updated with `source`'s values.
	 * @param  {Object} source A source of values to copy to `target`.
	 * @return {Object} The target.
	 */
	assign: function(target, source) {
		if(type.isIteratorLike(source) || type.isMoreListLikeThanMapLike(source) ) {
			// copy to array and add these keys in place
			shapeReflections.assignList(target, source);
		} else {
			shapeReflections.assignMap(target, source);
		}
		return target;
	},
	assignDeepMap: function(target, source) {

		var hasOwnKey = fastHasOwnKey(target);
		var getKeyValue = target[getKeyValueSymbol$1] || shiftedGetKeyValue;
		var setKeyValue = target[setKeyValueSymbol$1] || shiftedSetKeyValue;

		shapeReflections.eachKey(source, function(newVal, key){
			if(!hasOwnKey(key)) {
				// set no matter what
				getSet.setKeyValue(target, key, newVal);
			} else {
				var curVal = getKeyValue.call(target, key);

				// if either was primitive, no recursive update possible
				if(newVal === curVal) {
					// do nothing
				} else if(type.isPrimitive(curVal) || type.isPrimitive(newVal) || shouldUpdateOrAssign(curVal) === false ) {
					setKeyValue.call(target, key, newVal);
				} else {
					shapeReflections.assignDeep(curVal, newVal);
				}
			}
		}, this);
		return target;
	},
	assignDeepList: function(target, source) {
		return updateDeepList.call(this, target, source, true);
	},
	/**
	 * @function can-reflect.assignDeep assignDeep
	 * @parent can-reflect/shape
	 * @description Assign one objects values to another, and performs the same action for all child values.
	 *
	 * @signature `.assignDeep(target, source)`
	 *
	 * Copies the values (and properties if map-like) from `source` onto `target` and repeates for all child
	 * values.
	 *
	 * For map-like objects, every enumerable property on `target` is copied:
	 *
	 * ```js
	 * var target = {name: {first: "Justin"}};
	 * var source = {name: {last: "Meyer"}};
	 * var restult = canReflect.assignDeep(target, source);
	 * target //->  {name: {first: "Justin", last: "Meyer"}}
	 * ```
	 *
	 * An object can control the behavior of `assignDeep` using the [can-symbol/symbols/assignDeep] symbol.
	 *
	 * @param  {Object} target The value that will be updated with `source`'s values.
	 * @param  {Object} source A source of values to copy to `target`.
	 * @return {Object} The target.
	 */
	assignDeep: function(target, source){
		var assignDeep = target[canSymbol_1_7_0_canSymbol.for("can.assignDeep")];
		if(assignDeep) {
			assignDeep.call(target, source);
		} else if( type.isMoreListLikeThanMapLike(source) ) {
			// list-like
			shapeReflections.assignDeepList(target, source);
		} else {
			// map-like
			shapeReflections.assignDeepMap(target, source);
		}
		return target;
	},
	updateMap: function(target, source) {
		var sourceKeyMap = makeMap( shapeReflections.getOwnEnumerableKeys(source) );

		var sourceGetKeyValue = source[getKeyValueSymbol$1] || shiftedGetKeyValue;
		var targetSetKeyValue = target[setKeyValueSymbol$1] || shiftedSetKeyValue;

		shapeReflections.eachKey(target, function(curVal, key){
			if(!sourceKeyMap.get(key)) {
				getSet.deleteKeyValue(target, key);
				return;
			}
			sourceKeyMap.set(key, false);
			var newVal = sourceGetKeyValue.call(source, key);

			// if either was primitive, no recursive update possible
			if(newVal !== curVal) {
				targetSetKeyValue.call(target, key, newVal);
			}
		}, this);

		shapeReflections.eachIndex(sourceKeyMap.keys(), function(key){
			if(sourceKeyMap.get(key)) {
				targetSetKeyValue.call(target, key, sourceGetKeyValue.call(source, key) );
			}
		});

		return target;
	},
	updateList: function(target, source) {
		var inserting = shapeReflections.toArray(source);

		getSet.splice(target, 0, target, inserting );
		return target;
	},
	/**
	 * @function can-reflect.update update
	 * @parent can-reflect/shape
	 * @description Updates the values of an object match the values of an other object.
	 *
	 * @signature `.update(target, source)`
	 *
	 * Updates the values (and properties if map-like) of `target` to match the values of `source`.
	 * Properties of `target` that are not on `source` will be removed. This does
	 * not recursively update.  For that, use [can-reflect.updateDeep].
	 *
	 * For map-like objects, every enumerable property on `target` is copied:
	 *
	 * ```js
	 * var target = {name: {first: "Justin"}, age: 34};
	 * var source = {name: {last: "Meyer"}};
	 * var result = canReflect.update(target, source);
	 * target //->  {name: {last: "Meyer"}}
	 * ```
	 *
	 * With Arrays all items of the source will be replaced with the new items.
	 *
	 * ```js
	 * var target = ["a","b","c"];
	 * var source = ["A","B"];
	 * canReflect.update(target, source);
	 * target //-> ["A","B"]
	 * ```
	 *
	 * @param  {Object} target The value that will be updated with `source`'s values.
	 * @param  {Object} source A source of values to copy to `target`.
	 * @return {Object} The target.
	 */
	update: function(target, source) {
		if(type.isIteratorLike(source) || type.isMoreListLikeThanMapLike(source) ) {
			// copy to array and add these keys in place
			shapeReflections.updateList(target, source);
		} else {
			shapeReflections.updateMap(target, source);
		}
		return target;
	},
	updateDeepMap: function(target, source) {
		var sourceKeyMap = makeMap( shapeReflections.getOwnEnumerableKeys(source) );

		var sourceGetKeyValue = source[getKeyValueSymbol$1] || shiftedGetKeyValue;
		var targetSetKeyValue = target[setKeyValueSymbol$1] || shiftedSetKeyValue;

		shapeReflections.eachKey(target, function(curVal, key){

			if(!sourceKeyMap.get(key)) {
				getSet.deleteKeyValue(target, key);
				return;
			}
			sourceKeyMap.set(key, false);
			var newVal = sourceGetKeyValue.call(source, key);

			// if either was primitive, no recursive update possible
			if(type.isPrimitive(curVal) || type.isPrimitive(newVal) || shouldUpdateOrAssign(curVal) === false ) {
				targetSetKeyValue.call(target, key, newVal);
			} else {
				shapeReflections.updateDeep(curVal, newVal);
			}

		}, this);

		shapeReflections.eachIndex(sourceKeyMap.keys(), function(key){
			if(sourceKeyMap.get(key)) {
				targetSetKeyValue.call(target, key, sourceGetKeyValue.call(source, key) );
			}
		});
		return target;
	},
	updateDeepList: function(target, source) {
		return updateDeepList.call(this,target, source);
	},
	/**
	 * @function can-reflect.updateDeep updateDeep
	 * @parent can-reflect/shape
	 * @description Makes the values of an object match the values of an other object including all children values.
	 *
	 * @signature `.updateDeep(target, source)`
	 *
	 * Updates the values (and properties if map-like) of `target` to match the values of `source`.
	 * Removes properties from `target` that are not on `source`.
	 *
	 * For map-like objects, every enumerable property on `target` is copied:
	 *
	 * ```js
	 * var target = {name: {first: "Justin"}, age: 34};
	 * var source = {name: {last: "Meyer"}};
	 * var result = canReflect.updateDeep(target, source);
	 * target //->  {name: {last: "Meyer"}}
	 * ```
	 *
	 * An object can control the behavior of `updateDeep` using the [can-symbol/symbols/updateDeep] symbol.
	 *
	 * For list-like objects, a diff and patch strategy is used.  This attempts to limit the number of changes.
	 *
	 * @param  {Object} target The value that will be updated with `source`'s values.
	 * @param  {Object} source A source of values to copy to `target`.
	 * @return {Object} The target.
	 */
	updateDeep: function(target, source){
		var updateDeep = target[canSymbol_1_7_0_canSymbol.for("can.updateDeep")];
		if(updateDeep) {
			updateDeep.call(target, source);
		} else if( type.isMoreListLikeThanMapLike(source) ) {
			// list-like
			shapeReflections.updateDeepList(target, source);
		} else {
			// map-like
			shapeReflections.updateDeepMap(target, source);
		}
		return target;
	},
	// walks up the whole prototype chain
	/**
	 * @function can-reflect.hasKey hasKey
	 * @parent can-reflect/shape
	 * @description Determine whether an object contains a key on itself or its prototype chain
	 *
	 * @signature `hasKey(obj, key)`
	 *
	 * Return `true` if an object's properties include the property key `key` or an object on its prototype
	 * chain's properties include the key `key`, `false` otherwise.
	 * An object may implement [can-symbol/symbols/hasKey @@@@can.hasKey] to override default behavior.
	 * By default, `canReflect.hasKey` will use [can-reflect.hasOwnKey] and return true if the key is present.
	 * If `hasOwnKey` returns false, the [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in in Operator] will be used.
	 *
	 * ```js
	 * var foo = new DefineMap({ "bar": "baz" });
	 *
	 * canReflect.in(foo, "bar"); // -> true
	 * canReflect.in(foo, "each"); // -> true
	 * foo.each // -> function each() {...}
	 * ```
	 *
	 * @param  {Object} obj Any MapLike object
	 * @param  {String} key The key to look up on `obj`
	 * @return {Boolean} `true` if `obj`'s key set contains `key` or an object on its prototype chain's key set contains `key`, `false` otherwise
	 */
	hasKey: function(obj, key) {
		if( obj == null ) {
			return false;
		}
		if (type.isPrimitive(obj)) {
			if (hasOwnProperty.call(obj, key)) {
				return true;
			} else {
				var proto;
				if(getPrototypeOfWorksWithPrimitives) {
					proto = Object.getPrototypeOf(obj);
				} else {
					// IE-remove-start
					proto = obj.__proto__; // jshint ignore:line
					// IE-remove-end
				}
				if(proto !== undefined) {
					return key in proto;
				} else {
					// IE-remove-start
					return obj[key] !== undefined;
					// IE-remove-end
				}
			}
		}
		var hasKey = obj[canSymbol_1_7_0_canSymbol.for("can.hasKey")];
		if(hasKey) {
			return hasKey.call(obj, key);
		}

		var found = shapeReflections.hasOwnKey(obj, key);

		return found || key in obj;
	},
	getAllEnumerableKeys: function(){},
	getAllKeys: function(){},
	/**
	 * @function can-reflect.assignSymbols assignSymbols
	 * @parent can-reflect/shape
	 * @description Assign well known symbols and values to an object.
	 *
	 * @signature `.assignSymbols(target, source)`
	 *
	 * Converts each property name on the `source` object to a [can-symbol.for well known symbol]
	 * and uses that symbol to set the corresponding value on target.
	 *
	 * This is used to easily set symbols correctly even when symbol isn't natively supported.
	 *
	 * ```js
	 * canReflect.assignSymbols(Map.prototype, {
	 *   "can.getKeyValue": Map.prototype.get
	 * })
	 * ```
	 *
	 * If a `source` property name matches a symbol on `Symbol` (like `iterator` on `Symbol.iterator`),
	 * that symbol will be used:
	 *
	 * ```js
	 * canReflect.assignSymbols(ArrayLike.prototype, {
	 *   "iterator": function() { ... }
	 * })
	 * ArrayLike.prototype[Symbol.iterator] = function(){ ... }
	 * ```
	 *
	 * @param  {Object} target The value that will be updated with `source`'s symbols and values.
	 * @param  {Object<name,value>} source A source of symbol names and values to copy to `target`.
	 * @return {Object} The target.
	 */
	assignSymbols: function(target, source){
		shapeReflections.eachKey(source, function(value, key){
			var symbol = type.isSymbolLike(canSymbol_1_7_0_canSymbol[key]) ? canSymbol_1_7_0_canSymbol[key] : canSymbol_1_7_0_canSymbol.for(key);
			getSet.setKeyValue(target, symbol, value);
		});
		return target;
	},
	isSerialized: isSerializedHelper,
	/**
	 * @function can-reflect.size size
	 * @parent can-reflect/shape
	 * @description Return the number of items in the collection.
	 *
	 * @signature `.size(target)`
	 *
	 * Returns the number of items contained in `target`. Target can
	 * provide the size using the [can-symbol/symbols/size] symbol.
	 *
	 * If the `target` has a numeric `length` property that is greater than or equal to 0, that
	 * `length` will be returned.
	 *
	 * ```js
	 * canReflect.size([1,2,3]) //-> 3
	 * ```
	 *
	 * If the `target` is [can-reflect.isListLike], the values of the list will be counted.
	 *
	 * If the `target` is a plain JS object, the number of enumerable properties will be returned.
	 *
	 * ```js
	 * canReflect.size({foo:"bar"}) //-> 1
	 * ```
	 *
	 * If the `target` is anything else, `undefined` is returned.
	 *
	 * @param  {Object} target The container object.
	 * @return {Number} The number of values in the target.
	 */
	size: function(obj){
		if(obj == null) {
			return 0;
		}
		var size = obj[sizeSymbol];
		var count = 0;
		if(size) {
			return size.call(obj);
		}
		else if(helpers.hasLength(obj)){
			return obj.length;
		}
		else if(type.isListLike(obj)){

			shapeReflections.eachIndex(obj, function(){
				count++;
			});
			return count;
		}
		else if( obj ) {
			return shapeReflections.getOwnEnumerableKeys(obj).length;
		}
		else {
			return undefined;
		}
	},
	/**
	 * @function {Function, String|Symbol, Object} can-reflect.defineInstanceKey defineInstanceKey
	 * @parent can-reflect/shape
	 * @description Create a key for all instances of a constructor.
	 *
	 * @signature `defineInstanceKey(cls, key, properties)`
	 *
	 * Define the property `key` on the prototype of the constructor `cls` using the symbolic
	 * property [can-symbol/symbols/defineInstanceKey @@can.defineInstanceKey] if it exists; otherwise
	 * use `Object.defineProperty()` to define the property.  The property definition
	 *
	 * @param  {Function} cls  a Constructor function
	 * @param  {String} key     the String or Symbol key to set.
	 * @param  {Object} properties a JavaScript property descriptor
	 */
	defineInstanceKey: function(cls, key, properties) {
		var defineInstanceKey = cls[canSymbol_1_7_0_canSymbol.for("can.defineInstanceKey")];
		if(defineInstanceKey) {
			return defineInstanceKey.call(cls, key, properties);
		}
		var proto = cls.prototype;
		defineInstanceKey = proto[canSymbol_1_7_0_canSymbol.for("can.defineInstanceKey")];
		if(defineInstanceKey) {
			defineInstanceKey.call(proto, key, properties);
		} else {
			Object.defineProperty(
				proto,
				key,
				shapeReflections.assign({
					configurable: true,
					enumerable: !type.isSymbolLike(key),
					writable: true
				}, properties)
			);
		}
	}
};

shapeReflections.isSerializable = shapeReflections.isSerialized;
shapeReflections.keys = shapeReflections.getOwnEnumerableKeys;
var shape = shapeReflections;

var getSchemaSymbol = canSymbol_1_7_0_canSymbol.for("can.getSchema"),
    isMemberSymbol = canSymbol_1_7_0_canSymbol.for("can.isMember"),
    newSymbol = canSymbol_1_7_0_canSymbol.for("can.new");

function comparator(a, b) {
    return a.localeCompare(b);
}

function sort(obj) {
    if(type.isPrimitive(obj) || obj instanceof Date) {
        return obj;
    }
    var out;
    if (type.isListLike(obj)) {
        out = [];
        shape.eachKey(obj, function(item){
            out.push(sort(item));
        });
        return out;
    }
    if( type.isMapLike(obj) ) {

        out = {};

        shape.getOwnKeys(obj).sort(comparator).forEach(function (key) {
            out[key] = sort( getSet.getKeyValue(obj, key) );
        });

        return out;
    }


    return obj;
}

function isPrimitiveConverter(Type){
    return Type === Number || Type === String || Type === Boolean;
}

var schemaReflections =  {
    /**
	 * @function can-reflect.getSchema getSchema
	 * @parent can-reflect/shape
	 * @description Returns the schema for a type or value.
	 *
	 * @signature `getSchema(valueOrType)`
	 *
     * Calls the `@can.getSchema` property on the `valueOrType` argument. If it's not available and
     * `valueOrType` has a `constructor` property, calls the `constructor[@can.getSchema]`
     * and returns the result.
     *
     * ```js
     * import canReflect from "can-reflect";
     *
     * var Type = DefineMap.extend({
     *   name: "string",
     *   id: "number"
     * });
     *
     * canReflect.getSchema( Type ) //-> {
     * //   type: "map",
     * //   keys: {
     * //     name: MaybeString
     * //     id: MaybeNumber
     * //   }
     * // }
     * ```
	 *
	 *
	 * @param  {Object|Function} valueOrType A value, constructor function, or class to get the schema from.
	 * @return {Object} A schema. A schema for a [can-reflect.isMapLike] looks like:
     *
     *
     * ```js
     * {
     *   type: "map",
     *   identity: ["id"],
     *   keys: {
     *     id: Number,
     *     name: String,
     *     complete: Boolean,
     *     owner: User
     *   }
     * }
     * ```
     *
     * A schema for a list looks like:
     *
     * ```js
     * {
     *   type: "list",
     *   values: String
     *   keys: {
     *     count: Number
     *   }
     * }
     * ```
     *
	 */
    getSchema: function(type$$1){
        if (type$$1 === undefined || type$$1 === null) {
            return type$$1;
        }
        var getSchema = type$$1[getSchemaSymbol];
        if(getSchema === undefined ) {
            type$$1 = type$$1.constructor;
            getSchema = type$$1 && type$$1[getSchemaSymbol];
        }
        return getSchema !== undefined ? getSchema.call(type$$1) : undefined;
    },
    /**
	 * @function can-reflect.getIdentity getIdentity
	 * @parent can-reflect/shape
	 * @description Get a unique primitive representing an object.
	 *
	 * @signature `getIdentity( object [,schema] )`
	 *
	 * This uses the object's schema, or the provided schema to return a unique string or number that
     * represents the object.
     *
     * ```js
     * import canReflect from "can-reflect";
     *
     * canReflect.getIdentity({id: 5}, {identity: ["id"]}) //-> 5
     * ```
     *
     * If the schema has multiple identity keys, the identity keys and values
     * are return stringified (and sorted):
     *
     * ```js
     * canReflect.getIdentity(
     *   {z: "Z", a: "A", foo: "bar"},
     *   {identity: ["a","b"]}) //-> '{"a":"A","b":"B"}'
     * ```
	 *
	 * @param  {Object|Function} object A map-like object.
     * @param {Object} [schema] A schema object with an `identity` array of the unique
     * keys of the object like:
     *   ```js
     *   {identity: ["id"]}
     *   ```
	 * @return {Number|String} A value that uniquely represents the object.
	 */
    getIdentity: function(value, schema){
        schema = schema || schemaReflections.getSchema(value);
        if(schema === undefined) {
            throw new Error("can-reflect.getIdentity - Unable to find a schema for the given value.");
        }

        var identity = schema.identity;
        if(!identity || identity.length === 0) {
            throw new Error("can-reflect.getIdentity - Provided schema lacks an identity property.");
        } else if(identity.length === 1) {
            return getSet.getKeyValue(value, identity[0]);
        } else {
            var id = {};
            identity.forEach(function(key){
                id[key] = getSet.getKeyValue(value, key);
            });
            return JSON.stringify(schemaReflections.cloneKeySort(id));
        }
    },
    /**
	 * @function can-reflect.cloneKeySort cloneKeySort
	 * @parent can-reflect/shape
	 * @description Copy a value while sorting its keys.
	 *
	 * @signature `cloneKeySort(value)`
	 *
     * `cloneKeySort` returns a copy of `value` with its [can-reflect.isMapLike]
     * key values sorted. If you just want a copy of a value,
     * use [can-reflect.serialize].
     *
     * ```js
     * import canRefect from "can-reflect";
     *
     * canReflect.cloneKeySort({z: "Z", a: "A"}) //-> {a:"A",z:"Z"}
     * ```
     *
     * Nested objects are also sorted.
	 *
     * This is useful if you need to store a representation of an object that can be used as a
     * key.
	 *
	 * @param  {Object} value An object or array.
	 * @return {Object} A copy of the object with its keys sorted.
	 */
    cloneKeySort: function(obj) {
        return sort(obj);
    },
    /**
	 * @function can-reflect.convert convert
	 * @parent can-reflect/shape
	 * @description Convert one value to another type.
	 *
	 * @signature `convert(value, Type)`
	 *
     * `convert` attempts to convert `value` to the type specified by `Type`.
     *
     * ```js
     * import canRefect from "can-reflect";
     *
     * canReflect.convert("1", Number) //-> 1
     * ```
     *
     * `convert` works by performing the following logic:
     *
     * 1. If the `Type` is a primitive like `Number`, `String`, `Boolean`, the
     *    `value` will be passed to the `Type` function and the result returned.
     *    ```js
     *    return Type(value);
     *    ```
     * 2. The value will be checked if it is already an instance of the type
     *    by performing the following:
     *    1. If the `Type` has a `can.isMember` symbol value, that value will be used
     *       to determine if the `value` is already an instance.
     *    2. If the `Type` is a [can-reflect.isConstructorLike] function, `instanceof Type`
     *       will be used to check if `value` is already an instance.
     * 3. If `value` is already an instance, `value` will be returned.
     * 4. If `Type` has a `can.new` symbol, `value` will be passed to it and the result
     *    returned.
     * 5. If `Type` is a [can-reflect.isConstructorLike] function, `new Type(value)` will be
     *    called the the result returned.
     * 6. If `Type` is a regular function, `Type(value)` will be called and the result returned.
     * 7. If a value hasn't been returned, an error is thrown.
	 *
	 * @param  {Object|Primitive} value A value to be converted.
     * @param  {Object|Function} Type A constructor function or an object that implements the
     * necessary symbols.
	 * @return {Object} The `value` converted to a member of `Type`.
	 */
    convert: function(value, Type){
        if(isPrimitiveConverter(Type)) {
            return Type(value);
        }
        // check if value is already a member
        var isMemberTest = Type[isMemberSymbol],
            isMember = false,
            type$$1 = typeof Type,
            createNew = Type[newSymbol];
        if(isMemberTest !== undefined) {
            isMember = isMemberTest.call(Type, value);
        } else if(type$$1 === "function") {
            if(type.isConstructorLike(Type)) {
                isMember = (value instanceof Type);
            }
        }
        if(isMember) {
            return value;
        }
        if(createNew !== undefined) {
            return createNew.call(Type, value);
        } else if(type$$1 === "function") {
            if(type.isConstructorLike(Type)) {
                return new Type(value);
            } else {
                // call it like a normal function
                return Type(value);
            }
        } else {
            throw new Error("can-reflect: Can not convert values into type. Type must provide `can.new` symbol.");
        }
    }
};
var schema = schemaReflections;

var getNameSymbol = canSymbol_1_7_0_canSymbol.for("can.getName");

/**
 * @function {Object, String} can-reflect.setName setName
 * @parent can-reflect/shape
 * @description Set a human-readable name of an object.
 *
 * @signature `setName(obj, value)`
 *
 * ```js
 * var f = function() {};
 *
 * canReflect.setName(f, "myFunction")
 * f.name //-> "myFunction"
 * ```
 *
 * @param {Object} obj   the object to set on
 * @param {String} value the value to set for the object
 */
function setName(obj, nameGetter) {
	if (typeof nameGetter !== "function") {
		var value = nameGetter;
		nameGetter = function() {
			return value;
		};
	}

	Object.defineProperty(obj, getNameSymbol, {
		value: nameGetter
	});
}

/**
 * @function {Object} can-reflect.getName getName
 * @parent can-reflect/shape
 * @description Get the name of an object.
 *
 * @signature `getValue(obj)`
 *
 * @body
 *
 * The [@@@can.getName](can-symbol/symbols/getName.html) symbol is used to
 * provide objects human readable names; the main goal of these names is to help
 * users get a glance of what the object does and what it is used for.
 *
 * There are no hard rules to define names but CanJS uses the following convention
 * for consistent names across its observable types:
 *
 * - The name starts with the observable constructor name
 * - The constructor name is decorated with the following characters based on its type:
 *		- `<>`: for [value-like](can-reflect.isValueLike.html) observables, e.g: `SimpleObservable<>`
 *		- `[]`: for [list-like](can-reflect.isListLike.html) observables, e.g: `DefineList[]`
 *		- `{}`: for [map-like](can-reflect.isMapLike.html) observables, e.g: `DefineMap{}`
 * - Any property that makes the instance unique (like ids) are printed inside
 *    the chars mentioned before.
 *
 * The example below shows how to implement [@@@can.getName](can-symbol/symbols/getName.html),
 * in a value-like observable (similar to [can-simple-observable]).
 *
 * ```js
 * var canReflect = require("can-reflect");
 *
 * function MySimpleObservable(value) {
 *		this.value = value;
 * }
 *
 * canReflect.assignSymbols(MySimpleObservable.prototype, {
 *		"can.getName": function() {
 *			//!steal-remove-start
 *			if (process.env.NODE_ENV !== 'production') {
 *				var value = JSON.stringify(this.value);
 *				return canReflect.getName(this.constructor) + "<" + value + ">";
 *			}
 *			//!steal-remove-end
 *		}
 * });
 * ```
 *
 * With that in place, `MySimpleObservable` can be used like this:
 *
 * ```js
 * var one = new MySimpleObservable(1);
 * canReflect.getName(one); // MySimpleObservable<1>
 * ```
 *
 * @param  {Object} obj The object to get from
 * @return {String} The human-readable name of the object
 */
var anonymousID = 0;
function getName(obj) {
	var type$$1 = typeof obj;
	if(obj === null || (type$$1 !== "object" && type$$1 !== "function")) {
		return ""+obj;
	}
	var nameGetter = obj[getNameSymbol];
	if (nameGetter) {
		return nameGetter.call(obj);
	}

	if (type$$1 === "function") {
		if (!("name" in obj)) {
			// IE doesn't support function.name natively
			obj.name = "functionIE" + anonymousID++;
		}
		return obj.name;
	}

	if (obj.constructor && obj !== obj.constructor) {
		var parent = getName(obj.constructor);
		if (parent) {
			if (type.isValueLike(obj)) {
				return parent + "<>";
			}

			if (type.isMoreListLikeThanMapLike(obj)) {
				return parent + "[]";
			}

			if (type.isMapLike(obj)) {
				return parent + "{}";
			}
		}
	}

	return undefined;
}

var getName_1 = {
	setName: setName,
	getName: getName
};

function keysPolyfill() {
  var keys = [];
  var currentIndex = 0;

  this.forEach(function(val, key) { // jshint ignore:line
    keys.push(key);
  });

  return {
    next: function() {
      return {
        value: keys[currentIndex],
        done: (currentIndex++ === keys.length)
      };
    }
  };
}

if (typeof Map !== "undefined") {
  shape.assignSymbols(Map.prototype, {
    "can.getOwnEnumerableKeys": Map.prototype.keys,
    "can.setKeyValue": Map.prototype.set,
    "can.getKeyValue": Map.prototype.get,
    "can.deleteKeyValue": Map.prototype["delete"],
    "can.hasOwnKey": Map.prototype.has
  });

  if (typeof Map.prototype.keys !== "function") {
    Map.prototype.keys = Map.prototype[canSymbol_1_7_0_canSymbol.for("can.getOwnEnumerableKeys")] = keysPolyfill;
  }
}

if (typeof WeakMap !== "undefined") {
  shape.assignSymbols(WeakMap.prototype, {
    "can.getOwnEnumerableKeys": function() {
      throw new Error("can-reflect: WeakMaps do not have enumerable keys.");
    },
    "can.setKeyValue": WeakMap.prototype.set,
    "can.getKeyValue": WeakMap.prototype.get,
    "can.deleteKeyValue": WeakMap.prototype["delete"],
    "can.hasOwnKey": WeakMap.prototype.has
  });
}

if (typeof Set !== "undefined") {
  shape.assignSymbols(Set.prototype, {
    "can.isMoreListLikeThanMapLike": true,
    "can.updateValues": function(index, removing, adding) {
      if (removing !== adding) {
        shape.each(
          removing,
          function(value) {
            this.delete(value);
          },
          this
        );
      }
      shape.each(
        adding,
        function(value) {
          this.add(value);
        },
        this
      );
    },
    "can.size": function() {
      return this.size;
    }
  });

  // IE11 doesn't support Set.prototype[@@iterator]
  if (typeof Set.prototype[canSymbol_1_7_0_canSymbol.iterator] !== "function") {
	  Set.prototype[canSymbol_1_7_0_canSymbol.iterator] = function() {
		  var arr = [];
		  var currentIndex = 0;

		  this.forEach(function(val) {
			  arr.push(val);
		  });

		  return {
			  next: function() {
				  return {
					  value: arr[currentIndex],
					  done: (currentIndex++ === arr.length)
				  };
			  }
		  };
	  };
  }
}
if (typeof WeakSet !== "undefined") {
  shape.assignSymbols(WeakSet.prototype, {
    "can.isListLike": true,
    "can.isMoreListLikeThanMapLike": true,
    "can.updateValues": function(index, removing, adding) {
      if (removing !== adding) {
        shape.each(
          removing,
          function(value) {
            this.delete(value);
          },
          this
        );
      }
      shape.each(
        adding,
        function(value) {
          this.add(value);
        },
        this
      );
    },
    "can.size": function() {
      throw new Error("can-reflect: WeakSets do not have enumerable keys.");
    }
  });
}

var reflect = {};
[
	call,
	getSet,
	observe,
	shape,
	type,
	getName_1,
	schema
].forEach(function(reflections){
	for(var prop in reflections) {
		reflect[prop] = reflections[prop];
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			if(typeof reflections[prop] === "function") {
				var propDescriptor = Object.getOwnPropertyDescriptor(reflections[prop], 'name');
				if (!propDescriptor || propDescriptor.writable && propDescriptor.configurable) {
					Object.defineProperty(reflections[prop],"name",{
						value: "canReflect."+prop
					});
				}
			}
		}
		//!steal-remove-end
	}
});




var canReflect_1_19_2_canReflect = canNamespace_1_0_0_canNamespace.Reflect = reflect;

var utils = {
    isContainer: function (current) {
        var type = typeof current;
        return current && (type === "object" || type === "function");
    },
    strReplacer: /\{([^\}]+)\}/g,

    parts: function(name) {
        if(Array.isArray(name)) {
            return name;
        } else {
            return typeof name !== 'undefined' ? (name + '').replace(/\[/g,'.')
            		.replace(/]/g,'').split('.') : [];
        }
    }
};

var canKey_1_2_1_utils= utils;

/**
 * @module {function} can-key/delete/delete
 * @parent can-key
 */
var _delete = function deleteAtPath(data, path) {
    var parts = canKey_1_2_1_utils.parts(path);
    var current = data;

    for(var i = 0; i < parts.length - 1; i++) {
        if(current) {
            current = canReflect_1_19_2_canReflect.getKeyValue( current, parts[i]);
        }
    }

    if(current) {
        canReflect_1_19_2_canReflect.deleteKeyValue(current, parts[parts.length - 1 ]);
    }
};

/**
 * @module {function} can-key/get/get
 * @parent can-key
 * @description Get properties on deep/nested objects of different types: Object, Map, [can-reflect] types, etc.
 *
 * @signature `get(obj, path)`
 * @param  {Object} obj the object to use as the root for property-based navigation
 * @param  {String} path a String of dot-separated keys, representing a path of properties
 * @return {*}       the value at the property path
 *
 * @body
 *
 * A *path* is a dot-delimited sequence of zero or more property names, such that "foo.bar" means "the property
 * 'bar' of the object at the property 'foo' of the root."  An empty path returns the object passed.
 *
 * ```js
 * var get = require("can-key");
 * console.log(get({a: {b: {c: "foo"}}}, "a.b.c")); // -> "foo"
 * console.log(get({a: {}}, "a.b.c")); // -> undefined
 * console.log(get([{a: {}}, {a: {b: "bar"}}], "a.b")); // -> "bar"
 *
 * var map = new Map();
 * map.set("first", {second: "third"});
 *
 * get(map, "first.second") //-> "third"
 * ```
 */
function get(obj, name) {
    // The parts of the name we are looking up
    // `['App','Models','Recipe']`
    var parts = canKey_1_2_1_utils.parts(name);

    var length = parts.length,
        current, i, container;

    if (!length) {
        return obj;
    }

    current = obj;

    // Walk current to the 2nd to last object or until there
    // is not a container.
    for (i = 0; i < length && canKey_1_2_1_utils.isContainer(current) && current !== null; i++) {
        container = current;
        current = canReflect_1_19_2_canReflect.getKeyValue( container, parts[i] );
    }

    return current;
}

var get_1 = get;

/**
 * @module {function} can-key/replace-with/replace-with
 * @parent can-key
 *
 * Replace the templated parts of a string with values from an object.
 *
 * @signature `replaceWith(str, data, replacer, remove)`
 *
 * ```js
 * import replaceWith from "can-key/replace-with/replace-with";
 *
 * replaceWith("foo_{bar}", {bar: "baz"}); // -> "foo_baz"
 * ```
 *
 * @param {String} str String with {curly brace} delimited property names.
 * @param {Object} data Object from which to read properties.
 * @param {function(String,*)} [replacer(key,value)] Function which returns string replacements.  Optional.
 *
 *   ```js
 *   replaceWith("foo_{bar}", {bar: "baz"}, (key, value) => {
 *     return value.toUpperCase();
 *   }); // -> "foo_BAZ"
 *   ```
 *
 *
 * @param {Boolean} shouldRemoveMatchedPaths Whether to remove properties
 * found in delimiters in `str` from `data`.
 * @return {String} the supplied string with delimited properties replaced with their values.
 *
 * @body
 *
 * ```js
 * var replaceWith = require("can-key/replace-with/replace-with");
 * var answer = replaceWith(
 *   '{.}{.}{.}{.}{.} Batman!',
 *   {},
 *   () => 'Na'
 * );
 * // => 'NaNaNaNaNa Batman!'
 * ```
 */
var replaceWith = function (str, data, replacer, shouldRemoveMatchedPaths) {
    return str.replace(canKey_1_2_1_utils.strReplacer, function (whole, path) {
        var value = get_1(data, path);
        if(shouldRemoveMatchedPaths) {
            _delete(data, path);
        }
        return replacer ? replacer(path, value) : value;
    });
};

var setValueSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.setValue");

/**
 * @module {function} can-key/set/set
 * @parent can-key
 * @description Set properties on deep/nested objects of different types: Object, Map, [can-reflect] types, etc.
 *
 * @signature `set(object, path, value)`
 * @param  {Object} object The object to use as the root for property-based navigation.
 * @param  {String} path A String of dot-separated keys, representing a path of properties.
 * @param  {*} value The new value to be set at the property path.
 * @return {*} The object passed to set (for chaining calls).
 *
 * @body
 *
 * A *path* is a dot-delimited sequence of one or more property names, such that "foo.bar" means "the property
 * 'bar' of the object at the property 'foo' of the root."
 *
 * ```js
 * import set from "can-key/set/set";
 *
 * const object = {a: {b: {c: "foo"}}};
 * set(object, "a.b.c", "bar");
 * // Now object.a.b.c === "bar"
 *
 * var map = new Map();
 * map.set("first", {second: "third"});
 *
 * set(map, "first.second", "3rd");
 * // Now map.first.second === "3rd"
 * ```
 *
 * > **Note:** an error will be thrown if one of the objects in the key path does not exist.
 */
function set$1(object, path, value) {
    var parts = canKey_1_2_1_utils.parts(path);

    var current = object;
    var length = parts.length;

    // Walk current until there is not a container
    for (var i = 0; i < length - 1; i++) {
        if (canKey_1_2_1_utils.isContainer(current)) {
            current = canReflect_1_19_2_canReflect.getKeyValue(current, parts[i]);
        } else {
            break;
        }
    }

    // Set the value
    if (current) {
        canReflect_1_19_2_canReflect.setKeyValue(current, parts[i], value);
    } else {
        throw new TypeError("Cannot set value at key path '" + path + "'");
    }

    return object;
}

var set_1 = set$1;

/**
 * @module {function} can-key/walk/walk
 * @parent can-key
 *
 * @signature `walk(obj, name, keyCallback(info) )`
 *
 * ```js
 * import walk from "can-key/walk/walk";
 *
 * var user = {name: {first: "Justin"}}
 * walk(user, "name.first", (keyInfo)=> {
 *   // Called 2 times.
 *   // first call:
 *   keyInfo //-> {parent: user, key: "name", value: user.name}
 *   // second call:
 *   keyInfo //-> {parent: user.name, key: "first", value: user.name.first}
 * })
 * ```
 *
 * @param {Object} obj An object to read key values from.
 * @param {String} name A string key name like "foo.bar".
 * @param {function(Object)} keyCallback(info) For every key value,
 * `keyCallback` will be called back with an `info` object containing:
 *
 * - `info.parent` - The object the property value is being read from.
 * - `info.key` - The key being read.
 * - `info.value` - The key's value.
 *
 * If `keyCallback` returns a value other than `undefined`, the next key value
 * will be read from that value.
 */
var walk = function walk(obj, name, keyCallback){

    // The parts of the name we are looking up
    // `['App','Models','Recipe']`
    var parts = canKey_1_2_1_utils.parts(name);

    var length = parts.length,
        current, i, container, part;


    if (!length) {
        return;
    }

    current = obj;

    // Walk current to the 2nd to last object or until there
    // is not a container.
    for (i = 0; i < length; i++) {
        container = current;
        part = parts[i];
        current = canKey_1_2_1_utils.isContainer(container) && canReflect_1_19_2_canReflect.getKeyValue( container, part );

        var result = keyCallback({
            parent:container,
            key: part,
            value: current
        }, i);
        if(result !== undefined) {
            current = result;
        }
    }
};

function deleteKeys(parentsAndKeys) {
    for(var i  = parentsAndKeys.length - 1; i >= 0; i--) {
        var parentAndKey = parentsAndKeys[i];
        delete  parentAndKey.parent[parentAndKey.key];
        if(canReflect_1_19_2_canReflect.size(parentAndKey.parent) !== 0) {
            return;
        }
    }
}
/**
 * @module {function} can-key/transform/transform
 * @parent can-key
 */
var transform = function(obj, transformer){
    var copy = canReflect_1_19_2_canReflect.serialize( obj);

    canReflect_1_19_2_canReflect.eachKey(transformer, function(writeKey, readKey){
        var readParts = canKey_1_2_1_utils.parts(readKey),
            writeParts = canKey_1_2_1_utils.parts(writeKey);

        // find the value
        var parentsAndKeys = [];
        walk(copy, readParts, function(info){
            parentsAndKeys.push(info);
        });
        var last = parentsAndKeys[parentsAndKeys.length - 1];
        var value = last.value;
        if(value !== undefined) {
            // write the value
            walk(copy, writeParts, function(info, i){
                if(i < writeParts.length - 1 && !info.value) {
                    return info.parent[info.key] = {};
                } else if(i === writeParts.length - 1){
                    info.parent[info.key] = value;
                }
            });
            // delete the keys on old
            deleteKeys(parentsAndKeys);

        }
    });
    return copy;
};

var canKey_1_2_1_canKey = canNamespace_1_0_0_canNamespace.key = {
    deleteKey: _delete,
    get: get_1,
    replaceWith: replaceWith,
    set: set_1,
    transform: transform,
    walk: walk
};

var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

function commonjsRequire () {
	throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
}

function createCommonjsModule(fn, module) {
	return module = { exports: {} }, fn(module, module.exports), module.exports;
}

var warnTimeout = 5000;
var logLevel = 0;

/**
 * @module {{}} can-log log
 * @parent can-js-utilities
 * @collection can-infrastructure
 * @hide
 *
 * Utilities for logging to the console.
 */

/**
 * @function can-log.warn warn
 * @parent can-log
 * @description
 *
 * Adds a warning message to the console.
 *
 * ```
 * var canLog = require("can-log");
 *
 * canLog.warn("something evil");
 * ```
 *
 * @signature `canLog.warn(msg)`
 * @param {String} msg the message to be logged.
 */
var warn = function() {
	var ll = this.logLevel;
	if (ll < 2) {
		if (typeof console !== "undefined" && console.warn) {
			this._logger("warn", Array.prototype.slice.call(arguments));
		} else if (typeof console !== "undefined" && console.log) {
			this._logger("log", Array.prototype.slice.call(arguments));
		}
	}
};

/**
 * @function can-log.log log
 * @parent can-log
 * @description
 * Adds a message to the console.
 * @hide
 *
 * ```
 * var canLog = require("can-log");
 *
 * canLog.log("hi");
 * ```
 *
 * @signature `canLog.log(msg)`
 * @param {String} msg the message
 */
var log = function() {
	var ll = this.logLevel;
	if (ll < 1) {
		if (typeof console !== "undefined" && console.log) {
			this._logger("log", Array.prototype.slice.call(arguments));
		}
	}
};

/**
 * @function can-log.error error
 * @parent can-log
 * @description
 * Adds an error message to the console.
 * @hide
 *
 * ```
 * var canLog = require("can-log");
 *
 * canLog.error(new Error("Oh no!"));
 * ```
 *
 * @signature `canLog.error(err)`
 * @param {String|Error} err The error to be logged.
 */
var error = function() {
	var ll = this.logLevel;
	if (ll < 1) {
		if (typeof console !== "undefined" && console.error) {
			this._logger("error", Array.prototype.slice.call(arguments));
		}
	}
};

var _logger = function (type, arr) {
	try {
		console[type].apply(console, arr);
	} catch(e) {
		console[type](arr);
	}
};

var canLog_1_0_2_canLog = {
	warnTimeout: warnTimeout,
	logLevel: logLevel,
	warn: warn,
	log: log,
	error: error,
	_logger: _logger
};

/**
 * @module {{}} can-log/dev dev
 * @parent can-log
 * @hide
 * 
 * Utilities for logging development-mode messages. Use this module for
 * anything that should be shown to the user during development but isn't
 * needed in production. In production these functions become noops.
 */
var dev = {
	warnTimeout: 5000,
	logLevel: 0,
	/**
	 * @function can-log/dev.stringify stringify
	 * @parent can-log
	 * @description
	 * @hide
	 *
	 * JSON stringifies a value, but unlike JSON, will output properties with
	 * a value of `undefined` (e.g. `{ "prop": undefined }`, not `{}`).
	 *
	 * ```
	 * var dev = require('can-log/dev');
	 * var query = { where: undefined };
	 * 
	 * dev.warn('No records found: ' + dev.stringify(query));
	 * ```
	 *
	 * @signature `dev.stringify(value)`
	 * @param {Any} value A value to stringify.
	 * @return {String} A stringified representation of the passed in value.
	 */
	stringify: function(value) {
		var flagUndefined = function flagUndefined(key, value) {
			return value === undefined ?
				 "/* void(undefined) */" : value;
		};
		
		return JSON.stringify(value, flagUndefined, "  ").replace(
			/"\/\* void\(undefined\) \*\/"/g, "undefined");
	},
	/**
	 * @function can-log/dev.warn warn
	 * @parent can-log
	 * @description
	 * @hide
	 *
	 * Adds a warning message to the console.
	 *
	 * ```
	 * var dev = require('can-log/dev');
	 * 
	 * dev.warn("something evil");
	 * ```
	 *
	 * @signature `dev.warn(msg)`
	 * @param {String} msg The warning message.
	 */
	warn: function() {
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			canLog_1_0_2_canLog.warn.apply(this, arguments);
		}
		//!steal-remove-end
	},
	/**
	 * @function can-log/dev.log log
	 * @parent can-log
	 * @description
	 * @hide
	 *
	 * Adds a message to the console.
	 *
	 * ```
	 * var dev = require('can-log/dev');
	 * 
	 * dev.log("hi");
	 * ```
	 *
	 * @signature `dev.log(msg)`
	 * @param {String} msg The message.
	 */
	log: function() {
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			canLog_1_0_2_canLog.log.apply(this, arguments);
		}
		//!steal-remove-end
	},
	/**
	 * @function can-log/dev.error error
	 * @parent can-log
	 * @description
	 * @hide
	 *
	 * Adds an error message to the console.
	 *
	 * ```
	 * var dev = require("can-log/dev");
	 * 
	 * dev.error(new Error("Oh no!"));
	 * ```
	 *
	 * @signature `dev.error(err)`
	 * @param {String|Error} err The error to be logged.
	 */
	error: function() {
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			canLog_1_0_2_canLog.error.apply(this, arguments);
		}
		//!steal-remove-end
	},
	_logger: canLog_1_0_2_canLog._logger
};

var canQueues_1_3_2_queueState = {
	lastTask: null
};

/**
 * @module {function} can-assign can-assign
 * @parent can-js-utilities
 * @collection can-infrastructure
 * @signature `assign(target, source)`
 * @package ./package.json
 *
 * A simplified version of [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign), which only accepts a single source argument.
 *
 * ```js
 * var assign = require("can-assign");
 *
 * var obj = {};
 *
 * assign(obj, {
 *   foo: "bar"
 * });
 *
 * console.log(obj.foo); // -> "bar"
 * ```
 *
 * @param {Object} target The destination object. This object's properties will be mutated based on the object provided as `source`.
 * @param {Object} source The source object whose own properties will be applied to `target`.
 *
 * @return {Object} Returns the `target` argument.
 */

var canAssign_1_3_3_canAssign = canNamespace_1_0_0_canNamespace.assign = function (d, s) {
	for (var prop in s) {
		var desc = Object.getOwnPropertyDescriptor(d,prop);
		if(!desc || desc.writable !== false){
			d[prop] = s[prop];
		}
	}
	return d;
};

function noOperation () {}

var Queue = function ( name, callbacks ) {
	this.callbacks = canAssign_1_3_3_canAssign( {
		onFirstTask: noOperation,
		// The default behavior is to clear the lastTask state.
		// This is overwritten by `can-queues.js`.
		onComplete: function () {
			canQueues_1_3_2_queueState.lastTask = null;
		}
	}, callbacks || {});
	this.name = name;
	this.index = 0;
	this.tasks = [];
	this._log = false;
};

Queue.prototype.constructor = Queue;

Queue.noop = noOperation;

Queue.prototype.enqueue = function ( fn, context, args, meta ) {
	var len = this.tasks.push({
		fn: fn,
		context: context,
		args: args,
		meta: meta || {}
	});
	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		this._logEnqueue( this.tasks[len - 1] );
	}
	//!steal-remove-end

	if ( len === 1 ) {
		this.callbacks.onFirstTask( this );
	}
};

Queue.prototype.flush = function () {
	while ( this.index < this.tasks.length ) {
		var task = this.tasks[this.index++];
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			this._logFlush( task );
		}

		//!steal-remove-end
		task.fn.apply( task.context, task.args );
	}
	this.index = 0;
	this.tasks = [];
	this.callbacks.onComplete( this );
};

Queue.prototype.log = function () {
	this._log = arguments.length ? arguments[0] : true;
};

//The following are removed in production.
//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	Queue.prototype._logEnqueue = function ( task ) {
		// For debugging, set the parentTask to the last
		// run task.
		task.meta.parentTask = canQueues_1_3_2_queueState.lastTask;
		// Also let the task know which stack it was run within.
		task.meta.stack = this;

		if ( this._log === true || this._log === "enqueue" ) {
			var log = task.meta.log ? task.meta.log.concat( task ) : [task.fn.name, task];
			dev.log.apply( dev, [this.name + " enqueuing:"].concat( log ));
		}
	};
	// `_logFlush` MUST be called by all queues prior to flushing in
	// development.
	Queue.prototype._logFlush = function ( task ) {
		if ( this._log === true || this._log === "flush" ) {
			var log = task.meta.log ? task.meta.log.concat( task ) : [task.fn.name, task];
			dev.log.apply( dev, [this.name + " running  :"].concat( log ));
		}
		// Update the state to mark this as the task that was run last.
		canQueues_1_3_2_queueState.lastTask = task;
	};
}
//!steal-remove-end

var canQueues_1_3_2_queue = Queue;

var PriorityQueue = function () {
	canQueues_1_3_2_queue.apply( this, arguments );
	// A map of a task's function to the task for that function.
	// This is so we can prevent duplicate functions from being enqueued
	// and so `flushQueuedTask` can find the task and run it.
	this.taskMap = new Map();
	// An "array-of-arrays"-ish data structure that stores
	// each task organized by its priority.  Each object in this list
	// looks like `{tasks: [...], index: 0}` where:
	// - `tasks` - the tasks for a particular priority.
	// - `index` - the index of the task waiting to be prioritized.
	this.taskContainersByPriority = [];

	// The index within `taskContainersByPriority` of the first `taskContainer`
	// which has tasks that have not been run.
	this.curPriorityIndex = Infinity;
	// The index within `taskContainersByPriority` of the last `taskContainer`
	// which has tasks that have not been run.
	this.curPriorityMax = 0;

	this.isFlushing = false;

	// Manage the number of tasks remaining to keep
	// this lookup fast.
	this.tasksRemaining = 0;
};
PriorityQueue.prototype = Object.create( canQueues_1_3_2_queue.prototype );
PriorityQueue.prototype.constructor = PriorityQueue;

PriorityQueue.prototype.enqueue = function ( fn, context, args, meta ) {
	// Only allow the enqueing of a given function once.
	if ( !this.taskMap.has( fn ) ) {

		this.tasksRemaining++;

		var isFirst = this.taskContainersByPriority.length === 0;

		var task = {
			fn: fn,
			context: context,
			args: args,
			meta: meta || {}
		};

		var taskContainer = this.getTaskContainerAndUpdateRange( task );
		taskContainer.tasks.push( task );
		this.taskMap.set( fn, task );

		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			this._logEnqueue( task );
		}
		//!steal-remove-end

		if ( isFirst ) {
			this.callbacks.onFirstTask( this );
		}
	}
};

// Given a task, updates the queue's cursors so that `flush`
// will be able to run the task.
PriorityQueue.prototype.getTaskContainerAndUpdateRange = function ( task ) {
	var priority = task.meta.priority || 0;

	if ( priority < this.curPriorityIndex ) {
		this.curPriorityIndex = priority;
	}

	if ( priority > this.curPriorityMax ) {
		this.curPriorityMax = priority;
	}

	var tcByPriority = this.taskContainersByPriority;
	var taskContainer = tcByPriority[priority];
	if ( !taskContainer ) {
		taskContainer = tcByPriority[priority] = {tasks: [], index: 0};
	}
	return taskContainer;
};

PriorityQueue.prototype.flush = function () {
	// Only allow one task to run at a time.
	if ( this.isFlushing ) {
		return;
	}
	this.isFlushing = true;
	while ( true ) {
		// If the first prioritized taskContainer with tasks remaining
		// is before the last prioritized taskContainer ...
		if ( this.curPriorityIndex <= this.curPriorityMax ) {
			var taskContainer = this.taskContainersByPriority[this.curPriorityIndex];

			// If that task container actually has tasks remaining ...
			if ( taskContainer && ( taskContainer.tasks.length > taskContainer.index ) ) {

				// Run the task.
				var task = taskContainer.tasks[taskContainer.index++];
				//!steal-remove-start
				if(process.env.NODE_ENV !== 'production') {
					this._logFlush( task );
				}
				//!steal-remove-end
				this.tasksRemaining--;
				this.taskMap["delete"]( task.fn );
				task.fn.apply( task.context, task.args );

			} else {
				// Otherwise, move to the next taskContainer.
				this.curPriorityIndex++;
			}
		} else {
			// Otherwise, reset the state for the next `.flush()`.
			this.taskMap = new Map();
			this.curPriorityIndex = Infinity;
			this.curPriorityMax = 0;
			this.taskContainersByPriority = [];
			this.isFlushing = false;
			this.callbacks.onComplete( this );
			return;
		}
	}
};

PriorityQueue.prototype.isEnqueued = function ( fn ) {
	return this.taskMap.has( fn );
};

PriorityQueue.prototype.flushQueuedTask = function ( fn ) {
	var task = this.dequeue(fn);
	if(task) {
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			this._logFlush( task );
		}
		//!steal-remove-end
		task.fn.apply( task.context, task.args );
	}
};
PriorityQueue.prototype.dequeue = function(fn){
	var task = this.taskMap.get( fn );
	if ( task ) {
		var priority = task.meta.priority || 0;
		var taskContainer = this.taskContainersByPriority[priority];
		var index = taskContainer.tasks.indexOf( task, taskContainer.index );

		if ( index >= 0 ) {
			taskContainer.tasks.splice( index, 1 );
			this.tasksRemaining--;
			this.taskMap["delete"]( task.fn );
			return task;
		} else {
			console.warn("Task", fn, "has already run");
		}
	}
};

PriorityQueue.prototype.tasksRemainingCount = function () {
	return this.tasksRemaining;
};

var canQueues_1_3_2_priorityQueue = PriorityQueue;

// This queue does not allow another task to run until this one is complete
var CompletionQueue = function () {
	canQueues_1_3_2_queue.apply( this, arguments );
	this.flushCount = 0;
};
CompletionQueue.prototype = Object.create( canQueues_1_3_2_queue.prototype );
CompletionQueue.prototype.constructor = CompletionQueue;

CompletionQueue.prototype.flush = function () {
	if ( this.flushCount === 0 ) {
		this.flushCount ++;
		while ( this.index < this.tasks.length ) {
			var task = this.tasks[this.index++];
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				this._logFlush( task );
			}
			//!steal-remove-end
			task.fn.apply( task.context, task.args );
		}
		this.index = 0;
		this.tasks = [];
		this.flushCount--;
		this.callbacks.onComplete( this );
	}
};

var canQueues_1_3_2_completionQueue = CompletionQueue;

var canQueues_1_3_2_sortedIndexBy = function(compare, array, value) {
	if (!array || !array.length) {
		return undefined;
	}
	// check the start and the end
	if (compare(value, array[0]) === -1) {
		return 0;
	} else if (compare(value, array[array.length - 1]) === 1) {
		return array.length;
	}
	var low = 0,
		high = array.length;

	// From lodash lodash 4.6.1 <https://lodash.com/>
	// Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
	while (low < high) {
		var mid = (low + high) >>> 1,
			item = array[mid],
			computed = compare(value, item);
		if (computed === -1) {
			high = mid;
		} else {
			low = mid + 1;
		}
	}
	return high;
	// bisect by calling sortFunc
};

// Taken from jQuery
var hasDuplicate,
	sortInput,
	sortStable = true,
	indexOf = Array.prototype.indexOf;

function sortOrder( a, b ) {

	// Flag for duplicate removal
	if ( a === b ) {
		hasDuplicate = true;
		return 0;
	}

	// Sort on method existence if only one input has compareDocumentPosition
	var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
	if ( compare ) {
		return compare;
	}

	// Calculate position if both inputs belong to the same document
	compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
		a.compareDocumentPosition( b ) :

		// Otherwise we know they are disconnected
		1;

	// Disconnected nodes
	if ( compare & 1 ) {

		// Choose the first element that is related to our preferred document
		if ( a === document || a.ownerDocument === document &&
			document.documentElement.contains(a) ) {
			return -1;
		}
		if ( b === document || b.ownerDocument === document &&
			document.documentElement.contains(b) ) {
			return 1;
		}

		// Maintain original order
		return sortInput ?
			( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :
			0;
	}

	return compare & 4 ? -1 : 1;
}

function uniqueSort( results ) {
	var elem,
		duplicates = [],
		j = 0,
		i = 0;

	hasDuplicate = false;
	sortInput = !sortStable && results.slice( 0 );
	results.sort( sortOrder );

	if ( hasDuplicate ) {
		while ( ( elem = results[ i++ ] ) ) {
			if ( elem === results[ i ] ) {
				j = duplicates.push( i );
			}
		}
		while ( j-- ) {
			results.splice( duplicates[ j ], 1 );
		}
	}

	// Clear input after sorting to release objects
	// See https://github.com/jquery/sizzle/pull/225
	sortInput = null;

	return results;
}

var canQueues_1_3_2_elementSort = {
	uniqueSort: uniqueSort,
	sortOrder: sortOrder
};

var canElementSymbol = canSymbol_1_7_0_canSymbol.for("can.element");

// TODO: call sortable queue and take how it should be sorted ...
function sortTasks(taskA, taskB){
	// taskA - in the document?
	// taskA - given a number?
	//
	return canQueues_1_3_2_elementSort.sortOrder(taskA.meta.element, taskB.meta.element);
}

var DomOrderQueue = function () {
	canQueues_1_3_2_queue.apply( this, arguments );
	// A map of a task's function to the task for that function.
	// This is so we can prevent duplicate functions from being enqueued
	// and so `flushQueuedTask` can find the task and run it.
	this.taskMap = new Map();

	this.unsortable = [];
	this.isFlushing = false;
};
DomOrderQueue.prototype = Object.create( canQueues_1_3_2_queue.prototype );
DomOrderQueue.prototype.constructor = DomOrderQueue;

DomOrderQueue.prototype.enqueue = function ( fn, context, args, meta ) {
	var task;
	// Only allow the enqueing of a given function once.
	if ( !this.taskMap.has( fn ) ) {

		if(!meta) {
			meta = {};
		}
		if(!meta.element) {
			meta.element = fn[canElementSymbol];
		}

		task = {
			fn: fn,
			context: context,
			args: args,
			meta: meta
		};

		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			if( !meta.element ) {
				throw new Error("DomOrderQueue tasks must be created with a meta.element.");
			}
		}
		//!steal-remove-end

		this.taskMap.set( fn, task );

		var index = canQueues_1_3_2_sortedIndexBy(sortTasks, this.tasks, task);

		this.tasks.splice(index, 0, task);

		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			this._logEnqueue( task );
		}
		//!steal-remove-end

		if ( this.tasks.length === 1 ) {
			this.callbacks.onFirstTask( this );
		}
	} else {
		// update the task with the new data
		// TODO: ideally this would key off the mutation instead of the function.
		// We could make it key off the element and function,  not just function.
		task = this.taskMap.get( fn );
		task.context = context;
		task.args = args;

		if(!meta) {
			meta = {};
		}

		if(!meta.element) {
			meta.element = fn[canElementSymbol];
		}

		task.meta = meta;

		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			this._logEnqueue( task );
		}
		//!steal-remove-end
	}
};


DomOrderQueue.prototype.flush = function () {
	// Only allow one task to run at a time.
	if ( this.isFlushing ) {
		return;
	}
	this.isFlushing = true;

	while ( this.tasks.length ) {
		var task = this.tasks.shift();
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			this._logFlush( task );
		}
		//!steal-remove-end
		this.taskMap["delete"]( task.fn );
		task.fn.apply( task.context, task.args );
	}
	this.isFlushing = false;
	this.callbacks.onComplete( this );
};

DomOrderQueue.prototype.isEnqueued = function ( fn ) {
	return this.taskMap.has( fn );
};

DomOrderQueue.prototype.flushQueuedTask = function ( fn ) {
	var task = this.dequeue(fn);
	if(task) {
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			this._logFlush( task );
		}
		//!steal-remove-end
		task.fn.apply( task.context, task.args );
	}
};
DomOrderQueue.prototype.dequeue = function(fn){
	var task = this.taskMap.get( fn );
	if ( task ) {

		var index = this.tasks.indexOf(task);

		if ( index >= 0 ) {
			this.tasks.splice( index, 1 );
			this.taskMap["delete"]( task.fn );
			return task;
		} else {
			console.warn("Task", fn, "has already run");
		}
	}
};

DomOrderQueue.prototype.tasksRemainingCount = function () {
	return this.tasks.length;
};

var canQueues_1_3_2_domOrderQueue = DomOrderQueue;

var canQueues_1_3_2_canQueues = createCommonjsModule(function (module) {








// How many `batch.start` - `batch.stop` calls have been made.
var batchStartCounter = 0;
// If a task was added since the last flush caused by `batch.stop`.
var addedTask = false;

// Legacy values for the old batchNum.
var batchNum = 0;
var batchData;

// Used by `.enqueueByQueue` to know the property names that might be passed.
var queueNames = ["notify", "derive", "domUI", "dom","mutate"];
// Create all the queues so that when one is complete,
// the next queue is flushed.
var NOTIFY_QUEUE,
	DERIVE_QUEUE,
	DOM_UI_QUEUE,
	DOM_QUEUE,
	MUTATE_QUEUE;

// This is for immediate notification. This is where we teardown (remove childNodes)
// immediately.
NOTIFY_QUEUE = new canQueues_1_3_2_queue( "NOTIFY", {
	onComplete: function () {
		DERIVE_QUEUE.flush();
	},
	onFirstTask: function () {
		// Flush right away if we aren't in a batch.
		if ( !batchStartCounter ) {
			NOTIFY_QUEUE.flush();
		} else {
			addedTask = true;
		}
	}
});

// For observations not connected to the DOM
DERIVE_QUEUE = new canQueues_1_3_2_priorityQueue( "DERIVE", {
	onComplete: function () {
		DOM_QUEUE.flush();
	},
	onFirstTask: function () {
		addedTask = true;
	}
});

// DOM_DERIVE comes next so that any prior derives have a chance
// to settle before the derives that actually affect the DOM
// are re-caculated.
// See the `Child bindings are called before the parent` can-stache test.
// All stache-related observables should update in DOM order.

// Observations that are given an element update their value here.
DOM_QUEUE = new canQueues_1_3_2_domOrderQueue( "DOM   " ,{
	onComplete: function () {
		DOM_UI_QUEUE.flush();
	},
	onFirstTask: function () {
		addedTask = true;
	}
});

// The old DOM_UI queue ... we should seek to remove this.
DOM_UI_QUEUE = new canQueues_1_3_2_completionQueue( "DOM_UI", {
	onComplete: function () {
		MUTATE_QUEUE.flush();
	},
	onFirstTask: function () {
		addedTask = true;
	}
});

// Update
MUTATE_QUEUE = new canQueues_1_3_2_queue( "MUTATE", {
	onComplete: function () {
		canQueues_1_3_2_queueState.lastTask = null;
	},
	onFirstTask: function () {
		addedTask = true;
	}
});

var queues = {
	Queue: canQueues_1_3_2_queue,
	PriorityQueue: canQueues_1_3_2_priorityQueue,
	CompletionQueue: canQueues_1_3_2_completionQueue,
	DomOrderQueue: canQueues_1_3_2_domOrderQueue,
	notifyQueue: NOTIFY_QUEUE,
	deriveQueue: DERIVE_QUEUE,
	domQueue: DOM_QUEUE,
	domUIQueue: DOM_UI_QUEUE,
	mutateQueue: MUTATE_QUEUE,
	batch: {
		start: function () {
			batchStartCounter++;
			if ( batchStartCounter === 1 ) {
				batchNum++;
				batchData = {number: batchNum};
			}
		},
		stop: function () {
			batchStartCounter--;
			if ( batchStartCounter === 0 ) {
				if ( addedTask ) {
					addedTask = false;
					NOTIFY_QUEUE.flush();
				}
			}
		},
		// Legacy method to return if we are between start and stop calls.
		isCollecting: function () {
			return batchStartCounter > 0;
		},
		// Legacy method provide a number for each batch.
		number: function () {
			return batchNum;
		},
		// Legacy method to provide batch information.
		data: function () {
			return batchData;
		}
	},
	runAsTask: function(fn, reasonLog){
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			return function(){
				canQueues_1_3_2_queueState.lastTask = {
					fn: fn,
					context: this,
					args: arguments,
					meta: {
						reasonLog: typeof reasonLog === "function" ? reasonLog.apply(this, arguments): reasonLog,
						parentTask: canQueues_1_3_2_queueState.lastTask,
						stack: {name: "RUN_AS"}
					}
				};
				var ret = fn.apply(this, arguments);
				canQueues_1_3_2_queueState.lastTask = canQueues_1_3_2_queueState.lastTask && canQueues_1_3_2_queueState.lastTask.meta.parentTask;
				return ret;
			};
		}
		//!steal-remove-end
		return fn;
	},
	enqueueByQueue: function enqueueByQueue ( fnByQueue, context, args, makeMeta, reasonLog ) {
		if ( fnByQueue ) {
			queues.batch.start();
			// For each queue, check if there are tasks for it.
			queueNames.forEach( function ( queueName ) {
				var name = queueName + "Queue";
				var QUEUE = queues[name];
				var tasks = fnByQueue[queueName];
				if ( tasks !== undefined ) {
					// For each task function, setup the meta and enqueue it.
					tasks.forEach( function ( fn ) {
						var meta = makeMeta != null ? makeMeta( fn, context, args ) : {};
						meta.reasonLog = reasonLog;
						QUEUE.enqueue( fn, context, args, meta );
					});
				}
			});
			queues.batch.stop();
		}
	},
	lastTask: function(){
		return canQueues_1_3_2_queueState.lastTask;
	},
	// Currently an internal method that provides the task stack.
	// Returns an array with the first task as the first item.
	stack: function (task) {
		var current = task || canQueues_1_3_2_queueState.lastTask;
		var stack = [];
		while ( current ) {
			stack.unshift( current );
			// Queue.prototype._logEnqueue ensures
			// that the `parentTask` is always set.
			current = current.meta.parentTask;
		}
		return stack;
	},
	logStack: function (task) {
		var stack = this.stack(task);
		stack.forEach( function ( task, i ) {
			var meta = task.meta;
			if( i === 0 && meta && meta.reasonLog) {
				dev.log.apply( dev, meta.reasonLog);
			}
			var log = meta && meta.log ? meta.log : [task.fn.name, task];
			dev.log.apply( dev, [task.meta.stack.name + " ran task:"].concat( log ));
		});
	},
	// A method that is not used.  It should return the number of tasks
	// remaining, but doesn't seem to actually work.
	taskCount: function () {
		return NOTIFY_QUEUE.tasks.length + DERIVE_QUEUE.tasks.length + DOM_UI_QUEUE.tasks.length + MUTATE_QUEUE.tasks.length;
	},
	// A shortcut for flushign the notify queue.  `batch.start` and `batch.stop` should be
	// used instead.
	flush: function () {
		NOTIFY_QUEUE.flush();
	},
	log: function () {
		NOTIFY_QUEUE.log.apply( NOTIFY_QUEUE, arguments );
		DERIVE_QUEUE.log.apply( DERIVE_QUEUE, arguments );
		DOM_UI_QUEUE.log.apply( DOM_UI_QUEUE, arguments );
		DOM_QUEUE.log.apply( DOM_QUEUE, arguments );
		MUTATE_QUEUE.log.apply( MUTATE_QUEUE, arguments );
	}
};

if ( canNamespace_1_0_0_canNamespace.queues ) {
	throw new Error( "You can't have two versions of can-queues, check your dependencies" );
} else {
	module.exports = canNamespace_1_0_0_canNamespace.queues = queues;
}
});

var canObservationRecorder_1_3_1_canObservationRecorder = createCommonjsModule(function (module) {



// Contains stack of observation records created by pushing with `.start`
// and popping with `.stop()`.
// The top of the stack is the "target" observation record - the record that calls
// to `ObservationRecorder.add` get added to.
var stack = [];

var addParentSymbol = canSymbol_1_7_0_canSymbol.for("can.addParent"),
	getValueSymbol = canSymbol_1_7_0_canSymbol.for("can.getValue");

var ObservationRecorder = {
	stack: stack,
	start: function(name) {
		var deps = {
			keyDependencies: new Map(),
			valueDependencies: new Set(),
			childDependencies: new Set(),

			// `traps` and `ignore` are here only for performance
			// reasons. They work with `ObservationRecorder.ignore` and `ObservationRecorder.trap`.
			traps: null,
			ignore: 0,
			name: name
		};

		stack.push(deps);

		return deps;
	},
	stop: function() {
		return stack.pop();
	},

	add: function(obj, event) {
		var top = stack[stack.length - 1];
		if (top && top.ignore === 0) {

			if (top.traps) {
				top.traps.push([obj, event]);
			} else {
				// Use `=== undefined` instead of `arguments.length` for performance.
				if (event === undefined) {
					top.valueDependencies.add(obj);
				} else {
					var eventSet = top.keyDependencies.get(obj);
					if (!eventSet) {
						eventSet = new Set();
						top.keyDependencies.set(obj, eventSet);
					}
					eventSet.add(event);
				}
			}
		}
	},

	addMany: function(observes) {
		var top = stack[stack.length - 1];
		if (top) {
			if (top.traps) {
				top.traps.push.apply(top.traps, observes);
			} else {
				for (var i = 0, len = observes.length; i < len; i++) {
					this.add(observes[i][0], observes[i][1]);
				}
			}
		}
	},
	created: function(obs) {
		var top = stack[stack.length - 1];
		if (top) {
			top.childDependencies.add(obs);
			if (obs[addParentSymbol]) {
				obs[addParentSymbol](top);
			}
		}
	},
	ignore: function(fn) {
		return function() {
			if (stack.length) {
				var top = stack[stack.length - 1];
				top.ignore++;
				var res = fn.apply(this, arguments);
				top.ignore--;
				return res;
			} else {
				return fn.apply(this, arguments);
			}
		};
	},
	peekValue: function(value) {
		if(!value || !value[getValueSymbol]) {
			return value;
		}
		if (stack.length) {
			var top = stack[stack.length - 1];
			top.ignore++;
			var res = value[getValueSymbol]();
			top.ignore--;
			return res;
		} else {
			return value[getValueSymbol]();
		}
	},
	isRecording: function() {
		var len = stack.length;
		var last = len && stack[len - 1];
		return last && (last.ignore === 0) && last;
	},
	// `can-observation` uses this to do diffs more easily.
	makeDependenciesRecord: function(name) {
		return {
			traps: null,
			keyDependencies: new Map(),
			valueDependencies: new Set(),
			//childDependencies: new Set(),
			ignore: 0,
			name: name
		};
	},
	// The following are legacy methods we should do away with.
	makeDependenciesRecorder: function() {
		return ObservationRecorder.makeDependenciesRecord();
	},
	// Traps should be replace by calling `.start()` and `.stop()`.
	// To do this, we'd need a method that accepts a dependency record.
	trap: function() {
		if (stack.length) {
			var top = stack[stack.length - 1];
			var oldTraps = top.traps;
			var traps = top.traps = [];
			return function() {
				top.traps = oldTraps;
				return traps;
			};
		} else {
			return function() {
				return [];
			};
		}
	},
	trapsCount: function() {
		if (stack.length) {
			var top = stack[stack.length - 1];
			return top.traps.length;
		} else {
			return 0;
		}
	}
};

if (canNamespace_1_0_0_canNamespace.ObservationRecorder) {
	throw new Error("You can't have two versions of can-observation-recorder, check your dependencies");
} else {
	module.exports = canNamespace_1_0_0_canNamespace.ObservationRecorder = ObservationRecorder;
}
});

// ## Helpers
// The following implement helper functions useful to `can-key-tree`'s main methods.

// ### isBuiltInPrototype
// Returns if `obj` is the prototype of a built-in JS type like `Map`.
// Built in types' `toString` returns `[object TYPENAME]`.
function isBuiltInPrototype ( obj ) {
	if ( obj === Object.prototype ) {
		return true;
	}
	var protoString = Object.prototype.toString.call( obj );
	var isNotObjObj = protoString !== '[object Object]';
	var isObjSomething = protoString.indexOf( '[object ' ) !== -1;
	return isNotObjObj && isObjSomething;
}

// ### getDeepSize
// Recursively returns the number of leaf values below `root` node.
function getDeepSize ( root, level ) {
	if ( level === 0 ) {
		return canReflect_1_19_2_canReflect.size( root );
	} else if ( canReflect_1_19_2_canReflect.size( root ) === 0 ) {
		return 0;
	} else {
		var count = 0;
		canReflect_1_19_2_canReflect.each( root, function ( value ) {
			count += getDeepSize( value, level - 1 );
		});
		return count;
	}
}

// ### getDeep
// Adds all leaf values under `node` to `items`.
// `depth` is how deep `node` is in the tree.
// `maxDepth` is the total depth of the tree structure.
function getDeep ( node, items, depth, maxDepth ) {
	if ( !node ) {
		return;
	}
	if ( maxDepth === depth ) {
		if ( canReflect_1_19_2_canReflect.isMoreListLikeThanMapLike( node ) ) {
			canReflect_1_19_2_canReflect.addValues( items, canReflect_1_19_2_canReflect.toArray( node ) );
		} else {
			throw new Error( "can-key-tree: Map-type leaf containers are not supported yet." );
		}
	} else {
		canReflect_1_19_2_canReflect.each( node, function ( value ) {
			getDeep( value, items, depth + 1, maxDepth );
		});
	}
}

// ### clearDeep
// Recursively removes value from all child nodes of `node`.
function clearDeep ( node, keys, maxDepth, deleteHandler ) {
	if ( maxDepth === keys.length ) {
		if ( canReflect_1_19_2_canReflect.isMoreListLikeThanMapLike( node ) ) {
			var valuesToRemove = canReflect_1_19_2_canReflect.toArray( node );
			if(deleteHandler) {
				valuesToRemove.forEach(function(value){
					deleteHandler.apply(null, keys.concat(value));
				});
			}
			canReflect_1_19_2_canReflect.removeValues( node, valuesToRemove );
		} else {
			throw new Error( "can-key-tree: Map-type leaf containers are not supported yet." );
		}
	} else {
		canReflect_1_19_2_canReflect.each( node, function ( value, key ) {
			clearDeep( value, keys.concat(key), maxDepth, deleteHandler );
			canReflect_1_19_2_canReflect.deleteKeyValue( node, key );
		});
	}
}

// ## KeyTree
// Creates an instance of the KeyTree.
var KeyTree = function ( treeStructure, callbacks ) {
	var FirstConstructor = treeStructure[0];
	if ( canReflect_1_19_2_canReflect.isConstructorLike( FirstConstructor ) ) {
		this.root = new FirstConstructor();
	} else {
		this.root = FirstConstructor;
	}
	this.callbacks = callbacks || {};
	this.treeStructure = treeStructure;
	// An extra bit of state held for performance
	this.empty = true;
};

// ## Methods
canReflect_1_19_2_canReflect.assign(KeyTree.prototype,{
    // ### Add
    add: function ( keys ) {
    	if ( keys.length > this.treeStructure.length ) {
    		throw new Error( "can-key-tree: Can not add path deeper than tree." );
    	}
        // The place we will add the final leaf value.
    	var place = this.root;

        // Record if the root was empty so we know to call `onFirst`.
    	var rootWasEmpty = this.empty === true;

        // For each key, try to get the corresponding childNode.
        for ( var i = 0; i < keys.length - 1; i++ ) {
    		var key = keys[i];
    		var childNode = canReflect_1_19_2_canReflect.getKeyValue( place, key );
    		if ( !childNode ) {
                // If there is no childNode, create it and add it to the parent node.
    			var Constructor = this.treeStructure[i + 1];
    			if ( isBuiltInPrototype( Constructor.prototype ) ) {
    				childNode = new Constructor();
    			} else {
    				childNode = new Constructor( key );
    			}
    			canReflect_1_19_2_canReflect.setKeyValue( place, key, childNode );
    		}
    		place = childNode;
    	}

        // Add the final leaf value in the tree.
    	if ( canReflect_1_19_2_canReflect.isMoreListLikeThanMapLike( place ) ) {
    		canReflect_1_19_2_canReflect.addValues( place, [keys[keys.length - 1]] );
    	} else {
    		throw new Error( "can-key-tree: Map types are not supported yet." );
    	}

        // Callback `onFirst` if appropriate.
    	if ( rootWasEmpty ) {
			this.empty = false;
			if(this.callbacks.onFirst) {
				this.callbacks.onFirst.call( this );
			}

    	}

    	return this;
    },
    // ### getNode
    getNode: function ( keys ) {
        var node = this.root;
        // For each key, try to read the child node.
        // If a child is not found, return `undefined`.
        for ( var i = 0; i < keys.length; i++ ) {
            var key = keys[i];
            node = canReflect_1_19_2_canReflect.getKeyValue( node, key );
            if ( !node ) {
                return;
            }
        }
        return node;
    },
    // ### get
    get: function ( keys ) {
        // Get the node specified by keys.
    	var node = this.getNode( keys );

        // If it's a leaf, return it.
    	if ( this.treeStructure.length === keys.length ) {
    		return node;
    	} else {
    		// Otherwise, create a container for leaf values and
            // recursively walk the node's children.
    		var Type = this.treeStructure[this.treeStructure.length - 1];
    		var items = new Type();
    		getDeep( node, items, keys.length, this.treeStructure.length - 1 );
    		return items;
    	}
    },
    // ### delete
    delete: function ( keys, deleteHandler ) {

        // `parentNode` will eventually be the parent nodde of the
        // node specified by keys.
        var parentNode = this.root,
            // The nodes traversed to the node specified by `keys`.
            path = [this.root],
            lastKey = keys[keys.length - 1];

        // Set parentNode to the node specified by keys
        // and record the nodes in `path`.
        for ( var i = 0; i < keys.length - 1; i++ ) {
    		var key = keys[i];
    		var childNode = canReflect_1_19_2_canReflect.getKeyValue( parentNode, key );
    		if ( childNode === undefined ) {
    			return false;
    		} else {
    			path.push( childNode );
    		}
    		parentNode = childNode;
    	}


        // Depending on which keys were specified and the content of the
        // key, do various cleanups ...
        if ( !keys.length ) {
            // If there are no keys, recursively clear the entire tree.
    		clearDeep( parentNode, [], this.treeStructure.length - 1, deleteHandler );
    	}
        else if ( keys.length === this.treeStructure.length ) {
            // If removing a leaf, remove that value.
    		if ( canReflect_1_19_2_canReflect.isMoreListLikeThanMapLike( parentNode ) ) {
				if(deleteHandler) {
					deleteHandler.apply(null, keys.concat(lastKey));
				}
    			canReflect_1_19_2_canReflect.removeValues( parentNode, [lastKey] );
    		} else {
    			throw new Error( "can-key-tree: Map types are not supported yet." );
    		}
    	}
        else {
            // If removing a node 'within' the tree, recursively clear
            // that node and then delete the key from parent to node.
            var nodeToRemove = canReflect_1_19_2_canReflect.getKeyValue( parentNode, lastKey );
    		if ( nodeToRemove !== undefined ) {
    			clearDeep( nodeToRemove, keys, this.treeStructure.length - 1, deleteHandler );
    			canReflect_1_19_2_canReflect.deleteKeyValue( parentNode, lastKey );
    		} else {
    			return false;
    		}
    	}

        // After deleting the node, check if its parent is empty and
        // recursively prune parent nodes that are now empty.
    	for ( i = path.length - 2; i >= 0; i-- ) {
    		if ( canReflect_1_19_2_canReflect.size( parentNode ) === 0 ) {
    			parentNode = path[i];
    			canReflect_1_19_2_canReflect.deleteKeyValue( parentNode, keys[i] );
    		} else {
    			break;
    		}
    	}
        // Call `onEmpty` if the tree is now empty.
    	if (  canReflect_1_19_2_canReflect.size( this.root ) === 0 ) {
			this.empty = true;
			if(this.callbacks.onEmpty) {
				this.callbacks.onEmpty.call( this );
			}
    	}
    	return true;
    },
    // ### size
    // Recursively count the number of leaf values.
    size: function () {
    	return getDeepSize( this.root, this.treeStructure.length - 1 );
    },
	isEmpty: function(){
		return this.empty;
	}
});

var canKeyTree_1_2_2_canKeyTree = KeyTree;

/**
 * @module {function} can-define-lazy-value
 * @parent can-js-utilities
 * @collection can-infrastructure
 * @package ./package.json
 * @signature `defineLazyValue(obj, prop, fn, writable)`
 *
 * Use Object.defineProperty to define properties whose values will be created lazily when they are first read.
 *
 * ```js
 * var _id = 1;
 * function getId() {
 *     return _id++;
 * }
 *
 * function MyObj(name) {
 *     this.name = name;
 * }
 *
 * defineLazyValue(MyObj.prototype, 'id', getId);
 *
 * var obj1 = new MyObj('obj1');
 * var obj2 = new MyObj('obj2');
 *
 * console.log( obj2 ); // -> { name: "obj2" }
 * console.log( obj1 ); // -> { name: "obj1" }
 *
 * // the first `id` read will get id `1`
 * console( obj2.id ); // -> 1
 * console( obj1.id ); // -> 2
 *
 * console.log( obj2 ); // -> { name: "obj2", id: 1 }
 * console.log( obj1 ); // -> { name: "obj1", id: 2 }
 *
 * ```
 *
 * @param {Object} object The object to add the property to.
 * @param {String} prop   The name of the property.
 * @param {Function} fn   A function to get the value the property should be set to.
 * @param {boolean} writable   Whether the field should be writable (false by default).
 */
var canDefineLazyValue_1_1_1_defineLazyValue = function defineLazyValue(obj, prop, initializer, writable) {
	Object.defineProperty(obj, prop, {
		configurable: true,
		get: function() {
			// make the property writable
			Object.defineProperty(this, prop, {
				value: undefined,
				writable: true
			});

			// get the value from the initializer function
			var value = initializer.call(this, obj, prop);

			// redefine the property to the value property
			// and reset the writable flag
			Object.defineProperty(this, prop, {
				value: value,
				writable: !!writable
			});

			// return the value
			return value;
		},
		set: function(value){
			Object.defineProperty(this, prop, {
				value: value,
				writable: !!writable
			});

			return value;
		}
	});
};

var mergeValueDependencies = function mergeValueDependencies(obj, source) {
	var sourceValueDeps = source.valueDependencies;

	if (sourceValueDeps) {
		var destValueDeps = obj.valueDependencies;

		// make sure there is a valueDependencies Set
		// in the [obj] dependency record
		if (!destValueDeps) {
			destValueDeps = new Set();
			obj.valueDependencies = destValueDeps;
		}

		canReflect_1_19_2_canReflect.eachIndex(sourceValueDeps, function(dep) {
			destValueDeps.add(dep);
		});
	}
};

var mergeKeyDependencies = function mergeKeyDependencies(obj, source) {
	var sourcekeyDeps = source.keyDependencies;

	if (sourcekeyDeps) {
		var destKeyDeps = obj.keyDependencies;

		// make sure there is a keyDependencies Map
		// in the [obj] dependency record
		if (!destKeyDeps) {
			destKeyDeps = new Map();
			obj.keyDependencies = destKeyDeps;
		}

		canReflect_1_19_2_canReflect.eachKey(sourcekeyDeps, function(keys, obj) {
			var entry = destKeyDeps.get(obj);

			if (!entry) {
				entry = new Set();
				destKeyDeps.set(obj, entry);
			}

			canReflect_1_19_2_canReflect.eachIndex(keys, function(key) {
				entry.add(key);
			});
		});
	}
};

// Merges the key and value dependencies of the source object into the
// destination object
var merge = function mergeDependencyRecords(object, source) {
	mergeKeyDependencies(object, source);
	mergeValueDependencies(object, source);
	return object;
};

var properties = {
	/**
	 * @function can-event-queue/value/value.on on
	 * @parent can-event-queue/value/value
	 *
	 * @description Listen to changes in the observable's value.
	 *
	 * @signature `.on( handler[, queue='mutate'] )`
	 *
	 * This adds an event handler in the observable's [can-event-queue/value/value.handlers]
	 * tree. If this is the first handler, the observable's [can-event-queue/value/value.onBound] method is called.
	 *
	 * ```js
	 * observable.on(function(newVal){ ... });
	 * observable.on(function(newVal){ ... }, "notify");
	 * ```
	 *
	 * @param {function(*)} handler(newValue,oldValue) A handler that will be called with the new value of the
	 * observable and optionally the old value of the observable.
	 * @param {String} [queue] The [can-queues] queue this event handler should be bound to.  By default the handler will
	 * be called within the `mutate` queue.
	 */
	on: function(handler, queue) {
		this.handlers.add([queue || "mutate", handler]);
	},
	/**
	 * @function can-event-queue/value/value.off off
	 * @parent can-event-queue/value/value
	 *
	 * @description Stop listening to changes in the observable's value.
	 *
	 * @signature `.off( [handler [, queue='mutate']] )`
	 *
	 * Removes one or more event handler in the observable's [can-event-queue/value/value.handlers]
	 * tree. If the las handler is removed, the observable's [can-event-queue/value/value.onUnbound] method is called.
	 *
	 * ```js
	 * observable.off(function(newVal){ ... });
	 * observable.off(function(newVal){ ... }, "notify");
	 * observable.off();
	 * observable.off(undefined, "mutate");
	 * ```
	 *
	 * @param {function(*)} handler(newValue,oldValue) The handler to be removed.  If no handler is provided and no
	 * `queue` is provided, all handlers will be removed.
	 * @param {String} [queue] The [can-queues] queue this event handler should be removed from.
	 *
	 *  If a `handler` is
	 *  provided and no `queue` is provided, the `queue` will default to `"mutate"`.
	 *
	 *   If a `handler` is not provided, but a `queue` is provided, all handlers for the provided queue will be
	 *   removed.
	 */
	off: function(handler, queueName) {
		if (handler === undefined) {
			if (queueName === undefined) {
				this.handlers.delete([]);
			} else {
				this.handlers.delete([queueName]);
			}
		} else {
			this.handlers.delete([queueName || "mutate", handler]);
		}
	}
};

var symbols = {
	/**
	 * @function can-event-queue/value/value.can.onValue @can.onValue
	 * @parent can-event-queue/value/value
	 *
	 * @description Listen to changes in this observable value.
	 *
	 * This is an alias for [can-event-queue/value/value.on].  It satisfies [can-reflect].[can-reflect/observe.onValue].
	 */
	"can.onValue": properties.on,
	/**
	 * @function can-event-queue/value/value.can.offValue @can.offValue
	 * @parent can-event-queue/value/value
	 *
	 * @description Stop listening to changes in this observable value.
	 *
	 * This is an alias for [can-event-queue/value/value.off].  It satisfies [can-reflect].[can-reflect/observe.offValue].
	 */
	"can.offValue": properties.off,
	/**
	 * @function can-event-queue/value/value.can.dispatch @can.dispatch
	 * @parent can-event-queue/value/value
	 *
	 * @description Dispatch all event handlers within their appropriate queues.
	 *
	 * @signature `@can.dispatch(newValue, oldValue)`
	 *
	 * This is a helper method that will dispatch all [can-event-queue/value/value.handlers] within
	 * their appropriate [can-queues] queue.
	 *
	 * Furthermore, it will make sure the handlers include useful meta data for debugging.
	 *
	 * ```js
	 * var observable = mixinValueBindings({});
	 * observable[canSymbol.for("can.dispatch")]( 2, 1 );
	 * ```
	 *
	 * @param {Any} newValue The new value of the observable.
	 * @param {Any} oldValue The old value of the observable.
	 */
	"can.dispatch": function(value, old) {
		var queuesArgs = [];
		queuesArgs = [
			this.handlers.getNode([]),
			this,
			[value, old]
		];

		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			queuesArgs = [
				this.handlers.getNode([]),
				this,
				[value, old]
				/* jshint laxcomma: true */
				, null
				, [canReflect_1_19_2_canReflect.getName(this), "changed to", value, "from", old]
				/* jshint laxcomma: false */
			];
		}
		//!steal-remove-end
		canQueues_1_3_2_canQueues.enqueueByQueue.apply(canQueues_1_3_2_canQueues, queuesArgs);
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			if (typeof this._log === "function") {
				this._log(old, value);
			}
		}
		//!steal-remove-end
	},
	/**
	 * @function can-event-queue/value/value.can.getWhatIChange @can.getWhatIChange
	 * @parent can-event-queue/value/value
	 *
	 * @description Return observables whose values are affected by attached event handlers
	 * @signature `@can.getWhatIChange()`
	 *
	 * The `@@can.getWhatIChange` symbol is added to make sure [can-debug] can report
	 * all the observables whose values are set by value-like observables.
	 *
	 * This function iterates over the event handlers attached to  the observable's value
	 * event and collects the result of calling `@@can.getChangesDependencyRecord` on each
	 * handler; this symbol allows the caller to tell what observables are being mutated
	 * by the event handler when it is executed.
	 *
	 * In the following example a [can-simple-observable] instance named `month` is
	 * created and when its value changes the `age` property of the `map` [can-simple-map]
	 * instance is set. The event handler that causes the mutation is then decatorated with
	 * `@@can.getChangesDependencyRecord` to register the mutation dependency.
	 *
	 * ```js
	 * var month = new SimpleObservable(11);
	 * var map = new SimpleMap({ age: 30 });
	 * var canReflect = require("can-reflect");
	 *
	 * var onValueChange = function onValueChange() {
	 *	map.set("age", 31);
	 * };
	 *
	 * onValueChange[canSymbol.for("can.getChangesDependencyRecord")] = function() {
	 *	return {
	 *		keyDependencies: new Map([ [map, new Set(["age"])] ])
	 *	}
	 * };
	 *
	 * canReflect.onValue(month, onValueChange);
	 * month[canSymbol.for("can.getWhatIChange")]();
	 * ```
	 *
	 * The dependency records collected from the event handlers are divided into
	 * two categories:
	 *
	 * - mutate: Handlers in the mutate/domUI queues
	 * - derive: Handlers in the notify queue
	 *
	 * Since event handlers are added by default to the "mutate" queue, calling
	 * `@@can.getWhatIChange` on the `month` instance returns an object with a mutate
	 * property and the `keyDependencies` Map registered on the `onValueChange` handler.
	 *
	 * If multiple event handlers were attached to `month`, the dependency records
	 * of each handler are merged by `@@can.getWhatIChange`. Please check out the
	 * [can-reflect-dependencies] docs to learn more about how this symbol is used
	 * to keep track of custom observable dependencies.
	 */
	"can.getWhatIChange": function getWhatIChange() {
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			var whatIChange = {};

			var notifyHandlers = this.handlers.get(["notify"]);
			var mutateHandlers = [].concat(
				this.handlers.get(["mutate"]),
				this.handlers.get(["domUI"]),
				this.handlers.get(["dom"])
			);

			if (notifyHandlers.length) {
				notifyHandlers.forEach(function(handler) {
					var changes = canReflect_1_19_2_canReflect.getChangesDependencyRecord(handler);

					if (changes) {
						var record = whatIChange.derive;
						if (!record) {
							record = (whatIChange.derive = {});
						}
						merge(record, changes);
					}
				});
			}

			if (mutateHandlers.length) {
				mutateHandlers.forEach(function(handler) {
					var changes = canReflect_1_19_2_canReflect.getChangesDependencyRecord(handler);

					if (changes) {
						var record = whatIChange.mutate;
						if (!record) {
							record = (whatIChange.mutate = {});
						}
						merge(record, changes);
					}
				});
			}

			return Object.keys(whatIChange).length ? whatIChange : undefined;
		}
		//!steal-remove-end
	},

	/**
	 * @function can-event-queue/value/value.can.isBound @can.isBound
	 * @parent can-event-queue/value/value
	 */
	"can.isBound": function isBound() {
		return !this.handlers.isEmpty();
	}
};

/**
 * @property {can-key-tree} can-event-queue/value/value.handlers handlers
 * @parent can-event-queue/value/value
 *
 * @description Access the handlers tree directly.
 *
 * @type {can-key-tree}
 *
 *  The handlers property is a [can-define-lazy-value lazily] defined property containing
 *  all handlers bound with [can-event-queue/value/value.on] and
 *  [can-event-queue/value/value.can.onValue].  It is a [can-key-tree] defined like:
 *
 *  ```js
 *  this.handlers = new KeyTree([Object, Array])
 *  ```
 *
 *  It is configured to call [can-event-queue/value/value.onBound] and
 *  [can-event-queue/value/value.onUnbound] on the instances when the first item is
 *  added to the tree and when the tree is emptied.
 */
function defineLazyHandlers(){
	return new canKeyTree_1_2_2_canKeyTree([Object, Array], {
		onFirst: this.onBound !== undefined && this.onBound.bind(this),
		onEmpty: this.onUnbound !== undefined && this.onUnbound.bind(this)
	});
}

/**
 * @function can-event-queue/value/value.onBound onBound
 * @parent can-event-queue/value/value
 *
 * @description Perform operations when an observable is gains its first event handler.
 *
 * @signature `.onBound()`
 *
 * This method is not implemented by `can-event-queue/value/value`. Instead, the object
 * should implement it if it wants to perform some actions when it becomes bound.
 *
 * ```js
 * var mixinValueBindings = require("can-event-queue/value/value");
 *
 * var observable = mixinValueBindings({
 *   onBound: function(){
 *     console.log("I AM BOUND!");
 *   }
 * });
 *
 * observable.on(function(){});
 * // Logs: "I AM BOUND!"
 * ```
 *
 */

/**
 * @function can-event-queue/value/value.onUnbound onUnbound
 * @parent can-event-queue/value/value
 *
 * @description Perform operations when an observable loses all of its event handlers.
 *
 * @signature `.onBound()`
 *
 * This method is not implemented by `can-event-queue/value/value`. Instead, the object
 * should implement it if it wants to perform some actions when it becomes unbound.
 *
 * ```js
 * var mixinValueBindings = require("can-event-queue/value/value");
 *
 * var observable = mixinValueBindings({
 *   onUnbound: function(){
 *     console.log("I AM UNBOUND!");
 *   }
 * });
 * var handler = function(){}
 * observable.on(function(){});
 * observable.off(function(){});
 * // Logs: "I AM UNBOUND!"
 * ```
 */

/**
 * @module {function} can-event-queue/value/value
 * @parent can-event-queue
 *
 * @description Mixin methods and symbols to make this object or prototype object
 * behave like a single-value observable.
 *
 * @signature `mixinValueBindings( obj )`
 *
 * Adds symbols and methods that make `obj` or instances having `obj` on their prototype
 * behave like single-value observables.
 *
 * When `mixinValueBindings` is called on an `obj` like:
 *
 * ```js
 * var mixinValueBindings = require("can-event-queue/value/value");
 *
 * var observable = mixinValueBindings({});
 *
 * observable.on(function(newVal, oldVal){
 *   console.log(newVal);
 * });
 *
 * observable[canSymbol.for("can.dispatch")](2,1);
 * // Logs: 2
 * ```
 *
 * `mixinValueBindings` adds the following properties and symbols to the object:
 *
 * - [can-event-queue/value/value.on]
 * - [can-event-queue/value/value.off]
 * - [can-event-queue/value/value.can.dispatch]
 * - [can-event-queue/value/value.can.getWhatIChange]
 * - [can-event-queue/value/value.handlers]
 *
 * When the object is bound to for the first time with `.on` or `@can.onValue`, it will look for an [can-event-queue/value/value.onBound]
 * function on the object and call it.
 *
 * When the object is has no more handlers, it will look for an [can-event-queue/value/value.onUnbound]
 * function on the object and call it.
 */
var mixinValueEventBindings = function(obj) {
	canReflect_1_19_2_canReflect.assign(obj, properties);
	canReflect_1_19_2_canReflect.assignSymbols(obj, symbols);
	canDefineLazyValue_1_1_1_defineLazyValue(obj,"handlers",defineLazyHandlers, true);
	return obj;
};

// callbacks is optional
mixinValueEventBindings.addHandlers = function(obj, callbacks) {
	console.warn("can-event-queue/value: Avoid using addHandlers. Add onBound and onUnbound methods instead.");
	obj.handlers = new canKeyTree_1_2_2_canKeyTree([Object, Array], callbacks);
	return obj;
};

var value = mixinValueEventBindings;

// # Recorder Dependency Helpers
// This exposes two helpers:
// - `updateObservations` - binds and unbinds a diff of two observation records
//   (see can-observation-recorder for details on this data type).
// - `stopObserving` - unbinds an observation record.




// ## Helpers
// The following helpers all use `this` to pass additional arguments. This
// is for performance reasons as it avoids creating new functions.

function addNewKeyDependenciesIfNotInOld(event) {
    // Expects `this` to have:
    // - `.observable` - the observable we might be binding to.
    // - `.oldEventSet` - the bound keys on the old dependency record for `observable`.
    // - `.onDependencyChange` - the handler we will call back when the key is changed.
    // If there wasn't any keys, or when we tried to delete we couldn't because the key
    // wasn't in the set, start binding.
    if(this.oldEventSet === undefined || this.oldEventSet["delete"](event) === false) {
        canReflect_1_19_2_canReflect.onKeyValue(this.observable, event, this.onDependencyChange,"notify");
    }
}

// ### addObservablesNewKeyDependenciesIfNotInOld
// For each event in the `eventSet` of new observables,
// setup a binding (or delete the key).
function addObservablesNewKeyDependenciesIfNotInOld(eventSet, observable){
    eventSet.forEach(addNewKeyDependenciesIfNotInOld, {
        onDependencyChange: this.onDependencyChange,
        observable: observable,
        oldEventSet: this.oldDependencies.keyDependencies.get(observable)
    });
}

function removeKeyDependencies(event) {
    canReflect_1_19_2_canReflect.offKeyValue(this.observable, event, this.onDependencyChange,"notify");
}

function removeObservablesKeyDependencies(oldEventSet, observable){
    oldEventSet.forEach(removeKeyDependencies, {onDependencyChange: this.onDependencyChange, observable: observable});
}

function addValueDependencies(observable) {
    // If we were unable to delete the key in the old set, setup a binding.
    if(this.oldDependencies.valueDependencies.delete(observable) === false) {
        canReflect_1_19_2_canReflect.onValue(observable, this.onDependencyChange,"notify");
    }
}
function removeValueDependencies(observable) {
    canReflect_1_19_2_canReflect.offValue(observable, this.onDependencyChange,"notify");
}


var canObservation_4_2_0_recorderDependencyHelpers = {
    // ## updateObservations
    //
    // Binds `observationData.onDependencyChange` to dependencies in `observationData.newDependencies` that are not currently in
    // `observationData.oldDependencies`.  Anything in `observationData.oldDependencies`
    // left over is unbound.
    //
    // The algorthim works by:
    // 1. Loop through the `new` dependencies, checking if an equivalent is in the `old` bindings.
    //    - If there is an equivalent binding, delete that dependency from `old`.
    //    - If there is __not__ an equivalent binding, setup a binding from that dependency to `.onDependencyChange`.
    // 2. Loop through the remaining `old` dependencies, teardown bindings.
    //
    // For performance, this method mutates the values in `.oldDependencies`.
    updateObservations: function(observationData){
        observationData.newDependencies.keyDependencies.forEach(addObservablesNewKeyDependenciesIfNotInOld, observationData);
        observationData.oldDependencies.keyDependencies.forEach(removeObservablesKeyDependencies, observationData);
        observationData.newDependencies.valueDependencies.forEach(addValueDependencies, observationData);
        observationData.oldDependencies.valueDependencies.forEach(removeValueDependencies, observationData);
    },
    stopObserving: function(observationReciever, onDependencyChange){
        observationReciever.keyDependencies.forEach(removeObservablesKeyDependencies, {onDependencyChange: onDependencyChange});
        observationReciever.valueDependencies.forEach(removeValueDependencies, {onDependencyChange: onDependencyChange});
    }
};

var temporarilyBoundNoOperation = function(){};
// A list of temporarily bound computes
var observables;
// Unbinds all temporarily bound computes.
var unbindTemporarilyBoundValue = function () {
	for (var i = 0, len = observables.length; i < len; i++) {
		canReflect_1_19_2_canReflect.offValue(observables[i], temporarilyBoundNoOperation);
	}
	observables = null;
};

// ### temporarilyBind
// Binds computes for a moment to cache their value and prevent re-calculating it.
function temporarilyBind(compute) {
	var computeInstance = compute.computeInstance || compute;
	canReflect_1_19_2_canReflect.onValue(computeInstance, temporarilyBoundNoOperation);
	if (!observables) {
		observables = [];
		setTimeout(unbindTemporarilyBoundValue, 10);
	}
	observables.push(computeInstance);
}

var canObservation_4_2_0_temporarilyBind = temporarilyBind;

/* global require */
// # can-observation












var dispatchSymbol = canSymbol_1_7_0_canSymbol.for("can.dispatch");
var getChangesSymbol = canSymbol_1_7_0_canSymbol.for("can.getChangesDependencyRecord");
var getValueDependenciesSymbol = canSymbol_1_7_0_canSymbol.for("can.getValueDependencies");

// ## Observation constructor
function Observation(func, context, options){
	this.deriveQueue = canQueues_1_3_2_canQueues.deriveQueue;

	this.func = func;
	this.context = context;
	this.options = options || {priority: 0, isObservable: true};
	// A flag if we are bound or not
	this.bound = false;

	// Set _value to undefined so can-view-scope & can-compute can check for it
	this._value = undefined;

	// These properties will manage what our new and old dependencies are.
	this.newDependencies = canObservationRecorder_1_3_1_canObservationRecorder.makeDependenciesRecord();
	this.oldDependencies = null;

	// Make functions we need to pass around and maintain `this`.
	var self = this;
	this.onDependencyChange = function(newVal){
		self.dependencyChange(this, newVal);
	};
	this.update = this.update.bind(this);


	// Add debugging names.
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		this.onDependencyChange[getChangesSymbol] = function getChanges() {
			var s = new Set();
			s.add(self);
			return {
				valueDependencies: s
			};
		};
		Object.defineProperty(this.onDependencyChange, "name", {
			value: canReflect_1_19_2_canReflect.getName(this) + ".onDependencyChange",
		});
		Object.defineProperty(this.update, "name", {
			value: canReflect_1_19_2_canReflect.getName(this) + ".update",
		});
		this._name = canReflect_1_19_2_canReflect.getName(this); // cached for performance
	}
	//!steal-remove-end
}

// ## Observation prototype methods

// Mixin value event bindings. This is where the following are added:
// - `.handlers` which call `onBound` and `onUnbound`
// - `.on` / `.off`
// - `can.onValue` `can.offValue`
// - `can.getWhatIChange`
value(Observation.prototype);

canReflect_1_19_2_canReflect.assign(Observation.prototype, {
	// Starts observing changes and adds event listeners.
	onBound: function(){
		this.bound = true;

		// Store the old dependencies
		this.oldDependencies = this.newDependencies;
		// Start recording dependencies.
		canObservationRecorder_1_3_1_canObservationRecorder.start(this._name);
		// Call the observation's function and update the new value.
		this._value = this.func.call(this.context);
		// Get the new dependencies.
		this.newDependencies = canObservationRecorder_1_3_1_canObservationRecorder.stop();

		// Diff and update the bindings. On change, everything will call
		// `this.onDependencyChange`, which calls `this.dependencyChange`.
		canObservation_4_2_0_recorderDependencyHelpers.updateObservations(this);
	},
	// This is called when any of the dependencies change.
	// It queues up an update in the `deriveQueue` to be run after all source
	// observables have had time to notify all observables that "derive" their value.
	dependencyChange: function(context, args){
		if(this.bound === true) {
			var queuesArgs = [];
			queuesArgs = [
				this.update,
				this,
				[],
				{
					priority: this.options.priority,
					element: this.options.element
				}
			];
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				queuesArgs = [
					this.update,
					this,
					[],
					{
						priority: this.options.priority,
						element: this.options.element
						/* jshint laxcomma: true */
						, log: [ canReflect_1_19_2_canReflect.getName(this.update) ]
						/* jshint laxcomma: false */
					}
					/* jshint laxcomma: true */
					, [canReflect_1_19_2_canReflect.getName(context), "changed"]
					/* jshint laxcomma: false */
				];
			}
			//!steal-remove-end
			// Update this observation after all `notify` tasks have been run.
			this.deriveQueue.enqueue.apply(this.deriveQueue, queuesArgs);
		}
	},
	// Called to update its value as part of the `derive` queue.
	update: function() {
		if (this.bound === true) {
			// Keep the old value.
			var oldValue = this._value;
			this.oldValue = null;
			// Re-run `this.func` and update dependency bindings.
			this.onBound();
			// If our value changed, call the `dispatch` method provided by `can-event-queue/value/value`.
			if (oldValue !== this._value) {
				this[dispatchSymbol](this._value, oldValue);
			}
		}
	},
	// Called when nothing is bound to this observation.
	// Removes all event listeners on all dependency observables.
	onUnbound: function(){
		this.bound = false;
		canObservation_4_2_0_recorderDependencyHelpers.stopObserving(this.newDependencies, this.onDependencyChange);
		// Setup newDependencies in case someone binds again to this observable.
		this.newDependencies = canObservationRecorder_1_3_1_canObservationRecorder.makeDependenciesRecord();
	},
	// Reads the value of the observation.
	get: function(){

		// If an external observation is tracking observables and
		// this compute can be listened to by "function" based computes ....
		if( this.options.isObservable && canObservationRecorder_1_3_1_canObservationRecorder.isRecording() ) {

			// ... tell the tracking compute to listen to change on this observation.
			canObservationRecorder_1_3_1_canObservationRecorder.add(this);
			// ... if we are not bound, we should bind so that
			// we don't have to re-read to get the value of this observation.
			if (this.bound === false) {
				Observation.temporarilyBind(this);
			}

		}


		if(this.bound === true ) {
			// It's possible that a child dependency of this observable might be queued
			// to change. Check all child dependencies and make sure they are up-to-date by
			// possibly running what they have registered in the derive queue.
			if(this.deriveQueue.tasksRemainingCount() > 0) {
				Observation.updateChildrenAndSelf(this);
			}

			return this._value;
		} else {
			// If we are not bound, just call the function.
			return this.func.call(this.context);
		}
	},

	hasDependencies: function(){
		var newDependencies = this.newDependencies;
		return this.bound ?
			(newDependencies.valueDependencies.size + newDependencies.keyDependencies.size) > 0  :
			undefined;
	},
	log: function() {
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			var quoteString = function quoteString(x) {
				return typeof x === "string" ? JSON.stringify(x) : x;
			};
			this._log = function(previous, current) {
				dev.log(
					canReflect_1_19_2_canReflect.getName(this),
					"\n is  ", quoteString(current),
					"\n was ", quoteString(previous)
				);
			};
		}
		//!steal-remove-end
	}
});

Object.defineProperty(Observation.prototype, "value", {
	get: function() {
		return this.get();
	}
});

var observationProto = {
	"can.getValue": Observation.prototype.get,
	"can.isValueLike": true,
	"can.isMapLike": false,
	"can.isListLike": false,
	"can.valueHasDependencies": Observation.prototype.hasDependencies,
	"can.getValueDependencies": function(){
		if (this.bound === true) {
			// Only provide `keyDependencies` and `valueDependencies` properties
			// if there's actually something there.
			var deps = this.newDependencies,
				result = {};

			if (deps.keyDependencies.size) {
				result.keyDependencies = deps.keyDependencies;
			}

			if (deps.valueDependencies.size) {
				result.valueDependencies = deps.valueDependencies;
			}

			return result;
		}
		return undefined;
	},
	"can.getPriority": function(){
		return this.options.priority;
	},
	"can.setPriority": function(priority){
		this.options.priority = priority;
	},
	"can.setElement": function(element) {
		this.options.element = element;
		this.deriveQueue = canQueues_1_3_2_canQueues.domQueue || canQueues_1_3_2_canQueues.deriveQueue;
	}
};

//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	observationProto["can.getName"] = function() {
		return canReflect_1_19_2_canReflect.getName(this.constructor) + "<" + canReflect_1_19_2_canReflect.getName(this.func) + ">";
	};
}
//!steal-remove-end
canReflect_1_19_2_canReflect.assignSymbols(Observation.prototype, observationProto);

// ## Observation.updateChildrenAndSelf
// This recursively checks if an observation's dependencies might be in the `derive` queue.
// If it is, we need to update that value so the reading of this value will be correct.
// This can happen if an observation suddenly switches to depending on something that has higher
// priority than itself.  We need to make sure that value is completely updated.
Observation.updateChildrenAndSelf = function(observation){
	// If the observable has an `update` method and it's enqueued, flush that task immediately so
	// the value is right.
	// > NOTE: This only works for `Observation` right now.  We need a way of knowing how
	// > to find what an observable might have in the `deriveQueue`.
	if(observation.update !== undefined && observation.deriveQueue.isEnqueued( observation.update ) === true) {
		// TODO: In the future, we should be able to send log information
		// to explain why this needed to be updated.
		observation.deriveQueue.flushQueuedTask(observation.update);
		return true;
	}

	// If we can get dependency values from this observable ...
	if(observation[getValueDependenciesSymbol]) {
		// ... Loop through each dependency and see if any of them (or their children) needed an update.
		var childHasChanged = false;
		var valueDependencies = observation[getValueDependenciesSymbol]().valueDependencies || [];
		valueDependencies.forEach(function(observable){
			if( Observation.updateChildrenAndSelf( observable ) === true) {
				childHasChanged = true;
			}
		});
		return childHasChanged;
	} else {
		return false;
	}
};

// ## Legacy Stuff
// Warn when `ObservationRecorder` methods are called on `Observation`.
var alias = {addAll: "addMany"};
["add","addAll","ignore","trap","trapsCount","isRecording"].forEach(function(methodName){
	Observation[methodName] = function(){
		var name = alias[methodName] ? alias[methodName] : methodName;
		console.warn("can-observation: Call "+name+"() on can-observation-recorder.");
		return canObservationRecorder_1_3_1_canObservationRecorder[name].apply(this, arguments);
	};
});
Observation.prototype.start = function(){
	console.warn("can-observation: Use .on and .off to bind.");
	return this.onBound();
};
Observation.prototype.stop = function(){
	console.warn("can-observation: Use .on and .off to bind.");
	return this.onUnbound();
};

// ### temporarilyBind
// Will bind an observable value temporarily.  This should be part of queues probably.
Observation.temporarilyBind = canObservation_4_2_0_temporarilyBind;


var canObservation_4_2_0_canObservation = canNamespace_1_0_0_canNamespace.Observation = Observation;

// DependencyRecord :: { keyDependencies: Map, valueDependencies: Set }
var makeDependencyRecord = function makeDependencyRecord() {
	return {
		keyDependencies: new Map(),
		valueDependencies: new Set()
	};
};

var makeRootRecord = function makeRootRecord() {
	return {
		// holds mutated key dependencies of a key-value like object, e.g:
		// if person.first is mutated by other observable, this map will have a
		// key `first` (the mutated property) mapped to a DependencyRecord
		mutateDependenciesForKey: new Map(),

		// holds mutated value dependencies of value-like objects
		mutateDependenciesForValue: makeDependencyRecord()
	};
};

var addMutatedBy = function(mutatedByMap) {
	return function addMutatedBy(mutated, key, mutator) {
		var gotKey = arguments.length === 3;

		// normalize arguments
		if (arguments.length === 2) {
			mutator = key;
			key = undefined;
		}

		// normalize mutator when shorthand is used
		if (!mutator.keyDependencies && !mutator.valueDependencies) {
			var s = new Set();
			s.add(mutator);
			mutator = { valueDependencies:s };
		}

		// retrieve root record from the state map or create a new one
		var root = mutatedByMap.get(mutated);
		if (!root) {
			root = makeRootRecord();
			mutatedByMap.set(mutated, root);
		}

		// create a [key] DependencyRecord if [key] was provided
		// and Record does not already exist
		if (gotKey && !root.mutateDependenciesForKey.get(key)) {
			root.mutateDependenciesForKey.set(key, makeDependencyRecord());
		}

		// retrieve DependencyRecord
		var dependencyRecord = gotKey ?
			root.mutateDependenciesForKey.get(key) :
			root.mutateDependenciesForValue;

		if (mutator.valueDependencies) {
			canReflect_1_19_2_canReflect.addValues(
				dependencyRecord.valueDependencies,
				mutator.valueDependencies
			);
		}

		if (mutator.keyDependencies) {
			canReflect_1_19_2_canReflect.each(mutator.keyDependencies, function(keysSet, obj) {
				var entry = dependencyRecord.keyDependencies.get(obj);

				if (!entry) {
					entry = new Set();
					dependencyRecord.keyDependencies.set(obj, entry);
				}

				canReflect_1_19_2_canReflect.addValues(entry, keysSet);
			});
		}
	};
};

var deleteMutatedBy = function(mutatedByMap) {
	return function deleteMutatedBy(mutated, key, mutator) {
		var gotKey = arguments.length === 3;
		var root = mutatedByMap.get(mutated);

		// normalize arguments
		if (arguments.length === 2) {
			mutator = key;
			key = undefined;
		}

		// normalize mutator when shorthand is used
		if (!mutator.keyDependencies && !mutator.valueDependencies) {
			var s = new Set();
			s.add(mutator);
			mutator = { valueDependencies: s };
		}

		var dependencyRecord = gotKey ?
			root.mutateDependenciesForKey.get(key) :
			root.mutateDependenciesForValue;

		if (mutator.valueDependencies) {
			canReflect_1_19_2_canReflect.removeValues(
				dependencyRecord.valueDependencies,
				mutator.valueDependencies
			);
		}

		if (mutator.keyDependencies) {
			canReflect_1_19_2_canReflect.each(mutator.keyDependencies, function(keysSet, obj) {
				var entry = dependencyRecord.keyDependencies.get(obj);

				if (entry) {
					canReflect_1_19_2_canReflect.removeValues(entry, keysSet);
					if (!entry.size) {
						dependencyRecord.keyDependencies.delete(obj);
					}
				}
			});
		}
	};
};

var isFunction = function isFunction(value) {
	return typeof value === "function";
};

var getWhatIChangeSymbol = canSymbol_1_7_0_canSymbol.for("can.getWhatIChange");
var getKeyDependenciesSymbol = canSymbol_1_7_0_canSymbol.for("can.getKeyDependencies");
var getValueDependenciesSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.getValueDependencies");

var getKeyDependencies = function getKeyDependencies(obj, key) {
	if (isFunction(obj[getKeyDependenciesSymbol])) {
		return canReflect_1_19_2_canReflect.getKeyDependencies(obj, key);
	}
};

var getValueDependencies = function getValueDependencies(obj) {
	if (isFunction(obj[getValueDependenciesSymbol$1])) {
		return canReflect_1_19_2_canReflect.getValueDependencies(obj);
	}
};

var getMutatedKeyDependencies =
	function getMutatedKeyDependencies(mutatedByMap, obj, key) {
		var root = mutatedByMap.get(obj);
		var dependencyRecord;

		if (root && root.mutateDependenciesForKey.has(key)) {
			dependencyRecord = root.mutateDependenciesForKey.get(key);
		}

		return dependencyRecord;
	};

var getMutatedValueDependencies =
	function getMutatedValueDependencies( mutatedByMap, obj) {
		var result;
		var root = mutatedByMap.get(obj);

		if (root) {
			var	dependencyRecord = root.mutateDependenciesForValue;

			if (dependencyRecord.keyDependencies.size) {
				result = result || {};
				result.keyDependencies = dependencyRecord.keyDependencies;
			}

			if (dependencyRecord.valueDependencies.size) {
				result = result || {};
				result.valueDependencies = dependencyRecord.valueDependencies;
			}
		}

		return result;
	};

var getWhatIChange = function getWhatIChange(obj, key) {
	if (isFunction(obj[getWhatIChangeSymbol])) {
		var gotKey = arguments.length === 2;

		return gotKey ?
			canReflect_1_19_2_canReflect.getWhatIChange(obj, key) :
			canReflect_1_19_2_canReflect.getWhatIChange(obj);
	}
};

var isEmptyRecord = function isEmptyRecord(record) {
	return (
		record == null ||
		!Object.keys(record).length ||
		(record.keyDependencies && !record.keyDependencies.size) &&
		(record.valueDependencies && !record.valueDependencies.size)
	);
};

var getWhatChangesMe = function getWhatChangesMe(mutatedByMap, obj, key) {
	var gotKey = arguments.length === 3;

	var mutate = gotKey ?
		getMutatedKeyDependencies(mutatedByMap, obj, key) :
		getMutatedValueDependencies(mutatedByMap, obj);

	var derive = gotKey ?
		getKeyDependencies(obj, key) :
		getValueDependencies(obj);

	if (!isEmptyRecord(mutate) || !isEmptyRecord(derive)) {
		return canAssign_1_3_3_canAssign(
			canAssign_1_3_3_canAssign(
				{},
				mutate ? { mutate: mutate } : null
			),
			derive ? { derive: derive } : null
		);
	}
};

var getDependencyDataOf = function(mutatedByMap) {
	return function getDependencyDataOf(obj, key) {
		var gotKey = arguments.length === 2;

		var whatChangesMe = gotKey ?
			getWhatChangesMe(mutatedByMap, obj, key) :
			getWhatChangesMe(mutatedByMap, obj);

		var whatIChange = gotKey ? getWhatIChange(obj, key) : getWhatIChange(obj);

		if (whatChangesMe || whatIChange) {
			return canAssign_1_3_3_canAssign(
				canAssign_1_3_3_canAssign(
					{},
					whatIChange ? { whatIChange: whatIChange } : null
				),
				whatChangesMe ? { whatChangesMe: whatChangesMe } : null
			);
		}
	};
};

// mutatedByMap :: WeakMap<obj, {
//	mutateDependenciesForKey:   Map<key, DependencyRecord>,
//	mutateDependenciesForValue: DependencyRecord
// }>
var mutatedByMap = new WeakMap();

var canReflectDependencies_1_1_2_canReflectDependencies = {
	// Track mutations between observable as dependencies
	// addMutatedBy(obs, obs2);
	// addMutatedBy(obs, key, obs2);
	// addMutatedBy(obs, { valueDependencies: Set, keyDependencies: Map })
	// addMutatedBy(obs, key, { valueDependencies: Set, keyDependencies: Map })
	addMutatedBy: addMutatedBy(mutatedByMap),

	// Call this method with the same arguments as `addMutatedBy`
	// to unregister the mutation dependency
	deleteMutatedBy: deleteMutatedBy(mutatedByMap),

	// Returns an object with the dependecies of the given argument
	//	{
	//		whatIChange: { mutate: DependencyRecord, derive: DependencyRecord },
	//		whatChangesMe: { mutate: DependencyRecord, derive: DependencyRecord }
	//	}
	getDependencyDataOf: getDependencyDataOf(mutatedByMap)
};

//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	var canReflectDependencies = canReflectDependencies_1_1_2_canReflectDependencies;
}
//!steal-remove-end

var key = function keyObservable(root, keyPath) {
	var keyPathParts = canKey_1_2_1_utils.parts(keyPath);
	var lastIndex = keyPathParts.length - 1;

	// Some variables used to build the dependency/mutation graph
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		var lastKey;// This stores the last part of the keyPath, e.g. “key” in “outer.inner.key”
		var lastParent;// This stores the object that the last key is on, e.g. “outer.inner” in outer: {inner: {"key": "value"}}
	}
	//!steal-remove-end

	var observation = new canObservation_4_2_0_canObservation(function() {
		var value;

		// This needs to be walked every time because the objects along the key path might change
		canKey_1_2_1_canKey.walk(root, keyPathParts, function(keyData, i) {
			if (i === lastIndex) {
				//!steal-remove-start
				if (process.env.NODE_ENV !== 'production') {
					// observation is mutating keyData.parent
					if (lastParent && (keyData.key !== lastKey || keyData.parent !== lastParent)) {
						canReflectDependencies.deleteMutatedBy(lastParent, lastKey, observation);
					}
					lastKey = keyData.key;
					lastParent = keyData.parent;
					canReflectDependencies.addMutatedBy(lastParent, lastKey, observation);
				}
				//!steal-remove-end

				value = keyData.value;
			}
		});

		return value;
	});

	// Function for setting the value
	var valueSetter = function(newVal) {
		canKey_1_2_1_canKey.set(root, keyPathParts, newVal);
	};

	// The `value` property getter & setter
	Object.defineProperty(observation, "value", {
		get: observation.get,
		set: valueSetter
	});

	var symbolsToAssign = {
		"can.setValue": valueSetter
	};

	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {

		// Debug name
		symbolsToAssign["can.getName"] = function getName() {
			var objectName = canReflect_1_19_2_canReflect.getName(root);
			return "keyObservable<" + objectName + "." + keyPath + ">";
		};

		// Register what this observable changes
		symbolsToAssign["can.getWhatIChange"] = function getWhatIChange() {
			var m = new Map();
			var s = new Set();
			s.add(lastKey);
			m.set(lastParent, s);
			return {
				mutate: {
					keyDependencies: m
				}
			};
		};
	}
	//!steal-remove-end

	return canReflect_1_19_2_canReflect.assignSymbols(observation, symbolsToAssign);
};

// when printing out strings to the console, quotes are not included which
// makes it confusing to tell the actual output from static string messages
function quoteString(x) {
	return typeof x === "string" ? JSON.stringify(x) : x;
}

// To add the `.log` function to a observable
// a.- Add the log function to the propotype:
//	   `Observable.propotype.log = log`
// b.- Make sure `._log` is called by the observable when mutation happens
//     `_.log` should be passed the current value and the value before the mutation
var canSimpleObservable_2_5_0_log = function log() {
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		this._log = function(previous, current) {
			dev.log(
				canReflect_1_19_2_canReflect.getName(this),
				"\n is  ", quoteString(current),
				"\n was ", quoteString(previous)
			);
		};
	}
	//!steal-remove-end
};

var dispatchSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.dispatch");

/**
 * @module {function} can-simple-observable
 * @parent can-observables
 * @collection can-infrastructure
 * @package ./package.json
 * @description Create an observable value.
 *
 * @signature `new SimpleObservable(initialValue)`
 *
 * Creates an observable value that can be read, written, and observed using [can-reflect].
 *
 * @param {*} initialValue The initial value of the observable.
 *
 * @return {can-simple-observable} An observable instance
 *
 * @body
 *
 * ## Use
 *
 * ```js
 *  var obs = new SimpleObservable('one');
 *
 *  canReflect.getValue(obs); // -> "one"
 *
 *  canReflect.setValue(obs, 'two');
 *  canReflect.getValue(obs); // -> "two"
 *
 *  function handler(newValue) {
 *    // -> "three"
 *  };
 *  canReflect.onValue(obs, handler);
 *  canReflect.setValue(obs, 'three');
 *
 *  canReflect.offValue(obs, handler);
 * ```
 */
function SimpleObservable(initialValue) {
	this._value = initialValue;
}

// mix in the value-like object event bindings
value(SimpleObservable.prototype);

canReflect_1_19_2_canReflect.assignMap(SimpleObservable.prototype, {
	log: canSimpleObservable_2_5_0_log,
	get: function(){
		canObservationRecorder_1_3_1_canObservationRecorder.add(this);
		return this._value;
	},
	set: function(value$$1){
		var old = this._value;
		this._value = value$$1;

		this[dispatchSymbol$1](value$$1, old);
	}
});
Object.defineProperty(SimpleObservable.prototype,"value",{
	set: function(value$$1){
		return this.set(value$$1);
	},
	get: function(){
		return this.get();
	}
});

var simpleObservableProto = {
	"can.getValue": SimpleObservable.prototype.get,
	"can.setValue": SimpleObservable.prototype.set,
	"can.isMapLike": false,
	"can.valueHasDependencies": function(){
		return true;
	}
};

//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	simpleObservableProto["can.getName"] = function() {
		var value$$1 = this._value;
		if (typeof value$$1 !== 'object' || value$$1 === null) {
			value$$1 = JSON.stringify(value$$1);
		}
		else {
			value$$1 = '';
		}

		return canReflect_1_19_2_canReflect.getName(this.constructor) + "<" + value$$1 + ">";
	};
}
//!steal-remove-end

canReflect_1_19_2_canReflect.assignSymbols(SimpleObservable.prototype, simpleObservableProto);

var canSimpleObservable_2_5_0_canSimpleObservable = canNamespace_1_0_0_canNamespace.SimpleObservable = SimpleObservable;

var peek = canObservationRecorder_1_3_1_canObservationRecorder.ignore(canReflect_1_19_2_canReflect.getValue.bind(canReflect_1_19_2_canReflect));

// This supports an "internal" settable value that the `fn` can derive its value from.
// It's useful to `can-define`.
// ```
// new SettableObservable(function(lastSet){
//   return lastSet * 5;
// }, null, 5)
// ```
function SettableObservable(fn, context, initialValue) {

	this.lastSetValue = new canSimpleObservable_2_5_0_canSimpleObservable(initialValue);
	function observe() {
		return fn.call(context, this.lastSetValue.get());
	}
	this.handler = this.handler.bind(this);

	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		canReflect_1_19_2_canReflect.assignSymbols(this, {
			"can.getName": function() {
				return (
					canReflect_1_19_2_canReflect.getName(this.constructor) +
					"<" +
					canReflect_1_19_2_canReflect.getName(fn) +
					">"
				);
			}
		});
		Object.defineProperty(this.handler, "name", {
			value: canReflect_1_19_2_canReflect.getName(this) + ".handler"
		});
		Object.defineProperty(observe, "name", {
			value: canReflect_1_19_2_canReflect.getName(fn) + "::" + canReflect_1_19_2_canReflect.getName(this.constructor)
		});
	}
	//!steal-remove-end

	this.observation = new canObservation_4_2_0_canObservation(observe, this);
}

value(SettableObservable.prototype);

canReflect_1_19_2_canReflect.assignMap(SettableObservable.prototype, {
	// call `obs.log()` to log observable changes to the browser console
	// The observable has to be bound for `.log` to be called
	log: canSimpleObservable_2_5_0_log,
	constructor: SettableObservable,
	handler: function(newVal) {
		var old = this._value, reasonLog;
		this._value = newVal;

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			if (typeof this._log === "function") {
				this._log(old, newVal);
			}
			reasonLog = [canReflect_1_19_2_canReflect.getName(this),"set to", newVal, "from", old];
		}
		//!steal-remove-end

		// adds callback handlers to be called w/i their respective queue.
		canQueues_1_3_2_canQueues.enqueueByQueue(
			this.handlers.getNode([]),
			this,
			[newVal, old],
			null,
			reasonLog
		);
	},
	onBound: function() {
		// onBound can be called by `.get` and then later called through
		// a keyTree binding.
		if(!this.bound) {
			this.bound = true;
			this.activate();
		}
	},
	activate: function(){
		canReflect_1_19_2_canReflect.onValue(this.observation, this.handler, "notify");
		this._value = peek(this.observation);
	},
	onUnbound: function() {
		this.bound = false;
		canReflect_1_19_2_canReflect.offValue(this.observation, this.handler, "notify");
	},
	set: function(newVal) {
		var oldVal =  this.lastSetValue.get();

		if (
			canReflect_1_19_2_canReflect.isObservableLike(oldVal) &&
			canReflect_1_19_2_canReflect.isValueLike(oldVal) &&
			!canReflect_1_19_2_canReflect.isObservableLike(newVal)
		) {
			canReflect_1_19_2_canReflect.setValue(oldVal, newVal);
		} else {
			if (newVal !== oldVal) {
				this.lastSetValue.set(newVal);
			}
		}
	},
	get: function() {
		if (canObservationRecorder_1_3_1_canObservationRecorder.isRecording()) {
			canObservationRecorder_1_3_1_canObservationRecorder.add(this);
			if (!this.bound) {
				// proactively setup bindings
				this.onBound();
			}
		}

		if (this.bound === true) {
			return this._value;
		} else {
			return this.observation.get();
		}
	},
	hasDependencies: function() {
		return canReflect_1_19_2_canReflect.valueHasDependencies(this.observation);
	},
	getValueDependencies: function() {
		return canReflect_1_19_2_canReflect.getValueDependencies(this.observation);
	}
});

Object.defineProperty(SettableObservable.prototype,"value",{
	set: function(value$$1){
		return this.set(value$$1);
	},
	get: function(){
		return this.get();
	}
});

canReflect_1_19_2_canReflect.assignSymbols(SettableObservable.prototype, {
	"can.getValue": SettableObservable.prototype.get,
	"can.setValue": SettableObservable.prototype.set,
	"can.isMapLike": false,
	"can.getPriority": function() {
		return canReflect_1_19_2_canReflect.getPriority(this.observation);
	},
	"can.setPriority": function(newPriority) {
		canReflect_1_19_2_canReflect.setPriority(this.observation, newPriority);
	},
	"can.valueHasDependencies": SettableObservable.prototype.hasDependencies,
	"can.getValueDependencies": SettableObservable.prototype.getValueDependencies
});

var settable = SettableObservable;

var canValue_1_1_2_canValue = canNamespace_1_0_0_canNamespace.value = {
	bind: function(object, keyPath) {
		return key(object, keyPath);
	},

	from: function(object, keyPath) {
		var observationFunction = function() {
			return canKey_1_2_1_canKey.get(object, keyPath);
		};

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			var objectName = canReflect_1_19_2_canReflect.getName(object);
			Object.defineProperty(observationFunction, "name", {
				value: "ValueFrom<" + objectName + "." + keyPath + ">"
			});
		}
		//!steal-remove-end

		return new canObservation_4_2_0_canObservation(observationFunction);
	},

	returnedBy: function(getter, context, initialValue) {
		if(getter.length === 1) {
			return new settable(getter, context, initialValue);
		} else {
			return new canObservation_4_2_0_canObservation(getter, context);
		}
	},

	to: function(object, keyPath) {
		var observable = key(object, keyPath);

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			canReflect_1_19_2_canReflect.assignSymbols(observable.onDependencyChange, {
				"can.getChangesDependencyRecord": function getChangesDependencyRecord() {
					// can-simple-observable/key/ creates an observation that walks along
					// the keyPath. In doing so, it implicitly registers the objects and
					// keys along the path as mutators of the observation; this means
					// getDependencyDataOf(...an object and key along the path) returns
					// whatIChange.derive.valueDependencies = [observable], which is not
					// true! The observable does not derive its value from the objects
					// along the keyPath. By implementing getChangesDependencyRecord and
					// returning undefined, calls to can.getWhatIChange() for any objects
					// along the keyPath will not include the observable.
				}
			});
		}
		//!steal-remove-end

		var symbolsToAssign = {
			// Remove the getValue symbol so the observable is only a setter
			"can.getValue": null
		};

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			symbolsToAssign["can.getValueDependencies"] = function getValueDependencies() {
				// Normally, getDependencyDataOf(observable) would include
				// whatChangesMe.derive.keyDependencies, and it would contain
				// the object and anything along keyPath. This symbol returns
				// undefined because this observable does not derive its value
				// from the object or anything along the keyPath, it only
				// mutates the last object in the keyPath.
			};
		}
		//!steal-remove-end

		return canReflect_1_19_2_canReflect.assignSymbols(observable, symbolsToAssign);
	},

	with: function(initialValue) {
		return new canSimpleObservable_2_5_0_canSimpleObservable(initialValue);
	}
};

// ##string.js
// _Miscellaneous string utility functions._
// Several of the methods in this plugin use code adapted from Prototype
// Prototype JavaScript framework, version 1.6.0.1.
// © 2005-2007 Sam Stephenson
var strUndHash = /_|-/,
	strColons = /\=\=/,
	strWords = /([A-Z]+)([A-Z][a-z])/g,
	strLowUp = /([a-z\d])([A-Z])/g,
	strDash = /([a-z\d])([A-Z])/g,
	strQuote = /"/g,
	strSingleQuote = /'/g,
	strHyphenMatch = /-+(.)?/g,
	strCamelMatch = /[a-z][A-Z]/g,
	convertBadValues = function (content) {
		// Convert bad values into empty strings
		var isInvalid = content === null || content === undefined || isNaN(content) && '' + content === 'NaN';
		return '' + (isInvalid ? '' : content);
	};

var string = {
	/**
	 * @function can-string.esc esc
	 * @signature `string.esc(content)`
	 * @param  {String} content a string
	 * @return {String}         the string safely HTML-escaped
	 *
	 * ```js
	 * var string = require("can-string");
	 *
	 * string.esc("<div>&nbsp;</div>"); //-> "&lt;div&gt;&amp;nbsp;&lt;/div&gt;"
	 * ```
	 */
	esc: function (content) {
		return convertBadValues(content)
			.replace(/&/g, '&amp;')
			.replace(/</g, '&lt;')
			.replace(/>/g, '&gt;')
			.replace(strQuote, '&#34;')
			.replace(strSingleQuote, '&#39;');
	},
	/**
	 * @function can-string.capitalize capitalize
	 * @signature `string.capitalize(s)`
	 * @param  {String} s     the string to capitalize
	 * @return {String}       the supplied string with the first character uppercased if it is a letter
	 *
	 * ```js
	 * var string = require("can-string");
	 *
	 * console.log(string.capitalize("foo")); // -> "Foo"
	 * console.log(string.capitalize("123")); // -> "123"
	 * ```
	 */
	capitalize: function (s) {
		// Used to make newId.
		return s.charAt(0)
			.toUpperCase() + s.slice(1);
	},
	/**
	 * @function can-string.camelize camelize
	 * @signature `string.camelize(s)`
	 * @param  {String} str   the string to camelCase
	 * @return {String}       the supplied string with hyphens removed and following letters capitalized.
	 *
	 * ```js
	 * var string = require("can-string");
	 *
	 * console.log(string.camelize("foo-bar")); // -> "fooBar"
	 * console.log(string.camelize("-webkit-flex-flow")); // -> "WebkitFlexFlow"
	 * ```
	 */
	camelize: function (str) {
		return convertBadValues(str)
			.replace(strHyphenMatch, function (match, chr) {
				return chr ? chr.toUpperCase() : '';
			});
	},
	/**
	 * @function can-string.hyphenate hyphenate
	 * @signature `string.hyphenate(s)`
	 * @param  {String} str   a string in camelCase
	 * @return {String}       the supplied string with camelCase converted to hyphen-lowercase digraphs
	 *
	 * ```js
	 * var string = require("can-string");
	 *
	 * console.log(string.hyphenate("fooBar")); // -> "foo-bar"
	 * console.log(string.hyphenate("WebkitFlexFlow")); // -> "Webkit-flex-flow"
	 * ```
	 */
	hyphenate: function (str) {
		return convertBadValues(str)
			.replace(strCamelMatch, function (str) {
				return str.charAt(0) + '-' + str.charAt(1)
					.toLowerCase();
			});
	},
	/**
	 * @function can-string.pascalize pascalize
	 * @signature `string.pascalize(s)`
	 * @param  {String} str   the string in hyphen case | camelCase
	 * @return {String}       the supplied string with hyphens | camelCase converted to PascalCase
	 *
	 * ```js
	 * var string = require("can-string");
	 *
	 * console.log(string.pascalize("fooBar")); // -> "FooBar"
	 * console.log(string.pascalize("baz-bar")); // -> "BazBar"
	 * ```
	 */
	pascalize: function (str) {
		return string.capitalize(string.camelize(str));
	},
	/**
	 * @function can-string.underscore underscore
	 * @signature `string.underscore(s)`
	 * @param  {String} str   a string in camelCase
	 * @return {String}       the supplied string with camelCase converted to underscore-lowercase digraphs
	 *
	 * ```js
	 * var string = require("can-string");
	 *
	 * console.log(string.underscore("fooBar")); // -> "foo_bar"
	 * console.log(string.underscore("HTMLElement")); // -> "html_element"
	 * ```
	 */
	underscore: function (s) {
		return s.replace(strColons, '/')
			.replace(strWords, '$1_$2')
			.replace(strLowUp, '$1_$2')
			.replace(strDash, '_')
			.toLowerCase();
	},
	/**
	 * @property {RegExp} can-string.strUndHash strUndHash
	 *
	 * A regex which matches an underscore or hyphen character
	 */
	undHash: strUndHash
};
var canString_1_1_0_canString = string;

var inSetupSymbol = canSymbol_1_7_0_canSymbol.for("can.initializing");

//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var CanString = canString_1_1_0_canString;
	var reservedWords = {
		"abstract": true,
		"boolean": true,
		"break": true,
		"byte": true,
		"case": true,
		"catch": true,
		"char": true,
		"class": true,
		"const": true,
		"continue": true,
		"debugger": true,
		"default": true,
		"delete": true,
		"do": true,
		"double": true,
		"else": true,
		"enum": true,
		"export": true,
		"extends": true,
		"false": true,
		"final": true,
		"finally": true,
		"float": true,
		"for": true,
		"function": true,
		"goto": true,
		"if": true,
		"implements": true,
		"import": true,
		"in": true,
		"instanceof": true,
		"int": true,
		"interface": true,
		"let": true,
		"long": true,
		"native": true,
		"new": true,
		"null": true,
		"package": true,
		"private": true,
		"protected": true,
		"public": true,
		"return": true,
		"short": true,
		"static": true,
		"super": true,
		"switch": true,
		"synchronized": true,
		"this": true,
		"throw": true,
		"throws": true,
		"transient": true,
		"true": true,
		"try": true,
		"typeof": true,
		"var": true,
		"void": true,
		"volatile": true,
		"while": true,
		"with": true
	};
	var constructorNameRegex = /[^A-Z0-9_]/gi;
}
//!steal-remove-end

// ## construct.js
// `Construct`
// _This is a modified version of
// [John Resig's class](http://ejohn.org/blog/simple-javascript-inheritance/).
// It provides class level inheritance and callbacks._
// A private flag used to initialize a new class instance without
// initializing it's bindings.
var initializing = 0;

//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var namedCtor = (function(cache){
		return function(name, fn) {
			return ((name in cache) ? cache[name] : cache[name] = new Function(
				"__", "function "+name+"(){return __.apply(this,arguments)};return "+name
			))( fn );
		};
	}({}));
}
//!steal-remove-end

/**
 * @add can-construct
 */
var Construct = function () {
	if (arguments.length) {
		return Construct.extend.apply(Construct, arguments);
	}
};

var canGetDescriptor;
try {
	canGetDescriptor = true;
} catch(e) {
	canGetDescriptor = false;
}

var getDescriptor = function(newProps, name) {
		var descriptor = Object.getOwnPropertyDescriptor(newProps, name);
		if(descriptor && (descriptor.get || descriptor.set)) {
			return descriptor;
		}
		return null;
	},
	inheritGetterSetter = function(newProps, oldProps, addTo) {
		addTo = addTo || newProps;
		var descriptor;

		for (var name in newProps) {
			if( (descriptor = getDescriptor(newProps, name)) ) {
				this._defineProperty(addTo, oldProps, name, descriptor);
			} else {
				Construct._overwrite(addTo, oldProps, name, newProps[name]);
			}
		}
	},
	simpleInherit = function (newProps, oldProps, addTo) {
		addTo = addTo || newProps;

		for (var name in newProps) {
			Construct._overwrite(addTo, oldProps, name, newProps[name]);
		}
	},
	defineNonEnumerable = function(obj, prop, value) {
		Object.defineProperty(obj, prop, {
			configurable: true,
			writable: true,
			enumerable: false,
			value: value
		});
	};
/**
 * @static
 */
canReflect_1_19_2_canReflect.assignMap(Construct, {
	/**
	 * @property {Boolean} can-construct.constructorExtends constructorExtends
	 * @parent can-construct.static
	 *
	 * @description
	 * Toggles the behavior of a constructor function called
	 * without the `new` keyword to extend the constructor function or
	 * create a new instance.
	 *
	 * ```js
	 * var animal = Animal();
	 * // vs
	 * var animal = new Animal();
	 * ```
	 *
	 * @body
	 *
	 * If `constructorExtends` is:
	 *
	 *  - `true` - the constructor extends
	 *  - `false` - a new instance of the constructor is created
	 *
	 * This property defaults to false.
	 *
	 * Example of constructExtends as `true`:
	 *
	 * ```js
	 * var Animal = Construct.extend({
	 *   constructorExtends: true // the constructor extends
	 * },{
	 *   sayHi: function() {
	 *     console.log("hai!");
	 *   }
	 * });
	 *
	 * var Pony = Animal({
	 *   gallop: function () {
	 *      console.log("Galloping!!");
	 *   }
	 * }); // Pony is now a constructor function extended from Animal
	 *
	 * var frank = new Animal(); // frank is a new instance of Animal
	 *
	 * var gertrude = new Pony(); // gertrude is a new instance of Pony
	 * gertrude.sayHi(); // "hai!" - sayHi is "inherited" from Animal
	 * gertrude.gallop(); // "Galloping!!" - gallop is unique to instances of Pony
	 *```
	 *
	 * The default behavior is shown in the example below:
	 *
	 * ```js
	 * var Animal = Construct.extend({
	 *   constructorExtends: false // the constructor does NOT extend
	 * },{
	 *   sayHi: function() {
	 *     console.log("hai!");
	 *   }
	 * });
	 *
	 * var pony = Animal(); // pony is a new instance of Animal
	 * var frank = new Animal(); // frank is a new instance of Animal
	 *
	 * pony.sayHi() // "hai!"
	 * frank.sayHi() // "hai!"
	 *```
	 * By default to extend a constructor, you must use [can-construct.extend extend].
	 */
	constructorExtends: true,

	// This is a hook for adding legacy behaviors
	_created: function(){},
	/**
	 * @function can-construct.newInstance newInstance
	 * @parent can-construct.static
	 *
	 * @description Returns an instance of `Construct`. This method
	 * can be overridden to return a cached instance.
	 *
	 * @signature `Construct.newInstance([...args])`
	 *
	 * @param {*} [args] arguments that get passed to [can-construct::setup] and [can-construct::init]. Note
	 * that if [can-construct::setup] returns an array, those arguments will be passed to [can-construct::init]
	 * instead.
	 * @return {class} instance of the class
	 *
	 * @body
	 * Creates a new instance of the constructor function. This method is useful for creating new instances
	 * with arbitrary parameters. Typically, however, you will simply want to call the constructor with the
	 * __new__ operator.
	 *
	 * ## Example
	 *
	 * The following creates a `Person` Construct and overrides `newInstance` to cache all
	 * instances of Person to prevent duplication. If the properties of a new Person match an existing one it
	 * will return a reference to the previously created object, otherwise it returns a new object entirely.
	 *
	 * ```js
	 * // define and create the Person constructor
	 * var Person = Construct.extend({
	 *   init : function(first, middle, last) {
	 *     this.first = first;
	 *     this.middle = middle;
	 *     this.last = last;
	 *   }
	 * });
	 *
	 * // store a reference to the original newInstance function
	 * var _newInstance = Person.newInstance;
	 *
	 * // override Person's newInstance function
	 * Person.newInstance = function() {
	 *   // if cache does not exist make it an new object
	 *   this.__cache = this.__cache || {};
	 *   // id is a stingified version of the passed arguments
	 *   var id = JSON.stringify(arguments);
	 *
	 *   // look in the cache to see if the object already exists
	 *   var cachedInst = this.__cache[id];
	 *   if(cachedInst) {
	 *     return cachedInst;
	 *   }
	 *
	 *   //otherwise call the original newInstance function and return a new instance of Person.
	 *   var newInst = _newInstance.apply(this, arguments);
	 *   this.__cache[id] = newInst;
	 *   return newInst;
	 * };
	 *
	 * // create two instances with the same arguments
	 * var justin = new Person('Justin', 'Barry', 'Meyer'),
	 *		brian = new Person('Justin', 'Barry', 'Meyer');
	 *
	 * console.log(justin === brian); // true - both are references to the same instance
	 * ```
	 *
	 */
	newInstance: function () {
		// Get a raw instance object (`init` is not called).
		var inst = this.instance(),
			args;
		// Call `setup` if there is a `setup`
		if (inst.setup) {
			Object.defineProperty(inst,"__inSetup",{
				configurable: true,
				enumerable: false,
				value: true,
				writable: true
			});
			Object.defineProperty(inst, inSetupSymbol, {
				configurable: true,
				enumerable: false,
				value: true,
				writable: true
			});
			args = inst.setup.apply(inst, arguments);
			if (args instanceof Construct.ReturnValue){
				return args.value;
			}
			inst.__inSetup = false;
			inst[inSetupSymbol] = false;
		}
		// Call `init` if there is an `init`
		// If `setup` returned `args`, use those as the arguments
		if (inst.init) {
			inst.init.apply(inst, args || arguments);
		}
		return inst;
	},
	// Overwrites an object with methods. Used in the `super` plugin.
	// `newProps` - New properties to add.
	// `oldProps` - Where the old properties might be (used with `super`).
	// `addTo` - What we are adding to.
	_inherit: canGetDescriptor ? inheritGetterSetter : simpleInherit,

	// Adds a `defineProperty` with the given name and descriptor
	// Will only ever be called if ES5 is supported
	_defineProperty: function(what, oldProps, propName, descriptor) {
		Object.defineProperty(what, propName, descriptor);
	},

	// used for overwriting a single property.
	// this should be used for patching other objects
	// the super plugin overwrites this
	_overwrite: function (what, oldProps, propName, val) {
		Object.defineProperty(what, propName, {value: val, configurable: true, enumerable: true, writable: true});
	},
	// Set `defaults` as the merger of the parent `defaults` and this
	// object's `defaults`. If you overwrite this method, make sure to
	// include option merging logic.
	/**
	 * @function can-construct.setup setup
	 * @parent can-construct.static
	 *
	 * @description Perform initialization logic for a constructor function.
	 *
	 * @signature `Construct.setup(base, fullName, staticProps, protoProps)`
	 *
	 * A static `setup` method provides inheritable setup functionality
	 * for a Constructor function. The following example
	 * creates a Group constructor function.  Any constructor
	 * functions that inherit from Group will be added to
	 * `Group.childGroups`.
	 *
	 * ```js
	 * Group = Construct.extend({
	 *   setup: function(Construct, fullName, staticProps, protoProps){
	 *     this.childGroups = [];
	 *     if(Construct !== Construct){
	 *       this.childGroups.push(Construct)
	 *     }
	 *     Construct.setup.apply(this, arguments)
	 *   }
	 * },{})
	 * var Flock = Group.extend(...)
	 * Group.childGroups[0] //-> Flock
	 * ```
	 * @param {constructor} base The base constructor that is being inherited from.
	 * @param {String} fullName The name of the new constructor.
	 * @param {Object} staticProps The static properties of the new constructor.
	 * @param {Object} protoProps The prototype properties of the new constructor.
	 *
	 * @body
	 * The static `setup` method is called immediately after a constructor
	 * function is created and
	 * set to inherit from its base constructor. It is useful for setting up
	 * additional inheritance work.
	 * Do not confuse this with the prototype `[can-construct::setup]` method.
	 *
	 * ## Example
	 *
	 * This `Parent` class adds a reference to its base class to itself, and
	 * so do all the classes that inherit from it.
	 *
	 * ```js
	 * Parent = Construct.extend({
	 *   setup : function(base, fullName, staticProps, protoProps){
	 *     this.base = base;
	 *
	 *     // call base functionality
	 *     Construct.setup.apply(this, arguments)
	 *   }
	 * },{});
	 *
	 * Parent.base; // Construct
	 *
	 * Child = Parent({});
	 *
	 * Child.base; // Parent
	 * ```
	 */
	setup: function (base) {
		var defaults = base.defaults ? canReflect_1_19_2_canReflect.serialize(base.defaults) : {};
		this.defaults = canReflect_1_19_2_canReflect.assignDeepMap(defaults,this.defaults);
	},
	// Create's a new `class` instance without initializing by setting the
	// `initializing` flag.
	instance: function () {
		// Prevents running `init`.
		initializing = 1;
		var inst = new this();
		// Allow running `init`.
		initializing = 0;
		return inst;
	},
	// Extends classes.
	/**
	 * @function can-construct.extend extend
	 * @parent can-construct.static
	 *
	 * @signature `Construct.extend([name,] [staticProperties,] instanceProperties)`
	 *
	 * Extends `Construct`, or constructor functions derived from `Construct`,
	 * to create a new constructor function. Example:
	 *
	 * ```js
	 * var Animal = Construct.extend({
	 *   sayHi: function(){
	 *     console.log("hi")
	 *   }
	 * });
	 *
	 * var animal = new Animal()
	 * animal.sayHi();
	 * ```
	 *
	 * @param {String} [name] Adds a name to the constructor function so
	 * it is nicely labeled in the developer tools. The following:
	 *
	 *     Construct.extend("ConstructorName",{})
	 *
	 * returns a constructur function that will show up as `ConstructorName`
	 * in the developer tools.
	 * It also sets "ConstructorName" as [can-construct.shortName shortName].
	 *
	 * @param {Object} [staticProperties] Properties that are added the constructor
	 * function directly. For example:
	 *
	 * ```js
	 * var Animal = Construct.extend({
	 *   findAll: function(){
	 *     return can.ajax({url: "/animals"})
	 *   }
	 * },{}); // need to pass an empty instanceProperties object
	 *
	 * Animal.findAll().then(function(json){ ... })
	 * ```
	 *
	 * The [can-construct.setup static setup] method can be used to
	 * specify inheritable behavior when a Constructor function is created.
	 *
	 * @param {Object} instanceProperties Properties that belong to
	 * instances made with the constructor. These properties are added to the
	 * constructor's `prototype` object. Example:
	 *
	 *     var Animal = Construct.extend({
	 *		  findAll: function() {
	 *			return can.ajax({url: "/animals"});
	 *		  }
	 *     },{
	 *       init: function(name) {
	 *         this.name = name;
	 *       },
	 *       sayHi: function() {
	 *         console.log(this.name," says hai!");
	 *       }
	 *     })
	 *     var pony = new Animal("Gertrude");
	 *     pony.sayHi(); // "Gertrude says hai!"
	 *
	 * The [can-construct::init init] and [can-construct::setup setup] properties
	 * are used for initialization.
	 *
	 * @return {function} The constructor function.
	 *
	 * ```js
	 *	var Animal = Construct.extend(...);
	 *	var pony = new Animal(); // Animal is a constructor function
	 * ```
	 * @body
	 * ## Inheritance
	 * Creating "subclasses" with `Construct` is simple. All you need to do is call the base constructor
	 * with the new function's static and instance properties. For example, we want our `Snake` to
	 * be an `Animal`, but there are some differences:
	 *
	 *
	 *     var Snake = Animal.extend({
	 *         legs: 0
	 *     }, {
	 *         init: function() {
	 *             Animal.prototype.init.call(this, 'ssssss');
	 *         },
	 *         slither: function() {
	 *             console.log('slithering...');
	 *         }
	 *     });
	 *
	 *     var baslisk = new Snake();
	 *     baslisk.speak();   // "ssssss"
	 *     baslisk.slither(); // "slithering..."
	 *     baslisk instanceof Snake;  // true
	 *     baslisk instanceof Animal; // true
	 *
	 *
	 * ## Static properties and inheritance
	 *
	 * If you pass all three arguments to Construct, the second one will be attached directy to the
	 * constructor, allowing you to imitate static properties and functions. You can access these
	 * properties through the `[can-construct::constructor this.constructor]` property.
	 *
	 * Static properties can get overridden through inheritance just like instance properties. In the example below,
	 * we override both the legs static property as well as the the init function for each instance:
	 *
	 * ```js
	 * var Animal = Construct.extend({
	 *     legs: 4
	 * }, {
	 *     init: function(sound) {
	 *         this.sound = sound;
	 *     },
	 *     speak: function() {
	 *         console.log(this.sound);
	 *     }
	 * });
	 *
	 * var Snake = Animal.extend({
	 *     legs: 0
	 * }, {
	 *     init: function() {
	 *         this.sound = 'ssssss';
	 *     },
	 *     slither: function() {
	 *         console.log('slithering...');
	 *     }
	 * });
	 *
	 * Animal.legs; // 4
	 * Snake.legs; // 0
	 * var dog = new Animal('woof');
	 * var blackMamba = new Snake();
	 * dog.speak(); // 'woof'
	 * blackMamba.speak(); // 'ssssss'
	 * ```
	 *
	 * ## Alternative value for a new instance
	 *
	 * Sometimes you may want to return some custom value instead of a new object when creating an instance of your class.
	 * For example, you want your class to act as a singleton, or check whether an item with the given id was already
	 * created and return an existing one from your cache store (e.g. using [can-connect/constructor/store/store]).
	 *
	 * To achieve this you can return [can-construct.ReturnValue] from `setup` method of your class.
	 *
	 * Lets say you have `myStore` to cache all newly created instances. And if an item already exists you want to merge
	 * the new data into the existing instance and return the updated instance.
	 *
	 * ```
	 * var myStore = {};
	 *
	 * var Item = Construct.extend({
	 *     setup: function(params){
	 *         if (myStore[params.id]){
	 *             var item = myStore[params.id];
	 *
	 *             // Merge new data to the existing instance:
	 *             Object.assign(item, params);
	 *
	 *             // Return the updated item:
	 *             return new Construct.ReturnValue( item );
	 *         } else {
	 *             // Save to cache store:
	 *             myStore[this.id] = this;
	 *
	 *             return [params];
	 *         }
	 *     },
	 *     init: function(params){
	 *         Object.assign(this, params);
	 *     }
	 * });
	 *
	 * var item_1  = new Item( {id: 1, name: "One"} );
	 * var item_1a = new Item( {id: 1, name: "OnePlus"} )
	 * ```
	 */
	extend: function (name, staticProperties, instanceProperties) {
		var shortName = name,
			klass = staticProperties,
			proto = instanceProperties;

		// Figure out what was passed and normalize it.
		if (typeof shortName !== 'string') {
			proto = klass;
			klass = shortName;
			name = shortName = null;
		}
		if (!proto) {
			proto = klass;
			klass = null;
		}
		proto = proto || {};
		var _super_class = this,
			_super = this.prototype,
			Constructor, prototype;
		// Instantiate a base class (but only create the instance,
		// don't run the init constructor).
		prototype = this.instance();
		// Copy the properties over onto the new prototype.
		Construct._inherit(proto, _super, prototype);

		if(shortName) {

		} else if(klass && klass.shortName) {
			shortName = klass.shortName;
		} else if(this.shortName) {
			shortName = this.shortName;
		}
		// We want constructor.name to be the same as shortName, within
		// the bounds of what the JS VM will allow (meaning no non-word characters).
		// new Function() is significantly faster than eval() here.

		// Strip semicolons
		//!steal-remove-start
		// wrapping this var will cause "used out of scope." when linting
		var constructorName = shortName ? shortName.replace(constructorNameRegex, '_') : 'Constructor';
		if(process.env.NODE_ENV !== 'production') {
			if(reservedWords[constructorName]) {
				constructorName = CanString.capitalize(constructorName);
			}
		}
		//!steal-remove-end

		// The dummy class constructor.
		function init() {
			/* jshint validthis: true */
			// All construction is actually done in the init method.
			if (!initializing) {
				//!steal-remove-start
				if(process.env.NODE_ENV !== 'production') {
					if(!this || (this.constructor !== Constructor) &&
					// We are being called without `new` or we are extending.
					arguments.length && Constructor.constructorExtends) {
						dev.warn('can/construct/construct.js: extending a Construct without calling extend');
					}
				}
				//!steal-remove-end

				return (!this || this.constructor !== Constructor) &&
				// We are being called without `new` or we are extending.
				arguments.length && Constructor.constructorExtends ? Constructor.extend.apply(Constructor, arguments) :
				// We are being called with `new`.
				Constructor.newInstance.apply(Constructor, arguments);
			}
		}
		Constructor = typeof namedCtor === "function" ?
			namedCtor( constructorName, init ) :
			function() { return init.apply(this, arguments); };

		// Copy old stuff onto class (can probably be merged w/ inherit)
		for (var propName in _super_class) {
			if (_super_class.hasOwnProperty(propName)) {
				Constructor[propName] = _super_class[propName];
			}
		}
		// Copy new static properties on class.
		Construct._inherit(klass, _super_class, Constructor);

		// Set things that shouldn't be overwritten.
		canReflect_1_19_2_canReflect.assignMap(Constructor, {
			constructor: Constructor,
			prototype: prototype
			/**
			 * @property {String} can-construct.shortName shortName
			 * @parent can-construct.static
			 *
			 * If you pass a name when creating a Construct, the `shortName` property will be set to the
			 * name.
			 *
			 * ```js
			 * var MyConstructor = Construct.extend("MyConstructor",{},{});
			 * MyConstructor.shortName // "MyConstructor"
			 * ```
			 */
		});

		if (shortName !== undefined) {
			if (Object.getOwnPropertyDescriptor) {
				var desc = Object.getOwnPropertyDescriptor(Constructor, 'name');
				if (!desc || desc.configurable) {
					Object.defineProperty(
						Constructor,
						'name',
						{ writable: true, value: shortName, configurable: true }
					);
				}
			}
			Constructor.shortName = shortName;
		}
		// Make sure our prototype looks nice.
		defineNonEnumerable(Constructor.prototype, "constructor", Constructor);

		// Global callback for legacy behaviors
		Construct._created(name, Constructor);

		// Call the class `setup` and `init`
		var t = [_super_class].concat(Array.prototype.slice.call(arguments)),
			args = Constructor.setup.apply(Constructor, t);
		if (Constructor.init) {
			Constructor.init.apply(Constructor, args || t);
		}
		/**
		 * @prototype
		 */
		return Constructor; //
		/**
		 * @property {Object} can-construct.prototype.constructor constructor
		 * @parent can-construct.prototype
		 *
		 * A reference to the constructor function that created the instance. This allows you to access
		 * the constructor's static properties from an instance.
		 *
		 * @body
		 * ## Example
		 *
		 * This Construct has a static counter that counts how many instances have been created:
		 *
		 * ```js
		 * var Counter = Construct.extend({
		 *     count: 0
		 * }, {
		 *     init: function() {
		 *         this.constructor.count++;
		 *     }
		 * });
		 *
		 * var childCounter = new Counter();
		 * console.log(childCounter.constructor.count); // 1
		 * console.log(Counter.count); // 1
		 * ```
		 */
	},
	/**
	 * @function can-construct.ReturnValue ReturnValue
	 * @parent can-construct.static
	 *
	 * Use to overwrite the return value of new Construct(...).
	 *
	 * @signature `new Construct.ReturnValue( value )`
	 *
	 *   This constructor function can be used for creating a return value of the `setup` method.
	 *   [can-construct] will check if the return value is an instance of `Construct.ReturnValue`.
	 *   If it is then its `value` will be used as the new instance.
	 *
	 *   @param {Object} value A value to be used for a new instance instead of a new object.
	 *
	 *   ```js
	 *   var Student = function( name, school ){
	 *       this.name = name;
	 *       this.school = school;
	 *   }
	 *
	 *   var Person = Construct.extend({
	 *       setup: function( options ){
	 *           if (options.school){
	 *               return new Constructor.ReturnValue( new Student( options.name, options.school ) );
	 *           } else {
	 *               return [options];
	 *           }
	 *       }
	 *   });
	 *
	 *   var myPerson = new Person( {name: "Ilya", school: "PetrSU"} );
	 *
	 *   myPerson instanceof Student // => true
	 *   ```
   */
	ReturnValue: function(value){
		this.value = value;
	}
});
/**
 * @function can-construct.prototype.setup setup
 * @parent can-construct.prototype
 *
 * @signature `construct.setup(...args)`
 *
 * A setup function for the instantiation of a constructor function.
 *
 * @param {*} args The arguments passed to the constructor.
 *
 * @return {Array|undefined|can-construct.ReturnValue} If an array is returned, the array's items are passed as
 * arguments to [can-construct::init init]. If a [can-construct.ReturnValue] instance is returned, the ReturnValue
 * instance's value will be returned as the result of calling new Construct(). The following example always makes
 * sure that init is called with a jQuery wrapped element:
 *
 * ```js
 * 	WidgetFactory = Construct.extend({
 * 			setup: function(element){
 * 					return [$(element)]
 * 			}
 * 	});
 *
 * 	MyWidget = WidgetFactory.extend({
 * 			init: function($el){
 * 					$el.html("My Widget!!")
 * 			}
 * 	});
 *  ```
 *
 * Otherwise, the arguments to the
 * constructor are passed to [can-construct::init] and the return value of `setup` is discarded.
 *
 * @body
 *
 * ## Deciding between `setup` and `init`
 *
 *
 * Usually, you should use [can-construct::init init] to do your constructor function's initialization.
 * You should, instead, use `setup` when:
 *
 *   - there is initialization code that you want to run before the inheriting constructor's
 *     `init` method is called.
 *   - there is initialization code that should run whether or not inheriting constructors
 *     call their base's `init` methods.
 *   - you want to modify the arguments that will get passed to `init`.
 *
 */
defineNonEnumerable(Construct.prototype, "setup", function () {});
/**
 * @function can-construct.prototype.init init
 * @parent can-construct.prototype
 *
 * @description Called when a new instance of a Construct is created.
 *
 * @signature `construct.init(...args)`
 * @param {*} args the arguments passed to the constructor (or the items of the array returned from [can-construct::setup])
 *
 * @body
 * If a prototype `init` method is provided, `init` is called when a new Construct is created---
 * after [can-construct::setup]. The `init` method is where the bulk of your initialization code
 * should go. A common thing to do in `init` is save the arguments passed into the constructor.
 *
 * ## Examples
 *
 * First, we'll make a Person constructor that has a first and last name:
 *
 * ```js
 * var Person = Construct.extend({
 *     init: function(first, last) {
 *         this.first = first;
 *         this.last  = last;
 *     }
 * });
 *
 * var justin = new Person("Justin", "Meyer");
 * justin.first; // "Justin"
 * justin.last; // "Meyer"
 * ```
 *
 * Then, we'll extend Person into Programmer, and add a favorite language:
 *
 * ```js
 * var Programmer = Person.extend({
 *     init: function(first, last, language) {
 *         // call base's init
 *         Person.prototype.init.apply(this, arguments);
 *
 *         // other initialization code
 *         this.language = language;
 *     },
 *     bio: function() {
 *         return "Hi! I'm " + this.first + " " + this.last +
 *             " and I write " + this.language + ".";
 *     }
 * });
 *
 * var brian = new Programmer("Brian", "Moschel", 'ECMAScript');
 * brian.bio(); // "Hi! I'm Brian Moschel and I write ECMAScript.";
 * ```
 *
 * ## Modified Arguments
 *
 * [can-construct::setup] is able to modify the arguments passed to `init`.
 * If you aren't receiving the arguments you passed to `new Construct(args)`,
 * check that they aren't being changed by `setup` along
 * the inheritance chain.
 */
defineNonEnumerable(Construct.prototype, "init", function () {});

var canConstruct_3_5_7_canConstruct = canNamespace_1_0_0_canNamespace.Construct = Construct;

function dispatch(key) {
	// jshint -W040
	var handlers = this.eventHandlers[key];
	if (handlers) {
		var handlersCopy = handlers.slice();
		var value = this.getKeyValue(key);
		for (var i = 0; i < handlersCopy.length; i++) {
			handlersCopy[i](value);
		}
	}
}

function Globals() {
	this.eventHandlers = {};
	this.properties = {};
}

/**
 * @function define 
 * @parent can-globals/methods
 * 
 * Create a new global environment variable.
 * 
 * @signature `globals.define(key, value[, cache])`
 * 
 * Defines a new global called `key`, who's value defaults to `value`.
 * 
 * The following example defines the `global` key's default value to the [`window`](https://developer.mozilla.org/en-US/docs/Web/API/Window) object:
 * ```javascript
 * globals.define('global', window);
 * globals.getKeyValue('window') //-> window
 * ```
 * 
 * If a function is provided and `cache` is falsy, that function is run every time the key value is read:
 * ```javascript
 * globals.define('isBrowserWindow', function() {
 *   console.log('EVALUATING')
 *   return typeof window !== 'undefined' &&
 *     typeof document !== 'undefined' && typeof SimpleDOM === 'undefined'
 * }, false);
 * globals.get('isBrowserWindow') // logs 'EVALUATING'
 *                                // -> true
 * globals.get('isBrowserWindow') // logs 'EVALUATING' again
 *                                // -> true
 * ```
 * 
 * If a function is provided and `cache` is truthy, that function is run only the first time the value is read:
 * ```javascript
 * globals.define('isWebkit', function() {
 *   console.log('EVALUATING')
 *   var div = document.createElement('div')
 *   return 'WebkitTransition' in div.style
 * })
 * globals.getKeyValue('isWebkit') // logs 'EVALUATING'
 * 								   // -> true
 * globals.getKeyValue('isWebkit') // Does NOT log again!
 * 								   // -> true
 * ```
 * 
 * @param {String} key
 * The key value to create.
 * 
 * @param {*} value
 * The default value. If this is a function, its return value will be used.
 * 
 * @param {Boolean} [cache=true]
 * Enable cache. If false the `value` function is run every time the key value is read.
 * 
 * @return {can-globals}
 * Returns the instance of `can-globals` for chaining.
 */
Globals.prototype.define = function (key, value, enableCache) {
	if (enableCache === undefined) {
		enableCache = true;
	}
	if (!this.properties[key]) {
		this.properties[key] = {
			default: value,
			value: value,
			enableCache: enableCache
		};
	}
	return this;
};

/**
 * @function getKeyValue 
 * @parent can-globals/methods
 * 
 * Get a global environment variable by name.
 * 
 * @signature `globals.getKeyValue(key)`
 * 
 * Returns the current value at `key`. If no value has been set, it will return the default value (if it is not a function). If the default value is a function, it will return the output of the function. This execution is cached if the cache flag was set on initialization.
 * 
 * ```javascript
 * globals.define('foo', 'bar');
 * globals.getKeyValue('foo'); //-> 'bar'
 * ```
 * 
 * @param {String} key
 * The key value to access.
 * 
 * @return {*}
 * Returns the value of a given key.
 */
Globals.prototype.getKeyValue = function (key) {
	var property = this.properties[key];
	if (property) {
		if (typeof property.value === 'function') {
			if (property.cachedValue) {
				return property.cachedValue;
			}
			if (property.enableCache) {
				property.cachedValue = property.value();
				return property.cachedValue;
			} else {
				return property.value();
			}
		}
		return property.value;
	}
};

Globals.prototype.makeExport = function (key) {
	return function (value) {
		if (arguments.length === 0) {
			return this.getKeyValue(key);
		}

		if (typeof value === 'undefined' || value === null) {
			this.deleteKeyValue(key);
		} else {
			if (typeof value === 'function') {
				this.setKeyValue(key, function () {
					return value;
				});
			} else {
				this.setKeyValue(key, value);
			}
			return value;
		}
	}.bind(this);
};

/**
 * @function offKeyValue 
 * @parent can-globals/methods
 * 
 * Remove handler from event queue.
 * 
 * @signature `globals.offKeyValue(key, handler)`
 * 
 * Removes `handler` from future change events for `key`.
 * 
 * 
 * ```javascript
 * var handler = (value) => {
 *   value === 'baz' //-> true
 * };
 * globals.define('foo', 'bar');
 * globals.onKeyValue('foo', handler);
 * globals.setKeyValue('foo', 'baz');
 * globals.offKeyValue('foo', handler);
 * ```
 * 
 * @param {String} key
 * The key value to observe.
 * 
 * @param {Function} handler([value])
 * The observer callback.
 * 
 * @return {can-globals}
 * Returns the instance of `can-globals` for chaining.
 */
Globals.prototype.offKeyValue = function (key, handler) {
	if (this.properties[key]) {
		var handlers = this.eventHandlers[key];
		if (handlers) {
			var i = handlers.indexOf(handler);
			handlers.splice(i, 1);
		}
	}
	return this;
};

/**
 * @function onKeyValue 
 * @parent can-globals/methods
 * 
 * Add handler to event queue.
 * 
 * @signature `globals.onKeyValue(key, handler)`
 * 
 * Calls `handler` each time the value of `key` is set or reset.
 * 
 * ```javascript
 * globals.define('foo', 'bar');
 * globals.onKeyValue('foo', (value) => {
 *   value === 'baz' //-> true
 * });
 * globals.setKeyValue('foo', 'baz');
 * ```
 * 
 * @param {String} key
 * The key value to observe.
 * 
 * @param {function(*)} handler([value])
 * The observer callback.
 * 
 * @return {can-globals}
 * Returns the instance of `can-globals` for chaining.
 */
Globals.prototype.onKeyValue = function (key, handler) {
	if (this.properties[key]) {
		if (!this.eventHandlers[key]) {
			this.eventHandlers[key] = [];
		}
		this.eventHandlers[key].push(handler);
	}
	return this;
};

/**
 * @function deleteKeyValue 
 * @parent can-globals/methods
 * 
 * Reset global environment variable.
 * 
 * @signature `globals.deleteKeyValue(key)`
 * 
 * Deletes the current value at `key`. Future `get`s will use the default value.
 * 
 * ```javascript
 * globals.define('global', window);
 * globals.setKeyValue('global', {});
 * globals.deleteKeyValue('global');
 * globals.getKeyValue('global') === window; //-> true
 * ```
 * 
 * @param {String} key
 * The key value to access.
 * 
 * @return {can-globals}
 * Returns the instance of `can-globals` for chaining.
 */
Globals.prototype.deleteKeyValue = function (key) {
	var property = this.properties[key];
	if (property !== undefined) {
		property.value = property.default;
		property.cachedValue = undefined;
		dispatch.call(this, key);
	}
	return this;
};

/**
 * @function setKeyValue 
 * @parent can-globals/methods
 * 
 * Overwrite an existing global environment variable.
 * 
 * @signature `globals.setKeyValue(key, value)`
 * 
 * ```javascript
 * globals.define('foo', 'bar');
 * globals.setKeyValue('foo', 'baz');
 * globals.getKeyValue('foo'); //-> 'baz'
 * ```
 * 
 * Sets the new value at `key`. Will override previously set values, but preserves the default (see `deleteKeyValue`).
 * 
 * Setting a key which was not previously defined will call `define` with the key and value.
 * 
 * @param {String} key
 * The key value to access.
 * 
 * @param {*} value
 * The new value.
 * 
 * @return {can-globals}
 * Returns the instance of `can-globals` for chaining.
 */
Globals.prototype.setKeyValue = function (key, value) {
	if (!this.properties[key]) {
		return this.define(key, value);
	}
	var property = this.properties[key];
	property.value = value;
	property.cachedValue = undefined;
	dispatch.call(this, key);
	return this;
};

/**
 * @function reset 
 * @parent can-globals/methods
 * 
 * Reset all keys to their default value and clear their caches.
 * 
 * @signature `globals.setKeyValue(key, value)`
 * 
 * ```javascript
 * globals.define('foo', 'bar');
 * globals.setKeyValue('foo', 'baz');
 * globals.getKeyValue('foo'); //-> 'baz'
 * globals.reset();
 * globals.getKeyValue('foo'); //-> 'bar'
 * ```
 * 
 * @return {can-globals}
 * Returns the instance of `can-globals` for chaining.
 */
Globals.prototype.reset = function () {
	for (var key in this.properties) {
		if (this.properties.hasOwnProperty(key)) {
			this.properties[key].value = this.properties[key].default;
			this.properties[key].cachedValue = undefined;
			dispatch.call(this, key);
		}
	}
	return this;
};

canReflect_1_19_2_canReflect.assignSymbols(Globals.prototype, {
	'can.getKeyValue': Globals.prototype.getKeyValue,
	'can.setKeyValue': Globals.prototype.setKeyValue,
	'can.deleteKeyValue': Globals.prototype.deleteKeyValue,
	'can.onKeyValue': Globals.prototype.onKeyValue,
	'can.offKeyValue': Globals.prototype.offKeyValue
});

var canGlobals_1_2_2_canGlobalsProto = Globals;

var canGlobals_1_2_2_canGlobalsInstance = createCommonjsModule(function (module) {


var globals = new canGlobals_1_2_2_canGlobalsProto();

if (canNamespace_1_0_0_canNamespace.globals) {
	throw new Error("You can't have two versions of can-globals, check your dependencies");
} else {
	module.exports = canNamespace_1_0_0_canNamespace.globals = globals;
}
});

/* global self */
/* global WorkerGlobalScope */



/**
 * @module {function} can-globals/global/global global
 * @parent can-globals/modules
 * 
 * Get the global object for the current context.
 * 
 * @signature `GLOBAL([newGlobal])`
 *
 * Optionally sets, and returns the global that this environment provides. It will be one of:
 * 
 * ```js
 * var GLOBAL = require('can-globals/global/global');
 * var g = GLOBAL();
 * // In a browser
 * console.log(g === window); // -> true
 * ```
 *
 * - **Browser**: [`window`](https://developer.mozilla.org/en-US/docs/Web/API/window)
 * - **Web Worker**: [`self`](https://developer.mozilla.org/en-US/docs/Web/API/Window/self)
 * - **Node.js**: [`global`](https://nodejs.org/api/globals.html#globals_global)
 * 
 * @param {Object} [newGlobal] An optional global-like object to set as the context's global 
 *
 * @return {Object} The global object for this JavaScript environment.
 */
canGlobals_1_2_2_canGlobalsInstance.define('global', function(){
	// Web Worker
	return (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) ? self :

		// Node.js
		typeof process === 'object' &&
		{}.toString.call(process) === '[object process]' ? commonjsGlobal :

		// Browser window
		window;
});

var global_1 = canGlobals_1_2_2_canGlobalsInstance.makeExport('global');

/**
 * @module {function} can-globals/document/document document
 * @parent can-globals/modules
 * 
 * Get the global [`document`](https://developer.mozilla.org/en-US/docs/Web/API/document) object for the current context.
 * 
 * @signature `DOCUMENT([newDocument])`
 * 
 * Optionally sets, and returns, the [`document`](https://developer.mozilla.org/en-US/docs/Web/API/document) object for the context.
 * 
 * ```js
 * var documentShim = { getElementById() {...} };
 * var DOCUMENT = require('can-globals/document/document');
 * DOCUMENT(documentShim); //-> document
 * DOCUMENT().getElementById('foo');
 * ```
 *
 * @param {Object} [newDocument] An optional document-like object to set as the context's document 
 * 
 * @return {Object} The window object for this JavaScript environment.
 */
canGlobals_1_2_2_canGlobalsInstance.define('document', function(){
	return canGlobals_1_2_2_canGlobalsInstance.getKeyValue('global').document;
});

var document$1 = canGlobals_1_2_2_canGlobalsInstance.makeExport('document');

/**
 * @module {function} can-globals/is-node/is-node is-node
 * @parent can-globals/modules
 * @description Determines if your code is running in [Node.js](https://nodejs.org).
 * @signature `isNode()`
 *
 * ```js
 * var isNode = require("can-globals/is-node/is-node");
 * var GLOBAL = require("can-globals/global/global");
 *
 * if(isNode()) {
 *   console.log(GLOBAL() === global); // -> true
 * }
 * ```
 *
 * @return {Boolean} True if running in Node.js
 */

canGlobals_1_2_2_canGlobalsInstance.define('isNode', function(){
	return typeof process === "object" &&
		{}.toString.call(process) === "[object process]";
});

var isNode = canGlobals_1_2_2_canGlobalsInstance.makeExport('isNode');

// This module depends on isNode being defined


/**
 * @module {function} can-globals/is-browser-window/is-browser-window is-browser-window
 * @parent can-globals/modules
 * @signature `isBrowserWindow()`
 *
 * Returns `true` if the code is running within a Browser window. Use this function if you need special code paths for when running in a Browser window, a Web Worker, or another environment (such as Node.js).
 *
 * ```js
 * var isBrowserWindow = require("can-globals/is-browser-window/is-browser-window");
 * var GLOBAL = require("can-globals/global/global");
 *
 * if(isBrowserWindow()) {
 *   console.log(GLOBAL() === window); // -> true
 * }
 * ```
 *
 * @return {Boolean} True if the environment is a Browser window.
 */

canGlobals_1_2_2_canGlobalsInstance.define('isBrowserWindow', function(){
	var isNode = canGlobals_1_2_2_canGlobalsInstance.getKeyValue('isNode');
	return typeof window !== "undefined" &&
		typeof document !== "undefined" &&
		isNode === false;
});

var isBrowserWindow = canGlobals_1_2_2_canGlobalsInstance.makeExport('isBrowserWindow');

function getTargetDocument (target) {
	return target.ownerDocument || document$1();
}

function createEvent (target, eventData, bubbles, cancelable) {
	var doc = getTargetDocument(target);
	var event = doc.createEvent('HTMLEvents');
	var eventType;
	if (typeof eventData === 'string') {
		eventType = eventData;
	} else {
		eventType = eventData.type;
		for (var prop in eventData) {
			if (event[prop] === undefined) {
				event[prop] = eventData[prop];
			}
		}
	}
	if (bubbles === undefined) {
		bubbles = true;
	}
	event.initEvent(eventType, bubbles, cancelable);
	return event;
}

// We do not account for all EventTarget classes,
// only EventTarget DOM nodes, fragments, and the window.
function isDomEventTarget (obj) {
	if (!(obj && obj.nodeName)) {
		return obj === window;
	}
	var nodeType = obj.nodeType;
	return (
		nodeType === 1 || // Node.ELEMENT_NODE
		nodeType === 9 || // Node.DOCUMENT_NODE
		nodeType === 11 // Node.DOCUMENT_FRAGMENT_NODE
	);
}

function addDomContext (context, args) {
	if (isDomEventTarget(context)) {
		args = Array.prototype.slice.call(args, 0);
		args.unshift(context);
	}
	return args;
}

function removeDomContext (context, args) {
	if (!isDomEventTarget(context)) {
		args = Array.prototype.slice.call(args, 0);
		context = args.shift();
	}
	return {
		context: context,
		args: args
	};
}

var fixSyntheticEventsOnDisabled = false;
// In FireFox, dispatching a synthetic event on a disabled element throws an error.
// Other browsers, like IE 10 do not dispatch synthetic events on disabled elements at all.
// This determines if we have to work around that when dispatching events.
// https://bugzilla.mozilla.org/show_bug.cgi?id=329509
(function() {
	if(!isBrowserWindow()) {
		return;
	}

	var testEventName = 'fix_synthetic_events_on_disabled_test';
	var input = document.createElement("input");
	input.disabled = true;
	var timer = setTimeout(function() {
		fixSyntheticEventsOnDisabled = true;
	}, 50);
	var onTest = function onTest (){
		clearTimeout(timer);
		input.removeEventListener(testEventName, onTest);
	};
	input.addEventListener(testEventName, onTest);
	try {
		var event = document.create('HTMLEvents');
		event.initEvent(testEventName, false);
		input.dispatchEvent(event);
	} catch(e) {
		onTest();
		fixSyntheticEventsOnDisabled = true;
	}
})();

function isDispatchingOnDisabled(element, event) {
	var eventType = event.type;
	var isInsertedOrRemoved = eventType === 'inserted' || eventType === 'removed';
	var isDisabled = !!element.disabled;
	return isInsertedOrRemoved && isDisabled;
}

function forceEnabledForDispatch (element, event) {
	return fixSyntheticEventsOnDisabled && isDispatchingOnDisabled(element, event);
}

var util = {
	createEvent: createEvent,
	addDomContext: addDomContext,
	removeDomContext: removeDomContext,
	isDomEventTarget: isDomEventTarget,
	getTargetDocument: getTargetDocument,
	forceEnabledForDispatch: forceEnabledForDispatch
};

function EventRegistry () {
	this._registry = {};
}

/**
 * @module can-dom-events/helpers/make-event-registry
 * @parent can-dom-events.helpers
 * @description Create an event registry.
 * @signature `makeEventRegistry()`
 *   @return {can-dom-events/EventRegistry}
 * @hide
 * 
 * @body
 *
 * ```js
 * var makeEventRegistry = require('can-dom-events/helpers/make-event-registry');
 * var registry = makeEventRegistry();
 *
 * var radioChange = require('can-events-dom-radiochange');
 * var removeRadioChange = registry.add(radioChange);
 *
 * registry.has('radiochange'); // => true
 * registry.get('radiochange'); // => radioChange
 *
 * removeRadioChange();
 * ```
 */
var makeEventRegistry = function makeEventRegistry () {
	return new EventRegistry();
};

/**
 * @function make-event-registry.has eventRegistry.has
 *
 * Check whether an event type has already been registered.
 *
 * @signature `eventRegistry.has( eventType )`
 * @parent can-dom-events/EventRegistry
 * @param {String} eventType The event type for which to check.
 * @return {Boolean} Whether the event type is registered.
*/
EventRegistry.prototype.has = function (eventType) {
	return !!this._registry[eventType];
};

/**
 * @function make-event-registry.get eventRegistry.get
 *
 * Retrieve an event type which has already been registered.
 *
 * @signature `eventRegistry.get( eventType )`
 * @parent can-dom-events/EventRegistry
 * @param {String} eventType The event type for which to retrieve.
 * @return {EventDefinition} The registered event definition, or undefined if unregistered.
*/
EventRegistry.prototype.get = function (eventType) {
	return this._registry[eventType];
};

/**
 * @function make-event-registry.add eventRegistry.add
 *
 * Add an event to the registry.
 *
 * @signature `eventRegistry.add( event [, eventType ] )`
 * @parent can-dom-events/EventRegistry
 * @param {EventDefinition} event The event definition to register.
 * @param {String} eventType The event type with which to register the event.
 * @return {function} The callback to remove the event from the registry.
*/
EventRegistry.prototype.add = function (event, eventType) {
	if (!event) {
		throw new Error('An EventDefinition must be provided');
	}
	if (typeof event.addEventListener !== 'function') {
		throw new TypeError('EventDefinition addEventListener must be a function');
	}
	if (typeof event.removeEventListener !== 'function') {
		throw new TypeError('EventDefinition removeEventListener must be a function');
	}

	eventType = eventType || event.defaultEventType;
	if (typeof eventType !== 'string') {
		throw new TypeError('Event type must be a string, not ' + eventType);
	}

	if (this.has(eventType)) {
		if (process.env.NODE_ENV !== 'production') {
				dev.warn('Event "' + eventType + '" is already registered');
				return;
		}

		throw new Error('Event "' + eventType + '" is already registered');
	}

	this._registry[eventType] = event;
	var self = this;
	return function remove () {
		self._registry[eventType] = undefined;
	};
};

// Some events do not bubble, so delegating them requires registering the handler in the
// capturing phase.
// http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html
var useCapture = function(eventType) {
	return eventType === 'focus' || eventType === 'blur';
};

function makeDelegator (domEvents) {
	var Delegator = function Delegator (parentKey){
		this.element = parentKey; // HTMLElement
		this.events = {}; // {[eventType: string]: Array<(event) -> void>}
		this.delegated = {}; // {[eventType: string]: (event) -> void}
	};

	canReflect_1_19_2_canReflect.assignSymbols( Delegator.prototype, {
		"can.setKeyValue": function(eventType, handlersBySelector){
			var handler = this.delegated[eventType] = function(ev){
				var cur = ev.target;
				var propagate = true;
				var origStopPropagation = ev.stopPropagation;
				ev.stopPropagation = function() {
					origStopPropagation.apply(this, arguments);
					propagate = false;
				};
				var origStopImmediatePropagation = ev.stopImmediatePropagation;
				ev.stopImmediatePropagation = function() {
					origStopImmediatePropagation.apply(this, arguments);
					propagate = false;
				};
				do {
					// document does not implement `.matches` but documentElement does
					var el = cur === document ? document.documentElement : cur;
					var matches = el.matches || el.msMatchesSelector;

					canReflect_1_19_2_canReflect.each(handlersBySelector, function(handlers, selector){
						// Text and comment nodes may be included in mutation event targets
						//  but will never match selectors (and do not implement matches)
						if (matches && matches.call(el, selector)) {
							handlers.forEach(function(handler){
								handler.call(el, ev);
							});
						}
					});
					// since `el` points to `documentElement` when `cur` === document,
					// we need to continue using `cur` as the loop pointer, otherwhise
					// it will never end as documentElement.parentNode === document
					cur = cur.parentNode;
				} while ((cur && cur !== ev.currentTarget) && propagate);
			};
			this.events[eventType] = handlersBySelector;
			domEvents.addEventListener(this.element, eventType, handler, useCapture(eventType));
		},
		"can.getKeyValue": function(eventType) {
			return this.events[eventType];
		},
		"can.deleteKeyValue": function(eventType) {
			domEvents.removeEventListener(this.element, eventType, this.delegated[eventType], useCapture(eventType));
			delete this.delegated[eventType];
			delete this.events[eventType];
		},
		"can.getOwnEnumerableKeys": function() {
			return Object.keys(this.events);
		}
	});

	return Delegator;
}

var MakeDelegateEventTree = function makeDelegateEventTree (domEvents) {
	var Delegator = makeDelegator(domEvents);
	return new canKeyTree_1_2_2_canKeyTree([Map, Delegator, Object, Array]);
};

var domEvents = {
	_eventRegistry: makeEventRegistry(),

	/**
	* @function can-dom-events.addEvent addEvent
	* @parent can-dom-events.static
	*
	* Add a custom event to the global event registry.
	*
	* @signature `addEvent( event [, eventType ] )`
	*
	* ```js
	* var removeReturnEvent = domEvents.addEvent(enterEvent, "return");
	* ```
	*
	* @param {can-dom-events/EventDefinition} event The custom event definition.
	* @param {String} eventType The event type to associated with the custom event.
	* @return {function} The callback to remove the custom event from the registry.
	*/
	addEvent: function(event, eventType) {
		return this._eventRegistry.add(event, eventType);
	},

	/**
	* @function can-dom-events.addEventListener addEventListener
	*
	* Add an event listener for eventType to the target.
	*
	* @signature `addEventListener( target, eventType, ...eventArgs )`
	* @parent can-dom-events.static
	* @param {DomEventTarget} target The object to which to add the listener.
	* @param {String} eventType The event type with which to register.
	* @param {*} eventArgs The arguments which configure the associated event's behavior. This is usually a
	* function event handler.
	*/
	addEventListener: function(target, eventType) {
		var hasCustomEvent = domEvents._eventRegistry.has(eventType);
		if (hasCustomEvent) {
			var event = domEvents._eventRegistry.get(eventType);
			return event.addEventListener.apply(domEvents, arguments);
		}

		var eventArgs = Array.prototype.slice.call(arguments, 1);
		return target.addEventListener.apply(target, eventArgs);
	},

	/**
	* @function can-dom-events.removeEventListener removeEventListener
	*
	* Remove an event listener for eventType from the target.
	*
	* @signature `removeEventListener( target, eventType, ...eventArgs )`
	* @parent can-dom-events.static
	* @param {DomEventTarget} target The object from which to remove the listener.
	* @param {String} eventType The event type with which to unregister.
	* @param {*} eventArgs The arguments which configure the associated event's behavior. This is usually a
	* function event handler.
	*/
	removeEventListener: function(target, eventType) {
		var hasCustomEvent = domEvents._eventRegistry.has(eventType);
		if (hasCustomEvent) {
			var event = domEvents._eventRegistry.get(eventType);
			return event.removeEventListener.apply(domEvents, arguments);
		}

		var eventArgs = Array.prototype.slice.call(arguments, 1);
		return target.removeEventListener.apply(target, eventArgs);
	},

	/**
	* @function can-dom-events.addDelegateListener addDelegateListener
	*
	* Attach a handler for an event for all elements that match the selector,
	* now or in the future, based on a root element.
	*
	* @signature `addDelegateListener( target, eventType, selector, handler )`
	*
	* ```js
	* // Prevents all anchor elements from changing the page
	* domEvents.addDelegateListener(document.body,"click", "a", function(event){
	*   event.preventDefault();
	* })
	* ```
	* @parent can-dom-events.static
	* @param {DomEventTarget} root The html element to listen to events that match selector within.
	* @param {String} eventType The event name to listen to.
	* @param {String} selector A selector to filter the elements that trigger the event.
	* @param {function} handler A function to execute at the time the event is triggered.
	*/
	addDelegateListener: function(root, eventType, selector, handler) {
		domEvents._eventTree.add([root, eventType, selector, handler]);
	},
	/**
	* @function can-dom-events.removeDelegateListener removeDelegateListener
	*
	* Remove a handler for an event for all elements that match the selector.
	*
	* @signature `removeDelegateListener( target, eventType, selector, handler )`
	*
	* ```js
	* // Prevents all anchor elements from changing the page
	* function handler(event) {
	*   event.preventDefault();
	* }
	* domEvents.addDelegateListener(document.body,"click", "a", handler);
	*
	* domEvents.removeDelegateListener(document.body,"click", "a", handler);
	* ```
	* @parent can-dom-events.static
	* @param {DomEventTarget} root The html element to listen to events that match selector within.
	* @param {String} eventType The event name to listen to.
	* @param {String} selector A selector to filter the elements that trigger the event.
	* @param {function} handler A function that was previously passed to `addDelegateListener`.
	*/
	removeDelegateListener: function(target, eventType, selector, handler) {
		domEvents._eventTree.delete([target, eventType, selector, handler]);
	},

	/**
	* @function can-dom-events.dispatch dispatch
	*
	* Create and dispatch a configured event on the target.
	*
	* @signature `dispatch( target, eventData [, bubbles ][, cancelable ] )`
	* @parent can-dom-events.static
	* @param {DomEventTarget} target The object on which to dispatch the event.
	* @param {Object | String} eventData The data to be assigned to the event. If it is a string, that will be the event type.
	* @param {Boolean} bubbles Whether the event should bubble; defaults to true.
	* @param {Boolean} cancelable Whether the event can be cancelled; defaults to false.
	* @return {Boolean} notCancelled Whether the event dispatched without being cancelled.
	*/
	dispatch: function(target, eventData, bubbles, cancelable) {
		var event = util.createEvent(target, eventData, bubbles, cancelable);
		var enableForDispatch = util.forceEnabledForDispatch(target, event);
		if(enableForDispatch) {
			target.disabled = false;
		}

		var ret = target.dispatchEvent(event);
		if(enableForDispatch) {
			target.disabled = true;
		}

		return ret;
	}
};

domEvents._eventTree = MakeDelegateEventTree(domEvents);





var canDomEvents_1_3_13_canDomEvents = canNamespace_1_0_0_canNamespace.domEvents = domEvents;

/**
 * @module {function} can-event-queue/map/map
 * @parent can-event-queue
 * @templateRender true
 *
 * @description Mixin methods and symbols to make this object or prototype object
 * behave like a key-value observable.
 *
 * @signature `mixinMapBindings( obj )`
 *
 * Adds symbols and methods that make `obj` or instances having `obj` on their prototype
 * behave like key-value observables.
 *
 * When `mixinMapBindings` is called on an `obj` like:
 *
 * ```js
 * var mixinMapBindings = require("can-event-queue/map/map");
 *
 * var observable = mixinValueBindings({});
 *
 * observable.on("prop",function(ev, newVal, oldVal){
 *   console.log(newVal);
 * });
 *
 * observable[canSymbol.for("can.dispatch")]("prop",[2,1]);
 * // Logs: 2
 * ```
 *
 * `mixinMapBindings` adds the following properties and symbols to the object:
 *
 * {{#each (getChildren [can-event-queue/map/map])}}
 * - [{{name}}] - {{description}}{{/each}}
 *
 * Furthermore, `mixinMapBindings` looks for the following symbols on the object's `.constructor`
 * property:
 *
 * - `@can.dispatchInstanceBoundChange` - Called when the bind status of an instance changes.
 * - `@can.dispatchInstanceOnPatches` - Called if [can-event-queue/map/map.dispatch] is called with `event.patches` as an array of
 *   patches.
 */







var isDomEventTarget$1 = util.isDomEventTarget;



var metaSymbol = canSymbol_1_7_0_canSymbol.for("can.meta"),
	dispatchBoundChangeSymbol = canSymbol_1_7_0_canSymbol.for("can.dispatchInstanceBoundChange"),
	dispatchInstanceOnPatchesSymbol = canSymbol_1_7_0_canSymbol.for("can.dispatchInstanceOnPatches"),
	onKeyValueSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.onKeyValue"),
	offKeyValueSymbol = canSymbol_1_7_0_canSymbol.for("can.offKeyValue"),
	onEventSymbol = canSymbol_1_7_0_canSymbol.for("can.onEvent"),
	offEventSymbol = canSymbol_1_7_0_canSymbol.for("can.offEvent"),
	onValueSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.onValue"),
	offValueSymbol = canSymbol_1_7_0_canSymbol.for("can.offValue"),
	inSetupSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.initializing");

var legacyMapBindings;

function addHandlers(obj, meta) {
	if (!meta.handlers) {
		// Handlers are organized by:
		// event name - the type of event bound to
		// binding type - "event" for things that expect an event object (legacy), "onKeyValue" for reflective bindings.
		// queue name - mutate, queue, etc
		// handlers - the handlers.
		meta.handlers = new canKeyTree_1_2_2_canKeyTree([Object, Object, Object, Array], {
			onFirst: function() {
				if (obj._eventSetup !== undefined) {
					obj._eventSetup();
				}
				var constructor = obj.constructor;
				if(constructor[dispatchBoundChangeSymbol] !== undefined && obj instanceof constructor) {
					constructor[dispatchBoundChangeSymbol](obj, true);
				}
				//queues.enqueueByQueue(getLifecycleHandlers(obj).getNode([]), obj, [true]);
			},
			onEmpty: function() {
				if (obj._eventTeardown !== undefined) {
					obj._eventTeardown();
				}
				var constructor = obj.constructor;
				if(constructor[dispatchBoundChangeSymbol] !== undefined && obj instanceof constructor) {
					constructor[dispatchBoundChangeSymbol](obj, false);
				}
				//queues.enqueueByQueue(getLifecycleHandlers(obj).getNode([]), obj, [false]);
			}
		});
	}

	if (!meta.listenHandlers) {
		// context, eventName (might be undefined), queue, handlers
		meta.listenHandlers = new canKeyTree_1_2_2_canKeyTree([Map, Map, Object, Array]);
	}
}


// getHandlers returns a KeyTree used for event handling.
// `handlers` will be on the `can.meta` symbol on the object.
// Ensure the "obj" passed as an argument has an object on @@can.meta
var ensureMeta = function ensureMeta(obj) {
	var meta = obj[metaSymbol];

	if (!meta) {
		meta = {};
		canReflect_1_19_2_canReflect.setKeyValue(obj, metaSymbol, meta);
	}
	addHandlers(obj, meta);

	return meta;
};

function stopListeningArgumentsToKeys(bindTarget, event, handler, queueName) {
	if(arguments.length && canReflect_1_19_2_canReflect.isPrimitive(bindTarget)) {
		queueName = handler;
		handler = event;
		event = bindTarget;
		bindTarget = this.context;
	}
	if(typeof event === "function") {
		queueName = handler;
		handler = event;
		event = undefined;
	}
	if(typeof handler === "string") {
		queueName = handler;
		handler = undefined;
	}
	var keys = [];
	if(bindTarget) {
		keys.push(bindTarget);
		if(event || handler || queueName) {
			keys.push(event);
			if(queueName || handler) {
				keys.push(queueName || this.defaultQueue);
				if(handler) {
					keys.push(handler);
				}
			}
		}
	}
	return keys;
}


// These are the properties we are going to add to objects
var props = {
	/**
	 * @function can-event-queue/map/map.dispatch dispatch
	 * @parent can-event-queue/map/map
	 *
	 * @description Dispatch event and key binding handlers.
	 *
	 * @signature `obj.dispatch(event, [args])`
	 *
	 * Dispatches registered [can-event-queue/map/map.addEventListener] and
	 * [can-event-queue/map/map.can.onKeyValue] value binding handlers.
	 *
	 * The following shows dispatching the `property` event and
	 * `keyValue` handlers:
	 *
	 *
	 * ```js
	 * var mixinMapBindings = require("can-event-queue/map/map");
	 *
	 * var obj = mixinMapBindings({});
	 *
	 * obj.addEventListener("property", function(event, newVal){
	 *   event.type //-> "property"
	 *   newVal     //-> 5
	 * });
	 *
	 * canReflect.onKeyValue("property", function(newVal){
	 *   newVal     //-> 5
	 * })
	 *
	 * obj.dispatch("property", [5]);
	 * ```
	 *
	 * > NOTE: Event handlers have an additional `event` argument.
	 *
	 * @param {String|Object} event The event to dispatch. If a string is passed,
	 *   it will be used as the `type` of the event that will be dispatched and dispatch matching
	 *   [can-event-queue/map/map.can.onKeyValue] bindings:
	 *
	 *   ```js
	 *   obs.dispatch("key")
	 *   ```
	 *
	 *   If `event` is an object, it __MUST__ have a `type` property. The If a string is passed,
	 *   it will be used as the `type` of the event that will be dispatched and dispatch matching
	 *   [can-event-queue/map/map.can.onKeyValue] bindings:
	 *
	 *   ```js
	 *   obs.dispatch({type: "key"})
	 *   ```
	 *
	 *   The `event` object can also have the following properties and values:
	 *   - __reasonLog__ `{Array}` - The reason this event happened. This will be passed to
	 *     [can-queues.enqueueByQueue] for debugging purposes.
	 *   - __makeMeta__ `{function}` - Details about the handler being called. This will be passed to
	 *     [can-queues.enqueueByQueue] for debugging purposes.
	 *   - __patches__ `{Array<Patch>}` - The patch objects this event represents.  The `.patches` value will be
	 *     passed to the object's `.constructor`'s `@can.dispatchInstanceOnPatches` method.
	 *
	 * @param {Array} [args] Additional arguments to pass to event handlers.
	 * @return {Object} event The resulting event object.
	 */
	dispatch: function(event, args) {
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			if (arguments.length > 4) {
				dev.warn('Arguments to dispatch should be an array, not multiple arguments.');
				args = Array.prototype.slice.call(arguments, 1);
			}

			if (args && !Array.isArray(args)) {
				dev.warn('Arguments to dispatch should be an array.');
				args = [args];
			}
		}
		//!steal-remove-end

		// Don't send events if initalizing.
		if (this.__inSetup !== true && this[inSetupSymbol$1] !== true) {
			if (typeof event === 'string') {
				event = {
					type: event
				};
			}

			var meta = ensureMeta(this);

			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				if (!event.reasonLog) {
					event.reasonLog = [canReflect_1_19_2_canReflect.getName(this), "dispatched", '"' + event.type + '"', "with"].concat(args);
				}
			}

			if (typeof meta._log === "function") {
				meta._log.call(this, event, args);
			}
			//!steal-remove-end
			var handlers = meta.handlers;
			var handlersByType = event.type !== undefined && handlers.getNode([event.type]);
			var dispatchConstructorPatches = event.patches && this.constructor[dispatchInstanceOnPatchesSymbol];
			var patchesNode = event.patches !== undefined && handlers.getNode(["can.patches","onKeyValue"]);
			var keysNode = event.keyChanged !== undefined && handlers.getNode(["can.keys","onKeyValue"]);
			var batch = dispatchConstructorPatches || handlersByType || patchesNode || keysNode;
			if ( batch ) {
				canQueues_1_3_2_canQueues.batch.start();
			}
			if(handlersByType) {
				if (handlersByType.onKeyValue) {
					canQueues_1_3_2_canQueues.enqueueByQueue(handlersByType.onKeyValue, this, args, event.makeMeta, event.reasonLog);
				}
				if (handlersByType.event) {
					event.batchNum = canQueues_1_3_2_canQueues.batch.number();
					var eventAndArgs = [event].concat(args);
					canQueues_1_3_2_canQueues.enqueueByQueue(handlersByType.event, this, eventAndArgs, event.makeMeta, event.reasonLog);
				}
			}
			if(keysNode) {
				canQueues_1_3_2_canQueues.enqueueByQueue(keysNode, this, [event.keyChanged], event.makeMeta, event.reasonLog);
			}
			if(patchesNode) {
				canQueues_1_3_2_canQueues.enqueueByQueue(patchesNode, this, [event.patches], event.makeMeta, event.reasonLog);
			}
			if(dispatchConstructorPatches) {
				this.constructor[dispatchInstanceOnPatchesSymbol](this, event.patches);
			}
			if ( batch ) {
				canQueues_1_3_2_canQueues.batch.stop();
			}
		}
		return event;
	},
	/**
	 * @function can-event-queue/map/map.addEventListener addEventListener
	 * @parent can-event-queue/map/map
	 *
	 * @description Register an event handler to be called when an event is dispatched.
	 *
	 * @signature `obj.addEventListener(eventName, handler(event, ...) [,queueName] )`
	 *
	 * Add a event listener to an object.  Handlers attached by `.addEventListener` get
	 * called back with the [can-event-queue/map/map.dispatch]
	 * `event` object and any arguments used to dispatch. [can-event-queue/map/map.can.onKeyValue] bindings do
	 * not get the event object.
	 *
	 * ```js
	 * var mixinMapBindings = require("can-event-queue/map/map");
	 *
	 * var obj = mixinMapBindings({});
	 *
	 * obj.addEventListener("foo", function(event){ ... });
	 * ```
	 *
	 * @param {String} eventName The name of the event to listen for.
	 * @param {Function} handler(event,arg...) The handler that will be executed to handle the event.  The handler will be called
	 *   with the dispatched `event` and `args`.
	 * @param {String} [queueName='mutate'] The name of the [can-queues] queue the handler will called
	 *   back within. Defaults to `"mutate"`.
	 * @return {Object} Returns the object `.addEventListener` was called on.
	 *
	 */
	addEventListener: function(key, handler, queueName) {
		ensureMeta(this).handlers.add([key, "event", queueName || "mutate", handler]);
		return this;
	},
	/**
	 * @function can-event-queue/map/map.removeEventListener removeEventListener
	 * @parent can-event-queue/map/map
	 *
	 * @description Unregister an event handler to be called when an event is dispatched.
	 *
	 * @signature `obj.removeEventListener(eventName, [handler [,queueName]] )`
	 *
	 * Removes one or more handlers from being called when `eventName`
	 * is [can-event-queue/map/map.dispatch]ed.
	 *
	 * ```js
	 * // Removes `handler` if it is in the notify queue.
	 * obj.removeEventListener("closed", handler, "notify")
	 *
	 * // Removes `handler` if it is in the mutate queue.
	 * obj.removeEventListener("closed", handler)
	 *
	 * // Removes all "closed" handlers.
	 * obj.removeEventListener("closed")
	 * ```
	 *
	 * @param {String} eventName The name of the event to remove. If not specified, all events are removed.
	 * @param {Function} [handler] The handler that will be removed from the event. If not specified, all handlers for the event are removed.
	 * @param {String} [queueName='mutate'] The name of the [can-queues] queue the handler was registered on. Defaults to `"mutate"`.
	 * @return {Object} Returns the object `.removeEventListener` was called on.
	 */
	removeEventListener: function(key, handler, queueName) {
		if(key === undefined) {
			// This isn't super fast, but this pattern isn't used much.
			// We could re-arrange the tree so it would be faster.
			var handlers = ensureMeta(this).handlers;
			var keyHandlers = handlers.getNode([]);
			Object.keys(keyHandlers).forEach(function(key){
				handlers.delete([key,"event"]);
			});
		} else if (!handler && !queueName) {
			ensureMeta(this).handlers.delete([key, "event"]);
		} else if (!handler) {
			ensureMeta(this).handlers.delete([key, "event", queueName || "mutate"]);
		} else {
			ensureMeta(this).handlers.delete([key, "event", queueName || "mutate", handler]);
		}
		return this;
	},
	/**
	 * @function can-event-queue/map/map.one one
	 * @parent can-event-queue/map/map
	 *
	 * @description Register an event handler that gets called only once.
	 *
	 * @signature `obj.one(event, handler(event, args...) )`
	 *
	 * Adds a basic event listener that listens to an event once and only once.
	 *
	 * ```js
	 * obj.one("prop", function(){
	 *   console.log("prop dispatched");
	 * })
	 *
	 * obj[canSymbol.for("prop")]("prop") //-> logs "prop dispatched"
	 * obj[canSymbol.for("prop")]("prop")
	 * ```
	 *
	 * @param {String} eventName The name of the event to listen to.
	 * @param {Function} handler(event, args...) The handler that will be run when the
	 *   event is dispached.
	 * @return {Object} this
	 */
	one: function(event, handler) {
		// Unbind the listener after it has been executed
		var one = function() {
			legacyMapBindings.off.call(this, event, one);
			return handler.apply(this, arguments);
		};

		// Bind the altered listener
		legacyMapBindings.on.call(this, event, one);
		return this;
	},
	/**
	 * @function can-event-queue/map/map.listenTo listenTo
	 * @parent can-event-queue/map/map
	 *
	 * @description Listen to an event and register the binding for simplified unbinding.
	 *
	 * @signature `obj.listenTo([bindTarget,] event, handler)`
	 *
	 * `.listenTo` is useful for creating bindings that can can be torn down with
	 * [can-event-queue/map/map.stopListening].  This is useful when creating
	 * rich behaviors that can't be accomplished using computed values, or if you are trying to
	 * avoid streams.
	 *
	 * For example, the following creates an observable that counts how many times its
	 * `name` property has changed:
	 *
	 * ```js
	 * class Person {
	 *   constructor(){
	 *     this.nameChanged = 0;
	 *     this.listenTo("name", function(){
	 *       this.nameChanged++;
	 *     })
	 *   },
	 *   setName(newVal) {
	 *     this.name = newVal;
	 *     this.dispatch("name",[newVal])
	 *   }
	 * }
	 * mixinMapBindings(Person.prototype);
	 *
	 * var person = new Person();
	 * person.setName("Justin");
	 * person.setName("Ramiya");
	 * person.nameChanged //-> 2
	 * ```
	 *
	 * `.listenTo` event bindings are stored on an observable and MUST be unbound using
	 * [can-event-queue/map/map.stopListening]. `.stopListening` make it easy to unbind
	 * all of the `.listenTo` event bindings when the observable is no longer needed:
	 *
	 * ```js
	 * person.stopListening();
	 * ```
	 *
	 * If no `bindTarget` is passed, `.listenTo` binds to the current
	 * observable.
	 *
	 * [can-component]'s `connectedCallback` lifecyle hook is often used to call
	 * `.listenTo` to setup bindings that update viewmodel properties.
	 *
	 *
	 * @param {Object} [bindTarget] The object to listen for events on.  If `bindTarget` is not provided,
	 * the observable `.listenTo` was called on will be the `bindTarget`.
	 * @param {String} event The name of the event to listen for.
	 * @param {Function} handler The handler that will be executed to handle the event.
	 * @return {Object} this
	 */
	listenTo: function (bindTarget, event, handler, queueName) {

		if(canReflect_1_19_2_canReflect.isPrimitive(bindTarget)) {
			queueName = handler;
			handler = event;
			event = bindTarget;
			bindTarget = this;
		}

		if(typeof event === "function") {
			queueName = handler;
			handler = event;
			event = undefined;
		}

		// Initialize event cache
		ensureMeta(this).listenHandlers.add([bindTarget, event, queueName || "mutate", handler]);

		legacyMapBindings.on.call(bindTarget, event, handler, queueName || "mutate");
		return this;
	},
	/**
	 * @function can-event-queue/map/map.stopListening stopListening
	 * @parent can-event-queue/map/map
	 * @description Stops listening for registered event handlers.
	 *
	 * @signature `obj.stopListening( [bindTarget], [event,] handler]] )`
	 *
	 * `.stopListening` unbinds on event handlers registered through
	 * [can-event-queue/map/map.listenTo]. All event handlers
	 * that match the arguments will be unbound. For example:
	 *
	 * ```js
	 * // Unbinds all .listenTo registered handlers
	 * obj.stopListening()
	 *
	 * // Unbinds all .listenTo registered with `bindTarget`
	 * obj.stopListening(bindTarget)
	 *
	 * // Unbinds all .listenTo registered with `bindTarget`, `event`
	 * obj.stopListening(bindTarget, event)
	 *
	 * // Unbinds the handler registered with `bindTarget`, `event`, `handler`
	 * obj.stopListening(bindTarget, event, handler)
	 * ```
	 *
	 * `.listenTo` is often returned by [can-component]'s `connectedCallback` lifecyle hook.
	 *
	 * @param {Object} [bindTarget] The object we will stop listening to event on. If `bindTarget` is
	 * not provided, the observable `.stopListening` was called on will be the `bindTarget`.
	 * @param {String} [event] The name of the event to listen for.
	 * @param {Function} [handler] The handler that will be executed to handle the event.
	 * @return {Object} this
	 *
	 */
	stopListening: function () {
		var keys = stopListeningArgumentsToKeys.apply({context: this, defaultQueue: "mutate"}, arguments);

		var listenHandlers = ensureMeta(this).listenHandlers;

		function deleteHandler(bindTarget, event, queue, handler){
			legacyMapBindings.off.call(bindTarget, event, handler, queue);
		}
		listenHandlers.delete(keys, deleteHandler);

		return this;
	},
	/**
	 * @function can-event-queue/map/map.on on
	 * @parent can-event-queue/map/map
	 *
	 * @description A shorthand method for listening to event.
	 *
	 * @signature `obj.on( event, handler [, queue] )`
	 *
	 * Listen to when `obj` dispatches an event, a [can-reflect/observe.onKeyValue]
	 * change, or a [can-reflect/observe.onValue] change in that order.
	 *
	 * As this is the __legacy__ `.on`, it will look for an `.addEventListener`
	 * method on the `obj` first, before looking for the [can-symbol/symbols/onKeyValue]
	 * and then [can-symbol/symbols/onValue] symbol.
	 *
	 * @param {String} eventName
	 * @param {Function} handler
	 * @param {String} [queue]
	 * @return {Any} The object `on` was called on.
	 */
	on: function(eventName, handler, queue) {
		var listenWithDOM = isDomEventTarget$1(this);
		if (listenWithDOM) {
			if (typeof handler === 'string') {
				canDomEvents_1_3_13_canDomEvents.addDelegateListener(this, eventName, handler, queue);
			} else {
				canDomEvents_1_3_13_canDomEvents.addEventListener(this, eventName, handler, queue);
			}
		} else {
			if (this[onEventSymbol]) {
				this[onEventSymbol](eventName, handler, queue);
			} else if ("addEventListener" in this) {
				this.addEventListener(eventName, handler, queue);
			} else if (this[onKeyValueSymbol$1]) {
				canReflect_1_19_2_canReflect.onKeyValue(this, eventName, handler, queue);
			} else {
				if (!eventName && this[onValueSymbol$1]) {
					canReflect_1_19_2_canReflect.onValue(this, handler, queue);
				} else {
					throw new Error("can-event-queue: Unable to bind " + eventName);
				}
			}
		}
		return this;
	},
	/**
	 * @function can-event-queue/map/map.off off
	 * @parent can-event-queue/map/map
	 *
	 * @description A shorthand method for unbinding an event.
	 *
	 * @signature `obj.on( event, handler [, queue] )`
	 *
	 * Listen to when `obj` dispatches an event, a [can-reflect/observe.onKeyValue]
	 * change, or a [can-reflect/observe.onValue] change in that order.
	 *
	 * As this is the __legacy__ `.on`, it will look for an `.addEventListener`
	 * method on the `obj` first, before looking for the [can-symbol/symbols/onKeyValue]
	 * and then [can-symbol/symbols/onValue] symbol.
	 *
	 * @param {String} eventName
	 * @param {Function} handler
	 * @param {String} [queue]
	 * @return {Any} The object `on` was called on.
	 */
	off: function(eventName, handler, queue) {
		var listenWithDOM = isDomEventTarget$1(this);
		if (listenWithDOM) {
			if (typeof handler === 'string') {
				canDomEvents_1_3_13_canDomEvents.removeDelegateListener(this, eventName, handler, queue);
			} else {
				canDomEvents_1_3_13_canDomEvents.removeEventListener(this, eventName, handler, queue);
			}
		} else {
			if (this[offEventSymbol]) {
				this[offEventSymbol](eventName, handler, queue);
			} else if ("removeEventListener" in this) {
				this.removeEventListener(eventName, handler, queue);
			} else if (this[offKeyValueSymbol]) {
				canReflect_1_19_2_canReflect.offKeyValue(this, eventName, handler, queue);
			} else {
				if (!eventName && this[offValueSymbol]) {
					canReflect_1_19_2_canReflect.offValue(this, handler, queue);
				} else {
					throw new Error("can-event-queue: Unable to unbind " + eventName);
				}

			}
		}
		return this;
	}
};

// The symbols we'll add to objects
var symbols$1 = {
	/**
	 * @function can-event-queue/map/map.can.onKeyValue @can.onKeyValue
	 * @parent can-event-queue/map/map
	 *
	 * @description Register an event handler to be called when a key value changes.
	 *
	 * @signature `canReflect.onKeyValue( obj, key, handler(newVal) [,queueName] )`
	 *
	 * Add a key change handler to an object.  Handlers attached by `.onKeyValue` get
	 * called back with the new value of the `key`. Handlers attached with [can-event-queue/map/map.can.addEventListener]
	 * get the event object.
	 *
	 * ```js
	 * var mixinMapBindings = require("can-event-queue/map/map");
	 *
	 * var obj = mixinMapBindings({});
	 *
	 * canReflect.onKeyValue( obj, "prop", function(newPropValue){ ... });
	 * ```
	 *
	 * @param {String} key The name of property to listen to changes in values.
	 * @param {Function} handler(newVal, oldValue) The handler that will be called
	 *   back with the new and old value of the key.
	 * @param {String} [queueName='mutate'] The name of the [can-queues] queue the handler will called
	 *   back within. Defaults to `"mutate"`.
	 */
	"can.onKeyValue": function(key, handler, queueName) {
		ensureMeta(this).handlers.add([key, "onKeyValue", queueName || "mutate", handler]);
	},
	/**
	 * @function can-event-queue/map/map.can.offKeyValue @can.offKeyValue
	 * @parent can-event-queue/map/map
	 *
	 * @description Unregister an event handler to be called when an event is dispatched.
	 *
	 * @signature `canReflect.offKeyValue( obj, key, handler, queueName )`
	 *
	 * Removes a handlers from being called when `key` changes are
	 * [can-event-queue/map/map.dispatch]ed.
	 *
	 * ```js
	 * // Removes `handler` if it is in the notify queue.
	 * canReflect.offKeyValue( obj, "prop", handler, "notify" )
	 * ```
	 *
	 * @param {String} eventName The name of the event to remove. If not specified, all events are removed.
	 * @param {Function} [handler] The handler that will be removed from the event. If not specified, all handlers for the event are removed.
	 * @param {String} [queueName='mutate'] The name of the [can-queues] queue the handler was registered on. Defaults to `"mutate"`.
	 */
	"can.offKeyValue": function(key, handler, queueName) {
		ensureMeta(this).handlers.delete([key, "onKeyValue", queueName || "mutate", handler]);
	},
	/**
	 * @function can-event-queue/map/map.can.isBound @can.isBound
	 * @parent can-event-queue/map/map
	 *
	 * @description Return if the observable is bound to.
	 *
	 * @signature `canReflect.isBound(obj)`
	 *
	 * The `@can.isBound` symbol is added to make [can-reflect/observe.isBound]
	 * return if `obj` is bound or not.
	 *
	 * @return {Boolean} True if the observable has been bound to with `.onKeyValue` or `.addEventListener`.
	 */
	"can.isBound": function() {
		return !ensureMeta(this).handlers.isEmpty();
	},
	/**
	 * @function can-event-queue/map/map.can.getWhatIChange @can.getWhatIChange
	 * @parent can-event-queue/map/map
	 *
	 * @description Return observables whose values are affected by attached event handlers
	 * @signature `@can.getWhatIChange(key)`
	 *
	 * The `@@can.getWhatIChange` symbol is added to make sure [can-debug] can report
	 * all the observables whose values are set by a given observable's key.
	 *
	 * This function iterates over the event handlers attached to a given `key` and
	 * collects the result of calling `@@can.getChangesDependencyRecord` on each handler;
	 * this symbol allows the caller to tell what observables are being mutated by
	 * the event handler when it is executed.
	 *
	 * In the following example a [can-simple-map] instance named `me` is created
	 * and when its `age` property changes, the value of a [can-simple-observable]
	 * instance is set. The event handler that causes the mutation is then decatorated
	 * with `@@can.getChangesDependencyRecord` to register the mutation dependency.
	 *
	 * ```js
	 * var obs = new SimpleObservable("a");
	 * var me = new SimpleMap({ age: 30 });
	 * var canReflect = require("can-reflect");
	 *
	 * var onAgeChange = function onAgeChange() {
	 *	canReflect.setValue(obs, "b");
	 * };
	 *
	 * onAgeChange[canSymbol.for("can.getChangesDependencyRecord")] = function() {
	 *	return {
	 *		valueDependencies: new Set([ obs ]);
	 *	}
	 * };
	 *
	 * canReflect.onKeyValue(me, "age", onAgeChange);
	 * me[canSymbol.for("can.getWhatIChange")]("age");
	 * ```
	 *
	 * The dependency records collected from the event handlers are divided into
	 * two categories:
	 *
	 * - mutate: Handlers in the mutate/domUI queues
	 * - derive: Handlers in the notify queue
	 *
	 * Since event handlers are added by default to the "mutate" queue, calling
	 * `@@can.getWhatIChange` on the `me` instance returns an object with a mutate
	 * property and the `valueDependencies` Set registered on the `onAgeChange`
	 * handler.
	 *
	 * Please check out the [can-reflect-dependencies] docs to learn more about
	 * how this symbol is used to keep track of custom observable dependencies.
	 */
	"can.getWhatIChange": function getWhatIChange(key) {
		//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
			var whatIChange = {};
			var meta = ensureMeta(this);

			var notifyHandlers = [].concat(
				meta.handlers.get([key, "event", "notify"]),
				meta.handlers.get([key, "onKeyValue", "notify"])
			);

			var mutateHandlers = [].concat(
				meta.handlers.get([key, "event", "mutate"]),
				meta.handlers.get([key, "event", "domUI"]),
				meta.handlers.get([key, "onKeyValue", "mutate"]),
				meta.handlers.get([key, "onKeyValue", "domUI"])
			);

			if (notifyHandlers.length) {
				notifyHandlers.forEach(function(handler) {
					var changes = canReflect_1_19_2_canReflect.getChangesDependencyRecord(handler);

					if (changes) {
						var record = whatIChange.derive;
						if (!record) {
							record = (whatIChange.derive = {});
						}
						merge(record, changes);
					}
				});
			}

			if (mutateHandlers.length) {
				mutateHandlers.forEach(function(handler) {
					var changes = canReflect_1_19_2_canReflect.getChangesDependencyRecord(handler);

					if (changes) {
						var record = whatIChange.mutate;
						if (!record) {
							record = (whatIChange.mutate = {});
						}
						merge(record, changes);
					}
				});
			}

			return Object.keys(whatIChange).length ? whatIChange : undefined;
		}
		//!steal-remove-end
	},
	"can.onPatches": function(handler, queue) {
		var handlers = ensureMeta(this).handlers;
		handlers.add(["can.patches", "onKeyValue", queue || "notify", handler]);
	},
	"can.offPatches": function(handler, queue) {
		var handlers = ensureMeta(this).handlers;
		handlers.delete(["can.patches", "onKeyValue", queue || "notify", handler]);
	}
};

// This can be removed in a future version.
function defineNonEnumerable$1(obj, prop, value) {
	Object.defineProperty(obj, prop, {
		enumerable: false,
		value: value
	});
}

// The actual legacyMapBindings mixin function
legacyMapBindings = function(obj) {
	// add properties
	canReflect_1_19_2_canReflect.assignMap(obj, props);
	// add symbols
	return canReflect_1_19_2_canReflect.assignSymbols(obj, symbols$1);
};

defineNonEnumerable$1(legacyMapBindings, "addHandlers", addHandlers);
defineNonEnumerable$1(legacyMapBindings, "stopListeningArgumentsToKeys", stopListeningArgumentsToKeys);



// ## LEGACY
// The following is for compatability with the old can-event
props.bind = props.addEventListener;
props.unbind = props.removeEventListener;



// Adds methods directly to method so it can be used like `can-event` used to be used.
canReflect_1_19_2_canReflect.assignMap(legacyMapBindings, props);
canReflect_1_19_2_canReflect.assignSymbols(legacyMapBindings, symbols$1);

defineNonEnumerable$1(legacyMapBindings, "start", function() {
	console.warn("use can-queues.batch.start()");
	canQueues_1_3_2_canQueues.batch.start();
});
defineNonEnumerable$1(legacyMapBindings, "stop", function() {
	console.warn("use can-queues.batch.stop()");
	canQueues_1_3_2_canQueues.batch.stop();
});
defineNonEnumerable$1(legacyMapBindings, "flush", function() {
	console.warn("use can-queues.flush()");
	canQueues_1_3_2_canQueues.flush();
});

defineNonEnumerable$1(legacyMapBindings, "afterPreviousEvents", function(handler) {
	console.warn("don't use afterPreviousEvents");
	canQueues_1_3_2_canQueues.mutateQueue.enqueue(function afterPreviousEvents() {
		canQueues_1_3_2_canQueues.mutateQueue.enqueue(handler);
	});
	canQueues_1_3_2_canQueues.flush();
});

defineNonEnumerable$1(legacyMapBindings, "after", function(handler) {
	console.warn("don't use after");
	canQueues_1_3_2_canQueues.mutateQueue.enqueue(handler);
	canQueues_1_3_2_canQueues.flush();
});

var map$1 = legacyMapBindings;

// Ensure the "obj" passed as an argument has an object on @@can.meta
var ensureMeta$1 = function ensureMeta(obj) {
	var metaSymbol = canSymbol_1_7_0_canSymbol.for("can.meta");
	var meta = obj[metaSymbol];

	if (!meta) {
		meta = {};
		canReflect_1_19_2_canReflect.setKeyValue(obj, metaSymbol, meta);
	}

	return meta;
};

// this is a very simple can-map like object
var SimpleMap = canConstruct_3_5_7_canConstruct.extend("SimpleMap",
	{
		// ### setup
		// A setup function for the instantiation of a simple-map.
		setup: function(initialData){
			this._data = {};
			if(initialData && typeof initialData === "object") {
				this.attr(initialData);
			}
		},
		// ### attr
		// The main get/set interface simple-map.
		// Either sets or gets one or more properties depending on how it is called.
		attr: function(prop, value) {
			var self = this;

			if(arguments.length === 0 ) {
				canObservationRecorder_1_3_1_canObservationRecorder.add(this,"can.keys");
				var data = {};
				canReflect_1_19_2_canReflect.eachKey(this._data, function(value, prop){
					canObservationRecorder_1_3_1_canObservationRecorder.add(this, prop);
					data[prop] = value;
				}, this);
				return data;
			}
			else if(arguments.length > 1) {
				var had = this._data.hasOwnProperty(prop);
				var old = this._data[prop];
				this._data[prop] = value;
				if(old !== value) {


					//!steal-remove-start
					if (process.env.NODE_ENV !== 'production') {
						if (typeof this._log === "function") {
							this._log(prop, value, old);
						}
					}
					//!steal-remove-end

					var dispatched = {
						keyChanged: !had ? prop : undefined,
						type: prop
					};
					//!steal-remove-start
					if (process.env.NODE_ENV !== 'production') {
						dispatched = {
							keyChanged: !had ? prop : undefined,
							type: prop,
							reasonLog: [ canReflect_1_19_2_canReflect.getName(this) + "'s", prop, "changed to", value, "from", old ],
						};
					}
					//!steal-remove-end

					this.dispatch(dispatched, [value, old]);
				}

			}
			// 1 argument
			else if(typeof prop === 'object') {
				canQueues_1_3_2_canQueues.batch.start();
				canReflect_1_19_2_canReflect.eachKey(prop, function(value, key) {
					self.attr(key, value);
				});
				canQueues_1_3_2_canQueues.batch.stop();
			}
			else {
				if(prop !== "constructor") {
					canObservationRecorder_1_3_1_canObservationRecorder.add(this, prop);
					return this._data[prop];
				}

				return this.constructor;
			}
		},
		serialize: function(){
			return canReflect_1_19_2_canReflect.serialize(this, Map);
		},
		get: function(){
			return this.attr.apply(this, arguments);
		},
		set: function(){
			return this.attr.apply(this, arguments);
		},
		// call `.log()` to log all property changes
		// pass a single property to only get logs for said property, e.g: `.log("foo")`
		log: function(key) {
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				var quoteString = function quoteString(x) {
					return typeof x === "string" ? JSON.stringify(x) : x;
				};
				var meta = ensureMeta$1(this);
				meta.allowedLogKeysSet = meta.allowedLogKeysSet || new Set();

				if (key) {
					meta.allowedLogKeysSet.add(key);
				}

				this._log = function(prop, current, previous, log) {
					if (key && !meta.allowedLogKeysSet.has(prop)) {
						return;
					}
					dev.log(
						canReflect_1_19_2_canReflect.getName(this),
						"\n key ", quoteString(prop),
						"\n is  ", quoteString(current),
						"\n was ", quoteString(previous)
					);
				};
			}
			//!steal-remove-end
		}
	}
);

map$1(SimpleMap.prototype);

var simpleMapProto = {
	// -type-
	"can.isMapLike": true,
	"can.isListLike": false,
	"can.isValueLike": false,

	// -get/set-
	"can.getKeyValue": SimpleMap.prototype.get,
	"can.setKeyValue": SimpleMap.prototype.set,
	"can.deleteKeyValue": function(prop) {
		var dispatched;
		if( this._data.hasOwnProperty(prop) ) {
			var old = this._data[prop];
			delete this._data[prop];

			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				if (typeof this._log === "function") {
					this._log(prop, undefined, old);
				}
			}
			//!steal-remove-end
			dispatched = {
				keyChanged: prop,
				type: prop
			};
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				dispatched = {
					keyChanged: prop,
					type: prop,
					reasonLog: [ canReflect_1_19_2_canReflect.getName(this) + "'s", prop, "deleted", old ]
				};
			}
			//!steal-remove-end
			this.dispatch(dispatched, [undefined, old]);
		}
	},


	// -shape
	"can.getOwnEnumerableKeys": function(){
		canObservationRecorder_1_3_1_canObservationRecorder.add(this, 'can.keys');
		return Object.keys(this._data);
	},

	// -shape get/set-
	"can.assignDeep": function(source){
		canQueues_1_3_2_canQueues.batch.start();
		// TODO: we should probably just throw an error instead of cleaning
		canReflect_1_19_2_canReflect.assignMap(this, source);
		canQueues_1_3_2_canQueues.batch.stop();
	},
	"can.updateDeep": function(source){
		canQueues_1_3_2_canQueues.batch.start();
		// TODO: we should probably just throw an error instead of cleaning
		canReflect_1_19_2_canReflect.updateMap(this, source);
		canQueues_1_3_2_canQueues.batch.stop();
	},
	"can.keyHasDependencies": function(key) {
		return false;
	},
	"can.getKeyDependencies": function(key) {
		return undefined;
	},
	"can.hasOwnKey": function(key){
		return this._data.hasOwnProperty(key);
	}
};

//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	simpleMapProto["can.getName"] = function() {
		return canReflect_1_19_2_canReflect.getName(this.constructor) + "{}";
	};
}
//!steal-remove-end
canReflect_1_19_2_canReflect.assignSymbols(SimpleMap.prototype,simpleMapProto);

// Setup other symbols


var canSimpleMap_4_3_3_canSimpleMap = SimpleMap;

/**
 * Creates a constructor function from an ES2015 class, this is a workaround
 * needed to being able to extend a class from code that's transpiled by Babel.
 * See https://github.com/babel/babel/pull/8656
 * @param {*} Type The ES2015 base class used to create the constructor
 * @param {*} Parent The object where the prototype chain walk to copy over
 * symbols and static properties to the constructor stops. If not provided,
 * the chain stops at Object.
 * @returns {Function} Constructor function than can be safely subclassed from
 * transpiled code.
 */
function createConstructorFunction(Type, Parent) {
	if (typeof Parent === "undefined") {
		Parent = Object.getPrototypeOf(Object);
	}

	function TypeConstructor() {
		return Reflect.construct(Type, arguments, this.constructor);
	}

	TypeConstructor.prototype = Object.create(Type.prototype);
	TypeConstructor.prototype.constructor = TypeConstructor;

	/**
	 * Add `prop` to TypeConstructor from `source` if not defined already
	 * @param {{}} source The object that owns `prop`
	 * @param {string} prop The name of the property to be defined
	 */
	function copyIfMissing(source, prop) {
		if (!TypeConstructor[prop]) {
			Object.defineProperty(
				TypeConstructor,
				prop,
				Object.getOwnPropertyDescriptor(source, prop)
			);
		}
	}

	// Walk up the prototype chain to copy over all Symbols and
	// static properties to the constructor function
	let Link = Type;
	while (Link !== Parent && Link !== null) {
		const props = Object.getOwnPropertyNames(Link);
		props.forEach(function(prop) {
			copyIfMissing(Link, prop);
		});

		const symbols = Object.getOwnPropertySymbols(Link);
		symbols.forEach(function(symbol) {
			copyIfMissing(Link, symbol);
		});

		Link = Object.getPrototypeOf(Link);
	}

	return TypeConstructor;
}

var createConstructorFunction_1 = createConstructorFunction;

// This is an observable that is like `settable`, but passed a `resolve`
// function that can resolve the value of this observable late.
function AsyncObservable(fn, context, initialValue) {
	this.resolve = this.resolve.bind(this);
	this.lastSetValue = new canSimpleObservable_2_5_0_canSimpleObservable(initialValue);
	this.handler = this.handler.bind(this);

	function observe() {
		this.resolveCalled = false;

		// set inGetter flag to avoid calling `resolve` redundantly if it is called
		// synchronously in the getter
		this.inGetter = true;
		var newVal = fn.call(
			context,
			this.lastSetValue.get(),
			this.bound === true ? this.resolve : undefined
		);
		this.inGetter = false;

		// if the getter returned a value, resolve with the value
		if (newVal !== undefined) {
			this.resolve(newVal);
		}
		// otherwise, if `resolve` was called synchronously in the getter,
		// resolve with the value passed to `resolve`
		else if (this.resolveCalled) {
			this.resolve(this._value);
		}

		// if bound, the handlers will be called by `resolve`
		// returning here would cause a duplicate event
		if (this.bound !== true) {
			return newVal;
		}
	}

	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		canReflect_1_19_2_canReflect.assignSymbols(this, {
			"can.getName": function() {
				return (
					canReflect_1_19_2_canReflect.getName(this.constructor) +
					"<" +
					canReflect_1_19_2_canReflect.getName(fn) +
					">"
				);
			}
		});
		Object.defineProperty(this.handler, "name", {
			value: canReflect_1_19_2_canReflect.getName(this) + ".handler"
		});
		Object.defineProperty(observe, "name", {
			value: canReflect_1_19_2_canReflect.getName(fn) + "::" + canReflect_1_19_2_canReflect.getName(this.constructor)
		});
	}
	//!steal-remove-end

	this.observation = new canObservation_4_2_0_canObservation(observe, this);
}
AsyncObservable.prototype = Object.create(settable.prototype);
AsyncObservable.prototype.constructor = AsyncObservable;

AsyncObservable.prototype.handler = function(newVal) {
	if (newVal !== undefined) {
		settable.prototype.handler.apply(this, arguments);
	}
};

var peek$1 = canObservationRecorder_1_3_1_canObservationRecorder.ignore(canReflect_1_19_2_canReflect.getValue.bind(canReflect_1_19_2_canReflect));
AsyncObservable.prototype.activate = function() {
	canReflect_1_19_2_canReflect.onValue(this.observation, this.handler, "notify");
	if (!this.resolveCalled) {
		this._value = peek$1(this.observation);
	}
};

AsyncObservable.prototype.resolve = function resolve(newVal) {
	this.resolveCalled = true;
	var old = this._value;
	this._value = newVal;

	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		if (typeof this._log === "function") {
			this._log(old, newVal);
		}
	}
	//!steal-remove-end

	// if resolve was called synchronously from the getter, do not enqueue changes
	// the observation will handle calling resolve again if required
	if (!this.inGetter) {
		var queuesArgs = [
		this.handlers.getNode([]),
			this,
			[newVal, old],
			null
		];
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			queuesArgs = [
				this.handlers.getNode([]),
				this,
				[newVal, old],
				null
				/* jshint laxcomma: true */
				, [canReflect_1_19_2_canReflect.getName(this), "resolved with", newVal]
				/* jshint laxcomma: false */
			];
		}
		//!steal-remove-end
		// adds callback handlers to be called w/i their respective queue.
		canQueues_1_3_2_canQueues.enqueueByQueue.apply(canQueues_1_3_2_canQueues, queuesArgs);
	}
};

var async = AsyncObservable;

var getChangesSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.getChangesDependencyRecord");
var metaSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.meta");

function ResolverObservable(resolver, context, initialValue, options) {
	// we don't want reads leaking out.  We should be binding to all of this ourselves.
	this.resolver = canObservationRecorder_1_3_1_canObservationRecorder.ignore(resolver);
	this.context = context;
	this._valueOptions = {
		resolve: this.resolve.bind(this),
		listenTo: this.listenTo.bind(this),
		stopListening: this.stopListening.bind(this),
		lastSet: new canSimpleObservable_2_5_0_canSimpleObservable(initialValue)
	};

	this.update = this.update.bind(this);

	this.contextHandlers = new WeakMap();
	this.teardown = null;
	// a place holder for remembering where we bind
	this.binder = {};
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		canReflect_1_19_2_canReflect.assignSymbols(this, {
			"can.getName": function() {
				return (
					canReflect_1_19_2_canReflect.getName(this.constructor) +
					"<" +
					canReflect_1_19_2_canReflect.getName(resolver) +
					">"
				);
			}
		});
		Object.defineProperty(this.update, "name", {
			value: canReflect_1_19_2_canReflect.getName(this) + ".update"
		});

		canReflect_1_19_2_canReflect.assignSymbols(this._valueOptions.lastSet, {
			"can.getName": function() {
				return (
					canReflect_1_19_2_canReflect.getName(this.constructor)  +"::lastSet"+
					"<" +
					canReflect_1_19_2_canReflect.getName(resolver) +
					">"
				);
			}
		});
	}
	//!steal-remove-end

	this[metaSymbol$1] = canReflect_1_19_2_canReflect.assignMap({}, options);
}
ResolverObservable.prototype = Object.create(settable.prototype);

function deleteHandler(bindTarget, event, queue, handler){
	map$1.off.call(bindTarget, event, handler, queue);
}

canReflect_1_19_2_canReflect.assignMap(ResolverObservable.prototype, {
	constructor: ResolverObservable,
	listenTo: function(bindTarget, event, handler, queueName) {
		//Object.defineProperty(this.handler, "name", {
		//	value: canReflect.getName(this) + ".handler"
		//});
		if(canReflect_1_19_2_canReflect.isPrimitive(bindTarget)) {
			handler = event;
			event = bindTarget;
			bindTarget = this.context;
		}
		if(typeof event === "function") {
			handler = event;
			event = undefined;
		}

		var resolverInstance = this;

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			if(!handler.name) {
				Object.defineProperty(handler, "name", {
					value:
						(bindTarget ?
							 canReflect_1_19_2_canReflect.getName(bindTarget) : "")+
						 (event ? ".on('"+event+"',handler)" : ".on(handler)")+
						 "::"+canReflect_1_19_2_canReflect.getName(this)
				});
			}
		}
		//!steal-remove-end

		var contextHandler = handler.bind(this.context);
		contextHandler[getChangesSymbol$1] = function getChangesDependencyRecord() {
			var s = new Set();
			s.add(resolverInstance);
			return {
				valueDependencies: s
			};
		};

		this.contextHandlers.set(handler, contextHandler);
		map$1.listenTo.call(this.binder, bindTarget, event, contextHandler, queueName || "notify");
	},
	stopListening: function(){

		var meta = this.binder[canSymbol_1_7_0_canSymbol.for("can.meta")];
		var listenHandlers = meta && meta.listenHandlers;
		if(listenHandlers) {
			var keys = map$1.stopListeningArgumentsToKeys.call({context: this.context, defaultQueue: "notify"});

			listenHandlers.delete(keys, deleteHandler);
		}
		return this;
	},
	resolve: function(newVal) {
		this._value = newVal;
		// if we are setting up the initial binding and we get a resolved value
		// do not emit events for it.

		if(this.isBinding) {
			this.lastValue = this._value;
			return newVal;
		}

		if(this._value !== this.lastValue) {
			var enqueueMeta  = {};

			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				/* jshint laxcomma: true */
				enqueueMeta = {
					log: [canReflect_1_19_2_canReflect.getName(this.update)],
					reasonLog: [canReflect_1_19_2_canReflect.getName(this), "resolved with", newVal]
				};
				/* jshint laxcomma: false */
			}
			//!steal-remove-end

			canQueues_1_3_2_canQueues.batch.start();
			canQueues_1_3_2_canQueues.deriveQueue.enqueue(
				this.update,
				this,
				[],
				enqueueMeta
			);
			canQueues_1_3_2_canQueues.batch.stop();
		}
		return newVal;
	},
	update: function(){

		if(this.lastValue !== this._value) {

			var old = this.lastValue;
			this.lastValue = this._value;
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				if (typeof this._log === "function") {
					this._log(old, this._value);
				}
			}
			//!steal-remove-end

			// adds callback handlers to be called w/i their respective queue.
			canQueues_1_3_2_canQueues.enqueueByQueue(
				this.handlers.getNode([]),
				this,
				[this._value, old]
			);
		}
	},
	activate: function() {
		this.isBinding = true;
		this.teardown = this.resolver.call(this.context, this._valueOptions);
		this.isBinding = false;
	},
	onUnbound: function() {
		this.bound = false;
		map$1.stopListening.call(this.binder);
		if(this.teardown != null) {
			this.teardown();
			this.teardown = null;
		}
	},
	set: function(value) {
		this._valueOptions.lastSet.set(value);

		/*if (newVal !== this.lastSetValue.get()) {
			this.lastSetValue.set(newVal);
		}*/
	},
	get: function() {
		if (canObservationRecorder_1_3_1_canObservationRecorder.isRecording()) {
			canObservationRecorder_1_3_1_canObservationRecorder.add(this);
			if (!this.bound) {
				this.onBound();
			}
		}

		if (this.bound === true) {
			return this._value;
		} else {
			if (this[metaSymbol$1].resetUnboundValueInGet) {
				this._value = undefined;
			}

			var handler = function(){};
			this.on(handler);
			var val = this._value;
			this.off(handler);
			return val;
		}
	},
	hasDependencies: function hasDependencies() {
		var hasDependencies = false;

		if (this.bound) {
			var meta = this.binder[metaSymbol$1];
			var listenHandlers = meta && meta.listenHandlers;
			hasDependencies = !!listenHandlers.size();
		}

		return hasDependencies;
	},
	getValueDependencies: function getValueDependencies() {
		if (this.bound) {
			var meta = this.binder[canSymbol_1_7_0_canSymbol.for("can.meta")];
			var listenHandlers = meta && meta.listenHandlers;

			var keyDeps = new Map();
			var valueDeps = new Set();

			if (listenHandlers) {
				canReflect_1_19_2_canReflect.each(listenHandlers.root, function(events, obj) {
					canReflect_1_19_2_canReflect.each(events, function(queues, eventName) {
						if (eventName === undefined) {
							valueDeps.add(obj);
						} else {
							var entry = keyDeps.get(obj);
							if (!entry) {
								entry = new Set();
								keyDeps.set(obj, entry);
							}
							entry.add(eventName);
						}
					});
				});

				if (valueDeps.size || keyDeps.size) {
					var result = {};

					if (keyDeps.size) {
						result.keyDependencies = keyDeps;
					}
					if (valueDeps.size) {
						result.valueDependencies = valueDeps;
					}

					return result;
				}
			}
		}
	}
});

canReflect_1_19_2_canReflect.assignSymbols(ResolverObservable.prototype, {
	"can.getValue": ResolverObservable.prototype.get,
	"can.setValue": ResolverObservable.prototype.set,
	"can.isMapLike": false,
	"can.getPriority": function() {
		// TODO: the priority should come from any underlying values
		return this.priority || 0;
	},
	"can.setPriority": function(newPriority) {
		this.priority = newPriority;
	},
	"can.valueHasDependencies": ResolverObservable.prototype.hasDependencies,
	"can.getValueDependencies": ResolverObservable.prototype.getValueDependencies
});


var resolver = ResolverObservable;

/**
 * @module {function} can-event-queue/type/type
 * @parent can-event-queue
 *
 * @description Mixin methods and symbols to make a type constructor function able to
 * broadcast changes in its instances.
 *
 * @signature `mixinTypeBindings( type )`
 *
 * Adds symbols and methods that make `type` work with the following [can-reflect] APIs:
 *
 * - [can-reflect/observe.onInstanceBoundChange] - Observe when instances are bound.
 * - [can-reflect/observe.onInstancePatches] - Observe patche events on all instances.
 *
 * When `mixinTypeBindings` is called on an `Person` _type_ like:
 *
 * ```js
 * var mixinTypeBindings = require("can-event-queue/type/type");
 * var mixinLegacyMapBindings = require("can-event-queue/map/map");
 *
 * class Person {
 *   constructor(data){
 *     this.data = data;
 *   }
 * }
 * mixinTypeBindings(Person);
 * mixinLegacyMapBindings(Person.prototype);
 *
 * var me = new Person({first: "Justin", last: "Meyer"});
 *
 * // mixinTypeBindings allows you to listen to
 * // when a person instance's bind stache changes
 * canReflect.onInstanceBoundChange(Person, function(person, isBound){
 *    console.log("isBound");
 * });
 *
 * // mixinTypeBindings allows you to listen to
 * // when a patch change happens.
 * canReflect.onInstancePatches(Person, function(person, patches){
 *    console.log(patches[0]);
 * });
 *
 * me.on("name",function(ev, newVal, oldVal){}) //-> logs: "isBound"
 *
 * me.dispatch({
 *   type: "first",
 *   patches: [{type: "set", key: "first", value: "Ramiya"}]
 * }, ["Ramiya","Justin"])
 * //-> logs: {type: "set", key: "first", value: "Ramiya"}
 * ```
 *
 */





var metaSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.meta");

function addHandlers$1(obj, meta) {
    if (!meta.lifecycleHandlers) {
        meta.lifecycleHandlers = new canKeyTree_1_2_2_canKeyTree([Object, Array]);
    }
    if (!meta.instancePatchesHandlers) {
        meta.instancePatchesHandlers = new canKeyTree_1_2_2_canKeyTree([Object, Array]);
    }
}

function ensureMeta$2(obj) {
    var meta = obj[metaSymbol$2];

    if (!meta) {
        meta = {};
        canReflect_1_19_2_canReflect.setKeyValue(obj, metaSymbol$2, meta);
    }

    addHandlers$1(obj, meta);
    return meta;
}

var props$1 = {
    /**
     * @function can-event-queue/type/type.can.onInstanceBoundChange @can.onInstanceBoundChange
     * @parent can-event-queue/type/type
     * @description Listen to when any instance is bound for the first time or all handlers are removed.
     *
     * @signature `canReflect.onInstanceBoundChange(Type, handler(instance, isBound) )`
     *
     * ```js
     * canReflect.onInstanceBoundChange(Person, function(person, isBound){
     *    console.log("isBound");
     * });
     * ```
     *
     * @param {function(Any,Boolean)} handler(instance,isBound) A function is called
     * when an instance is bound or unbound.  `isBound` will be `true` when the instance
     * becomes bound and `false` when unbound.
     */

    /**
     * @function can-event-queue/type/type.can.offInstanceBoundChange @can.offInstanceBoundChange
     * @parent can-event-queue/type/type
     *
     * @description Stop listening to when an instance's bound status changes.
     *
     * @signature `canReflect.offInstanceBoundChange(Type, handler )`
     *
     * Stop listening to a handler bound with
     * [can-event-queue/type/type.can.onInstanceBoundChange].
     */


    /**
     * @function can-event-queue/type/type.can.onInstancePatches @can.onInstancePatches
     * @parent can-event-queue/type/type
     *
     * @description Listen to patch changes on any instance.
     *
     * @signature `canReflect.onInstancePatches(Type, handler(instance, patches) )`
     *
     * Listen to patch changes on any instance of `Type`. This is used by
     * [can-connect] to know when a potentially `unbound` instance's `id`
     * changes. If the `id` changes, the instance can be moved into the store
     * while it is being saved.
     *
     */

    /**
     * @function can-event-queue/type/type.can.offInstancePatches @can.offInstancePatches
     * @parent can-event-queue/type/type
     *
     * @description Stop listening to patch changes on any instance.
     *
     * @signature `canReflect.onInstancePatches(Type, handler )`
     *
     * Stop listening to a handler bound with [can-event-queue/type/type.can.onInstancePatches].
     */
};

function onOffAndDispatch(symbolName, dispatchName, handlersName){
    props$1["can.on"+symbolName] = function(handler, queueName) {
        ensureMeta$2(this)[handlersName].add([queueName || "mutate", handler]);
    };
    props$1["can.off"+symbolName] = function(handler, queueName) {
        ensureMeta$2(this)[handlersName].delete([queueName || "mutate", handler]);
    };
    props$1["can."+dispatchName] = function(instance, arg){
        canQueues_1_3_2_canQueues.enqueueByQueue(ensureMeta$2(this)[handlersName].getNode([]), this, [instance, arg]);
    };
}

onOffAndDispatch("InstancePatches","dispatchInstanceOnPatches","instancePatchesHandlers");
onOffAndDispatch("InstanceBoundChange","dispatchInstanceBoundChange","lifecycleHandlers");

function mixinTypeBindings(obj){
    return canReflect_1_19_2_canReflect.assignSymbols(obj,props$1);
}

Object.defineProperty(mixinTypeBindings, "addHandlers", {
    enumerable: false,
    value: addHandlers$1
});

var type$1 = mixinTypeBindings;

var canType_1_1_6_canType = createCommonjsModule(function (module, exports) {
var isMemberSymbol = canSymbol_1_7_0_canSymbol.for("can.isMember");
var newSymbol = canSymbol_1_7_0_canSymbol.for("can.new");
var getSchemaSymbol = canSymbol_1_7_0_canSymbol.for("can.getSchema");
var baseTypeSymbol = canSymbol_1_7_0_canSymbol.for("can.baseType");
var strictTypeOfSymbol = canSymbol_1_7_0_canSymbol.for("can.strictTypeOf");

var type = exports;

function makeSchema(values) {
	return function(){
		return {
			type: "Or",
			values: values
		};
	};
}

// Default "can.new"
function canNew(value) {
	if(this[isMemberSymbol](value)) {
		return value;
	}

	return canReflect_1_19_2_canReflect.convert(value, this[baseTypeSymbol]);
}

function strictNew(value) {
	var isMember = this[isMemberSymbol](value);
	if(!isMember) {
		return check(this[baseTypeSymbol], value);
	}
	return value;
}

// "can.new" for Booleans
function booleanNew(value) {
	if (value === "false" || value=== "0") {
		return false;
	}
	return Boolean(value);
}

var maybeValues = Object.freeze([null, undefined]);

function check(Type, val) {
	var valueType = canString_1_1_0_canString.capitalize(typeof val);
	var error = new Error('Type value ' + typeof val === "string" ? '"' + val + '"' : val + ' (' + valueType + ') is not of type ' + canReflect_1_19_2_canReflect.getName(Type) + '.'	);
	error.type = 'can-type-error';
	throw error;
}

function makeIsMember(Type) {
	if(isMemberSymbol in Type) {
		return Type[isMemberSymbol];
	}
	return function(value) {
		return value instanceof Type;
	};
}

function makeBaseType(Type) {
	var typeObject = {};
	typeObject[newSymbol] = canNew;
	typeObject[isMemberSymbol] = makeIsMember(Type);
	typeObject[baseTypeSymbol] = Type;
	typeObject[getSchemaSymbol] = makeSchema([Type]);
	Type[strictTypeOfSymbol] = typeObject[strictTypeOfSymbol] = typeObject;
	return typeObject;
}

function makePrimitiveType(Type, typeString) {
	var typeObject = makeBaseType(Type);
	if(Type === Boolean) {
		typeObject[newSymbol] = booleanNew;
		typeObject[getSchemaSymbol] = makeSchema([true, false]);
	}
	typeObject[isMemberSymbol] = function(value) {
		return typeof value === typeString;
	};
	return typeObject;
}

function getBaseType(Type) {
	if(typeof Type === "function") {
		if(canReflect_1_19_2_canReflect.hasOwnKey(Type, strictTypeOfSymbol)) {
			return Type[strictTypeOfSymbol];
		}
	} else if(strictTypeOfSymbol in Type) {
		return Type[strictTypeOfSymbol];
	}
	return makeBaseType(Type);
}

function makeMaybe(Type) {
	var isMember = Type[isMemberSymbol];
	return function(value) {
		return value == null || isMember.call(this, value);
	};
}

function makeMaybeSchema(baseType) {
	var baseSchema = canReflect_1_19_2_canReflect.getSchema(baseType);
	var allValues = baseSchema.values.concat(maybeValues);
	return makeSchema(allValues);
}

function inheritFrom(o, Type, property) {
	if(property in Type) {
		o[property] = Type[property];
	}
}

function wrapName(wrapper, Type) {
	var baseName = canReflect_1_19_2_canReflect.getName(Type);
	return "type." + wrapper + "(" + baseName + ")";
}

canReflect_1_19_2_canReflect.each({
	"boolean": Boolean,
	"number": Number,
	"string": String
}, function(Type, typeString) {
	makePrimitiveType(Type, typeString);
});

function isTypeObject(Type) {
	if(canReflect_1_19_2_canReflect.isPrimitive(Type)) {
		return false;
	}

	return (newSymbol in Type) && (isMemberSymbol in Type);
}

function normalize(Type) {
	if(canReflect_1_19_2_canReflect.isPrimitive(Type)) {
		throw new Error("can-type: Unable to normalize primitive values.");
	} else if(isTypeObject(Type)) {
		return Type;
	} else {
		return type.check(Type);
	}
}

function late(fn) {
	var lateType = {};
	var underlyingType;
	var unwrap = function() {
		underlyingType = type.normalize(fn());
		unwrap = function() { return underlyingType; };
		return underlyingType;
	};
	return canReflect_1_19_2_canReflect.assignSymbols(lateType, {
		"can.new": function(val) {
			return canReflect_1_19_2_canReflect.new(unwrap(), val);
		},
		"can.isMember": function(val) {
			return unwrap()[isMemberSymbol](val);
		}
	});
}

var Any = canReflect_1_19_2_canReflect.assignSymbols({}, {
	"can.new": function(val) { return val; },
	"can.isMember": function() { return true; }
});

function all(typeFn, Type) {
	var typeObject = typeFn(Type);
	typeObject[getSchemaSymbol] = function() {
		var parentSchema = canReflect_1_19_2_canReflect.getSchema(Type);
		var schema = canReflect_1_19_2_canReflect.assignMap({}, parentSchema);
		schema.keys = {};
		canReflect_1_19_2_canReflect.eachKey(parentSchema.keys, function(value, key) {
			schema.keys[key] = typeFn(value);
		});
		return schema;
	};

	function Constructor(values) {
		var schema = canReflect_1_19_2_canReflect.getSchema(this);
		var keys = schema.keys;
		var convertedValues = {};
		canReflect_1_19_2_canReflect.eachKey(values || {}, function(value, key) {
			convertedValues[key] = canReflect_1_19_2_canReflect.convert(value, keys[key]);
		});
		return canReflect_1_19_2_canReflect.new(Type, convertedValues);
	}

	canReflect_1_19_2_canReflect.setName(Constructor, "Converted<" + canReflect_1_19_2_canReflect.getName(Type) + ">");
	Constructor.prototype = typeObject;

	return Constructor;
}

var Integer = {};
Integer[newSymbol] = function(value) {
	// parseInt(notANumber) returns NaN
	// Since we always want an integer returned
	// using |0 instead.
	return value | 0;
};
Integer[isMemberSymbol] = function(value) {
	// “polyfill” for Number.isInteger because it’s not supported in IE11
	return typeof value === "number" && isFinite(value) &&
		Math.floor(value) === value;
};
Integer[getSchemaSymbol] = makeSchema([Number]);
canReflect_1_19_2_canReflect.setName(Integer, "Integer");

function makeCache(fn) {
	var cache = new WeakMap();
	return function(Type) {
		if(cache.has(Type)) {
			return cache.get(Type);
		}
		var typeObject = fn.call(this, Type);
		cache.set(Type, typeObject);
		return typeObject;
	};
}

exports.check = makeCache(function(Type) {
	var o = Object.create(getBaseType(Type));
	o[newSymbol] = strictNew;
	inheritFrom(o, Type, isMemberSymbol);
	inheritFrom(o, Type, getSchemaSymbol);
	canReflect_1_19_2_canReflect.setName(o, wrapName("check", Type));
	return o;
});

exports.convert = makeCache(function(Type) {
	var o = Object.create(getBaseType(Type));
	inheritFrom(o, Type, isMemberSymbol);
	inheritFrom(o, Type, getSchemaSymbol);
	canReflect_1_19_2_canReflect.setName(o, wrapName("convert", Type));
	return o;
});

exports.maybe = makeCache(function(Type) {
	var baseType = getBaseType(Type);
	var desc = {};
	desc[newSymbol] = {
		value: strictNew
	};
	desc[isMemberSymbol] = {
		value: makeMaybe(baseType)
	};
	desc[getSchemaSymbol] = {
		value: makeMaybeSchema(baseType)
	};
	var o = Object.create(baseType, desc);
	canReflect_1_19_2_canReflect.setName(o, wrapName("maybe", Type));
	return o;
});

exports.maybeConvert = makeCache(function(Type) {
	var baseType = getBaseType(Type);
	var desc = {};
	desc[isMemberSymbol] = {
		value: makeMaybe(baseType)
	};
	desc[getSchemaSymbol] = {
		value: makeMaybeSchema(baseType)
	};
	var o = Object.create(baseType, desc);
	canReflect_1_19_2_canReflect.setName(o, wrapName("maybeConvert", Type));
	return o;
});

//!steal-remove-start
// type checking should not throw in production
if(process.env.NODE_ENV === 'production') {
	exports.check = exports.convert;
	exports.maybe = exports.maybeConvert;
}
//!steal-remove-end

exports.Any = Any;
exports.Integer = Integer;

exports.late = late;
exports.isTypeObject = isTypeObject;
exports.normalize = normalize;
exports.all = all;
exports.convertAll = all.bind(null, exports.convert);
canNamespace_1_0_0_canNamespace.type = exports;
});
var canType_1_1_6_canType_1 = canType_1_1_6_canType.check;
var canType_1_1_6_canType_2 = canType_1_1_6_canType.convert;
var canType_1_1_6_canType_3 = canType_1_1_6_canType.maybe;
var canType_1_1_6_canType_4 = canType_1_1_6_canType.maybeConvert;
var canType_1_1_6_canType_5 = canType_1_1_6_canType.Any;
var canType_1_1_6_canType_6 = canType_1_1_6_canType.Integer;
var canType_1_1_6_canType_7 = canType_1_1_6_canType.late;
var canType_1_1_6_canType_8 = canType_1_1_6_canType.isTypeObject;
var canType_1_1_6_canType_9 = canType_1_1_6_canType.normalize;
var canType_1_1_6_canType_10 = canType_1_1_6_canType.all;
var canType_1_1_6_canType_11 = canType_1_1_6_canType.convertAll;

let define; //jshint ignore:line
















const newSymbol$1 = Symbol.for("can.new"),
	serializeSymbol = Symbol.for("can.serialize"),
	inSetupSymbol$2 = Symbol.for("can.initializing"),
	isMemberSymbol$1 = Symbol.for("can.isMember"),
	hasBeenDefinedSymbol = Symbol.for("can.hasBeenDefined"),
	canMetaSymbol = Symbol.for("can.meta"),
	baseTypeSymbol = Symbol.for("can.baseType");

let eventsProto,
	make, makeDefinition, getDefinitionsAndMethods, getDefinitionOrMethod;

// UTILITIES
function isDefineType(func){
	return func && (func.canDefineType === true || func[newSymbol$1] );
}

function observableType() {
	throw new Error("This is not currently implemented.");
}

let AsyncFunction;
const browserSupportsAsyncFunctions = (function() {
	try {
		AsyncFunction = (async function(){}).constructor;
		return true;
	} catch(e) {
		return false;
	}
}());
function isAsyncFunction(fn) {
	if (!browserSupportsAsyncFunctions) {
		return false;
	}
	return fn && fn instanceof AsyncFunction;
}

const peek$2 = canObservationRecorder_1_3_1_canObservationRecorder.ignore(canReflect_1_19_2_canReflect.getValue.bind(canReflect_1_19_2_canReflect));

let Object_defineNamedPrototypeProperty = Object.defineProperty;
//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	Object_defineNamedPrototypeProperty = function(obj, prop, definition) {
		if (definition.get) {
			Object.defineProperty(definition.get, "name", {
				value: "get "+canReflect_1_19_2_canReflect.getName(obj) + "."+prop,
				writable: true,
				configurable: true
			});
		}
		if (definition.set) {
			Object.defineProperty(definition.set, "name", {
				value:  "set "+canReflect_1_19_2_canReflect.getName(obj) + "."+prop,
				configurable: true
			});
		}
		return Object.defineProperty(obj, prop, definition);
	};
}
//!steal-remove-end


function defineConfigurableAndNotEnumerable(obj, prop, value) {
	Object.defineProperty(obj, prop, {
		configurable: true,
		enumerable: false,
		writable: true,
		value: value
	});
}

function defineNotWritableAndNotEnumerable(obj, prop, value) {
	Object.defineProperty(obj, prop, {
		value: value,
		enumerable: false,
		writable: false
	});
}

function eachPropertyDescriptor(map, cb, ...args){
	for(const prop of Object.getOwnPropertyNames(map)) {
		if(map.hasOwnProperty(prop)) {
			cb.call(map, prop, Object.getOwnPropertyDescriptor(map, prop), ...args);
		}
	}
}

function getEveryPropertyAndSymbol(obj) {
	const props = Object.getOwnPropertyNames(obj);
	const symbols = ("getOwnPropertySymbols" in Object) ?
	  Object.getOwnPropertySymbols(obj) : [];
	return props.concat(symbols);
}

var define_1 = define = function(typePrototype, defines, baseDefine, propertyDefaults = {}) {
	// default property definitions on _data
	let prop,
		dataInitializers = Object.create(baseDefine ? baseDefine.dataInitializers : null),
		// computed property definitions on _computed
		computedInitializers = Object.create(baseDefine ? baseDefine.computedInitializers : null),
		required = new Set();

	const result = getDefinitionsAndMethods(defines, baseDefine, typePrototype, propertyDefaults);
	result.dataInitializers = dataInitializers;
	result.computedInitializers = computedInitializers;
	result.required = required;

	// Goes through each property definition and creates
	// a `getter` and `setter` function for `Object.defineProperty`.
	canReflect_1_19_2_canReflect.eachKey(result.definitions, function(definition, property){
		// Add this as a required property
		if(definition.required === true) {
			required.add(property);
		}

		define.property(typePrototype, property, definition, dataInitializers, computedInitializers, result.defaultDefinition);
	});

	// Places a `_data` on the prototype that when first called replaces itself
	// with a `_data` object local to the instance.  It also defines getters
	// for any value that has a default value.
	if(typePrototype.hasOwnProperty("_data")) {
		for (prop in dataInitializers) {
			canDefineLazyValue_1_1_1_defineLazyValue(typePrototype._data, prop, dataInitializers[prop].bind(typePrototype), true);
		}
	} else {
		canDefineLazyValue_1_1_1_defineLazyValue(typePrototype, "_data", function() {
			const map = this;
			const data = {};
			for (const prop in dataInitializers) {
				canDefineLazyValue_1_1_1_defineLazyValue(data, prop, dataInitializers[prop].bind(map), true);
			}
			return data;
		});
	}

	// Places a `_computed` on the prototype that when first called replaces itself
	// with a `_computed` object local to the instance.  It also defines getters
	// that will create the property's compute when read.
	if(typePrototype.hasOwnProperty("_computed")) {
		for (prop in computedInitializers) {
			canDefineLazyValue_1_1_1_defineLazyValue(typePrototype._computed, prop, computedInitializers[prop].bind(typePrototype));
		}
	} else {
		canDefineLazyValue_1_1_1_defineLazyValue(typePrototype, "_computed", function() {
			const map = this;
			const data = Object.create(null);
			for (const prop in computedInitializers) {
				canDefineLazyValue_1_1_1_defineLazyValue(data, prop, computedInitializers[prop].bind(map));
			}
			return data;
		});
	}

	// Add necessary event methods to this object.
	getEveryPropertyAndSymbol(eventsProto).forEach(function(prop){
		Object.defineProperty(typePrototype, prop, {
			enumerable: false,
			value: eventsProto[prop],
			configurable: true,
			writable: true
		});
	});
	// also add any symbols
	// add so instance defs can be dynamically added
	Object.defineProperty(typePrototype,"_define",{
		enumerable: false,
		value: result,
		configurable: true,
		writable: true
	});

	// Places Symbol.iterator or @@iterator on the prototype
	// so that this can be iterated with for/of and canReflect.eachIndex
	const iteratorSymbol = Symbol.iterator || Symbol.for("iterator");
	if(!typePrototype[iteratorSymbol]) {
		defineConfigurableAndNotEnumerable(typePrototype, iteratorSymbol, function(){
			return new define.Iterator(this);
		});
	}

	return result;
};

const onlyType = function(obj){
	for(const prop in obj) {
		if(prop !== "type") {
			return false;
		}
	}
	return true;
};

const callAsync = function(fn) {
	return function asyncResolver(lastSet, resolve){
		let newValue = fn.call(this, resolve, lastSet);

		// This should really be happening in can-simple-observable/async/
		// But that would be a breaking change so putting it here.
		if(canReflect_1_19_2_canReflect.isPromise(newValue)) {
			newValue.then(resolve);
			return undefined;
		}

		return newValue;
	};
};

define.extensions = function () {};

define.isEnumerable = function(definition) {
	return typeof definition !== "object" ||
		("serialize" in definition ?
			!!definition.serialize :
			(!definition.get && !definition.async && !definition.value));
};

// typePrototype - the prototype of the type we are defining `prop` on.
// `definition` - the user provided definition
define.property = function(typePrototype, prop, definition, dataInitializers, computedInitializers, defaultDefinition) {
	const propertyDefinition = define.extensions.apply(this, arguments);

	if (propertyDefinition) {
		definition = makeDefinition(prop, propertyDefinition, defaultDefinition || {}, typePrototype);
	}

	const type = definition.type;

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		if(!definition.set && definition.get && definition.get.length === 0 && ( "default" in definition ) ) {
			dev.warn("can-observable-object: default value for property " +
					canReflect_1_19_2_canReflect.getName(typePrototype)+"."+ prop +
					" ignored, as its definition has a zero-argument getter and no setter");
		}

	if(!definition.set && definition.get && definition.get.length === 0 && ( definition.type && definition.type !== defaultDefinition.type ) ) {
			dev.warn("can-observable-object: type value for property " +
					canReflect_1_19_2_canReflect.getName(typePrototype)+"."+ prop +
					" ignored, as its definition has a zero-argument getter and no setter");
		}
	}

	for (let defFuncProp of ['get', 'set', 'value']) {
		const propType = definition[defFuncProp] && typeof definition[defFuncProp];
		if (propType && propType !== 'function') {
			dev.error(`can-observable-object: "${defFuncProp}" for property ${canReflect_1_19_2_canReflect.getName(typePrototype)}.${prop}` +
				` is expected to be a function, but it's a ${propType}.`);
			return;
		}
	}
	//!steal-remove-end

	// Special case definitions that have only `type: "*"`.
	if (type && onlyType(definition) && type === type.Any) {
		Object_defineNamedPrototypeProperty(typePrototype, prop, {
			get: make.get.data(prop),
			set: make.set.events(prop, make.get.data(prop), make.set.data(prop), make.eventType.data(prop)),
			enumerable: true,
			configurable: true
		});
		return;
	}
	definition.type = type;

	// Where the value is stored.  If there is a `get` the source of the value
	// will be a compute in `this._computed[prop]`.  If not, the source of the
	// value will be in `this._data[prop]`.
	let dataProperty = definition.get || definition.async || definition.value ? "computed" : "data",

		// simple functions that all read/get/set to the right place.
		// - reader - reads the value but does not observe.
		// - getter - reads the value and notifies observers.
		// - setter - sets the value.
		reader = make.read[dataProperty](prop),
		getter = make.get[dataProperty](prop),
		setter = make.set[dataProperty](prop),
		getInitialValue;

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		if (definition.get) {
			Object.defineProperty(definition.get, "name", {
				value: canReflect_1_19_2_canReflect.getName(typePrototype) + "'s " + prop + " getter",
				configurable: true
			});
		}
		if (definition.set) {
			Object.defineProperty(definition.set, "name", {
				value: canReflect_1_19_2_canReflect.getName(typePrototype) + "'s " + prop + " setter",
				configurable: true
			});
		}
		if(definition.value) {
			Object.defineProperty(definition.value, "name", {
				value: canReflect_1_19_2_canReflect.getName(typePrototype) + "'s " + prop + " value",
				configurable: true
			});
		}
	}
	//!steal-remove-end

	// Determine the type converter
	let typeConvert = function(val) {
		return val;
	};

	if (type) {
		typeConvert = make.set.type(prop, type, typeConvert);
	}

	// make a setter that's going to fire of events
	const eventsSetter = make.set.events(prop, reader, setter, make.eventType[dataProperty](prop));
	if(definition.value) {
		computedInitializers[prop] = make.resolver(prop, definition, typeConvert);
	}
	// Determine a function that will provide the initial property value.
	else if (definition.default !== undefined) {

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			// If value is an object or array, give a warning
			if (definition.default !== null && typeof definition.default === 'object') {
				dev.warn("can-observable-object: The default value for " + canReflect_1_19_2_canReflect.getName(typePrototype)+"."+prop + " is set to an object. This will be shared by all instances of the DefineMap. Use a function that returns the object instead.");
			}
			// If value is a constructor, give a warning
			if (definition.default && canReflect_1_19_2_canReflect.isConstructorLike(definition.default)) {
				dev.warn("can-observable-object: The \"default\" for " + canReflect_1_19_2_canReflect.getName(typePrototype)+"."+prop + " is set to a constructor. Did you mean \"Default\" instead?");
			}
		}
		//!steal-remove-end

		getInitialValue = canObservationRecorder_1_3_1_canObservationRecorder.ignore(make.get.defaultValue(prop, definition, typeConvert, eventsSetter));
	}

	// If property has a getter, create the compute that stores its data.
	if (definition.get) {
		computedInitializers[prop] = make.compute(prop, definition.get, getInitialValue);
	}
	else if (definition.async) {
		computedInitializers[prop] = make.compute(prop, callAsync(definition.async), getInitialValue);
	}
	// If the property isn't a getter, but has an initial value, setup a
	// default value on `this._data[prop]`.
	else if (getInitialValue) {
		dataInitializers[prop] = getInitialValue;
	}

	// Define setter behavior.

	// If there's a `get` and `set`, make the setter get the `lastSetValue` on the
	// `get`'s compute.
	if (definition.get && definition.set) {
		// the compute will set off events, so we can use the basic setter
		setter = make.set.setter(prop, definition.set, make.read.lastSet(prop), setter, true);
	}
	// If there's a `set` and no `get`,
	else if (definition.set) {
		// Add `set` functionality to the eventSetter.
		setter = make.set.setter(prop, definition.set, reader, eventsSetter, false);
	}
	// If there's neither `set` or `get` or `value` (resolver)
	else if (dataProperty === "data") {
		// make a set that produces events.
		setter = eventsSetter;
	}
	// If there's zero-arg `get` but not `set`, warn on all sets in dev mode
	else if (definition.get && definition.get.length < 1) {
		setter = function() {
			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				dev.warn("can-observable-object: Set value for property " +
					canReflect_1_19_2_canReflect.getName(typePrototype)+"."+ prop +
					" ignored, as its definition has a zero-argument getter and no setter");
			}
			//!steal-remove-end
		};
	}

	// Add type behavior to the setter.
	if (type) {
		setter = make.set.type(prop, type, setter);
	}

	// Define the property.
	Object_defineNamedPrototypeProperty(typePrototype, prop, {
		get: getter,
		set: setter,
		enumerable: define.isEnumerable(definition),
		configurable: true
	});
};

define.makeDefineInstanceKey = function(constructor) {
	constructor[Symbol.for("can.defineInstanceKey")] = function(property, value) {
		define.hooks.finalizeClass(this);
		const defineResult = this.prototype._define;
		if(value && typeof value.value !== "undefined") {
			value.default = value.value;
			value.type = canType_1_1_6_canType.Any;
			delete value.value;
		}
		const definition = getDefinitionOrMethod(property, value, defineResult.defaultDefinition, this);
		if(definition && typeof definition === "object") {
			define.property(this.prototype, property, definition, defineResult.dataInitializers, defineResult.computedInitializers, defineResult.defaultDefinition);
			defineResult.definitions[property] = definition;
		} else {
			defineResult.methods[property] = definition;
		}

		this.prototype.dispatch({
			action: "can.keys",
			type: "can.keys",
			target: this.prototype
		});
	};
};

// Makes a simple constructor function.
define.Constructor = function(defines, sealed) {
	const constructor = function DefineConstructor(props) {
		Object.defineProperty(this, inSetupSymbol$2, {
			configurable: true,
			enumerable: false,
			value: true,
			writable: true
		});
		define.setup.call(this, props, sealed);
		this[inSetupSymbol$2] = false;
	};
	const result = define(constructor.prototype, defines);
	type$1(constructor);
	define.makeDefineInstanceKey(constructor, result);
	return constructor;
};

// A bunch of helper functions that are used to create various behaviors.
make = {
	computeObj: function(map, prop, observable) {
		const computeObj = {
			oldValue: undefined,
			compute: observable,
			count: 0,
			handler: function(newVal) {
				let oldValue = computeObj.oldValue;
				computeObj.oldValue = newVal;

				map.dispatch({
					action: "prop",
					key: prop,
					value: newVal,
					oldValue: oldValue,
					type: prop,
					target: map
				}, [newVal, oldValue]);
			}
		};
		return computeObj;
	},
	resolver: function(prop, definition, typeConvert) {
		const getDefault = make.get.defaultValue(prop, definition, typeConvert);
		return function(){
			const map = this;
			const defaultValue = getDefault.call(this);
			const computeObj = make.computeObj(map, prop, new resolver(definition.value, map, defaultValue, {
				resetUnboundValueInGet: true
			}));
			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				Object.defineProperty(computeObj.handler, "name", {
					value: canReflect_1_19_2_canReflect.getName(definition.value).replace('value', 'event emitter')
				});
			}
			//!steal-remove-end
			return computeObj;
		};
	},
	// Returns a function that creates the `_computed` prop.
	compute: function(prop, get, defaultValueFn) {

		return function() {
			const map = this;
			const defaultValue = defaultValueFn && defaultValueFn.call(this);
			let observable, computeObj;

			if(get.length === 0) {
				observable = new canObservation_4_2_0_canObservation(get, map);
			} else if(get.length === 1) {
				observable = new settable(get, map, defaultValue);
			} else {
				observable = new async(get, map, defaultValue);
			}

			computeObj = make.computeObj(map, prop, observable);

			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				Object.defineProperty(computeObj.handler, "name", {
					value: canReflect_1_19_2_canReflect.getName(get).replace('getter', 'event emitter')
				});
			}
			//!steal-remove-end

			return computeObj;
		};
	},
	// Set related helpers.
	set: {
		data: function(prop) {
			return function(newVal) {
				this._data[prop] = newVal;
			};
		},
		computed: function(prop) {
			return function(val) {
				canReflect_1_19_2_canReflect.setValue( this._computed[prop].compute, val );
			};
		},
		events: function(prop, getCurrent, setData/*, eventType*/) {
			return function(newVal) {
				if (this[inSetupSymbol$2]) {
					setData.call(this, newVal);
				}
				else {
					const current = getCurrent.call(this);
					if (newVal !== current) {
						let dispatched;
						setData.call(this, newVal);

						dispatched = {
							patches: [{type: "set", key: prop, value: newVal}],
							action: "prop",
							key: prop,
							value: newVal,
							oldValue: current,
							type: prop,
							target: this
						};

						//!steal-remove-start
						if(process.env.NODE_ENV !== 'production') {
							dispatched.reasonLog = [ canReflect_1_19_2_canReflect.getName(this) + "'s", prop, "changed to", newVal, "from", current ];
						}
						//!steal-remove-end

						this.dispatch(dispatched, [newVal, current]);
					}
				}
			};
		},
		eventDispatcher: function(map, prop, current, newVal) {
			if (map[inSetupSymbol$2]) {
				return;
			}
			else {
				if (newVal !== current) {
					const dispatched = {
						patches: [{type: "set", key: prop, value: newVal}],
						action: "prop",
						key: prop,
						value: newVal,
						oldValue: current,
						type: prop,
						target: map
					};

					//!steal-remove-start
					if(process.env.NODE_ENV !== 'production') {
						dispatched.reasonLog = [ canReflect_1_19_2_canReflect.getName(this) + "'s", prop, "changed to", newVal, "from", current ];
					}
					//!steal-remove-end

					map$1.dispatch.call(map, dispatched, [newVal, current]);
				}
			}
		},
		setter: function(prop, setter, getCurrent, setEvents, hasGetter) {
			return function(value) {
				//!steal-remove-start
				var asyncTimer;
				//!steal-remove-end

				const self = this;

				// call the setter, if returned value is undefined,
				// this means the setter is async so we
				// do not call update property and return right away

				canQueues_1_3_2_canQueues.batch.start();
				const setterCalled = false,
					current = getCurrent.call(this),
					setValue = setter.call(this, value, current);

				if (setterCalled) {
					canQueues_1_3_2_canQueues.batch.stop();
				} else {
					if (hasGetter) {
						// we got a return value
						if (setValue !== undefined) {
							// if the current `set` value is returned, don't set
							// because current might be the `lastSetVal` of the internal compute.
							if (current !== setValue) {
								setEvents.call(this, setValue);
							}
							canQueues_1_3_2_canQueues.batch.stop();
						}
						// this is a side effect, it didn't take a value
						// so use the original set value
						else if (setter.length === 0) {
							setEvents.call(this, value);
							canQueues_1_3_2_canQueues.batch.stop();
							return;
						}
						// it took a value
						else if (setter.length === 1) {
							// if we have a getter, and undefined was returned,
							// we should assume this is setting the getters properties
							// and we shouldn't do anything.
							canQueues_1_3_2_canQueues.batch.stop();
						}
						// we are expecting something
						else {
							//!steal-remove-start
							if(process.env.NODE_ENV !== 'production') {
								asyncTimer = setTimeout(function() {
									dev.warn('can-observable-object: Setter "' + canReflect_1_19_2_canReflect.getName(self)+"."+prop + '" did not return a value or call the setter callback.');
								}, dev.warnTimeout);
							}
							//!steal-remove-end
							canQueues_1_3_2_canQueues.batch.stop();
							return;
						}
					} else {
						// we got a return value
						if (setValue !== undefined) {
							// if the current `set` value is returned, don't set
							// because current might be the `lastSetVal` of the internal compute.
							setEvents.call(this, setValue);
							canQueues_1_3_2_canQueues.batch.stop();
						}
						// this is a side effect, it didn't take a value
						// so use the original set value
						else if (setter.length === 0) {
							setEvents.call(this, value);
							canQueues_1_3_2_canQueues.batch.stop();
							return;
						}
						// it took a value
						else if (setter.length === 1) {
							// if we don't have a getter, we should probably be setting the
							// value to undefined
							setEvents.call(this, undefined);
							canQueues_1_3_2_canQueues.batch.stop();
						}
						// we are expecting something
						else {
							//!steal-remove-start
							if(process.env.NODE_ENV !== 'production') {
								asyncTimer = setTimeout(function() {
									dev.warn('can/map/setter.js: Setter "' + canReflect_1_19_2_canReflect.getName(self)+"."+prop + '" did not return a value or call the setter callback.');
								}, dev.warnTimeout);
							}
							//!steal-remove-end
							canQueues_1_3_2_canQueues.batch.stop();
							return;
						}
					}
				}
			};
		},
		type: function(prop, type, set) {
			function setter(newValue) {
				return set.call(this, type.call(this, newValue, prop));
			}
			if(isDefineType(type)) {
				// TODO: remove this `canDefineType` check in a future release.
				if(type.canDefineType) {
					return setter;
				} else {
					return function setter(newValue){
						//!steal-remove-start
						if(process.env.NODE_ENV !== 'production') {
							try {
								return set.call(this, canReflect_1_19_2_canReflect.convert(newValue, type));
							} catch (error) {
								if (error.type === 'can-type-error') {
									const typeName = canReflect_1_19_2_canReflect.getName(type[baseTypeSymbol]);
									const valueType = typeof newValue;
									let message  = '"' + newValue + '"' +  ' ('+ valueType + ') is not of type ' + typeName + '. Property ' + prop + ' is using "type: ' + typeName + '". ';
									message += 'Use "' + prop + ': type.convert(' + typeName + ')" to automatically convert values to ' + typeName + 's when setting the "' + prop + '" property.';
									error.message = message;
									
								}
								throw error;
							}
						}
						//!steal-remove-end
						return set.call(this, canReflect_1_19_2_canReflect.convert(newValue, type));
					};
				}
			}
			return setter;
		}
	},
	// Helpes that indicate what the event type should be.  These probably aren't needed.
	eventType: {
		data: function(prop) {
			return function(newVal, oldVal) {
				return oldVal !== undefined || this._data.hasOwnProperty(prop) ? "set" : "add";
			};
		},
		computed: function() {
			return function() {
				return "set";
			};
		}
	},
	// Helpers that read the data in a non-observable way.
	read: {
		data: function(prop) {
			return function() {
				return this._data[prop];
			};
		},
		computed: function(prop) {
			// might want to protect this
			return function() {
				return canReflect_1_19_2_canReflect.getValue( this._computed[prop].compute );
			};
		},
		lastSet: function(prop) {
			return function() {
				const observable = this._computed[prop].compute;
				if(observable.lastSetValue) {
					return canReflect_1_19_2_canReflect.getValue(observable.lastSetValue);
				}
			};
		}
	},
	// Helpers that read the data in an observable way.
	get: {
		// uses the default value
		defaultValue: function(prop, definition, typeConvert, callSetter) {
			return function() {
				let value = definition.default;
				if (value !== undefined) {
					// call `get default() { ... }` but not `default() { ... }`
					if (typeof value === "function" && value.isAGetter) {
						value = value.call(this);
					}
					value = typeConvert.call(this, value);
				}
				if(definition.set) {
					// TODO: there's almost certainly a faster way of making this happen
					// But this is maintainable.

					let VALUE;
					let sync = true;

					const setter = make.set.setter(prop, definition.set, function(){}, function(value){
						if(sync) {
							VALUE = value;
						} else {
							callSetter.call(this, value);
						}
					}, definition.get);

					setter.call(this,value);
					sync = false;

					// VALUE will be undefined if the callback is never called.
					return VALUE;


				}
				return value;
			};
		},
		data: function(prop) {
			return function() {
				if (!this[inSetupSymbol$2]) {
					canObservationRecorder_1_3_1_canObservationRecorder.add(this, prop);
				}

				return this._data[prop];
			};
		},
		computed: function(prop) {
			return function(/*val*/) {
				const compute = this._computed[prop].compute;
				if (canObservationRecorder_1_3_1_canObservationRecorder.isRecording()) {
					canObservationRecorder_1_3_1_canObservationRecorder.add(this, prop);
					if (!canReflect_1_19_2_canReflect.isBound(compute)) {
						canObservation_4_2_0_canObservation.temporarilyBind(compute);
					}
				}

				return peek$2(compute);
			};
		}
	}
};

define.behaviors = ["get", "set", "value", "type", "serialize"];

// This cleans up a particular behavior and adds it to the definition
const addBehaviorToDefinition = function(definition, behavior, descriptor, def, prop, typePrototype) {
	if(behavior === "enumerable") {
		// treat enumerable like serialize
		definition.serialize = !!def[behavior];
	}
	else if(behavior === "type") {
		const behaviorDef = def[behavior];
		if (typeof behaviorDef !== 'undefined') {
			definition[behavior] = behaviorDef;
		}
	}
	else {
		// This is a good place to do warnings? This gets called for every behavior
		// Both by .define() and .property()
		const value = descriptor.get || descriptor.value;
		if (descriptor.get) {
			value.isAGetter = true;
		}
		if(behavior === "async") {
			if(value.length === 1 && isAsyncFunction(value)) {
				dev.warn(`${canReflect_1_19_2_canReflect.getName(typePrototype)}: async property [${prop}] should not be an async function and also use the resolve() argument. Remove the argument and return a value from the async function instead.`);
			}
		}

		definition[behavior] = value;
	}
};

// This is called by `define.property` AND `getDefinitionOrMethod` (which is called by `define`)
// Currently, this is adding default behavior
// copying `type` over, and even cleaning up the final definition object
makeDefinition = function(prop, def, defaultDefinition, typePrototype) {
	let definition = {};

	eachPropertyDescriptor(def, function(behavior, descriptor) {
		addBehaviorToDefinition(definition, behavior, descriptor, def, prop, typePrototype);
	});
	// only add default if it doesn't exist
	canReflect_1_19_2_canReflect.eachKey(defaultDefinition, function(value, prop){
		if(definition[prop] === undefined) {
			if(prop !== "type") {
				definition[prop] = value;
			}
		}
	});

	if (def.type) {
		const value = def.type;
		const serialize = value[serializeSymbol];
		if(serialize) {
			definition.serialize = function(val){
				return serialize.call(val);
			};
		}
		definition.type = canType_1_1_6_canType.normalize(value);
	}

	const noTypeDefined = !definition.type && (!defaultDefinition.type ||
		defaultDefinition.type && defaultDefinition.typeSetByDefault);

	if (definition.hasOwnProperty("default")) {
		if (typeof definition.default === "function" && !definition.default.isAGetter && noTypeDefined) {
			definition.type = canType_1_1_6_canType.normalize(Function);
		}

		if (canReflect_1_19_2_canReflect.isPrimitive(definition.default) && noTypeDefined) {
			if (definition.default === null || typeof definition.default === 'undefined') {
				definition.type = canType_1_1_6_canType.Any;
			} else {
				definition.type = canType_1_1_6_canType.normalize(definition.default.constructor);
			}
		}
	}

	// if there's no type definition, take it from the defaultDefinition
	if(!definition.type) {
		const defaultsCopy = canReflect_1_19_2_canReflect.assignMap({}, defaultDefinition);
		definition = canReflect_1_19_2_canReflect.assignMap(defaultsCopy, definition);
	}

	if(canReflect_1_19_2_canReflect.size(definition) === 0) {
		definition.type = canType_1_1_6_canType.Any;
		// `setByDefault` indicates that the default type can be
		// overridden by an inferred type
		definition.typeSetByDefault = true;
	}

	return definition;
};

// called by `can.defineInstanceKey` and `getDefinitionsAndMethods`
// returns the value or the definition object.
// calls makeDefinition
// This is dealing with a string value
getDefinitionOrMethod = function(prop, value, defaultDefinition, typePrototype){
	// Clean up the value to make it a definition-like object
	let definition;
	let definitionType;
	if(canReflect_1_19_2_canReflect.isPrimitive(value)) {
		if (value === null || typeof value === 'undefined') {
			definitionType = canType_1_1_6_canType.Any;
		} else {
			// only include type from defaultDefininition
			// if it came from propertyDefaults
			definitionType = defaultDefinition.typeSetByDefault ?
				canType_1_1_6_canType.normalize(value.constructor) :
				defaultDefinition.type;
		}
		definition = {
			default: value,
			type: definitionType
		};
	}
    // copies a `Type`'s methods over
	else if(value && (value[serializeSymbol] || value[newSymbol$1]) ) {
		if(value[isMemberSymbol$1]) {
			definition = { type: value };
		} else {
			definition = { type: canType_1_1_6_canType.normalize(value) };
		}
	}
	else if(typeof value === "function") {
		if(canReflect_1_19_2_canReflect.isConstructorLike(value)) {
			definition = { type: canType_1_1_6_canType.normalize(value) };
		} else {
			definition = { default: value, type: Function };
		}
	} else if( Array.isArray(value) ) {
		definition = { type: canType_1_1_6_canType.normalize(Array) };
	} else if( canReflect_1_19_2_canReflect.isPlainObject(value) ){
		definition = value;
	}

	if(definition) {
		return makeDefinition(prop, definition, defaultDefinition, typePrototype);
	}
	else {
		return value;
	}
};
// called by can.define
getDefinitionsAndMethods = function(defines, baseDefines, typePrototype, propertyDefaults) {
	// make it so the definitions include base definitions on the proto
	const definitions = Object.create(baseDefines ? baseDefines.definitions : null);
	let methods = {};
	// first lets get a default if it exists
	let defaultDefinition;
	if(propertyDefaults) {
		defaultDefinition = getDefinitionOrMethod("*", propertyDefaults, {}, typePrototype);
	} else {
		defaultDefinition = Object.create(null);
	}

	function addDefinition(prop, propertyDescriptor, skipGetDefinitionForMethods) {
		let value;
		if(propertyDescriptor.get || propertyDescriptor.set) {
			value = { get: propertyDescriptor.get, set: propertyDescriptor.set };
		} else {
			value = propertyDescriptor.value;
		}

		if(prop === "constructor" || skipGetDefinitionForMethods && typeof value === "function") {
			methods[prop] = value;
			return;
		} else {
			const result = getDefinitionOrMethod(prop, value, defaultDefinition, typePrototype);
			const resultType = typeof result;
			if(result && resultType === "object" && canReflect_1_19_2_canReflect.size(result) > 0) {
				definitions[prop] = result;
			}
			else {
				// Removed adding raw values that are not functions
				if (resultType === "function") {
					methods[prop] = result;
				}
				//!steal-remove-start
				else if (resultType !== 'undefined') {
					if(process.env.NODE_ENV !== 'production') {
						// Ex: {prop: 0}
						dev.error(canReflect_1_19_2_canReflect.getName(typePrototype)+"."+prop + " does not match a supported definitionObject. See: https://canjs.com/doc/can-observable-object/object.types.definitionObject.html");
					}
				}
				//!steal-remove-end
			}
		}
	}

	eachPropertyDescriptor(typePrototype, addDefinition, true);
	eachPropertyDescriptor(defines, addDefinition);
	if(propertyDefaults) {
		// we should move this property off the prototype.
		defineConfigurableAndNotEnumerable(defines, "*", propertyDefaults);
	}
	return { definitions: definitions, methods: methods, defaultDefinition: defaultDefinition };
};

eventsProto = map$1({});

function setupComputed(instance, eventName) {
	const computedBinding = instance._computed && instance._computed[eventName];
	if (computedBinding && computedBinding.compute) {
		if (!computedBinding.count) {
			computedBinding.count = 1;
			canReflect_1_19_2_canReflect.onValue(computedBinding.compute, computedBinding.handler, "notify");
			computedBinding.oldValue = peek$2(computedBinding.compute);
		} else {
			computedBinding.count++;
		}

	}
}
function teardownComputed(instance, eventName){
	const computedBinding = instance._computed && instance._computed[eventName];
	if (computedBinding) {
		if (computedBinding.count === 1) {
			computedBinding.count = 0;
			canReflect_1_19_2_canReflect.offValue(computedBinding.compute, computedBinding.handler,"notify");
		} else {
			computedBinding.count--;
		}
	}
}

canAssign_1_3_3_canAssign(eventsProto, {
	_eventSetup: function() {},
	_eventTeardown: function() {},
	addEventListener: function(eventName/*, handler, queue*/) {
		setupComputed(this, eventName);
		return map$1.addEventListener.apply(this, arguments);
	},

	// ### unbind
	// Stops listening to an event.
	// If this is the last listener of a computed property,
	// stop forwarding events of the computed property to this map.
	removeEventListener: function(eventName/*, handler*/) {
		teardownComputed(this, eventName);
		return map$1.removeEventListener.apply(this, arguments);

	}
});
eventsProto.on = eventsProto.bind = eventsProto.addEventListener;
eventsProto.off = eventsProto.unbind = eventsProto.removeEventListener;


const onKeyValueSymbol$2 = Symbol.for("can.onKeyValue");
const offKeyValueSymbol$1 = Symbol.for("can.offKeyValue");

canReflect_1_19_2_canReflect.assignSymbols(eventsProto,{
	"can.onKeyValue": function(key){
		setupComputed(this, key);
		return map$1[onKeyValueSymbol$2].apply(this, arguments);
	},
	"can.offKeyValue": function(key){
		teardownComputed(this, key);
		return map$1[offKeyValueSymbol$1].apply(this, arguments);
	}
});

delete eventsProto.one;

define.finalizeInstance = function() {
	defineNotWritableAndNotEnumerable(this, "constructor", this.constructor);
	defineNotWritableAndNotEnumerable(this, canMetaSymbol, Object.create(null));
};

define.setup = function(props, sealed) {
	const requiredButNotProvided = new Set(this._define.required);
	const definitions = this._define.definitions;
	const instanceDefinitions = Object.create(null);
	const map = this;
	canReflect_1_19_2_canReflect.eachKey(props, function(value, prop){
		if(requiredButNotProvided.has(prop)) {
			requiredButNotProvided.delete(prop);
		}
		if(definitions[prop] !== undefined) {
			map[prop] = value;
		} else {
			if(sealed) {
				throw new Error(`The type ${canReflect_1_19_2_canReflect.getName(map.constructor)} is sealed, but the property [${prop}] has no definition.`);
			}

			define.expando(map, prop, value);
		}
	});
	if(canReflect_1_19_2_canReflect.size(instanceDefinitions) > 0) {
		defineConfigurableAndNotEnumerable(this, "_instanceDefinitions", instanceDefinitions);
	}
	if(requiredButNotProvided.size) {
		let msg;
		const missingProps = Array.from(requiredButNotProvided);
		let thisName = canReflect_1_19_2_canReflect.getName(this);
		if(requiredButNotProvided.size === 1) {
			msg = `${thisName}: Missing required property [${missingProps[0]}].`;
		} else {
			msg = `${thisName}: Missing required properties [${missingProps.join(", ")}].`;
		}

		throw new Error(msg);
	}
};


const returnFirstArg = function(arg){
	return arg;
};

// TODO Why is this exported, does it need to be?
define.normalizeTypeDefinition = canType_1_1_6_canType.normalize;

define.expando = function(map, prop, value) {
	if(define._specialKeys[prop]) {
		// ignores _data and _computed
		return true;
	}
	// first check if it's already a constructor define
	const constructorDefines = map._define.definitions;
	if(constructorDefines && constructorDefines[prop]) {
		return;
	}
	// next if it's already on this instances
	let instanceDefines = map._instanceDefinitions;
	if(!instanceDefines) {
		if(Object.isSealed(map)) {
			let errorMessage = `Cannot set property [${prop}] on sealed instance of ${canReflect_1_19_2_canReflect.getName(map)}`;
			throw new Error(errorMessage);
		}
		Object.defineProperty(map, "_instanceDefinitions", {
			configurable: true,
			enumerable: false,
			writable: true,
			value: {}
		});
		instanceDefines = map._instanceDefinitions;
	}
	if(!instanceDefines[prop]) {
		const defaultDefinition = map._define.defaultDefinition || { type: observableType };
		define.property(map, prop, defaultDefinition, {},{});
		// possibly convert value to List or DefineMap
		if(defaultDefinition.type) {
			map._data[prop] = define.make.set.type(prop, defaultDefinition.type, returnFirstArg).call(map, value);
		} else {
			map._data[prop] = observableType(value);
		}

		instanceDefines[prop] = defaultDefinition;
		if(!map[inSetupSymbol$2]) {
			canQueues_1_3_2_canQueues.batch.start();
			map.dispatch({
				action: "can.keys",
				type: "can.keys",
				target: map
			});
			if(Object.prototype.hasOwnProperty.call(map._data, prop)) {
				map.dispatch({
					action: "add",
					key: prop,
					type: prop,
					value: map._data[prop],
					target: map,
					patches: [{type: "add", key: prop, value: map._data[prop]}],
				},[map._data[prop], undefined]);
			} else {
				map.dispatch({
					action: "set",
					type: "set",
					value: map._data[prop],
					target: map,
					patches: [{type: "add", key: prop, value: map._data[prop]}],
				},[map._data[prop], undefined]);
			}
			canQueues_1_3_2_canQueues.batch.stop();
		}
		return true;
	}
};
define.replaceWith = canDefineLazyValue_1_1_1_defineLazyValue;
define.eventsProto = eventsProto;
define.defineConfigurableAndNotEnumerable = defineConfigurableAndNotEnumerable;
define.make = make;
define.getDefinitionOrMethod = getDefinitionOrMethod;
define._specialKeys = {_data: true, _computed: true};
let simpleGetterSetters = {};
define.makeSimpleGetterSetter = function(prop){
	if(simpleGetterSetters[prop] === undefined) {

		const setter = make.set.events(prop, make.get.data(prop), make.set.data(prop), make.eventType.data(prop) );

		simpleGetterSetters[prop] = {
			get: make.get.data(prop),
			set: function(newVal){
				return setter.call(this, observableType(newVal));
			},
			enumerable: true,
            configurable: true
		};
	}
	return simpleGetterSetters[prop];
};

define.Iterator = function(obj){
	this.obj = obj;
	this.definitions = Object.keys(obj._define.definitions);
	this.instanceDefinitions = obj._instanceDefinitions ?
		Object.keys(obj._instanceDefinitions) :
		Object.keys(obj);
	this.hasGet = typeof obj.get === "function";
};

define.Iterator.prototype.next = function(){
	let key;
	if(this.definitions.length) {
		key = this.definitions.shift();

		// Getters should not be enumerable
		const def = this.obj._define.definitions[key];
		if(def.get) {
			return this.next();
		}
	} else if(this.instanceDefinitions.length) {
		key = this.instanceDefinitions.shift();
	} else {
		return {
			value: undefined,
			done: true
		};
	}

	return {
		value: [
			key,
			this.hasGet ? this.obj.get(key) : this.obj[key]
		],
		done: false
	};
};

define.updateSchemaKeys = function(schema, definitions) {
	for(const prop in definitions) {
		const definition = definitions[prop];
		if(definition.serialize !== false ) {
			if(definition.type) {
				schema.keys[prop] = definition.type;
			} else {
				schema.keys[prop] = function(val){ return val; };
			}
			 // some unknown type
			if(definitions[prop].identity === true) {
				schema.identity.push(prop);
			}
		}
	}
	return schema;
};


define.hooks = {
	finalizeClass: function(Type) {
		let hasBeenDefined = Type.hasOwnProperty(hasBeenDefinedSymbol);
		if(!hasBeenDefined) {
			let prototypeObject = Type.prototype;
			// check for `static props = {}`
			// fall back to `static define = {}` if `props` doesn't exist
			let defines = typeof Type.props === "object" ?
				Type.props :
				typeof Type.define === "object" ?
					Type.define :
					{};
			define(prototypeObject, defines, null, Type.propertyDefaults);
			Type[hasBeenDefinedSymbol] = true;
		}
	},
	initialize: function(instance, props) {
		const firstInitialize = !instance.hasOwnProperty(canMetaSymbol);
		const sealed = instance.constructor.seal;

		if (firstInitialize) {
			define.finalizeInstance.call(instance);
		}

		if (!instance[canMetaSymbol].initialized) {
			defineConfigurableAndNotEnumerable(instance, inSetupSymbol$2, true);

			define.setup.call(instance, props, sealed);

			// set inSetup to false so events can be dispatched
			instance[inSetupSymbol$2] = false;

			// set instance as initialized so this is only called once
			instance[canMetaSymbol].initialized = true;
		}

		// only seal in dev mode for performance reasons.
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			// only seal the first time initialize is called
			// even if meta.initialized is reset to false
			if (firstInitialize) {
				/* jshint -W030 */
				instance._data;
				instance._computed;
				if(sealed === true) {
					Object.seal(instance);
				}
			}
		}
		//!steal-remove-end
	},
	expando: define.expando,
	normalizeTypeDefinition: canType_1_1_6_canType.normalize //define.normalizeTypeDefinition
};

// Ensure the "obj" passed as an argument has an object on @@can.meta
var ensureMeta$3 = function ensureMeta(obj) {
	const metaSymbol = Symbol.for("can.meta");
	let meta = obj[metaSymbol];

	if (!meta) {
		meta = {};
		canReflect_1_19_2_canReflect.setKeyValue(obj, metaSymbol, meta);
	}

	return meta;
};

/*jshint -W079 */






const defineHelpers = {
	// returns `true` if the value was defined and set
	defineExpando: define_1.expando,
	reflectSerialize: function(unwrapped){
		const constructorDefinitions = this._define.definitions;
		const defaultDefinition = this._define.defaultDefinition;
		this.forEach(function(val, name){
			const propDef = constructorDefinitions[name];

			if(propDef && typeof propDef.serialize === "function") {
				val = propDef.serialize.call(this, val, name);
			}
			else if(defaultDefinition && typeof defaultDefinition.serialize === "function") {
				val =  defaultDefinition.serialize.call(this, val, name);
			} else {
				val = canReflect_1_19_2_canReflect.serialize(val);
			}
			if(val !== undefined) {
				unwrapped[name] = val;
			}
		}, this);
		return unwrapped;
	},
	reflectUnwrap: function(unwrapped){
		this.forEach(function(value, key){
			if(value !== undefined) {
				unwrapped[key] = canReflect_1_19_2_canReflect.unwrap(value);
			}
		});
		return unwrapped;
	},
	log: function(key) {
		const instance = this;

		const quoteString = function quoteString(x) {
			return typeof x === "string" ? JSON.stringify(x) : x;
		};

		const meta = ensureMeta$3(instance);
		const allowed = meta.allowedLogKeysSet || new Set();
		meta.allowedLogKeysSet = allowed;

		if (key) {
			allowed.add(key);
		}

		meta._log = function(event, data) {
			const type = event.type;

			if (
				type === "can.onPatches" || (key && !allowed.has(type)) ||
				type === "can.keys" || (key && !allowed.has(type))
				) {
				return;
			}

			if (type === "add" || type === "remove") {
				dev.log(
					canReflect_1_19_2_canReflect.getName(instance),
					"\n how   ", quoteString(type),
					"\n what  ", quoteString(data[0]),
					"\n index ", quoteString(data[1])
				);
			} else {
				// log `length` and `propertyName` events
				dev.log(
					canReflect_1_19_2_canReflect.getName(instance),
					"\n key ", quoteString(type),
					"\n is  ", quoteString(data[0]),
					"\n was ", quoteString(data[1])
				);
			}
		};
	},
	deleteKey: function(prop){
		const instanceDefines = this._instanceDefinitions;
		if(instanceDefines && Object.prototype.hasOwnProperty.call(instanceDefines, prop) && !Object.isSealed(this)) {
			delete instanceDefines[prop];
			delete this[prop];
			canQueues_1_3_2_canQueues.batch.start();
			this.dispatch({
				action: "can.keys",
				type: "can.keys",
				target: this
			});
			const oldValue = this._data[prop];
			if(oldValue !== undefined) {
				delete this._data[prop];
				//delete this[prop];
				this.dispatch({
					action: "delete",
					key: prop,
					oldValue: oldValue,
					type: prop,
					target: this,
					patches: [{type: "delete", key: prop}],
				},[undefined,oldValue]);
			}
			canQueues_1_3_2_canQueues.batch.stop();
		} else {
			this.set(prop, undefined);
		}
		return this;
	}
};

var defineHelpers_1 = defineHelpers;

const { updateSchemaKeys, hooks, isEnumerable } = define_1;







const getSchemaSymbol$1 = Symbol.for("can.getSchema");

function keysForDefinition(definitions) {
	const keys = [];
	for(let prop in definitions) {
		if(isEnumerable(definitions[prop])) {
			keys.push(prop);
		}
	}
	return keys;
}

function assign(source) {
	canQueues_1_3_2_canQueues.batch.start();
	canReflect_1_19_2_canReflect.assignMap(this, source || {});
	canQueues_1_3_2_canQueues.batch.stop();
}
function update(source) {
	canQueues_1_3_2_canQueues.batch.start();
	if (canReflect_1_19_2_canReflect.isListLike(source)) {
		canReflect_1_19_2_canReflect.updateList(this, source);
	} else {
		canReflect_1_19_2_canReflect.updateMap(this, source || {});
	}
	canQueues_1_3_2_canQueues.batch.stop();
}
function assignDeep(source){
	canQueues_1_3_2_canQueues.batch.start();
	// TODO: we should probably just throw an error instead of cleaning
	canReflect_1_19_2_canReflect.assignDeepMap(this, source || {});
	canQueues_1_3_2_canQueues.batch.stop();
}
function updateDeep(source){
	canQueues_1_3_2_canQueues.batch.start();
	if (canReflect_1_19_2_canReflect.isListLike(source)) {
		canReflect_1_19_2_canReflect.updateDeepList(this, source);
	} else {
		// TODO: we should probably just throw an error instead of cleaning
		canReflect_1_19_2_canReflect.updateDeepMap(this, source || {});
	}
	canQueues_1_3_2_canQueues.batch.stop();
}
function setKeyValue(key, value) {
	const defined = defineHelpers_1.defineExpando(this, key, value);
	if(!defined) {
		this[key] = value;
	}
}
function getKeyValue(key) {
	const value = this[key];
	if(value !== undefined || key in this || Object.isSealed(this)) {
		return value;
	} else {
		canObservationRecorder_1_3_1_canObservationRecorder.add(this, key);
		return this[key];
	}
}

var mixinMapprops = function(Type) {
	return class extends Type {
		static [getSchemaSymbol$1]() {
			hooks.finalizeClass(this);
			let def = this.prototype._define;
			let definitions = def ? def.definitions : {};
			let schema = {
				type: "map",
				identity: [],
				keys: {}
			};
			return updateSchemaKeys(schema, definitions);
		}

		get(prop){
			if(prop) {
				return getKeyValue.call(this, prop);
			} else {
				return canReflect_1_19_2_canReflect.unwrap(this, Map);
			}
		}

		set(prop, value){
			if(typeof prop === "object") {
				//!steal-remove-start
				if(process.env.NODE_ENV !== 'production') {
					dev.warn('can-define/map/map.prototype.set is deprecated; please use can-define/map/map.prototype.assign or can-define/map/map.prototype.update instead');
				}
				//!steal-remove-end
				if(value === true) {
					updateDeep.call(this, prop);
				} else {
					assignDeep.call(this, prop);
				}

			} else {
				setKeyValue.call(this, prop, value);
			}

			return this;
		}

		assignDeep(prop) {
			assignDeep.call(this, prop);
			return this;
		}

		updateDeep(prop) {
			updateDeep.call(this, prop);
			return this;
		}

		assign(prop) {
			assign.call(this, prop);
			return this;
		}

		update(prop) {
			update.call(this, prop);
			return this;
		}

		serialize () {
			return canReflect_1_19_2_canReflect.serialize(this, Map);
		}

		deleteKey() {
			return defineHelpers_1.deleteKey.apply(this, arguments);
		}

		forEach(cb, thisarg, observe) {
			function forEach(list, cb, thisarg){
				return canReflect_1_19_2_canReflect.eachKey(list, cb, thisarg);
			}

			if(observe === false) {
				canObservationRecorder_1_3_1_canObservationRecorder.ignore(forEach)(this, cb, thisarg);
			} else {
				return forEach(this, cb, thisarg);
			}
		}

		static [Symbol.for("can.new")](...args) {
			return new this(...args);
		}

		get [Symbol.for("can.isMapLike")]() {
			return true;
		}

		get [Symbol.for("can.isListLike")]() {
			return false;
		}

		get [Symbol.for("can.isValueLike")]() {
			return false;
		}

		[Symbol.for("can.getKeyValue")](...args) {
			return getKeyValue.apply(this, args);
		}

		[Symbol.for("can.deleteKeyValue")](...args) {
			return defineHelpers_1.deleteKey.call(this, ...args);
		}

		[Symbol.for("can.getOwnKeys")]() {
			const keys = canReflect_1_19_2_canReflect.getOwnEnumerableKeys(this);
			if(this._computed) {
				const computedKeys = canReflect_1_19_2_canReflect.getOwnKeys(this._computed);

				let key;
				for (let i=0; i<computedKeys.length; i++) {
					key = computedKeys[i];
					if (keys.indexOf(key) < 0) {
						keys.push(key);
					}
				}
			}

			return keys;
		}

		[Symbol.for("can.getOwnEnumerableKeys")]() {
			canObservationRecorder_1_3_1_canObservationRecorder.add(this, 'can.keys');
			canObservationRecorder_1_3_1_canObservationRecorder.add(Object.getPrototypeOf(this), 'can.keys');
			return keysForDefinition(this._define.definitions).concat(keysForDefinition(this._instanceDefinitions) );
		}

		[Symbol.for("can.serialize")](...args) {
			return defineHelpers_1.reflectSerialize.apply(this, args);
		}

		[Symbol.for("can.unwrap")](...args) {
			return defineHelpers_1.reflectUnwrap.apply(this, args);
		}

		[Symbol.for("can.hasKey")](key) {
			return (key in this._define.definitions) || (this._instanceDefinitions !== undefined && key in this._instanceDefinitions);
		}

		[Symbol.for("can.updateDeep")](...args) {
			return this.updateDeep(...args);
		}
	};
};

const eventDispatcher = define_1.make.set.eventDispatcher;
const inSetupSymbol$3 = canSymbol_1_7_0_canSymbol.for("can.initializing");



// A bug in Safari means that __proto__ key is sent. This causes problems
// When addEventListener is called on a non-element.
// https://github.com/tc39/test262/pull/2203
let isProtoReadOnSuper = false;
(function(){
	if(typeof Proxy === "function") {
		let par = class { fn() { } };
		let base = new Proxy(par, {
			get(t, k, r) {
				if(k === "__proto__") { isProtoReadOnSuper = true; }
				return Reflect.get(t, k, r);
			}
		});
		let chi = class extends base { fn() { super.fn(); } };
		(new chi()).fn();
	}
})();

let wasLogged = false;
function logNotSupported() {
	if (!wasLogged && (typeof Proxy !== "function")) {
		wasLogged = true;
		dev.warn("can-observable-mixin/mixin-proxy requires ES Proxies which are not supported by your JS runtime.");
	}
}

function proxyPrototype(Base) {
	const instances = new WeakSet();

	function LateDefined() {
		//!steal-remove-start
		if(process.env.NODE_ENV !== "production") {
			logNotSupported();
		}
		//!steal-remove-end

		let inst = Reflect.construct(Base, arguments, this.constructor);
		instances.add(inst);
		return inst;
	}

	LateDefined.instances = instances;

	const underlyingPrototypeObject = Object.create(Base.prototype);

	const getHandler = isProtoReadOnSuper ?
		function(target, key, receiver) {
			if (!this[inSetupSymbol$3] && typeof key !== "symbol" && key !== "__proto__") {
				canObservationRecorder_1_3_1_canObservationRecorder.add(receiver, key);
			}
			return Reflect.get(target, key, receiver);
		} :
		function(target, key, receiver) {
			if (!this[inSetupSymbol$3] && typeof key !== "symbol") {
				canObservationRecorder_1_3_1_canObservationRecorder.add(receiver, key);
			}
			return Reflect.get(target, key, receiver);
		};

	const proxyHandlers = {
		get: getHandler,
		set(target, key, value, receiver) {
			// Symbols are not observable, so just set the value
			if (typeof key === "symbol") {
				Reflect.set(target, key, value, receiver);
				return true;
			}

			// We decided to punt on making the prototype observable, so anything
			// set on a prototype just gets set.
			if(key in target || !instances.has(receiver)) {
				let current = Reflect.get(target, key, receiver);
				Reflect.set(target, key, value, receiver);
				eventDispatcher(receiver, key, current, value);
			} else {
				define_1.expando(receiver, key, value);
			}

			return true;
		}
	};

	LateDefined.prototype = (typeof Proxy === "function") ?
		new Proxy(underlyingPrototypeObject, proxyHandlers) :
		underlyingPrototypeObject;

	return LateDefined;
}

var mixinProxy = proxyPrototype;

function mixinTypeEvents(Type) {
	let Child = class extends Type {};
	type$1(Child);
	map$1(Child);
	return Child;
}

var mixinTypeevents = mixinTypeEvents;

const { hooks: hooks$1, makeDefineInstanceKey } = define_1;




const constructorPropsSymbol = Symbol.for("can.constructorProps");
const renderedSymbol = Symbol.for("can.rendered");

var mixinElement = function mixinElement(BaseElement){
	let Element = class extends mixinProxy(BaseElement) {
		constructor(props) {
			super();
			hooks$1.finalizeClass(this.constructor);
			this[constructorPropsSymbol] = props;
		}

		initialize(props) {
			if(super.initialize) {
				super.initialize(props);
			}
			hooks$1.initialize(this, props || this[constructorPropsSymbol]);
		}

		render(props) {
			if(super.render) {
				super.render(props);
			}
			hooks$1.initialize(this, props || this[constructorPropsSymbol]);
			this[renderedSymbol] = true;
		}

		connectedCallback() {
			if(super.connectedCallback) {
				super.connectedCallback();
			}
			if(!this[renderedSymbol]) {
				this.render();
			}
		}
	};

	Element = mixinTypeevents(mixinMapprops(Element));
	makeDefineInstanceKey(Element);

	return Element;
};

var createConstructorFunction_1$1 = createConstructorFunction_1;

var makeDefineInstanceKey$1 = define_1.makeDefineInstanceKey;
var mixins_1 = define_1.hooks;

var mixinElement_1 = mixinElement;
var mixinMapProps_1 = mixinMapprops;
var mixinProxy_1 = mixinProxy;
var mixinTypeEvents_1 = mixinTypeevents;

var mixins = {
	createConstructorFunction: createConstructorFunction_1$1,
	makeDefineInstanceKey: makeDefineInstanceKey$1,
	mixins: mixins_1,
	mixinElement: mixinElement_1,
	mixinMapProps: mixinMapProps_1,
	mixinProxy: mixinProxy_1,
	mixinTypeEvents: mixinTypeEvents_1
};

const {
	createConstructorFunction: createConstructorFunction$1,
	makeDefineInstanceKey: makeDefineInstanceKey$2,
	mixins: mixins$1,
	mixinMapProps,
	mixinProxy: mixinProxy$1,
	mixinTypeEvents: mixinTypeEvents$1
} = mixins;


let ObservableObject = class extends mixinProxy$1(Object) {
	constructor(props) {
		super();
		mixins$1.finalizeClass(this.constructor);
		mixins$1.initialize(this, props);
		
		// Define class fields observables 
		//and return the proxy
		const proxiedInstance =  new Proxy(this, {
			defineProperty(target, prop, descriptor) {
				const props = target.constructor.props;
				let value = descriptor.value;

				// do not create expando properties for special keys set by can-observable-mixin
				const specialKeys = ['_instanceDefinitions', '_data', '_computed'];
				if (specialKeys.indexOf(prop) >= 0) {
					return Reflect.defineProperty(target, prop, descriptor);
				}

				if (value) {
					// do not create expando properties for properties that are described
					// by `static props` or `static propertyDefaults`
					if (props && props[prop] || target.constructor.propertyDefaults) {
						target.set(prop, value);
						return true;
					}
					// create expandos to make all other properties observable
					return mixins$1.expando(target, prop, value);
				}

				// Prevent dispatching more than one event with canReflect.setKeyValue
				return Reflect.defineProperty(target, prop, descriptor);
			}
		});

		// Adding the instance to observable-mixin 
		// prevents additional event dispatching 
		// https://github.com/canjs/can-observable-object/issues/35
		this.constructor.instances.add(proxiedInstance);
		return proxiedInstance;
	}

};

ObservableObject = mixinTypeEvents$1(mixinMapProps(ObservableObject));
makeDefineInstanceKey$2(ObservableObject);

// Export a constructor function to workaround an issue where ES2015 classes
// cannot be extended in code that's transpiled by Babel.
var canObservableObject = canNamespace_1_0_0_canNamespace.ObservableObject = createConstructorFunction$1(
	ObservableObject
);

const { mixins: mixins$2 } = mixins;


const metaSymbol$3 = Symbol.for("can.meta");

const helpers$1 = {
	assignNonEnumerable: function(obj, key, value) {
		return Object.defineProperty(obj, key, {
		    enumerable: false,
		    writable: true,
		    configurable: true,
		    value: value
		});
	},
	shouldRecordObservationOnAllKeysExceptFunctionsOnProto: function(keyInfo, meta){
		return meta.preventSideEffects === 0 && !keyInfo.isAccessor && (
			// it's on us
			(// it's on our proto, but not a function
			(keyInfo.targetHasOwnKey ) ||
			// it's "missing", and we are not sealed
			(!keyInfo.protoHasKey && !Object.isSealed(meta.target)) || keyInfo.protoHasKey && (typeof targetValue !== "function"))
		);
	},
	/*
	 * dispatch an event when an index changes
	 */
	dispatchIndexEvent: function(attr, how, newVal, oldVal) {
		var index = +attr;
		// Make sure this is not nested and not an expando
		if (!isNaN(index)) {
			var itemsDefinition = this._define.definitions["#"];
			if (how === 'set') {
				this.dispatch({
					type: index,
					action: how,
					key: index,
					value: newVal,
					oldValue: oldVal
				}, [ newVal, oldVal ]);

				// if event is being set through an ObservableArray.prototype method,
				// do not dispatch length or patch events.
				// This will be handled by ObservableArray.prototype method.
				let meta = this[metaSymbol$3];
				if (!("preventSideEffects" in meta) || meta.preventSideEffects === 0) {
					let patches = [{
						index: index,
						deleteCount: 1,
						insert: [ newVal ],
						type: "splice"
					}];
					helpers$1.dispatchLengthPatch.call(this, how, patches, this.length, this.length);
				}
			} else if (how === 'add') {
				if (itemsDefinition && typeof itemsDefinition.added === 'function') {
					canObservationRecorder_1_3_1_canObservationRecorder.ignore(itemsDefinition.added).call(this, newVal, index);
				}

				this.dispatch({
					type: index,
					action: how,
					key: index,
					value: newVal,
					oldValue: oldVal
				}, [ newVal, oldVal ]);

				// if event is being set through an ObservableArray.prototype method,
				// do not dispatch length or patch events.
				// This will be handled by ObservableArray.prototype method.
				let meta = this[metaSymbol$3];
				if (!("preventSideEffects" in meta) || meta.preventSideEffects === 0) {
					let patches = [{
						index: index,
						deleteCount: 0,
						insert: [ newVal ],
						type: "splice"
					}];
					helpers$1.dispatchLengthPatch.call(this, how, patches, this.length, this.length - 1);
				}
			} else if (how === 'remove') {
				if (itemsDefinition && typeof itemsDefinition.removed === 'function') {
					canObservationRecorder_1_3_1_canObservationRecorder.ignore(itemsDefinition.removed).call(this, oldVal, index);
				}
			}
		} else {
			var key = "" + attr;
			this.dispatch({
				type: key,
				key: key,
				action: how,
				value: newVal,
				oldValue: oldVal,
				target: this
			}, [ newVal, oldVal ]);
		}
	},
	/*
	 * Dispatch a `type: "splice"` patch and a `length` event
	 */
	dispatchLengthPatch: function(how, patches, newLength, oldLength) {
		const dispatchArgs = {
			type: "length",
			key: "length",
			action: how,
			value: newLength,
			oldValue: oldLength,
			patches: patches
		};

		//!steal-remove-start
		if(process.env.NODE_ENV !== "production") {
			dispatchArgs.reasonLog = [canReflect_1_19_2_canReflect.getName(this) + "." + how + " called with", arguments];
		}
		//!steal-remove-end

		map$1.dispatch.call(this, dispatchArgs, [newLength, oldLength]);
	},

	convertItem: function(Constructor, item) {
		if(Constructor.items) {
			const definition = mixins$2.normalizeTypeDefinition(Constructor.items.type || Constructor.items);
			return canReflect_1_19_2_canReflect.convert(item, definition);
		}
		return item;
	},

	convertItems: function(Constructor, items) {
		if(items.length) {
			if(Constructor.items) {
				for(let i = 0, len = items.length; i < len; i++) {
					items[i] = helpers$1.convertItem(Constructor, items[i]);
				}
			}
		}
		return items;
	}
};

var helpers_1$1 = helpers$1;

var canMeta = Symbol.for("can.meta");
const computedPropertyDefinitionSymbol = Symbol.for("can.computedPropertyDefinitions");
const onKeyValueSymbol$3 = Symbol.for("can.onKeyValue");
const offKeyValueSymbol$2 = Symbol.for("can.offKeyValue");

// ## ComputedObjectObservationData
// Instances of this are created to wrap the observation.
// The `.bind` and `.unbind` methods should be called when the
// instance's prop is bound or unbound.
function ComputedObjectObservationData(instance, prop, observation){
	this.instance = instance;
    this.prop = prop;
    this.observation = observation;
	this.forward = this.forward.bind(this);
}

ComputedObjectObservationData.prototype.bind = function(){
    this.bindingCount++;
    if(this.bindingCount === 1) {
        this.observation.on(this.forward, "notify");
    }
};

ComputedObjectObservationData.prototype.unbind = function(){
    this.bindingCount--;
    if(this.bindingCount === 0) {
        this.observation.off(this.forward, "notify");
    }
};

ComputedObjectObservationData.prototype.forward = function(newValue, oldValue){
	map$1.dispatch.call(this.instance, {
		type: this.prop,
		key: this.prop,
		target: this.instance,
		value: newValue,
		oldValue: oldValue

		// patches: [{
		// 	key: this.prop,
		// 	type: "set",
		// 	value: newValue
		// }]
		// keyChanged: undefined
	}, [newValue, oldValue]);
};

ComputedObjectObservationData.prototype.bindingCount = 0;

function findComputed(instance, key) {
	var meta = instance[canMeta];
	var target = meta.target;

	var computedPropertyDefinitions = target[computedPropertyDefinitionSymbol];
	if (computedPropertyDefinitions === undefined) {
		return;
	}
	var computedPropertyDefinition = computedPropertyDefinitions[key];
	if (computedPropertyDefinition === undefined) {
		return;
	}

	if (meta.computedKeys[key] === undefined) {
		meta.computedKeys[key] = new ComputedObjectObservationData(
			instance, key,
			computedPropertyDefinition(instance, key)
		);
	}

	return meta.computedKeys[key];
}

const computedHelpers = {
	bind: function(instance, key) {
		let computedObj = findComputed(instance, key);
		if (computedObj === undefined) {
			return;
		}

		computedObj.bind();
	},
	addKeyDependencies: function(proxyKeys) {
		let onKeyValue = proxyKeys[onKeyValueSymbol$3];
		let offKeyValue = proxyKeys[offKeyValueSymbol$2];

		canReflect_1_19_2_canReflect.assignSymbols(proxyKeys, {
			"can.onKeyValue": function(key) {
				computedHelpers.bind(this, key);
				return onKeyValue.apply(this, arguments);
			},
			"can.offKeyValue": function(key) {
				computedHelpers.unbind(this, key);
				return offKeyValue.apply(this, arguments);
			},
			"can.getKeyDependencies": function(key) {
				var computedObj = findComputed(this, key);
				if (computedObj === undefined) {
					return;
				}

				return {
					valueDependencies: new Set([ computedObj.observation ])
				};
			},
		});
	}
};

var computedHelpers_1 = computedHelpers;

const {
	assignNonEnumerable,
	convertItem,
	dispatchIndexEvent,
	shouldRecordObservationOnAllKeysExceptFunctionsOnProto
} = helpers_1$1;
const { mixins: mixins$3 } = mixins;

const hasOwn = Object.prototype.hasOwnProperty;
const { isSymbolLike: isSymbolLike$1 } = canReflect_1_19_2_canReflect;
const metaSymbol$4 = Symbol.for("can.meta");

const proxiedObjects = new WeakMap();
const proxies = new WeakSet();

const proxyKeys = Object.create(null);
Object.getOwnPropertySymbols(map$1).forEach(function(symbol){
	assignNonEnumerable(proxyKeys, symbol, map$1[symbol]);
});
computedHelpers_1.addKeyDependencies(proxyKeys);

const mutateMethods = {
	"push": function(arr, args) {
		return [{
			index: arr.length - args.length,
			deleteCount: 0,
			insert: args,
			type: "splice"
		}];
	},
	"pop": function(arr) {
		return [{
			index: arr.length,
			deleteCount: 1,
			insert: [],
			type: "splice"
		}];
	},
	"shift": function() {
		return [{
			index: 0,
			deleteCount: 1,
			insert: [],
			type: "splice"
		}];
	},
	"unshift": function(arr, args) {
		return [{
			index: 0,
			deleteCount: 0,
			insert: args,
			type: "splice"
		}];
	},
	"splice": function(arr, args) {
		return [{
			index: args[0],
			deleteCount: args[1],
			insert: args.slice(2),
			type: "splice"
		}];
	},
	"sort": function(arr) {
		// The array replaced everything.
		return [{
			index: 0,
			deleteCount: arr.length,
			insert: arr,
			type: "splice"
		}];
	},
	"reverse": function(arr) {
		// The array replaced everything.
		return [{
			index: 0,
			deleteCount: arr.length,
			insert: arr,
			type: "splice"
		}];
	}
};

// Overwrite Array's methods that mutate to:
// - prevent other events from being fired off (index events and length events.)
// - dispatch patches events.
canReflect_1_19_2_canReflect.eachKey(mutateMethods, function(makePatches, prop){
	var protoFn = Array.prototype[prop];
	var mutateMethod = function() {
		var meta = this[metaSymbol$4],
			// Capture if this function should be making sideEffects
			makeSideEffects = meta.preventSideEffects === 0,
			oldLength = meta.target.length;

		// Prevent proxy from calling ObservationRecorder and sending events.
		meta.preventSideEffects++;

		// Call the function -- note that *this* is the Proxy here, so
		// accesses in the function still go through `get()` and `set()`.
		var ret = protoFn.apply(meta.target, arguments);
		var patches = makePatches(meta.target, Array.from(arguments), oldLength);

		if (makeSideEffects === true) {
			//!steal-remove-start
			var reasonLog = [canReflect_1_19_2_canReflect.getName(meta.proxy)+"."+prop+" called with", arguments];
			//!steal-remove-end
			var dispatchArgs = {
				type: "length",
				key: "length",
				value: meta.target.length,
				oldValue: oldLength,
				patches: patches
			};

			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				dispatchArgs.reasonLog = reasonLog;
			}
			//!steal-remove-end

			map$1.dispatch.call( meta.proxy, dispatchArgs , [meta.target.length, oldLength]);
		}

		meta.preventSideEffects--;
		return ret;
	};
	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		Object.defineProperty(mutateMethod, "name", {
			value: prop
		});
	}
	//!steal-remove-end

	// Store the proxied method so it will be used instead of the
	// prototype method.
	proxiedObjects.set(protoFn, mutateMethod);
	proxies.add(mutateMethod);
});

function setValueAndOnChange(key, value, target, proxy, onChange) {
	let old, change;
	let hadOwn = hasOwn.call(target, key);

	let descriptor = Object.getOwnPropertyDescriptor(target, key);
	// call the setter on the Proxy to properly do any side-effect sets (and run corresponding handlers)
	// -- setters do not return values, so it is unnecessary to check for changes.
	if (descriptor && descriptor.set) {
		descriptor.set.call(proxy, value);
	} else {
		// otherwise check for a changed value
		old = target[key];
		change = old !== value;
		if (change) {
			let keyType = typeof key;
			let keyIsString = keyType === "string";

			// String keys added to the instance (and is not "length")
			// Are newly defined properties and have propertyDefaults provided.
			if(keyIsString && !(key in target)) {
				mixins$3.expando(target, key, value);
			} else {
				// arr[0] = { foo: 'bar' } should convert to MyArray.items
				if(keyType === "number") {
					value = convertItem(target.constructor, value);
				}

				target[key] = value;
				onChange(hadOwn, old);
			}
		}
	}
}

const proxyHandlers = {
	get(target, key, receiver) {
		if (isSymbolLike$1(key)) {
			return target[key];
		}

		let proxy = proxiedObjects.get(target);
		canObservationRecorder_1_3_1_canObservationRecorder.add(proxy, key.toString());

		const numberKey = !isSymbolLike$1(key) && +key;
		if (Number.isInteger(numberKey)) {
			canObservationRecorder_1_3_1_canObservationRecorder.add(proxy, "length");
		}
		
		let value = Reflect.get(target, key, receiver);
		return value;
	},

	set(target, key, newValue, receiver) {
		let proxy = proxiedObjects.get(target);
		let numberKey = !isSymbolLike$1(key) && +key;

		if (Number.isInteger(numberKey)) {
			key = numberKey;
		}

		setValueAndOnChange(key, newValue, target, proxy, function onChange(hadOwn, oldValue) {

			if (Number.isInteger(key)) {
				dispatchIndexEvent.call(
					receiver,
					key,
					hadOwn ? (typeof newValue !== 'undefined' ? "set" : "remove") : "add",
					newValue,
					oldValue
				);
			}
		});

		return true;
	},
	deleteProperty(target, key) {
		let old = this.target[key];
		let deleteSuccessful = delete this.target[key];

		// Fire event handlers if we were able to delete and the value changed.
		if (deleteSuccessful && this.preventSideEffects === 0 && old !== undefined) {
			dispatchIndexEvent.call(
				this.proxy,
				key,
				"remove",
				undefined,
				old
			);
		}

		return deleteSuccessful;
	},
	ownKeys() {
		canObservationRecorder_1_3_1_canObservationRecorder.add(this.proxy, "can.keys");

		let keysSet = new Set(
			Object.getOwnPropertyNames(this.target)
				.concat(Object.getOwnPropertySymbols(this.target))
				.concat(Object.getOwnPropertySymbols(this.proxyKeys))
		);

		return Array.from(keysSet);
	}
};

function makeObservable(array, options) {
	let meta = {
		target: array,
		proxyKeys: options.proxyKeys !== undefined ? options.proxyKeys : Object.create(proxyKeys),
		computedKeys: Object.create(null),
		options: options,
		// `preventSideEffects` is a counter used to "turn off" the proxy.  This is incremented when some
		// function (like `Array.splice`) wants to handle event dispatching and/or calling
		// `ObservationRecorder` itself for performance reasons.
		preventSideEffects: 0
	};
	meta.proxyKeys[metaSymbol$4] = meta;

	meta.proxy = new Proxy(array, {
		get: proxyHandlers.get.bind(meta),
		set: proxyHandlers.set.bind(meta),
		ownKeys: proxyHandlers.ownKeys.bind(meta),
		deleteProperty: proxyHandlers.deleteProperty.bind(meta),
		meta: meta
	});
	map$1.addHandlers(meta.proxy, meta);
	return meta.proxy;
}

function proxyArray() {
	return class ProxyArray extends Array {
		constructor(...items) {
			super(...items);

			let localProxyKeys = Object.create(proxyKeys);
        	localProxyKeys.constructor = this.constructor;

			let observable = makeObservable(this, {
				//observe: makeObserve.observe,
 				proxyKeys: localProxyKeys,
 				shouldRecordObservation: shouldRecordObservationOnAllKeysExceptFunctionsOnProto
			});
			proxiedObjects.set(this, observable);
			proxies.add(observable);
			return observable;
		}
	};
}

var proxyArray_1 = proxyArray;

const {
	createConstructorFunction: createConstructorFunction$2,
	makeDefineInstanceKey: makeDefineInstanceKey$3,
	mixins: mixins$4,
	mixinMapProps: mixinMapProps$1,
	mixinTypeEvents: mixinTypeEvents$2
} = mixins;
const {
	convertItem: convertItem$1,
	convertItems,
	dispatchLengthPatch
} = helpers_1$1;

const ProxyArray = proxyArray_1();



// symbols aren't enumerable ... we'd need a version of Object that treats them that way
const localOnPatchesSymbol = "can.patches";
const onKeyValueSymbol$4 = Symbol.for("can.onKeyValue");
const offKeyValueSymbol$3 = Symbol.for("can.offKeyValue");
const metaSymbol$5 = Symbol.for("can.meta");

function isListLike$1(items) {
	return canReflect_1_19_2_canReflect.isListLike(items) && typeof items !== "string";
}

const MixedInArray = mixinTypeEvents$2(mixinMapProps$1(ProxyArray));

class ObservableArray extends MixedInArray {
	// TODO define stuff here
	constructor(items, props) {
		// Arrays can be passed a length like `new Array(15)`
		let isLengthArg = typeof items === "number";
		if(isLengthArg) {
			super(items);
		} else if(arguments.length > 0 && !isListLike$1(items)) {
			throw new Error("can-observable-array: Unexpected argument: " + typeof items);
		} else {
			super();
		}

		mixins$4.finalizeClass(this.constructor);
		mixins$4.initialize(this, props || {});

		for(let i = 0, len = items && items.length; i < len; i++) {
			this[i] = convertItem$1(this.constructor, items[i]);
		}

		// Define class fields observables
		//and return the proxy
		return new Proxy(this, {
			defineProperty(target, prop, descriptor) {
				if ('items' === prop) {
					throw new Error('ObservableArray does not support a class field named items. Try using a different name or using static items');
				}

				// do not create expando properties for special keys set by can-observable-mixin
				if (prop === '_instanceDefinitions') {
					return Reflect.defineProperty(target, prop, descriptor);
				}

				let value = descriptor.value;

				// do not create expando properties for properties that are described
				// by `static props` or `static propertyDefaults`
				const props = target.constructor.props;
				if (props && props[prop] || target.constructor.propertyDefaults) {
					if (value) {
						target.set(prop, value);
						return true;
					}
					return Reflect.defineProperty(target, prop, descriptor);
				}

				// create expandos to make all other properties observable
				return mixins$4.expando(target, prop, value);
			}
		});
	}

	static get [Symbol.species]() {
		return this;
	}

	static [Symbol.for("can.new")](items) {
		let array = items || [];
		return new this(array);
	}

	push(...items) {
		return super.push(...items);
	}

	unshift(...items) {
		return super.unshift(...items);
	}

	filter(callback) {
		if(typeof callback === "object") {
			let props = callback;
			callback = function(item) {
				for (let prop in props) {
					if (item[prop] !== props[prop]) {
						return false;
					}
				}
				return true;
			};
		}

		return super.filter(callback);
	}

	forEach(...args) {
		return Array.prototype.forEach.apply(this, args);
	}

	splice(...args) {
		let index = args[0],
			howMany = args[1],
			added = [],
			i, len, listIndex,
			allSame = args.length > 2;

		index = index || 0;

		// converting the arguments to the right type
		for (i = 0, len = args.length - 2; i < len; i++) {
			listIndex = i + 2;
			added.push(args[listIndex]);

			// Now lets check if anything will change
			if (this[i + index] !== args[listIndex]) {
				allSame = false;
			}
		}

		// if nothing has changed, then return
		if (allSame && this.length <= added.length) {
			return added;
		}

		// default howMany if not provided
		if (howMany === undefined) {
			howMany = args[1] = this.length - index;
		}

		canQueues_1_3_2_canQueues.batch.start();
		var removed = super.splice.apply(this, args);
		canQueues_1_3_2_canQueues.batch.stop();
		return removed;
	}

	static convertsTo(Type) {
		const ConvertedType = canType_1_1_6_canType.convert(Type);

		const ArrayType = class extends this {
			static get items() {
				return ConvertedType;
			}
		};

		const name = `ConvertedObservableArray<${canReflect_1_19_2_canReflect.getName(Type)}>`;
		canReflect_1_19_2_canReflect.setName(ArrayType, name);

		return ArrayType;
	}

	/* Symbols */
	[Symbol.for("can.splice")](index, deleteCount, insert){
		return this.splice(...[index, deleteCount].concat(insert));
	}

	[Symbol.for("can.onPatches")](handler, queue){
		this[onKeyValueSymbol$4](localOnPatchesSymbol, handler,queue);
	}

	[Symbol.for("can.offPatches")](handler, queue) {
		this[offKeyValueSymbol$3](localOnPatchesSymbol, handler, queue);
	}

	get [Symbol.for("can.isListLike")]() {
		return true;
	}

	[Symbol.for("can.getOwnEnumerableKeys")]() {
		let base = super[Symbol.for("can.getOwnEnumerableKeys")]();
		let keysSet = new Set([...Object.keys(this), ...base]);
		return Array.from(keysSet);
	}
}

var mutateMethods$1 = {
	"push": function(arr, args) {
		return [{
			index: arr.length - args.length,
			deleteCount: 0,
			insert: args,
			type: "splice"
		}];
	},
	"pop": function(arr, args, oldLength) {
		return [{
			index: arr.length,
			deleteCount: oldLength > 0 ? 1 : 0,
			type: "splice"
		}];
	},
	"shift": function(arr, args, oldLength) {
		return [{
			index: 0,
			deleteCount: oldLength > 0 ? 1 : 0,
			type: "splice"
		}];
	},
	"unshift": function(arr, args) {
		return [{
			index: 0,
			deleteCount: 0,
			insert: args,
			type: "splice"
		}];
	},
	"splice": function(arr, args, oldLength) {
		const index = args[0] < 0 ?
			Math.max(oldLength + args[0], 0) :
			Math.min(oldLength, args[0]);
		return [{
			index,
			deleteCount: Math.max(0, Math.min(args[1], oldLength - index)),
			insert: args.slice(2),
			type: "splice"
		}];
	},
	"sort": function(arr) {
		return [{
			index: 0,
			deleteCount: arr.length,
			insert: arr,
			type: "splice"
		}];
	},
	"reverse": function(arr) {
		return [{
			index: 0,
			deleteCount: arr.length,
			insert: arr,
			type: "splice"
		}];
	}
};

const convertArgs = {
	"push": function(arr, args) {
		return convertItems(arr.constructor, args);
	},
	"unshift": function(arr, args) {
		return convertItems(arr.constructor, args);
	},
	"splice": function(arr, args) {
		return args.slice(0, 2).concat(convertItems(arr.constructor, args.slice(2)));
	}
};

canReflect_1_19_2_canReflect.eachKey(mutateMethods$1, function(makePatches, prop) {
	const protoFn = ObservableArray.prototype[prop];
	ObservableArray.prototype[prop] = function() {
		const oldLength = this.length;
		let args = Array.from(arguments);
		if(convertArgs[prop]) {
			args = convertArgs[prop](this, args);
		}

		// prevent `length` event from being dispatched by get/set proxy hooks
		this[metaSymbol$5].preventSideEffects = (this[metaSymbol$5].preventSideEffects || 0) + 1;
		const result = protoFn.apply(this, args);
		this[metaSymbol$5].preventSideEffects--;

		const patches = makePatches(this, args, oldLength);
		dispatchLengthPatch.call(this, prop, patches, this.length, oldLength);
		return result;
	};
});

makeDefineInstanceKey$3(ObservableArray);

// Export a constructor function to workaround an issue where ES2015 classes
// cannot be extended in code that's transpiled by Babel.
var canObservableArray = canNamespace_1_0_0_canNamespace.ObservableArray = createConstructorFunction$2(
	ObservableArray
);

//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var canLog = dev;
	var canReflectDeps = canReflectDependencies_1_1_2_canReflectDependencies;
}
//!steal-remove-end

// Symbols
var getChangesSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.getChangesDependencyRecord");
var getValueSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.getValue");
var onValueSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.onValue");
var onEmitSymbol = canSymbol_1_7_0_canSymbol.for("can.onEmit");
var offEmitSymbol = canSymbol_1_7_0_canSymbol.for("can.offEmit");
var setValueSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.setValue");
var canElementSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.element");

// Default implementations for setting the child and parent values
function defaultSetValue(newValue, observable) {
	canReflect_1_19_2_canReflect.setValue(observable, newValue);
}

// onEmit function
function onEmit (listenToObservable, updateFunction, queue) {
	return listenToObservable[onEmitSymbol](updateFunction, queue);
}

// offEmit function
function offEmit (listenToObservable, updateFunction, queue) {
	return listenToObservable[offEmitSymbol](updateFunction, queue);
}

// Given an observable, stop listening to it and tear down the mutation dependencies
function turnOffListeningAndUpdate(listenToObservable, updateObservable, updateFunction, queue) {
	var offValueOrOffEmitFn;

	// Use either offValue or offEmit depending on which Symbols are on the `observable`
	if (listenToObservable[onValueSymbol$2]) {
		offValueOrOffEmitFn = canReflect_1_19_2_canReflect.offValue;
	} else if (listenToObservable[onEmitSymbol]) {
		offValueOrOffEmitFn = offEmit;
	}

	if (offValueOrOffEmitFn) {
		offValueOrOffEmitFn(listenToObservable, updateFunction, queue);

		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {

			// The updateObservable is no longer mutated by listenToObservable
			canReflectDeps.deleteMutatedBy(updateObservable, listenToObservable);

			// The updateFunction no longer mutates anything
			updateFunction[getChangesSymbol$2] = function getChangesDependencyRecord() {
			};

		}
		//!steal-remove-end
	}
}

// Given an observable, start listening to it and set up the mutation dependencies
function turnOnListeningAndUpdate(listenToObservable, updateObservable, updateFunction, queue) {
	var onValueOrOnEmitFn;

	// Use either onValue or onEmit depending on which Symbols are on the `observable`
	if (listenToObservable[onValueSymbol$2]) {
		onValueOrOnEmitFn = canReflect_1_19_2_canReflect.onValue;
	} else if (listenToObservable[onEmitSymbol]) {
		onValueOrOnEmitFn = onEmit;
	}

	if (onValueOrOnEmitFn) {
		onValueOrOnEmitFn(listenToObservable, updateFunction, queue);

		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {

			// The updateObservable is mutated by listenToObservable
			canReflectDeps.addMutatedBy(updateObservable, listenToObservable);

			// The updateFunction mutates updateObservable
			updateFunction[getChangesSymbol$2] = function getChangesDependencyRecord() {
				var s = new Set();
				s.add(updateObservable);
				return {
					valueDependencies: s
				};
			};

		}

		//!steal-remove-end
	}
}

// Semaphores are used to keep track of updates to the child & parent
// For debugging purposes, Semaphore and Bind are highly coupled.
function Semaphore(binding, type) {
	this.value = 0;
	this._binding = binding;
	this._type = type;
}
canAssign_1_3_3_canAssign(Semaphore.prototype, {
	decrement: function() {
		this.value -= 1;
	},
	increment: function(args) {
		this._incremented = true;
		this.value += 1;
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			if(this.value === 1) {
				this._binding._debugSemaphores = [];
			}
			var semaphoreData = {
				type: this._type,
				action: "increment",
				observable: args.observable,
				newValue: args.newValue,
				value: this.value,
				lastTask: canQueues_1_3_2_canQueues.lastTask()
			};
			this._binding._debugSemaphores.push(semaphoreData);
		}
		//!steal-remove-end
	}
});

function Bind(options) {
	this._options = options;

	// These parameters must be supplied
	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		if (options.child === undefined) {
			throw new TypeError("You must supply a child");
		}
		if (options.parent === undefined) {
			throw new TypeError("You must supply a parent");
		}
		if (options.queue && ["notify", "derive", "domUI","dom"].indexOf(options.queue) === -1) {
			throw new RangeError("Invalid queue; must be one of notify, derive, dom, or domUI");
		}
	}
	//!steal-remove-end

	// queue; by default, domUI
	if (options.queue === undefined) {
		if(options.element) {
			options.queue = "dom";
		} else {
			options.queue = "domUI";
		}

	}

	// cycles: when an observable is set in a two-way binding, it can update the
	// other bound observable, which can then update the original observable the
	// “cycles” number of times. For example, a child is set and updates the parent;
	// with cycles: 0, the parent could not update the child;
	// with cycles: 1, the parent could update the child, which can update the parent
	// with cycles: 2, the parent can update the child again, and so on and so forth…
	if (options.cycles > 0 === false) {
		options.cycles = 0;
	}

	// onInitDoNotUpdateChild is false by default
	options.onInitDoNotUpdateChild =
		typeof options.onInitDoNotUpdateChild === "boolean" ?
			options.onInitDoNotUpdateChild
			: false;

	// onInitDoNotUpdateParent is false by default
	options.onInitDoNotUpdateParent =
		typeof options.onInitDoNotUpdateParent === "boolean" ?
			options.onInitDoNotUpdateParent
			: false;

	// onInitSetUndefinedParentIfChildIsDefined is true by default
	options.onInitSetUndefinedParentIfChildIsDefined =
		typeof options.onInitSetUndefinedParentIfChildIsDefined === "boolean" ?
			options.onInitSetUndefinedParentIfChildIsDefined
			: true;

	// The way the cycles are tracked is through semaphores; currently, when
	// either the child or parent is updated, we increase their respective
	// semaphore so that if it’s two-way binding, then the “other” observable
	// will only update if the total count for both semaphores is less than or
	// equal to twice the number of cycles (because a cycle means two updates).
	var childSemaphore = new Semaphore(this,"child");
	var parentSemaphore = new Semaphore(this,"parent");

	// Determine if this is a one-way or two-way binding; by default, accept
	// whatever options are passed in, but if they’re not defined, then check for
	// the getValue and setValue symbols on the child and parent values.
	var childToParent = true;
	if (typeof options.childToParent === "boolean") {
		// Always let the option override any checks
		childToParent = options.childToParent;
	} else if (options.child[getValueSymbol$1] == null) {
		// Child to parent won’t work if we can’t get the child’s value
		childToParent = false;
	} else if (options.setParent === undefined && options.parent[setValueSymbol$2] == null) {
		// Child to parent won’t work if we can’t set the parent’s value
		childToParent = false;
	}
	var parentToChild = true;
	if (typeof options.parentToChild === "boolean") {
		// Always let the option override any checks
		parentToChild = options.parentToChild;
	} else if (options.parent[getValueSymbol$1] == null) {
		// Parent to child won’t work if we can’t get the parent’s value
		parentToChild = false;
	} else if (options.setChild === undefined && options.child[setValueSymbol$2] == null) {
		// Parent to child won’t work if we can’t set the child’s value
		parentToChild = false;
	}
	if (childToParent === false && parentToChild === false) {
		throw new Error("Neither the child nor parent will be updated; this is a no-way binding");
	}
	this._childToParent = childToParent;
	this._parentToChild = parentToChild;

	// Custom child & parent setters can be supplied; if they aren’t provided,
	// then create our own.
	if (options.setChild === undefined) {
		options.setChild = defaultSetValue;
	}
	if (options.setParent === undefined) {
		options.setParent = defaultSetValue;
	}

	// Set the observables’ priority
	if (options.priority !== undefined) {
		canReflect_1_19_2_canReflect.setPriority(options.child, options.priority);
		canReflect_1_19_2_canReflect.setPriority(options.parent, options.priority);
	}

	// These variables keep track of how many updates are allowed in a cycle.
	// cycles is multipled by two because one update is allowed for each side of
	// the binding, child and parent. One more update is allowed depending on the
	// sticky option; if it’s sticky, then one more update needs to be allowed.
	var allowedUpdates = options.cycles * 2;
	var allowedChildUpdates = allowedUpdates + (options.sticky === "childSticksToParent" ? 1 : 0);
	var allowedParentUpdates = allowedUpdates + (options.sticky === "parentSticksToChild" ? 1 : 0);

	// This keeps track of whether we’re bound to the child and/or parent; this
	// allows startParent() to be called first and on() can be called later to
	// finish setting up the child binding. This is also checked when updating
	// values; if stop() has been called but updateValue() is called, then we
	// ignore the update.
	this._bindingState = {
		child: false,
		parent: false
	};

	// This is the listener that’s called when the parent changes
	this._updateChild = function(newValue) {
		updateValue.call(this, {
			bindingState: this._bindingState,
			newValue: newValue,

			// Some options used for debugging
			debugObservableName: "child",
			debugPartnerName: "parent",

			// Main observable values
			observable: options.child,
			setValue: options.setChild,
			semaphore: childSemaphore,

			// If the sum of the semaphores is less than or equal to this number, then
			// it’s ok to update the child with the new value.
			allowedUpdates: allowedChildUpdates,

			// If options.sticky === "parentSticksToChild", then after the parent sets
			// the child, check to see if the child matches the parent; if not, then
			// set the parent to the child’s value. This is used in cases where the
			// child modifies its own value and the parent should be kept in sync with
			// the child.
			sticky: options.sticky === "parentSticksToChild",

			// Partner observable values
			partner: options.parent,
			setPartner: options.setParent,
			partnerSemaphore: parentSemaphore
		});
	}.bind(this);

	// This is the listener that’s called when the child changes
	this._updateParent = function(newValue) {
		updateValue.call(this, {
			bindingState: this._bindingState,
			newValue: newValue,

			// Some options used for debugging
			debugObservableName: "parent",
			debugPartnerName: "child",

			// Main observable values
			observable: options.parent,
			setValue: options.setParent,
			semaphore: parentSemaphore,

			// If the sum of the semaphores is less than or equal to this number, then
			// it’s ok to update the parent with the new value.
			allowedUpdates: allowedParentUpdates,

			// If options.sticky === "childSticksToParent", then after the child sets
			// the parent, check to see if the parent matches the child; if not, then
			// set the child to the parent’s value. This is used in cases where the
			// parent modifies its own value and the child should be kept in sync with
			// the parent.
			sticky: options.sticky === "childSticksToParent",

			// Partner observable values
			partner: options.child,
			setPartner: options.setChild,
			partnerSemaphore: childSemaphore
		});
	}.bind(this);

	if(options.element) {
		this._updateChild[canElementSymbol$1] = this._updateParent[canElementSymbol$1] = options.element;
	}

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {

		Object.defineProperty(this._updateChild, "name", {
			value: options.updateChildName ? options.updateChildName : "update "+canReflect_1_19_2_canReflect.getName(options.child),
			configurable: true
		});

		Object.defineProperty(this._updateParent, "name", {
			value: options.updateParentName ? options.updateParentName : "update "+canReflect_1_19_2_canReflect.getName(options.parent),
			configurable: true
		});
	}
	//!steal-remove-end

}

Object.defineProperty(Bind.prototype, "parentValue", {
	get: function() {
		return canReflect_1_19_2_canReflect.getValue(this._options.parent);
	}
});

canAssign_1_3_3_canAssign(Bind.prototype, {

	// Turn on any bindings that haven’t already been enabled;
	// also update the child or parent if need be.
	start: function() {
		var childValue;
		var options = this._options;
		var parentValue;

		// The tests don’t show that it matters which is bound first, but we’ll
		// bind to the parent first to stay consistent with how
		// can-stache-bindings did things.
		this.startParent();
		this.startChild();

		// Initialize the child & parent values
		if (this._childToParent === true && this._parentToChild === true) {
			// Two-way binding
			parentValue = canReflect_1_19_2_canReflect.getValue(options.parent);
			if (parentValue === undefined) {
				childValue = canReflect_1_19_2_canReflect.getValue(options.child);
				if (childValue === undefined) {
					// Check if updating the child is allowed
					if (options.onInitDoNotUpdateChild === false) {
						this._updateChild(parentValue);
					}
				} else if (options.onInitDoNotUpdateParent === false && options.onInitSetUndefinedParentIfChildIsDefined === true) {
					this._updateParent(childValue);
				}
			} else {
				// Check if updating the child is allowed
				if (options.onInitDoNotUpdateChild === false) {
					this._updateChild(parentValue);
				}
			}

			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production'){
				// Here we want to do a dev-mode check to see whether the child does type conversions on
				//  any two-way bindings.  This will be ignored and the child and parent will be desynched.
				var parentContext = options.parent.observation && options.parent.observation.func || options.parent;
				var childContext = options.child.observation && options.child.observation.func || options.child;
				parentValue = canReflect_1_19_2_canReflect.getValue(options.parent);
				childValue = canReflect_1_19_2_canReflect.getValue(options.child);
				if (options.sticky && childValue !== parentValue) {
					canLog.warn(
						"can-bind: The " +
						(options.sticky === "parentSticksToChild" ? "parent" : "child") +
						" of the sticky two-way binding " +
						(options.debugName || (canReflect_1_19_2_canReflect.getName(parentContext) + "<->" + canReflect_1_19_2_canReflect.getName(childContext))) +
						" is changing or converting its value when set. Conversions should only be done on the binding " +
						(options.sticky === "parentSticksToChild" ? "child" : "parent") +
						" to preserve synchronization. " +
						"See https://canjs.com/doc/can-stache-bindings.html#StickyBindings for more about sticky bindings"
					);
				}
			}
			//!steal-remove-end

		} else if (this._childToParent === true) {
			// One-way child -> parent, so update the parent
			// Check if we are to initialize the parent
			if (options.onInitDoNotUpdateParent === false) {
				childValue = canReflect_1_19_2_canReflect.getValue(options.child);
				this._updateParent(childValue);
			}

		} else if (this._parentToChild === true) {
			// One-way parent -> child, so update the child
			// Check if updating the child is allowed
			if (options.onInitDoNotUpdateChild === false) {
				parentValue = canReflect_1_19_2_canReflect.getValue(options.parent);
				this._updateChild(parentValue);
			}
		}
	},

	// Listen for changes to the child observable and update the parent
	startChild: function() {
		if (this._bindingState.child === false && this._childToParent === true) {
			var options = this._options;
			this._bindingState.child = true;
			turnOnListeningAndUpdate(options.child, options.parent, this._updateParent, options.queue);
		}
	},

	// Listen for changes to the parent observable and update the child
	startParent: function() {
		if (this._bindingState.parent === false && this._parentToChild === true) {
			var options = this._options;
			this._bindingState.parent = true;
			turnOnListeningAndUpdate(options.parent, options.child, this._updateChild, options.queue);
		}
	},

	// Turn off all the bindings
	stop: function() {
		var bindingState = this._bindingState;
		var options = this._options;

		// Turn off the parent listener
		if (bindingState.parent === true && this._parentToChild === true) {
			bindingState.parent = false;
			turnOffListeningAndUpdate(options.parent, options.child, this._updateChild, options.queue);
		}

		// Turn off the child listener
		if (bindingState.child === true && this._childToParent === true) {
			bindingState.child = false;
			turnOffListeningAndUpdate(options.child, options.parent, this._updateParent, options.queue);
		}
	}

});

["parent", "child"].forEach(function(property){
	Object.defineProperty(Bind.prototype, property, {
		get: function(){
			return this._options[property];
		}
	});
});



// updateValue is a helper function that’s used by updateChild and updateParent
function updateValue(args) {
	/* jshint validthis: true */
	// Check to see whether the binding is active; ignore updates if it isn’t active
	var bindingState = args.bindingState;
	if (bindingState.child === false && bindingState.parent === false) {
		// We don’t warn the user about this because it’s a common occurrence in
		// can-stache-bindings, e.g. {{#if value}}<input value:bind="value"/>{{/if}}
		return;
	}

	// Now check the semaphore; if this change is happening because the partner
	// observable was just updated, we only want to update this observable again
	// if the total count for both semaphores is less than or equal to the number
	// of allowed updates.
	var semaphore = args.semaphore;
	if ((semaphore.value + args.partnerSemaphore.value) <= args.allowedUpdates) {
		canQueues_1_3_2_canQueues.batch.start();

		// Increase the semaphore so that when the batch ends, if an update to the
		// partner observable’s value is made, then it won’t update this observable
		// again unless cycles are allowed.
		semaphore.increment(args);

		// Update the observable’s value; this uses either a custom function passed
		// in when the binding was initialized or canReflect.setValue.
		args.setValue(args.newValue, args.observable);



		// Decrease the semaphore after all other updates have occurred
		canQueues_1_3_2_canQueues.mutateQueue.enqueue(semaphore.decrement, semaphore, []);

		canQueues_1_3_2_canQueues.batch.stop();

		// Stickiness is used in cases where the call to args.setValue above might
		// have resulted in the observable being set to a different value than what
		// was passed into this function (args.newValue). If sticky:true, then set
		// the partner observable’s value so they’re kept in sync.
		if (args.sticky) {
			var observableValue = canReflect_1_19_2_canReflect.getValue(args.observable);
			if (observableValue !== canReflect_1_19_2_canReflect.getValue(args.partner)) {
				args.setPartner(observableValue, args.partner);
			}
		}

	} else {
		// It’s natural for this “else” block to be hit in two-way bindings; as an
		// example, if a parent gets set and the child gets updated, the child’s
		// listener to update the parent will be called, but it’ll be ignored if we
		// don’t want cycles. HOWEVER, if this gets called and the parent is not the
		// same value as the child, then their values are going to be out of sync,
		// probably unintentionally. This is worth pointing out to developers
		// because it can cause unexpected behavior… some people call those bugs. :)

		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production'){
			var currentValue = canReflect_1_19_2_canReflect.getValue(args.observable);
			if (currentValue !== args.newValue) {
				var warningParts = [
					"can-bind: attempting to update " + args.debugObservableName + " " + canReflect_1_19_2_canReflect.getName(args.observable) + " to new value: %o",
					"…but the " + args.debugObservableName + " semaphore is at " + semaphore.value + " and the " + args.debugPartnerName + " semaphore is at " + args.partnerSemaphore.value + ". The number of allowed updates is " + args.allowedUpdates + ".",
					"The " + args.debugObservableName + " value will remain unchanged; it’s currently: %o. ",
					"Read https://canjs.com/doc/can-bind.html#Warnings for more information. Printing mutation history:"
				];
				canLog.warn(warningParts.join("\n"), args.newValue, currentValue);
				if(console.groupCollapsed) {
					// stores the last stack we've seen so we only need to show what's happened since the
					// last increment.
					var lastStack = [];
					var getFromLastStack = function(stack){
						if(lastStack.length) {
							// walk backwards
							for(var i = lastStack.length - 1; i >= 0 ; i--) {
								var index = stack.indexOf(lastStack[i]);
								if(index !== - 1) {
									return stack.slice(i+1);
								}
							}
						}
						return stack;
					};
					// Loop through all the debug information
					// And print out what caused increments.
					this._debugSemaphores.forEach(function(semaphoreMutation){
						if(semaphoreMutation.action === "increment") {
							console.groupCollapsed(semaphoreMutation.type+" "+canReflect_1_19_2_canReflect.getName(semaphoreMutation.observable)+" set.");
							var stack = canQueues_1_3_2_canQueues.stack(semaphoreMutation.lastTask);
							var printStack = getFromLastStack(stack);
							lastStack = stack;
							// This steals how `logStack` logs information.
							canQueues_1_3_2_canQueues.logStack.call({
								stack: function(){
									return printStack;
								}
							});
							console.log(semaphoreMutation.type+ " semaphore incremented to "+semaphoreMutation.value+".");
							console.log(canReflect_1_19_2_canReflect.getName(semaphoreMutation.observable),semaphoreMutation.observable,"set to ", semaphoreMutation.newValue);
							console.groupEnd();
						}
					});
					console.groupCollapsed(args.debugObservableName+" "+canReflect_1_19_2_canReflect.getName(args.observable)+" NOT set.");
					var stack = getFromLastStack(canQueues_1_3_2_canQueues.stack());
					canQueues_1_3_2_canQueues.logStack.call({
						stack: function(){
							return stack;
						}
					});
					console.log(args.debugObservableName+" semaphore ("+semaphore.value+
					 ") + "+args.debugPartnerName+" semaphore ("+args.partnerSemaphore.value+ ") IS NOT <= allowed updates ("+
					 args.allowedUpdates+")");
					console.log("Prevented from setting "+canReflect_1_19_2_canReflect.getName(args.observable), args.observable, "to", args.newValue);
					console.groupEnd();
				}
			}
		}
		//!steal-remove-end
	}
}

var canBind_1_5_1_canBind = canNamespace_1_0_0_canNamespace.Bind = Bind;

const value$1 = canValue_1_1_2_canValue;





//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var Observation$1 = canObservation_4_2_0_canObservation;
}
//!steal-remove-end

const metaSymbol$6 = Symbol.for("can.meta");

function isJSONLike (obj) {
	return (canReflect_1_19_2_canReflect.isFunctionLike(obj.parse) &&
			canReflect_1_19_2_canReflect.isFunctionLike(obj.stringify));
}

function initializeFromAttribute (propertyName, ctr, converter, attributeName) {
	if (ctr[metaSymbol$6] === undefined) {
		ctr[metaSymbol$6] = {};
	}
	// Create array for all attributes we want to listen to change events for
	if (ctr[metaSymbol$6]._observedAttributes === undefined) {
		ctr[metaSymbol$6]._observedAttributes = [];
	}
	// Create object for attributeChangedCallback for each prop
	if (ctr[metaSymbol$6]._attributeChangedCallbackHandler === undefined) {
		ctr[metaSymbol$6]._attributeChangedCallbackHandler = {};
	}

	if (attributeName === undefined) {
		attributeName = propertyName;
	}
	// Ensure the attributeName is hyphen case
	attributeName = canString_1_1_0_canString.hyphenate(attributeName);

	// Modify the class prototype here
	if (!ctr[metaSymbol$6]._hasInitializedAttributeBindings) {
		// Set up the static getter for `observedAttributes`
		Object.defineProperty(ctr, "observedAttributes", {
			get() {
				return ctr[metaSymbol$6]._observedAttributes;
			}
		});

		ctr.prototype.attributeChangedCallback = function (prop) {
			ctr[metaSymbol$6]._attributeChangedCallbackHandler[prop].apply(this, arguments);
		};

		ctr[metaSymbol$6]._hasInitializedAttributeBindings = true;
	}
	// Push into `_observedAttributes` for `observedAttributes` getter
	ctr[metaSymbol$6]._observedAttributes.push(attributeName);

	// Create the attributeChangedCallback handler
	ctr[metaSymbol$6]._attributeChangedCallbackHandler[attributeName] = function (prop, oldVal, newVal) {
		if (this[metaSymbol$6] && this[metaSymbol$6]._attributeBindings && newVal !== oldVal) {
			canReflect_1_19_2_canReflect.setValue(this[metaSymbol$6]._attributeBindings[prop], newVal);
		}
	};

	var lazyGetType = function() {
		var Type;
		var schema = canReflect_1_19_2_canReflect.getSchema(ctr);
		if(schema) {
			Type = schema.keys[propertyName];
		}
		if(!Type) {
			Type = canType_1_1_6_canType.Any;
		}
		Type = canType_1_1_6_canType.convert(Type);
		lazyGetType = function() { return Type; };
		return Type;
	};
	function convertToValue(value) {
		if (converter) {
			value = converter.parse(value);
		}
		return canReflect_1_19_2_canReflect.convert(value, lazyGetType());
	}

	return function fromAttributeBind (instance) {
		// Child binding used by `attributeChangedCallback` to update the value when an attribute change occurs
		const childValue = value$1.to(instance, propertyName);
		const intermediateValue = {};
		canReflect_1_19_2_canReflect.assignSymbols(intermediateValue, {
			"can.setValue": function(value) {
				canReflect_1_19_2_canReflect.setValue(childValue, convertToValue(value) );
			}
		});
		const parentValue = value$1.from(instance.hasAttribute(attributeName) ?  convertToValue(instance.getAttribute(attributeName)) : undefined);

		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			// Ensure pretty names for dep graph
			canReflect_1_19_2_canReflect.assignSymbols(parentValue, {
				"can.getName": function getName() {
					return (
						"FromAttribute<" +
						instance.nodeName.toLowerCase() +
						"." +
						attributeName +
						">"
					);
				}
			});
			canReflect_1_19_2_canReflect.assignSymbols(childValue, {
				"can.getName": function getName() {
					return (
						"Observation<" +
						canReflect_1_19_2_canReflect.getName(parentValue) +
						">"
					);
				}
			});
			// Create temporary binding to initialize dep graph
			Observation$1.temporarilyBind(childValue);
		}
		//!steal-remove-end
		const bind = new canBind_1_5_1_canBind({
			parent: parentValue,
			child: intermediateValue,
			queue: "dom",
			// During initialization prevent update of child
			onInitDoNotUpdateChild: true
		});

		if (instance[metaSymbol$6] === undefined) {
			instance[metaSymbol$6] = {};
		}
		if (instance[metaSymbol$6]._attributeBindings === undefined) {
			instance[metaSymbol$6]._attributeBindings = {};
		}

		// Push binding so it can be used within `attributeChangedCallback`
		instance[metaSymbol$6]._attributeBindings[attributeName] = intermediateValue;

		return bind;
	};
}

var canObservableBindings_1_3_3_fromAttribute = function fromAttribute (attributeName, ctr) {
	var converter;
	// Handle the class constructor
	if (arguments.length === 2 && canReflect_1_19_2_canReflect.isConstructorLike(ctr) && !isJSONLike(ctr)) {
		return initializeFromAttribute(attributeName, ctr);
	} else if (arguments.length === 1 && typeof attributeName === 'object') {
		// Handle fromAttribute(JSON)
		converter = attributeName;
		attributeName = undefined;
	} else if (typeof ctr === 'object' && isJSONLike(ctr)) {
		// Handle the case where an attribute name
		// and JSON like converter is passed
		// fromAttribute('attr', JSON)
		converter = ctr;
	}
	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		if (converter && !isJSONLike(converter)) {
			throw new Error('The passed converter object is wrong! The object must have "parse" and "stringify" methods!');
		}
	}
	//!steal-remove-end
	return function (propertyName, ctr) {
		return initializeFromAttribute(propertyName, ctr, converter, attributeName);
	};
};

var setElementSymbol = canSymbol_1_7_0_canSymbol.for("can.setElement");

// SetterObservable's call a function when set. Their getter is backed up by an
// observation.
function SetterObservable(getter, setter) {
	this.setter = setter;
	this.observation = new canObservation_4_2_0_canObservation(getter);
	this.handler = this.handler.bind(this);

	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		canReflect_1_19_2_canReflect.assignSymbols(this, {
			"can.getName": function() {
				return (
					canReflect_1_19_2_canReflect.getName(this.constructor) +
					"<" +
					canReflect_1_19_2_canReflect.getName(getter) +
					">"
				);
			}
		});
		Object.defineProperty(this.handler, "name", {
			value: canReflect_1_19_2_canReflect.getName(this) + ".handler"
		});
	}
	//!steal-remove-end
}

SetterObservable.prototype = Object.create(settable.prototype);
SetterObservable.prototype.constructor = SetterObservable;
SetterObservable.prototype.set = function(newVal) {
	this.setter(newVal);
};
SetterObservable.prototype.hasDependencies = function() {
	return canReflect_1_19_2_canReflect.valueHasDependencies(this.observation);
};
canReflect_1_19_2_canReflect.assignSymbols(SetterObservable.prototype, {
	"can.setValue": SetterObservable.prototype.set,
	"can.valueHasDependencies": SetterObservable.prototype.hasDependencies,
	"can.setElement": function(el) {
		this.observation[setElementSymbol](el);
	}
});

var setter = SetterObservable;

const lifecycleStatusSymbol = Symbol.for("can.lifecycleStatus");
const inSetupSymbol$4 = Symbol.for("can.initializing");
const teardownHandlersSymbol = Symbol.for("can.teardownHandlers");

function defineConfigurableNonEnumerable(obj, prop, value) {
	Object.defineProperty(obj, prop, {
		configurable: true,
		enumerable: false,
		writable: true,
		value: value
	});
}

var mixinLifecycleMethods = function mixinLifecycleMethods(BaseElement = HTMLElement) {
	return class LifecycleElement extends BaseElement {
		constructor() {
			super();
			if (arguments.length) {
				throw new Error("can-stache-element: Do not pass arguments to the constructor. Initial property values should be passed to the `initialize` hook.");
			}

			// add inSetup symbol to prevent events being dispatched
			defineConfigurableNonEnumerable(this, inSetupSymbol$4, true);

			// add lifecycle status symbol
			defineConfigurableNonEnumerable(this, lifecycleStatusSymbol, {
				initialized: false,
				rendered: false,
				connected: false,
				disconnected: false
			});

			// add a place to store additional teardownHandlers
			defineConfigurableNonEnumerable(this, teardownHandlersSymbol, []);
		}

		// custom element lifecycle methods
		connectedCallback(props) {
			this.initialize(props);
			this.render();
			this.connect();
			return this;
		}

		disconnectedCallback() {
			this.disconnect();
			return this;
		}

		// custom lifecycle methods
		initialize(props) {
			const lifecycleStatus = this[lifecycleStatusSymbol];

			if (lifecycleStatus.initialized) {
				return this;
			}

			// Overwrite ... this means that this initialize
			// can't be inherited (super.initialize).
			this[inSetupSymbol$4] = true;

			if (super.initialize) {
				super.initialize(props);
			}

			this[inSetupSymbol$4] = false;

			lifecycleStatus.initialized = true;

			return this;
		}

		render(props) {
			const lifecycleStatus = this[lifecycleStatusSymbol];

			if (lifecycleStatus.rendered) {
				return this;
			}

			if (!lifecycleStatus.initialized) {
				this.initialize(props);
			}

			if (super.render) {
				super.render(props);
			}

			lifecycleStatus.rendered = true;

			return this;
		}

		connect(props) {
			const lifecycleStatus = this[lifecycleStatusSymbol];

			if (lifecycleStatus.connected) {
				return this;
			}

			if (!lifecycleStatus.initialized) {
				this.initialize(props);
			}

			if (!lifecycleStatus.rendered) {
				this.render(props);
			}

			if (super.connect) {
				super.connect(props);
			}

			if (this.connected) {
				let connectedTeardown = this.connected();
				if (typeof connectedTeardown === "function") {
					this[teardownHandlersSymbol].push(connectedTeardown);
				}
			}

			lifecycleStatus.connected = true;
			lifecycleStatus.disconnected = false;

			return this;
		}

		disconnect() {
			const lifecycleStatus = this[lifecycleStatusSymbol];

			if (lifecycleStatus.disconnected) {
				return this;
			}

			if (super.disconnect) {
				super.disconnect();
			}

			if (this.stopListening) {
				this.stopListening();
			}

			for (let handler of this[teardownHandlersSymbol]) {
				handler.call(this);
			}

			if (this.disconnected) {
				this.disconnected();
			}

			this[lifecycleStatusSymbol] = {
				initialized: false,
				rendered: false,
				connected: false,
				disconnected: true
			};

			return this;
		}
	};
};

const { mixinElement: mixinElement$1, mixins: mixins$5 } = mixins;


const eventTargetInstalledSymbol = Symbol.for("can.eventTargetInstalled");

var mixinProps = function mixinDefine(Base = HTMLElement) {
	const realAddEventListener = Base.prototype.addEventListener;
	const realRemoveEventListener = Base.prototype.removeEventListener;

	function installEventTarget(Type) {
		if(Type[eventTargetInstalledSymbol]) {
			return;
		}
		const eventQueueAddEventListener = Type.prototype.addEventListener;
		const eventQueueRemoveEventListener = Type.prototype.removeEventListener;
		Type.prototype.addEventListener = function() {
			eventQueueAddEventListener.apply(this, arguments);
			return realAddEventListener.apply(this, arguments);
		};
		Type.prototype.removeEventListener = function() {
			eventQueueRemoveEventListener.apply(this, arguments);
			return realRemoveEventListener.apply(this, arguments);
		};
		Type[eventTargetInstalledSymbol] = true;
	}

	// Warn on special properties
	//!steal-remove-start
	function raisePropWarnings(Type, Base) {
		if(process.env.NODE_ENV !== 'production') {
			// look for `static props`and fall back to `static define` if `props` doesn't exist
			let props = typeof Type.props === "object" ?
				Type.props :
				typeof Type.define === "object" ?
					Type.define :
					{};
			
			Object.keys(props).forEach(function(key) {
				if("on" + key in Type.prototype) {
					dev.warn(`${canReflect_1_19_2_canReflect.getName(Type)}: The defined property [${key}] matches the name of a DOM event. This property could update unexpectedly. Consider renaming.`);
				}
				else if(key in Base.prototype) {
					dev.warn(`${canReflect_1_19_2_canReflect.getName(Type)}: The defined property [${key}] matches the name of a property on the type being extended, ${canReflect_1_19_2_canReflect.getName(Base)}. This could lead to errors by changing the expected behaviour of that property. Consider renaming.`);
				}
			});
		}
	}
	//!steal-remove-end

	class DefinedClass extends mixinElement$1(Base) {
		constructor() {
			super();
			//!steal-remove-start
			raisePropWarnings(this.constructor, Base);
			//!steal-remove-end
			installEventTarget(this.constructor);
		}

		initialize(props) {
			super.initialize(props);
			let prop, staticProps;

			if (this.constructor.props) {
				staticProps = Object.keys(this.constructor.props);
			}

			for (prop in this) {
				if (this.hasOwnProperty(prop)) {
					if (staticProps && staticProps.includes(prop)) {
						const val = this[prop];
						delete this[prop];
						this[prop] = val;
					} else {
						mixins$5.expando(this, prop, this[prop]);
					}
				}
			}

		}
	}

	return DefinedClass;
};

var canAttributeEncoder_1_1_4_canAttributeEncoder = createCommonjsModule(function (module) {



/**
 * @module {{}} can-attribute-encoder can-attribute-encoder
 * @parent can-dom-utilities
 * @collection can-infrastructure
 * @package ./package.json
 *
 * Encode and decode attribute names.
 *
 * @option {Object} An object with the methods:
 * [can-attribute-encoder.encode] and [can-attribute-encoder.decode].
 *
 */


function each(items, callback){
	for ( var i = 0; i < items.length; i++ ) {
		callback(items[i], i);
	}
}

function makeMap(str){
	var obj = {}, items = str.split(",");
	each(items, function(name){
		obj[name] = true;
	});
	return obj;
}

// Attributes for which the case matters - shouldn’t be lowercased.
var caseMattersAttributes = makeMap("allowReorder,attributeName,attributeType,autoReverse,baseFrequency,baseProfile,calcMode,clipPathUnits,contentScriptType,contentStyleType,diffuseConstant,edgeMode,externalResourcesRequired,filterRes,filterUnits,glyphRef,gradientTransform,gradientUnits,kernelMatrix,kernelUnitLength,keyPoints,keySplines,keyTimes,lengthAdjust,limitingConeAngle,markerHeight,markerUnits,markerWidth,maskContentUnits,maskUnits,patternContentUnits,patternTransform,patternUnits,pointsAtX,pointsAtY,pointsAtZ,preserveAlpha,preserveAspectRatio,primitiveUnits,repeatCount,repeatDur,requiredExtensions,requiredFeatures,specularConstant,specularExponent,spreadMethod,startOffset,stdDeviation,stitchTiles,surfaceScale,systemLanguage,tableValues,textLength,viewBox,viewTarget,xChannelSelector,yChannelSelector,controlsList");

function camelCaseToSpinalCase(match, lowerCaseChar, upperCaseChar) {
	return lowerCaseChar + "-" + upperCaseChar.toLowerCase();
}

function startsWith(allOfIt, startsWith) {
	return allOfIt.indexOf(startsWith) === 0;
}

function endsWith(allOfIt, endsWith) {
	return (allOfIt.length - allOfIt.lastIndexOf(endsWith)) === endsWith.length;
}

var regexes = {
	leftParens: /\(/g,
	rightParens: /\)/g,
	leftBrace: /\{/g,
	rightBrace: /\}/g,
	camelCase: /([a-z]|[0-9]|^)([A-Z])/g,
	forwardSlash: /\//g,
	space: /\s/g,
	uppercase: /[A-Z]/g,
	uppercaseDelimiterThenChar: /:u:([a-z])/g,
	caret: /\^/g,
	dollar: /\$/g,
	at: /@/g
};

var delimiters = {
	prependUppercase: ':u:',
	replaceSpace: ':s:',
	replaceForwardSlash: ':f:',
	replaceLeftParens: ':lp:',
	replaceRightParens: ':rp:',
	replaceLeftBrace: ':lb:',
	replaceRightBrace: ':rb:',
	replaceCaret: ':c:',
	replaceDollar: ':d:',
	replaceAt: ':at:'
};

var encoder = {};

/**
 * @function can-attribute-encoder.encode encode
 * @parent can-attribute-encoder
 * @description Encode an attribute name
 *
 * @signature `encoder.encode(attributeName)`
 *
 * Note: specific encoding may change, but encoded attributes
 * can always be decoded using [can-attribute-encoder.decode].
 *
 * @body
 *
 * ```js
 * var encodedAttributeName = encoder.encode("{(^$foo/bar baz)}");
 * div.setAttribute(encodedAttributeName, "attribute value");
 * ```
 *
 * @param {String} attributeName The attribute name.
 * @return {String} The encoded attribute name.
 *
 */
encoder.encode = function(name) {
	var encoded = name;

	// encode or convert camelCase attributes unless in list of attributes
	// where case matters
	if (!caseMattersAttributes[encoded] && encoded.match(regexes.camelCase)) {
		// encode uppercase characters in new bindings
		// - on:fooBar, fooBar:to, fooBar:from, fooBar:bind
		if (
			startsWith(encoded, 'on:') ||
			endsWith(encoded, ':to') ||
			endsWith(encoded, ':from') ||
			endsWith(encoded, ':bind') ||
			endsWith(encoded, ':raw')
		) {
			encoded = encoded
				.replace(regexes.uppercase, function(char) {
					return delimiters.prependUppercase + char.toLowerCase();
				});
		} else if(startsWith(encoded, '(') || startsWith(encoded, '{')) {
			// convert uppercase characters in older bindings to kebab-case
			// - {fooBar}, (fooBar), {(fooBar)}
			encoded = encoded.replace(regexes.camelCase, camelCaseToSpinalCase);
			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				dev.warn("can-attribute-encoder: Found attribute with name: " + name + ". Converting to: " + encoded + '.');
			}
			//!steal-remove-end
		}
	}

	//encode spaces
	encoded = encoded.replace(regexes.space, delimiters.replaceSpace)
		//encode forward slashes
		.replace(regexes.forwardSlash, delimiters.replaceForwardSlash)
		// encode left parentheses
		.replace(regexes.leftParens, delimiters.replaceLeftParens)
		// encode right parentheses
		.replace(regexes.rightParens, delimiters.replaceRightParens)
		// encode left braces
		.replace(regexes.leftBrace, delimiters.replaceLeftBrace)
		// encode left braces
		.replace(regexes.rightBrace, delimiters.replaceRightBrace)
		// encode ^
		.replace(regexes.caret, delimiters.replaceCaret)
		// encode $
		.replace(regexes.dollar, delimiters.replaceDollar)
		// encode @
		.replace(regexes.at, delimiters.replaceAt);

	return encoded;
};

/**
 * @function can-attribute-encoder.decode decode
 * @parent can-attribute-encoder
 * @description Decode an attribute name encoded by [can-attribute-encoder.encode]
 * @signature `encoder.decode(attributeName)`
 *
 * @body
 *
 * ```js
 * encoder.decode(attributeName); // -> "{(^$foo/bar baz)}"
 *
 * ```
 *
 * @param {String} attributeName The encoded attribute name.
 * @return {String} The decoded attribute name.
 *
 */
encoder.decode = function(name) {
	var decoded = name;

	// decode uppercase characters in new bindings
	if (!caseMattersAttributes[decoded] && regexes.uppercaseDelimiterThenChar.test(decoded)) {
		if (
			startsWith(decoded, 'on:') ||
			endsWith(decoded, ':to') ||
			endsWith(decoded, ':from') ||
			endsWith(decoded, ':bind') ||
			endsWith(decoded, ':raw')
		) {
			decoded = decoded
				.replace(regexes.uppercaseDelimiterThenChar, function(match, char) {
					return char.toUpperCase();
				});
		}
	}

	// decode left parentheses
	decoded = decoded.replace(delimiters.replaceLeftParens, '(')
		// decode right parentheses
		.replace(delimiters.replaceRightParens, ')')
		// decode left braces
		.replace(delimiters.replaceLeftBrace, '{')
		// decode left braces
		.replace(delimiters.replaceRightBrace, '}')
		// decode forward slashes
		.replace(delimiters.replaceForwardSlash, '/')
		// decode spaces
		.replace(delimiters.replaceSpace, ' ')
		// decode ^
		.replace(delimiters.replaceCaret, '^')
		//decode $
		.replace(delimiters.replaceDollar, '$')
		//decode @
		.replace(delimiters.replaceAt, '@');

	return decoded;
};

if (canNamespace_1_0_0_canNamespace.encoder) {
	throw new Error("You can't have two versions of can-attribute-encoder, check your dependencies");
} else {
	module.exports = canNamespace_1_0_0_canNamespace.encoder = encoder;
}
});

/* jshint maxdepth:7,node:true, latedef:false */


function each(items, callback){
	for ( var i = 0; i < items.length; i++ ) {
		callback(items[i], i);
	}
}

function makeMap$1(str){
	var obj = {}, items = str.split(",");
	each(items, function(name){
		obj[name] = true;
	});
	return obj;
}

function handleIntermediate(intermediate, handler){
	for(var i = 0, len = intermediate.length; i < len; i++) {
		var item = intermediate[i];
		handler[item.tokenType].apply(handler, item.args);
	}
	return intermediate;
}

//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	//assign the function to a var to avoid jshint
	//"Function declarations should not be placed in blocks"
	var countLines = function countLines(input) {
		// TODO: optimize?
		return input.split('\n').length - 1;
	};
}
//!steal-remove-end

var alphaNumeric = "A-Za-z0-9",
	alphaNumericHU = "-:_"+alphaNumeric,
	magicStart = "{{",
	endTag = new RegExp("^<\\/(["+alphaNumericHU+"]+)[^>]*>"),
	magicMatch = new RegExp("\\{\\{(![\\s\\S]*?!|[\\s\\S]*?)\\}\\}\\}?","g"),
	space = /\s/,
	alphaRegex = new RegExp('['+ alphaNumeric + ']'),
	attributeRegexp = new RegExp("["+alphaNumericHU+"]+\s*=\s*(\"[^\"]*\"|'[^']*')");

// Empty Elements - HTML 5
var empty = makeMap$1("area,base,basefont,br,col,frame,hr,img,input,isindex,link,meta,param,embed");

// Elements for which tag case matters - shouldn't be lowercased.
var caseMattersElements = makeMap$1("altGlyph,altGlyphDef,altGlyphItem,animateColor,animateMotion,animateTransform,clipPath,feBlend,feColorMatrix,feComponentTransfer,feComposite,feConvolveMatrix,feDiffuseLighting,feDisplacementMap,feDistantLight,feFlood,feFuncA,feFuncB,feFuncG,feFuncR,feGaussianBlur,feImage,feMerge,feMergeNode,feMorphology,feOffset,fePointLight,feSpecularLighting,feSpotLight,feTile,feTurbulence,foreignObject,glyphRef,linearGradient,radialGradient,textPath");

// Elements that you can, intentionally, leave open
// (and which close themselves)
var closeSelf = makeMap$1("colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr");

// Special Elements (can contain anything)
var special = makeMap$1("script");

// Callback names on `handler`.
var tokenTypes = "start,end,close,attrStart,attrEnd,attrValue,chars,comment,special,done".split(",");

//maps end characters to start characters
var startOppositesMap = {"{": "}", "(":")"};

var fn = function(){};

var HTMLParser = function (html, handler, returnIntermediate) {
	if(typeof html === "object") {
		return handleIntermediate(html, handler);
	}

	var intermediate = [];
	handler = handler || {};
	if(returnIntermediate) {
		// overwrite handlers so they add to intermediate
		each(tokenTypes, function(name){
			var callback = handler[name] || fn;
			handler[name] = function(){
				if( callback.apply(this, arguments) !== false ) {
					var end = arguments.length;

					// the intermediate is stringified in the compiled stache templates
					// so we want to trim the last item if it is the line number
					if (arguments[end - 1] === undefined) {
						end = arguments.length - 1;
					}

					//!steal-remove-start
					if (process.env.NODE_ENV !== 'production') {
						// but restore line number in dev mode
						end = arguments.length;
					}
					//!steal-remove-end

					intermediate.push({
						tokenType: name,
						args: [].slice.call(arguments, 0, end),
					});
				}
			};
		});
	}

	function parseStartTag(tag, tagName, rest, unary) {
		tagName = caseMattersElements[tagName] ? tagName : tagName.toLowerCase();

		if (closeSelf[tagName] && stack.last() === tagName) {
			parseEndTag("", tagName);
		}

		unary = empty[tagName] || !!unary;
		handler.start(tagName, unary, lineNo);
		if (!unary) {
			stack.push(tagName);
		}

		// find attribute or special
		HTMLParser.parseAttrs(rest, handler, lineNo);

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			lineNo += countLines(tag);
		}
		//!steal-remove-end


		handler.end(tagName, unary, lineNo);

		if(tagName === "html") {
			skipChars = true;
		}
	}

	function parseEndTag(tag, tagName) {
		// If no tag name is provided, clean shop
		var pos;
		if (!tagName) {
			pos = 0;
		}
		// Find the closest opened tag of the same type
		else {
			tagName = caseMattersElements[tagName] ? tagName : tagName.toLowerCase();
			for (pos = stack.length - 1; pos >= 0; pos--) {
				if (stack[pos] === tagName) {
					break;
				}
			}
		}

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			if (typeof tag === 'undefined') {
				if (stack.length > 0) {
					if (handler.filename) {
						dev.warn(handler.filename + ": expected closing tag </" + stack[pos] + ">");
					}
					else {
						dev.warn("expected closing tag </" + stack[pos] + ">");
					}
				}
			} else if (pos < 0 || pos !== stack.length - 1) {
				if (stack.length > 0) {
					if (handler.filename) {
						dev.warn(handler.filename + ":" + lineNo + ": unexpected closing tag " + tag + " expected </" + stack[stack.length - 1] + ">");
					}
					else {
						dev.warn(lineNo + ": unexpected closing tag " + tag + " expected </" + stack[stack.length - 1] + ">");
					}
				} else {
					if (handler.filename) {
						dev.warn(handler.filename + ":" + lineNo + ": unexpected closing tag " + tag);
					}
					else {
						dev.warn(lineNo + ": unexpected closing tag " + tag);
					}
				}
			}
		}
		//!steal-remove-end

		if (pos >= 0) {
			// Close all the open elements, up the stack
			for (var i = stack.length - 1; i >= pos; i--) {
				if (handler.close) {
					handler.close(stack[i], lineNo);
				}
			}

			// Remove the open elements from the stack
			stack.length = pos;

			// Don't add TextNodes after the <body> tag
			if(tagName === "body") {
				skipChars = true;
			}
		}
	}

	function parseMustache(mustache, inside){
		if(handler.special){
			handler.special(inside, lineNo);
		}
	}

	var callChars = function(){
		if(charsText && !skipChars) {
			if(handler.chars) {
				handler.chars(charsText, lineNo);
			}

			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				lineNo += countLines(charsText);
			}
			//!steal-remove-end
		}

		skipChars = false;
		charsText = "";
	};

	var index,
		chars,
		skipChars,
		match,
		lineNo,
		stack = [],
		last = html,
		// an accumulating text for the next .chars callback
		charsText = "";

	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		lineNo = 1;
	}
	//!steal-remove-end

	stack.last = function () {
		return this[this.length - 1];
	};

	while (html) {

		chars = true;

		// Make sure we're not in a script or style element
		if (!stack.last() || !special[stack.last()]) {

			// Comment
			if (html.indexOf("<!--") === 0) {
				index = html.indexOf("-->");

				if (index >= 0) {
					callChars();
					if (handler.comment) {
						handler.comment(html.substring(4, index), lineNo);
					}

					//!steal-remove-start
					if (process.env.NODE_ENV !== 'production') {
						lineNo += countLines(html.substring(0, index + 3));
					}
					//!steal-remove-end

					html = html.substring(index + 3);
					chars = false;
				}

				// end tag
			} else if (html.indexOf("</") === 0) {
				match = html.match(endTag);

				if (match) {
					callChars();
					match[0].replace(endTag, parseEndTag);

					//!steal-remove-start
					if (process.env.NODE_ENV !== 'production') {
						lineNo += countLines(html.substring(0, match[0].length));
					}
					//!steal-remove-end

					html = html.substring(match[0].length);
					chars = false;
				}

				// start tag
			} else if (html.indexOf("<") === 0) {
				var res = HTMLParser.searchStartTag(html);

				if(res) {
					callChars();
					parseStartTag.apply(null, res.match);

					html = res.html;
					chars = false;
				}

				// magic tag
			} else if (html.indexOf(magicStart) === 0 ) {
				match = html.match(magicMatch);

				if (match) {
					callChars();
					match[0].replace(magicMatch, parseMustache);

					//!steal-remove-start
					if (process.env.NODE_ENV !== 'production') {
						lineNo += countLines(html.substring(0, match[0].length));
					}
					//!steal-remove-end

					html = html.substring(match[0].length);
				}
			}

			if (chars) {
				index = findBreak(html, magicStart);
				if(index === 0 && html === last) {
					charsText += html.charAt(0);
					html = html.substr(1);
					index = findBreak(html, magicStart);
				}

				var text = index < 0 ? html : html.substring(0, index);
				html = index < 0 ? "" : html.substring(index);

				if (text) {
					charsText += text;
				}
			}

		} else {
			html = html.replace(new RegExp("([\\s\\S]*?)<\/" + stack.last() + "[^>]*>"), function (all, text) {
				text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, "$1$2");
				if (handler.chars) {
					handler.chars(text, lineNo);
				}

				//!steal-remove-start
				if (process.env.NODE_ENV !== 'production') {
					lineNo += countLines(text);
				}
				//!steal-remove-end

				return "";
			});

			parseEndTag("", stack.last());
		}

		if (html === last) {
			throw new Error("Parse Error: " + html);
		}

		last = html;
	}
	callChars();
	// Clean up any remaining tags
	parseEndTag();


	handler.done(lineNo);
	return intermediate;
};

var callAttrStart = function(state, curIndex, handler, rest, lineNo){
	var attrName = rest.substring(typeof state.nameStart === "number" ? state.nameStart : curIndex, curIndex),
		newAttrName = canAttributeEncoder_1_1_4_canAttributeEncoder.encode(attrName);

	state.attrStart = newAttrName;
	handler.attrStart(state.attrStart, lineNo);
	state.inName = false;
};

var callAttrEnd = function(state, curIndex, handler, rest, lineNo){
	if(state.valueStart !== undefined && state.valueStart < curIndex) {
		var val = rest.substring(state.valueStart, curIndex);
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			var quotedVal, closedQuote;
			quotedVal = rest.substring(state.valueStart - 1, curIndex + 1);
			quotedVal = quotedVal.trim();
			closedQuote = quotedVal.charAt(quotedVal.length - 1);

			if (state.inQuote !== closedQuote) {
				if (handler.filename) {
					dev.warn(handler.filename + ":" + lineNo + ": End quote is missing for " + val);
				} else {
					dev.warn(lineNo + ": End quote is missing for " + val);
				}
			}
		}
		//!steal-remove-end
		handler.attrValue(val, lineNo);
	}
	// if this never got to be inValue, like `DISABLED` then send a attrValue
	// else if(!state.inValue){
	// 	handler.attrValue(state.attrStart, lineNo);
	// }

	handler.attrEnd(state.attrStart, lineNo);
	state.attrStart = undefined;
	state.valueStart = undefined;
	state.inValue = false;
	state.inName = false;
	state.lookingForEq = false;
	state.inQuote = false;
	state.lookingForName = true;
};

var findBreak = function(str, magicStart) {
	var magicLength = magicStart.length;
	for(var i = 0, len = str.length; i < len; i++) {
		if(str[i] === "<" || str.substr(i, magicLength) === magicStart) {
			return i;
		}
	}
	return -1;
};

HTMLParser.parseAttrs = function(rest, handler, lineNo){
	if(!rest) {
		return;
	}

	var i = 0;
	var curIndex;
	var state = {
		inName: false,
		nameStart: undefined,
		inValue: false,
		valueStart: undefined,
		inQuote: false,
		attrStart: undefined,
		lookingForName: true,
		lookingForValue: false,
		lookingForEq : false
	};

	while(i < rest.length) {
		curIndex = i;
		var cur = rest.charAt(i);
		i++;

		if(magicStart === rest.substr(curIndex, magicStart.length) ) {
			if(state.inValue && curIndex > state.valueStart) {
				handler.attrValue(rest.substring(state.valueStart, curIndex), lineNo);
			}
			// `{{#foo}}DISABLED{{/foo}}`
			else if(state.inName && state.nameStart < curIndex) {
				callAttrStart(state, curIndex, handler, rest, lineNo);
				callAttrEnd(state, curIndex, handler, rest, lineNo);
			}
			// foo={{bar}}
			else if(state.lookingForValue){
				state.inValue = true;
			}
			// a {{bar}}
			else if(state.lookingForEq && state.attrStart) {
				callAttrEnd(state, curIndex, handler, rest, lineNo);
			}

			magicMatch.lastIndex = curIndex;
			var match = magicMatch.exec(rest);
			if(match) {
				handler.special(match[1], lineNo);
				// i is already incremented
				i = curIndex + (match[0].length);
				if(state.inValue) {
					state.valueStart = curIndex+match[0].length;
				}
			}
		}
		else if(state.inValue) {
			if(state.inQuote) {
				if(cur === state.inQuote) {
					callAttrEnd(state, curIndex, handler, rest, lineNo);
				}
			}
			else if(space.test(cur)) {
				callAttrEnd(state, curIndex, handler, rest, lineNo);
			}
		}
		// if we hit an = outside a value
		else if(cur === "=" && (state.lookingForEq || state.lookingForName || state.inName)) {
			// if we haven't yet started this attribute `{{}}=foo` case:
			if(!state.attrStart) {
				callAttrStart(state, curIndex, handler, rest, lineNo);
			}
			state.lookingForValue = true;
			state.lookingForEq = false;
			state.lookingForName = false;
		}
		// if we are currently in a name:
		//  when the name starts with `{` or `(`
		//  it isn't finished until the matching end character is found
		//  otherwise, a space finishes the name
		else if(state.inName) {
			var started = rest[ state.nameStart ],
					otherStart, otherOpposite;
			if(startOppositesMap[started] === cur) {
				//handle mismatched brackets: `{(})` or `({)}`
				otherStart = started === "{" ? "(" : "{";
				otherOpposite = startOppositesMap[otherStart];

				if(rest[curIndex+1] === otherOpposite){
					callAttrStart(state, curIndex+2, handler, rest, lineNo);
					i++;
				}else{
					callAttrStart(state, curIndex+1, handler, rest, lineNo);
				}

				state.lookingForEq = true;
			}
			else if(space.test(cur) && started !== "{" && started !== "(") {
					callAttrStart(state, curIndex, handler, rest, lineNo);
					state.lookingForEq = true;
			}
		}
		else if(state.lookingForName) {
			if(!space.test(cur)) {
				// might have just started a name, we need to close it
				if(state.attrStart) {
					callAttrEnd(state, curIndex, handler, rest, lineNo);
				}
				state.nameStart = curIndex;
				state.inName = true;
			}
		}
		else if(state.lookingForValue) {
			if(!space.test(cur)) {
				state.lookingForValue = false;
				state.inValue = true;
				if(cur === "'" || cur === '"') {
					state.inQuote = cur;
					state.valueStart = curIndex+1;
				} else {
					state.valueStart = curIndex;
				}
				// if we are looking for a value
				// at the end of the loop we need callAttrEnd
			} else if (i === rest.length){
				callAttrEnd(state, curIndex, handler, rest, lineNo);
			}
		}
	}

	if(state.inName) {
		callAttrStart(state, curIndex+1, handler, rest, lineNo);
		callAttrEnd(state, curIndex+1, handler, rest, lineNo);
	} else if(state.lookingForEq || state.lookingForValue || state.inValue) {
		callAttrEnd(state, curIndex+1, handler, rest, lineNo);
	}
	magicMatch.lastIndex = 0;
};

HTMLParser.searchStartTag = function (html) {
	var closingIndex = html.indexOf('>');

	// The first closing bracket we find might be in an attribute value.
	// Move through the attributes by regexp.
	var attributeRange = attributeRegexp.exec(html.substring(1));
	var afterAttributeOffset = 1;
	// if the closing index is after the next attribute...
	while(attributeRange && closingIndex >= afterAttributeOffset + attributeRange.index) {

		// prepare to move to the attribute after this one by increasing the offset
		afterAttributeOffset += attributeRange.index + attributeRange[0].length;
		// if the closing index is before the new offset, then this closing index is inside
		//  an attribute value and should be ignored.  Find the *next* closing character.
		while(closingIndex < afterAttributeOffset) {
			closingIndex += html.substring(closingIndex + 1).indexOf('>') + 1;
		}

		// find the next attribute by starting from the new offset.
		attributeRange = attributeRegexp.exec(html.substring(afterAttributeOffset));
	}

	// if there is no closing bracket
	// <input class=
	// or if the tagName does not start with alphaNumer character
	// <_iaois>
	// it is not a startTag
	if(closingIndex === -1 || !(alphaRegex.test(html[1]))){
		return null;
	}

	var tagName, tagContent, match, rest = '', unary = '';
	var startTag = html.substring(0, closingIndex + 1);
	var isUnary = startTag[startTag.length-2] === '/';
	var spaceIndex = startTag.search(space);

	if(isUnary){
		unary = '/';
		tagContent = startTag.substring(1, startTag.length-2).trim();
	} else {
		tagContent = startTag.substring(1, startTag.length-1).trim();
	}

	if(spaceIndex === -1){
		tagName = tagContent;
	} else {
		//spaceIndex needs to shift one to the left
		spaceIndex--;
		tagName = tagContent.substring(0, spaceIndex);
		rest = tagContent.substring(spaceIndex);
	}

	match = [startTag, tagName, rest, unary];

	return {
		match: match,
		html: html.substring(startTag.length),
	};


};

var canViewParser_4_1_3_canViewParser = canNamespace_1_0_0_canNamespace.HTMLParser = HTMLParser;

/**
 * @module {function} can-globals/location/location location
 * @parent can-globals/modules
 * 
 * Get the global [`location`](https://developer.mozilla.org/en-US/docs/Web/API/Window/location) object for the current context.
 * 
 * @signature `LOCATION([newLocation])`
 * 
 * Optionally sets, and returns, the [`location`](https://developer.mozilla.org/en-US/docs/Web/API/Window/location) object for the context.
 * 
 * ```js
 * var locationShim = { path: '/' };
 * var LOCATION = require('can-globals/location/location');
 * LOCATION(locationShim);
 * LOCATION().path; // -> '/'
 * ```
 *
 * @param {Object} location An optional location-like object to set as the context's location
 *
 * @return {Object} The location object for this JavaScript environment.
 */
canGlobals_1_2_2_canGlobalsInstance.define('location', function(){
	return canGlobals_1_2_2_canGlobalsInstance.getKeyValue('global').location;
});

var location_1 = canGlobals_1_2_2_canGlobalsInstance.makeExport('location');

/**
 * @module {function} can-globals/mutation-observer/mutation-observer mutation-observer
 * @parent can-globals/modules
 * 
 * Get the global [`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) object for the current context.
 * 
 * @signature `MUTATIONOBSERVER([newMutationObserver])`
 * 
 * Optionally sets, and returns, the [`MutationObserver`](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) object for the context.
 * 
 * ```js
 * var mutationObserverShim = require('can-globals/mutation-observer/mutation-observer');
 * MUTATIONOBSERVER(mutationObserverShim);
 * MUTATIONOBSERVER() //-> MutationObserver
 * ```
 *
 * @param {Object} MutationObserver An optional MutationObserver-like object to set as the context's MutationObserver
 *
 * @return {Object} The MutationObserver object for this JavaScript environment.
 */

canGlobals_1_2_2_canGlobalsInstance.define('MutationObserver', function(){
	var GLOBAL = canGlobals_1_2_2_canGlobalsInstance.getKeyValue('global');
	return GLOBAL.MutationObserver || GLOBAL.WebKitMutationObserver || GLOBAL.MozMutationObserver;
});

var mutationObserver = canGlobals_1_2_2_canGlobalsInstance.makeExport('MutationObserver');

/**
 * @module {function} can-globals/custom-elements/custom-elements custom-elements
 * @parent can-globals/modules
 *
 * Get the global [`customElements`](https://developer.mozilla.org/en-US/docs/Web/API/Window/customElements) object for the current context.
 *
 * @signature `CUSTOMELEMENTS([newCustomElements])`
 *
 * Optionally sets, and returns, the [`customElements`](https://developer.mozilla.org/en-US/docs/Web/API/Window/customElements) object for the context.
 *
 * ```js
 * var customElementsShim = require('some-custom-elements-shim');
 * CUSTOMELEMENTS(customElementsShim);
 * CUSTOMELEMENTS() //-> customElementsShim
 * ```
 *
 * @param {Object} customElements An optional CustomElementRegistry-like object to set as the context's customElements
 *
 * @return {Object} The customElements object for this JavaScript environment.
 */

canGlobals_1_2_2_canGlobalsInstance.define('customElements', function(){
	var GLOBAL = canGlobals_1_2_2_canGlobalsInstance.getKeyValue('global');
	return GLOBAL.customElements;
});

var customElements = canGlobals_1_2_2_canGlobalsInstance.makeExport('customElements');

var canGlobals_1_2_2_canGlobals = canGlobals_1_2_2_canGlobalsInstance;

function eliminate(array, item) {
	var index = array.indexOf(item);
	if (index >= 0) {
		array.splice(index, 1);
	}
}
function wasNotInSet(item, set) {
	var inSet = set.has(item);
	if(inSet === false) {
		set.add(item);
	}
	return !inSet;
}


function contains(parent, child){
	if(child && child.nodeType === Node.TEXT_NODE) {
		return contains(parent, child.parentNode);
	}
	if(parent.contains) {
		return parent.contains(child);
	}
	if(parent.nodeType === Node.DOCUMENT_NODE && parent.documentElement) {
		return contains(parent.documentElement, child);
	} else {
		child = child.parentNode;
		if(child === parent) {
			return true;
		}
		return false;
	}
}

function isDocumentElement (node) {
	return document$1().documentElement === node;
}

function isFragment (node) {
	return !!(node && node.nodeType === 11);
}

function isElementNode (node) {
	return !!(node && node.nodeType === 1);
}

function getChildren (parentNode) {
	var nodes = [];
	var node = parentNode.firstChild;
	while (node) {
		nodes.push(node);
		node = node.nextSibling;
	}
	return nodes;
}

function getParents (node) {
	var nodes;
	if (isFragment(node)) {
		nodes = getChildren(node);
	} else {
		nodes = [node];
	}
	return nodes;
}


function getNodesLegacyB(node) {
	var skip, tmp;

	var depth = 0;

	var items = isFragment(node) ? [] : [node];
	if(node.firstChild == null) {
		return items;
	}

	// Always start with the initial element.
	do {
		if ( !skip && (tmp = node.firstChild) ) {
			depth++;
			items.push(tmp);
		} else if ( tmp = node.nextSibling ) {
			skip = false;
			items.push(tmp);
		} else {
			// Skipped or no first child and no next sibling, so traverse upwards,
			tmp = node.parentNode;
			// and decrement the depth.
			depth--;
			// Enable skipping, so that in the next loop iteration, the children of
			// the now-current node (parent node) aren't processed again.
			skip = true;
		}

		// Instead of setting node explicitly in each conditional block, use the
		// tmp var and set it here.
		node = tmp;

		// Stop if depth comes back to 0 (or goes below zero, in conditions where
		// the passed node has neither children nore next siblings).
	} while ( depth > 0 );

	return items;
}

// IE11 requires a filter parameter for createTreeWalker
// it also must be an object with an `acceptNode` property
function treeWalkerFilterFunction() {
	return NodeFilter.FILTER_ACCEPT;
}
var treeWalkerFilter = treeWalkerFilterFunction;
treeWalkerFilter.acceptNode = treeWalkerFilterFunction;

function getNodesWithTreeWalker(rootNode) {
	var result = isFragment(rootNode) ? [] : [rootNode];

	// IE11 throws if createTreeWalker is called on a non-ElementNode
	var walker = isElementNode(rootNode) && document$1().createTreeWalker(
		rootNode,
		NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT,
		treeWalkerFilter,
		false
	);

	var node;
	while(node = walker && walker.nextNode()) {
		result.push(node);
	}
	return result;
}

function getAllNodes (node) {
	if( document$1().createTreeWalker !== undefined ) {
		return getNodesWithTreeWalker(node);
	} else {
		return getNodesLegacyB(node);
	}
}

function subscription (fn) {
	return function _subscription () {
		var disposal = fn.apply(this, arguments);
		var isDisposed = false;
		return function _disposal () {
			if (isDisposed) {
				var fnName = fn.name || fn.displayName || 'an anonymous function';
				var message = 'Disposal function returned by ' + fnName + ' called more than once.';
				throw new Error(message);
			}
			disposal.apply(this, arguments);
			isDisposed = true;
		};
	};
}

var canDomMutate_2_0_9_Util = {
	eliminate: eliminate,
	getDocument: document$1,
	isDocumentElement: isDocumentElement,
	isFragment: isFragment,
	getParents: getParents,
	getAllNodes: getAllNodes,
	getChildren: getChildren,
	subscription: subscription,
	wasNotInSet: wasNotInSet,
	contains: contains
};

var contains$1 = canDomMutate_2_0_9_Util.contains;
var mutate = {};
var isConnected;
function getIsConnectedFromNode(node) {
	return node.isConnected;
}
function getIsConnectedFromDocument(node) {
	var doc = node.ownerDocument;
	// if node *is* the document, ownerDocument is null
	// However, CanSimpleDom implements this incorrectly, and a document's ownerDocument is itself,
	//   so make both checks
	return doc === null || doc === node || contains$1(doc, node);
}

function setIsConnected(doc) {
	if(doc) {
		var node = doc.createTextNode("");
		isConnected = 'isConnected' in node.constructor.prototype ?
			getIsConnectedFromNode :
			getIsConnectedFromDocument;
		if(mutate) {
			mutate.isConnected = isConnected;
		}
	} else {
		mutate.isConnected = getIsConnectedFromNode;
	}
}
setIsConnected(canGlobals_1_2_2_canGlobals.getKeyValue("document"));
canGlobals_1_2_2_canGlobals.onKeyValue("document", setIsConnected);

var canDomMutate_2_0_9_IsConnected = mutate;

var eliminate$1 = canDomMutate_2_0_9_Util.eliminate;
var subscription$1 = canDomMutate_2_0_9_Util.subscription;
var isDocumentElement$1 = canDomMutate_2_0_9_Util.isDocumentElement;
var getAllNodes$1 = canDomMutate_2_0_9_Util.getAllNodes;

var domMutate,
	dispatchNodeInserted,
	dispatchNodeConnected,
	dispatchGlobalConnected,
	dispatchNodeRemoved,
	dispatchNodeDisconnected,
	dispatchGlobalDisconnected,
	dispatchAttributeChange;

var dataStore = new WeakMap();


var queue;

function getRelatedData(node, key) {
	var data = dataStore.get(node);
	if (data) {
		return data[key];
	}
}

function setRelatedData(node, key, targetListenersMap) {
	var data = dataStore.get(node);
	if (!data) {
		data = {};
		dataStore.set(node, data);
	}
	data[key] = targetListenersMap;
}

function deleteRelatedData(node, key) {
	var data = dataStore.get(node);
	return delete data[key];
}

function toMutationEvent(node, mutation) {
	return {target: node, sourceMutation: mutation};
}

function getDocumentListeners (target, key) {
	// TODO: it's odd these functions read DOCUMENT() instead of
	// target.ownerDocument.  To change to ownerDocument, we might need a "is document"
	// check.
	var doc = document$1();
	var data = getRelatedData(doc, key);
	if (data) {
		return data.listeners;
	}
}

function getTargetListeners (target, key) {
	var doc = document$1();
	var targetListenersMap = getRelatedData(doc, key);
	if (!targetListenersMap) {
		return;
	}

	return targetListenersMap.get(target);
}

function addTargetListener (target, key, listener) {
	var doc = document$1();
	var targetListenersMap = getRelatedData(doc, key);
	if (!targetListenersMap) {
		targetListenersMap = new WeakMap();
		setRelatedData(doc, key, targetListenersMap);
	}
	var targetListeners = targetListenersMap.get(target);
	if (!targetListeners) {
		targetListeners = [];
		targetListenersMap.set(target, targetListeners);
	}
	targetListeners.push(listener);
}

function removeTargetListener (target, key, listener) {
	var doc = document$1();
	var targetListenersMap = getRelatedData(doc, key);
	if (!targetListenersMap) {
		return;
	}
	var targetListeners = targetListenersMap.get(target);
	if (!targetListeners) {
		return;
	}
	eliminate$1(targetListeners, listener);
	if (targetListeners.length === 0) {
		targetListenersMap['delete'](target);
		if (targetListenersMap.size === 0) {
			deleteRelatedData(doc, key);
		}
	}
}

var promise = Promise.resolve();
function nextTick(handler) {
	promise.then(handler);
}

//var recordsAndCallbacks = null;

function flushCallbacks(callbacks, arg){
	var callbacksCount = callbacks.length;
	var safeCallbacks = callbacks.slice(0);
	for(var c = 0; c < callbacksCount; c++){
		safeCallbacks[c](arg);
	}
}

function dispatch$1(getListeners, targetKey) {

	return function dispatchEvents(event) {
		var targetListeners = getListeners(event.target, targetKey);

		if (targetListeners) {
			flushCallbacks(targetListeners, event);
		}
	};
}

var count = 0;

function observeMutations(target, observerKey, config, handler) {

	var observerData = getRelatedData(target, observerKey);
	if (!observerData) {
		observerData = {
			observingCount: 0
		};
		setRelatedData(target, observerKey, observerData);
	}

	var setupObserver = function () {
		// disconnect the old one
		if (observerData.observer) {
			observerData.observer.disconnect();
			observerData.observer = null;
		}

		var MutationObserver = mutationObserver();
		if (MutationObserver) {
			var Node = global_1().Node;
			var isRealNode = !!(Node && target instanceof Node);
			if (isRealNode) {
				var targetObserver = new MutationObserver(handler);
				targetObserver.id = count++;
				targetObserver.observe(target, config);
				observerData.observer = targetObserver;
			}
		}
	};

	if (observerData.observingCount === 0) {
		canGlobals_1_2_2_canGlobals.onKeyValue('MutationObserver', setupObserver);
		setupObserver();
	}

	observerData.observingCount++;
	return function stopObservingMutations() {
		var observerData = getRelatedData(target, observerKey);
		if (observerData) {
			observerData.observingCount--;
			if (observerData.observingCount <= 0) {
				if (observerData.observer) {
					observerData.observer.disconnect();
				}
				deleteRelatedData(target, observerKey);
				canGlobals_1_2_2_canGlobals.offKeyValue('MutationObserver', setupObserver);
			}
		}
	};
}

var treeMutationConfig = {
	subtree: true,
	childList: true
};

var attributeMutationConfig = {
	attributes: true,
	attributeOldValue: true
};

function addNodeListener(listenerKey, observerKey, isAttributes) {
	return subscription$1(function _addNodeListener(target, listener) {
		// DocumentFragment
		if(target.nodeType === 11) {
			// This returns a noop without actually doing anything.
			// We should probably warn about passing a DocumentFragment here,
			// but since can-stache does so currently we are ignoring until that is
			// fixed.
			return Function.prototype;
		}

		var stopObserving;
		if (isAttributes) {
			stopObserving = observeMutations(target, observerKey, attributeMutationConfig, queue.enqueueAndFlushMutations);
		} else {
			stopObserving = observeMutations(document$1(), observerKey, treeMutationConfig, queue.enqueueAndFlushMutations);
		}

		addTargetListener(target, listenerKey, listener);
		return function removeNodeListener() {
			if(stopObserving) {
				stopObserving();
			}

			removeTargetListener(target, listenerKey, listener);
		};
	});
}

function addGlobalListener(globalDataKey, addNodeListener) {
	return subscription$1(function addGlobalGroupListener(documentElement, listener) {
		if (!isDocumentElement$1(documentElement)) {
			throw new Error('Global mutation listeners must pass a documentElement');
		}

		var doc = document$1();
		var documentData = getRelatedData(doc, globalDataKey);
		if (!documentData) {
			documentData = {listeners: []};
			setRelatedData(doc, globalDataKey, documentData);
		}

		var listeners = documentData.listeners;
		if (listeners.length === 0) {
			// We need at least on listener for mutation events to propagate
			documentData.removeListener = addNodeListener(doc, function () {});
		}

		listeners.push(listener);

		return function removeGlobalGroupListener() {
			var documentData = getRelatedData(doc, globalDataKey);
			if (!documentData) {
				return;
			}

			var listeners = documentData.listeners;
			eliminate$1(listeners, listener);
			if (listeners.length === 0) {
				documentData.removeListener();
				deleteRelatedData(doc, globalDataKey);
			}
		};
	});
}



var domMutationPrefix = 'domMutation';

// target listener keys
var connectedDataKey = domMutationPrefix + 'ConnectedData';
var disconnectedDataKey = domMutationPrefix + 'DisconnectedData';
var insertedDataKey = domMutationPrefix + 'InsertedData';
var removedDataKey = domMutationPrefix + 'RemovedData';
var attributeChangeDataKey = domMutationPrefix + 'AttributeChangeData';

// document listener keys
var documentConnectedDataKey = domMutationPrefix + 'DocumentConnectedData';
var documentDisconnectedDataKey = domMutationPrefix + 'DocumentDisconnectedData';
var documentAttributeChangeDataKey = domMutationPrefix + 'DocumentAttributeChangeData';

// observer keys
var treeDataKey = domMutationPrefix + 'TreeData';
var attributeDataKey = domMutationPrefix + 'AttributeData';

dispatchNodeInserted = dispatch$1(getTargetListeners, insertedDataKey);
dispatchNodeConnected = dispatch$1(getTargetListeners, connectedDataKey);
dispatchGlobalConnected = dispatch$1(getDocumentListeners, documentConnectedDataKey);

dispatchNodeRemoved = dispatch$1(getTargetListeners, removedDataKey);
dispatchNodeDisconnected = dispatch$1(getTargetListeners, disconnectedDataKey);
dispatchGlobalDisconnected = dispatch$1(getDocumentListeners, documentDisconnectedDataKey);

dispatchAttributeChange = dispatch$1(getTargetListeners, attributeChangeDataKey);

// node listeners
var addNodeConnectedListener = addNodeListener(connectedDataKey, treeDataKey);
var addNodeDisconnectedListener = addNodeListener(disconnectedDataKey, treeDataKey);
var addNodeInsertedListener = addNodeListener(insertedDataKey, treeDataKey);
var addNodeRemovedListener = addNodeListener(removedDataKey, treeDataKey);
var addNodeAttributeChangeListener = addNodeListener(attributeChangeDataKey, attributeDataKey, true);

// global listeners
var addConnectedListener = addGlobalListener(
	documentConnectedDataKey,
	addNodeConnectedListener
);
var addDisconnectedListener = addGlobalListener(
	documentDisconnectedDataKey,
	addNodeDisconnectedListener
);
var addAttributeChangeListener = addGlobalListener(
	documentAttributeChangeDataKey,
	addNodeAttributeChangeListener
);

// ==========================================
function dispatchTreeMutation(mutation, processedState) {
	// was the mutation connected
	var wasConnected = mutation.isConnected === true || mutation.isConnected === undefined;

	// there are
	// - the global connected
	// - individual connected
	// - individual inserted
	var removedCount = mutation.removedNodes.length;
	for (var r = 0; r < removedCount; r++) {
		// get what already isn't in `removed`

		// see if "removed"
		// if wasConnected .. dispatch disconnected
		var removedNodes = getAllNodes$1(mutation.removedNodes[r]);
		removedNodes.forEach(function(node){
			var event = toMutationEvent(node, mutation);

			if( canDomMutate_2_0_9_Util.wasNotInSet(node, processedState.removed) ) {
				dispatchNodeRemoved( event );
			}
			if(wasConnected && canDomMutate_2_0_9_Util.wasNotInSet(node, processedState.disconnected) ) {
				dispatchNodeDisconnected( event );
				dispatchGlobalDisconnected( event );
			}
		});
	}

	var addedCount = mutation.addedNodes.length;
	for (var a = 0; a < addedCount; a++) {
		var insertedNodes = getAllNodes$1(mutation.addedNodes[a]);
		insertedNodes.forEach(function(node){
			var event = toMutationEvent(node, mutation);

			if(canDomMutate_2_0_9_Util.wasNotInSet(node, processedState.inserted)) {
				dispatchNodeInserted( event );
			}
			if(wasConnected && canDomMutate_2_0_9_Util.wasNotInSet(node, processedState.connected) ) {
				dispatchNodeConnected( event );
				dispatchGlobalConnected( event );
			}
		});
	}
	// run mutation
}


var FLUSHING_MUTATIONS = [];
var IS_FLUSHING = false;

var IS_FLUSH_PENDING = false;
var ENQUEUED_MUTATIONS = [];

queue = {
	// This is used to dispatch mutations immediately.
	// This is usually called by the result of a mutation observer.
	enqueueAndFlushMutations: function(mutations) {
		if(IS_FLUSH_PENDING) {
			FLUSHING_MUTATIONS = FLUSHING_MUTATIONS.concat(ENQUEUED_MUTATIONS);
			IS_FLUSH_PENDING = false;
			ENQUEUED_MUTATIONS = [];
		}

		FLUSHING_MUTATIONS = FLUSHING_MUTATIONS.concat(mutations);
		if(IS_FLUSHING) {
			return;
		}

		IS_FLUSHING = true;

		var index = 0;

		var processedState = {
			connected: new Set(),
			disconnected: new Set(),
			inserted: new Set(),
			removed: new Set()
		};

		while(index < FLUSHING_MUTATIONS.length) {
			var mutation = FLUSHING_MUTATIONS[index];
			// process mutation
			if(mutation.type === "childList") {
				dispatchTreeMutation(mutation, processedState);
			} else if(mutation.type === "attributes") {
				dispatchAttributeChange(mutation);
			}
			index++;

		}
		FLUSHING_MUTATIONS = [];
		IS_FLUSHING = false;
	},
	// called to dipatch later unless we are already dispatching.
	enqueueMutationsAndFlushAsync: function(mutations){
		ENQUEUED_MUTATIONS = ENQUEUED_MUTATIONS.concat(mutations);

		// if there are currently dispatching mutations, this should happen sometime after
		if(!IS_FLUSH_PENDING) {
			IS_FLUSH_PENDING = true;
			nextTick(function(){
				if(IS_FLUSH_PENDING) {
					IS_FLUSH_PENDING = false;
					var pending = ENQUEUED_MUTATIONS;
					ENQUEUED_MUTATIONS = [];
					queue.enqueueAndFlushMutations(pending);
				} else {
					// Someone called enqueueAndFlushMutations before this finished.
				}
			});
		}
	}
};


// ==========================================


domMutate = {
	/**
	* @function can-dom-mutate.dispatchNodeInsertion dispatchNodeInsertion
	* @hide
	*
	* Dispatch an insertion mutation on the given node.
	*
	* @signature `dispatchNodeInsertion( node [, callback ] )`
	* @parent can-dom-mutate.static
	* @param {Node} node The node on which to dispatch an insertion mutation.
	*/
	dispatchNodeInsertion: function (node, target) {
		queue.enqueueMutationsAndFlushAsync(
			[{
				type: "childList",
				target: target,
				addedNodes: [node],
				isConnected: canDomMutate_2_0_9_IsConnected.isConnected(target),
				removedNodes: []
			}]
		);
		/*
		var nodes = new Set();
		util.addToSet( getAllNodes(node), nodes);
		var events = toMutationEvents( canReflect.toArray(nodes) );
		// this is basically an array of every single child of node including node
		dispatchInsertion(events, callback, dispatchConnected, flushAsync);*/
	},

	/**
	* @function can-dom-mutate.dispatchNodeRemoval dispatchNodeRemoval
	* @hide
	*
	* Dispatch a removal mutation on the given node.
	*
	* @signature `dispatchNodeRemoval( node [, callback ] )`
	* @parent can-dom-mutate.static
	* @param {Node} node The node on which to dispatch a removal mutation.
	* @param {function} callback The optional callback called after the mutation is dispatched.
	*/
	dispatchNodeRemoval: function (node, target) {
		queue.enqueueMutationsAndFlushAsync(
			[{
				type: "childList",
				target: target,
				addedNodes: [],
				removedNodes: [node],
				isConnected: canDomMutate_2_0_9_IsConnected.isConnected(target)
			}]
		);
		/*
		var nodes = new Set();
		util.addToSet( getAllNodes(node), nodes);
		var events = toMutationEvents( canReflect.toArray(nodes) );
		dispatchRemoval(events, callback, dispatchConnected, flushAsync);*/
	},

	/**
	* @function can-dom-mutate.dispatchNodeAttributeChange dispatchNodeAttributeChange
	* @parent can-dom-mutate.static
	* @hide
	*
	* Dispatch an attribute change mutation on the given node.
	*
	* @signature `dispatchNodeAttributeChange( node, attributeName, oldValue [, callback ] )`
	*
	* ```
	* input.setAttribute("value", "newValue")
	* domMutate.dispatchNodeAttributeChange(input, "value","oldValue")
	* ```
	*
	*
	* @param {Node} target The node on which to dispatch an attribute change mutation.
	* @param {String} attributeName The attribute name whose value has changed.
	* @param {String} oldValue The attribute value before the change.
	*/
	dispatchNodeAttributeChange: function (target, attributeName, oldValue) {
		queue.enqueueMutationsAndFlushAsync(
			[{
				type: "attributes",
				target: target,
				attributeName: attributeName,
				oldValue: oldValue
			}]
		);
	},

	/**
	* @function can-dom-mutate.onNodeConnected onNodeConnected
	*
	* Listen for insertion mutations on the given node.
	*
	* @signature `onNodeConnected( node, callback )`
	* @parent can-dom-mutate.static
	* @param {Node} node The node on which to listen for insertion mutations.
	* @param {function} callback The callback called when an insertion mutation is dispatched.
	* @return {function} The callback to remove the mutation listener.
	*/
	onNodeConnected: addNodeConnectedListener,
	onNodeInsertion: function(){
		// TODO: remove in prod
		console.warn("can-dom-mutate: Use onNodeConnected instead of onNodeInsertion");
		return addNodeConnectedListener.apply(this, arguments);
	},
	/**
	* @function can-dom-mutate.onNodeDisconnected onNodeDisconnected
	*
	* Listen for removal mutations on the given node.
	*
	* @signature `onNodeDisconnected( node, callback )`
	* @parent can-dom-mutate.static
	* @param {Node} node The node on which to listen for removal mutations.
	* @param {function} callback The callback called when a removal mutation is dispatched.
	* @return {function} The callback to remove the mutation listener.
	*/
	onNodeDisconnected: addNodeDisconnectedListener,
	onNodeRemoval: function(){
		// TODO: remove in prod
		console.warn("can-dom-mutate: Use onNodeDisconnected instead of onNodeRemoval");
		return addNodeDisconnectedListener.apply(this, arguments);
	},
	/**
	* @function can-dom-mutate.onNodeAttributeChange onNodeAttributeChange
	*
	* Listen for attribute change mutations on the given node.
	*
	* @signature `onNodeAttributeChange( node, callback )`
	* @parent can-dom-mutate.static
	* @param {Node} node The node on which to listen for attribute change mutations.
	* @param {function} callback The callback called when an attribute change mutation is dispatched.
	* @return {function} The callback to remove the mutation listener.
	*/
	onNodeAttributeChange: addNodeAttributeChangeListener,

	/**
	* @function can-dom-mutate.onDisconnected onDisconnected
	*
	* Listen for removal mutations on any node within the documentElement.
	*
	* @signature `onDisconnected( documentElement, callback )`
	* @parent can-dom-mutate.static
	* @param {Node} documentElement The documentElement on which to listen for removal mutations.
	* @param {function} callback The callback called when a removal mutation is dispatched.
	* @return {function} The callback to remove the mutation listener.
	*/
	onDisconnected: addDisconnectedListener,
	onRemoval: function(){
		// TODO: remove in prod
		console.warn("can-dom-mutate: Use onDisconnected instead of onRemoval");
		return addDisconnectedListener.apply(this, arguments);
	},
	/**
	* @function can-dom-mutate.onConnected onConnected
	*
	* Listen for insertion mutations on any node within the documentElement.
	*
	* @signature `onConnected( documentElement, callback )`
	* @parent can-dom-mutate.static
	* @param {Node} documentElement The documentElement on which to listen for removal mutations.
	* @param {function} callback The callback called when a insertion mutation is dispatched.
	* @return {function} The callback to remove the mutation listener.
	*/
	onConnected: addConnectedListener,
	onInsertion: function(){
		// TODO: remove in prod
		console.warn("can-dom-mutate: Use onConnected instead of onInsertion");
		return addConnectedListener.apply(this, arguments);
	},
	/**
	* @function can-dom-mutate.onAttributeChange onAttributeChange
	*
	* Listen for attribute change mutations on any node within the documentElement.
	*
	* @signature `onAttributeChange( documentElement, callback )`
	* @parent can-dom-mutate.static
	* @param {Node} documentElement The documentElement on which to listen for removal mutations.
	* @param {function} callback The callback called when an attribute change mutation is dispatched.
	* @return {function} The callback to remove the mutation listener.
	*/
	onAttributeChange: addAttributeChangeListener,

	flushRecords: function(doc){
		doc = doc || document$1();
		var data = dataStore.get(doc),
			records = [];
		if(data) {
			if(data.domMutationTreeData && data.domMutationTreeData.observer) {
				records = data.domMutationTreeData.observer.takeRecords();
			}
		}
		queue.enqueueAndFlushMutations(records);
	},
	onNodeInserted: addNodeInsertedListener,
	onNodeRemoved: addNodeRemovedListener
};

//!steal-remove-start
if(process.env.NODE_ENV !== "production") {
	domMutate.dataStore = dataStore;
}
//!steal-remove-end

var canDomMutate_2_0_9_canDomMutate = canNamespace_1_0_0_canNamespace.domMutate = domMutate;

var getParents$1 = canDomMutate_2_0_9_Util.getParents;



var compat = {
	replaceChild: function (newChild, oldChild) {
		var newChildren = getParents$1(newChild);
		var result = this.replaceChild(newChild, oldChild);
		canDomMutate_2_0_9_canDomMutate.dispatchNodeRemoval(oldChild, this);
		for (var i = 0; i < newChildren.length; i++) {
			canDomMutate_2_0_9_canDomMutate.dispatchNodeInsertion(newChildren[i], this);
		}
		return result;
	},
	setAttribute: function (name, value) {
		var oldAttributeValue = this.getAttribute(name);
		var result = this.setAttribute(name, value);
		var newAttributeValue = this.getAttribute(name);
		if (oldAttributeValue !== newAttributeValue) {
			canDomMutate_2_0_9_canDomMutate.dispatchNodeAttributeChange(this, name, oldAttributeValue);
		}
		return result;
	},
	setAttributeNS: function (namespace, name, value) {
		var oldAttributeValue = this.getAttribute(name);
		var result = this.setAttributeNS(namespace, name, value);
		var newAttributeValue = this.getAttribute(name);
		if (oldAttributeValue !== newAttributeValue) {
			canDomMutate_2_0_9_canDomMutate.dispatchNodeAttributeChange(this, name, oldAttributeValue);
		}
		return result;
	},
	removeAttribute: function (name) {
		var oldAttributeValue = this.getAttribute(name);
		var result = this.removeAttribute(name);
		if (oldAttributeValue) {
			canDomMutate_2_0_9_canDomMutate.dispatchNodeAttributeChange(this, name, oldAttributeValue);
		}
		return result;
	}
};

var compatData = [
	['appendChild', 'Insertion'],
	['insertBefore', 'Insertion'],
	['removeChild', 'Removal']
];
compatData.forEach(function (pair) {
	var nodeMethod = pair[0];
	var dispatchMethod = 'dispatchNode' + pair[1];
	compat[nodeMethod] = function (node) {
		var nodes = getParents$1(node);
		var result = this[nodeMethod].apply(this, arguments);
		for (var i = 0; i < nodes.length; i++) {
			canDomMutate_2_0_9_canDomMutate[dispatchMethod](nodes[i], this);
		}
		return result;
	};
});

var normal = {};
var nodeMethods = ['appendChild', 'insertBefore', 'removeChild', 'replaceChild', 'setAttribute', 'setAttributeNS', 'removeAttribute'];
nodeMethods.forEach(function (methodName) {
	normal[methodName] = function () {
		if(canDomMutate_2_0_9_IsConnected.isConnected(this)) {
			return this[methodName].apply(this, arguments);
		} else {
			return compat[methodName].apply(this, arguments);
		}
	};
});

/**
* @module {{}} can-dom-mutate/node node
* @parent can-dom-mutate/modules
*
* Append, insert, and remove DOM nodes. Also, change node attributes.
* This allows mutations to be dispatched in environments where MutationObserver is not supported.
* @signature `mutateNode`
*
* Exports an `Object` with methods that shouhld be used to mutate HTML.
*
* ```js
* var mutateNode = require('can-dom-mutate/node');
* var el = document.createElement('div');
*
* mutateNode.appendChild.call(document.body, el);
*
* ```
*/
var mutate$1 = {};

/**
* @function can-dom-mutate/node.appendChild appendChild
* @parent can-dom-mutate/node
*
* Append a node to an element, effectively `Node.prototype.appendChild`.
*
* @signature `mutate.appendChild.call(parent, child)`
*
* @param {Node} parent The parent into which the child is inserted.
* @param {Node} child The child which will be inserted into the parent.
* @return {Node} The appended child.
*/

/**
* @function can-dom-mutate/node.insertBefore insertBefore
* @parent can-dom-mutate/node
*
* Insert a node before a given reference node in an element, effectively `Node.prototype.insertBefore`.
*
* @signature `mutate.insertBefore.call(parent, child, reference)`
* @param {Node} parent The parent into which the child is inserted.
* @param {Node} child The child which will be inserted into the parent.
* @param {Node} reference The reference which the child will be placed before.
* @return {Node} The inserted child.
*/

/**
* @function can-dom-mutate/node.removeChild removeChild
* @parent can-dom-mutate/node
*
* Remove a node from an element, effectively `Node.prototype.removeChild`.
*
* @signature `mutate.removeChild.call(parent, child)`
*
* @param {Node} parent The parent from which the child is removed.
* @param {Node} child The child which will be removed from the parent.
* @return {Node} The removed child.
*/

/**
* @function can-dom-mutate/node.replaceChild replaceChild
* @parent can-dom-mutate/node
*
* Insert a node before a given reference node in an element, effectively `Node.prototype.replaceChild`.
*
* @signature `mutate.replaceChild.call(parent, newChild, oldChild)`
*
* @param {Node} parent The parent into which the newChild is inserted.
* @param {Node} newChild The child which is inserted into the parent.
* @param {Node} oldChild The child which is removed from the parent.
* @return {Node} The replaced child.
*/

/**
* @function can-dom-mutate/node.setAttribute setAttribute
* @parent can-dom-mutate/node
*
* Set an attribute value on an element, effectively `Element.prototype.setAttribute`.
*
* @signature `mutate.setAttribute.call(element, name, value)`
*
* @param {Element} element The element on which to set the attribute.
* @param {String} name The name of the attribute to set.
* @param {String} value The value to set on the attribute.
*/

/**
* @function can-dom-mutate/node.removeAttribute removeAttribute
* @parent can-dom-mutate/node
*
* Removes an attribute from an element, effectively `Element.prototype.removeAttribute`.
*
* @signature `mutate.removeAttribute.call(element, name, value)`
*
* @param {Element} element The element from which to remove the attribute.
* @param {String} name The name of the attribute to remove.
*/

function setMutateStrategy(observer) {
	var strategy = observer ? normal : compat;

	for (var key in strategy) {
		mutate$1[key] = strategy[key];
	}
}

var mutationObserverKey = 'MutationObserver';
setMutateStrategy(canGlobals_1_2_2_canGlobals.getKeyValue(mutationObserverKey));
canGlobals_1_2_2_canGlobals.onKeyValue(mutationObserverKey, setMutateStrategy);

var node = canNamespace_1_0_0_canNamespace.domMutateNode = canDomMutate_2_0_9_canDomMutate.node = mutate$1;

// backwards compatibility
var canDomMutate_2_0_9_node = canNamespace_1_0_0_canNamespace.node = node;

/**
 * @module {function} can-child-nodes
 * @parent can-dom-utilities
 * @collection can-infrastructure
 * @package ./package.json
 * 
 * @signature `childNodes(node)`
 *
 * Get all of the childNodes of a given node.
 *
 * ```js
 * var stache = require("can-stache");
 * var childNodes = require("can-util/child-nodes/child-nodes");
 *
 * var html = "<div><h1><span></span></h1></div>";
 * var frag = stache(html)();
 *
 * console.log(childNodes(frag)[0].nodeName); // -> DIV
 * ```
 *
 * @param {Object} node The Node that you want child nodes for.
 */

function childNodes(node) {
	var childNodes = node.childNodes;
	if ("length" in childNodes) {
		return childNodes;
	} else {
		var cur = node.firstChild;
		var nodes = [];
		while (cur) {
			nodes.push(cur);
			cur = cur.nextSibling;
		}
		return nodes;
	}
}

var canChildNodes_1_2_1_canChildNodes = canNamespace_1_0_0_canNamespace.childNodes = childNodes;

/**
@module {function} can-fragment
@parent can-dom-utilities
@collection can-infrastructure
@package ./package.json

Convert a String, HTMLElement, documentFragment, contentArray, or object with a `can.toDOM` symbol into a documentFragment.

@signature `fragment(item, doc)`

@param {String|HTMLElement|documentFragment|contentArray} item
@param {Document} doc   an optional DOM document in which to build the fragment

@return {documentFragment}

@body

## Use

ContentArrays can be used to combine multiple HTMLElements into a single document fragment.  For example:

    var fragment = require("can-fragment");

    var p = document.createElement("p");
    p.innerHTML = "Welcome to <b>CanJS</b>";
    var contentArray = ["<h1>Hi There</h1>", p];
    var fragment = fragment( contentArray )

`fragment` will be a documentFragment with the following elements:

    <h1>Hi There</h1>
    <p>Welcome to <b>CanJS</b></p>

 */


// fragment.js
// ---------
// _DOM Fragment support._
var fragmentRE = /^\s*<(\w+)[^>]*>/,
	toString = {}.toString,
	toDOMSymbol = canSymbol_1_7_0_canSymbol.for("can.toDOM");

function makeFragment(html, name, doc) {
	if (name === undefined) {
		name = fragmentRE.test(html) && RegExp.$1;
	}
	if (html && toString.call(html.replace) === "[object Function]") {
		// Fix "XHTML"-style tags in all browsers
		html = html.replace(/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, '<$1></$2>');
	}
	var container = doc.createElement('div'),
		temp = doc.createElement('div');
	// IE's parser will strip any `<tr><td>` tags when `innerHTML`
	// is called on a `tbody`. To get around this, we construct a
	// valid table with a `tbody` that has the `innerHTML` we want.
	// Then the container is the `firstChild` of the `tbody`.
	// [source](http://www.ericvasilik.com/2006/07/code-karma.html).
	if (name === 'tbody' || name === 'tfoot' || name === 'thead' || name === 'colgroup') {
		temp.innerHTML = '<table>' + html + '</table>';
		container = temp.firstChild.nodeType === 3 ? temp.lastChild : temp.firstChild;
	} else if (name === 'col') {
		temp.innerHTML = '<table><colgroup>' + html + '</colgroup></table>';
		container = temp.firstChild.nodeType === 3 ? temp.lastChild : temp.firstChild.firstChild;
	} else if (name === 'tr') {
		temp.innerHTML = '<table><tbody>' + html + '</tbody></table>';
		container = temp.firstChild.nodeType === 3 ? temp.lastChild : temp.firstChild.firstChild;
	} else if (name === 'td' || name === 'th') {
		temp.innerHTML = '<table><tbody><tr>' + html + '</tr></tbody></table>';
		container = temp.firstChild.nodeType === 3 ? temp.lastChild : temp.firstChild.firstChild.firstChild;
	} else if (name === 'option') {
		temp.innerHTML = '<select>' + html + '</select>';
		container = temp.firstChild.nodeType === 3 ? temp.lastChild : temp.firstChild;
	} else {
		container.innerHTML = '' + html;
	}

	return [].slice.call(canChildNodes_1_2_1_canChildNodes(container));
}

function fragment(html, doc) {
	if (html && html.nodeType === 11) {
		return html;
	}
	if (!doc) {
		doc = document$1();
	} else if (doc.length) {
		doc = doc[0];
	}

	var parts = makeFragment(html, undefined, doc),
		frag = (doc || document).createDocumentFragment();
	for (var i = 0, length = parts.length; i < length; i++) {
		frag.appendChild(parts[i]);
	}
	return frag;
}

var makeFrag = function(item, doc) {
	var document = doc || document$1();
	var frag;
	if (!item || typeof item === "string") {
		frag = fragment(item == null ? "" : "" + item, document);
		// If we have an empty frag...
	} else if(typeof item[toDOMSymbol] === "function") {
		return makeFrag(item[toDOMSymbol]());
	}
	else if (item.nodeType === 11) {
		return item;
	} else if (typeof item.nodeType === "number") {
		frag = document.createDocumentFragment();
		frag.appendChild(item);
		return frag;
	} else if (canReflect_1_19_2_canReflect.isListLike(item)) {
		frag = document.createDocumentFragment();
		canReflect_1_19_2_canReflect.eachIndex(item, function(item) {
			frag.appendChild(makeFrag(item));
		});
	} else {
		frag = fragment("" + item, document);
	}
    if (!canChildNodes_1_2_1_canChildNodes(frag).length) {
        frag.appendChild(document.createTextNode(''));
    }
    return frag;
};

var canFragment_1_3_1_canFragment = canNamespace_1_0_0_canNamespace.fragment = canNamespace_1_0_0_canNamespace.frag = makeFrag;

var canViewCallbacks_5_0_0_canViewCallbacks = createCommonjsModule(function (module) {













var callbackMapSymbol = canSymbol_1_7_0_canSymbol.for('can.callbackMap');
var initializeSymbol = canSymbol_1_7_0_canSymbol.for('can.initialize');

//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	var requestedAttributes = {};
}
//!steal-remove-end

var tags = {};

// WeakSet containing elements that have been rendered already
// and therefore do not need to be rendered again

var automountEnabled = function(){
	var document = canGlobals_1_2_2_canGlobals.getKeyValue("document");
	if(document == null || document.documentElement == null) {
		return false;
	}
	return document.documentElement.getAttribute("data-can-automount") !== "false";
};

var renderedElements = new WeakMap();

var mountElement = function (node) {
	var tagName = node.tagName && node.tagName.toLowerCase();
	var tagHandler = tags[tagName];

	// skip elements that already have a viewmodel or elements whose tags don't match a registered tag
	// or elements that have already been rendered
	if (tagHandler) {
		callbacks.tagHandler(node, tagName, {});
	}
};

var mutationObserverEnabled = false;
var disableMutationObserver;
var enableMutationObserver = function() {
	var docEl = document$1().documentElement;

	if (mutationObserverEnabled) {
		if (mutationObserverEnabled === docEl) {
			return;
		}
		// if the document has changed, re-enable mutationObserver
		disableMutationObserver();
	}

	var undoOnInsertionHandler = canDomMutate_2_0_9_canDomMutate.onConnected(docEl, function(mutation) {
		mountElement(mutation.target);
	});
	mutationObserverEnabled = true;

	disableMutationObserver = function() {
		undoOnInsertionHandler();
		mutationObserverEnabled = false;
	};
};

var renderTagsInDocument = function(tagName) {
	var nodes = document$1().getElementsByTagName(tagName);

	for (var i=0, node; (node = nodes[i]) !== undefined; i++) {
		mountElement(node);
	}
};

var attr = function (attributeName, attrHandler) {
	if(attrHandler) {
		if (typeof attributeName === "string") {
			attributes[attributeName] = attrHandler;
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				if(requestedAttributes[attributeName]) {
					dev.warn("can-view-callbacks: " + attributeName+ " custom attribute behavior requested before it was defined.  Make sure "+attributeName+" is defined before it is needed.");
				}
			}
			//!steal-remove-end
		} else {
			regExpAttributes.push({
				match: attributeName,
				handler: attrHandler
			});

			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				Object.keys(requestedAttributes).forEach(function(requested){
					if(attributeName.test(requested)) {
						dev.warn("can-view-callbacks: " + requested+ " custom attribute behavior requested before it was defined.  Make sure "+requested+" is defined before it is needed.");
					}
				});
			}
			//!steal-remove-end
		}
	} else {
		var cb = attributes[attributeName];
		if( !cb ) {

			for( var i = 0, len = regExpAttributes.length; i < len; i++) {
				var attrMatcher = regExpAttributes[i];
				if(attrMatcher.match.test(attributeName)) {
					return attrMatcher.handler;
				}
			}
		}
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			requestedAttributes[attributeName] = true;
		}
		//!steal-remove-end

		return cb;
	}
};

var attrs = function(attrMap) {
	var map = canReflect_1_19_2_canReflect.getKeyValue(attrMap, callbackMapSymbol) || attrMap;

	// Only add bindings once.
	if(attrMaps.has(map)) {
		return;
	} else {
		// Would prefer to use WeakSet but IE11 doesn't support it.
		attrMaps.set(map, true);
	}

	canReflect_1_19_2_canReflect.eachKey(map, function(callback, exp){
		attr(exp, callback);
	});
};

var attributes = {},
	regExpAttributes = [],
	attrMaps = new WeakMap(),
	automaticCustomElementCharacters = /[-\:]/;
var defaultCallback = function () {};

var tag = function (tagName, tagHandler) {
	if(tagHandler) {
		var validCustomElementName = automaticCustomElementCharacters.test(tagName),
			tagExists = typeof tags[tagName.toLowerCase()] !== 'undefined',
			customElementExists;

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			if (tagExists) {
				dev.warn("Custom tag: " + tagName.toLowerCase() + " is already defined");
			}

			if (!validCustomElementName && tagName !== "content") {
				dev.warn("Custom tag: " + tagName.toLowerCase() + " hyphen missed");
			}
		}
		//!steal-remove-end

		tags[tagName.toLowerCase()] = tagHandler;

		if(automountEnabled()) {
			var customElements = canGlobals_1_2_2_canGlobals.getKeyValue("customElements");

			// automatically render elements that have tagHandlers
			// If browser supports customElements, register the tag as a custom element
			if (customElements) {
				customElementExists = customElements.get(tagName.toLowerCase());

				if (validCustomElementName && !customElementExists) {
					var CustomElement = function() {
						return Reflect.construct(HTMLElement, [], CustomElement);
					};

					CustomElement.prototype = Object.create(HTMLElement.prototype);
					CustomElement.prototype.constructor = CustomElement;

					CustomElement.prototype.connectedCallback = function() {
						callbacks.tagHandler(this, tagName.toLowerCase(), {});
					};

					customElements.define(tagName, CustomElement);
				}
			}
			// If browser doesn't support customElements, set up MutationObserver for
			// rendering elements when they are inserted in the page
			// and rendering elements that are already in the page
			else {
				enableMutationObserver();
				renderTagsInDocument(tagName);
			}
		} else if(mutationObserverEnabled) {
			disableMutationObserver();
		}
	} else {
		var cb;

		// if null is passed as tagHandler, remove tag
		if (tagHandler === null) {
			delete tags[tagName.toLowerCase()];
		} else {
			cb = tags[tagName.toLowerCase()];
		}

		if(!cb && automaticCustomElementCharacters.test(tagName)) {
			// empty callback for things that look like special tags
			cb = defaultCallback;
		}
		return cb;
	}

};

var callbacks = {
	_tags: tags,
	_attributes: attributes,
	_regExpAttributes: regExpAttributes,
	defaultCallback: defaultCallback,
	tag: tag,
	attr: attr,
	attrs: attrs,
	// handles calling back a tag callback
	tagHandler: function(el, tagName, tagData){
		// skip elements that have already been rendered
		if (renderedElements.has(el)) {
			return;
		}

		var scope = tagData.scope,
			helperTagCallback = scope && scope.templateContext.tags.get(tagName),
			tagCallback = helperTagCallback || tags[tagName] || el[initializeSymbol],
			res;

		// If this was an element like <foo-bar> that doesn't have a component, just render its content
		if(tagCallback) {
			res = canObservationRecorder_1_3_1_canObservationRecorder.ignore(tagCallback)(el, tagData);

			// add the element to the Set of elements that have had their handlers called
			// this will prevent the handler from being called again when the element is inserted
			renderedElements.set(el, true);
		} else {
			res = scope;
		}

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			if (!tagCallback) {
				var GLOBAL = global_1();
				var ceConstructor = document$1().createElement(tagName).constructor;
				// If not registered as a custom element, the browser will use default constructors
				if (ceConstructor === GLOBAL.HTMLElement || ceConstructor === GLOBAL.HTMLUnknownElement) {
					dev.warn('can-view-callbacks: No custom element found for ' + tagName);
				}
			}
		}
		//!steal-remove-end

		// If the tagCallback gave us something to render with, and there is content within that element
		// render it!
		if (res && tagData.subtemplate) {
			if (scope !== res) {
				scope = scope.add(res);
			}

			//var nodeList = nodeLists.register([], undefined, tagData.parentNodeList || true, false);
			//nodeList.expression = "<" + el.tagName + ">";

			var result = tagData.subtemplate(scope, tagData.options);
			var frag = typeof result === "string" ? canFragment_1_3_1_canFragment(result) : result;
			canDomMutate_2_0_9_node.appendChild.call(el, frag);
		}
	}
};

canNamespace_1_0_0_canNamespace.view = canNamespace_1_0_0_canNamespace.view || {};

if (canNamespace_1_0_0_canNamespace.view.callbacks) {
	throw new Error("You can't have two versions of can-view-callbacks, check your dependencies");
} else {
	module.exports = canNamespace_1_0_0_canNamespace.view.callbacks = callbacks;
}
});

/* jshint maxdepth:7 */
/* jshint latedef:false */





// if an object or a function
// convert into what it should look like
// then the modification can happen in place
// but it has to have more than the current node
// blah!
var processNodes = function(nodes, paths, location, document){
	var frag = document.createDocumentFragment();

	for(var i = 0, len = nodes.length; i < len; i++) {
		var node = nodes[i];
		frag.appendChild( processNode(node,paths,location.concat(i), document) );
	}
	return frag;
},
	keepsTextNodes =  typeof document !== "undefined" && (function(){
		var testFrag = document.createDocumentFragment();
		var div = document.createElement("div");

		div.appendChild(document.createTextNode(""));
		div.appendChild(document.createTextNode(""));
		testFrag.appendChild(div);

		var cloned  = testFrag.cloneNode(true);

		return cloned.firstChild.childNodes.length === 2;
	})(),
	clonesWork = typeof document !== "undefined" && (function(){
		// Since html5shiv is required to support custom elements, assume cloning
		// works in any browser that doesn't have html5shiv

		// Clone an element containing a custom tag to see if the innerHTML is what we
		// expect it to be, or if not it probably was created outside of the document's
		// namespace.
		var el = document.createElement('a');
		el.innerHTML = "<xyz></xyz>";
		var clone = el.cloneNode(true);
		var works = clone.innerHTML === "<xyz></xyz>";
		var MO, observer;

		if(works) {
			// Cloning text nodes with dashes seems to create multiple nodes in IE11 when
			// MutationObservers of subtree modifications are used on the documentElement.
			// Since this is not what we expect we have to include detecting it here as well.
			el = document.createDocumentFragment();
			el.appendChild(document.createTextNode('foo-bar'));

			MO = mutationObserver();

			if (MO) {
				observer = new MO(function() {});
				observer.observe(document.documentElement, { childList: true, subtree: true });

				clone = el.cloneNode(true);

				observer.disconnect();
			} else {
				clone = el.cloneNode(true);
			}

			return clone.childNodes.length === 1;
		}

		return works;
	})(),
	namespacesWork = typeof document !== "undefined" && !!document.createElementNS;

/**
 * @function cloneNode
 * @hide
 *
 * A custom cloneNode function to be used in browsers that properly support cloning
 * of custom tags (IE8 for example). Fixes it by doing some manual cloning that
 * uses innerHTML instead, which has been shimmed.
 *
 * @param {DocumentFragment} frag A document fragment to clone
 * @return {DocumentFragment} a new fragment that is a clone of the provided argument
 */
var cloneNode = clonesWork ?
	function(el){
		return el.cloneNode(true);
	} :
	function(node){
		var document = node.ownerDocument;
		var copy;

		if(node.nodeType === 1) {
			if(node.namespaceURI !== 'http://www.w3.org/1999/xhtml' && namespacesWork && document.createElementNS) {
				copy = document.createElementNS(node.namespaceURI, node.nodeName);
			}
			else {
				copy = document.createElement(node.nodeName);
			}
		} else if(node.nodeType === 3){
			copy = document.createTextNode(node.nodeValue);
		} else if(node.nodeType === 8) {
			copy = document.createComment(node.nodeValue);
		} else if(node.nodeType === 11) {
			copy = document.createDocumentFragment();
		}

		if(node.attributes) {
			var attributes = node.attributes;
			for (var i = 0; i < attributes.length; i++) {
				var attribute = attributes[i];
				if (attribute && attribute.specified) {
					// If the attribute has a namespace set the namespace 
					// otherwise it will be set to null
					if (attribute.namespaceURI) {
						copy.setAttributeNS(attribute.namespaceURI, attribute.nodeName || attribute.name, attribute.nodeValue || attribute.value);
					} else {
						copy.setAttribute(attribute.nodeName || attribute.name, attribute.nodeValue || attribute.value);
					}
				}
			}
		}

		if(node && node.firstChild) {
			var child = node.firstChild;

			while(child) {
				copy.appendChild( cloneNode(child) );
				child = child.nextSibling;
			}
		}

		return copy;
	};

function processNode(node, paths, location, document){
	var callback,
		loc = location,
		nodeType = typeof node,
		el,
		p,
		i , len;
	var getCallback = function(){
		if(!callback) {
			callback  = {
				path: location,
				callbacks: []
			};
			paths.push(callback);
			loc = [];
		}
		return callback;
	};

	if(nodeType === "object") {
		if( node.tag ) {
			if(namespacesWork && node.namespace) {
				el = document.createElementNS(node.namespace, node.tag);
			} else {
				el = document.createElement(node.tag);
			}

			if(node.attrs) {
				for(var attrName in node.attrs) {
					var value = node.attrs[attrName];
					if(typeof value === "function"){
						getCallback().callbacks.push({
							callback:  value
						});
					} else if (value !== null && typeof value === "object" && value.namespaceURI) {
						el.setAttributeNS(value.namespaceURI,attrName,value.value);
					} else {
						canDomMutate_2_0_9_node.setAttribute.call(el, attrName, value);
					}
				}
			}
			if(node.attributes) {
				for(i = 0, len = node.attributes.length; i < len; i++ ) {
					getCallback().callbacks.push({callback: node.attributes[i]});
				}
			}
			if(node.children && node.children.length) {
				// add paths
				if(callback) {
					p = callback.paths = [];
				} else {
					p = paths;
				}

				el.appendChild( processNodes(node.children, p, loc, document) );
			}
		} else if(node.comment) {
			el = document.createComment(node.comment);

			if(node.callbacks) {
				for(i = 0, len = node.callbacks.length; i < len; i++ ) {
					getCallback().callbacks.push({callback: node.callbacks[i]});
				}
			}
		}


	} else if(nodeType === "string"){

		el = document.createTextNode(node);

	} else if(nodeType === "function") {

		if(keepsTextNodes) {
			el = document.createTextNode("");
			getCallback().callbacks.push({
				callback: node
			});
		} else {
			el = document.createComment("~");
			getCallback().callbacks.push({
				callback: function(){
					var el = document.createTextNode("");
					canDomMutate_2_0_9_node.replaceChild.call(this.parentNode, el, this);
					return node.apply(el,arguments );
				}
			});
		}

	}
	return el;
}

function getCallbacks(el, pathData, elementCallbacks){
	var path = pathData.path,
		callbacks = pathData.callbacks,
		paths = pathData.paths,
		child = el,
		pathLength = path ? path.length : 0,
		pathsLength = paths ? paths.length : 0;

	for(var i = 0; i < pathLength; i++) {
		child = child.childNodes.item(path[i]);
	}

	for( i= 0 ; i < pathsLength; i++) {
		getCallbacks(child, paths[i], elementCallbacks);
	}

	elementCallbacks.push({element: child, callbacks: callbacks});
}

function hydrateCallbacks(callbacks, args) {
	var len = callbacks.length,
		callbacksLength,
		callbackElement,
		callbackData;

	for(var i = 0; i < len; i++) {
		callbackData = callbacks[i];
		callbacksLength = callbackData.callbacks.length;
		callbackElement = callbackData.element;
		for(var c = 0; c < callbacksLength; c++) {
			callbackData.callbacks[c].callback.apply(callbackElement, args);
		}
	}
}

function makeTarget(nodes, doc){
	var paths = [];
	var frag = processNodes(nodes, paths, [], doc || document$1());
	return {
		paths: paths,
		clone: frag,
		hydrate: function(){
			var cloned = cloneNode(this.clone);
			var args = [];
			for (var a = 0, ref = args.length = arguments.length; a < ref; a++) {
				args[a] = arguments[a];
			} // see https://jsperf.com/nodelist-to-array

			var callbacks = [];
			for(var i = 0; i < paths.length; i++) {
				getCallbacks(cloned, paths[i], callbacks);
			}
			hydrateCallbacks(callbacks, args);

			return cloned;
		}
	};
}
makeTarget.keepsTextNodes = keepsTextNodes;
makeTarget.cloneNode = cloneNode;

canNamespace_1_0_0_canNamespace.view = canNamespace_1_0_0_canNamespace.view || {};
var canViewTarget_5_0_0_canViewTarget = canNamespace_1_0_0_canNamespace.view.target = makeTarget;

var getKeyValueSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.getKeyValue"),
	observeDataSymbol = canSymbol_1_7_0_canSymbol.for("can.meta");

var promiseDataPrototype = {
	isPending: true,
	state: "pending",
	isResolved: false,
	isRejected: false,
	value: undefined,
	reason: undefined
};

function setVirtualProp(promise, property, value) {
	var observeData = promise[observeDataSymbol];
	var old = observeData[property];
	observeData[property] = value;
	canQueues_1_3_2_canQueues.enqueueByQueue(observeData.handlers.getNode([property]), promise, [value,old], function() {
		return {};
	},["Promise", promise, "resolved with value", value, "and changed virtual property: "+property]);
}

function initPromise(promise) {
	var observeData = promise[observeDataSymbol];
	if(!observeData) {
		Object.defineProperty(promise, observeDataSymbol, {
			enumerable: false,
			configurable: false,
			writable: false,
			value: Object.create(promiseDataPrototype)
		});
		observeData = promise[observeDataSymbol];
		observeData.handlers = new canKeyTree_1_2_2_canKeyTree([Object, Object, Array]);
	}
	promise.then(function(value){
		canQueues_1_3_2_canQueues.batch.start();
		setVirtualProp(promise, "isPending", false);
		setVirtualProp(promise, "isResolved", true);
		setVirtualProp(promise, "value", value);
		setVirtualProp(promise, "state", "resolved");
		canQueues_1_3_2_canQueues.batch.stop();
	}, function(reason){
		canQueues_1_3_2_canQueues.batch.start();
		setVirtualProp(promise, "isPending", false);
		setVirtualProp(promise, "isRejected", true);
		setVirtualProp(promise, "reason", reason);
		setVirtualProp(promise, "state", "rejected");
		canQueues_1_3_2_canQueues.batch.stop();

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			dev.error("Failed promise:", reason);
		}
		//!steal-remove-end
	});
}

function setupPromise(value) {
	var oldPromiseFn;
	var proto = "getPrototypeOf" in Object ? Object.getPrototypeOf(value) : value.__proto__; //jshint ignore:line

	if(value[getKeyValueSymbol$2] && value[observeDataSymbol]) {
		// promise has already been set up.  Don't overwrite.
		return;
	}

	if(proto === null || proto === Object.prototype) {
		// promise type is a plain object or dictionary.  Set up object instead of proto.
		proto = value;

		if(typeof proto.promise === "function") {
			// Duck-type identification as a jQuery.Deferred;
			// In that case, the promise() function returns a new object
			//  that needs to be decorated.
			oldPromiseFn = proto.promise;
			proto.promise = function() {
				var result = oldPromiseFn.call(proto);
				setupPromise(result);
				return result;
			};
		}
	}

	canReflect_1_19_2_canReflect.assignSymbols(proto, {
		"can.getKeyValue": function(key) {
			if(!this[observeDataSymbol]) {
				initPromise(this);
			}

			canObservationRecorder_1_3_1_canObservationRecorder.add(this, key);
			switch(key) {
				case "state":
				case "isPending":
				case "isResolved":
				case "isRejected":
				case "value":
				case "reason":
				return this[observeDataSymbol][key];
				default:
				return this[key];
			}
		},
		"can.getValue": function() {
			return this[getKeyValueSymbol$2]("value");
		},
		"can.isValueLike": false,
		"can.onKeyValue": function(key, handler, queue) {
			if(!this[observeDataSymbol]) {
				initPromise(this);
			}
			this[observeDataSymbol].handlers.add([key, queue || "mutate", handler]);
		},
		"can.offKeyValue": function(key, handler, queue) {
			if(!this[observeDataSymbol]) {
				initPromise(this);
			}
			this[observeDataSymbol].handlers.delete([key, queue || "mutate", handler]);
		},
		"can.hasOwnKey": function(key) {
			if (!this[observeDataSymbol]) {
				initPromise(this);
			}
			return (key in this[observeDataSymbol]);
		}
	});
}

var canReflectPromise_2_2_1_canReflectPromise = setupPromise;

var getValueSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.getValue");
var setValueSymbol$3 = canSymbol_1_7_0_canSymbol.for("can.setValue");

var isValueLikeSymbol = canSymbol_1_7_0_canSymbol.for("can.isValueLike");
var peek$3 = canObservationRecorder_1_3_1_canObservationRecorder.ignore(canReflect_1_19_2_canReflect.getKeyValue.bind(canReflect_1_19_2_canReflect));
var observeReader;
var isPromiseLike = canObservationRecorder_1_3_1_canObservationRecorder.ignore(function isPromiseLike(value){
	return typeof value === "object" && value && typeof value.then === "function";
});

var bindName = Function.prototype.bind;
//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	bindName = function(source){
		var fn = Function.prototype.bind.call(this, source);
		Object.defineProperty(fn, "name", {
			value: canReflect_1_19_2_canReflect.getName(source) + "."+canReflect_1_19_2_canReflect.getName(this)
		});
		return fn;
	};
}
//!steal-remove-end

var isAt = function(index, reads) {
	var prevRead = reads[index-1];
	return prevRead && prevRead.at;
};

var readValue = function(value, index, reads, options, state, prev){
	// if the previous read is AT false ... we shouldn't be doing this;
	var usedValueReader;
	do {

		usedValueReader = false;
		for(var i =0, len = observeReader.valueReaders.length; i < len; i++){
			if( observeReader.valueReaders[i].test(value, index, reads, options) ) {
				value = observeReader.valueReaders[i].read(value, index, reads, options, state, prev);
				//usedValueReader = true;
			}
		}
	} while(usedValueReader);

	return value;
};

var specialRead = {index: true, key: true, event: true, element: true, viewModel: true};

var checkForObservableAndNotify = function(options, state, getObserves, value, index){
	if(options.foundObservable && !state.foundObservable) {
		if(canObservationRecorder_1_3_1_canObservationRecorder.trapsCount()) {
			canObservationRecorder_1_3_1_canObservationRecorder.addMany( getObserves() );
			options.foundObservable(value, index);
			state.foundObservable = true;
		}
	}
};

var objHasKeyAtIndex = function(obj, reads, index) {
	return !!(
		reads && reads.length &&
		canReflect_1_19_2_canReflect.hasKey(obj, reads[index].key)
	);
};

observeReader = {
	// there are things that you need to evaluate when you get them back as a property read
	// for example a compute or a function you might need to call to get the next value to
	// actually check
	// - readCompute - can be set to `false` to prevent reading an ending compute.  This is used by component to get a
	//   compute as a delegate.  In 3.0, this should be removed and force people to write "{@prop} change"
	// - callMethodsOnObservables - this is an overwrite ... so normal methods won't be called, but observable ones will.
	// - executeAnonymousFunctions - call a function if it's found, defaults to true
	// - proxyMethods - if the last read is a method, return a function so `this` will be correct.
	// - args - arguments to call functions with.
	//
	// Callbacks
	// - earlyExit - called if a value could not be found
	// - foundObservable - called when an observable value is found
	read: function (parent, reads, options) {
		options = options || {};
		var state = {
			foundObservable: false
		};
		var getObserves;
		if(options.foundObservable) {
			getObserves = canObservationRecorder_1_3_1_canObservationRecorder.trap();
		}

		// `cur` is the current value.
		var cur = readValue(parent, 0, reads, options, state),
			// `prev` is the object we are reading from.
			prev,
			// `foundObs` did we find an observable.
			readLength = reads.length,
			i = 0,
			parentHasKey;

		checkForObservableAndNotify(options, state, getObserves, parent, 0);

		while( i < readLength ) {
			prev = cur;
			// try to read the property
			for(var r=0, readersLength = observeReader.propertyReaders.length; r < readersLength; r++) {
				var reader = observeReader.propertyReaders[r];
				if(reader.test(cur)) {
					cur = reader.read(cur, reads[i], i, options, state);
					break; // there can be only one reading of a property
				}
			}
			checkForObservableAndNotify(options, state, getObserves, prev, i);
			i = i+1;
			// read the value if it is a compute or function
			cur = readValue(cur, i, reads, options, state, prev);

			checkForObservableAndNotify(options, state, getObserves, prev, i-1);
			// early exit if need be
			if (i < reads.length && (cur === null || cur === undefined )) {
				parentHasKey = objHasKeyAtIndex(prev, reads, i - 1);
				if (options.earlyExit && !parentHasKey) {
					options.earlyExit(prev, i - 1, cur);
				}
				// return undefined so we know this isn't the right value
				return {
					value: undefined,
					parent: prev,
					parentHasKey: parentHasKey,
					foundLastParent: false
				};
			}

		}

		parentHasKey = objHasKeyAtIndex(prev, reads, reads.length - 1);
		// if we don't have a value, exit early.
		if (cur === undefined && !parentHasKey) {
			if (options.earlyExit) {
				options.earlyExit(prev, i - 1);
			}
		}
		return {
			value: cur,
			parent: prev,
			parentHasKey: parentHasKey,
			foundLastParent: true
		};
	},
	get: function(parent, reads, options){
		return observeReader.read(parent, observeReader.reads(reads), options || {}).value;
	},
	valueReadersMap: {},
	// an array of types that might have a value inside them like functions
	// value readers check the current value
	// and get a new value from it
	// ideally they would keep calling until
	// none of these passed
	valueReaders: [
		{
			name: "function",
			// if this is a function before the last read and its not a constructor function
			test: function(value){
				return value && canReflect_1_19_2_canReflect.isFunctionLike(value) && !canReflect_1_19_2_canReflect.isConstructorLike(value);
			},
			read: function(value, i, reads, options, state, prev){
				if(options.callMethodsOnObservables && canReflect_1_19_2_canReflect.isObservableLike(prev) && canReflect_1_19_2_canReflect.isMapLike(prev)) {
					dev.warn("can-stache-key: read() called with `callMethodsOnObservables: true`.");

					return value.apply(prev, options.args || []);
				}

				return options.proxyMethods !== false ? bindName.call(value, prev) : value;
			}
		},
		{
			name: "isValueLike",
			// compute value reader
			test: function(value, i, reads, options) {
				return value && value[getValueSymbol$2] && value[isValueLikeSymbol] !== false && (options.foundAt || !isAt(i, reads) );
			},
			read: function(value, i, reads, options){
				if(options.readCompute === false && i === reads.length ) {
					return value;
				}
				return canReflect_1_19_2_canReflect.getValue(value);
			},
			write: function(base, newVal){
				if(base[setValueSymbol$3]) {
					base[setValueSymbol$3](newVal);
				} else if(base.set) {
					base.set(newVal);
				} else {
					base(newVal);
				}
			}
		}],
	propertyReadersMap: {},
	// an array of things that might have a property
	propertyReaders: [
		{
			name: "map",
			test: function(value){
				// the first time we try reading from a promise, set it up for
				//  special reflections.
				if(canReflect_1_19_2_canReflect.isPromise(value) ||
					isPromiseLike(value)) {
					canReflectPromise_2_2_1_canReflectPromise(value);
				}

				return canReflect_1_19_2_canReflect.isObservableLike(value) && canReflect_1_19_2_canReflect.isMapLike(value);
			},
			read: function(value, prop){
				var res = canReflect_1_19_2_canReflect.getKeyValue(value, prop.key);
				if(res !== undefined) {
					return res;
				} else {
					return value[prop.key];
				}
			},
			write: canReflect_1_19_2_canReflect.setKeyValue
		},

		// read a normal object
		{
			name: "object",
			// this is the default
			test: function(){return true;},
			read: function(value, prop, i, options){
				if(value == null) {
					return undefined;
				} else {
					if(typeof value === "object") {
						if(prop.key in value) {
							return value[prop.key];
						}
						// TODO: remove in 5.0.
						//!steal-remove-start
						if (process.env.NODE_ENV !== 'production') {
							if( prop.at && specialRead[prop.key] && ( ("@"+prop.key) in value)) {
								options.foundAt = true;
								dev.warn("Use %"+prop.key+" in place of @"+prop.key+".");
								return undefined;
							}
						}
						//!steal-remove-end
					} else {
						return value[prop.key];
					}
				}
			},
			write: function(base, prop, newVal){
				var propValue = base[prop];
				// if newVal is observable object, lets try to update
				if(newVal != null && typeof newVal === "object" && canReflect_1_19_2_canReflect.isMapLike(propValue) ) {
					dev.warn("can-stache-key: Merging data into \"" + prop + "\" because its parent is non-observable");
					canReflect_1_19_2_canReflect.update(propValue, newVal);
				} else if(propValue != null && propValue[setValueSymbol$3] !== undefined){
					canReflect_1_19_2_canReflect.setValue(propValue, newVal);
				} else {
					base[prop] = newVal;
				}
			}
		}
	],
	reads: function(keyArg) {
		var key = ""+keyArg;
		var keys = [];
		var last = 0;
		var at = false;
		if( key.charAt(0) === "@" ) {
			last = 1;
			at = true;
		}
		var keyToAdd = "";
		for(var i = last; i < key.length; i++) {
			var character = key.charAt(i);
			if(character === "." || character === "@") {
				if( key.charAt(i -1) !== "\\" ) {
					keys.push({
						key: keyToAdd,
						at: at
					});
					at = character === "@";
					keyToAdd = "";
				} else {
					keyToAdd = keyToAdd.substr(0,keyToAdd.length - 1) + ".";
				}
			} else {
				keyToAdd += character;
			}
		}
		keys.push({
			key: keyToAdd,
			at: at
		});

		return keys;
	},
	// This should be able to set a property similar to how read works.
	write: function(parent, key, value, options) {
		var keys = typeof key === "string" ? observeReader.reads(key) : key;
		var last;

		options = options || {};
		if(keys.length > 1) {
			last = keys.pop();
			parent = observeReader.read(parent, keys, options).value;
			keys.push(last);
		} else {
			last = keys[0];
		}
		if(!parent) {
			return;
		}
		var keyValue = peek$3(parent, last.key);
		// here's where we need to figure out the best way to write

		// if property being set points at a compute, set the compute
		if( observeReader.valueReadersMap.isValueLike.test(keyValue, keys.length - 1, keys, options) ) {
			observeReader.valueReadersMap.isValueLike.write(keyValue, value, options);
		} else {
			if(observeReader.valueReadersMap.isValueLike.test(parent, keys.length - 1, keys, options) ) {
				parent = parent[getValueSymbol$2]();
			}
			if(observeReader.propertyReadersMap.map.test(parent)) {
				observeReader.propertyReadersMap.map.write(parent, last.key, value, options);
			}
			else if(observeReader.propertyReadersMap.object.test(parent)) {
				observeReader.propertyReadersMap.object.write(parent, last.key, value, options);
				if(options.observation) {
					options.observation.update();
				}
			}
		}
	}
};
observeReader.propertyReaders.forEach(function(reader){
	observeReader.propertyReadersMap[reader.name] = reader;
});
observeReader.valueReaders.forEach(function(reader){
	observeReader.valueReadersMap[reader.name] = reader;
});
observeReader.set = observeReader.write;

var canStacheKey_1_4_3_canStacheKey = observeReader;

var TemplateContext = function(options) {
	options = options || {};
	this.vars = new canSimpleMap_4_3_3_canSimpleMap(options.vars || {});
	this.helpers = new canSimpleMap_4_3_3_canSimpleMap(options.helpers || {});
	this.partials = new canSimpleMap_4_3_3_canSimpleMap(options.partials || {});
	this.tags = new canSimpleMap_4_3_3_canSimpleMap(options.tags || {});
};

var canViewScope_4_13_7_templateContext = TemplateContext;

var canCid_1_3_1_canCid = createCommonjsModule(function (module) {

/**
 * @module {function} can-cid
 * @parent can-typed-data
 * @collection can-infrastructure
 * @package ./package.json
 * @description Utility for getting a unique identifier for an object.
 * @signature `cid(object, optionalObjectType)`
 *
 * Get a unique identifier for the object, optionally prefixed by a type name.
 *
 * Once set, the unique identifier does not change, even if the type name
 * changes on subsequent calls.
 *
 * ```js
 * var cid = require("can-cid");
 * var x = {};
 * var y = {};
 *
 * console.log(cid(x, "demo")); // -> "demo1"
 * console.log(cid(x, "prod")); // -> "demo1"
 * console.log(cid(y));         // -> "2"
 * ```
 *
 * @param {Object} object The object to uniquely identify.
 * @param {String} name   An optional type name with which to prefix the identifier
 *
 * @return {String} Returns the unique identifier
 */
var _cid = 0;
// DOM nodes shouldn't all use the same property
var domExpando = "can" + new Date();
var cid = function (object, name) {
	var propertyName = object.nodeName ? domExpando : "_cid";

	if (!object[propertyName]) {
		_cid++;
		object[propertyName] = (name || '') + _cid;
	}
	return object[propertyName];
};
cid.domExpando = domExpando;
cid.get = function(object){
	var type = typeof object;
	var isObject = type !== null && (type === "object" || type === "function");
	return isObject ? cid(object) : (type + ":" + object);
};

if (canNamespace_1_0_0_canNamespace.cid) {
	throw new Error("You can't have two versions of can-cid, check your dependencies");
} else {
	module.exports = canNamespace_1_0_0_canNamespace.cid = cid;
}
});

var singleReference;

function getKeyName(key, extraKey) {
	var keyName = extraKey ? canCid_1_3_1_canCid(key) + ":" + extraKey : canCid_1_3_1_canCid(key);
	return keyName || key;
}

// weak maps are slow
/* if(typeof WeakMap !== "undefined") {
	var globalMap = new WeakMap();
	singleReference = {
		set: function(obj, key, value){
			var localMap = globalMap.get(obj);
			if( !localMap ) {
				globalMap.set(obj, localMap = new WeakMap());
			}
			localMap.set(key, value);
		},
		getAndDelete: function(obj, key){
			return globalMap.get(obj).get(key);
		},
		references: globalMap
	};
} else {*/
singleReference = {
	// obj is a function ... we need to place `value` on it so we can retreive it
	// we can't use a global map
	set: function(obj, key, value, extraKey){
		// check if it has a single reference map
		obj[getKeyName(key, extraKey)] = value;
	},

	getAndDelete: function(obj, key, extraKey){
		var keyName = getKeyName(key, extraKey);
		var value = obj[keyName];
		delete obj[keyName];
		return value;
	}
};
/*}*/

var canSingleReference_1_3_0_canSingleReference = singleReference;

var Compute = function(newVal){
	if(arguments.length) {
		return canReflect_1_19_2_canReflect.setValue(this, newVal);
	} else {
		return canReflect_1_19_2_canReflect.getValue(this);
	}
};

var canViewScope_4_13_7_makeComputeLike = function(observable) {
    var compute = Compute.bind(observable);

	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		Object.defineProperty(compute, "name", {
			value: "Compute<"+canReflect_1_19_2_canReflect.getName(observable) + ">",
		});
	}
	//!steal-remove-end

    compute.on = compute.bind = compute.addEventListener = function(event, handler) {
        var translationHandler = function(newVal, oldVal) {
            handler.call(compute, {type:'change'}, newVal, oldVal);
        };
        canSingleReference_1_3_0_canSingleReference.set(handler, this, translationHandler);
        observable.on(translationHandler);
    };
    compute.off = compute.unbind = compute.removeEventListener = function(event, handler) {
        observable.off( canSingleReference_1_3_0_canSingleReference.getAndDelete(handler, this) );
    };

    canReflect_1_19_2_canReflect.assignSymbols(compute, {
        "can.getValue": function(){
            return canReflect_1_19_2_canReflect.getValue(observable);
        },
        "can.setValue": function(newVal){
            return canReflect_1_19_2_canReflect.setValue(observable, newVal);
        },
        "can.onValue": function(handler, queue){
            return canReflect_1_19_2_canReflect.onValue(observable, handler, queue);
        },
        "can.offValue": function(handler, queue){
            return canReflect_1_19_2_canReflect.offValue(observable, handler, queue);
        },
        "can.valueHasDependencies": function(){
            return canReflect_1_19_2_canReflect.valueHasDependencies(observable);
        },
        "can.getPriority": function(){
    		return canReflect_1_19_2_canReflect.getPriority( observable );
    	},
    	"can.setPriority": function(newPriority){
    		canReflect_1_19_2_canReflect.setPriority( observable, newPriority );
    	},
		"can.isValueLike": true,
		"can.isFunctionLike": false
    });
    compute.isComputed = true;
    return compute;
};

var canStacheHelpers_1_2_0_canStacheHelpers = createCommonjsModule(function (module) {


if (canNamespace_1_0_0_canNamespace.stacheHelpers) {
	throw new Error("You can't have two versions of can-stache-helpers, check your dependencies");
} else {
	module.exports = canNamespace_1_0_0_canNamespace.stacheHelpers = {};
}
});

var dispatchSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.dispatch");
var setElementSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.setElement");

// The goal of this is to create a high-performance compute that represents a key value from can.view.Scope.
// If the key value is something like {{name}} and the context is a can.Map, a faster
// binding path will be used where new rebindings don't need to be looked for with every change of
// the observable property.
// However, if the property changes to a compute, then the slower `can.compute.read` method of
// observing values will be used.

// ideally, we would know the order things were read.  If the last thing read
// was something we can observe, and the value of it matched the value of the observation,
// and the key matched the key of the observation
// it's a fair bet that we can just listen to that last object.
// If the `this` is not that object ... freak out.  Though `this` is not necessarily part of it.  can-observation could make
// this work.


var getFastPathRoot = canObservationRecorder_1_3_1_canObservationRecorder.ignore(function(computeData){
	if( computeData.reads &&
				// a single property read
				computeData.reads.length === 1 ) {
		var root = computeData.root;
		if( root && root[canSymbol_1_7_0_canSymbol.for("can.getValue")] ) {
			root = canReflect_1_19_2_canReflect.getValue(root);
		}
		// on a map
		return root && canReflect_1_19_2_canReflect.isObservableLike(root) && canReflect_1_19_2_canReflect.isMapLike(root) &&
			// that isn't calling a function
			typeof root[computeData.reads[0].key] !== "function" && root;
	}
	return;
});

var isEventObject = function(obj){
	return obj && typeof obj.batchNum === "number" && typeof obj.type === "string";
};

function getMutated(scopeKeyData){
	// The _thisArg is the value before the last `.`. For example if the key was `foo.bar.zed`,
	// _thisArg would be the value at foo.bar.
	// This should be improved as `foo.bar` might not be observable.
	var value$$1 = canObservationRecorder_1_3_1_canObservationRecorder.peekValue(scopeKeyData._thisArg);

	// Something like `string@split` would provide a primitive which can't be a mutated subject
	return !canReflect_1_19_2_canReflect.isPrimitive(value$$1) ? value$$1 : scopeKeyData.root;
}

function callMutateWithRightArgs(method, mutated, reads, mutator){
	if(reads.length) {
		method.call(canReflectDependencies_1_1_2_canReflectDependencies,mutated, reads[ reads.length - 1 ].key ,mutator);
	} else {
		method.call(canReflectDependencies_1_1_2_canReflectDependencies,mutated ,mutator);
	}
}




var warnOnUndefinedProperty;
//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	warnOnUndefinedProperty = function(options) {
		if ( options.key !== "debugger" && !options.parentHasKey) {
			var filename = options.scope.peek('scope.filename');
			var lineNumber = options.scope.peek('scope.lineNumber');

			var reads = canStacheKey_1_4_3_canStacheKey.reads(options.key);
			var firstKey = reads[0].key;
			var key = reads.map(function(read) {
				return read.key + (read.at ? "()" : "");
			}).join(".");
			var pathsForKey = options.scope.getPathsForKey(firstKey);
			var paths = Object.keys( pathsForKey );
			var firstKeyValue = options.scope.get(firstKey);

			var includeSuggestions = paths.length && (paths.indexOf(firstKey) < 0);

			var warning = [
				(filename ? filename + ':' : '') +
					(lineNumber ? lineNumber + ': ' : '') +
					'Unable to find key "' + key + '".'
			];

			if (includeSuggestions) {
				warning[0] = warning[0] + ' Did you mean' + (paths.length > 1 ? ' one of these' : '') + '?\n';
				paths.forEach(function(path) {
					warning.push('\t"' + path + '" which will read from');
					warning.push(pathsForKey[path]);
					warning.push("\n");
				});
			} else if (firstKeyValue) {
				warning[0] = warning[0] + ' Found "' + firstKey + '" with value: %o\n';
			}

			if (firstKeyValue) {
				dev.warn.apply(dev, [warning.join("\n"), firstKeyValue]);
			} else {
				dev.warn.apply(dev,
					warning
				);
			}

		}
	};
}
//!steal-remove-end

// could we make this an observation first ... and have a getter for the compute?

// This is a fast-path enabled Observation wrapper use many places in can-stache.
// The goal of this is to:
//
// 1.  Make something that can be passed to can-view-live directly, hopefully
//     avoiding creating expensive computes.  Instead we will only be creating
//     `ScopeKeyData` which are thin wrappers.
var ScopeKeyData = function(scope, key, options){

	this.startingScope = scope;
	this.key = key;
	this.read = this.read.bind(this);
	this.dispatch = this.dispatch.bind(this);

	// special case debugger helper so that it is called with helperOtions
	// when you do {{debugger}} as it already is with {{debugger()}}
	if (key === "debugger") {
		// prevent "Unable to find key" warning
		this.startingScope = { _context: canStacheHelpers_1_2_0_canStacheHelpers };

		this.read = function() {
			var helperOptions = { scope: scope };
			var debuggerHelper = canStacheHelpers_1_2_0_canStacheHelpers["debugger"];
			return debuggerHelper(helperOptions);
		};
	}

	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		Object.defineProperty(this.read, "name", {
			value: canReflect_1_19_2_canReflect.getName(this) + ".read",
		});
		Object.defineProperty(this.dispatch, "name", {
			value: canReflect_1_19_2_canReflect.getName(this) + ".dispatch",
		});
	}
	//!steal-remove-end

	var observation = this.observation = new canObservation_4_2_0_canObservation(this.read, this);
	this.options = canAssign_1_3_3_canAssign({ observation: this.observation }, options);

	// things added later
	this.fastPath = undefined;
	this.root = undefined;
	this.reads = undefined;
	this.setRoot = undefined;
	// This is read by call expressions so it needs to be observable
	this._thisArg = new canSimpleObservable_2_5_0_canSimpleObservable();
	this.parentHasKey = undefined;
	var valueDependencies = new Set();
	valueDependencies.add(observation);
	this.dependencies = {valueDependencies: valueDependencies};

	// This is basically what .get() should give, but it
	// isn't used to figure out the last value.
	this._latestValue = undefined;
};

value(ScopeKeyData.prototype);

function fastOnBoundSet_Value() {
	this._value = this.newVal;
}

function fastOnBoundSetValue() {
	this.value = this.newVal;
}

canAssign_1_3_3_canAssign(ScopeKeyData.prototype, {
	constructor: ScopeKeyData,
	dispatch: function dispatch(newVal){
		var old = this.value;
		this._latestValue = this.value = newVal;
		// call the base implementation in can-event-queue
		this[dispatchSymbol$2].call(this, this.value, old);
	},
	onBound: function onBound(){
		this.bound = true;
		canReflect_1_19_2_canReflect.onValue(this.observation, this.dispatch, "notify");
		// TODO: we should check this sometime in the background.
		var fastPathRoot = getFastPathRoot(this);
		if( fastPathRoot ) {
			// rewrite the observation to call its event handlers
			this.toFastPath(fastPathRoot);
		}
		this._latestValue = this.value = canObservationRecorder_1_3_1_canObservationRecorder.peekValue(this.observation);
	},
	onUnbound: function onUnbound() {
		this.bound = false;
		canReflect_1_19_2_canReflect.offValue(this.observation, this.dispatch, "notify");
		this.toSlowPath();
	},
	set: function(newVal){
		var root = this.root || this.setRoot;
		if(root) {
			if(this.reads.length) {
				canStacheKey_1_4_3_canStacheKey.write(root, this.reads, newVal, this.options);
			} else {
				canReflect_1_19_2_canReflect.setValue(root,newVal);
			}
		} else {
			this.startingScope.set(this.key, newVal, this.options);
		}
	},
	get: function() {
		if (canObservationRecorder_1_3_1_canObservationRecorder.isRecording()) {
			canObservationRecorder_1_3_1_canObservationRecorder.add(this);
			if (!this.bound) {
				canObservation_4_2_0_canObservation.temporarilyBind(this);
			}
		}

		if (this.bound === true && this.fastPath === true) {
			return this._latestValue;
		} else {
			return canObservationRecorder_1_3_1_canObservationRecorder.peekValue(this.observation);
		}
	},
	toFastPath: function(fastPathRoot){
		var self = this,
			observation = this.observation;

		this.fastPath = true;

		// there won't be an event in the future ...
		observation.dependencyChange = function(target, newVal){
			if(isEventObject(newVal)) {
				throw "no event objects!";
			}
			// but I think we will be able to get at it b/c there should only be one
			// dependency we are binding to ...
			if(target === fastPathRoot && typeof newVal !== "function") {
				self._latestValue = newVal;
				this.newVal = newVal;
			} else {
				// restore
				self.toSlowPath();
			}

			return canObservation_4_2_0_canObservation.prototype.dependencyChange.apply(this, arguments);
		};

		if (observation.hasOwnProperty("_value")) {// can-observation 4.1+
			observation.onBound = fastOnBoundSet_Value;
		} else {// can-observation < 4.1
			observation.onBound = fastOnBoundSetValue;
		}
	},
	toSlowPath: function(){
		this.observation.dependencyChange = canObservation_4_2_0_canObservation.prototype.dependencyChange;
		this.observation.onBound = canObservation_4_2_0_canObservation.prototype.onBound;
		this.fastPath = false;
	},
	read: function(){
		var data;

		if (this.root) {
			// if we've figured out a root observable, start reading from there
			data = canStacheKey_1_4_3_canStacheKey.read(this.root, this.reads, this.options);

			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				// remove old dependency
				if(this.reads.length) {
					callMutateWithRightArgs(canReflectDependencies_1_1_2_canReflectDependencies.deleteMutatedBy, getMutated(this), this.reads,this);
				}

			}
			//!steal-remove-end

			// update thisArg and add new dependency
			this.thisArg = data.parent;

			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				var valueDeps = new Set();
				valueDeps.add(this);
				callMutateWithRightArgs(canReflectDependencies_1_1_2_canReflectDependencies.addMutatedBy, data.parent || this.root, this.reads,{
					valueDependencies: valueDeps
				});
			}
			//!steal-remove-end

			return data.value;
		}
		// If the key has not already been located in a observable then we need to search the scope for the
		// key.  Once we find the key then we need to return it's value and if it is found in an observable
		// then we need to store the observable so the next time this compute is called it can grab the value
		// directly from the observable.
		data = this.startingScope.read(this.key, this.options);


		this.scope = data.scope;
		this.reads = data.reads;
		this.root = data.rootObserve;
		this.setRoot = data.setRoot;
		this.thisArg = data.thisArg;
		this.parentHasKey = data.parentHasKey;

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			if (data.rootObserve) {
				var rootValueDeps = new Set();
				rootValueDeps.add(this);
				callMutateWithRightArgs(canReflectDependencies_1_1_2_canReflectDependencies.addMutatedBy, getMutated(this), data.reads,{
					valueDependencies: rootValueDeps
				});
			}
			if(data.value === undefined && this.options.warnOnMissingKey === true) {
				warnOnUndefinedProperty({
					scope: this.startingScope,
					key: this.key,
					parentHasKey: data.parentHasKey
				});
			}
		}
		//!steal-remove-end

		return data.value;
	},
	hasDependencies: function(){
		// ScopeKeyData is unique in that when these things are read, it will temporarily bind
		// to make sure the right value is returned. This is for can-stache.
		// Helpers warns about a missing helper.
		if (!this.bound) {
			canObservation_4_2_0_canObservation.temporarilyBind(this);
		}
		return canReflect_1_19_2_canReflect.valueHasDependencies( this.observation );
	}
});

Object.defineProperty(ScopeKeyData.prototype, "thisArg", {
	get: function(){
		return this._thisArg.get();
	},
	set: function(newVal) {
		this._thisArg.set(newVal);
	}
});

var scopeKeyDataPrototype = {
	"can.getValue": ScopeKeyData.prototype.get,
	"can.setValue": ScopeKeyData.prototype.set,
	"can.valueHasDependencies": ScopeKeyData.prototype.hasDependencies,
	"can.getValueDependencies": function() {
		return this.dependencies;
	},
	"can.getPriority": function(){
		return canReflect_1_19_2_canReflect.getPriority( this.observation );
	},
	"can.setPriority": function(newPriority){
		canReflect_1_19_2_canReflect.setPriority( this.observation, newPriority );
	},
	"can.setElement": function(element) {
		this.observation[setElementSymbol$1](element);
	}
};

//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	scopeKeyDataPrototype["can.getName"] = function() {
		return canReflect_1_19_2_canReflect.getName(this.constructor) + "{{" + this.key + "}}";
	};
}
//!steal-remove-end
canReflect_1_19_2_canReflect.assignSymbols(ScopeKeyData.prototype, scopeKeyDataPrototype);

// Creates a compute-like for legacy reasons ...
Object.defineProperty(ScopeKeyData.prototype, "compute", {
	get: function(){
		var compute = canViewScope_4_13_7_makeComputeLike(this);

		Object.defineProperty(this, "compute", {
			value: compute,
			writable: false,
			configurable: false
		});
		return compute;
	},
	configurable: true
});

Object.defineProperty(ScopeKeyData.prototype, "initialValue", {
	get: function(){
		if (!this.bound) {
			canObservation_4_2_0_canObservation.temporarilyBind(this);
		}
		return canObservationRecorder_1_3_1_canObservationRecorder.peekValue(this);
	},
	set: function(){
		throw new Error("initialValue should not be set");
	},
	configurable: true
});

var canViewScope_4_13_7_scopeKeyData = ScopeKeyData;

var canViewScope_4_13_7_compute_data = function(scope, key, options){
	return new canViewScope_4_13_7_scopeKeyData(scope, key, options || {
		args: []
	});
};

// ### LetContext
// Instances of this are used to create a `let` variable context.

// Like Object.create, but only keeps Symbols and properties in `propertiesToKeep`
function objectCreateWithSymbolsAndSpecificProperties(obj, propertiesToKeep) {
	var newObj = {};

	// copy over all Symbols from obj
	if ("getOwnPropertySymbols" in Object) {
		Object.getOwnPropertySymbols(obj).forEach(function(key) {
			newObj[key] = obj[key];
		});
	}

	// copy over specific properties from obj (also fake Symbols properties for IE support);
	Object.getOwnPropertyNames(obj).forEach(function(key) {
		if (propertiesToKeep.indexOf(key) >= 0 || key.indexOf("@@symbol") === 0) {
			newObj[key] = obj[key];
		}
	});

	return Object.create(newObj);
}

var LetContext = canSimpleMap_4_3_3_canSimpleMap.extend("LetContext", {});
LetContext.prototype = objectCreateWithSymbolsAndSpecificProperties(canSimpleMap_4_3_3_canSimpleMap.prototype, [
	// SimpleMap properties
	"setup",
	"attr",
	"serialize",
	"get",
	"set",
	"log",
	// required by SimpleMap properties
	"dispatch",
	// Construct properties (not added by can-event-queue)
	"constructorExtends",
	"newInstance",
	"_inherit",
	"_defineProperty",
	"_overwrite",
	"instance",
	"extend",
	"ReturnValue",
	"setup",
	"init"
]);
LetContext.prototype.constructor = LetContext;

var canViewScope_4_13_7_letContext = LetContext;

// # can-view-scope.js
//
// This provides the ability to lookup values across a higherarchy of objects.  This is similar to
// how closures work in JavaScript.
//
// This is done with the `Scope` type. It works by having a `_context` reference to
// an object whose properties can be searched for values.  It also has a `_parent` reference
// to the next Scope in which to check.  In this way, `Scope` is used to form a tree-like
// structure.  Leaves and Nodes in the tree only point to their parent.













// ## Helpers

function canHaveProperties(obj){
	return obj != null;
}
function returnFalse(){
	return false;
}

// ## Scope
// Represents a node in the scope tree.
function Scope(context, parent, meta) {
	// The object that will be looked on for values.
	// If the type of context is TemplateContext, there will be special rules for it.
	this._context = context;
	// The next Scope object whose context should be looked on for values.
	this._parent = parent;
	// If this is a special context, it can be labeled here.
	// Options are:
	// - `viewModel` - This is a viewModel. This is mostly used by can-component to make `scope.vm` work.
	// - `notContext` - This can't be looked within using `./` and `../`. It will be skipped.
	//   This is for virtual contexts like those used by `%index`. This is very much like
	//   `variable`.  Most things should switch to `variable` in the future.
	// - `special` - This can't be looked within using `./` and `../`. It will be skipped.
	//   This is for reading properties on the scope {{scope.index}}. It's different from variable
	//   because it's never lookup up like {{key}}.
	// - `variable` - This is used to define a variable (as opposed to "normal" context). These
	//   will also be skipped when using `./` and `../`.
	this._meta = meta || {};

	// A cache that can be used to store computes used to look up within this scope.
	// For example if someone creates a compute to lookup `name`, another compute does not
	// need to be created.
	this.__cache = {};
}

var parentContextSearch = /(\.\.\/)|(\.\/)|(this[\.@])/g;

// ## Static Methods
// The following methods are exposed mostly for testing purposes.
canAssign_1_3_3_canAssign(Scope, {
	// ### Scope.read
	// Scope.read was moved to can-stache-key.read
	// can-stache-key.read reads properties from a parent. A much more complex version of getObject.
	read: canStacheKey_1_4_3_canStacheKey.read,
	TemplateContext: canViewScope_4_13_7_templateContext,
	// ### keyInfo(key)
	// Returns an object that details what the `key` means with the following:
	// ```js
	// {
	//   remainingKey, // what would be read on a context (or this)
	//   isScope, // if the scope itself is being read
	//   inScope, // if a key on the scope is being read
	//   parentContextWalkCount, // how many ../
	//   isContextBased // if a "normal" context is explicitly being read
	// }
	// ```
	keyInfo: function(attr){

		if (attr === "./") {
			attr = "this";
		}

		var info = {remainingKey: attr};

		// handle scope stuff first
		info.isScope = attr === "scope";
		if(info.isScope) {
			return info;
		}
		var firstSix = attr.substr(0, 6);
		info.isInScope =
			firstSix === "scope." ||
			firstSix === "scope@";
		if(info.isInScope) {
			info.remainingKey = attr.substr(6);
			return info;
		} else if(firstSix === "scope/") {
			info.walkScope = true;
			info.remainingKey = attr.substr(6);
			return info;
		} else if(attr.substr(0, 7) === "@scope/") {
			info.walkScope = true;
			info.remainingKey = attr.substr(7);
			return info;
		}

		info.parentContextWalkCount = 0;
		// Searches for `../` and other context specifiers
		info.remainingKey = attr.replace(parentContextSearch, function(token, parentContext, dotSlash, thisContext, index){
			info.isContextBased = true;
			if(parentContext !== undefined) {
				info.parentContextWalkCount++;
			}
			return "";
		});
		// ../..
		if(info.remainingKey === "..") {
			info.parentContextWalkCount++;
			info.remainingKey = "this";
		}
		else if(info.remainingKey === "." || info.remainingKey === "") {
			info.remainingKey = "this";
		}

		if(info.remainingKey === "this") {
			info.isContextBased = true;
		}
		return info;
	},
	// ### isTemplateContextOrCanNotHaveProperties
	// Returns `true` if a template context or a `null` or `undefined`
	// context.
	isTemplateContextOrCanNotHaveProperties: function(currentScope){
		var currentContext = currentScope._context;
		if(currentContext instanceof canViewScope_4_13_7_templateContext) {
			return true;
		} else if( !canHaveProperties(currentContext) ) {
			return true;
		}
		return false;
	},
	// ### shouldSkipIfSpecial
	// Return `true` if special.
	shouldSkipIfSpecial: function(currentScope){
		var isSpecialContext = currentScope._meta.special === true;
		if (isSpecialContext === true) {
			return true;
		}
		if( Scope.isTemplateContextOrCanNotHaveProperties(currentScope) ) {
			return true;
		}
		return false;
	},
	// ### shouldSkipEverythingButSpecial
	// Return `true` if not special.
	shouldSkipEverythingButSpecial: function(currentScope){
		var isSpecialContext = currentScope._meta.special === true;
		if (isSpecialContext === false) {
			return true;
		}
		if( Scope.isTemplateContextOrCanNotHaveProperties(currentScope) ) {
			return true;
		}
		return false;
	},
	// ### makeShouldExitOnSecondNormalContext
	// This will keep checking until we hit a second "normal" context.
	makeShouldExitOnSecondNormalContext: function(){
		var foundNormalContext = false;
		return function shouldExitOnSecondNormalContext(currentScope){
			var isNormalContext = !currentScope.isSpecial();
			var shouldExit = isNormalContext && foundNormalContext;
			// leaks some state
			if(isNormalContext) {
				foundNormalContext = true;
			}
			return shouldExit;
		};
	},
	// ### makeShouldExitAfterFirstNormalContext
	// This will not check anything after the first normal context.
	makeShouldExitAfterFirstNormalContext: function(){
		var foundNormalContext = false;
		return function shouldExitAfterFirstNormalContext(currentScope){
			if(foundNormalContext) {
				return true;
			}
			var isNormalContext = !currentScope.isSpecial();
			// leaks some state
			if(isNormalContext) {
				foundNormalContext = true;
			}
			return false;
		};
	},
	// ### makeShouldSkipSpecialContexts
	// Skips `parentContextWalkCount` contexts. This is used to
	// walk past scopes when `../` is used.
	makeShouldSkipSpecialContexts: function(parentContextWalkCount){
		var walkCount = parentContextWalkCount || 0;
		return function shouldSkipSpecialContexts(currentScope){
			// after walking past the correct number of contexts,
			// should not skip notContext scopes
			// so that ../foo can be used to read from a notContext scope
			if (walkCount < 0 && currentScope._meta.notContext) {
				return false;
			}

			if(currentScope.isSpecial()) {
				return true;
			}
			walkCount--;

			if(walkCount < 0) {
				return false;
			}
			return true;
		};
	}
});

// ## Prototype methods
canAssign_1_3_3_canAssign(Scope.prototype, {

	// ### scope.add
	// Creates a new scope and sets the current scope to be the parent.
	// ```
	// var scope = new can.view.Scope([
	//   {name:"Chris"},
	//   {name: "Justin"}
	// ]).add({name: "Brian"});
	// scope.attr("name") //-> "Brian"
	// ```
	add: function(context, meta) {
		if (context !== this._context) {
			return new this.constructor(context, this, meta);
		} else {
			return this;
		}
	},

	// ### scope.find
	// This is the equivalent of Can 3's scope walking.
	find: function(attr, options) {

		var keyReads = canStacheKey_1_4_3_canStacheKey.reads(attr);
		var howToRead = {
			shouldExit: returnFalse,
			shouldSkip: Scope.shouldSkipIfSpecial,
			shouldLookForHelper: true,
			read: canStacheKey_1_4_3_canStacheKey.read
		};
		var result = this._walk(keyReads, options, howToRead);

		return result.value;

	},
	// ### scope.readFromSpecialContext
	readFromSpecialContext: function(key) {
		return this._walk(
			[{key: key, at: false }],
			{ special: true },
			{
				shouldExit: returnFalse,
				shouldSkip: Scope.shouldSkipEverythingButSpecial,
				shouldLookForHelper: false,
				read: canStacheKey_1_4_3_canStacheKey.read
			}
		);
	},

	// ### scope.readFromTemplateContext
	readFromTemplateContext: function(key, readOptions) {
		var keyReads = canStacheKey_1_4_3_canStacheKey.reads(key);
		return canStacheKey_1_4_3_canStacheKey.read(this.templateContext, keyReads, readOptions);
	},

	// ### Scope.prototype.read
	// Reads from the scope chain and returns the first non-`undefined` value.
	// `read` deals mostly with setting up "context based" keys to start reading
	// from the right scope. Once the right scope is located, `_walk` is called.
	/**
	 * @hide
	 * @param {can.stache.key} attr A dot-separated path. Use `"\."` if you have a property name that includes a dot.
	 * @param {can.view.Scope.readOptions} options that configure how this gets read.
	 * @return {{}}
	 *   @option {Object} parent the value's immediate parent
	 *   @option {can.Map|can.compute} rootObserve the first observable to read from.
	 *   @option {Array<String>} reads An array of properties that can be used to read from the rootObserve to get the value.
	 *   @option {*} value the found value
	 */
	read: function(attr, options) {
		options = options || {};
		return this.readKeyInfo(Scope.keyInfo(attr), options || {});
	},
	readKeyInfo: function(keyInfo, options){

		// Identify context based keys. Context based keys try to
		// specify a particular context a key should be within.
		var readValue,
			keyReads,
			howToRead = {
				read: options.read || canStacheKey_1_4_3_canStacheKey.read
			};

		// 1.A. Handle reading the scope itself
		if (keyInfo.isScope) {
			return { value: this };
		}
		// 1.B. Handle reading something on the scope
		else if (keyInfo.isInScope) {
			keyReads = canStacheKey_1_4_3_canStacheKey.reads(keyInfo.remainingKey);
			// check for a value on Scope.prototype
			readValue = canStacheKey_1_4_3_canStacheKey.read(this, keyReads, options);

			// otherwise, check the templateContext
			if (typeof readValue.value === 'undefined' && !readValue.parentHasKey) {
				readValue = this.readFromTemplateContext(keyInfo.remainingKey, options);
			}

			return canAssign_1_3_3_canAssign(readValue, {
				thisArg: keyReads.length > 0 ? readValue.parent : undefined
			});
		}
		// 1.C. Handle context-based reads. They should skip over special stuff.
		// this.key, ../.., .././foo
		else if (keyInfo.isContextBased) {
			// TODO: REMOVE
			// options && options.special === true && console.warn("SPECIAL!!!!");

			if(keyInfo.remainingKey !== "this") {
				keyReads = canStacheKey_1_4_3_canStacheKey.reads(keyInfo.remainingKey);
			} else {
				keyReads = [];
			}
			howToRead.shouldExit = Scope.makeShouldExitOnSecondNormalContext();
			howToRead.shouldSkip = Scope.makeShouldSkipSpecialContexts(keyInfo.parentContextWalkCount);
			howToRead.shouldLookForHelper = true;

			return this._walk(keyReads, options, howToRead);
		}
		// 1.D. Handle scope walking with scope/key
		else if(keyInfo.walkScope) {
			howToRead.shouldExit = returnFalse;
			howToRead.shouldSkip = Scope.shouldSkipIfSpecial;
			howToRead.shouldLookForHelper = true;
			keyReads = canStacheKey_1_4_3_canStacheKey.reads(keyInfo.remainingKey);

			return this._walk(keyReads, options, howToRead);
		}
		// 1.E. Handle reading without context clues
		// {{foo}}
		else {
			keyReads = canStacheKey_1_4_3_canStacheKey.reads(keyInfo.remainingKey);

			var isSpecialRead = options && options.special === true;
			// TODO: remove
			// options && options.special === true && console.warn("SPECIAL!!!!");

			howToRead.shouldExit = Scope.makeShouldExitOnSecondNormalContext();
			howToRead.shouldSkip = isSpecialRead ? Scope.shouldSkipEverythingButSpecial : Scope.shouldSkipIfSpecial;
			howToRead.shouldLookForHelper = isSpecialRead ? false : true;

			return this._walk(keyReads, options, howToRead);
		}
	},


	// ### scope._walk
	// This is used to walk up the scope chain.
	_walk: function(keyReads, options, howToRead) {
		// The current scope and context we are trying to find "keyReads" within.
		var currentScope = this,
			currentContext,

			// If no value can be found, this is a list of of every observed
			// object and property name to observe.
			undefinedObserves = [],

			// Tracks the first found observe.
			currentObserve,
			// Tracks the reads to get the value from `currentObserve`.
			currentReads,

			// Tracks the most likely observable to use as a setter.
			setObserveDepth = -1,
			currentSetReads,
			currentSetObserve,

			readOptions = canAssign_1_3_3_canAssign({
				/* Store found observable, incase we want to set it as the rootObserve. */
				foundObservable: function(observe, nameIndex) {
					currentObserve = observe;
					currentReads = keyReads.slice(nameIndex);
				},
				earlyExit: function(parentValue, nameIndex) {
					var isVariableScope = currentScope._meta.variable === true,
						updateSetObservable = false;
					if(isVariableScope === true && nameIndex === 0) {
						// we MUST have pre-defined the key in a variable scope
						updateSetObservable = canReflect_1_19_2_canReflect.hasKey( parentValue, keyReads[nameIndex].key);
					} else {
						updateSetObservable =
							// Has more matches
							nameIndex > setObserveDepth ||
							// The same number of matches but it has the key
							nameIndex === setObserveDepth && (typeof parentValue === "object" && canReflect_1_19_2_canReflect.hasOwnKey( parentValue, keyReads[nameIndex].key));
					}
					if ( updateSetObservable ) {
						currentSetObserve = currentObserve;
						currentSetReads = currentReads;
						setObserveDepth = nameIndex;
					}
				}
			}, options);



		var isRecording = canObservationRecorder_1_3_1_canObservationRecorder.isRecording(),
			readAContext = false;

		// Goes through each scope context provided until it finds the key (attr). Once the key is found
		// then it's value is returned along with an observe, the current scope and reads.
		// While going through each scope context searching for the key, each observable found is returned and
		// saved so that either the observable the key is found in can be returned, or in the case the key is not
		// found in an observable the closest observable can be returned.
		while (currentScope) {

			if(howToRead.shouldSkip(currentScope) === true) {
				currentScope = currentScope._parent;
				continue;
			}
			if(howToRead.shouldExit(currentScope) === true) {
				break;
			}
			readAContext = true;

			currentContext = currentScope._context;


			// Prevent computes from temporarily observing the reading of observables.
			var getObserves = canObservationRecorder_1_3_1_canObservationRecorder.trap();

			var data = howToRead.read(currentContext, keyReads, readOptions);

			// Retrieve the observes that were read.
			var observes = getObserves();
			// If a **value was was found**, return value and location data.
			if (data.value !== undefined || data.parentHasKey) {

				if(!observes.length && isRecording) {
					// if we didn't actually observe anything
					// the reads and currentObserve don't mean anything
					// we just point to the current object so setting is fast
					currentObserve = data.parent;
					currentReads = keyReads.slice(keyReads.length - 1);
				} else {
					canObservationRecorder_1_3_1_canObservationRecorder.addMany(observes);
				}

				return {
					scope: currentScope,
					rootObserve: currentObserve,
					value: data.value,
					reads: currentReads,
					thisArg: data.parent,
					parentHasKey: data.parentHasKey
				};
			}
			// Otherwise, save all observables that were read. If no value
			// is found, we will observe on all of them.
			else {
				undefinedObserves.push.apply(undefinedObserves, observes);
			}

			currentScope = currentScope._parent;
		}

		// The **value was not found** in the scope
		// if not looking for a "special" key, check in can-stache-helpers
		if (howToRead.shouldLookForHelper) {
			var helper = this.getHelperOrPartial(keyReads);

			if (helper) {
				// Don't return parent so `.bind` is not used.
				return {value: helper};
			}
		}

		// The **value was not found**, return `undefined` for the value.
		// Make sure we listen to everything we checked for when the value becomes defined.
		// Once it becomes defined, we won't have to listen to so many things.
		canObservationRecorder_1_3_1_canObservationRecorder.addMany(undefinedObserves);
		return {
			setRoot: currentSetObserve,
			reads: currentSetReads,
			value: undefined,
			noContextAvailable: !readAContext
		};
	},
	// ### scope.getDataForScopeSet
	// Returns an object with data needed by `.set` to figure out what to set,
	// and how.
	// {
	//   parent: what is being set
	//   key: try setting a key value
	//   how: "setValue" | "set" | "updateDeep" | "write" | "setKeyValue"
	// }
	// This works by changing how `readKeyInfo` will read individual scopes.
	// Specifically, with something like `{{foo.bar}}` it will read `{{foo}}` and
	// only check if a `bar` property exists.
	getDataForScopeSet: function getDataForScopeSet(key, options) {
		var keyInfo = Scope.keyInfo(key);
		var firstSearchedContext;

		// Overwrite the options to use this read.
		var opts = canAssign_1_3_3_canAssign({
			// This read is used by `._walk` to read from the scope.
			// This will use `hasKey` on the last property instead of reading it.
			read: function(context, keys){

				// If nothing can be found with the keys we are looking for, save the
				// first possible match.  This is where we will write to.
				if(firstSearchedContext === undefined && !(context instanceof canViewScope_4_13_7_letContext)) {
					firstSearchedContext = context;
				}
				// If we have multiple keys ...
				if(keys.length > 1) {
					// see if we can find the parent ...
					var parentKeys = keys.slice(0, keys.length-1);
					var parent = canStacheKey_1_4_3_canStacheKey.read(context, parentKeys, options).value;

					// If there is a parent, see if it has the last key
					if( parent != null && canReflect_1_19_2_canReflect.hasKey(parent, keys[keys.length-1].key ) ) {
						return {
							parent: parent,
							parentHasKey: true,
							value: undefined
						};
					} else {
						return {};
					}
				}
				// If we have only one key, try to find a context with this key
				else if(keys.length === 1) {
					if( canReflect_1_19_2_canReflect.hasKey(context, keys[0].key ) ) {
						return {
							parent: context,
							parentHasKey: true,
							value: undefined
						};
					} else {
						return {};
					}
				}
				// If we have no keys, we are reading `this`.
				else {
					return {
						value: context
					};
				}
			}
		},options);


		// Use the read above to figure out what we are probably writing to.
		var readData = this.readKeyInfo(keyInfo, opts);

		if(keyInfo.remainingKey === "this") {
			// If we are setting a context, then return that context
			return { parent: readData.value, how: "setValue" };
		}
		// Now we are trying to set a property on something.  Parent will
		// be the something we are setting a property on.
		var parent;

		var props = keyInfo.remainingKey.split(".");
		var propName = props.pop();

		// If we got a `thisArg`, that's the parent.
		if(readData.thisArg) {
			parent = readData.thisArg;
		}
		// Otherwise, we didn't find anything, use the first searched context.
		// TODO: there is likely a bug here when trying to set foo.bar where nothing in the scope
		// has a foo.
		else if(firstSearchedContext) {
			parent = firstSearchedContext;
		}

		if (parent === undefined) {
			return {
				error: "Attempting to set a value at " +
					key + " where the context is undefined."
			};
		}
		// Now we need to figure out how we would update this value.  The following does that.
		if(!canReflect_1_19_2_canReflect.isObservableLike(parent) && canReflect_1_19_2_canReflect.isObservableLike(parent[propName])) {
			if(canReflect_1_19_2_canReflect.isMapLike(parent[propName])) {
				return {
					parent: parent,
					key: propName,
					how: "updateDeep",
					warn: "can-view-scope: Merging data into \"" +
						propName + "\" because its parent is non-observable"
				};
			}
			else if(canReflect_1_19_2_canReflect.isValueLike(parent[propName])){
				return { parent: parent, key: propName, how: "setValue" };
			} else {
				return { parent: parent, how: "write", key: propName, passOptions: true };
			}
		} else {
			return { parent: parent, how: "write", key: propName, passOptions: true };
		}
	},

	// ### scope.getHelper
	// read a helper from the templateContext or global helpers list
	getHelper: function(keyReads) {
		console.warn(".getHelper is deprecated, use .getHelperOrPartial");
		return this.getHelperOrPartial(keyReads);
	},
	getHelperOrPartial: function(keyReads) {
		// try every template context
		var scope = this, context, helper;
		while (scope) {
			context = scope._context;
			if (context instanceof canViewScope_4_13_7_templateContext) {
				helper = canStacheKey_1_4_3_canStacheKey.read(context.helpers, keyReads, { proxyMethods: false });
				if(helper.value !== undefined) {
					return helper.value;
				}
				helper = canStacheKey_1_4_3_canStacheKey.read(context.partials, keyReads, { proxyMethods: false });
				if(helper.value !== undefined) {
					return helper.value;
				}
			}
			scope = scope._parent;
		}

		return canStacheKey_1_4_3_canStacheKey.read(canStacheHelpers_1_2_0_canStacheHelpers, keyReads, { proxyMethods: false }).value;
	},

	// ### scope.get
	// Gets a value from the scope without being observable.
	get: function(key, options) {

		options = canAssign_1_3_3_canAssign({
			isArgument: true
		}, options);

		var res = this.read(key, options);
		return res.value;
	},
	peek: canObservationRecorder_1_3_1_canObservationRecorder.ignore(function(key, options) {
		return this.get(key, options);
	}),
	// TODO: Remove in 6.0
	peak: canObservationRecorder_1_3_1_canObservationRecorder.ignore(function(key, options) {
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			dev.warn('peak is deprecated, please use peek instead');
		}
		//!steal-remove-end
		return this.peek(key, options);
	}),
	// ### scope.getScope
	// Returns the first scope that passes the `tester` function.
	getScope: function(tester) {
		var scope = this;
		while (scope) {
			if (tester(scope)) {
				return scope;
			}
			scope = scope._parent;
		}
	},
	// ### scope.getContext
	// Returns the first context whose scope passes the `tester` function.
	getContext: function(tester) {
		var res = this.getScope(tester);
		return res && res._context;
	},
	// ### scope.getTemplateContext
	// Returns the template context scope
	// This function isn't named right.
	getTemplateContext: function() {
		var lastScope;

		// find the first reference scope
		var templateContext = this.getScope(function(scope) {
			lastScope = scope;
			return scope._context instanceof canViewScope_4_13_7_templateContext;
		});

		// if there is no reference scope, add one as the root
		if(!templateContext) {
			templateContext = new Scope(new canViewScope_4_13_7_templateContext());

			// add templateContext to root of the scope chain so it
			// can be found using `getScope` next time it is looked up
			lastScope._parent = templateContext;
		}
		return templateContext;
	},
	addTemplateContext: function(){
		return this.add(new canViewScope_4_13_7_templateContext());
	},
	addLetContext: function(values){
		return this.add(new canViewScope_4_13_7_letContext(values || {}), {variable: true});
	},
	// ### scope.getRoot
	// Returns the top most context that is not a references scope.
	// Used by `.read` to provide `%root`.
	getRoot: function() {
		var cur = this,
			child = this;

		while (cur._parent) {
			child = cur;
			cur = cur._parent;
		}

		if (cur._context instanceof canViewScope_4_13_7_templateContext) {
			cur = child;
		}
		return cur._context;
	},

	// first viewModel scope
	getViewModel: function() {
		var vmScope = this.getScope(function(scope) {
			return scope._meta.viewModel;
		});

		return vmScope && vmScope._context;
	},

	// _top_ viewModel scope
	getTop: function() {
		var top;

		this.getScope(function(scope) {
			if (scope._meta.viewModel) {
				top = scope;
			}

			// walk entire scope tree
			return false;
		});

		return top && top._context;
	},

	// ### scope.getPathsForKey
	// Finds all paths that will return a value for a specific key
	// NOTE: this is for development purposes only and is removed in production
	getPathsForKey: function getPathsForKey(key) {
		//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
			var paths = {};

			var getKeyDefinition = function(obj, key) {
				if (!obj || typeof obj !== "object") {
					return {};
				}

				var keyExistsOnObj = key in obj;
				var objHasKey = canReflect_1_19_2_canReflect.hasKey(obj, key);

				return {
					isDefined: keyExistsOnObj || objHasKey,
					isFunction: keyExistsOnObj && typeof obj[key] === "function"
				};
			};

			// scope.foo@bar -> bar
			var reads = canStacheKey_1_4_3_canStacheKey.reads(key);
			var keyParts = reads.map(function(read) {
				return read.key;
			});
			var scopeIndex = keyParts.indexOf("scope");

			if (scopeIndex > -1) {
				keyParts.splice(scopeIndex, 2);
			}
			var normalizedKey = keyParts.join(".");

			// check scope.vm.<key>
			var vm = this.getViewModel();
			var vmKeyDefinition = getKeyDefinition(vm, normalizedKey);

			if (vmKeyDefinition.isDefined) {
				paths["scope.vm." + normalizedKey + (vmKeyDefinition.isFunction ? "()" : "")] = vm;
			}

			// check scope.top.<key>
			var top = this.getTop();
			var topKeyDefinition = getKeyDefinition(top, normalizedKey);

			if (topKeyDefinition.isDefined) {
				paths["scope.top." + normalizedKey + (topKeyDefinition.isFunction ? "()" : "")] = top;
			}

			// find specific paths (like ../key)
			var cur = "";

			this.getScope(function(scope) {
				// `notContext` and `special` contexts can't be read using `../`
				var canBeRead = !scope.isSpecial();

				if (canBeRead) {
					var contextKeyDefinition = getKeyDefinition(scope._context, normalizedKey);
					if (contextKeyDefinition.isDefined) {
						paths[cur + normalizedKey + (contextKeyDefinition.isFunction ? "()" : "")] = scope._context;
					}

					cur += "../";
				}

				// walk entire scope tree
				return false;
			});

			return paths;
		}
		//!steal-remove-end
	},

	// ### scope.hasKey
	// returns whether or not this scope has the key
	hasKey: function hasKey(key) {
		var reads = canStacheKey_1_4_3_canStacheKey.reads(key);
		var readValue;

		if (reads[0].key === "scope") {
			// read properties like `scope.vm.foo` directly from the scope
			readValue = canStacheKey_1_4_3_canStacheKey.read(this, reads.slice(1), key);
		} else {
			// read normal properties from the scope's context
			readValue = canStacheKey_1_4_3_canStacheKey.read(this._context, reads, key);
		}

		return readValue.foundLastParent && readValue.parentHasKey;
	},

	set: function(key, value, options) {
		options = options || {};

		var data = this.getDataForScopeSet(key, options);
		var parent = data.parent;

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			if (data.error) {
				return dev.error(data.error);
			}
		}
		//!steal-remove-end

		if (data.warn) {
			dev.warn(data.warn);
		}

		switch (data.how) {
			case "set":
				parent.set(data.key, value, data.passOptions ? options : undefined);
				break;

			case "write":
				canStacheKey_1_4_3_canStacheKey.write(parent, data.key, value, options);
				break;

			case "setValue":
				canReflect_1_19_2_canReflect.setValue("key" in data ? parent[data.key] : parent, value);
				break;

			case "setKeyValue":
				canReflect_1_19_2_canReflect.setKeyValue(parent, data.key, value);
				break;

			case "updateDeep":
				canReflect_1_19_2_canReflect.updateDeep(parent[data.key], value);
				break;
		}
	},

	// ### scope.attr
	// Gets or sets a value in the scope without being observable.
	attr: canObservationRecorder_1_3_1_canObservationRecorder.ignore(function(key, value, options) {
		dev.warn("can-view-scope::attr is deprecated, please use peek, get or set");

		options = canAssign_1_3_3_canAssign({
			isArgument: true
		}, options);

		// Allow setting a value on the context
		if (arguments.length === 2) {
			return this.set(key, value, options);

		} else {
			return this.get(key, options);
		}
	}),

	// ### scope.computeData
	// Finds the first location of the key in the scope and then provides a get-set compute that represents the key's value
	// and other information about where the value was found.
	computeData: function(key, options) {
		return canViewScope_4_13_7_compute_data(this, key, options);
	},

	// ### scope.compute
	// Provides a get-set compute that represents a key's value.
	compute: function(key, options) {
		return this.computeData(key, options)
			.compute;
	},
	// ### scope.cloneFromRef
	//
	// This takes a scope and essentially copies its chain from
	// right before the last TemplateContext. And it does not include the ref.
	// this is a helper function to provide lexical semantics for refs.
	// This will not be needed for leakScope: false.
	cloneFromRef: function() {
		var scopes = [];
		var scope = this,
			context,
			parent;
		while (scope) {
			context = scope._context;
			if (context instanceof canViewScope_4_13_7_templateContext) {
				parent = scope._parent;
				break;
			}
			scopes.unshift(scope);
			scope = scope._parent;
		}
		if (parent) {
			scopes.forEach(function(scope) {
				// For performance, re-use _meta, don't copy it.
				parent = parent.add(scope._context, scope._meta);
			});
			return parent;
		} else {
			return this;
		}
	},
	isSpecial: function(){
		return this._meta.notContext || this._meta.special || (this._context instanceof canViewScope_4_13_7_templateContext) || this._meta.variable;
	}
});
// Legacy name for _walk.
Scope.prototype._read = Scope.prototype._walk;

canReflect_1_19_2_canReflect.assignSymbols(Scope.prototype, {
	"can.hasKey": Scope.prototype.hasKey,
	"can.isScopeLike": true
});

var templateContextPrimitives = [
	"filename", "lineNumber"
];

// create getters/setters for primitives on the templateContext
// scope.filename -> scope.readFromTemplateContext("filename")
templateContextPrimitives.forEach(function(key) {
	Object.defineProperty(Scope.prototype, key, {
		get: function() {
			return this.readFromTemplateContext(key).value;
		},
		set: function(val) {
			this.templateContext[key] = val;
		}
	});
});

canDefineLazyValue_1_1_1_defineLazyValue(Scope.prototype, 'templateContext', function() {
	return this.getTemplateContext()._context;
});

canDefineLazyValue_1_1_1_defineLazyValue(Scope.prototype, 'root', function() {
	dev.warn('`scope.root` is deprecated. Use either `scope.top`: https://canjs.com/doc/can-stache/keys/scope.html#scope_top or `scope.vm`: https://canjs.com/doc/can-stache/keys/scope.html#scope_vm instead.');
	return this.getRoot();
});

canDefineLazyValue_1_1_1_defineLazyValue(Scope.prototype, 'vm', function() {
	return this.getViewModel();
});

canDefineLazyValue_1_1_1_defineLazyValue(Scope.prototype, 'top', function() {
	return this.getTop();
});

canDefineLazyValue_1_1_1_defineLazyValue(Scope.prototype, 'helpers', function() {
	return canStacheHelpers_1_2_0_canStacheHelpers;
});

var specialKeywords = [
	'index', 'key', 'element',
	'event', 'viewModel','arguments',
	'helperOptions', 'args'
];

// create getters for "special" keys
// scope.index -> scope.readFromSpecialContext("index")
specialKeywords.forEach(function(key) {
	Object.defineProperty(Scope.prototype, key, {
		get: function() {
			return this.readFromSpecialContext(key).value;
		}
	});
});


//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	Scope.prototype.log = function() {
		var scope = this;
	    var indent = "";
		var contextType = "";
		while(scope) {
			contextType = scope._meta.notContext ? " (notContext)" :
				scope._meta.special ? " (special)" : "";
			console.log(indent, canReflect_1_19_2_canReflect.getName(scope._context) + contextType, scope._context);
	        scope = scope._parent;
	        indent += " ";
	    }
	};
}
//!steal-remove-end


canNamespace_1_0_0_canNamespace.view = canNamespace_1_0_0_canNamespace.view || {};
var canViewScope_4_13_7_canViewScope = canNamespace_1_0_0_canNamespace.view.Scope = Scope;

function KeyObservable(root, key){
    key = ""+key;
    this.key = key;
    this.root = root;
    settable.call(this, function(){
        return canStacheKey_1_4_3_canStacheKey.get(this,key);
    }, root);
}

KeyObservable.prototype = Object.create(settable.prototype);

KeyObservable.prototype.set = function(newVal) {
    canStacheKey_1_4_3_canStacheKey.set(this.root,this.key, newVal);
};


var keyObservable = KeyObservable;

var isViewSymbol = canSymbol_1_7_0_canSymbol.for("can.isView");

// this creates a noop that marks that a renderer was called
// this is for situations where a helper function calls a renderer
// that was not provided such as
// {{#if false}} ... {{/if}}
// with no {{else}}
var createNoOpRenderer = function (metadata) {
	return function noop() {
		if (metadata) {
			metadata.rendered = true;
		}
	};
};

var utils$1 = {
	last: function(arr){
		return arr !=null && arr[arr.length-1];
	},
	// A generic empty function
	emptyHandler: function(){},
	// Converts a string like "1" into 1. "null" into null, etc.
	// This doesn't have to do full JSON, so removing eval would be good.
	jsonParse: function(str){
		// if it starts with a quote, assume a string.
		if(str[0] === "'") {
			return str.substr(1, str.length -2);
		} else if(str === "undefined") {
			return undefined;
		} else {
			return JSON.parse(str);
		}
	},
	mixins: {
		last: function(){
			return this.stack[this.stack.length - 1];
		},
		add: function(chars){
			this.last().add(chars);
		},
		subSectionDepth: function(){
			return this.stack.length - 1;
		}
	},
	// Sets .fn and .inverse on a helperOptions object and makes sure
	// they can reference the current scope and options.
	createRenderers: function(helperOptions, scope, truthyRenderer, falseyRenderer, isStringOnly){
		helperOptions.fn = truthyRenderer ? this.makeRendererConvertScopes(truthyRenderer, scope, isStringOnly, helperOptions.metadata) : createNoOpRenderer(helperOptions.metadata);
		helperOptions.inverse = falseyRenderer ? this.makeRendererConvertScopes(falseyRenderer, scope, isStringOnly, helperOptions.metadata) : createNoOpRenderer(helperOptions.metadata);
		helperOptions.isSection = !!(truthyRenderer || falseyRenderer);
	},
	// Returns a new renderer function that makes sure any data or helpers passed
	// to it are converted to a can.view.Scope and a can.view.Options.
	makeRendererConvertScopes: function (renderer, parentScope, observeObservables, metadata) {
		var convertedRenderer = function (newScope, newOptions) {
			// prevent binding on fn.
			// If a non-scope value is passed, add that to the parent scope.
			if (newScope !== undefined && !(newScope instanceof canViewScope_4_13_7_canViewScope)) {
				if (parentScope) {
					newScope = parentScope.add(newScope);
				}
				else {
					newScope = new canViewScope_4_13_7_canViewScope(newScope || {});
				}
			}
			if (metadata) {
				metadata.rendered = true;
			}

			var result = renderer(newScope || parentScope );
			return result;
		};
		return observeObservables ? convertedRenderer :
			canObservationRecorder_1_3_1_canObservationRecorder.ignore(convertedRenderer);
	},
	makeView: function(renderer){
		var view = canObservationRecorder_1_3_1_canObservationRecorder.ignore(function(scope){
			if(!(scope instanceof canViewScope_4_13_7_canViewScope)) {
				scope = new canViewScope_4_13_7_canViewScope(scope);
			}
			return renderer(scope);
		});
		view[isViewSymbol] = true;
		return view;
	},
	// Calls the truthy subsection for each item in a list and returning them in a string.
	getItemsStringContent: function(items, isObserveList, helperOptions){
		var txt = "",
			len = canStacheKey_1_4_3_canStacheKey.get(items, 'length'),
			isObservable = canReflect_1_19_2_canReflect.isObservableLike(items);

		for (var i = 0; i < len; i++) {
			var item = isObservable ? new keyObservable(items, i) :items[i];
			txt += helperOptions.fn(item);
		}
		return txt;
	},
	// Calls the truthy subsection for each item in a list and returns them in a document Fragment.
	getItemsFragContent: function(items, helperOptions, scope) {
		var result = [],
			len = canStacheKey_1_4_3_canStacheKey.get(items, 'length'),
			isObservable = canReflect_1_19_2_canReflect.isObservableLike(items),
			hashExprs = helperOptions.exprData && helperOptions.exprData.hashExprs,
			hashOptions;

		// Check if using hash
		if (canReflect_1_19_2_canReflect.size(hashExprs) > 0) {
			hashOptions = {};
			canReflect_1_19_2_canReflect.eachKey(hashExprs, function (exprs, key) {
				hashOptions[exprs.key] = key;
			});
		}

		for (var i = 0; i < len; i++) {
			var aliases = {};

			var item = isObservable ? new keyObservable(items, i) :items[i];

			if (canReflect_1_19_2_canReflect.size(hashOptions) > 0) {
				if (hashOptions.value) {
					aliases[hashOptions.value] = item;
				}
				if (hashOptions.index) {
					aliases[hashOptions.index] = i;
				}
			}

			result.push(helperOptions.fn(
				scope
				.add(aliases, { notContext: true })
				.add({ index: i }, { special: true })
				.add(item))
			);
		}
		return result;
	}
};

var last = utils$1.last;

var decodeHTML = typeof document !== "undefined" && (function(){
	var el = document$1().createElement('div');
	return function(html){
		if(html.indexOf("&") === -1) {
			return html.replace(/\r\n/g,"\n");
		}
		el.innerHTML = html;
		return el.childNodes.length === 0 ? "" : el.childNodes.item(0).nodeValue;
	};
})();
// ## HTMLSectionBuilder
//
// Contains a stack of HTMLSections.
// An HTMLSection is created everytime a subsection is found. For example:
//
//     {{#if(items)}} {{#items}} X
//
// At the point X was being processed, there would be 2 HTMLSections in the
// stack.  One for the content of `{{#if(items)}}` and the other for the
// content of `{{#items}}`
var HTMLSectionBuilder = function(filename){
	if (filename) {
		this.filename = filename;
	}
	this.stack = [new HTMLSection()];
};


canAssign_1_3_3_canAssign(HTMLSectionBuilder.prototype,utils$1.mixins);

canAssign_1_3_3_canAssign(HTMLSectionBuilder.prototype,{
	startSubSection: function(process){
		var newSection = new HTMLSection(process);
		this.stack.push(newSection);
		return newSection;
	},
	// Ends the current section and returns a renderer.
	// But only returns a renderer if there is a template.
	endSubSectionAndReturnRenderer: function(){
		if(this.last().isEmpty()) {
			this.stack.pop();
			return null;
		} else {
			var htmlSection = this.endSection();
			return utils$1.makeView(htmlSection.compiled.hydrate.bind(htmlSection.compiled));
		}
	},
	startSection: function( process, commentName ) {
		var newSection = new HTMLSection(process);
		this.last().add({
			comment: commentName || "#section",
			callbacks: [newSection.targetCallback]
		});
		this.last().add({
			comment: "can-end-placeholder"
		});
		// adding a section within a section ...
		// the stack has section ...
		this.stack.push(newSection);
	},
	endSection: function(){
		this.last().compile();
		return this.stack.pop();
	},
	inverse: function(){
		this.last().inverse();
	},
	compile: function(){
		var compiled = this.stack.pop().compile();
		// ignore observations here.  the render fn
		//  itself doesn't need to be observable.
		return utils$1.makeView( compiled.hydrate.bind(compiled) );
	},
	push: function(chars){
		this.last().push(chars);
	},
	pop: function(){
		return this.last().pop();
	},
	removeCurrentNode: function() {
		this.last().removeCurrentNode();
	}
});

var HTMLSection = function(process){
	this.data = "targetData";
	this.targetData = [];
	// A record of what targetData element we are within.
	this.targetStack = [];
	var self = this;
	this.targetCallback = function(scope){
		process.call(this,
			scope,
			self.compiled.hydrate.bind(self.compiled),
			self.inverseCompiled && self.inverseCompiled.hydrate.bind(self.inverseCompiled)  ) ;
	};
};
canAssign_1_3_3_canAssign(HTMLSection.prototype,{
	inverse: function(){
		this.inverseData = [];
		this.data = "inverseData";
	},
	// Adds a DOM node.
	push: function(data){
		this.add(data);
		this.targetStack.push(data);
	},
	pop: function(){
		return this.targetStack.pop();
	},
	add: function(data){
		if(typeof data === "string"){
			data = decodeHTML(data);
		}
		if(this.targetStack.length) {
			last(this.targetStack).children.push(data);
		} else {
			this[this.data].push(data);
		}
	},
	compile: function(){
		this.compiled = canViewTarget_5_0_0_canViewTarget(this.targetData, document$1());
		if(this.inverseData) {
			this.inverseCompiled = canViewTarget_5_0_0_canViewTarget(this.inverseData, document$1());
			delete this.inverseData;
		}
		this.targetStack = this.targetData = null;
		return this.compiled;
	},
	removeCurrentNode: function() {
		var children = this.children();
		return children.pop();
	},
	children: function(){
		if(this.targetStack.length) {
			return last(this.targetStack).children;
		} else {
			return this[this.data];
		}
	},
	// Returns if a section is empty
	isEmpty: function(){
		return !this.targetData.length;
	}
});
HTMLSectionBuilder.HTMLSection = HTMLSection;

var html_section = HTMLSectionBuilder;

var canDomData_1_0_3_canDomData = createCommonjsModule(function (module) {


var isEmptyObject = function(obj){
	/* jshint -W098 */
	for(var prop in obj) {
		return false;
	}
	return true;
};

var data = new WeakMap();

// delete this node's `data`
// returns true if the node was deleted.
var deleteNode = function(node) {
	var nodeDeleted = false;
	if (data.has(node)) {
		nodeDeleted = true;
		data.delete(node);
	}
	return nodeDeleted;
};

var setData = function(node, name, value) {
	var store = data.get(node);
	if (store === undefined) {
		store = {};
		data.set(node, store);
	}
	if (name !== undefined) {
		store[name] = value;
	}
	return store;
};

/*
 * Core of domData that does not depend on mutationDocument
 * This is separated in order to prevent circular dependencies
 */
var domData = {
	_data: data,

	get: function(node, key) {
		var store = data.get(node);
		return key === undefined ? store : store && store[key];
	},

	set: setData,

	clean: function(node, prop) {
		var itemData = data.get(node);
		if (itemData && itemData[prop]) {
			delete itemData[prop];
		}
		if (isEmptyObject(itemData)) {
			deleteNode(node);
		}
	},

	delete: deleteNode
};

if (canNamespace_1_0_0_canNamespace.domData) {
	throw new Error("You can't have two versions of can-dom-data, check your dependencies");
} else {
	module.exports = canNamespace_1_0_0_canNamespace.domData = domData;
}
});

var slice$1 = [].slice;
// a b c
// a b c d
// [[2,0, d]]


function defaultIdentity(a, b){
    return a === b;
}

function makeIdentityFromMapSchema(typeSchema) {
    if(typeSchema.identity && typeSchema.identity.length) {
        return function identityCheck(a, b) {
            var aId = canReflect_1_19_2_canReflect.getIdentity(a, typeSchema),
                bId = canReflect_1_19_2_canReflect.getIdentity(b, typeSchema);
            return aId === bId;
        };
    } else {
        return defaultIdentity;
    }
}

function makeIdentityFromListSchema(listSchema) {
    return listSchema.values != null ?
        makeIdentityFromMapSchema( canReflect_1_19_2_canReflect.getSchema(listSchema.values) ) :
        defaultIdentity;
}

function makeIdentity(oldList, oldListLength) {
    var listSchema = canReflect_1_19_2_canReflect.getSchema(oldList),
        typeSchema;
    if(listSchema != null) {
        if(listSchema.values != null) {
            typeSchema = canReflect_1_19_2_canReflect.getSchema(listSchema.values);
        } else {
            return defaultIdentity;
        }
    }
    if(typeSchema == null && oldListLength > 0) {
        typeSchema = canReflect_1_19_2_canReflect.getSchema( canReflect_1_19_2_canReflect.getKeyValue(oldList, 0) );
    }
    if(typeSchema) {
        return makeIdentityFromMapSchema(typeSchema);
    } else {
        return defaultIdentity;
    }
}



function reverseDiff(oldDiffStopIndex, newDiffStopIndex, oldList, newList, identity) {
	var oldIndex = oldList.length - 1,
		newIndex =  newList.length - 1;

	while( oldIndex > oldDiffStopIndex && newIndex > newDiffStopIndex) {
		var oldItem = oldList[oldIndex],
			newItem = newList[newIndex];

		if( identity( oldItem, newItem, oldIndex ) ) {
			oldIndex--;
			newIndex--;
			continue;
		} else {
			// use newIndex because it reflects any deletions
			return [{
                type: "splice",
				index: newDiffStopIndex,
			 	deleteCount: (oldIndex-oldDiffStopIndex+1),
			 	insert: slice$1.call(newList, newDiffStopIndex,newIndex+1)
			}];
		}
	}
	// if we've reached of either the new or old list
	// we simply return
	return [{
        type: "splice",
		index: newDiffStopIndex,
		deleteCount: (oldIndex-oldDiffStopIndex+1),
		insert: slice$1.call(newList, newDiffStopIndex,newIndex+1)
	}];

}

/**
 * @module {function} can-diff/list/list
 * @parent can-diff
 *
 * @description Return a difference of two lists.
 *
 * @signature `diffList( oldList, newList, [identity] )`
 *
 * Compares two lists and produces a sequence of patches that can be applied to make `oldList` take
 * the shape of `newList`.
 *
 * ```js
 * var diffList = require("can-diff/list/list");
 *
 * console.log(diff([1], [1, 2])); // -> [{type: "splice", index: 1, deleteCount: 0, insert: [2]}]
 * console.log(diff([1, 2], [1])); // -> [{type: "splice", index: 1, deleteCount: 1, insert: []}]
 *
 * // with an optional identity function:
 * diffList(
 *     [{id:1},{id:2}],
 *     [{id:1},{id:3}],
 *     (a,b) => a.id === b.id
 * ); // -> [{type: "splice", index: 1, deleteCount: 1, insert: [{id:3}]}]
 * ```
 *
 * The patch algorithm is linear with respect to the length of the lists and therefore does not produce a
 * [perfect edit distance](https://en.wikipedia.org/wiki/Edit_distance) (which would be at least quadratic).
 *
 * It is designed to work with most common list change scenarios, when items are inserted or removed
 * to a list (as opposed to moved with in the last).
 *
 * For example, it is able to produce the following patches:
 *
 * ```js
 * diffList(
 *     ["a","b","c","d"],
 *     ["a","b","X","Y","c","d"]
 * ); // -> [{type: "splice", index: 2, deleteCount: 0, insert: ["X","Y"]}]
 * ```
 *
 * @param  {ArrayLike} oldList The source array or list to diff from.
 * @param  {ArrayLike} newList The array or list to diff to.
 * @param  {function|can-reflect.getSchema} schemaOrIdentity An optional identity function or a schema with
 * an identity property for comparing elements.  If a `schemaOrIdentity` is not provided, the schema of
 * the `oldList` will be used.  If a schema can not be found, items a default identity function will be created
 * that checks if the two values are strictly equal `===`.
 * @return {Array} An array of [can-symbol/types/Patch] objects representing the differences
 *
 * Returns the difference between two ArrayLike objects (that have nonnegative
 * integer keys and the `length` property) as an array of patch objects.
 *
 * A patch object returned by this function has the following properties:
 * - **type**: the type of patch (`"splice"`).
 * - **index**:  the index of newList where the patch begins
 * - **deleteCount**: the number of items deleted from that index in newList
 * - **insert**: an Array of items newly inserted at that index in newList
 *
 * Patches should be applied in the order they are returned.
 */

var list = function(oldList, newList, schemaOrIdentity){
    var oldIndex = 0,
		newIndex =  0,
		oldLength = canReflect_1_19_2_canReflect.size( oldList ),
		newLength = canReflect_1_19_2_canReflect.size( newList ),
		patches = [];

    var schemaType = typeof schemaOrIdentity,
        identity;
    if(schemaType === "function") {
        identity = schemaOrIdentity;
    } else if(schemaOrIdentity != null) {
        if(schemaOrIdentity.type === "map") {
            identity = makeIdentityFromMapSchema(schemaOrIdentity);
        } else {
            identity = makeIdentityFromListSchema(schemaOrIdentity);
        }
    } else {
        identity = makeIdentity(oldList, oldLength);
    }



	while(oldIndex < oldLength && newIndex < newLength) {
		var oldItem = oldList[oldIndex],
			newItem = newList[newIndex];

		if( identity( oldItem, newItem, oldIndex ) ) {
			oldIndex++;
			newIndex++;
			continue;
		}
		// look for single insert, does the next newList item equal the current oldList.
		// 1 2 3
		// 1 2 4 3
		if(  newIndex+1 < newLength && identity( oldItem, newList[newIndex+1], oldIndex ) ) {
			patches.push({index: newIndex, deleteCount: 0, insert: [ newList[newIndex] ], type: "splice"});
			oldIndex++;
			newIndex += 2;
			continue;
		}
		// look for single removal, does the next item in the oldList equal the current newList item.
		// 1 2 3
		// 1 3
		else if( oldIndex+1 < oldLength  && identity( oldList[oldIndex+1], newItem, oldIndex+1 ) ) {
			patches.push({index: newIndex, deleteCount: 1, insert: [], type: "splice"});
			oldIndex += 2;
			newIndex++;
			continue;
		}
		// just clean up the rest and exit
		// 1 2 3
		// 1 2 5 6 7
		else {
			// iterate backwards to `newIndex`
			// "a", "b", "c", "d", "e"
			// "a", "x", "y", "z", "e"
			// -> {}
			patches.push.apply(patches, reverseDiff(oldIndex, newIndex , oldList, newList, identity) );


			return patches;
		}
	}
	if( (newIndex === newLength) && (oldIndex === oldLength) ) {
		return patches;
	}
	// a b
	// a b c d e
	patches.push(
				{type: "splice", index: newIndex,
				 deleteCount: oldLength-oldIndex,
				 insert: slice$1.call(newList, newIndex) } );

	return patches;
};

var global$1 = global_1();









var xmlnsAttrNamespaceURI = "http://www.w3.org/2000/xmlns/";
var xlinkHrefAttrNamespaceURI =  "http://www.w3.org/1999/xlink";
var attrsNamespacesURI = {
	'xmlns': xmlnsAttrNamespaceURI,
	'xlink:href': xlinkHrefAttrNamespaceURI
};


var formElements = {"INPUT": true, "TEXTAREA": true, "SELECT": true, "BUTTON": true},
	// Used to convert values to strings.
	toString$1 = function(value){
		if(value == null) {
			return "";
		} else {
			return ""+value;
		}
	},
	isSVG = function(el){
		return el.namespaceURI === "http://www.w3.org/2000/svg";
	},
	truthy = function() { return true; },
	getSpecialTest = function(special){
		return (special && special.test) || truthy;
	},
	propProp = function(prop, obj){
		obj = obj || {};
		obj.get = function(){
			return this[prop];
		};
		obj.set = function(value){
			if(this[prop] !== value) {
				this[prop] = value;
			}
		};
		return obj;
	},
	booleanProp = function(prop){
		return {
			isBoolean: true,
			set: function(value){
				if(prop in this) {
					this[prop] = value;
				} else {
					canDomMutate_2_0_9_node.setAttribute.call(this, prop, "");
				}
			},
			remove: function(){
				this[prop] = false;
			}
		};
	},
	setupMO = function(el, callback){
		var attrMO = canDomData_1_0_3_canDomData.get(el, "attrMO");
		if(!attrMO) {
			var onMutation = function(){
				callback.call(el);
			};
			var MO = mutationObserver();
			if(MO) {
				var observer = new MO(onMutation);
				observer.observe(el, {
					childList: true,
					subtree: true
				});
				canDomData_1_0_3_canDomData.set(el, "attrMO", observer);
			} else {
				canDomData_1_0_3_canDomData.set(el, "attrMO", true);
				canDomData_1_0_3_canDomData.set(el, "canBindingCallback", {onMutation: onMutation});
			}
		}
	},
	_findOptionToSelect = function (parent, value) {
		var child = parent.firstChild;
		while (child) {
			if (child.nodeName === "OPTION" && value === child.value) {
				return child;
			}
			if (child.nodeName === "OPTGROUP") {
				var groupChild = _findOptionToSelect(child, value);
				if (groupChild) {
					return groupChild;
				}
			}
			child = child.nextSibling;
		}
	},
	setChildOptions = function(el, value){
		var option;
		if (value != null) {
			option = _findOptionToSelect(el, value);
		}
		if (option) {
			option.selected = true;
		} else {
			el.selectedIndex = -1;
		}
	},
	forEachOption = function (parent, fn) {
		var child = parent.firstChild;
		while (child) {
			if (child.nodeName === "OPTION") {
				fn(child);
			}
			if (child.nodeName === "OPTGROUP") {
				forEachOption(child, fn);
			}
			child = child.nextSibling;
		}
	},
	collectSelectedOptions = function (parent) {
		var selectedValues = [];
		forEachOption(parent, function (option) {
			if (option.selected) {
				selectedValues.push(option.value);
			}
		});
		return selectedValues;
	},
	markSelectedOptions = function (parent, values) {
		forEachOption(parent, function (option) {
			option.selected = values.indexOf(option.value) !== -1;
		});
	},
	// Create a handler, only once, that will set the child options any time
	// the select's value changes.
	setChildOptionsOnChange = function(select, aEL){
		var handler = canDomData_1_0_3_canDomData.get(select, "attrSetChildOptions");
		if(handler) {
			return Function.prototype;
		}
		handler = function(){
			setChildOptions(select, select.value);
		};
		canDomData_1_0_3_canDomData.set(select, "attrSetChildOptions", handler);
		aEL.call(select, "change", handler);
		return function(rEL){
			canDomData_1_0_3_canDomData.clean(select, "attrSetChildOptions");
			rEL.call(select, "change", handler);
		};
	},
	// cache of rules already calculated by `attr.getRule`
	behaviorRules = new Map(),
	// # isPropWritable
	// check if a property is writable on an element by finding its property descriptor
	// on the element or its prototype chain
	isPropWritable = function(el, prop) {
		   var desc = Object.getOwnPropertyDescriptor(el, prop);

		   if (desc) {
				   return desc.writable || desc.set;
		   } else {
				   var proto = Object.getPrototypeOf(el);
				   if (proto) {
						   return isPropWritable(proto, prop);
				   }
		   }

		   return false;
	},
	// # cacheRule
	// add a rule to the rules Map so it does not need to be calculated more than once
	cacheRule = function(el, attrOrPropName, rule) {
		   var rulesForElementType;

		   rulesForElementType = behaviorRules.get(el.prototype);

		   if (!rulesForElementType) {
				   rulesForElementType = {};
				   behaviorRules.set(el.constructor, rulesForElementType);
		   }

		   rulesForElementType[attrOrPropName] = rule;

		   return rule;
	};

var specialAttributes = {
	checked: {
		get: function(){
			return this.checked;
		},
		set: function(val){
			// - `set( truthy )` => TRUE
			// - `set( "" )`     => TRUE
			// - `set()`         => TRUE
			// - `set(undefined)` => false.
			var notFalse = !!val || val === "" || arguments.length === 0;
			this.checked = notFalse;
			if(notFalse && this.type === "radio") {
				this.defaultChecked = true;
			}
		},
		remove: function(){
			this.checked = false;
		},
		test: function(){
			return this.nodeName === "INPUT";
		}
	},
	"class": {
		get: function(){
			if(isSVG(this)) {
				return this.getAttribute("class");
			}
			return this.className;
		},
		set: function(val){
			val = val || "";

			if(isSVG(this)) {
				canDomMutate_2_0_9_node.setAttribute.call(this, "class", "" + val);
			} else {
				this.className = val;
			}
		}
	},
	disabled: booleanProp("disabled"),
	focused: {
		get: function(){
			return this === document.activeElement;
		},
		set: function(val){
			var cur = attr.get(this, "focused");
			var docEl = this.ownerDocument.documentElement;
			var element = this;
			function focusTask() {
				if (val) {
					element.focus();
				} else {
					element.blur();
				}
			}
			if (cur !== val) {
				if (!docEl.contains(element)) {
					var connectionDisposal = canDomMutate_2_0_9_canDomMutate.onNodeConnected(element, function () {
						connectionDisposal();
						focusTask();
					});
				} else {
					// THIS MIGHT NEED TO BE PUT IN THE MUTATE QUEUE
					canQueues_1_3_2_canQueues.enqueueByQueue({
						mutate: [focusTask]
					}, null, []);
				}
			}
			return true;
		},
		addEventListener: function(eventName, handler, aEL){
			aEL.call(this, "focus", handler);
			aEL.call(this, "blur", handler);
			return function(rEL){
				rEL.call(this, "focus", handler);
				rEL.call(this, "blur", handler);
			};
		},
		test: function(){
			return this.nodeName === "INPUT";
		}
	},
	"for": propProp("htmlFor"),
	innertext: propProp("innerText"),
	innerhtml: propProp("innerHTML"),
	innerHTML: propProp("innerHTML", {
		addEventListener: function(eventName, handler, aEL){
			var handlers = [];
			var el = this;
			["change", "blur"].forEach(function(eventName){
				var localHandler = function(){
					handler.apply(this, arguments);
				};
				canDomEvents_1_3_13_canDomEvents.addEventListener(el, eventName, localHandler);
				handlers.push([eventName, localHandler]);
			});

			return function(rEL){
				handlers.forEach( function(info){
					rEL.call(el, info[0], info[1]);
				});
			};
		}
	}),
	required: booleanProp("required"),
	readonly: booleanProp("readOnly"),
	selected: {
		get: function(){
			return this.selected;
		},
		set: function(val){
			val = !!val;
			canDomData_1_0_3_canDomData.set(this, "lastSetValue", val);
			this.selected = val;
		},
		addEventListener: function(eventName, handler, aEL){
			var option = this;
			var select = this.parentNode;
			var lastVal = option.selected;
			var localHandler = function(changeEvent){
				var curVal = option.selected;
				lastVal = canDomData_1_0_3_canDomData.get(option, "lastSetValue") || lastVal;
				if(curVal !== lastVal) {
					lastVal = curVal;

					canDomEvents_1_3_13_canDomEvents.dispatch(option, eventName);
				}
			};

			var removeChangeHandler = setChildOptionsOnChange(select, aEL);
			canDomEvents_1_3_13_canDomEvents.addEventListener(select, "change", localHandler);
			aEL.call(option, eventName, handler);

			return function(rEL){
				removeChangeHandler(rEL);
				canDomEvents_1_3_13_canDomEvents.removeEventListener(select, "change", localHandler);
				rEL.call(option, eventName, handler);
			};
		},
		test: function(){
			return this.nodeName === "OPTION" && this.parentNode &&
				this.parentNode.nodeName === "SELECT";
		}
	},
	style: {
		set: (function () {
			var el = global$1.document && document$1().createElement("div");
			if ( el && el.style && ("cssText" in el.style) ) {
				return function (val) {
					this.style.cssText = (val || "");
				};
			} else {
				return function (val) {
					canDomMutate_2_0_9_node.setAttribute.call(this, "style", val);
				};
			}
		})()
	},
	textcontent: propProp("textContent"),
	value: {
		get: function(){
			var value = this.value;
			if(this.nodeName === "SELECT") {
				if(("selectedIndex" in this) && this.selectedIndex === -1) {
					value = undefined;
				}
			}
			return value;
		},
		set: function(value){
			var providedValue = value;
			var nodeName = this.nodeName.toLowerCase();
			if(nodeName === "input" || nodeName === "textarea") {
				// Do some input types support non string values?
				value = toString$1(value);
			}
			if(this.value !== value || nodeName === "option") {
				this.value = value;
			}
			if (nodeName === "input" || nodeName === "textarea") {
				this.defaultValue = value;
			}
			if(nodeName === "select") {
				canDomData_1_0_3_canDomData.set(this, "attrValueLastVal", value);
				//If it's null then special case
				setChildOptions(this, value === null ? value : this.value);

				// If not in the document reset the value when inserted.
				var docEl = this.ownerDocument.documentElement;
				if(!docEl.contains(this)) {
					var select = this;
					var connectionDisposal = canDomMutate_2_0_9_canDomMutate.onNodeConnected(select, function () {
						connectionDisposal();
						setChildOptions(select, value === null ? value : select.value);
					});
				}

				// MO handler is only set up **ONCE**
				setupMO(this, function(){
					var value = canDomData_1_0_3_canDomData.get(this, "attrValueLastVal");
					attr.set(this, "value", value);
					canDomEvents_1_3_13_canDomEvents.dispatch(this, "change");
				});
			}

			// Warnings area
			//!steal-remove-start
			if(process.env.NODE_ENV !== "production") {
				var settingADateInputToADate = nodeName === "input" && this.type === "date" && (providedValue instanceof Date);
				if(settingADateInputToADate) {
					dev.warn("Binding a Date to the \"value\" property on an <input type=\"date\"> will not work as expected. Use valueAsDate:bind instead. See https://canjs.com/doc/guides/forms.html#Dateinput for more information.");
				}
			}
			//!steal-remove-end
		},
		test: function(){
			return formElements[this.nodeName];
		}
	},
	values: {
		get: function(){
			return collectSelectedOptions(this);
		},
		set: function(values){
			values = values || [];

			// set new DOM state
			markSelectedOptions(this, values);

			// store new DOM state
			canDomData_1_0_3_canDomData.set(this, "stickyValues", attr.get(this,"values") );

			// MO handler is only set up **ONCE**
			// TODO: should this be moved into addEventListener?
			setupMO(this, function(){

				// Get the previous sticky state
				var previousValues = canDomData_1_0_3_canDomData.get(this,
					"stickyValues");

				// Set DOM to previous sticky state
				attr.set(this, "values", previousValues);

				// Get the new result after trying to maintain the sticky state
				var currentValues = canDomData_1_0_3_canDomData.get(this,
					"stickyValues");

				// If there are changes, trigger a `values` event.
				var changes = list(previousValues.slice().sort(),
					currentValues.slice().sort());

				if (changes.length) {
					canDomEvents_1_3_13_canDomEvents.dispatch(this, "values");
				}
			});
		},
		addEventListener: function(eventName, handler, aEL){
			var localHandler = function(){
				canDomEvents_1_3_13_canDomEvents.dispatch(this, "values");
			};

			canDomEvents_1_3_13_canDomEvents.addEventListener(this, "change", localHandler);
			aEL.call(this, eventName, handler);

			return function(rEL){
				canDomEvents_1_3_13_canDomEvents.removeEventListener(this, "change", localHandler);
				rEL.call(this, eventName, handler);
			};
		}
	}
};

var attr = {
	// cached rules (stored on `attr` for testing purposes)
	rules: behaviorRules,

	// special attribute behaviors (stored on `attr` for testing purposes)
	specialAttributes: specialAttributes,

	// # attr.getRule
	//
	// get the behavior rule for an attribute or property on an element
	//
	// Rule precendence:
	//   1. "special" behaviors - use the special behavior getter/setter
	//   2. writable properties - read and write as a property
	//   3. all others - read and write as an attribute
	//
	// Once rule is determined it will be cached for all elements of the same type
	// so that it does not need to be calculated again
	getRule: function(el, attrOrPropName) {
		var special = specialAttributes[attrOrPropName];
		// always use "special" if available
		// these are not cached since they would have to be cached separately
		// for each element type and it is faster to just look up in the
		// specialAttributes object
		if (special) {
			return special;
		}

		// next use rules cached in a previous call to getRule
		var rulesForElementType = behaviorRules.get(el.constructor);
		var cached = rulesForElementType && rulesForElementType[attrOrPropName];

		if (cached) {
			return cached;
		}

		// if the element doesn't have a property of this name, it must be an attribute
		if (!(attrOrPropName in el)) {
			return this.attribute(attrOrPropName);
		}

		// if there is a property, check if it is writable
		var newRule = isPropWritable(el, attrOrPropName) ?
			this.property(attrOrPropName) :
			this.attribute(attrOrPropName);

		// cache the new rule and return it
		return cacheRule(el, attrOrPropName, newRule);
	},

	attribute: function(attrName) {
		return {
			get: function() {
				return this.getAttribute(attrName);
			},
			set: function(val) {
				if (attrsNamespacesURI[attrName]) {
					canDomMutate_2_0_9_node.setAttributeNS.call(this, attrsNamespacesURI[attrName], attrName, val);
				} else {
					canDomMutate_2_0_9_node.setAttribute.call(this, attrName, val);
				}
			}
		};
	},

	property: function(propName) {
		return {
			get: function() {
				return this[propName];
			},
			set: function(val) {
				this[propName] = val;
			}
		};
	},

	findSpecialListener: function(attributeName) {
		return specialAttributes[attributeName] && specialAttributes[attributeName].addEventListener;
	},

	setAttrOrProp: function(el, attrName, val){
		return this.set(el, attrName, val);
	},
	// ## attr.set
	// Set the value an attribute on an element.
	set: function (el, attrName, val) {
		var rule = this.getRule(el, attrName);
		var setter = rule && rule.set;

		if (setter) {
			return setter.call(el, val);
		}
	},
	// ## attr.get
	// Gets the value of an attribute or property.
	// First checks if the property is an `specialAttributes` and if so calls the special getter.
	// Then checks if the attribute or property is a property on the element.
	// Otherwise uses `getAttribute` to retrieve the value.
	get: function (el, attrName) {
		var rule = this.getRule(el, attrName);
		var getter = rule && rule.get;

		if (getter) {
			return rule.test ?
				rule.test.call(el) && getter.call(el) :
				getter.call(el);
		}
	},
	// ## attr.remove
	// Removes an attribute from an element. First checks specialAttributes to see if the attribute is special and has a setter. If so calls the setter with `undefined`. Otherwise `removeAttribute` is used.
	// If the attribute previously had a value and the browser doesn't support MutationObservers we then trigger an "attributes" event.
	remove: function (el, attrName) {
		attrName = attrName.toLowerCase();
		var special = specialAttributes[attrName];
		var setter = special && special.set;
		var remover = special && special.remove;
		var test = getSpecialTest(special);

		if(typeof remover === "function" && test.call(el)) {
			remover.call(el);
		} else if(typeof setter === "function" && test.call(el)) {
			setter.call(el, undefined);
		} else {
			canDomMutate_2_0_9_node.removeAttribute.call(el, attrName);
		}
	}
};

var canAttributeObservable_2_0_2_behaviors = attr;

var setElementSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.setElement");
var elementSymbol = canSymbol_1_7_0_canSymbol.for("can.element");

function ListenUntilRemovedAndInitialize(
	observable,
	handler,
	placeholder,
	queueName,
	handlerName
) {
	this.observable = observable;
	this.handler = handler;
	this.placeholder = placeholder;
	this.queueName = queueName;
	this.handler[elementSymbol] = placeholder;

	if( observable[setElementSymbol$2] ) {
		observable[setElementSymbol$2](placeholder);
	} else {
		console.warn("no can.setElement symbol on observable", observable);
	}

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		// register that the handler changes the parent element
		canReflect_1_19_2_canReflect.assignSymbols(handler, {
			"can.getChangesDependencyRecord": function() {
				var s = new Set();
				s.add(placeholder);
				return {
					valueDependencies: s
				};
			}
		});

		Object.defineProperty(handler, "name", {
			value: handlerName,
		});

	}
	//!steal-remove-end

	this.setup();
}
ListenUntilRemovedAndInitialize.prototype.setup = function() {
	// reinsertion case, not applicable during initial setup
	if(this.setupNodeReinserted) {
		// do not set up again if disconnected
		if(!canDomMutate_2_0_9_IsConnected.isConnected(this.placeholder)) {
			return;
		}
		this.setupNodeReinserted();
	}
	this.teardownNodeRemoved = canDomMutate_2_0_9_canDomMutate.onNodeRemoved(this.placeholder,
		this.teardown.bind(this));


	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		canReflectDependencies_1_1_2_canReflectDependencies.addMutatedBy(this.placeholder, this.observable);
	}
	//!steal-remove-end

	canReflect_1_19_2_canReflect.onValue(this.observable, this.handler, this.queueName);
	this.handler(  canReflect_1_19_2_canReflect.getValue(this.observable) );

};
ListenUntilRemovedAndInitialize.prototype.teardown = function(){
	// do not teardown if still connected.
	if(canDomMutate_2_0_9_IsConnected.isConnected(this.placeholder)) {
		return;
	}
	this.teardownNodeRemoved();
	this.setupNodeReinserted = canDomMutate_2_0_9_canDomMutate.onNodeInserted(this.placeholder,
		this.setup.bind(this));

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		canReflectDependencies_1_1_2_canReflectDependencies.deleteMutatedBy(this.placeholder, this.observable);
	}
	//!steal-remove-end
	canReflect_1_19_2_canReflect.offValue(this.observable, this.handler, this.queueName);
};


var helpers$2 = {
	range: {
		create: function(el, rangeName){
			var start, end, next;

			if(el.nodeType === Node.COMMENT_NODE) {
				start = el;
				next = el.nextSibling;
				if(next && next.nodeType === Node.COMMENT_NODE && next.nodeValue === "can-end-placeholder") {
					end = next;
					end.nodeValue = "/" + (start.nodeValue = rangeName);
				} else {
					dev.warn("can-view-live: creating an end comment for ", rangeName, el);
				}
			} else {
				dev.warn("can-view-live: forcing a comment range for ", rangeName, el);
				start = el.ownerDocument.createComment( rangeName );
				el.parentNode.replaceChild( start, el );
			}

			if(!end) {
				end = el.ownerDocument.createComment( "/" + rangeName );
				start.parentNode.insertBefore(end, start.nextSibling);
			}

			return {start: start, end: end};
		},
		remove: function ( range ) {
			// TODO: Ideally this would be able to remove from the end, but
			// dispatch in the right order.
			// For now, we might want to remove nodes in the right order.
			var parentNode = range.start.parentNode,
				cur = range.end.previousSibling,
				remove;
			while(cur && cur !== range.start) {
				remove = cur;
				cur = cur.previousSibling;
				canDomMutate_2_0_9_node.removeChild.call(parentNode, remove );
			}

			canDomMutate_2_0_9_canDomMutate.flushRecords();
		},

		update: function ( range, frag ) {
			var parentNode = range.start.parentNode;
			if(parentNode) {
				canDomMutate_2_0_9_node.insertBefore.call(parentNode, frag, range.end);
				// this makes it so `connected` events will be called immediately
				canDomMutate_2_0_9_canDomMutate.flushRecords();
			}
		}
	},
	ListenUntilRemovedAndInitialize: ListenUntilRemovedAndInitialize,
	getAttributeParts: function(newVal) {
		var attrs = {},
			attr;
		canViewParser_4_1_3_canViewParser.parseAttrs(newVal, {
			attrStart: function(name) {
				attrs[name] = "";
				attr = name;
			},
			attrValue: function(value) {
				attrs[attr] += value;
			},
			attrEnd: function() {}
		});
		return attrs;
	},
	// #### addTextNodeIfNoChildren
	// Append an empty text node to a parent with no children;
	//  do nothing if the parent already has children.
	addTextNodeIfNoChildren: function(frag) {
		if (!frag.firstChild) {
			frag.appendChild(frag.ownerDocument.createTextNode(""));
		}
	},
	// #### makeString
	// any -> string converter (including nullish)
	makeString: function(txt) {
		return txt == null ? "" : "" + txt;
	}
};

/**
 * @function can-view-live.attr attr
 * @parent can-view-live
 *
 * @signature `live.attr(el, attributeName, observable)`
 *
 * Keep an attribute live to a [can-reflect]-ed observable.
 *
 * ```js
 * var div = document.createElement('div');
 * var value = new SimpleObservable("foo bar");
 * live.attr(div,"class", value);
 * ```
 *
 * @param {HTMLElement} el The element whos attribute will be kept live.
 * @param {String} attributeName The attribute name.
 * @param {Object} observable An observable value.
 *
 * @body
 *
 * ## How it works
 *
 * This listens for the changes in the observable and uses those changes to
 * set the specified attribute.
 */
var attr_1 = function(el, attributeName, compute) {
	var handlerName = "";
	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		// register that the handler changes the parent element
		handlerName = "live.attr update::"+canReflect_1_19_2_canReflect.getName(compute);
	}
	//!steal-remove-end

	new helpers$2.ListenUntilRemovedAndInitialize(compute,
			function liveUpdateAttr(newVal) {
				canAttributeObservable_2_0_2_behaviors.set(el,attributeName, newVal);
			},
			el,
			"dom",
			handlerName
		);
};

// This provides live binding for stache attributes.






var attrs = function(el, compute, scope, options) {
	var handlerName = "";
	if (!canReflect_1_19_2_canReflect.isObservableLike(compute)) {
		// Non-live case (`compute` was not a compute):
		//  set all attributes on the element and don't
		//  worry about setting up live binding since there
		//  is not compute to bind on.
		var attrs = helpers$2.getAttributeParts(compute);
		for (var name in attrs) {
			canDomMutate_2_0_9_node.setAttribute.call(el, name, attrs[name]);
		}
		return;
	}

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		handlerName = "live.attrs update::"+canReflect_1_19_2_canReflect.getName(compute);
	}
	//!steal-remove-end


	// last set of attributes
	var oldAttrs = {};


	new helpers$2.ListenUntilRemovedAndInitialize(compute,
		function canViewLive_updateAttributes(newVal) {
			var newAttrs = helpers$2.getAttributeParts(newVal),
				name;
			for (name in newAttrs) {
				var newValue = newAttrs[name],
					// `oldAttrs` was set on the last run of setAttrs in this context
					//  (for this element and compute)
					oldValue = oldAttrs[name];
				// Only fire a callback
				//  if the value of the attribute has changed
				if (newValue !== oldValue) {
					// set on DOM attributes (dispatches an "attributes" event as well)
					canDomMutate_2_0_9_node.setAttribute.call(el, name, newValue);
					// get registered callback for attribute name and fire
					var callback = canViewCallbacks_5_0_0_canViewCallbacks.attr(name);
					if (callback) {
						callback(el, {
							attributeName: name,
							scope: scope,
							options: options
						});
					}
				}
				// remove key found in new attrs from old attrs
				delete oldAttrs[name];
			}
			// any attrs left at this point are not set on the element now,
			// so remove them.
			for (name in oldAttrs) {
				canDomMutate_2_0_9_node.removeAttribute.call(el, name);
			}
			oldAttrs = newAttrs;
		},
		el,
		"dom",
		handlerName);

};

var viewInsertSymbol = canSymbol_1_7_0_canSymbol.for("can.viewInsert");

function makeCommentFragment(comment) {
		var doc = document$1();
		return canFragment_1_3_1_canFragment([
			doc.createComment(comment),
			doc.createComment("can-end-placeholder")
		]);
}

/**
 * @function can-view-live.html html
 * @parent can-view-live
 * @release 2.0.4
 *
 * Live binds a compute's value to a collection of elements.
 *
 * @signature `live.html(el, compute, [parentNode])`
 *
 * `live.html` is used to setup incremental live-binding on a block of html.
 *
 * ```js
 * // a compute that changes its list
 * var greeting = compute(function(){
 *   return "Welcome <i>"+me.attr("name")+"</i>"
 * });
 *
 * var placeholder = document.createTextNode(" ");
 * $("#greeting").append(placeholder);
 *
 * live.html(placeholder, greeting);
 * ```
 *
 * @param {HTMLElement} el An html element to replace with the live-section.
 *
 * @param {can.compute} compute A [can.compute] whose value is HTML.
 *
 * @param {HTMLElement} [parentNode] An overwritable parentNode if `el`'s parent is
 * a documentFragment.
 *
 *
 */
var html = function(el, compute, viewInsertSymbolOptions) {

	var observableName = "";
	var updateRange = helpers$2.range.update;

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		// register that the handler changes the parent element
		updateRange = helpers$2.range.update.bind(null);
		observableName = canReflect_1_19_2_canReflect.getName(compute);
		Object.defineProperty(updateRange, "name", {
			value: "live.html update::"+observableName,
		});
	}
	//!steal-remove-end

	if (el.nodeType !== Node.COMMENT_NODE) {
		var commentFrag = makeCommentFragment(observableName);
		var startCommentNode = commentFrag.firstChild;
		el.parentNode.replaceChild(commentFrag, el);
		el = startCommentNode;
	}

	// replace element with a comment node
	var range = helpers$2.range.create(el, observableName);

	var useQueue = false;
	new helpers$2.ListenUntilRemovedAndInitialize(compute,
		function canViewLive_updateHTML(val) {

			// If val has the can.viewInsert symbol, call it and get something usable for val back
			if (val && typeof val[viewInsertSymbol] === "function") {
				val = val[viewInsertSymbol](viewInsertSymbolOptions);
			}

			var isFunction = typeof val === "function";

			// translate val into a document fragment if it's DOM-like
			var frag = isFunction ?
				makeCommentFragment(observableName) :
				canFragment_1_3_1_canFragment(val);

			if(isFunction) {
				val(frag.firstChild);
			}

			if(useQueue === true) {
				helpers$2.range.remove(range);
				updateRange(range, frag);
			} else {
				helpers$2.range.update(range, frag);
				useQueue = true;
			}
		},
		range.start,
		"dom",
		"live.html replace::" + observableName);

};

var onValueSymbol$3 = canSymbol_1_7_0_canSymbol.for("can.onValue");
var offValueSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.offValue");
var onPatchesSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.onPatches");
var offPatchesSymbol = canSymbol_1_7_0_canSymbol.for("can.offPatches");

// Patcher takes a observable that might wrap a list type.
// When the observable changes, it will diff, and emit patches,
// and if the list emits patches, it will emit those too.
// It is expected that only `domUI` handlers are registered.
/*
var observable = new SimpleObservable( new DefineList([ "a", "b", "c" ]) )
var patcher = new Patcher(observable)
canReflect.onPatches( patcher,function(patches){
  console.log(patches) // a patch removing c, then a
})
var newList = new DefineList(["a","b"]);
observable.set(newList);
newList.unshift("X");
[
    {type: "splice", index: 2, deleteCount: 1}
]
var patches2 = [
    {type: "splice", index: 0, deleteCount: 0, inserted: ["X"]}
]
 */
var Patcher = function(observableOrList, priority) {
	// stores listeners for this patcher
	this.handlers = new canKeyTree_1_2_2_canKeyTree([Object, Array], {
		// call setup when the first handler is bound
		onFirst: this.setup.bind(this),
		// call teardown when the last handler is removed
		onEmpty: this.teardown.bind(this)
	});

	// save this value observable or patch emitter (list)
	this.observableOrList = observableOrList;
	// if we were passed an observable value that we need to read its array for changes
	this.isObservableValue = canReflect_1_19_2_canReflect.isValueLike(this.observableOrList) || canReflect_1_19_2_canReflect.isObservableLike(this.observableOrList);
	if(this.isObservableValue) {
	    this.priority = canReflect_1_19_2_canReflect.getPriority(observableOrList);
	} else {
	    this.priority = priority || 0;
	}
	this.onList = this.onList.bind(this);
	this.onPatchesNotify = this.onPatchesNotify.bind(this);
	// needs to be unique so the derive queue doesn't only add one.
	this.onPatchesDerive = this.onPatchesDerive.bind(this);

	// stores patches that have happened between notification and
	// when we queue the  `onPatches` handlers in the `domUI` queue
	this.patches = [];


	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		Object.defineProperty(this.onList, "name", {
			value: "live.list new list::"+canReflect_1_19_2_canReflect.getName(observableOrList),
		});
		Object.defineProperty(this.onPatchesNotify, "name", {
			value: "live.list notify::"+canReflect_1_19_2_canReflect.getName(observableOrList),
		});
		Object.defineProperty(this.onPatchesDerive, "name", {
			value: "live.list derive::"+canReflect_1_19_2_canReflect.getName(observableOrList),
		});
	}
	//!steal-remove-end
};


Patcher.prototype = {
	constructor: Patcher,
	setup: function() {
		if (this.observableOrList[onValueSymbol$3]) {
			// if we have an observable value, listen to when it changes to get a
			// new list.
			canReflect_1_19_2_canReflect.onValue(this.observableOrList, this.onList, "notify");
			// listen on the current value (which shoudl be a list) if there is one
			this.setupList(canReflect_1_19_2_canReflect.getValue(this.observableOrList));
		} else {
			this.setupList(this.observableOrList);
		}
	},
	teardown: function() {
		if (this.observableOrList[offValueSymbol$1]) {
			canReflect_1_19_2_canReflect.offValue(this.observableOrList, this.onList, "notify");
		}
		if (this.currentList && this.currentList[offPatchesSymbol]) {
			this.currentList[offPatchesSymbol](this.onPatchesNotify, "notify");
		}
	},
	// listen to the list for patches
	setupList: function(list$$1) {
		this.currentList = list$$1;
		if (list$$1 && list$$1[onPatchesSymbol$1]) {
			// If observable, set up bindings on list changes
			list$$1[onPatchesSymbol$1](this.onPatchesNotify, "notify");
		}
	},
	// when the list changes, teardown the old list bindings
	// and setup the new list
	onList: function onList(newList) {
		var current = this.currentList || [];
		newList = newList || [];
		if (current[offPatchesSymbol]) {
			current[offPatchesSymbol](this.onPatchesNotify, "notify");
		}
		var patches = list(current, newList);
		this.currentList = newList;
		this.onPatchesNotify(patches);
		if (newList[onPatchesSymbol$1]) {
			// If observable, set up bindings on list changes
			newList[onPatchesSymbol$1](this.onPatchesNotify, "notify");
		}
	},
	// This is when we get notified of patches on the underlying list.
	// Save the patches and queue up a `derive` task that will
	// call `domUI` updates.
	onPatchesNotify: function onPatchesNotify(patches) {
		// we are going to collect all patches
		this.patches.push.apply(this.patches, patches);
		// TODO: share priority
		canQueues_1_3_2_canQueues.deriveQueue.enqueue(this.onPatchesDerive, this, [], {
			priority: this.priority
		});
	},
	// Let handlers (which should only be registered in `domUI`) know about patches
	// that they can apply.
	onPatchesDerive: function onPatchesDerive() {
		var patches = this.patches;
		this.patches = [];
		canQueues_1_3_2_canQueues.enqueueByQueue(this.handlers.getNode([]), this.currentList, [patches, this.currentList], null,["Apply patches", patches]);
	}
};

canReflect_1_19_2_canReflect.assignSymbols(Patcher.prototype, {
	"can.onPatches": function(handler, queue) {
		this.handlers.add([queue || "mutate", handler]);
	},
	"can.offPatches": function(handler, queue) {
		this.handlers.delete([queue || "mutate", handler]);
	}
});

var patcher = Patcher;

var patchSort = function(patches) {
	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		var deletes =[],
			inserts = [],
			moves = [];
		patches.forEach(function(patch){
			if (patch.type === "move") {
				moves.push(patch);
			} else {
				if (patch.deleteCount) {
					deletes.push(patch);
				}
				if (patch.insert && patch.insert.length) {
					inserts.push(inserts);
				}
			}
		});
		if(deletes.length + inserts.length > 2) {
			console.error("unable to group patches",patches);
			throw new Error("unable to group patches");
		}
		if(moves.length &&(deletes.length || inserts.length)) {
			console.error("unable to sort a move with a delete or insert");
			throw new Error("unable to sort a move with a delete or insert");
		}
	}
	//!steal-remove-end


	var splitPatches = [];
	patches.forEach(function(patch){
		if (patch.type === "move") {
			splitPatches.push( {patch: patch, kind: "move"} );
		} else {
			if (patch.deleteCount) {
				splitPatches.push({
					type: "splice",
					index: patch.index,
					deleteCount: patch.deleteCount,
					insert: [],
				});
			}
			if (patch.insert && patch.insert.length) {
				splitPatches.push({
					type: "splice",
					index: patch.index,
					deleteCount: 0,
					insert: patch.insert
				});
			}
		}
	});
	if(patches.length !== 2) {
		return patches;
	}
	var first = splitPatches[0],
		second = splitPatches[1];
	// if insert before a delete
	if(first.insert && first.insert.length && second.deleteCount) {
		// lets swap the order.
		var insert = first,
			remove = second;
		if(insert.index < remove.index) {
			remove.index = remove.index - insert.insert.length;
		} else if(insert.index > remove.index) {
			insert.index = insert.index - remove.deleteCount;
		} else {
			throw "indexes the same!"
		}
		return [remove, insert];
	}
	return patches;
};

function SetObservable(initialValue, setter) {
	this.setter = setter;

	canSimpleObservable_2_5_0_canSimpleObservable.call(this, initialValue);
}

SetObservable.prototype = Object.create(canSimpleObservable_2_5_0_canSimpleObservable.prototype);
SetObservable.prototype.constructor = SetObservable;
SetObservable.prototype.set = function(newVal) {
	this.setter(newVal);
};


canReflect_1_19_2_canReflect.assignSymbols(SetObservable.prototype, {
	"can.setValue": SetObservable.prototype.set
});

var setObservable = SetObservable;

var splice = [].splice;

// #### renderAndAddRangeNode
// a helper function that renders something and adds its nodeLists to newNodeLists
// in the right way for stache.
var renderAndAddRangeNode = function(render, context, args, document) {
		// call the renderer, passing in the new nodeList as the last argument
		var itemHTML = render.apply(context, args.concat()),
			// and put the output into a document fragment
			itemFrag = canFragment_1_3_1_canFragment(itemHTML);

		var rangeNode = document.createTextNode("");
		itemFrag.appendChild(rangeNode);
		return itemFrag;
	};


function getFrag(first, last){
	var frag = first.ownerDocument.createDocumentFragment();
	var current,
		lastInserted;
	// hopefully this doesn't dispatch removed?
	while(last !== first) {
		current = last;
		last = current.previousSibling;
		frag.insertBefore(current, lastInserted);
		lastInserted = current;
	}
	frag.insertBefore(last, lastInserted);
	return frag;
}

var onPatchesSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.onPatches");
var offPatchesSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.offPatches");

function ListDOMPatcher(el, compute, render, context, falseyRender) {
	this.patcher = new patcher(compute);
	var observableName = canReflect_1_19_2_canReflect.getName(compute);

	// argument cleanup

	// function callback binding

	// argument saving -----
	this.value = compute;
	this.render = render;
	this.context = context;
	this.falseyRender = falseyRender;
	this.range = helpers$2.range.create(el, observableName);

	// A mapping of indices to observables holding that index.
	this.indexMap = [];
	// A mapping of each item's end node
	this.itemEndNode = [];

	// A mapping of each item to its pending patches.
	this.domQueue = [];

	this.isValueLike = canReflect_1_19_2_canReflect.isValueLike(this.value);
	this.isObservableLike = canReflect_1_19_2_canReflect.isObservableLike(this.value);

	// Setup binding and teardown to add and remove events
	this.onPatches = this.onPatches.bind(this);
	this.processDomQueue = this.processDomQueue.bind(this);
	this.teardownValueBinding = this.teardownValueBinding.bind(this);

	this.meta = {reasonLog: "live.html add::"+observableName, element: this.range.start};

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		Object.defineProperty(this.onPatches, "name", {
			value: "live.list update::"+canReflect_1_19_2_canReflect.getName(compute),
		});
	}
	//!steal-remove-end

	this.setupValueBinding();
}

var onPatchesSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.onPatches");
var offPatchesSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.offPatches");

ListDOMPatcher.prototype = {
	setupValueBinding: function() {
		// Teardown when the placeholder element is removed.
		this.teardownNodeRemoved = canDomMutate_2_0_9_canDomMutate.onNodeRemoved(this.range.start, this.teardownValueBinding);

		// Listen to when the patcher produces patches.
		this.patcher[onPatchesSymbol$2](this.onPatches, "notify");

		// Initialize with the patcher's value
		if (this.patcher.currentList && this.patcher.currentList.length) {
			this.add(this.patcher.currentList, 0);
		} else {
			this.addFalseyIfEmpty();
		}
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			canReflectDependencies_1_1_2_canReflectDependencies.addMutatedBy(this.range.start, this.patcher.observableOrList);
		}
		//!steal-remove-end
	},
	teardownValueBinding: function() {

		this.exit = true;
		// Stop listening for teardowns
		this.teardownNodeRemoved();
		this.patcher[offPatchesSymbol$1](this.onPatches, "notify");
		// Todo: I bet this is no longer necessary?
		//this.remove({
		//	length: this.patcher.currentList ? this.patcher.currentList.length : 0
		//}, 0, true);
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			canReflectDependencies_1_1_2_canReflectDependencies.deleteMutatedBy(this.range.start, this.patcher.observableOrList);
		}
		//!steal-remove-end
	},
	onPatches: function ListDOMPatcher_onPatches(patches) {
		if (this.exit) {
			return;
		}
		var sortedPatches = [];
		patches.forEach(function(patch) {
			sortedPatches.push.apply(sortedPatches, patchSort([patch]));
		});

		// adjust so things can happen
		for (var i = 0, patchLen = sortedPatches.length; i < patchLen; i++) {
			var patch = sortedPatches[i];
			if (patch.type === "move") {
				this.addToDomQueue(
					this.move,
					[patch.toIndex, patch.fromIndex]
				);
			} else if (patch.type === "splice") {
				if (patch.deleteCount) {
					// Remove any items scheduled for deletion from the patch.
					this.addToDomQueue(this.remove, [{
						length: patch.deleteCount
					}, patch.index]);
				}
				if (patch.insert && patch.insert.length) {
					// Insert any new items at the index
					this.addToDomQueue(this.add, [patch.insert, patch.index]);
				}
			} else {
				// all other patch types are ignored
				continue;
			}
		}
	},
	addToDomQueue: function(fn, args) {
		this.domQueue.push({
			fn: fn,
			args: args
		});
		canQueues_1_3_2_canQueues.domQueue.enqueue(this.processDomQueue, this, [this.domQueue], this.meta);
	},
	processDomQueue: function() {
		this.domQueue.forEach(function(queueItem) {
			var fn = queueItem.fn;
			var args = queueItem.args;
			fn.apply(this, args);
		}.bind(this));
		this.domQueue = [];
	},
	add: function(items, index) {
		//if (!afterPreviousEvents) {
		//	return;
		//}
		// Collect new html and mappings
		var ownerDocument = this.range.start.ownerDocument,
			frag = ownerDocument.createDocumentFragment(),
			newEndNodes = [],
			newIndicies = [],
			render = this.render,
			context = this.context;
		// For each new item,
		items.forEach( function(item, key) {

			var itemIndex = new canSimpleObservable_2_5_0_canSimpleObservable(key + index),
				itemCompute = new setObservable(item, function(newVal) {
					canReflect_1_19_2_canReflect.setKeyValue(this.patcher.currentList, itemIndex.get(), newVal );
				}.bind(this)),
				itemFrag = renderAndAddRangeNode(render, context, [itemCompute, itemIndex], ownerDocument);

			newEndNodes.push(itemFrag.lastChild);
			// Hookup the fragment (which sets up child live-bindings) and
			// add it to the collection of all added elements.
			frag.appendChild(itemFrag);
			// track indicies;
			newIndicies.push(itemIndex);
		}, this);
		// The position of elements is always after the initial text placeholder node

		// TODO: this should probably happen earlier.
		// remove falsey if there's something there
		if (!this.indexMap.length) {
			// remove all leftover things
			helpers$2.range.remove(this.range);
			this.itemEndNode = [];
		}
		// figure out where we are placing things.
		var placeholder,
			endNodesLength = this.itemEndNode.length;
		if(index === endNodesLength ) {
			placeholder = this.range.end;
		} else if(index === 0) {
			placeholder = this.range.start.nextSibling;
		} else if(index < endNodesLength) {
			placeholder = this.itemEndNode[index - 1].nextSibling;
		} else {
			throw new Error("Unable to place item");
		}

		canDomMutate_2_0_9_node.insertBefore.call(placeholder.parentNode,frag,placeholder);

		splice.apply(this.itemEndNode, [
			index,
			0
		].concat(newEndNodes));

		// update indices after insert point
		splice.apply(this.indexMap, [
			index,
			0
		].concat(newIndicies));

		for (var i = index + newIndicies.length, len = this.indexMap.length; i < len; i++) {
			this.indexMap[i].set(i);
		}
	},
	remove: function(items, index) {
		//if (!afterPreviousEvents) {
		//	return;
		//}

		// If this is because an element was removed, we should
		// check to make sure the live elements are still in the page.
		// If we did this during a teardown, it would cause an infinite loop.
		//if (!duringTeardown && this.data.teardownCheck(this.placeholder.parentNode)) {
		//	return;
		//}
		if (index < 0) {
			index = this.indexMap.length + index;
		}
		var removeStart;
		var removeEnd;
		var removeCount = items.length;
		var endIndex = index + removeCount - 1;
		if(index === 0) {
			removeStart = this.range.start;
		} else {
			removeStart = this.itemEndNode[index - 1];
		}
		removeEnd = this.itemEndNode[endIndex].nextSibling;

		this.itemEndNode.splice(index, items.length);

		if (removeStart && removeEnd) {
			helpers$2.range.remove({start: removeStart, end: removeEnd});
		}

		var indexMap = this.indexMap;

		// update indices after remove point
		indexMap.splice(index, items.length);
		for (var i = index, len = indexMap.length; i < len; i++) {
			indexMap[i].set(i);
		}

		// don't remove elements during teardown.  Something else will probably be doing that.
		if (!this.exit) {
			// adds the falsey section if the list is empty
			this.addFalseyIfEmpty();
		} else {
			// This probably isn't needed anymore as element removal will be propagated
			// nodeLists.unregister(this.masterNodeList);
		}
	},
	// #### addFalseyIfEmpty
	// Add the results of redering the "falsey" or inverse case render to the
	// master nodeList and the DOM if the live list is empty
	addFalseyIfEmpty: function() {
		if (this.falseyRender && this.indexMap.length === 0) {
			// If there are no items ... we should render the falsey template
			var falseyFrag = renderAndAddRangeNode(this.falseyRender, this.currentList, [this.currentList], this.range.start.ownerDocument);
			helpers$2.range.update(this.range, falseyFrag);
		}
	},
	move: function move(newIndex, currentIndex) {
		//if (!afterPreviousEvents) {
		//	return;
		//}
		// The position of elements is always after the initial text
		// placeholder node


		var currentFirstNode,
			currentEndNode = this.itemEndNode[currentIndex];
		if( currentIndex > 0 ) {
			currentFirstNode = this.itemEndNode[currentIndex - 1].nextSibling;
		} else {
			currentFirstNode = this.range.start.nextSibling;
		}
		var newIndexFirstNode;
		if (currentIndex < newIndex) {
			// we need to advance one spot, because removing at
			// current index will shift everything left
			newIndexFirstNode = this.itemEndNode[newIndex].nextSibling;
		} else {
			if( newIndex > 0 ) {
				newIndexFirstNode = this.itemEndNode[newIndex - 1].nextSibling;
			} else {
				newIndexFirstNode = this.range.start.nextSibling;
			}
		}
		// need to put this at the newIndex



		var frag = getFrag(currentFirstNode, currentEndNode);
		newIndexFirstNode.parentNode.insertBefore(frag, newIndexFirstNode);

		// update endNodes
		this.itemEndNode.splice(currentIndex, 1);
		this.itemEndNode.splice(newIndex, 0,currentEndNode);


		// Update indexMap
		newIndex = newIndex + 1;
		currentIndex = currentIndex + 1;

		var indexMap = this.indexMap;

		// Convert back to a zero-based array index
		newIndex = newIndex - 1;
		currentIndex = currentIndex - 1;

		// Grab the index compute from the `indexMap`
		var indexCompute = indexMap[currentIndex];

		// Remove the index compute from the `indexMap`
		[].splice.apply(indexMap, [currentIndex, 1]);

		// Move the index compute to the correct index in the `indexMap`
		[].splice.apply(indexMap, [newIndex, 0, indexCompute]);

		var i = Math.min(currentIndex, newIndex);
		var len = indexMap.length;

		for (len; i < len; i++) {
			// set each compute to have its current index in the map as its value
			indexMap[i].set(i);
		}
	}
};



/**
 * @function can-view-live.list list
 * @parent can-view-live
 * @release 2.0.4
 *
 * @signature `live.list(el, list, render, context)`
 *
 * Live binds a compute's list incrementally.
 *
 * ```js
 * // a compute that change's it's list
 * var todos = compute(function(){
 *   return new Todo.List({page: can.route.attr("page")})
 * })
 *
 * var placeholder = document.createTextNode(" ");
 * $("ul#todos").append(placeholder);
 *
 * can.view.live.list(
 *   placeholder,
 *   todos,
 *   function(todo, index){
 *     return "<li>"+todo.attr("name")+"</li>"
 *   });
 * ```
 *
 * @param {HTMLElement} el An html element to replace with the live-section.
 *
 * @param {Object} list An observable value or list type. If an observable value, it should contain
 * a falsey value or a list type.
 *
 * @param {function(this:*,*,index):String} render(index, index) A function that when called with
 * the incremental item to render and the index of the item in the list.
 *
 * @param {Object} context The `this` the `render` function will be called with.
 *
 * @body
 *
 * ## How it works
 *
 * If `list` is an observable value, `live.list` listens to changes in in that
 * observable value.  It will generally change from one list type (often a list type that implements `onPatches`)
 * to another.  When the value changes, a diff will be performed and the DOM updated.  Also, `live.list`
 * will listen to `.onPatches` on the new list and apply any patches emitted from it.
 *
 *
 */
var list$1 = function(el, list, render, context, falseyRender) {
	new ListDOMPatcher(el, list, render, context, falseyRender);
};

/**
 * @function can-view-live.text text
 * @parent can-view-live
 * @release 2.0.4
 *
 * @signature `live.text(el, compute)`
 *
 * Replaces one element with some content while keeping [can-view-live.nodeLists nodeLists] data correct.
 */
var text = function(el, compute) {
	var handlerName = "";

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		if(arguments.length > 2) {
			// TODO: remove
			throw new Error("too many arguments");

		}
		handlerName = "live.text update::"+canReflect_1_19_2_canReflect.getName(compute);
	}
	//!steal-remove-end

	// TODO: we can remove this at some point
	if (el.nodeType !== Node.TEXT_NODE) {
		var textNode;

		textNode = document.createTextNode("");
		el.parentNode.replaceChild(textNode, el);
		el = textNode;

	}

	new helpers$2.ListenUntilRemovedAndInitialize(compute, function liveTextUpdateTextNode(newVal) {
		el.nodeValue = helpers$2.makeString(newVal);
	},
	el,
	"dom", // TODO: should this still be domUI?
	handlerName);
};

/**	
 * @module {{}} can-view-live can-view-live	
 * @parent can-views	
 * @collection can-infrastructure	
 * @package ./package.json	
 *	
 * Setup live-binding between the DOM and a compute manually.	
 *	
 * @option {Object} An object with the live-binding methods:	
 * [can-view-live.html], [can-view-live.list], [can-view-live.text], and	
 * [can-view-live.attr].	
 *
 *	
 * @body	
 *	
 * ## Use	
 *	
 *  [can-view-live] is an object with utility methods for setting up	
 *  live-binding in relation to different parts of the DOM and DOM elements.  For	
 *  example, to make an `<h2>`'s text stay live with	
 *  a compute:	
 *	
 *  ```js	
 *  var live = require("can-view-live");	
 *  var text = canCompute("Hello World");	
 *  var textNode = $("h2").text(" ")[0].childNodes[0];	
 *  live.text(textNode, text);	
 *  ```	
 *	
 */
var live = {};
live.attr = attr_1;
live.attrs = attrs;
live.html = html;
live.list = list$1;
live.text = text;


var canViewLive_5_0_5_canViewLive = live;

var noop = function(){};

var TextSectionBuilder = function(filename){
	if (filename) {
		this.filename = filename;
	}
	this.stack = [new TextSection()];
};

canAssign_1_3_3_canAssign(TextSectionBuilder.prototype,utils$1.mixins);

canAssign_1_3_3_canAssign(TextSectionBuilder.prototype,{
	// Adds a subsection.
	startSection: function(process){
		var subSection = new TextSection();
		this.last().add({process: process, truthy: subSection});
		this.stack.push(subSection);
	},
	endSection: function(){
		this.stack.pop();
	},
	inverse: function(){
		this.stack.pop();
		var falseySection = new TextSection();
		this.last().last().falsey = falseySection;
		this.stack.push(falseySection);
	},
	compile: function(state){

		var renderer = this.stack[0].compile();
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			Object.defineProperty(renderer,"name",{
				value: "textSectionRenderer<"+state.tag+"."+state.attr+">"
			});
		}
		//!steal-remove-end

		return function(scope){
			function textSectionRender(){
				return renderer(scope);
			}
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				Object.defineProperty(textSectionRender,"name",{
					value: "textSectionRender<"+state.tag+"."+state.attr+">"
				});
			}
			//!steal-remove-end
			var observation = new canObservation_4_2_0_canObservation(textSectionRender, null, {isObservable: false});

			canReflect_1_19_2_canReflect.onValue(observation, noop);

			var value = canReflect_1_19_2_canReflect.getValue(observation);
			if( canReflect_1_19_2_canReflect.valueHasDependencies( observation ) ) {
				if(state.textContentOnly) {
					canViewLive_5_0_5_canViewLive.text(this, observation);
				}
				else if(state.attr) {
					canViewLive_5_0_5_canViewLive.attr(this, state.attr, observation);
				}
				else {
					canViewLive_5_0_5_canViewLive.attrs(this, observation, scope);
				}
				canReflect_1_19_2_canReflect.offValue(observation, noop);
			} else {
				if(state.textContentOnly) {
					this.nodeValue = value;
				}
				else if(state.attr) {
					canDomMutate_2_0_9_node.setAttribute.call(this, state.attr, value);
				}
				else {
					canViewLive_5_0_5_canViewLive.attrs(this, value);
				}
			}
		};
	}
});

var passTruthyFalsey = function(process, truthy, falsey){
	return function(scope){
		return process.call(this, scope, truthy, falsey);
	};
};

var TextSection = function(){
	this.values = [];
};

canAssign_1_3_3_canAssign( TextSection.prototype, {
	add: function(data){
		this.values.push(data);
	},
	last: function(){
		return this.values[this.values.length - 1];
	},
	compile: function(){
		var values = this.values,
			len = values.length;

		for(var i = 0 ; i < len; i++) {
			var value = this.values[i];
			if(typeof value === "object") {
				values[i] = passTruthyFalsey( value.process,
				    value.truthy && value.truthy.compile(),
				    value.falsey && value.falsey.compile());
			}
		}

		return function(scope){
			var txt = "",
				value;
			for(var i = 0; i < len; i++){
				value = values[i];
				txt += typeof value === "string" ? value : value.call(this, scope);
			}
			return txt;
		};
	}
});

var text_section = TextSectionBuilder;

// ### Arg
// `new Arg(Expression [,modifierOptions] )`
// Used to identify an expression that should return a value.
var Arg = function(expression, modifiers){
	this.expr = expression;
	this.modifiers = modifiers || {};
	this.isCompute = false;
};
Arg.prototype.value = function(){
	return this.expr.value.apply(this.expr, arguments);
};
//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	Arg.prototype.sourceText = function(){
		return (this.modifiers.compute ? "~" : "")+ this.expr.sourceText();
	};
}
//!steal-remove-end

var arg = Arg;

// ### Literal
// For inline static values like `{{"Hello World"}}`
var Literal = function(value){
	this._value = value;
};
Literal.prototype.value = function(){
	return this._value;
};
//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	Literal.prototype.sourceText = function(){
		return JSON.stringify(this._value);
	};
}
//!steal-remove-end

var literal = Literal;

// ## Helpers

function getObservableValue_fromDynamicKey_fromObservable(key, root, helperOptions, readOptions) {
	// This needs to return something similar to a ScopeKeyData with intialValue and parentHasKey
	var getKeys = function(){
		return canStacheKey_1_4_3_canStacheKey.reads(("" + canReflect_1_19_2_canReflect.getValue(key)).replace(/\./g, "\\."));
	};
	var parentHasKey;
	var computeValue = new setter(function getDynamicKey() {
		var readData = canStacheKey_1_4_3_canStacheKey.read( canReflect_1_19_2_canReflect.getValue(root) , getKeys());
		parentHasKey = readData.parentHasKey;
		return readData.value;
	}, function setDynamicKey(newVal){
		canStacheKey_1_4_3_canStacheKey.write(canReflect_1_19_2_canReflect.getValue(root), getKeys(), newVal);
	});
	// This prevents lazy evalutaion
	canObservation_4_2_0_canObservation.temporarilyBind(computeValue);

	// peek so no observable that might call getObservableValue_fromDynamicKey_fromObservable will re-evaluate if computeValue changes.
	computeValue.initialValue = canObservationRecorder_1_3_1_canObservationRecorder.peekValue(computeValue);
	computeValue.parentHasKey = parentHasKey;
	// Todo:
	// 1. We should warn here if `initialValue` is undefined.  We can expose the warning function
	//    in can-view-scope and call it here.
	// 2. We should make this lazy if possible.  We can do that by making getter/setters for
	//    initialValue and parentHasKey (and possibly @@can.valueHasDependencies)
	return computeValue;
}

// If not a Literal or an Arg, convert to an arg for caching.
function convertToArgExpression(expr) {
	if(!(expr instanceof arg) && !(expr instanceof literal)) {
		return new arg(expr);
	} else {
		return expr;
	}
}

function toComputeOrValue(value) {
	// convert to non observable value
	if(canReflect_1_19_2_canReflect.isObservableLike(value)) {
		// we only want to do this for things that `should` have dependencies, but dont.
		if(canReflect_1_19_2_canReflect.isValueLike(value) && canReflect_1_19_2_canReflect.valueHasDependencies(value) === false) {
			return canReflect_1_19_2_canReflect.getValue(value);
		}
		// if compute data
		if(value.compute) {
			return value.compute;
		} else {
			return canViewScope_4_13_7_makeComputeLike(value);
		}
	}
	return value;
}

// try to make it a compute no matter what.  This is useful for
// ~ operator.
function toCompute(value) {
	if(value) {

		if(value.isComputed) {
			return value;
		}
		if(value.compute) {
			return value.compute;
		} else {
			return canViewScope_4_13_7_makeComputeLike(value);
		}
	}
	return value;
}

var expressionHelpers = {
	getObservableValue_fromDynamicKey_fromObservable: getObservableValue_fromDynamicKey_fromObservable,
	convertToArgExpression: convertToArgExpression,
	toComputeOrValue: toComputeOrValue,
	toCompute: toCompute
};

var Hashes = function(hashes){
	this.hashExprs = hashes;
};
Hashes.prototype.value = function(scope, helperOptions){
	var hash = {};
	for(var prop in this.hashExprs) {
		var val = expressionHelpers.convertToArgExpression(this.hashExprs[prop]),
			value = val.value.apply(val, arguments);

		hash[prop] = {
			call: !val.modifiers || !val.modifiers.compute,
			value: value
		};
	}
	return new canObservation_4_2_0_canObservation(function(){
		var finalHash = {};
		for(var prop in hash) {
			finalHash[prop] = hash[prop].call ? canReflect_1_19_2_canReflect.getValue( hash[prop].value ) : expressionHelpers.toComputeOrValue( hash[prop].value );
		}
		return finalHash;
	});
};
//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	Hashes.prototype.sourceText = function(){
		var hashes = [];
		canReflect_1_19_2_canReflect.eachKey(this.hashExprs, function(expr, prop){
			hashes.push( prop+"="+expr.sourceText() );
		});
		return hashes.join(" ");
	};
}
//!steal-remove-end

var hashes = Hashes;

//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	var canSymbol = canSymbol_1_7_0_canSymbol;
}
//!steal-remove-end


// ### Bracket
// For accessing properties using bracket notation like `foo[bar]`
var Bracket = function (key, root, originalKey) {
	this.root = root;
	this.key = key;
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		this[canSymbol.for("can-stache.originalKey")] = originalKey;
	}
	//!steal-remove-end
};
Bracket.prototype.value = function (scope, helpers) {
	var root = this.root ? this.root.value(scope, helpers) : scope.peek("this");
	return expressionHelpers.getObservableValue_fromDynamicKey_fromObservable(this.key.value(scope, helpers), root, scope, helpers, {});
};
//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	Bracket.prototype.sourceText = function(){
		if(this.rootExpr) {
			return this.rootExpr.sourceText()+"["+this.key+"]";
		} else {
			return "["+this.key+"]";
		}
	};
}
//!steal-remove-end

Bracket.prototype.closingTag = function() {
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		return this[canSymbol.for('can-stache.originalKey')] || '';
	}
	//!steal-remove-end
};

var bracket = Bracket;

var setIdentifier = function SetIdentifier(value){
	this.value = value;
};

var sourceTextSymbol = canSymbol_1_7_0_canSymbol.for("can-stache.sourceText");
var isViewSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.isView");



// ### Call
// `new Call( new Lookup("method"), [new ScopeExpr("name")], {})`
// A call expression like `method(arg1, arg2)` that, by default,
// calls `method` with non compute values.
var Call = function(methodExpression, argExpressions){
	this.methodExpr = methodExpression;
	this.argExprs = argExpressions.map(expressionHelpers.convertToArgExpression);
};
Call.prototype.args = function(scope, ignoreArgLookup) {
	var hashExprs = {};
	var args = [];
	var gotIgnoreFunction = typeof ignoreArgLookup === "function";

	for (var i = 0, len = this.argExprs.length; i < len; i++) {
		var arg = this.argExprs[i];
		if(arg.expr instanceof hashes){
			canAssign_1_3_3_canAssign(hashExprs, arg.expr.hashExprs);
		}
		if (!gotIgnoreFunction || !ignoreArgLookup(i)) {
			var value = arg.value.apply(arg, arguments);
			args.push({
				// always do getValue unless compute is false
				call: !arg.modifiers || !arg.modifiers.compute,
				value: value
			});
		}
	}
	return function(doNotWrapArguments){
		var finalArgs = [];
		if(canReflect_1_19_2_canReflect.size(hashExprs) > 0){
			finalArgs.hashExprs = hashExprs;
		}
		for(var i = 0, len = args.length; i < len; i++) {
			if (doNotWrapArguments) {
				finalArgs[i] = args[i].value;
			} else {
				finalArgs[i] = args[i].call ?
					canReflect_1_19_2_canReflect.getValue( args[i].value ) :
					expressionHelpers.toCompute( args[i].value );
			}
		}
		return finalArgs;
	};
};

Call.prototype.value = function(scope, helperOptions){
	var callExpression = this;

	// proxyMethods must be false so that the `requiresOptionsArgument` and any
	// other flags stored on the function are preserved
	var method = this.methodExpr.value(scope, { proxyMethods: false });
	canObservation_4_2_0_canObservation.temporarilyBind(method);
	var func = canReflect_1_19_2_canReflect.getValue( method );

	var getArgs = callExpression.args(scope , func && func.ignoreArgLookup);

	var computeFn = function(newVal){
		var func = canReflect_1_19_2_canReflect.getValue( method );
		if(typeof func === "function") {
			if (canReflect_1_19_2_canReflect.isObservableLike(func)) {
				func = canReflect_1_19_2_canReflect.getValue(func);
			}
			var args = getArgs(
				func.isLiveBound
			);

			if (func.requiresOptionsArgument) {
				if(args.hashExprs && helperOptions && helperOptions.exprData){
					helperOptions.exprData.hashExprs = args.hashExprs;
				}
				// For #581
				if(helperOptions !== undefined) {
					args.push(helperOptions);
				}
			}
			// we are calling a view!
			if(func[isViewSymbol$1] === true) {
				// if not a scope, we should create a scope that
				// includes the template scope
				if(!(args[0] instanceof canViewScope_4_13_7_canViewScope)){
					args[0] = scope.getTemplateContext().add(args[0]);
				}
			}
			if(arguments.length) {
				args.unshift(new setIdentifier(newVal));
			}

			// if this is a call like `foo.bar()` the method.thisArg will be set to `foo`
			// for a call like `foo()`, method.thisArg will not be set and we will default
			// to setting the scope as the context of the function
			return func.apply(method.thisArg || scope.peek("this"), args);
		}
	};
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		Object.defineProperty(computeFn, "name", {
			value: "{{" + this.sourceText() + "}}"
		});
	}
	//!steal-remove-end

	if (helperOptions && helperOptions.doNotWrapInObservation) {
		return computeFn();
	} else {
		var computeValue = new setter(computeFn, computeFn);

		return computeValue;
	}
};
//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	Call.prototype.sourceText = function(){
		var args = this.argExprs.map(function(arg){
			return arg.sourceText();
		});
		return this.methodExpr.sourceText()+"("+args.join(",")+")";
	};
}
//!steal-remove-end
Call.prototype.closingTag = function() {
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		if(this.methodExpr[sourceTextSymbol]) {
			return this.methodExpr[sourceTextSymbol];
		}
	}
	//!steal-remove-end
	return this.methodExpr.key;
};

var call$1 = Call;

var Helper = function(methodExpression, argExpressions, hashExpressions){
	this.methodExpr = methodExpression;
	this.argExprs = argExpressions;
	this.hashExprs = hashExpressions;
	this.mode = null;
};
Helper.prototype.args = function(scope){
	var args = [];
	for(var i = 0, len = this.argExprs.length; i < len; i++) {
		var arg = this.argExprs[i];
		// TODO: once we know the helper, we should be able to avoid compute conversion
		args.push( expressionHelpers.toComputeOrValue( arg.value.apply(arg, arguments) ) );
	}
	return args;
};
Helper.prototype.hash = function(scope){
	var hash = {};
	for(var prop in this.hashExprs) {
		var val = this.hashExprs[prop];
		// TODO: once we know the helper, we should be able to avoid compute conversion
		hash[prop] = expressionHelpers.toComputeOrValue( val.value.apply(val, arguments) );
	}
	return hash;
};

Helper.prototype.value = function(scope, helperOptions){
	// If a literal, this means it should be treated as a key. But helpers work this way for some reason.
	// TODO: fix parsing so numbers will also be assumed to be keys.
	var methodKey = this.methodExpr instanceof literal ?
		"" + this.methodExpr._value :
		this.methodExpr.key,
		helperInstance = this,
		// proxyMethods must be false so that the `requiresOptionsArgument` and any
		// other flags stored on the function are preserved
		helperFn = scope.computeData(methodKey,  { proxyMethods: false }),
		initialValue = helperFn && helperFn.initialValue,
		thisArg = helperFn && helperFn.thisArg;

	if (typeof initialValue === "function") {
		helperFn = function helperFn() {
			var args = helperInstance.args(scope),
				helperOptionArg = canAssign_1_3_3_canAssign(canAssign_1_3_3_canAssign({}, helperOptions), {
					hash: helperInstance.hash(scope),
					exprData: helperInstance
				});

			args.push(helperOptionArg);

			return initialValue.apply(thisArg || scope.peek("this"), args);
		};
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			Object.defineProperty(helperFn, "name", {
				configurable: true,
				value: canReflect_1_19_2_canReflect.getName(this)
			});
		}
		//!steal-remove-end
	}
	//!steal-remove-start
	else if (process.env.NODE_ENV !== 'production') {
		var filename = scope.peek('scope.filename');
			var lineNumber = scope.peek('scope.lineNumber');
			dev.warn(
				(filename ? filename + ':' : '') +
				(lineNumber ? lineNumber + ': ' : '') +
				'Unable to find helper "' + methodKey + '".');
	}
	//!steal-remove-end

	return  helperFn;
};

Helper.prototype.closingTag = function() {
	return this.methodExpr.key;
};

//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	Helper.prototype.sourceText = function(){
		var text = [this.methodExpr.sourceText()];
		if(this.argExprs.length) {
			text.push( this.argExprs.map(function(arg){
				return arg.sourceText();
			}).join(" ") );
		}
		if(canReflect_1_19_2_canReflect.size(this.hashExprs) > 0){
			text.push( hashes.prototype.sourceText.call(this) );
		}
		return text.join(" ");
	};

	canReflect_1_19_2_canReflect.assignSymbols(Helper.prototype,{
		"can.getName": function() {
			return canReflect_1_19_2_canReflect.getName(this.constructor) + "{{" + (this.sourceText()) + "}}";
		}
	});
}
//!steal-remove-end

var helper = Helper;

var sourceTextSymbol$1 = canSymbol_1_7_0_canSymbol.for("can-stache.sourceText");


// ### Lookup
// `new Lookup(String, [Expression])`
// Finds a value in the scope or a helper.
var Lookup = function(key, root, sourceText) {
	this.key = key;
	this.rootExpr = root;
	canReflect_1_19_2_canReflect.setKeyValue(this, sourceTextSymbol$1, sourceText);
};
Lookup.prototype.value = function(scope, readOptions){
	if (this.rootExpr) {
		return expressionHelpers.getObservableValue_fromDynamicKey_fromObservable(this.key, this.rootExpr.value(scope), scope, {}, {});
	} else {
		return scope.computeData(this.key, canAssign_1_3_3_canAssign({
			warnOnMissingKey: true
		},readOptions));
	}
};
//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	Lookup.prototype.sourceText = function(){
		if(this[sourceTextSymbol$1]) {
			return this[sourceTextSymbol$1];
		} else if(this.rootExpr) {
			return this.rootExpr.sourceText()+"."+this.key;
		} else {
			return this.key;
		}
	};
}
//!steal-remove-end

var lookup = Lookup;

// ## Expression Types
//
// These expression types return a value. They are assembled by `expression.parse`.













var last$1 = utils$1.last;



var sourceTextSymbol$2 = canSymbol_1_7_0_canSymbol.for("can-stache.sourceText");

// ### Hash
// A placeholder. This isn't actually used.
var Hash = function(){ }; // jshint ignore:line

// NAME - \w
// KEY - foo, foo.bar, foo@bar, %foo (special), &foo (references), ../foo, ./foo
// ARG - ~KEY, KEY, CALLEXPRESSION, PRIMITIVE
// CALLEXPRESSION = KEY(ARG,ARG, NAME=ARG)
// HELPEREXPRESSION = KEY ARG ARG NAME=ARG
// DOT .NAME
// AT @NAME
//
var keyRegExp = /[\w\.\\\-_@\/\&%]+/,
	tokensRegExp = /('.*?'|".*?"|=|[\w\.\\\-_@\/*%\$]+|[\(\)]|,|\~|\[|\]\s*|\s*(?=\[))/g,
	bracketSpaceRegExp = /\]\s+/,
	literalRegExp = /^('.*?'|".*?"|-?[0-9]+\.?[0-9]*|true|false|null|undefined)$/;

var isTokenKey = function(token){
	return keyRegExp.test(token);
};

var testDot = /^[\.@]\w/;
var isAddingToExpression = function(token) {

	return isTokenKey(token) && testDot.test(token);
};

var ensureChildren = function(type) {
	if(!type.children) {
		type.children = [];
	}
	return type;
};

var Stack = function(){

	this.root = {children: [], type: "Root"};
	this.current = this.root;
	this.stack = [this.root];
};
canAssign_1_3_3_canAssign(Stack.prototype,{
	top: function(){
		return last$1(this.stack);
	},
	isRootTop: function(){
		return this.top() === this.root;
	},
	popTo: function(types){
		this.popUntil(types);
		this.pop();
	},
	pop: function() {
		if(!this.isRootTop()) {
			this.stack.pop();
		}
	},
	first: function(types){
		var curIndex = this.stack.length - 1;
		while( curIndex > 0 && types.indexOf(this.stack[curIndex].type) === -1 ) {
			curIndex--;
		}
		return this.stack[curIndex];
	},
	firstParent: function(types){
		var curIndex = this.stack.length - 2;
		while( curIndex > 0 && types.indexOf(this.stack[curIndex].type) === -1 ) {
			curIndex--;
		}
		return this.stack[curIndex];
	},
	popUntil: function(types){
		while( types.indexOf(this.top().type) === -1 && !this.isRootTop() ) {
			this.stack.pop();
		}
		return this.top();
	},
	addTo: function(types, type){
		var cur = this.popUntil(types);
		ensureChildren(cur).children.push(type);
	},
	addToAndPush: function(types, type){
		this.addTo(types, type);
		this.stack.push(type);
	},
	push: function(type) {
		this.stack.push(type);
	},
	topLastChild: function(){
		return last$1(this.top().children);
	},
	replaceTopLastChild: function(type){
		var children = ensureChildren(this.top()).children;
		children.pop();
		children.push(type);
		return type;
	},
	replaceTopLastChildAndPush: function(type) {
		this.replaceTopLastChild(type);
		this.stack.push(type);
	},
	replaceTopAndPush: function(type){
		var children;
		if(this.top() === this.root) {
			children = ensureChildren(this.top()).children;
		} else {
			this.stack.pop();
			// get parent and clean
			children = ensureChildren(this.top()).children;
		}

		children.pop();
		children.push(type);
		this.stack.push(type);
		return type;
	}
});

// converts
// - "../foo" -> "../@foo",
// - "foo" -> "@foo",
// - ".foo" -> "@foo",
// - "./foo" -> "./@foo"
// - "foo.bar" -> "foo@bar"
var convertKeyToLookup = function(key){
	var lastPath = key.lastIndexOf("./");
	var lastDot = key.lastIndexOf(".");
	if(lastDot > lastPath) {
		return key.substr(0, lastDot)+"@"+key.substr(lastDot+1);
	}
	var firstNonPathCharIndex = lastPath === -1 ? 0 : lastPath+2;
	var firstNonPathChar = key.charAt(firstNonPathCharIndex);
	if(firstNonPathChar === "." || firstNonPathChar === "@" ) {
		return key.substr(0, firstNonPathCharIndex)+"@"+key.substr(firstNonPathCharIndex+1);
	} else {
		return key.substr(0, firstNonPathCharIndex)+"@"+key.substr(firstNonPathCharIndex);
	}
};
var convertToAtLookup = function(ast){
	if(ast.type === "Lookup") {
		canReflect_1_19_2_canReflect.setKeyValue(ast, sourceTextSymbol$2, ast.key);
		ast.key = convertKeyToLookup(ast.key);
	}
	return ast;
};

var convertToHelperIfTopIsLookup = function(stack){
	var top = stack.top();
	// if two scopes, that means a helper
	if(top && top.type === "Lookup") {

		var base = stack.stack[stack.stack.length - 2];
		// That lookup shouldn't be part of a Helper already or
		if(base.type !== "Helper" && base) {
			stack.replaceTopAndPush({
				type: "Helper",
				method: top
			});
		}
	}
};

var expression = {
	toComputeOrValue: expressionHelpers.toComputeOrValue,
	convertKeyToLookup: convertKeyToLookup,

	Literal: literal,
	Lookup: lookup,
	Arg: arg,
	Hash: Hash,
	Hashes: hashes,
	Call: call$1,
	Helper: helper,
	Bracket: bracket,

	SetIdentifier: setIdentifier,
	tokenize: function(expression){
		var tokens = [];
		(expression.trim() + ' ').replace(tokensRegExp, function (whole, arg$$1) {
			if (bracketSpaceRegExp.test(arg$$1)) {
				tokens.push(arg$$1[0]);
				tokens.push(arg$$1.slice(1));
			} else {
				tokens.push(arg$$1);
			}
		});
		return tokens;
	},
	lookupRules: {
		"default": function(ast, methodType, isArg){
			return ast.type === "Helper" ? helper : lookup;
		},
		"method": function(ast, methodType, isArg){
			return lookup;
		}
	},
	methodRules: {
		"default": function(ast){
			return ast.type === "Call" ? call$1 : helper;
		},
		"call": function(ast){
			return call$1;
		}
	},
	// ## expression.parse
	//
	// - {String} expressionString - A stache expression like "abc foo()"
	// - {Object} options
	//   - baseMethodType - Treat this like a Helper or Call.  Default to "Helper"
	//   - lookupRule - "default" or "method"
	//   - methodRule - "default" or "call"
	parse: function(expressionString, options){
		options =  options || {};
		var ast = this.ast(expressionString);

		if(!options.lookupRule) {
			options.lookupRule = "default";
		}
		if(typeof options.lookupRule === "string") {
			options.lookupRule = expression.lookupRules[options.lookupRule];
		}
		if(!options.methodRule) {
			options.methodRule = "default";
		}
		if(typeof options.methodRule === "string") {
			options.methodRule = expression.methodRules[options.methodRule];
		}

		var expr = this.hydrateAst(ast, options, options.baseMethodType || "Helper");

		return expr;
	},
	hydrateAst: function(ast, options, methodType, isArg){
		var hashes$$1;
		if(ast.type === "Lookup") {
			var LookupRule = options.lookupRule(ast, methodType, isArg);
			var lookup$$1 = new LookupRule(ast.key, ast.root && this.hydrateAst(ast.root, options, methodType), ast[sourceTextSymbol$2] );
			return lookup$$1;
		}
		else if(ast.type === "Literal") {
			return new literal(ast.value);
		}
		else if(ast.type === "Arg") {
			return new arg(this.hydrateAst(ast.children[0], options, methodType, isArg),{compute: true});
		}
		else if(ast.type === "Hash") {
			throw new Error("");
		}
		else if(ast.type === "Hashes") {
			hashes$$1 = {};
			ast.children.forEach(function(hash){
				hashes$$1[hash.prop] = this.hydrateAst( hash.children[0], options, methodType, true );
			}, this);
			return new hashes(hashes$$1);
		}
		else if(ast.type === "Call" || ast.type === "Helper") {
			//get all arguments and hashes
			hashes$$1 = {};
			var args = [],
				children = ast.children,
				ExpressionType = options.methodRule(ast);
			if(children) {
				for(var i = 0 ; i <children.length; i++) {
					var child = children[i];
					if(child.type === "Hashes" && ast.type === "Helper" &&
						(ExpressionType !== call$1)) {

						child.children.forEach(function(hash){
							hashes$$1[hash.prop] = this.hydrateAst( hash.children[0], options, ast.type, true );
						}, this);

					} else {
						args.push( this.hydrateAst(child, options, ast.type, true) );
					}
				}
			}


			return new ExpressionType(this.hydrateAst(ast.method, options, ast.type),
																args, hashes$$1);
		} else if (ast.type === "Bracket") {
			var originalKey;
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				originalKey = ast[canSymbol_1_7_0_canSymbol.for("can-stache.originalKey")];
			}
			//!steal-remove-end
			return new bracket(
				this.hydrateAst(ast.children[0], options),
				ast.root ? this.hydrateAst(ast.root, options) : undefined,
				originalKey
			);
		}
	},
	ast: function(expression){
		var tokens = this.tokenize(expression);
		return this.parseAst(tokens, {
			index: 0
		});
	},
	parseAst: function(tokens, cursor) {
		// jshint maxdepth: 6
		var stack = new Stack(),
			top,
			firstParent,
			lastToken;

		while(cursor.index < tokens.length) {
			var token = tokens[cursor.index],
				nextToken = tokens[cursor.index+1];

			cursor.index++;

			// Hash
			if(nextToken === "=") {
				//convertToHelperIfTopIsLookup(stack);
				top = stack.top();

				// If top is a Lookup, we might need to convert to a helper.
				if(top && top.type === "Lookup") {
					// Check if current Lookup is part of a Call, Helper, or Hash
					// If it happens to be first within a Call or Root, that means
					// this is helper syntax.
					firstParent = stack.firstParent(["Call","Helper","Hash"]);
					if(firstParent.type === "Call" || firstParent.type === "Root") {

						stack.popUntil(["Call"]);
						top = stack.top();
						stack.replaceTopAndPush({
							type: "Helper",
							method: top.type === "Root" ? last$1(top.children) : top
						});

					}
				}

				firstParent = stack.first(["Call","Helper","Hashes","Root"]);
				// makes sure we are adding to Hashes if there already is one
				// otherwise we create one.
				var hash = {type: "Hash", prop: token};
				if(firstParent.type === "Hashes") {
					stack.addToAndPush(["Hashes"], hash);
				} else {
					stack.addToAndPush(["Helper", "Call","Root"], {
						type: "Hashes",
						children: [hash]
					});
					stack.push(hash);
				}
				cursor.index++;

			}
			// Literal
			else if(literalRegExp.test( token )) {
				convertToHelperIfTopIsLookup(stack);
				// only add to hash if there's not already a child.
				firstParent = stack.first(["Helper", "Call", "Hash", "Bracket"]);
				if(firstParent.type === "Hash" && (firstParent.children && firstParent.children.length > 0)) {
					stack.addTo(["Helper", "Call", "Bracket"], {type: "Literal", value: utils$1.jsonParse( token )});
				} else if(firstParent.type === "Bracket" && (firstParent.children && firstParent.children.length > 0)) {
					stack.addTo(["Helper", "Call", "Hash"], {type: "Literal", value: utils$1.jsonParse( token )});
				} else {
					stack.addTo(["Helper", "Call", "Hash", "Bracket"], {type: "Literal", value: utils$1.jsonParse( token )});
				}

			}
			// Lookup
			else if(keyRegExp.test(token)) {
				lastToken = stack.topLastChild();
				firstParent = stack.first(["Helper", "Call", "Hash", "Bracket"]);

				// if we had `foo().bar`, we need to change to a Lookup that looks up from lastToken.
				if(lastToken && (lastToken.type === "Call" || lastToken.type === "Bracket" ) && isAddingToExpression(token)) {
					stack.replaceTopLastChildAndPush({
						type: "Lookup",
						root: lastToken,
						key: token.slice(1) // remove leading `.`
					});
				}
				else if(firstParent.type === 'Bracket') {
					// a Bracket expression without children means we have
					// parsed `foo[` of an expression like `foo[bar]`
					// so we know to add the Lookup as a child of the Bracket expression
					if (!(firstParent.children && firstParent.children.length > 0)) {
						stack.addToAndPush(["Bracket"], {type: "Lookup", key: token});
					} else {
						// check if we are adding to a helper like `eq foo[bar] baz`
						// but not at the `.baz` of `eq foo[bar].baz xyz`
						if(stack.first(["Helper", "Call", "Hash", "Arg"]).type === 'Helper' && token[0] !== '.') {
							stack.addToAndPush(["Helper"], {type: "Lookup", key: token});
						} else {
							// otherwise, handle the `.baz` in expressions like `foo[bar].baz`
							stack.replaceTopAndPush({
								type: "Lookup",
								key: token.slice(1),
								root: firstParent
							});
						}
					}
				}
				else {
					// if two scopes, that means a helper
					convertToHelperIfTopIsLookup(stack);

					stack.addToAndPush(["Helper", "Call", "Hash", "Arg", "Bracket"], {type: "Lookup", key: token});
				}

			}
			// Arg
			else if(token === "~") {
				convertToHelperIfTopIsLookup(stack);
				stack.addToAndPush(["Helper", "Call", "Hash"], {type: "Arg", key: token});
			}
			// Call
			// foo[bar()]
			else if(token === "(") {
				top = stack.top();
				lastToken = stack.topLastChild();
				if(top.type === "Lookup") {
					stack.replaceTopAndPush({
						type: "Call",
						method: convertToAtLookup(top)
					});

				// Nested Call
				// foo()()
				} else if (lastToken && lastToken.type === "Call") {
					stack.replaceTopAndPush({
						type: "Call",
						method: lastToken
					});
				} else {
					throw new Error("Unable to understand expression "+tokens.join(''));
				}
			}
			// End Call
			else if(token === ")") {
				stack.popTo(["Call"]);
			}
			// End Call argument
			else if(token === ",") {
				// The {{let foo=zed, bar=car}} helper is not in a call
				// expression.
				var call = stack.first(["Call"]);
				if(call.type !== "Call") {
					stack.popUntil(["Hash"]);
				} else {
					stack.popUntil(["Call"]);
				}

			}
			// Bracket
			else if(token === "[") {
				top = stack.top();
				lastToken = stack.topLastChild();

				// foo()[bar] => top -> root, lastToken -> {t: call, m: "@foo"}
				// foo()[bar()] => same as above last thing we see was a call expression "rotate"
				// test['foo'][0] => lastToken => {root: test, t: Bracket, c: 'foo' }
				// log(thing['prop'][0]) =>
				//
				//     top -> {Call, children|args: [Bracket(Lookup(thing), c: ['[prop]'])]}
				//     last-> Bracket(Lookup(thing), c: ['[prop]'])
				if (lastToken && (lastToken.type === "Call" || lastToken.type === "Bracket"  )  ) {
					// must be on top of the stack as it recieves new stuff ...
					// however, what we really want is to
					stack.replaceTopLastChildAndPush({type: "Bracket", root: lastToken});
				} else if (top.type === "Lookup" || top.type === "Bracket") {
					var bracket$$1 = {type: "Bracket", root: top};
					//!steal-remove-start
					if (process.env.NODE_ENV !== 'production') {
						canReflect_1_19_2_canReflect.setKeyValue(bracket$$1, canSymbol_1_7_0_canSymbol.for("can-stache.originalKey"), top.key);
					}
					//!steal-remove-end
					stack.replaceTopAndPush(bracket$$1);
				} else if (top.type === "Call") {
					stack.addToAndPush(["Call"], { type: "Bracket" });
				} else if (top === " ") {
					stack.popUntil(["Lookup", "Call"]);
					convertToHelperIfTopIsLookup(stack);
					stack.addToAndPush(["Helper", "Call", "Hash"], {type: "Bracket"});
				} else {
					stack.replaceTopAndPush({type: "Bracket"});
				}
			}
			// End Bracket
			else if(token === "]") {
				stack.pop();
			}
			else if(token === " ") {
				stack.push(token);
			}
		}
		return stack.root.children[0];
	}
};

var expression_1 = expression;

//
// This provides helper utilities for Mustache processing. Currently,
// only stache uses these helpers.  Ideally, these utilities could be used
// in other libraries implementing Mustache-like features.






var expression$1 = expression_1;








var toDOMSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.toDOM");

// Lazily lookup the context only if it's needed.
function HelperOptions(scope, exprData, stringOnly) {
	this.metadata = { rendered: false };
	this.stringOnly = stringOnly;
	this.scope = scope;
	this.exprData = exprData;
}
canDefineLazyValue_1_1_1_defineLazyValue(HelperOptions.prototype,"context", function(){
	return this.scope.peek("this");
});




// ## Helpers

var mustacheLineBreakRegExp = /(?:(^|\r?\n)(\s*)(\{\{([\s\S]*)\}\}\}?)([^\S\n\r]*)($|\r?\n))|(\{\{([\s\S]*)\}\}\}?)/g,
	mustacheWhitespaceRegExp = /\s*\{\{--\}\}\s*|\s*(\{\{\{?)-|-(\}\}\}?)\s*/g,
	k = function(){};
var viewInsertSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.viewInsert");


// DOM, safeString or the insertSymbol can opt-out of updating as text
function valueShouldBeInsertedAsHTML(value) {
	return value !== null && typeof value === "object" && (
		typeof value[toDOMSymbol$1] === "function" ||
		typeof value[viewInsertSymbol$1] === "function" ||
		typeof value.nodeType === "number" );
}




var core = {
	expression: expression$1,
	// ## mustacheCore.makeEvaluator
	// Given a scope and expression, returns a function that evaluates that expression in the scope.
	//
	// This function first reads lookup values in the args and hash.  Then it tries to figure out
	// if a helper is being called or a value is being read.  Finally, depending on
	// if it's a helper, or not, and which mode the expression is in, it returns
	// a function that can quickly evaluate the expression.
	/**
	 * @hide
	 * Given a mode and expression data, returns a function that evaluates that expression.
	 * @param {can-view-scope} The scope in which the expression is evaluated.
	 * @param {can.view.Options} The option helpers in which the expression is evaluated.
	 * @param {String} mode Either null, #, ^. > is handled elsewhere
	 * @param {Object} exprData Data about what was in the mustache expression
	 * @param {renderer} [truthyRenderer] Used to render a subsection
	 * @param {renderer} [falseyRenderer] Used to render the inverse subsection
	 * @param {String} [stringOnly] A flag to indicate that only strings will be returned by subsections.
	 * @return {Function} An 'evaluator' function that evaluates the expression.
	 */
	makeEvaluator: function (scope, mode, exprData, truthyRenderer, falseyRenderer, stringOnly) {

		if(mode === "^") {
			var temp = truthyRenderer;
			truthyRenderer = falseyRenderer;
			falseyRenderer = temp;
		}

		var value,
			helperOptions = new HelperOptions(scope , exprData, stringOnly);
			// set up renderers
			utils$1.createRenderers(helperOptions, scope ,truthyRenderer, falseyRenderer, stringOnly);

		if(exprData instanceof expression$1.Call) {
			value = exprData.value(scope, helperOptions);
		} else if (exprData instanceof expression$1.Bracket) {
			value = exprData.value(scope);
		} else if (exprData instanceof expression$1.Lookup) {
			value = exprData.value(scope);
		} else if (exprData instanceof expression$1.Literal) {
			value = exprData.value.bind(exprData);
		} else if (exprData instanceof expression$1.Helper && exprData.methodExpr instanceof expression$1.Bracket) {
			// Brackets get wrapped in Helpers when used in attributes
			// like `<p class="{{ foo[bar] }}" />`
			value = exprData.methodExpr.value(scope, helperOptions);
		} else {
			value = exprData.value(scope, helperOptions);
			if (typeof value === "function") {
				return value;
			}
		}
		// {{#something()}}foo{{/something}}
		// return evaluator for no mode or rendered value if a renderer was called
		if(!mode || helperOptions.metadata.rendered) {
			return value;
		} else if( mode === "#" || mode === "^" ) {

			return function(){
				// Get the value
				var finalValue = canReflect_1_19_2_canReflect.getValue(value);
				var result;

				// if options.fn or options.inverse was called, we take the observable's return value
				// as what should be put in the DOM.
				if(helperOptions.metadata.rendered) {
					result = finalValue;
				}
				// If it's an array, render.
				else if ( typeof finalValue !== "string" && canReflect_1_19_2_canReflect.isListLike(finalValue) ) {
					var isObserveList = canReflect_1_19_2_canReflect.isObservableLike(finalValue) &&
						canReflect_1_19_2_canReflect.isListLike(finalValue);

					if(canReflect_1_19_2_canReflect.getKeyValue(finalValue, "length")) {
						if (stringOnly) {
							result = utils$1.getItemsStringContent(finalValue, isObserveList, helperOptions);
						} else {
							result = canFragment_1_3_1_canFragment(utils$1.getItemsFragContent(finalValue, helperOptions, scope));
						}
					} else {
						result = helperOptions.inverse(scope);
					}
				}
				else {
					result = finalValue ? helperOptions.fn(finalValue || scope) : helperOptions.inverse(scope);
				}
				// We always set the rendered result back to false.
				// - Future calls might change from returning a value to calling `.fn`
				// - We are calling `.fn` and `.inverse` ourselves.
				helperOptions.metadata.rendered = false;
				return result;
			};
		} else {
			// not supported!
		}
	},
	// ## mustacheCore.makeLiveBindingPartialRenderer
	// Returns a renderer function that live binds a partial.
	/**
	 * @hide
	 * Returns a renderer function that live binds a partial.
	 * @param {String} expressionString
	 * @param {Object} state The html state of where the expression was found.
	 * @return {function(this:HTMLElement,can-view-scope,can.view.Options)} A renderer function
	 * live binds a partial.
	 */
	makeLiveBindingPartialRenderer: function(expressionString, state){
		expressionString = expressionString.trim();
		var exprData,
				partialName = expressionString.split(/\s+/).shift();

		if(partialName !== expressionString) {
			exprData = core.expression.parse(expressionString);
		}

		return function(scope){
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				scope.set('scope.filename', state.filename);
				scope.set('scope.lineNumber', state.lineNo);
			}
			//!steal-remove-end

			var partialFrag = new canObservation_4_2_0_canObservation(function(){
				var localPartialName = partialName;
				var partialScope = scope;
				// If the second parameter of a partial is a custom context
				if(exprData && exprData.argExprs.length === 1) {
					var newContext = canReflect_1_19_2_canReflect.getValue( exprData.argExprs[0].value(scope) );
					if(typeof newContext === "undefined") {
						//!steal-remove-start
						if (process.env.NODE_ENV !== 'production') {
							dev.warn('The context ('+ exprData.argExprs[0].key +') you passed into the' +
								'partial ('+ partialName +') is not defined in the scope!');
						}
						//!steal-remove-end
					}else{
						partialScope = scope.add(newContext);
					}
				}
				// Look up partials in templateContext first
				var partial = canReflect_1_19_2_canReflect.getKeyValue(partialScope.templateContext.partials, localPartialName);
				var renderer;

				if (partial) {
					renderer = function() {
						return partial.render ? partial.render(partialScope)
							: partial(partialScope);
					};
				}
				// Use can.view to get and render the partial.
				else {
					var scopePartialName = partialScope.read(localPartialName, {
						isArgument: true
					}).value;

					if (scopePartialName === null || !scopePartialName && localPartialName[0] === '*') {
						return canFragment_1_3_1_canFragment("");
					}
					if (scopePartialName) {
						localPartialName = scopePartialName;
					}

					renderer = function() {
						if(typeof localPartialName === "function"){
							return localPartialName(partialScope, {});
						} else {
							var domRenderer = core.getTemplateById(localPartialName);
							//!steal-remove-start
							if (process.env.NODE_ENV !== 'production') {
								if (!domRenderer) {
									dev.warn(
										(state.filename ? state.filename + ':' : '') +
										(state.lineNo ? state.lineNo + ': ' : '') +
										'Unable to find partial "' + localPartialName + '".');
								}
							}
							//!steal-remove-end
							return domRenderer ? domRenderer(partialScope, {}) : document$1().createDocumentFragment();
						}
					};
				}
				var res = canObservationRecorder_1_3_1_canObservationRecorder.ignore(renderer)();
				return canFragment_1_3_1_canFragment(res);
			});

			canViewLive_5_0_5_canViewLive.html(this, partialFrag);
		};
	},
	// ## mustacheCore.makeStringBranchRenderer
	// Return a renderer function that evalutes to a string and caches
	// the evaluator on the scope.
	/**
	 * @hide
	 * Return a renderer function that evaluates to a string.
	 * @param {String} mode
	 * @param {can.stache.Expression} expression
	 * @param {Object} state The html state of where the expression was found.
	 * @return {function(can.view.Scope,can.view.Options, can-stache.view, can.view.renderer)}
	 */
	makeStringBranchRenderer: function(mode, expressionString, state){
		var exprData = core.expression.parse(expressionString),
			// Use the full mustache expression as the cache key.
			fullExpression = mode+expressionString;

		// A branching renderer takes truthy and falsey renderer.
		var branchRenderer = function branchRenderer(scope, truthyRenderer, falseyRenderer){
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				scope.set('scope.filename', state.filename);
				scope.set('scope.lineNumber', state.lineNo);
			}
			//!steal-remove-end
			// Check the scope's cache if the evaluator already exists for performance.
			var evaluator = scope.__cache[fullExpression];
			if(mode || !evaluator) {
				evaluator = makeEvaluator( scope, mode, exprData, truthyRenderer, falseyRenderer, true);
				if(!mode) {
					scope.__cache[fullExpression] = evaluator;
				}
			}
			var gotObservableValue = evaluator[canSymbol_1_7_0_canSymbol.for("can.onValue")],
				res;

			// Run the evaluator and return the result.
			if(gotObservableValue) {
				res = canReflect_1_19_2_canReflect.getValue(evaluator);
			} else {
				res = evaluator();
			}

			if (res == null) {
				return "";
			}
			return res.nodeType === 11 ? res.textContent : ""+res;
		};

		branchRenderer.exprData = exprData;

		return branchRenderer;
	},
	// ## mustacheCore.makeLiveBindingBranchRenderer
	// Return a renderer function that evaluates the mustache expression and
	// sets up live binding if a compute with dependencies is found. Otherwise,
	// the element's value is set.
	//
	// This function works by creating a `can.compute` from the mustache expression.
	// If the compute has dependent observables, it passes the compute to `can.view.live`; otherwise,
	// it updates the element's property based on the compute's value.
	/**
	 * @hide
	 * Returns a renderer function that evaluates the mustache expression.
	 * @param {String} mode
	 * @param {can.stache.Expression} expression
	 * @param {Object} state The html state of where the expression was found.
	 */
	makeLiveBindingBranchRenderer: function(mode, expressionString, state){
		// Pre-process the expression.
		var exprData = core.expression.parse(expressionString);

		// A branching renderer takes truthy and falsey renderer.
		var branchRenderer = function branchRenderer(scope, truthyRenderer, falseyRenderer){
			// If this is within a tag, make sure we only get string values.
			var stringOnly = state.tag;
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				scope.set('scope.filename', state.filename);
				scope.set('scope.lineNumber', state.lineNo);
			}
			//!steal-remove-end

			// Get the evaluator. This does not need to be cached (probably) because if there
			// an observable value, it will be handled by `can.view.live`.
			var evaluator = makeEvaluator( scope, mode, exprData, truthyRenderer, falseyRenderer, stringOnly );

			// Create a compute that can not be observed by other
			// computes. This is important because this renderer is likely called by
			// parent expressions.  If this value changes, the parent expressions should
			// not re-evaluate. We prevent that by making sure this compute is ignored by
			// everyone else.
			//var compute = can.compute(evaluator, null, false);
			var gotObservableValue = evaluator[canSymbol_1_7_0_canSymbol.for("can.onValue")];
			var observable;
			if(gotObservableValue) {
				observable = evaluator;
			} else {
				//!steal-remove-start
				if (process.env.NODE_ENV !== 'production') {
					Object.defineProperty(evaluator,"name",{
						value: "{{"+(mode || "")+expressionString+"}}"
					});
				}
				//!steal-remove-end
				observable = new canObservation_4_2_0_canObservation(evaluator,null,{isObservable: false});
			}

			// Bind on the computeValue to set the cached value. This helps performance
			// so live binding can read a cached value instead of re-calculating.
			canReflect_1_19_2_canReflect.onValue(observable, k);

			var value = canReflect_1_19_2_canReflect.getValue(observable);

			// If value is a function and not a Lookup ({{foo}}),
			// it's a helper that returned a function and should be called.
			if(typeof value === "function" && !(exprData instanceof expression$1.Lookup)) {

				// A helper function should do it's own binding.  Similar to how
				// we prevented this function's compute from being noticed by parent expressions,
				// we hide any observables read in the function by saving any observables that
				// have been read and then setting them back which overwrites any `can.__observe` calls
				// performed in value.
				canObservationRecorder_1_3_1_canObservationRecorder.ignore(value)(this);

			}
			// If the computeValue has observable dependencies, setup live binding.
			else if( canReflect_1_19_2_canReflect.valueHasDependencies(observable) ) {
				// Depending on where the template is, setup live-binding differently.
				if(state.attr) {
					canViewLive_5_0_5_canViewLive.attr(this, state.attr, observable);
				}
				else if( state.tag )  {
					canViewLive_5_0_5_canViewLive.attrs( this, observable );
				}
				else if(state.text && !valueShouldBeInsertedAsHTML(value)) {
					//!steal-remove-start
					if (process.env.NODE_ENV !== 'production') {
						if(value !== null && typeof value === "object") {
							dev.warn("Previously, the result of "+
								expressionString+" in "+state.filename+":"+state.lineNo+
								", was being inserted as HTML instead of TEXT. Please use stache.safeString(obj) "+
								"if you would like the object to be treated as HTML.");
						}
					}
					//!steal-remove-end
					canViewLive_5_0_5_canViewLive.text(this, observable);
				} else {
					canViewLive_5_0_5_canViewLive.html(this, observable);
				}
			}
			// If the computeValue has no observable dependencies, just set the value on the element.
			else {

				if(state.attr) {
					canDomMutate_2_0_9_canDomMutate.setAttribute(this, state.attr, value);
				}
				else if(state.tag) {
					canViewLive_5_0_5_canViewLive.attrs(this, value);
				}
				else if(state.text && !valueShouldBeInsertedAsHTML(value)) {
					this.nodeValue = helpers$2.makeString(value);
				}
				else if( value != null ){
					if (typeof value[viewInsertSymbol$1] === "function") {
						var insert = value[viewInsertSymbol$1]({});
						this.parentNode.replaceChild( insert, this );
					} else {
						this.parentNode.replaceChild(canFragment_1_3_1_canFragment(value, this.ownerDocument), this);
						//domMutateNode.replaceChild.call(this.parentNode, frag(value, this.ownerDocument), this);
					}
				}
			}
			// Unbind the compute.
			canReflect_1_19_2_canReflect.offValue(observable, k);
		};

		branchRenderer.exprData = exprData;

		return branchRenderer;
	},
	// ## mustacheCore.splitModeFromExpression
	// Returns the mustache mode split from the rest of the expression.
	/**
	 * @hide
	 * Returns the mustache mode split from the rest of the expression.
	 * @param {can.stache.Expression} expression
	 * @param {Object} state The state of HTML where the expression was found.
	 */
	splitModeFromExpression: function(expression, state){
		expression = expression.trim();
		var mode = expression.charAt(0);

		if( "#/{&^>!<".indexOf(mode) >= 0 ) {
			expression =  expression.substr(1).trim();
		} else {
			mode = null;
		}
		// Triple braces do nothing within a tag.
		if(mode === "{" && state.node) {
			mode = null;
		}
		return {
			mode: mode,
			expression: expression
		};
	},
	// ## mustacheCore.cleanLineEndings
	// Removes line breaks accoding to the mustache specification.
	/**
	 * @hide
	 * Prunes line breaks accoding to the mustache specification.
	 * @param {String} template
	 * @return {String}
	 */
	cleanLineEndings: function(template){

		// Finds mustache tags with space around them or no space around them.
		return template.replace( mustacheLineBreakRegExp,
			function(whole,
				returnBefore,
				spaceBefore,
				special,
				expression,
				spaceAfter,
				returnAfter,
				// A mustache magic tag that has no space around it.
				spaceLessSpecial,
				spaceLessExpression,
				matchIndex){

			// IE 8 will provide undefined
			spaceAfter = (spaceAfter || "");
			returnBefore = (returnBefore || "");
			spaceBefore = (spaceBefore || "");

			var modeAndExpression = splitModeFromExpression(expression || spaceLessExpression,{});

			// If it's a partial or tripple stache, leave in place.
			if(spaceLessSpecial || ">{".indexOf( modeAndExpression.mode) >= 0) {
				return whole;
			}  else if( "^#!/".indexOf(  modeAndExpression.mode ) >= 0 ) {
				// Return the magic tag and a trailing linebreak if this did not
				// start a new line and there was an end line.
				// Add a normalized leading space, if there was any leading space, in case this abuts a tag name
				spaceBefore = (returnBefore + spaceBefore) && " ";
				return spaceBefore+special+( matchIndex !== 0 && returnAfter.length ? returnBefore+"\n" :"");


			} else {
				// There is no mode, return special with spaces around it.
				return spaceBefore+special+spaceAfter+(spaceBefore.length || matchIndex !== 0 ? returnBefore+"\n" : "");
			}

		});
	},
	// ## mustacheCore.cleanWhitespaceControl
	// Removes whitespace according to the whitespace control.
	/**
	 * @hide
	 * Prunes whitespace according to the whitespace control.
	 * @param {String} template
	 * @return {String}
	 */
	cleanWhitespaceControl: function(template) {
		return template.replace(mustacheWhitespaceRegExp, "$1$2");
	},
	getTemplateById: function(){}
};

// ## Local Variable Cache
//
// The following creates slightly more quickly accessible references of the following
// core functions.
var makeEvaluator = core.makeEvaluator,
	splitModeFromExpression = core.splitModeFromExpression;

var mustache_core = core;

/**
 * @module {function} can-globals/base-url/base-url base-url
 * @parent can-globals/modules
 *
 * @signature `baseUrl(optionalBaseUrlToSet)`
 *
 * Get and/or set the "base" (containing path) of the document.
 *
 * ```js
 * var baseUrl = require("can-globals/base-url/base-url");
 *
 * console.log(baseUrl());           // -> "http://localhost:8080"
 * console.log(baseUrl(baseUrl() + "/foo/bar")); // -> "http://localhost:8080/foo/bar"
 * console.log(baseUrl());           // -> "http://localhost:8080/foo/bar"
 * ```
 *
 * @param {String} setUrl An optional base url to override reading the base URL from the known path.
 *
 * @return {String} Returns the set or computed base URL
 */

canGlobals_1_2_2_canGlobalsInstance.define('base-url', function(){
	var global = canGlobals_1_2_2_canGlobalsInstance.getKeyValue('global');
	var domDocument = canGlobals_1_2_2_canGlobalsInstance.getKeyValue('document');
	if (domDocument && 'baseURI' in domDocument) {
		return domDocument.baseURI;
	} else if(global.location) {
		var href = global.location.href;
		var lastSlash = href.lastIndexOf("/");
		return lastSlash !== -1 ? href.substr(0, lastSlash) : href;
	} else if(typeof process !== "undefined") {
		return process.cwd();
	}
});

var baseUrl = canGlobals_1_2_2_canGlobalsInstance.makeExport('base-url');

/**
 * @module {function} can-parse-uri can-parse-uri
 * @parent can-js-utilities
 * @collection can-infrastructure
 * @package ./package.json
 * @signature `parseURI(url)`
 *
 * Parse a URI into its components.
 *
 * ```js
 * import {parseURI} from "can"
 * parseURI("http://foo:8080/bar.html?query#change")
 * //-> {
 * //  authority: "//foo:8080",
 * //  hash: "#change",
 * //  host: "foo:8080",
 * //  hostname: "foo",
 * //  href: "http://foo:8080/bar.html?query#change",
 * //  pathname: "/bar.html",
 * //  port: "8080",
 * //  protocol: "http:",
 * //  search: "?query"
 * // }
 * ```
 *
 * @param {String} url The URL you want to parse.
 *
 * @return {Object} Returns an object with properties for each part of the URL. `null`
 * is returned if the url can not be parsed.
 */

var canParseUri_1_2_2_canParseUri = canNamespace_1_0_0_canNamespace.parseURI = function(url){
		var m = String(url).replace(/^\s+|\s+$/g, '').match(/^([^:\/?#]+:)?(\/\/(?:[^:@]*(?::[^:@]*)?@)?(([^:\/?#]*)(?::(\d*))?))?([^?#]*)(\?[^#]*)?(#[\s\S]*)?/);
			// authority = '//' + user + ':' + pass '@' + hostname + ':' port
		return (m ? {
			href     : m[0] || '',
			protocol : m[1] || '',
			authority: m[2] || '',
			host     : m[3] || '',
			hostname : m[4] || '',
			port     : m[5] || '',
			pathname : m[6] || '',
			search   : m[7] || '',
			hash     : m[8] || ''
		} : null);
	};

var canJoinUris_1_2_0_canJoinUris = canNamespace_1_0_0_canNamespace.joinURIs = function(base, href) {
	function removeDotSegments(input) {
		var output = [];
		input.replace(/^(\.\.?(\/|$))+/, '')
			.replace(/\/(\.(\/|$))+/g, '/')
			.replace(/\/\.\.$/, '/../')
			.replace(/\/?[^\/]*/g, function (p) {
				if (p === '/..') {
					output.pop();
				} else {
					output.push(p);
				}
			});
		return output.join('').replace(/^\//, input.charAt(0) === '/' ? '/' : '');
	}

	href = canParseUri_1_2_2_canParseUri(href || '');
	base = canParseUri_1_2_2_canParseUri(base || '');

	return !href || !base ? null : (href.protocol || base.protocol) +
		(href.protocol || href.authority ? href.authority : base.authority) +
		removeDotSegments(href.protocol || href.authority || href.pathname.charAt(0) === '/' ? href.pathname : (href.pathname ? ((base.authority && !base.pathname ? '/' : '') + base.pathname.slice(0, base.pathname.lastIndexOf('/') + 1) + href.pathname) : base.pathname)) +
			(href.protocol || href.authority || href.pathname ? href.search : (href.search || base.search)) +
			href.hash;
};

function noop$1 () {}
var resolveValue = noop$1;
var evaluateArgs = noop$1;
var __testing = {};

//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	var canReflect = canReflect_1_19_2_canReflect;

	var canSymbol$1 = canSymbol_1_7_0_canSymbol;

	__testing = {
		allowDebugger: true
	};

	resolveValue = function (value) {
		if (value && value[canSymbol$1.for("can.getValue")]) {
			return canReflect.getValue(value);
		}
		return value;
	};

	evaluateArgs = function (left, right) {
		switch (arguments.length) {
			case 0: return true;
			case 1: return !!resolveValue(left);
			case 2: return resolveValue(left) === resolveValue(right);
			default:
				canLog_1_0_2_canLog.log([
					'Usage:',
					'  {{debugger}}: break any time this helper is evaluated',
					'  {{debugger condition}}: break when `condition` is truthy',
					'  {{debugger left right}}: break when `left` === `right`'
				].join('\n'));
				throw new Error('{{debugger}} must have less than three arguments');
		}
	};
}
//!steal-remove-end

function debuggerHelper (left, right) {
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		var shouldBreak = evaluateArgs.apply(null, Array.prototype.slice.call(arguments, 0, -1));
		if (!shouldBreak) {
			return;
		}

		var options = arguments[arguments.length - 1],
			scope = options && options.scope;
		var get = function (path) {
			return scope.get(path);
		};
		// This makes sure `get`, `options` and `scope` are available
		debuggerHelper._lastGet = get;

		canLog_1_0_2_canLog.log('Use `get(<path>)` to debug this template');

		var allowDebugger = __testing.allowDebugger;
		// forgotten debugger
		// jshint -W087
		if (allowDebugger) {
			debugger;
			return;
		}
		// jshint +W087
	}
	//!steal-remove-end

	canLog_1_0_2_canLog.warn('Forgotten {{debugger}} helper');
}
debuggerHelper.requiresOptionsArgument = true;

var Debugger = {
	helper: debuggerHelper,
	evaluateArgs: evaluateArgs,
	resolveValue: resolveValue,

	// used only for testing purposes
	__testing: __testing
};

var truthyObservable = function(observable){
    return new canObservation_4_2_0_canObservation(function truthyObservation(){
        var val = canReflect_1_19_2_canReflect.getValue(observable);

        return !!val;
    });
};

function makeConverter(getterSetter){
	getterSetter = getterSetter || {};
	return function(newVal, source) {
		var args = canReflect_1_19_2_canReflect.toArray(arguments);
		if(newVal instanceof setIdentifier) {
			return typeof getterSetter.set === "function" ?
				getterSetter.set.apply(this, [newVal.value].concat(args.slice(1))) :
				source(newVal.value);
		} else {
			return typeof getterSetter.get === "function" ?
				getterSetter.get.apply(this, args) :
				args[0];
		}
	};
}

var converter = makeConverter;

var bindAndRead = function (value) {
	if ( value && canReflect_1_19_2_canReflect.isValueLike(value) ) {
		canObservation_4_2_0_canObservation.temporarilyBind(value);
		return canReflect_1_19_2_canReflect.getValue(value);
	} else {
		return value;
	}
};

function forOfInteger(integer, variableName, options) {
	var result = [];
	for (var i = 0; i < integer; i++) {
		var variableScope = {};
		if(variableName !== undefined){
			variableScope[variableName] = i;
		}
		result.push(
			options.fn( options.scope
				.add({ index: i }, { special: true })
				.addLetContext(variableScope) )
		);
	}

	return options.stringOnly ? result.join('') : result;
}

function forOfObject(object, variableName, options){
	var result = [];
	canReflect_1_19_2_canReflect.each(object, function(val, key){
		// Allow key to contain a dot, for example: "My.key.has.dot"
		var value = new keyObservable(object, key.replace(/\./g, "\\."));
		var variableScope = {};
		if(variableName !== undefined){
			variableScope[variableName] = value;
		}
		result.push(
			options.fn( options.scope
				.add({ key: key }, { special: true })
				.addLetContext(variableScope) )
		);
	});

	return options.stringOnly ? result.join('') : result;
}

// this is called with the ast ... we are going to use that to our advantage.
var forHelper = function(helperOptions) {
	// lookup

	// TODO: remove in prod
	// make sure we got called with the right stuff
	if(helperOptions.exprData.argExprs.length !== 1) {
		throw new Error("for(of) broken syntax");
	}

	// TODO: check if an instance of helper;

	var helperExpr = helperOptions.exprData.argExprs[0].expr;
	var variableName, valueLookup, valueObservable;
	if(helperExpr instanceof expression_1.Lookup) {

		valueObservable = helperExpr.value(helperOptions.scope);

	} else if(helperExpr instanceof expression_1.Helper) {
		// TODO: remove in prod
		var inLookup = helperExpr.argExprs[0];
		if(inLookup.key !== "of") {
			throw new Error("for(of) broken syntax");
		}
		variableName = helperExpr.methodExpr.key;
		valueLookup = helperExpr.argExprs[1];
		valueObservable = valueLookup.value(helperOptions.scope);
	}

	var items =  valueObservable;

	var args = [].slice.call(arguments),
		options = args.pop(),
		resolved = bindAndRead(items);

	if(resolved && resolved === Math.floor(resolved)) {
		return forOfInteger(resolved, variableName, helperOptions);
	}
	if(resolved && !canReflect_1_19_2_canReflect.isListLike(resolved)) {
		return forOfObject(resolved,variableName, helperOptions);
	}
	if(options.stringOnly) {
		var parts = [];
		canReflect_1_19_2_canReflect.eachIndex(resolved, function(value, index){
			var variableScope = {};
			if(variableName !== undefined){
				variableScope[variableName] = value;
			}
			parts.push(
				helperOptions.fn( options.scope
					.add({ index: index }, { special: true })
					.addLetContext(variableScope) )
			);
		});
		return parts.join("");
	} else {
		// Tells that a helper has been called, this function should be returned through
		// checking its value.
		options.metadata.rendered = true;
		return function(el){

			var cb = function (item, index) {
				var variableScope = {};
				if(variableName !== undefined){
					variableScope[variableName] = item;
				}
				return options.fn(
					options.scope
					.add({ index: index }, { special: true })
					.addLetContext(variableScope),
					options.options
				);
			};

			canViewLive_5_0_5_canViewLive.list(el, items, cb, options.context, function(list){
				return options.inverse(options.scope, options.options);
			});
		};
	}
};
forHelper.isLiveBound = true;
forHelper.requiresOptionsArgument = true;
forHelper.ignoreArgLookup = function ignoreArgLookup(index) {
	return index === 0;
};

var ForOf = forHelper;

function isVariable(scope) {
	return scope._meta.variable === true;
}

// This sets variables so it needs to not causes changes.
var letHelper = canObservationRecorder_1_3_1_canObservationRecorder.ignore(function(options){
	if(options.isSection){
		return options.fn( options.scope.addLetContext( options.hash ) );
	}
	var variableScope = options.scope.getScope(isVariable);
	if(!variableScope) {
		throw new Error("There is no variable scope!");
	}

	canReflect_1_19_2_canReflect.assignMap(variableScope._context, options.hash);
	return document.createTextNode("");
});

var Let = letHelper;

var keepNodeSymbol = canSymbol_1_7_0_canSymbol.for("done.keepNode");

function portalHelper(elementObservable, options){
	var debugName = "portal(" + canReflect_1_19_2_canReflect.getName(elementObservable) + ")";

	function portalContents() {
		var frag = options.fn(
			options.scope
			.addLetContext({}),
			options.options
		);

		var child = frag.firstChild;
		while(child) {
			// makes sure DoneJS does not remove these nodes
			child[keepNodeSymbol] = true;
			child = child.nextSibling;
		}


		return frag;
	}

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		Object.defineProperty(portalContents,"name",{
			value: debugName+" contents"
		});
	}
	//!steal-remove-end


	// Where we are portalling
	var portalElement,
		startPortalledPlaceholder,
		endPortalledPlaceholder,
		commentPlaceholderDispose;
	function teardownPortalledContent() {

		if(portalElement) {
			canReflect_1_19_2_canReflect.offValue(elementObservable, getElementAndRender);
			portalElement = null;
		}

		if(startPortalledPlaceholder && endPortalledPlaceholder) {
			var parentNode = startPortalledPlaceholder.parentNode;
			if(parentNode) {
				helpers$2.range.remove({start: startPortalledPlaceholder, end: endPortalledPlaceholder});
				canDomMutate_2_0_9_node.removeChild.call(parentNode, startPortalledPlaceholder );
				canDomMutate_2_0_9_node.removeChild.call(parentNode, endPortalledPlaceholder );
				startPortalledPlaceholder = endPortalledPlaceholder = null;
			}
		}
	}
	function teardownEverything(){
		if(commentPlaceholderDispose) {
			commentPlaceholderDispose();
		}
		teardownPortalledContent();
	}
	// The element has changed
	function getElementAndRender() {
		// remove the old rendered content and unbind if we've bound before
		teardownPortalledContent();

		canReflect_1_19_2_canReflect.onValue(elementObservable, getElementAndRender);

		portalElement = canReflect_1_19_2_canReflect.getValue(elementObservable);

		if(portalElement) {
			startPortalledPlaceholder = portalElement.ownerDocument.createComment(debugName+" contents");
			endPortalledPlaceholder = portalElement.ownerDocument.createComment("can-end-placeholder");
			startPortalledPlaceholder[keepNodeSymbol] = true;
			endPortalledPlaceholder[keepNodeSymbol] = true;
			portalElement.appendChild(startPortalledPlaceholder);
			portalElement.appendChild(endPortalledPlaceholder);

			var observable = new canObservation_4_2_0_canObservation(portalContents, null, {isObservable: false});

			canViewLive_5_0_5_canViewLive.html(startPortalledPlaceholder, observable);
		} else {
			options.metadata.rendered = true;
		}

	}

	getElementAndRender();

	return function(placeholderElement) {
		var commentPlaceholder = placeholderElement.ownerDocument.createComment(debugName);

		placeholderElement.parentNode.replaceChild(commentPlaceholder, placeholderElement);
		commentPlaceholderDispose = canDomMutate_2_0_9_canDomMutate.onNodeRemoved(commentPlaceholder, teardownEverything);
		return commentPlaceholder;
	};
}

portalHelper.isLiveBound = true;
portalHelper.requiresOptionsArgument = true;

var Portal = portalHelper;

var debuggerHelper$1 = Debugger.helper;












var builtInHelpers = {};
var builtInConverters = {};
var converterPackages = new WeakMap();

// ## Helpers
var helpersCore = {
	looksLikeOptions: function(options){
		return options && typeof options.fn === "function" && typeof options.inverse === "function";
	},
	resolve: function(value) {
		if (value && canReflect_1_19_2_canReflect.isValueLike(value)) {
			return canReflect_1_19_2_canReflect.getValue(value);
		} else {
			return value;
		}
	},
	resolveHash: function(hash){
		var params = {};
		for(var prop in hash) {
			params[prop] = helpersCore.resolve(hash[prop]);
		}
		return params;
	},
	bindAndRead: function (value) {
		if ( value && canReflect_1_19_2_canReflect.isValueLike(value) ) {
			canObservation_4_2_0_canObservation.temporarilyBind(value);
			return canReflect_1_19_2_canReflect.getValue(value);
		} else {
			return value;
		}
	},
	registerHelper: function(name, callback){
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			if (canStacheHelpers_1_2_0_canStacheHelpers[name]) {
				dev.warn('The helper ' + name + ' has already been registered.');
			}
		}
		//!steal-remove-end

		// mark passed in helper so it will be automatically passed
		// helperOptions (.fn, .inverse, etc) when called as Call Expressions
		callback.requiresOptionsArgument = true;

		// store on global helpers list
		canStacheHelpers_1_2_0_canStacheHelpers[name] = callback;
	},
	registerHelpers: function(helpers) {
		var name, callback;
		for(name in helpers) {
			callback = helpers[name];
			helpersCore.registerHelper(name, helpersCore.makeSimpleHelper(callback));
		}
	},
	registerConverter: function(name, getterSetter) {
		helpersCore.registerHelper(name, converter(getterSetter));
	},
	makeSimpleHelper: function(fn) {
		return function() {
			var realArgs = [];
			canReflect_1_19_2_canReflect.eachIndex(arguments, function(val) {
				realArgs.push(helpersCore.resolve(val));
			});
			return fn.apply(this, realArgs);
		};
	},
	addHelper: function(name, callback) {
		if(typeof name === "object") {
			return helpersCore.registerHelpers(name);
		}
		return helpersCore.registerHelper(name, helpersCore.makeSimpleHelper(callback));
	},
	addConverter: function(name, getterSetter) {
		if(typeof name === "object") {
			if(!converterPackages.has(name)) {
				converterPackages.set(name, true);
				canReflect_1_19_2_canReflect.eachKey(name, function(getterSetter, name) {
					helpersCore.addConverter(name, getterSetter);
				});
			}
			return;
		}

		var helper = converter(getterSetter);
		helper.isLiveBound = true;
		helpersCore.registerHelper(name, helper);
	},

	// add helpers that set up their own internal live-binding
	// these helpers will not be wrapped in computes and will
	// receive observable arguments when called with Call Expressions
	addLiveHelper: function(name, callback) {
		callback.isLiveBound = true;
		return helpersCore.registerHelper(name, callback);
	},

	getHelper: function(name, scope) {
		var helper = scope && scope.getHelper(name);

		if (!helper) {
			helper = canStacheHelpers_1_2_0_canStacheHelpers[name];
		}

		return helper;
	},
	__resetHelpers: function() {
		// remove all helpers from can-stache-helpers object
		for (var helper in canStacheHelpers_1_2_0_canStacheHelpers) {
			delete canStacheHelpers_1_2_0_canStacheHelpers[helper];
		}
		// Clear converterPackages map before re-adding converters
		converterPackages.delete(builtInConverters);

		helpersCore.addBuiltInHelpers();
		helpersCore.addBuiltInConverters();
	},
	addBuiltInHelpers: function() {
		canReflect_1_19_2_canReflect.each(builtInHelpers, function(helper, helperName) {
			canStacheHelpers_1_2_0_canStacheHelpers[helperName] = helper;
		});
	},
	addBuiltInConverters: function () {
		helpersCore.addConverter(builtInConverters);
	},
	_makeLogicHelper: function(name, logic){
		var logicHelper =  canAssign_1_3_3_canAssign(function() {
			var args = Array.prototype.slice.call(arguments, 0),
				options;

			if( helpersCore.looksLikeOptions(args[args.length - 1]) ){
				options = args.pop();
			}

			function callLogic(){
				// if there are options, we want to prevent re-rendering if values are still truthy
				if(options) {
					return logic(args) ? true: false;
				} else {
					return logic(args);
				}

			}

			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				Object.defineProperty(callLogic, "name", {
					value: name+"("+args.map(function(arg){
						return canReflect_1_19_2_canReflect.getName(arg);
					}).join(",")+")",
					configurable: true
				});
			}
			//!steal-remove-end
			var callFn = new canObservation_4_2_0_canObservation(callLogic);

			if(options) {
				return callFn.get() ? options.fn() : options.inverse();
			} else {
				return callFn.get();
			}

		},{requiresOptionsArgument: true, isLiveBound: true});

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			Object.defineProperty(logicHelper, "name", {
				value: name,
				configurable: true
			});
		}
		//!steal-remove-end

		return logicHelper;
	}
};



// ## IF HELPER
var ifHelper = canAssign_1_3_3_canAssign(function ifHelper(expr, options) {
	var value;
	// if it's a function, wrap its value in a compute
	// that will only change values from true to false
	if (expr && canReflect_1_19_2_canReflect.isValueLike(expr)) {
		value = canReflect_1_19_2_canReflect.getValue(new truthyObservable(expr));
	} else {
		value = !! helpersCore.resolve(expr);
	}

	if (options) {
		return value ? options.fn(options.scope || this) : options.inverse(options.scope || this);
	}

	return !!value;
}, {requiresOptionsArgument: true, isLiveBound: true});




//## EQ/IS HELPER
var isHelper = helpersCore._makeLogicHelper("eq", function eqHelper(args){
	var curValue, lastValue;
	for (var i = 0; i < args.length; i++) {
		curValue = helpersCore.resolve(args[i]);
		curValue = typeof curValue === "function" ? curValue() : curValue;

		if (i > 0) {
			if (curValue !== lastValue) {
				return false;
			}
		}
		lastValue = curValue;
	}
	return true;
});

var andHelper = helpersCore._makeLogicHelper("and", function andHelper(args){
	if(args.length === 0 ) {
		return false;
	}
	var last;
	for (var i = 0, len = args.length; i < len; i++) {
		last = helpersCore.resolve(args[i]);
		if( !last  ) {
			return last;
		}
	}
	return last;
});

var orHelper = helpersCore._makeLogicHelper("or", function orHelper(args){
	if(args.length === 0 ) {
		return false;
	}
	var last;
	for (var i = 0, len = args.length; i < len; i++) {
		last = helpersCore.resolve(args[i]);
		if( last  ) {
			return last;
		}
	}
	return last;
});


var switchHelper = function(expression, options){
	helpersCore.resolve(expression);
	var found = false;

	var caseHelper = function(value, options) {
		if(!found && helpersCore.resolve(expression) === helpersCore.resolve(value)) {
			found = true;
			return options.fn(options.scope);
		}
	};
	caseHelper.requiresOptionsArgument = true;

	// create default helper as a value-like function
	// so that either {{#default}} or {{#default()}} will work
	var defaultHelper = function(options) {
		if (!found) {
			return options ? options.scope.peek('this') : true;
		}
	};
	defaultHelper.requiresOptionsArgument = true;
	canReflect_1_19_2_canReflect.assignSymbols(defaultHelper, {
		"can.isValueLike": true,
		"can.isFunctionLike": false,
		"can.getValue": function() {
			// pass the helperOptions passed to {{#switch}}
			return this(options);
		}
	});

	var newScope = options.scope.add({
		case: caseHelper,
		default: defaultHelper
	}, { notContext: true });

	return options.fn(newScope, options);
};
switchHelper.requiresOptionsArgument = true;


// ## ODD HELPERS

var domDataHelper = function(attr, value) {
	var data = (helpersCore.looksLikeOptions(value) ? value.context : value) || this;
	return function setDomData(el) {
		canDomData_1_0_3_canDomData.set( el, attr, data );
	};
};

var joinBaseHelper = function(firstExpr/* , expr... */){
	var args = [].slice.call(arguments);
	var options = args.pop();

	var moduleReference = args.map( function(expr){
		var value = helpersCore.resolve(expr);
		return typeof value === "function" ? value() : value;
	}).join("");

	var templateModule = canReflect_1_19_2_canReflect.getKeyValue(options.scope.templateContext.helpers, 'module');
	var parentAddress = templateModule ? templateModule.uri: undefined;

	var isRelative = moduleReference[0] === ".";

	if(isRelative && parentAddress) {
		return canJoinUris_1_2_0_canJoinUris(parentAddress, moduleReference);
	} else {
		var baseURL = (typeof System !== "undefined" &&
			(System.renderingBaseURL || System.baseURL)) ||	baseUrl();

		// Make sure one of them has a needed /
		if(moduleReference[0] !== "/" && baseURL[baseURL.length - 1] !== "/") {
			baseURL += "/";
		}

		return canJoinUris_1_2_0_canJoinUris(baseURL, moduleReference);
	}
};
joinBaseHelper.requiresOptionsArgument = true;

// ## LEGACY HELPERS

// ### each
var eachHelper = function(items) {
	var args = [].slice.call(arguments),
		options = args.pop(),
		hashExprs = options.exprData.hashExprs,
		resolved = helpersCore.bindAndRead(items),
		hashOptions,
		aliases;

	// Check if using hash
	if (canReflect_1_19_2_canReflect.size(hashExprs) > 0) {
		hashOptions = {};
		canReflect_1_19_2_canReflect.eachKey(hashExprs, function (exprs, key) {
			hashOptions[exprs.key] = key;
		});
	}

	if ((
		canReflect_1_19_2_canReflect.isObservableLike(resolved) && canReflect_1_19_2_canReflect.isListLike(resolved) ||
			( canReflect_1_19_2_canReflect.isListLike(resolved) && canReflect_1_19_2_canReflect.isValueLike(items) )
	) && !options.stringOnly) {
		// Tells that a helper has been called, this function should be returned through
		// checking its value.
		options.metadata.rendered = true;
		return function(el){
			var cb = function (item, index) {
				var aliases = {};

				if (canReflect_1_19_2_canReflect.size(hashOptions) > 0) {
					if (hashOptions.value) {
						aliases[hashOptions.value] = item;
					}
					if (hashOptions.index) {
						aliases[hashOptions.index] = index;
					}
				}

				return options.fn(
					options.scope
					.add(aliases, { notContext: true })
					.add({ index: index }, { special: true })
					.add(item),
				options.options
				);
			};

			canViewLive_5_0_5_canViewLive.list(el, items, cb, options.context , function(list){
				return options.inverse(options.scope.add(list), options.options);
			});
		};
	}

	var expr = helpersCore.resolve(items),
		result;

	if (!!expr && canReflect_1_19_2_canReflect.isListLike(expr)) {
		result = utils$1.getItemsFragContent(expr, options, options.scope);
		return options.stringOnly ? result.join('') : result;
	} else if (canReflect_1_19_2_canReflect.isObservableLike(expr) && canReflect_1_19_2_canReflect.isMapLike(expr) || expr instanceof Object) {
		result = [];
		canReflect_1_19_2_canReflect.each(expr, function(val, key){
			var value = new keyObservable(expr, key);
			aliases = {};

			if (canReflect_1_19_2_canReflect.size(hashOptions) > 0) {
				if (hashOptions.value) {
					aliases[hashOptions.value] = value;
				}
				if (hashOptions.key) {
					aliases[hashOptions.key] = key;
				}
			}
			result.push(options.fn(
				options.scope
				.add(aliases, { notContext: true })
				.add({ key: key }, { special: true })
				.add(value)
			));
		});

		return options.stringOnly ? result.join('') : result;
	}
};
eachHelper.isLiveBound = true;
eachHelper.requiresOptionsArgument = true;
eachHelper.ignoreArgLookup = function ignoreArgLookup(index) {
	return index === 1;
};

// ### index
// This is legacy for `{{index(5)}}`
var indexHelper = canAssign_1_3_3_canAssign(function indexHelper(offset, options) {
	if (!options) {
		options = offset;
		offset = 0;
	}
	var index = options.scope.peek("scope.index");
	return ""+((typeof(index) === "function" ? index() : index) + offset);
}, {requiresOptionsArgument: true});

// ### WITH HELPER
var withHelper = function (expr, options) {
	var ctx = expr;
	if(!options) {
		// hash-only case if no current context expression
		options = expr;
		expr = true;
		ctx = options.hash;
	} else {
		expr = helpersCore.resolve(expr);
		if(options.hash && canReflect_1_19_2_canReflect.size(options.hash) > 0) {
			// presumably rare case of both a context object AND hash keys
			// Leaving it undocumented for now, but no reason not to support it.
			ctx = options.scope.add(options.hash, { notContext: true }).add(ctx);
		}
	}
	return options.fn(ctx || {});
};
withHelper.requiresOptionsArgument = true;

// ### data helper
var dataHelper = function(attr, value) {
	var data = (helpersCore.looksLikeOptions(value) ? value.context : value) || this;
	return function setData(el) {
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			dev.warn('The {{data}} helper has been deprecated; use {{domData}} instead: https://canjs.com/doc/can-stache.helpers.domData.html');
		}
		//!steal-remove-end
		canDomData_1_0_3_canDomData.set( el, attr, data );
	};
};

// ## UNLESS HELPER
var unlessHelper = function (expr, options) {
	if(!options) {
		return !ifHelper.apply(this, [expr]);
	}
	return ifHelper.apply(this, [expr, canAssign_1_3_3_canAssign(canAssign_1_3_3_canAssign({}, options), {
		fn: options.inverse,
		inverse: options.fn
	})]);
};
unlessHelper.requiresOptionsArgument = true;
unlessHelper.isLiveBound = true;


// ## Converters
// ## NOT converter
var notConverter = {
	get: function(obs, options){
		if(helpersCore.looksLikeOptions(options)) {
			return canReflect_1_19_2_canReflect.getValue(obs) ? options.inverse() : options.fn();
		} else {
			return !canReflect_1_19_2_canReflect.getValue(obs);
		}
	},
	set: function(newVal, obs){
		canReflect_1_19_2_canReflect.setValue(obs, !newVal);
	}
};

// ## Register as defaults

canAssign_1_3_3_canAssign(builtInHelpers, {
	'debugger': debuggerHelper$1,
	each: eachHelper,
	eachOf: eachHelper,
	index: indexHelper,
	'if': ifHelper,
	is: isHelper,
	eq: isHelper,
	unless: unlessHelper,
	'with': withHelper,
	console: console,
	data: dataHelper,
	domData: domDataHelper,
	'switch': switchHelper,
	joinBase: joinBaseHelper,
	and: andHelper,
	or: orHelper,
	'let': Let,
	'for': ForOf,
	portal: Portal
});

canAssign_1_3_3_canAssign(builtInConverters, {
	'not': notConverter
});

// add all the built-in helpers when stache is loaded
helpersCore.addBuiltInHelpers();
helpersCore.addBuiltInConverters();

var core$1 = helpersCore;

var mustacheLineBreakRegExp$1 = /(?:(^|\r?\n)(\s*)(\{\{([\s\S]*)\}\}\}?)([^\S\n\r]*)($|\r?\n))|(\{\{([\s\S]*)\}\}\}?)/g,
	mustacheWhitespaceRegExp$1 = /(\s*)(\{\{\{?)(-?)([\s\S]*?)(-?)(\}\}\}?)(\s*)/g;

function splitModeFromExpression$1(expression, state){
	expression = expression.trim();
	var mode = expression.charAt(0);

	if( "#/{&^>!<".indexOf(mode) >= 0 ) {
		expression =  expression.substr(1).trim();
	} else {
		mode = null;
	}
	// Triple braces do nothing within a tag.
	if(mode === "{" && state.node) {
		mode = null;
	}
	return {
		mode: mode,
		expression: expression
	};
}

function cleanLineEndings(template) {
		// Finds mustache tags with space around them or no space around them.
		return template.replace( mustacheLineBreakRegExp$1,
			function(whole,
				returnBefore,
				spaceBefore,
				special,
				expression,
				spaceAfter,
				returnAfter,
				// A mustache magic tag that has no space around it.
				spaceLessSpecial,
				spaceLessExpression,
				matchIndex){

			// IE 8 will provide undefined
			spaceAfter = (spaceAfter || "");
			returnBefore = (returnBefore || "");
			spaceBefore = (spaceBefore || "");

			var modeAndExpression = splitModeFromExpression$1(expression || spaceLessExpression,{});

			// If it's a partial or tripple stache, leave in place.
			if(spaceLessSpecial || ">{".indexOf( modeAndExpression.mode) >= 0) {
				return whole;
			}  else if( "^#!/".indexOf(  modeAndExpression.mode ) >= 0 ) {
				// Return the magic tag and a trailing linebreak if this did not
				// start a new line and there was an end line.
				// Add a normalized leading space, if there was any leading space, in case this abuts a tag name
				spaceBefore = (returnBefore + spaceBefore) && " ";
				return spaceBefore+special+( matchIndex !== 0 && returnAfter.length ? returnBefore+"\n" :"");


			} else {
				// There is no mode, return special with spaces around it.
				return spaceBefore+special+spaceAfter+(spaceBefore.length || matchIndex !== 0 ? returnBefore+"\n" : "");
			}
		});
}

function whiteSpaceReplacement(
	whole,
	spaceBefore,
	bracketBefore,
	controlBefore,
	expression,
	controlAfter,
	bracketAfter,
	spaceAfter
) {

	if (controlBefore === '-') {
		spaceBefore = '';
	}

	if (controlAfter === '-') {
		spaceAfter = '';
	}

	return spaceBefore + bracketBefore + expression + bracketAfter + spaceAfter;
}

function cleanWhitespaceControl(template) {
	return template.replace(mustacheWhitespaceRegExp$1, whiteSpaceReplacement);
}

var cleanLineEndings_1 = cleanLineEndings;
var cleanWhitespaceControl_1 = cleanWhitespaceControl;

var canStacheAst_1_1_0_controls = {
	cleanLineEndings: cleanLineEndings_1,
	cleanWhitespaceControl: cleanWhitespaceControl_1
};

var parse = function(filename, source){
	if (arguments.length === 1) {
		source = arguments[0];
		filename = undefined;
	}

	var template = source;
	template = canStacheAst_1_1_0_controls.cleanWhitespaceControl(template);
	template = canStacheAst_1_1_0_controls.cleanLineEndings(template);

	var imports = [],
		dynamicImports = [],
		importDeclarations = [],
		ases = {},
		attributes = new Map(),
		inImport = false,
		inFrom = false,
		inAs = false,
		isUnary = false,
		importIsDynamic = false,
		currentAs = "",
		currentFrom = "",
		currentAttrName = null;

	function processImport(line) {
		if(currentAs) {
			ases[currentAs] = currentFrom;
			currentAs = "";
		}
		if(importIsDynamic) {
			dynamicImports.push(currentFrom);
		} else {
			imports.push(currentFrom);
		}
		importDeclarations.push({
			specifier: currentFrom,
			loc: {
				line: line
			},
			attributes: attributes
		});

		// Reset this scope value so that the next import gets new attributes.
		attributes = new Map();
	}

	var program = canViewParser_4_1_3_canViewParser(template, {
		filename: filename,
		start: function( tagName, unary ){
			if(tagName === "can-import") {
				isUnary = unary;
				importIsDynamic = false; // assume static import unless there is content (chars/tags/special).
				inImport = true;
			} else if(tagName === "can-dynamic-import") {
				isUnary = unary;
				importIsDynamic = true;
				inImport = true;
			} else if(inImport) {
				importIsDynamic = true;  // found content inside can-import tag.
				inImport = false;
			}
		},
		attrStart: function( attrName ){
			currentAttrName = attrName;
			// Default to a boolean attribute, the attrValue hook will replace that.
			attributes.set(currentAttrName, true);

			if(attrName === "from") {
				inFrom = true;
			} else if(attrName === "as" || attrName === "export-as") {
				inAs = true;
			}
		},
		attrEnd: function( attrName ){
			if(attrName === "from") {
				inFrom = false;
			} else if(attrName === "as" || attrName === "export-as") {
				inAs = false;
			}
		},
		attrValue: function( value ){
			if(inImport) {
				attributes.set(currentAttrName, value);
			}
			if(inFrom && inImport) {
				currentFrom = value;
			} else if(inAs && inImport) {
				currentAs = value;
			}
		},
		end: function(tagName, unary, line){
			if((tagName === "can-import" || tagName === "can-dynamic-import") && isUnary) {
				processImport(line);
			}
		},
		close: function(tagName, unary, line){
			if((tagName === "can-import" || tagName === "can-dynamic-import")) {
				processImport(line);
			}
		},
		chars: function(text) {
			if(text.trim().length > 0) {
				importIsDynamic = true;
			}
		},
		special: function() {
			importIsDynamic = true;
		}
	}, true);

	return {
		intermediate: program,
		program: program,
		imports: imports,
		dynamicImports: dynamicImports,
		importDeclarations: importDeclarations,
		ases: ases,
		exports: ases
	};
};

var canStacheAst_1_1_0_canStacheAst = {
	parse: parse
};

var global$2 = global_1();

var stealOptimized = function(moduleName, parentName){
	if (typeof global$2.stealRequire !== "undefined") {
		return steal.import(moduleName, { name: parentName });
	}
};

var global$3 = global_1();

function isFunction$1(fn) {
	return typeof fn === "function";
}
// since stealJS uses a SystemJS fork and SystemJS is exposed globally we can use this loader for SystemJS or stealJS
var system = function(moduleName, parentName) {
	if(typeof global$3.System === "object" && isFunction$1(global$3.System["import"])) {
		return global$3.System["import"](moduleName, {
			name: parentName
		});
	}
};

var es6 = createCommonjsModule(function (module) {
// check for `noModule` in HTMLScriptElement. if its present, then the browser can handle dynamic loading because if
// HTMLScriptElement.noModule is `true` the browser used to run fallback scripts in older browsers that do not support JavaScript modules
if ("HTMLScriptElement" in global_1() && "noModule" in HTMLScriptElement.prototype) {
	// "import()" is a syntax error on some platforms and will cause issues if this module is bundled
	//  into a larger script bundle, so only eval it to code if the platform is known to support it.
	module.exports = new Function(
		"moduleName",
		// if moduleName has no extension, treat it as a javascript file and add .js extension
		"if (!(moduleName.match(/[^\\\\\\/]\\.([^.\\\\\\/]+)$/) || [null]).pop()) {\n" +
			"moduleName += '.js';\n" +
		"}\n" +
		"return import(moduleName.replace(/['\"]+/g, ''));\n"
	);
} else {
	module.exports = function() {};
}
});

var node$1 = function(moduleName) {
	if (isNode()) {
		return Promise.resolve(commonjsRequire(moduleName));
	}
};

var global$4 = global_1();

// AMD loader
var require = function(moduleName){
	if(global$4.define && global$4.define.amd){
		return new Promise(function(resolve, reject) {
			global$4.require([moduleName], function(value){
				resolve(value);
			});
		});
	}
};

/**
 * @module {function} can-util/js/import/import import
 * @parent can-util/js
 * @signature `importModule(moduleName, parentName)`
 * @hide
 *
 * ```js
 * var importModule = require("can-util/js/import/import");
 *
 * importModule("foo.stache").then(function(){
 *   // module was imported
 * });
 * ```
 *
 * @param {String} moduleName The module to be imported.
 * @param {String} [parentName] A parent module that will be used as a reference for resolving relative module imports.
 * @return {Promise} A Promise that will resolve when the module has been imported.
 */

// array of loader functions, last in first out
var loader = [];

/**
 * add a loader-function to the list of loader
 * the function should return a promise that resolves when the module has been loaded
 * otherwise the loader function should return null or undefined
 * 
 * @signature `import.addLoader(loader)`
 * @param fn callable
 */
function addLoader(fn){
	if(typeof fn === "function"){
		loader.push(fn);
	}
}

/**
 * clear the list of loaders
 */
function flushLoader(){
	loader = [];
}

/**
 * a bunch of presets that can be used in a certain environment 
 * 
 * @param preset string
 */
function preset(preset){
	flushLoader();
	
	switch (preset){
		case "stealjs":
			addLoader(stealOptimized);
			addLoader(system);
			break;
		case "ES2020":
		case "es2020":
		case "dynamic-import":
			addLoader(es6);
			break;
		case "node":
			addLoader(node$1);
			break;
		case "all":
		default:
			addLoader(stealOptimized);
			addLoader(es6);
			addLoader(node$1);
			addLoader(require);
			addLoader(system);
			break;
	}
}

// by default, add all available loaders to the list
preset('all');

var canImportModule_1_3_2_canImportModule = canNamespace_1_0_0_canNamespace.import = function(moduleName, parentName) {
	return new Promise(function(resolve, reject) {
		try {
			var loaderPromise;
			// last added loader will be called first
			for (var i = loader.length - 1; i >= 0; i--) {
				loaderPromise = loader[i](moduleName, parentName);
				if (loaderPromise) {
					break;
				}
			}

			if(loaderPromise){
				loaderPromise.then(resolve, reject);
			}else{
				reject("no proper module-loader available");
			}
		} catch(err) {
			reject(err);
		}
	});
};
var addLoader_1 = addLoader;
var flushLoader_1 = flushLoader;
var preset_1 = preset;
canImportModule_1_3_2_canImportModule.addLoader = addLoader_1;
canImportModule_1_3_2_canImportModule.flushLoader = flushLoader_1;
canImportModule_1_3_2_canImportModule.preset = preset_1;

/* jshint undef: false */








var getIntermediateAndImports = canStacheAst_1_1_0_canStacheAst.parse;

var makeRendererConvertScopes = utils$1.makeRendererConvertScopes;
var last$2 = utils$1.last;












// Make sure that we can also use our modules with Stache as a plugin




if(!canViewCallbacks_5_0_0_canViewCallbacks.tag("content")) {
	// This was moved from the legacy view/scanner.js to here.
	// This makes sure content elements will be able to have a callback.
	canViewCallbacks_5_0_0_canViewCallbacks.tag("content", function(el, tagData) {
		return tagData.scope;
	});
}

var isViewSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.isView");

var wrappedAttrPattern = /[{(].*[)}]/;
var colonWrappedAttrPattern = /^on:|(:to|:from|:bind)$|.*:to:on:.*/;
var svgNamespace = "http://www.w3.org/2000/svg",
xmlnsAttrNamespaceURI$1 = "http://www.w3.org/2000/xmlns/",
xlinkHrefAttrNamespaceURI$1 =  "http://www.w3.org/1999/xlink";
var namespaces = {
	"svg": svgNamespace,
	// this allows a partial to start with g.
	"g": svgNamespace,
	"defs": svgNamespace,
	"path": svgNamespace,
	"filter": svgNamespace,
	"feMorphology": svgNamespace,
	"feGaussianBlur": svgNamespace,
	"feOffset": svgNamespace,
	"feComposite": svgNamespace,
	"feColorMatrix": svgNamespace,
	"use": svgNamespace
},
	attrsNamespacesURI$1 = {
		'xmlns': xmlnsAttrNamespaceURI$1,
		'xlink:href': xlinkHrefAttrNamespaceURI$1
	},
	textContentOnlyTag = {style: true, script: true};

function stache (filename, template) {
	if (arguments.length === 1) {
		template = arguments[0];
		filename = undefined;
	}

	var inlinePartials = {};

	// Remove line breaks according to mustache's specs.
	if(typeof template === "string") {
		template = mustache_core.cleanWhitespaceControl(template);
		template = mustache_core.cleanLineEndings(template);
	}

	// The HTML section that is the root section for the entire template.
	var section = new html_section(filename),
		// Tracks the state of the parser.
		state = {
			node: null,
			attr: null,
			// A stack of which node / section we are in.
			// There is probably a better way of doing this.
			sectionElementStack: [],
			// If text should be inserted and HTML escaped
			text: false,
			// which namespace we are in
			namespaceStack: [],
			// for style and script tags
			// we create a special TextSectionBuilder and add things to that
			// when the element is done, we compile the text section and
			// add it as a callback to `section`.
			textContentOnly: null

		},

		// This function is a catch all for taking a section and figuring out
		// how to create a "renderer" that handles the functionality for a
		// given section and modify the section to use that renderer.
		// For example, if an HTMLSection is passed with mode `#` it knows to
		// create a liveBindingBranchRenderer and pass that to section.add.
		// jshint maxdepth:5
		makeRendererAndUpdateSection = function(section, mode, stache, lineNo){

			if(mode === ">") {
				// Partials use liveBindingPartialRenderers
				section.add(mustache_core.makeLiveBindingPartialRenderer(stache, copyState({ filename: section.filename, lineNo: lineNo })));

			} else if(mode === "/") {

				var createdSection = section.last();
				if ( createdSection.startedWith === "<" ) {
					inlinePartials[ stache ] = section.endSubSectionAndReturnRenderer();
					// Remove *TWO* nodes because we now have a start and an end comment for the section....
					section.removeCurrentNode();
					section.removeCurrentNode();
				} else {
					section.endSection();
				}

				// to avoid "Blocks are nested too deeply" when linting
				//!steal-remove-start
				if (process.env.NODE_ENV !== 'production') {
					if(section instanceof html_section) {
						var last = state.sectionElementStack[state.sectionElementStack.length - 1];
						if (last.tag && last.type === "section" && stache !== "" && stache !== last.tag) {
							if (filename) {
								dev.warn(filename + ":" + lineNo + ": unexpected closing tag {{/" + stache + "}} expected {{/" + last.tag + "}}");
							}
							else {
								dev.warn(lineNo + ": unexpected closing tag {{/" + stache + "}} expected {{/" + last.tag + "}}");
							}
						}
					}
				}
				//!steal-remove-end

				if(section instanceof html_section) {
					state.sectionElementStack.pop();
				}
			} else if(mode === "else") {

				section.inverse();

			} else {

				// If we are an HTMLSection, we will generate a
				// a LiveBindingBranchRenderer; otherwise, a StringBranchRenderer.
				// A LiveBindingBranchRenderer function processes
				// the mustache text, and sets up live binding if an observable is read.
				// A StringBranchRenderer function processes the mustache text and returns a
				// text value.
				var makeRenderer = section instanceof html_section ?
					mustache_core.makeLiveBindingBranchRenderer:
					mustache_core.makeStringBranchRenderer;

				if(mode === "{" || mode === "&") {

					// Adds a renderer function that just reads a value or calls a helper.
					section.add(makeRenderer(null,stache, copyState({ filename: section.filename, lineNo: lineNo })));

				} else if(mode === "#" || mode === "^" || mode === "<") {
					// Adds a renderer function and starts a section.
					var renderer = makeRenderer(mode, stache, copyState({ filename: section.filename, lineNo: lineNo }));
					var sectionItem = {
						type: "section"
					};
					section.startSection(renderer, stache);
					section.last().startedWith = mode;

					// If we are a directly nested section, count how many we are within
					if(section instanceof html_section) {
						//!steal-remove-start
						if (process.env.NODE_ENV !== 'production') {
							var tag = typeof renderer.exprData.closingTag === 'function' ?
								renderer.exprData.closingTag() : stache;
							sectionItem.tag = tag;
						}
						//!steal-remove-end

						state.sectionElementStack.push(sectionItem);
					}
				} else {
					// Adds a renderer function that only updates text.
					section.add(makeRenderer(null, stache, copyState({text: true, filename: section.filename, lineNo: lineNo })));
				}

			}
		},
		isDirectlyNested = function() {
			var lastElement = state.sectionElementStack[state.sectionElementStack.length - 1];
			return state.sectionElementStack.length ?
				lastElement.type === "section" || lastElement.type === "custom": true;
		},
		// Copys the state object for use in renderers.
		copyState = function(overwrites){

			var cur = {
				tag: state.node && state.node.tag,
				attr: state.attr && state.attr.name,
				// <content> elements should be considered direclty nested
				directlyNested: isDirectlyNested(),
				textContentOnly: !!state.textContentOnly
			};
			return overwrites ? canAssign_1_3_3_canAssign(cur, overwrites) : cur;
		},
		addAttributesCallback = function(node, callback){
			if( !node.attributes ) {
				node.attributes = [];
			}
			node.attributes.unshift(callback);
		};

	canViewParser_4_1_3_canViewParser(template, {
		filename: filename,
		start: function(tagName, unary, lineNo){
			var matchedNamespace = namespaces[tagName];

			if (matchedNamespace && !unary ) {
				state.namespaceStack.push(matchedNamespace);
			}

			// either add templates: {} here or check below and decorate
			// walk up the stack/targetStack until you find the first node
			// with a templates property, and add the popped renderer
			state.node = {
				tag: tagName,
				children: [],
				namespace: matchedNamespace || last$2(state.namespaceStack)
			};
		},
		end: function(tagName, unary, lineNo){
			var isCustomTag =  canViewCallbacks_5_0_0_canViewCallbacks.tag(tagName);
			var directlyNested = isDirectlyNested();
			if(unary){
				// If it's a custom tag with content, we need a section renderer.
				section.add(state.node);
				if(isCustomTag) {
					// Call directlyNested now as it's stateful.
					addAttributesCallback(state.node, function(scope){
						//!steal-remove-start
						if (process.env.NODE_ENV !== 'production') {
							scope.set('scope.lineNumber', lineNo);
						}
						//!steal-remove-end
						canViewCallbacks_5_0_0_canViewCallbacks.tagHandler(this,tagName, {
							scope: scope,
							subtemplate: null,
							templateType: "stache",
							directlyNested: directlyNested
						});
					});
				}
			} else {
				section.push(state.node);

				state.sectionElementStack.push({
					type: isCustomTag ? "custom" : null,
					tag: isCustomTag ? null : tagName,
					templates: {},
					directlyNested: directlyNested
				});

				// If it's a custom tag with content, we need a section renderer.
				if( isCustomTag ) {
					section.startSubSection();
				} else if(textContentOnlyTag[tagName]) {
					state.textContentOnly = new text_section(filename);
				}
			}


			state.node =null;

		},
		close: function(tagName, lineNo) {
			var matchedNamespace = namespaces[tagName];

			if (matchedNamespace  ) {
				state.namespaceStack.pop();
			}

			var isCustomTag = canViewCallbacks_5_0_0_canViewCallbacks.tag(tagName),
				renderer;

			if( isCustomTag ) {
				renderer = section.endSubSectionAndReturnRenderer();
			}

			if(textContentOnlyTag[tagName]) {
				section.last().add(state.textContentOnly.compile(copyState()));
				state.textContentOnly = null;
			}

			var oldNode = section.pop();
			if( isCustomTag ) {
				if (tagName === "can-template") {
					// If we find a can-template we want to go back 2 in the stack to get it's inner content
					// rather than the <can-template> element itself
					var parent = state.sectionElementStack[state.sectionElementStack.length - 2];
					if (renderer) {// Only add the renderer if the template has content
						parent.templates[oldNode.attrs.name] = makeRendererConvertScopes(renderer);
					}
					section.removeCurrentNode();
				} else {
					// Get the last element in the stack
					var current = state.sectionElementStack[state.sectionElementStack.length - 1];
					addAttributesCallback(oldNode, function(scope){
						//!steal-remove-start
						if (process.env.NODE_ENV !== 'production') {
							scope.set('scope.lineNumber', lineNo);
						}
						//!steal-remove-end
						canViewCallbacks_5_0_0_canViewCallbacks.tagHandler(this,tagName, {
							scope: scope,
							subtemplate: renderer  ? makeRendererConvertScopes(renderer) : renderer,
							templateType: "stache",
							templates: current.templates,
							directlyNested: current.directlyNested
						});
					});
				}
			}
			state.sectionElementStack.pop();
		},
		attrStart: function(attrName, lineNo){
			if(state.node.section) {
				state.node.section.add(attrName+"=\"");
			} else {
				state.attr = {
					name: attrName,
					value: ""
				};
			}

		},
		attrEnd: function(attrName, lineNo){
			var matchedAttrNamespacesURI = attrsNamespacesURI$1[attrName];
			if(state.node.section) {
				state.node.section.add("\" ");
			} else {
				if(!state.node.attrs) {
					state.node.attrs = {};
				}

				if (state.attr.section) {
					state.node.attrs[state.attr.name] = state.attr.section.compile(copyState());
				} else if (matchedAttrNamespacesURI) {
					state.node.attrs[state.attr.name] = {
						value: state.attr.value,
						namespaceURI: attrsNamespacesURI$1[attrName]
					};
				} else {
					state.node.attrs[state.attr.name] = state.attr.value;
				}

				var attrCallback = canViewCallbacks_5_0_0_canViewCallbacks.attr(attrName);

				//!steal-remove-start
				if (process.env.NODE_ENV !== 'production') {
					var decodedAttrName = canAttributeEncoder_1_1_4_canAttributeEncoder.decode(attrName);
					var weirdAttribute = !!wrappedAttrPattern.test(decodedAttrName) || !!colonWrappedAttrPattern.test(decodedAttrName);
					if (weirdAttribute && !attrCallback) {
						dev.warn("unknown attribute binding " + decodedAttrName + ". Is can-stache-bindings imported?");
					}
				}
				//!steal-remove-end

				if(attrCallback) {
					if( !state.node.attributes ) {
						state.node.attributes = [];
					}
					state.node.attributes.push(function(scope){
						//!steal-remove-start
						if (process.env.NODE_ENV !== 'production') {
							scope.set('scope.lineNumber', lineNo);
						}
						//!steal-remove-end
						attrCallback(this,{
							attributeName: attrName,
							scope: scope
						});
					});
				}

				state.attr = null;
			}
		},
		attrValue: function(value, lineNo){
			var section = state.node.section || state.attr.section;
			if(section){
				section.add(value);
			} else {
				state.attr.value += value;
			}
		},
		chars: function(text, lineNo) {
			(state.textContentOnly || section).add(text);
		},
		special: function(text, lineNo){
			var firstAndText = mustache_core.splitModeFromExpression(text, state),
				mode = firstAndText.mode,
				expression = firstAndText.expression;


			if(expression === "else") {
				var inverseSection;
				if(state.attr && state.attr.section) {
					inverseSection = state.attr.section;
				} else if(state.node && state.node.section ) {
					inverseSection = state.node.section;
				} else {
					inverseSection = state.textContentOnly || section;
				}
				inverseSection.inverse();
				return;
			}

			if(mode === "!") {
				return;
			}

			if(state.node && state.node.section) {

				makeRendererAndUpdateSection(state.node.section, mode, expression, lineNo);

				if(state.node.section.subSectionDepth() === 0){
					state.node.attributes.push( state.node.section.compile(copyState()) );
					delete state.node.section;
				}

			}
			// `{{}}` in an attribute like `class="{{}}"`
			else if(state.attr) {

				if(!state.attr.section) {
					state.attr.section = new text_section(filename);
					if(state.attr.value) {
						state.attr.section.add(state.attr.value);
					}
				}
				makeRendererAndUpdateSection(state.attr.section, mode, expression, lineNo);

			}
			// `{{}}` in a tag like `<div {{}}>`
			else if(state.node) {

				if(!state.node.attributes) {
					state.node.attributes = [];
				}
				if(!mode) {
					state.node.attributes.push(mustache_core.makeLiveBindingBranchRenderer(null, expression, copyState({ filename: section.filename, lineNo: lineNo })));
				} else if( mode === "#" || mode === "^" ) {
					if(!state.node.section) {
						state.node.section = new text_section(filename);
					}
					makeRendererAndUpdateSection(state.node.section, mode, expression, lineNo);
				} else {
					throw new Error(mode+" is currently not supported within a tag.");
				}
			}
			else {
				makeRendererAndUpdateSection(state.textContentOnly || section, mode, expression, lineNo);
			}
		},
		comment: function(text) {
			// create comment node
			section.add({
				comment: text
			});
		},
		done: function(lineNo){
			//!steal-remove-start
			// warn if closing magic tag is missed #675
			if (process.env.NODE_ENV !== 'production') {
				var last = state.sectionElementStack[state.sectionElementStack.length - 1];
				if (last && last.tag && last.type === "section") {
					if (filename) {
						dev.warn(filename + ":" + lineNo + ": closing tag {{/" + last.tag + "}} was expected");
					}
					else {
						dev.warn(lineNo + ": closing tag {{/" + last.tag + "}} was expected");
					}
				}
			}
			//!steal-remove-end
		}
	});

	var renderer = section.compile();

	var scopifiedRenderer = canObservationRecorder_1_3_1_canObservationRecorder.ignore(function(scope, options){
		// if an object is passed to options, assume it is the helpers object
		if (options && !options.helpers && !options.partials && !options.tags) {
			options = {
				helpers: options
			};
		}
		// mark passed in helper so they will be automatically passed
		// helperOptions (.fn, .inverse, etc) when called as Call Expressions
		canReflect_1_19_2_canReflect.eachKey(options && options.helpers, function(helperValue) {
			helperValue.requiresOptionsArgument = true;
		});

		// helpers, partials, tags, vars
		var templateContext = new canViewScope_4_13_7_templateContext(options);

		// copy inline partials over
		canReflect_1_19_2_canReflect.eachKey(inlinePartials, function(partial, partialName) {
			canReflect_1_19_2_canReflect.setKeyValue(templateContext.partials, partialName, partial);
		});

		// allow the current renderer to be called with {{>scope.view}}
		canReflect_1_19_2_canReflect.setKeyValue(templateContext, 'view', scopifiedRenderer);
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			canReflect_1_19_2_canReflect.setKeyValue(templateContext, 'filename', section.filename);
		}
		//!steal-remove-end


		// now figure out the final structure ...
		if ( !(scope instanceof canViewScope_4_13_7_canViewScope) ) {
			scope = new canViewScope_4_13_7_canViewScope(templateContext).add(scope);
		} else {
			// we are going to split ...
			var templateContextScope = new canViewScope_4_13_7_canViewScope(templateContext);
			templateContextScope._parent = scope._parent;
			scope._parent = templateContextScope;
		}

		return renderer(scope.addLetContext());
	});

	// Identify is a view type
	scopifiedRenderer[isViewSymbol$2] = true;

	return scopifiedRenderer;
}

// At this point, can.stache has been created
canAssign_1_3_3_canAssign(stache, core$1);

stache.safeString = function(text){

	return canReflect_1_19_2_canReflect.assignSymbols({},{
		"can.toDOM": function(){
			return text;
		}
	});
};
stache.async = function(source){
	var iAi = getIntermediateAndImports(source);
	var importPromises = iAi.imports.map(function(moduleName){
		return canImportModule_1_3_2_canImportModule(moduleName);
	});
	return Promise.all(importPromises).then(function(){
		return stache(iAi.intermediate);
	});
};
var templates = {};
stache.from = mustache_core.getTemplateById = function(id){
	if(!templates[id]) {
		var el = document$1().getElementById(id);
		if(el) {
			templates[id] = stache("#" + id, el.innerHTML);
		}
	}
	return templates[id];
};

stache.registerPartial = function(id, partial) {
	templates[id] = (typeof partial === "string" ? stache(partial) : partial);
};

stache.addBindings = canViewCallbacks_5_0_0_canViewCallbacks.attrs;

var canStache_5_1_1_canStache = canNamespace_1_0_0_canNamespace.stache = stache;

var viewModelSymbol = canSymbol_1_7_0_canSymbol.for('can.viewModel');

var canViewModel_4_0_3_canViewModel = canNamespace_1_0_0_canNamespace.viewModel = function (el, attr, val) {
	if (typeof el === "string") {
		el = document$1().querySelector(el);
	} else if (canReflect_1_19_2_canReflect.isListLike(el) && !el.nodeType) {
		el = el[0];
	}

	if (canReflect_1_19_2_canReflect.isObservableLike(attr) && canReflect_1_19_2_canReflect.isMapLike(attr)) {
		el[viewModelSymbol] = attr;
		return;
	}

	var scope = el[viewModelSymbol];
	if(!scope) {
		scope = new canSimpleMap_4_3_3_canSimpleMap();
		el[viewModelSymbol] = scope;
	}
	switch (arguments.length) {
		case 0:
		case 1:
			return scope;
		case 2:
			return canReflect_1_19_2_canReflect.getKeyValue(scope, attr);
		default:
			canReflect_1_19_2_canReflect.setKeyValue(scope, attr, val);
			return el;
	}
};

var isDomEventTarget$2 = util.isDomEventTarget;

var canEvent = {
	on: function on(eventName, handler, queue) {
		if (isDomEventTarget$2(this)) {
			canDomEvents_1_3_13_canDomEvents.addEventListener(this, eventName, handler, queue);
		} else {
			canReflect_1_19_2_canReflect.onKeyValue(this, eventName, handler, queue);
		}
	},
	off: function off(eventName, handler, queue) {
		if (isDomEventTarget$2(this)) {
			canDomEvents_1_3_13_canDomEvents.removeEventListener(this, eventName, handler, queue);
		} else {
			canReflect_1_19_2_canReflect.offKeyValue(this, eventName, handler, queue);
		}
	},
	one: function one(event, handler, queue) {
		// Unbind the listener after it has been executed
		var one = function() {
			canEvent.off.call(this, event, one, queue);
			return handler.apply(this, arguments);
		};

		// Bind the altered listener
		canEvent.on.call(this, event, one, queue);
		return this;
	}
};

var canAttributeObservable_2_0_2_event = canEvent;

var isRadioInput = function isRadioInput(el) {
	return el.nodeName.toLowerCase() === "input" && el.type === "radio";
};

// Determine the event or events we need to listen to when this value changes.
var canAttributeObservable_2_0_2_getEventName = function getEventName(el, prop) {
	var event = "change";

	if (isRadioInput(el) && prop === "checked" ) {
		event = "can-attribute-observable-radiochange";
	}

	if (canAttributeObservable_2_0_2_behaviors.findSpecialListener(prop)) {
		event = prop;
	}

	return event;
};

function getRoot () {
	return document$1().documentElement;
}

function findParentForm (el) {
	while (el) {
		if (el.nodeName === 'FORM') {
			break;
		}
		el = el.parentNode;
	}
	return el;
}

function shouldReceiveEventFromRadio (source, dest) {
	// Must have the same name attribute and parent form
	var name = source.getAttribute('name');
	return (
		name &&
		name === dest.getAttribute('name') &&
		findParentForm(source) === findParentForm(dest)
	);
}

function isRadioInput$1 (el) {
	return el.nodeName === 'INPUT' && el.type === 'radio';
}


function attachRootListener (domEvents, eventTypeTargets) {
	var root = getRoot();
	var newListener = function (event) {
		var target = event.target;
		if (!isRadioInput$1(target)) {
			return;
		}

		for (var eventType in eventTypeTargets) {
			var newEvent = {type: eventType};
			var listeningNodes = eventTypeTargets[eventType];
			listeningNodes.forEach(function (el) {
				if (shouldReceiveEventFromRadio(target, el)) {
					domEvents.dispatch(el, newEvent, false);
				}
			});
		}
	};
	domEvents.addEventListener(root, 'change', newListener);
	return newListener;
}

function detachRootListener (domEvents, listener) {
	var root = getRoot();
	domEvents.removeEventListener(root, 'change', listener);
}

/**
 * @module {events} can-event-dom-radiochange
 * @parent can-dom-utilities
 * @collection can-infrastructure
 * @package ./package.json
 *
 * A custom event for listening to changes of inputs with type "radio",
 * which fires when a conflicting radio input changes. A "conflicting"
 * radio button has the same "name" attribute and exists within in the
 * same form, or lack thereof. This event coordinates state bound to
 * whether a radio is checked. The "change" event does not fire for deselected
 * radios. By using this event instead, deselected radios receive notification.
 *
 * ```js
 * var domEvents = require('can-dom-events');
 * var radioChange = require('can-event-dom-radiochange');
 * domEvents.addEvent(radioChange);
 *
 * var target = document.createElement('input');
 *
 * function handler () {
 * 	console.log('radiochange event fired');
 * }
 *
 * domEvents.addEventListener(target, 'radiochange', handler);
 * domEvents.removeEventListener(target, 'radiochange', handler);
 * ```
 */
var radioChangeEvent = {
	defaultEventType: 'radiochange',

	addEventListener: function (target, eventType, handler) {
		if (!isRadioInput$1(target)) {
			throw new Error('Listeners for ' + eventType + ' must be radio inputs');
		}

		var eventTypeTrackedRadios = radioChangeEvent._eventTypeTrackedRadios;
		if (!eventTypeTrackedRadios) {
			eventTypeTrackedRadios = radioChangeEvent._eventTypeTrackedRadios = {};
			if (!radioChangeEvent._rootListener) {
				radioChangeEvent._rootListener = attachRootListener(this, eventTypeTrackedRadios);
			}			
		}

		var trackedRadios = radioChangeEvent._eventTypeTrackedRadios[eventType];
		if (!trackedRadios) {
			trackedRadios = radioChangeEvent._eventTypeTrackedRadios[eventType] = new Set();
		}

		trackedRadios.add(target);
		target.addEventListener(eventType, handler);
	},

	removeEventListener: function (target, eventType, handler) {
		target.removeEventListener(eventType, handler);

		var eventTypeTrackedRadios = radioChangeEvent._eventTypeTrackedRadios;
		if (!eventTypeTrackedRadios) {
			return;
		}

		var trackedRadios = eventTypeTrackedRadios[eventType];
		if (!trackedRadios) {
			return;
		}
	
		trackedRadios.delete(target);
		if (trackedRadios.size === 0) {
			delete eventTypeTrackedRadios[eventType];
			for (var key in eventTypeTrackedRadios) {
				if (eventTypeTrackedRadios.hasOwnProperty(key)) {
					return;
				}						
			}
			delete radioChangeEvent._eventTypeTrackedRadios;
			detachRootListener(this, radioChangeEvent._rootListener);
			delete radioChangeEvent._rootListener;
		}
	}
};

var canEventDomRadiochange_2_2_1_canEventDomRadiochange = canNamespace_1_0_0_canNamespace.domEventRadioChange = radioChangeEvent;

var onValueSymbol$4 = canSymbol_1_7_0_canSymbol.for('can.onValue');
var offValueSymbol$2 = canSymbol_1_7_0_canSymbol.for('can.offValue');
var onEmitSymbol$1 = canSymbol_1_7_0_canSymbol.for('can.onEmit');
var offEmitSymbol$1 = canSymbol_1_7_0_canSymbol.for('can.offEmit');

// We register a namespaced radiochange event with the global
// event registry so it does not interfere with user-defined events.


var internalRadioChangeEventType = "can-attribute-observable-radiochange";
canDomEvents_1_3_13_canDomEvents.addEvent(canEventDomRadiochange_2_2_1_canEventDomRadiochange, internalRadioChangeEventType);

var isSelect = function isSelect(el) {
	return el.nodeName.toLowerCase() === "select";
};

var isMultipleSelect = function isMultipleSelect(el, prop) {
	return isSelect(el) && prop === "value" && el.multiple;
};

var slice$2 = Array.prototype.slice;

function canUtilAEL () {
	var args = slice$2.call(arguments, 0);
	args.unshift(this);
	return canDomEvents_1_3_13_canDomEvents.addEventListener.apply(null, args);
}

function canUtilREL () {
	var args = slice$2.call(arguments, 0);
	args.unshift(this);
	return canDomEvents_1_3_13_canDomEvents.removeEventListener.apply(null, args);
}

function AttributeObservable(el, prop, bindingData, event) {
	if(typeof bindingData === "string") {
		event = bindingData;
		bindingData = undefined;
	}

	this.el = el;
	this.bound = false;
	this.prop = isMultipleSelect(el, prop) ? "values" : prop;
	this.event = event || canAttributeObservable_2_0_2_getEventName(el, prop);
	this.handler = this.handler.bind(this);

	// If we have an event
	// remove onValue/offValue and add onEvent
	if (event !== undefined) {
		this[onValueSymbol$4] = null;
		this[offValueSymbol$2] = null;
		this[onEmitSymbol$1] = AttributeObservable.prototype.on;
		this[offEmitSymbol$1] = AttributeObservable.prototype.off;
	}


	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		// register what changes the element's attribute
		canReflectDependencies_1_1_2_canReflectDependencies.addMutatedBy(this.el, this.prop, this);

		canReflect_1_19_2_canReflect.assignSymbols(this, {
			"can.getName": function getName() {
				return (
					"AttributeObservable<" +
					el.nodeName.toLowerCase() +
					"." +
					this.prop +
					">"
				);
			}
		});
	}
	//!steal-remove-end
}

AttributeObservable.prototype = Object.create(settable.prototype);

canAssign_1_3_3_canAssign(AttributeObservable.prototype, {
	constructor: AttributeObservable,

	get: function get() {
		if (canObservationRecorder_1_3_1_canObservationRecorder.isRecording()) {
			canObservationRecorder_1_3_1_canObservationRecorder.add(this);
			if (!this.bound) {
				canObservation_4_2_0_canObservation.temporarilyBind(this);
			}
		}
		var value = canAttributeObservable_2_0_2_behaviors.get(this.el, this.prop);
		if (typeof value === 'function') {
			value = value.bind(this.el);
		}
		return value;
	},

	set: function set(newVal) {
		var setterDispatchedEvents = canAttributeObservable_2_0_2_behaviors.setAttrOrProp(this.el, this.prop, newVal);
		// update the observation internal value
		if(!setterDispatchedEvents) {
			this._value = newVal;
		}


		return newVal;
	},

	handler: function handler(newVal, event) {
		var old = this._value;
		var queuesArgs = [];
		this._value = canAttributeObservable_2_0_2_behaviors.get(this.el, this.prop);

		// If we have an event then we want to enqueue on all changes
		// otherwise only enquue when there are changes to the value
		if (event !== undefined || this._value !== old) {
			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				if (typeof this._log === "function") {
					this._log(old, newVal);
				}
			}
			//!steal-remove-end


			queuesArgs = [
				this.handlers.getNode([]),
  			this,
  			[newVal, old]
  		];
			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				queuesArgs = [
					this.handlers.getNode([]),
					this,
					[newVal, old]
					/* jshint laxcomma: true */
					,null
					,[this.el,this.prop,"changed to", newVal, "from", old, "by", event]
					/* jshint laxcomma: false */
				];
			}
			//!steal-remove-end
			// adds callback handlers to be called w/i their respective queue.
			canQueues_1_3_2_canQueues.enqueueByQueue.apply(canQueues_1_3_2_canQueues, queuesArgs);
		}
	},

	onBound: function onBound() {
		var observable = this;

		observable.bound = true;

		// make sure `this.handler` gets the new value instead of
		// the event object passed to the event handler
		observable._handler = function(event) {
			observable.handler(canAttributeObservable_2_0_2_behaviors.get(observable.el, observable.prop), event);
		};

		if (observable.event === internalRadioChangeEventType) {
			canAttributeObservable_2_0_2_event.on.call(observable.el, "change", observable._handler);
		}

		var specialBinding = canAttributeObservable_2_0_2_behaviors.findSpecialListener(observable.prop);
		if (specialBinding) {
			observable._specialDisposal = specialBinding.call(observable.el, observable.prop, observable._handler, canUtilAEL);
		}

		canAttributeObservable_2_0_2_event.on.call(observable.el, observable.event, observable._handler);

		// initial value
		this._value = canAttributeObservable_2_0_2_behaviors.get(this.el, this.prop);
	},

	onUnbound: function onUnbound() {
		var observable = this;

		observable.bound = false;

		if (observable.event === internalRadioChangeEventType) {
			canAttributeObservable_2_0_2_event.off.call(observable.el, "change", observable._handler);
		}

		if (observable._specialDisposal) {
			observable._specialDisposal.call(observable.el, canUtilREL);
			observable._specialDisposal = null;
		}

		canAttributeObservable_2_0_2_event.off.call(observable.el, observable.event, observable._handler);
	},

	valueHasDependencies: function valueHasDependencies() {
		return true;
	},

	getValueDependencies: function getValueDependencies() {
		var m = new Map();
		var s = new Set();
		s.add(this.prop);
		m.set(this.el, s);
		return {
			keyDependencies: m
		};
	}
});

canReflect_1_19_2_canReflect.assignSymbols(AttributeObservable.prototype, {
	"can.isMapLike": false,
	"can.getValue": AttributeObservable.prototype.get,
	"can.setValue": AttributeObservable.prototype.set,
	"can.onValue": AttributeObservable.prototype.on,
	"can.offValue": AttributeObservable.prototype.off,
	"can.valueHasDependencies": AttributeObservable.prototype.hasDependencies,
	"can.getValueDependencies": AttributeObservable.prototype.getValueDependencies
});

var canAttributeObservable_2_0_2_canAttributeObservable = AttributeObservable;

// # can-stache-bindings.js
//
// This module provides CanJS's default data and event bindings.
// It's broken up into several parts:
//
// - Behaviors - Binding behaviors that run given an attribute or element.
// - Attribute Syntaxes - Hooks up custom attributes to their behaviors.
// - getObservableFrom - Methods that return a observable cross bound to the scope, viewModel, or element.
// - bind - Methods for setting up cross binding
// - getBindingInfo - A helper that returns the details of a data binding given an attribute.
// - makeDataBinding - A helper method for setting up a data binding.
// - initializeValues - A helper that initializes a data binding.























// Contains all of the stache bindings that will be exported.
var bindings = new Map();

var onMatchStr = "on:",
	vmMatchStr = "vm:",
	elMatchStr = "el:",
	byMatchStr = ":by:",
	toMatchStr = ":to",
	fromMatchStr = ":from",
	bindMatchStr = ":bind",
	viewModelBindingStr = "viewModel",
	attributeBindingStr = "attribute",
	scopeBindingStr = "scope",
	viewModelOrAttributeBindingStr = "viewModelOrAttribute",
	viewModelSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.viewModel"),
	preventDataBindingsSymbol = canSymbol_1_7_0_canSymbol.for("can.preventDataBindings");

var throwOnlyOneTypeOfBindingError = function() {
	throw new Error("can-stache-bindings - you can not have contextual bindings ( this:from='value' ) and key bindings ( prop:from='value' ) on one element.");
};

// This function checks if there bindings that are trying
// to set a property ON the viewModel _conflicting_ with bindings trying to
// set THE viewModel ITSELF.
// If there is a conflict, an error is thrown.
var checkBindingState = function(bindingState, siblingBindingData) {
	var isSettingOnViewModel = siblingBindingData.parent.exports && siblingBindingData.child.source === viewModelBindingStr;
	if (isSettingOnViewModel) {
		var bindingName = siblingBindingData.child.name;
		var isSettingViewModel = isSettingOnViewModel && ( bindingName === 'this' || bindingName === '.' );

		if (isSettingViewModel) {
			if (bindingState.isSettingViewModel || bindingState.isSettingOnViewModel) {
				throwOnlyOneTypeOfBindingError();
			} else {
				return {
					isSettingViewModel: true,
					initialViewModelData: undefined
				};
			}
		} else {
			// just setting on viewModel
			if (bindingState.isSettingViewModel) {
				throwOnlyOneTypeOfBindingError();
			} else {
				return {
					isSettingOnViewModel: true,
					initialViewModelData: bindingState.initialViewModelData
				};
			}
		}
	} else {
		return bindingState;
	}
};

var getEventBindingData = function (attributeName, el, scope) {
	var bindingCode = attributeName.substr(onMatchStr.length);
	var viewModel = el && el[viewModelSymbol$1];
	var elUsed = startsWith.call(bindingCode, elMatchStr);
	var vmUsed = startsWith.call(bindingCode, vmMatchStr);
	var byUsed = bindingCode.indexOf(byMatchStr) > -1;
	var scopeUsed;

	// The values being returned
	var bindingContext;
	var eventName;
	var bindingContextObservable;
	var shortBindingCode = "";

	// if explicit context is specified, trim the string down
	// else, determine value of which scope being used elUsed, vmUsed, scopeUsed
	if (vmUsed) {
		shortBindingCode = "vm";
		bindingCode = bindingCode.substr(vmMatchStr.length);
	} else if (elUsed) {
		shortBindingCode = "el";
		bindingCode = bindingCode.substr(elMatchStr.length);
	} else if (!vmUsed && !elUsed) {
		if (byUsed) {
			scopeUsed = true;
		} else if (viewModel)  {
			vmUsed = true;
		} else {
			elUsed = true;
		}
	}

	// if by is used, take the appropriate path to determine the bindingContext
	// and create the bindingKeyValue
	var bindingContextKey;
	if (byUsed) {
		var byIndex = bindingCode.indexOf(byMatchStr);
		bindingContextKey = bindingCode.substr(byIndex + byMatchStr.length);
		bindingCode = bindingCode.substr(0, byIndex);
	}
	eventName = bindingCode;
	if (elUsed) {
		if (byUsed) {
			throw new Error('binding with :by in element scope is not currently supported');
		} else {
			bindingContext = el;
		}
	} else if (vmUsed) {
		bindingContext = viewModel;
		if (byUsed) {
			bindingContext = viewModel.get(bindingContextKey);
			bindingContextObservable = new canViewScope_4_13_7_canViewScope(viewModel).computeData(bindingContextKey);
		}
	} else if (scopeUsed) {
		bindingContext = scope;
		if (byUsed) {
			bindingContext = bindingContext.get(bindingContextKey);
			bindingContextObservable = scope.computeData(bindingContextKey);
		}
	}

	return {
		// single observable object to listen to eventName directly on one observable object
		bindingContext: bindingContext,
		// this observable emits the bindingContext
		bindingContextObservable: bindingContextObservable,
		// the eventName string
		eventName: eventName,
		// which binding code was explicitly set by the user
		bindingCode: shortBindingCode,
	};
};

var onKeyValueSymbol$5 = canSymbol_1_7_0_canSymbol.for("can.onKeyValue");
var makeScopeFromEvent = function(element, event, viewModel, args, data, bindingContext){
	// TODO: Remove in 6.0.  In 4 and 5 arguments were wrong.
	var shiftArgumentsForLegacyArguments = bindingContext && bindingContext[onKeyValueSymbol$5] !== undefined;

	var specialValues = {
		element: element,
		event: event,
		viewModel: viewModel,
		arguments: shiftArgumentsForLegacyArguments ? Array.prototype.slice.call(args, 1) : args,
		args: args
	};

	// make a scope with these things just under
	return data.scope.add(specialValues, { special: true });
};

var runEventCallback = function (el, ev, data, scope, expr, attributeName, attrVal) {
	// create "special" values that can be looked up using
	// {{scope.element}}, etc

	var updateFn = function() {
		var value = expr.value(scope, {
			doNotWrapInObservation: true
		});

		value = canReflect_1_19_2_canReflect.isValueLike(value) ?
			canReflect_1_19_2_canReflect.getValue(value) :
			value;

		return typeof value === 'function' ?
			value(el) :
			value;
	};
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		Object.defineProperty(updateFn, "name", {
			value: attributeName + '="' + attrVal + '"'
		});
	}
	//!steal-remove-end

	canQueues_1_3_2_canQueues.batch.start();
	var mutateQueueArgs = [];
	mutateQueueArgs = [
		updateFn,
		null,
		null,
		{}
	];
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		mutateQueueArgs = [
			updateFn,
			null,
			null, {
				reasonLog: [el, ev, attributeName+"="+attrVal]
			}
		];
	}
	//!steal-remove-end
	canQueues_1_3_2_canQueues.mutateQueue.enqueue.apply(canQueues_1_3_2_canQueues.mutateQueue, mutateQueueArgs);
	canQueues_1_3_2_canQueues.batch.stop();
};

// ## Behaviors
var behaviors = {
	// ## completeBindings
	// Given a list of bindings, initializes the bindings, then the viewModel then completes the bindings.
	// Arguments:
	// - bindings  - An array of `{binding, siblingBindingData}`
	// - initialViewModelData - Extra initial viewModel values
	// - makeViewModel - `makeViewModel(props, hasBindings, bindingsState)`
	// - bindingContext - optional, `{scope}`
	// Returns:
	// `{viewModel, onTeardowns, bindingsState}`
	initializeViewModel: function(bindings, initialViewModelData, makeViewModel, bindingContext) {

		var onCompleteBindings = [],
			onTeardowns = {};

		var bindingsState = {
			// if we have a binding like {something}="foo"
			isSettingOnViewModel: false,
			// if we have binding like {this}="bar"
			isSettingViewModel: false,
			initialViewModelData: initialViewModelData || {}
		};

		bindings.forEach(function(dataBinding){
			// Immediately bind to the parent so we can read its value
			dataBinding.binding.startParent();

			var siblingBindingData = dataBinding.siblingBindingData;
			bindingsState = checkBindingState(bindingsState, siblingBindingData);

			// For bindings that change the viewModel,
			// save the initial value on the viewModel.
			if (siblingBindingData.parent.exports) {

				var parentValue = siblingBindingData.child.setCompute ? canViewScope_4_13_7_makeComputeLike(dataBinding.binding.parent) : dataBinding.binding.parentValue;

				if (parentValue !== undefined) {

					if (bindingsState.isSettingViewModel) {
						// the initial data is the context
						// TODO: this is covered by can-component’s tests but not can-stache-bindings’ tests
						bindingsState.initialViewModelData = parentValue;
					} else {
						bindingsState.initialViewModelData[cleanVMName(siblingBindingData.child.name, bindingContext.scope)] = parentValue;
					}

				}
			}

			// Save what needs to happen after the `viewModel` is created.
			onCompleteBindings.push(dataBinding.binding.start.bind(dataBinding.binding));

			onTeardowns[siblingBindingData.bindingAttributeName] = dataBinding.binding.stop.bind(dataBinding.binding);
		});

		var viewModel = makeViewModel(bindingsState.initialViewModelData, bindings.length > 0, bindingsState);

		// bind on the viewModel so we can updat ethe parent
		for (var i = 0, len = onCompleteBindings.length; i < len; i++) {
			onCompleteBindings[i]();
		}
		return {viewModel: viewModel, onTeardowns: onTeardowns, bindingsState: bindingsState};
	},
	// ### bindings.behaviors.viewModel
	// Sets up all of an element's data binding attributes to a "soon-to-be-created"
	// `viewModel`.
	// This is primarily used by `Component` to ensure that its
	// `viewModel` is initialized with values from the data bindings as quickly as possible.
	// Component could look up the data binding values itself.  However, that lookup
	// would have to be duplicated when the bindings are established.
	// Instead, this uses the `makeDataBinding` helper, which allows creation of the `viewModel`
	// after scope values have been looked up.
	//
	// Arguments:
	// - `makeViewModel(initialViewModelData)` - a function that returns the `viewModel`.
	// - `initialViewModelData` any initial data that should already be added to the `viewModel`.
	//
	// Returns:
	// - `function` - a function that tears all the bindings down. Component
	// wants all the bindings active so cleanup can be done during a component being removed.
	viewModel: function(el, tagData, makeViewModel, initialViewModelData, options) {

		if(typeof options === "boolean") {
			options = {staticDataBindingsOnly: options};
		} else if(typeof options === "undefined") {
			options = {};
		}
		var staticDataBindingsOnly = options.staticDataBindingsOnly;
		var makeDataBindingFn = options.makeDataBinding || makeDataBinding;

		var attributeViewModelBindings = canAssign_1_3_3_canAssign({}, initialViewModelData),

			// The data around the binding.
			bindingContext = canAssign_1_3_3_canAssign({
				element: el,
				// this gets defined later
				viewModel: undefined
			}, tagData),

			// global settings for the bindings
			bindingSettings = {
				attributeViewModelBindings: attributeViewModelBindings,
				alreadyUpdatedChild: true,
				// force viewModel bindings in cases when it is ambiguous whether you are binding
				// on viewModel or an attribute (:to, :from, :bind)
				favorViewModel: true,
				makeDataBinding: makeDataBindingFn,
				getSiblingBindingData: options.getSiblingBindingData || getSiblingBindingData
			},
			dataBindings = [];

		// For each attribute, we create a dataBinding object.
		// These look like: `{binding, siblingBindingData}`
		canReflect_1_19_2_canReflect.eachListLike(el.attributes || [], function(node) {
			var dataBinding = makeDataBindingFn(node, bindingContext, bindingSettings);

			if (dataBinding) {
				dataBindings.push(dataBinding);
			}
		});

		// If there are no binding, exit.
		if (staticDataBindingsOnly && dataBindings.length === 0) {
			return;
		}

		// Initialize the viewModel
		var completedData = behaviors.initializeViewModel(dataBindings, initialViewModelData, function(){
			// we need to make sure we have the viewModel available
			bindingContext.viewModel = makeViewModel.apply(this, arguments);
		}, bindingContext),
			onTeardowns = completedData.onTeardowns,
			bindingsState = completedData.bindingsState,
			siblingBindingDatas = {};


		// Listen to attribute changes and re-initialize
		// the bindings.
		var attributeDisposal;
		if (!bindingsState.isSettingViewModel) {
			// We need to update the child on any new bindings.
			bindingSettings.alreadyUpdatedChild = false;
			attributeDisposal = canDomMutate_2_0_9_canDomMutate.onNodeAttributeChange(el, function(ev) {
				var attrName = ev.attributeName,
					value = el.getAttribute(attrName);

				if (onTeardowns[attrName]) {
					onTeardowns[attrName]();
				}
				// Parent attribute bindings we always re-setup.
				var parentBindingWasAttribute = siblingBindingDatas[attrName] && siblingBindingDatas[attrName].parent.source === attributeBindingStr;

				if (value !== null || parentBindingWasAttribute) {
					var dataBinding = makeDataBinding({
						name: attrName,
						value: value
					}, bindingContext, bindingSettings);
					if (dataBinding) {
						// The viewModel is created, so call callback immediately.
						dataBinding.binding.start();
						siblingBindingDatas[attrName] = dataBinding.siblingBindingData;
						onTeardowns[attrName] = dataBinding.binding.stop.bind(dataBinding.binding);
					}
				}
			});
		}

		return function() {
			if (attributeDisposal) {
				attributeDisposal();
				attributeDisposal = undefined;
			}
			for (var attrName in onTeardowns) {
				onTeardowns[attrName]();
			}
		};
	},
	// ### bindings.behaviors.data
	// This is called when an individual data binding attribute is placed on an element.
	// For example `{^value}="name"`.
	data: function(el, attrData) {
		if (el[preventDataBindingsSymbol] === true || canDomData_1_0_3_canDomData.get(el, "preventDataBindings")) {
			return;
		}
		var viewModel,
			getViewModel = canObservationRecorder_1_3_1_canObservationRecorder.ignore(function() {
				return viewModel || (viewModel = canViewModel_4_0_3_canViewModel(el));
			}),
			teardown,
			attributeDisposal,
			removedDisposal,
			bindingContext = {
				element: el,
				templateType: attrData.templateType,
				scope: attrData.scope,
				parentNodeList: attrData.nodeList,
				get viewModel(){
					return getViewModel();
				}
			};

		// Setup binding
		var dataBinding = makeDataBinding({
			name: attrData.attributeName,
			value: el.getAttribute(attrData.attributeName),
		}, bindingContext, {
			syncChildWithParent: false,
			getSiblingBindingData: getSiblingBindingData
		});

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			if (dataBinding.siblingBindingData.child.source === "viewModel" && !canDomData_1_0_3_canDomData.get(el, "viewModel")) {
				dev.warn('This element does not have a viewModel. (Attempting to bind `' + dataBinding.siblingBindingData.bindingAttributeName + '="' + dataBinding.siblingBindingData.parent.name + '"`)');
			}
		}
		//!steal-remove-end

		// Flag to prevent start binding twice in dev mode
		var started = false;

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			if (el.nodeName === 'INPUT') {
				try {
					dataBinding.binding.start();
					started = true;
				} catch (error) {
					throw new Error(error.message + ' <input> elements always set properties to Strings.');
				}
			}
		}
		//!steal-remove-end

		if (!started) {
			dataBinding.binding.start();
			started = true;
		}

		var attributeListener = function(ev) {
			var attrName = ev.attributeName,
				value = el.getAttribute(attrName);

			if (attrName === attrData.attributeName) {
				if (teardown) {
					teardown();
				}

				if(value !== null  ) {
					var dataBinding = makeDataBinding({name: attrName, value: value}, bindingContext, {
						syncChildWithParent: false,
						getSiblingBindingData: getSiblingBindingData
					});
					if(dataBinding) {
						// The viewModel is created, so call callback immediately.
						dataBinding.binding.start();
						teardown = dataBinding.binding.stop.bind(dataBinding.binding);
					}
					teardown = dataBinding.onTeardown;
				}
			}
		};


		var tearItAllDown = function() {
			if (teardown) {
				teardown();
				teardown = undefined;
			}

			if (removedDisposal) {
				removedDisposal();
				removedDisposal = undefined;
			}
			if (attributeDisposal) {
				attributeDisposal();
				attributeDisposal = undefined;
			}
		};



		// Listen for changes
		teardown = dataBinding.binding.stop.bind(dataBinding.binding);

		attributeDisposal = canDomMutate_2_0_9_canDomMutate.onNodeAttributeChange(el, attributeListener);
		removedDisposal = canDomMutate_2_0_9_canDomMutate.onNodeDisconnected(el, function() {
			var doc = el.ownerDocument;
			var ownerNode = doc.contains ? doc : doc.documentElement;
			if (!ownerNode || ownerNode.contains(el) === false) {
				tearItAllDown();
			}
		});
	},
	// ### bindings.behaviors.event
	// The following section contains code for implementing the can-EVENT attribute.
	// This binds on a wildcard attribute name. Whenever a view is being processed
	// and can-xxx (anything starting with can-), this callback will be run.  Inside, its setting up an event handler
	// that calls a method identified by the value of this attribute.
	event: function(el, data) {
		var eventBindingData;
		// Get the `event` name and if we are listening to the element or viewModel.
		// The attribute name is the name of the event.
		var attributeName = canAttributeEncoder_1_1_4_canAttributeEncoder.decode(data.attributeName),
			// the name of the event we are binding
			event,
			// the context to which we bind the event listener
			bindingContext,
			// if the bindingContext is null, then use this observable to watch for changes
			bindingContextObservable;

		// check for `on:event:value:to` type things and call data bindings
		if (attributeName.indexOf(toMatchStr + ":") !== -1 ||
			attributeName.indexOf(fromMatchStr + ":") !== -1 ||
			attributeName.indexOf(bindMatchStr + ":") !== -1
		) {
			return this.data(el, data);
		}

		if (startsWith.call(attributeName, onMatchStr)) {
			eventBindingData = getEventBindingData(attributeName, el, data.scope);
			event = eventBindingData.eventName;
			bindingContext = eventBindingData.bindingContext;
			bindingContextObservable = eventBindingData.bindingContextObservable;

			//!steal-remove-start
			if(process.env.NODE_ENV !== "production") {
				if(
					!eventBindingData.bindingCode &&
					el[viewModelSymbol$1] &&
					("on" + event) in el
				) {
					dev.warn(
						"The " + event + " event is bound the view model for <" + el.tagName.toLowerCase() +
							">. Use " + attributeName.replace(onMatchStr, "on:el:") +  " to bind to the element instead."
					);
				}
			}
			//!steal-remove-end
		} else {
			throw new Error("can-stache-bindings - unsupported event bindings " + attributeName);
		}

		// This is the method that the event will initially trigger. It will look up the method by the string name
		// passed in the attribute and call it.
		var handler = function(ev) {
			var attrVal = el.getAttribute(canAttributeEncoder_1_1_4_canAttributeEncoder.encode(attributeName));
			if (!attrVal) {
				return;
			}

			var viewModel = el[viewModelSymbol$1];

			// expression.parse will read the attribute
			// value and parse it identically to how mustache helpers
			// get parsed.
			var expr = expression_1.parse(attrVal, {
				lookupRule: function() {
					return expression_1.Lookup;
				},
				methodRule: "call"
			});

			var runScope = makeScopeFromEvent(el, ev, viewModel, arguments, data, bindingContext);

			if (expr instanceof expression_1.Hashes) {
				var hashExprs = expr.hashExprs;
				var key = Object.keys(hashExprs)[0];
				var value = expr.hashExprs[key].value(runScope);
				var isObservableValue = canReflect_1_19_2_canReflect.isObservableLike(value) && canReflect_1_19_2_canReflect.isValueLike(value);
				runScope.set(key, isObservableValue ? canReflect_1_19_2_canReflect.getValue(value) : value);
			} else if (expr instanceof expression_1.Call) {
				runEventCallback(el, ev, data, runScope, expr, attributeName, attrVal);
			} else {
				throw new Error("can-stache-bindings: Event bindings must be a call expression. Make sure you have a () in " + data.attributeName + "=" + JSON.stringify(attrVal));
			}
		};

		var attributesDisposal,
			removalDisposal,
			removeObservation,
			currentContext;

		// Unbind the event when the attribute is removed from the DOM
		var attributesHandler = function(ev) {
			var isEventAttribute = ev.attributeName === attributeName;
			var isRemoved = !el.getAttribute(attributeName);
			var isEventAttributeRemoved = isEventAttribute && isRemoved;
			if (isEventAttributeRemoved) {
				unbindEvent();
			}
		};
		var removalHandler = function() {
			var doc = el.ownerDocument;
			var ownerNode = doc.contains ? doc : doc.documentElement;
			if (!ownerNode || !ownerNode.contains(el)) {
				unbindEvent();
			}
		};
		var unbindEvent = function() {
			if (bindingContext) {
				map$1.off.call(bindingContext, event, handler);
			}
			if (attributesDisposal) {
				attributesDisposal();
				attributesDisposal = undefined;
			}
			if (removalDisposal) {
				removalDisposal();
				removalDisposal = undefined;
			}
			if (removeObservation) {
				removeObservation();
				removeObservation = undefined;
			}
		};

		function updateListener(newVal, oldVal) {
			if (oldVal) {
				map$1.off.call(oldVal, event, handler);
			}
			if (newVal) {
				map$1.on.call(newVal, event, handler);
				currentContext = newVal;
			}
		}

		// Bind the handler defined above to the element we're currently processing and the event name provided in this
		// attribute name (can-click="foo")
		attributesDisposal = canDomMutate_2_0_9_canDomMutate.onNodeAttributeChange(el, attributesHandler);
		removalDisposal = canDomMutate_2_0_9_canDomMutate.onNodeDisconnected(el, removalHandler);
		if (!bindingContext && bindingContextObservable) {
			// on value changes of the observation, rebind the listener to the new context
			removeObservation = function () {
				if (currentContext) {
					map$1.off.call(currentContext, event, handler);
				}
				canReflect_1_19_2_canReflect.offValue(bindingContextObservable, updateListener);
			};
			canReflect_1_19_2_canReflect.onValue(bindingContextObservable, updateListener);
		} else {
			try {
				map$1.on.call(bindingContext, event, handler);
			} catch (error) {
				if (/Unable to bind/.test(error.message)) {
					var msg = 'can-stache-bindings - Unable to bind "' + event + '"';
					msg += ': "' + event  + '" is a property on a plain object "';
					msg += JSON.stringify(bindingContext);
					msg += '". Binding is available with observable objects only.';
					msg += ' For more details check https://canjs.com/doc/can-stache-bindings.html#Callafunctionwhenaneventhappensonavalueinthescope_animation_';
					throw new Error(msg);
				} else {
					throw error;
				}
			}
		}
	}
};


// ## Attribute Syntaxes
// The following sets up the bindings functions to be called
// when called in a template.


// value:to="bar" data bindings
// these are separate so that they only capture at the end
// to avoid (toggle)="bar" which is encoded as :lp:toggle:rp:="bar"
bindings.set(/[\w\.:]+:to$/, behaviors.data);
bindings.set(/[\w\.:]+:from$/, behaviors.data);
bindings.set(/[\w\.:]+:bind$/, behaviors.data);
bindings.set(/[\w\.:]+:raw$/, behaviors.data);
// value:to:on:input="bar" data bindings
bindings.set(/[\w\.:]+:to:on:[\w\.:]+/, behaviors.data);
bindings.set(/[\w\.:]+:from:on:[\w\.:]+/, behaviors.data);
bindings.set(/[\w\.:]+:bind:on:[\w\.:]+/, behaviors.data);


// `(EVENT)` event bindings.
bindings.set(/on:[\w\.:]+/, behaviors.event);

// ## getObservableFrom
// An object of helper functions that make a getter/setter observable
// on different types of objects.
var getObservableFrom = {
	// ### getObservableFrom.viewModelOrAttribute
	viewModelOrAttribute: function(bindingData, bindingContext) {
		var viewModel = bindingContext.element[viewModelSymbol$1];

		// if we have a viewModel, use it; otherwise, setup attribute binding
		if (viewModel) {
			return this.viewModel.apply(this, arguments);
		} else {
			return this.attribute.apply(this, arguments);
		}
	},
	// ### getObservableFrom.scope
	// Returns a compute from the scope.  This handles expressions like `someMethod(.,1)`.
	scope: function(bindingData, bindingContext) {
		var scope = bindingContext.scope,
			scopeProp = bindingData.name,
			mustBeGettable = bindingData.exports;

		if (!scopeProp) {
			return new canSimpleObservable_2_5_0_canSimpleObservable();
		} else {
			// Check if we need to spend time building a scope-key-data
			// If we have a '(', it likely means a call expression.
			if (mustBeGettable || scopeProp.indexOf("(") >= 0 || scopeProp.indexOf("=") >= 0) {
				var parentExpression = expression_1.parse(scopeProp,{baseMethodType: "Call"});

				if (parentExpression instanceof expression_1.Hashes) {
					return new canSimpleObservable_2_5_0_canSimpleObservable(function () {
						var hashExprs = parentExpression.hashExprs;
						var key = Object.keys(hashExprs)[0];
						var value = parentExpression.hashExprs[key].value(scope);
						var isObservableValue = canReflect_1_19_2_canReflect.isObservableLike(value) && canReflect_1_19_2_canReflect.isValueLike(value);
						scope.set(key, isObservableValue ? canReflect_1_19_2_canReflect.getValue(value) : value);
					});
				} else {
					return parentExpression.value(scope);
				}
			} else {
				var observation = {};
				canReflect_1_19_2_canReflect.assignSymbols(observation, {
					"can.getValue": function getValue() {},

					"can.valueHasDependencies": function hasValueDependencies() {
						return false;
					},

					"can.setValue": function setValue(newVal) {
						var expr = expression_1.parse(cleanVMName(scopeProp, scope),{baseMethodType: "Call"});
						var value = expr.value(scope);
						canReflect_1_19_2_canReflect.setValue(value, newVal);
					},

					// Register what the custom observation changes
					"can.getWhatIChange": function getWhatIChange() {
						var data = scope.getDataForScopeSet(cleanVMName(scopeProp, scope));
						var m = new Map();
						var s = new Set();
						s.add(data.key);
						m.set(data.parent, s);

						return {
							mutate: {
								keyDependencies: m
							}
						};
					},

					"can.getName": function getName() {
						//!steal-remove-start
						if (process.env.NODE_ENV !== 'production') {
							var result = "ObservableFromScope<>";
							var data = scope.getDataForScopeSet(cleanVMName(scopeProp, scope));

							if (data.parent && data.key) {
								result = "ObservableFromScope<" +
									canReflect_1_19_2_canReflect.getName(data.parent) +
									"." +
									data.key +
									">";
							}

							return result;
						}
						//!steal-remove-end
					},
				});

				var data = scope.getDataForScopeSet(cleanVMName(scopeProp, scope));
				if (data.parent && data.key) {
					// Register what changes the Scope's parent key
					canReflectDependencies_1_1_2_canReflectDependencies.addMutatedBy(data.parent, data.key, observation);
				}

				return observation;
			}
		}
	},
	// ### getObservableFrom.viewModel
	// Returns a compute that's two-way bound to the `viewModel` returned by
	// `options.bindingSettings()`.
	// Arguments:
	// - bindingData - {source, name, setCompute}
	// - bindingContext - {scope, element}
	// - bindingSettings - {getViewModel}
	viewModel: function(bindingData, bindingContext) {
		var scope = bindingContext.scope,
			vmName = bindingData.name,
			setCompute = bindingData.setCompute;

		var setName = cleanVMName(vmName, scope);
		var isBoundToContext = vmName === "." || vmName === "this";
		var keysToRead = isBoundToContext ? [] : canStacheKey_1_4_3_canStacheKey.reads(vmName);

		function getViewModelProperty() {
			var viewModel = bindingContext.viewModel;
			return canStacheKey_1_4_3_canStacheKey.read(viewModel, keysToRead, {}).value;
		}
		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {

			Object.defineProperty(getViewModelProperty, "name", {
				value: "<"+bindingContext.element.tagName.toLowerCase()+">." + vmName
			});
		}
		//!steal-remove-end

		var observation = new setter(
			getViewModelProperty,

			function setViewModelProperty(newVal) {
				var viewModel = bindingContext.viewModel;

				if (setCompute) {
					// If there is a binding like `foo:from="~bar"`, we need
					// to set the observable itself.
					var oldValue = canReflect_1_19_2_canReflect.getKeyValue(viewModel, setName);
					if (canReflect_1_19_2_canReflect.isObservableLike(oldValue)) {
						canReflect_1_19_2_canReflect.setValue(oldValue, newVal);
					} else {
						canReflect_1_19_2_canReflect.setKeyValue(
							viewModel,
							setName,
							new canSimpleObservable_2_5_0_canSimpleObservable(canReflect_1_19_2_canReflect.getValue(newVal))
						);
					}
				} else {
					if (isBoundToContext) {
						canReflect_1_19_2_canReflect.setValue(viewModel, newVal);
					} else {
						canStacheKey_1_4_3_canStacheKey.write(viewModel, keysToRead, newVal);
					}
				}
			}
		);

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			var viewModel = bindingContext.viewModel;
			if (viewModel && setName) {
				canReflectDependencies_1_1_2_canReflectDependencies.addMutatedBy(viewModel, setName, observation);
			}
		}
		//!steal-remove-end

		return observation;
	},
	// ### getObservableFrom.attribute
	// Returns a compute that is two-way bound to an attribute or property on the element.
	attribute: function(bindingData, bindingContext ) {

		if(bindingData.name === "this") {
			return canReflect_1_19_2_canReflect.assignSymbols({}, {
				"can.getValue": function() {
					return bindingContext.element;
				},

				"can.valueHasDependencies": function() {
					return false;
				},
				"can.getName": function getName() {
					//!steal-remove-start
					return "<"+bindingContext.element.nodeName+">";
					//!steal-remove-end
				}
			});
		} else {
			return new canAttributeObservable_2_0_2_canAttributeObservable(bindingContext.element, bindingData.name, {}, bindingData.event);
		}

	}
};

var startsWith = String.prototype.startsWith || function(text){
	return this.indexOf(text) === 0;
};

// Gets an event name in the after part.
function getEventName(result) {
	if (result.special.on !== undefined) {
		return result.tokens[result.special.on + 1];
	}
}

var siblingBindingRules = {
	to: {
		child: {
			exports: true,
			syncSibling: false
		},
		parent: {
			exports: false,
			syncSibling: false
		}
	},
	from: {
		child: {
			exports: false,
			syncSibling: false
		},
		parent: {
			exports: true,
			syncSibling: false
		}
	},
	bind: {
		child: {
			exports: true,
			syncSibling: false
		},
		parent: {
			exports: true,
			syncSibling: true
		}
	},
	raw: {
		child: {
			exports: false,
			syncSibling: false
		},
		parent: {
			exports: true,
			syncSibling: false
		}
	}
};
var bindingNames = [];
var special$1 = {
	vm: true,
	on: true
};
canReflect_1_19_2_canReflect.eachKey(siblingBindingRules, function(value, key) {
	bindingNames.push(key);
	special$1[key] = true;
});

// "on:click:value:to" //-> {tokens: [...], special: {on: 0, to: 3}}
function tokenize(source) {
	var splitByColon = source.split(":");
	// combine tokens that are not to, from, vm,
	var result = {
		tokens: [],
		special: {}
	};
	splitByColon.forEach(function(token) {
		if (special$1[token]) {
			result.special[token] = result.tokens.push(token) - 1;
		} else {
			result.tokens.push(token);
		}
	});

	return result;
}

// ## getChildBindingStr
var getChildBindingStr = function(tokens, favorViewModel) {
	if (tokens.indexOf('vm') >= 0) {
		return viewModelBindingStr;
	} else if (tokens.indexOf('el') >= 0) {
		return attributeBindingStr;
	} else {
		return favorViewModel ? viewModelBindingStr : viewModelOrAttributeBindingStr;
	}
};

// ## getSiblingBindingData
// Returns information about the binding read from an attribute node.
// Arguments:
// - node - An attribute node like: `{name, value}`
// - bindingSettings - Optional.  Has {favorViewModel: Boolean}
// Returns an object with:
// - `parent` - {source, name, event, exports, syncSibling}
// - `child` - {source, name, event, exports, syncSibling, setCompute}
// - `bindingAttributeName` - debugging name.
// - `initializeValues` - should parent and child be initialized to their counterpart.
//
// `parent` and `child` properties:
//
// - `source` - where is the value read from: "scope", "attribute", "viewModel".
// - `name` - the name of the property that should be read
// - `event` - an optional event name to listen to
// - `exports` - if the value is exported to its sibling
// - `syncSibling` - if the value is sticky. When this value is updated, should the value be checked after
//   and its sibling be updated immediately.
// - `setCompute` - set the value to a compute.
function getSiblingBindingData(node, bindingSettings) {

	var siblingBindingData,
		attributeName = canAttributeEncoder_1_1_4_canAttributeEncoder.decode(node.name),
		attributeValue = node.value || "";

	var result = tokenize(attributeName),
		dataBindingName,
		specialIndex;

	// check if there's a match of a binding name with at least a value before it
	bindingNames.forEach(function(name) {
		if (result.special[name] !== undefined && result.special[name] > 0) {
			dataBindingName = name;
			specialIndex = result.special[name];
			return false;
		}
	});

	if (dataBindingName) {
		var childEventName = getEventName(result);

		var initializeValues = childEventName && dataBindingName !== "bind" ? false : true;
		siblingBindingData = {
			parent: canAssign_1_3_3_canAssign({
				source: scopeBindingStr,
				name: result.special.raw ? ('"' + attributeValue + '"') : attributeValue
			}, siblingBindingRules[dataBindingName].parent),
			child: canAssign_1_3_3_canAssign({
				source: getChildBindingStr(result.tokens, bindingSettings && bindingSettings.favorViewModel),
				name: result.tokens[specialIndex - 1],
				event: childEventName
			}, siblingBindingRules[dataBindingName].child),
			bindingAttributeName: attributeName,
			initializeValues: initializeValues
		};
		if (attributeValue.trim().charAt(0) === "~") {
			siblingBindingData.child.setCompute = true;
		}
		return siblingBindingData;
	}
}



// ## makeDataBinding
// Makes a data binding for an attribute `node`.  Returns an object with information
// about the binding, including an `onTeardown` method that undoes the binding.
// If the data binding involves a `viewModel`, an `onCompleteBinding` method is returned on
// the object.  This method must be called after the element has a `viewModel` with the
// `viewModel` to complete the binding.
//
// Arguments:
// - `node` - an attribute node or an object with a `name` and `value` property.
// - `bindingContext` - The stache context  `{scope, element, parentNodeList}`
// - `bindingSettings` - Settings to control the behavior.
//   - `getViewModel`  - a function that returns the `viewModel` when called.  This function can be passed around (not called) even if the
//      `viewModel` doesn't exist yet.
//   - `attributeViewModelBindings` - properties already specified as being a viewModel<->attribute (as opposed to viewModel<->scope) binding.
//   - `favorViewModel`
//   - `alreadyUpdatedChild`
// Returns:
// - `undefined` - If this isn't a data binding.
// - `object` - An object with information about the binding:
//   - siblingBindingData: the binding behavior
//   - binding: canBinding
var makeDataBinding = function(node, bindingContext, bindingSettings) {
	// Get information about the binding.
	var siblingBindingData = bindingSettings.getSiblingBindingData( node, bindingSettings );
	if (!siblingBindingData) {
		return;
	}

	// Get computes for the parent and child binding
	var parentObservable = getObservableFrom[siblingBindingData.parent.source](
		siblingBindingData.parent,
		bindingContext, bindingSettings
	),
	childObservable = getObservableFrom[siblingBindingData.child.source](
		siblingBindingData.child,
		bindingContext, bindingSettings,
		parentObservable
	);

	var childToParent = !!siblingBindingData.child.exports;
	var parentToChild = !!siblingBindingData.parent.exports;

	// Check for child:bind="~parent" (it’s not supported because it’s unclear
	// what the “right” behavior should be)

	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		if (siblingBindingData.child.setCompute && childToParent && parentToChild) {
			dev.warn("Two-way binding computes is not supported.");
		}
	}
	//!steal-remove-end

	var bindingOptions = {
		child: childObservable,
		childToParent: childToParent,
		// allow cycles if one directional
		cycles: childToParent === true && parentToChild === true ? 0 : 100,
		onInitDoNotUpdateChild: bindingSettings.alreadyUpdatedChild || siblingBindingData.initializeValues === false,
		onInitDoNotUpdateParent: siblingBindingData.initializeValues === false,
		onInitSetUndefinedParentIfChildIsDefined: true,
		parent: parentObservable,
		parentToChild: parentToChild,
		priority: bindingContext.parentNodeList ? bindingContext.parentNodeList.nesting + 1 : undefined,
		queue: "dom",
		sticky: siblingBindingData.parent.syncSibling ? "childSticksToParent" : undefined,
		element: bindingContext.element
	};

	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		var nodeHTML = canAttributeEncoder_1_1_4_canAttributeEncoder.decode(node.name)+"="+JSON.stringify(node.value);
		var tagStart = "<"+bindingContext.element.nodeName.toLowerCase(),
			tag = tagStart+">";

		var makeUpdateName = function(child, childName) {

			if(child === "viewModel") {
				return tag+"."+childName;
			}
			else if(child === "scope") {
				return "{{"+childName+"}}";
			}
			else {
				return ""+child+"."+childName;
			}
		};
		bindingOptions.debugName = tagStart+" "+nodeHTML+">";
		bindingOptions.updateChildName = bindingOptions.debugName+" updates "+
			makeUpdateName(siblingBindingData.child.source, siblingBindingData.child.name)+
			" from "+makeUpdateName(siblingBindingData.parent.source, siblingBindingData.parent.name);

		bindingOptions.updateParentName = bindingOptions.debugName+" updates "+
			makeUpdateName(siblingBindingData.parent.source, siblingBindingData.parent.name)+
			" from "+makeUpdateName(siblingBindingData.child.source, siblingBindingData.child.name);
	}
	//!steal-remove-end

	// Create the binding
	var canBinding = new canBind_1_5_1_canBind(bindingOptions);

	return {
		siblingBindingData: siblingBindingData,
		binding: canBinding
	};
};

var cleanVMName = function(name, scope) {
	//!steal-remove-start
	if (process.env.NODE_ENV !== 'production') {
		if (name.indexOf("@") >= 0 && scope) {
			var filename = scope.peek('scope.filename');
			var lineNumber = scope.peek('scope.lineNumber');

			dev.warn(
				(filename ? filename + ':' : '') +
				(lineNumber ? lineNumber + ': ' : '') +
				'functions are no longer called by default so @ is unnecessary in \'' + name + '\'.');
		}
	}
	//!steal-remove-end
	return name.replace(/@/g, "");
};

var canStacheBindings = {
	behaviors: behaviors,
	getSiblingBindingData: getSiblingBindingData,
	bindings: bindings,
	getObservableFrom: getObservableFrom,
	makeDataBinding: makeDataBinding
};

canStacheBindings[canSymbol_1_7_0_canSymbol.for("can.callbackMap")] = bindings;

var canStacheBindings_5_0_5_canStacheBindings = canStacheBindings;

const rendererSymbol = Symbol.for("can.stacheRenderer");
const viewInsertSymbol$2 = Symbol.for("can.viewInsert");

// make bindings work
canStache_5_1_1_canStache.addBindings(canStacheBindings_5_0_5_canStacheBindings);

var mixinStacheView = function mixinStacheView(Base = HTMLElement) {
	class StacheClass extends Base {
		render(props, renderOptions) {
			if(super.render) {
				super.render(props);
			}

			// cache renderer function so `stache(...)` is only called
			// for the first instance of each StacheElement constructor
			let renderer = this.constructor[rendererSymbol];
			if (!renderer) {
				const view = this.constructor.view;
				const viewName = canReflect_1_19_2_canReflect.getName(this.constructor) + "View";

				renderer = typeof view === "function" ?
					view :
					canStache_5_1_1_canStache(viewName, view || "");

				this.constructor[rendererSymbol] = renderer;
			}

			const frag = renderer(
				new canViewScope_4_13_7_canViewScope(this, null, { viewModel: true }),
				renderOptions
			);

			const viewRoot = this.viewRoot || this;
			canDomMutate_2_0_9_node.appendChild.call(viewRoot, frag);
		}

		connect() {
			if (super.connect) {
				super.connect();
			}

			const removedDisposal = canDomMutate_2_0_9_canDomMutate.onNodeRemoved(this, () => {
				var doc = this.ownerDocument;
				var rootNode = doc.contains ? doc : doc.documentElement;
				if (!rootNode || !rootNode.contains(this)) {
					removedDisposal();
					this.disconnect();
				}
			});
		}

		[viewInsertSymbol$2]() {
			return this;
		}
	}
	StacheClass.prototype[Symbol.for("can.preventDataBindings")] = true;
	return StacheClass;
};

const viewModelSymbol$2 = Symbol.for("can.viewModel");

var mixinViewmodelSymbol = function mixinViewModelSymbol(BaseClass = HTMLElement) {
	class ViewModelClass extends BaseClass {}

	// can-stache-bindings uses viewModel symbol
	canDefineLazyValue_1_1_1_defineLazyValue(ViewModelClass.prototype, viewModelSymbol$2, function() {
		return this;
	});

	return ViewModelClass;
};

const getValueSymbol$3 = Symbol.for("can.getValue");
const setValueSymbol$4 = Symbol.for("can.setValue");
const metaSymbol$7 = Symbol.for("can.meta");

var mixinBindings = function mixinBindings(Base = HTMLElement) {
	return class BindingsClass extends Base {
		bindings(bindings) {
			if(this[metaSymbol$7] === undefined) {
				this[metaSymbol$7] = {};
			}
			const bindingsObservables = {};
			canReflect_1_19_2_canReflect.eachKey(bindings, (parent, propName) => {
				// Create an observable for reading/writing the viewModel
				// even though it doesn't exist yet.
				const child = key(this, propName);

				bindingsObservables[propName] = {
					parent,
					child
				};
			});
			this[metaSymbol$7]._connectedBindings = bindingsObservables;
			return this;
		}
		initialize(props) {
			var savedBindings = this[metaSymbol$7] && this[metaSymbol$7]._connectedBindings;
			if (savedBindings) {
				props = props || {};

				if (this[metaSymbol$7]._bindings === undefined) {
					this[metaSymbol$7]._bindings = [];
				}

				canReflect_1_19_2_canReflect.eachKey(savedBindings, (binding, propName) => {
					const { child, parent } = binding;

					var canGetParentValue = parent != null && !!parent[getValueSymbol$3];
					var canSetParentValue = parent != null && !!parent[setValueSymbol$4];

					// If we can get or set the value, then we’ll create a binding
					if (canGetParentValue || canSetParentValue) {

						// Create the binding similar to what’s in can-stache-bindings
						var canBinding = new canBind_1_5_1_canBind({
							child: child,
							parent: parent,
							queue: "dom",
							element: this,

							//!steal-remove-start
							// For debugging: the names that will be assigned to the updateChild
							// and updateParent functions within can-bind
							updateChildName: "update <" + this.nodeName.toLowerCase() + ">."+propName,
							updateParentName: "update " + canReflect_1_19_2_canReflect.getName(parent) + " from <" + this.nodeName.toLowerCase() + ">."+propName
							//!steal-remove-end
						});

						this[metaSymbol$7]._bindings.push({
							binding: canBinding,
							siblingBindingData: {
								parent: {
									source: "scope",
									exports: canGetParentValue
								},
								child: {
									source: "viewModel",
									exports: canSetParentValue,
									name: propName
								},
								bindingAttributeName: propName
							}
						});

					} else {
						// Can’t get or set the value, so assume it’s not an observable
						props[propName] = parent;
					}
				});

				this[metaSymbol$7].other = true;
			}
			if (super.initialize) {
				super.initialize(props);
			}
		}
		render(props, renderOptions) {
			const viewRoot = this.viewRoot || this;
			viewRoot.innerHTML = "";

			if(super.render) {
				super.render(props, renderOptions);
			}
		}
		disconnect() {
			delete this[metaSymbol$7]._bindings;
			if (super.disconnect) {
				super.disconnect();
			}
		}
	};
};

const metaSymbol$8 = Symbol.for("can.meta");
const inSetupSymbol$5 = Symbol.for("can.initializing");

var mixinInitializeBindings = function mixinBindings(Base = HTMLElement) {
	return class InitializeBindingsClass extends Base {
		initialize(props) {
			var bindings = this[metaSymbol$8] && this[metaSymbol$8]._bindings;

			if (bindings && bindings.length) {
				// set inSetup to false so that observations read in `initializeViewModel`
				// correctly set up bindings
				const origInSetup = this[inSetupSymbol$5];
				this[inSetupSymbol$5] = false;

				const bindingContext = {
					element: this
				};
				// Initialize the viewModel.  Make sure you
				// save it so the observables can access it.
				var initializeData = canStacheBindings_5_0_5_canStacheBindings.behaviors.initializeViewModel(bindings, props, (properties) => {
					super.initialize(properties);
					return this;
				}, bindingContext);
	
				this[metaSymbol$8]._connectedBindingsTeardown = function() {
					for (var attrName in initializeData.onTeardowns) {
						initializeData.onTeardowns[attrName]();
					}
				};

				// restore inSetup to the original value
				this[inSetupSymbol$5] = origInSetup;
			} else {
				if (super.initialize) {
					super.initialize(props);
				}
			}
		}
		disconnect() {
			if(this[metaSymbol$8] && this[metaSymbol$8]._connectedBindingsTeardown) {
				this[metaSymbol$8]._connectedBindingsTeardown();
				this[metaSymbol$8]._connectedBindingsTeardown = null;
			}
			if (super.disconnect) {
				super.disconnect();
			}
		}
	};
};

const { mixins: mixins$6 } = mixins;

const metaSymbol$9 = Symbol.for("can.meta");

// `attributeChangedCallback` cannot be overwritten so we need to create a named
// function to check if we have had a `attributeChangedCallback` set.
function baseAttributeChangedCallback () {
	/* jshint validthis: true */
	if (this.attributeChangedCallback !== baseAttributeChangedCallback) {
		// `this.attributeChangedCallback` is being set up within `can-observable-bindings`
		this.attributeChangedCallback.apply(this, arguments);
	}
}

var mixinBindBehaviour = function mixinBindBehaviour(Base = HTMLElement) {
	class BindingPropsClass extends Base {
		initialize(props) {
			if(this[metaSymbol$9] === undefined) {
				this[metaSymbol$9] = {};
			}
			if (this[metaSymbol$9]._bindings === undefined) {
				this[metaSymbol$9]._bindings = [];
			}
			// `_uninitializedBindings` are being set within `observedAttributes` which creates the bindings
			Object.keys(this.constructor[metaSymbol$9]._uninitializedBindings).forEach(propName => {
				const binding = this.constructor[metaSymbol$9]._uninitializedBindings[propName](this);

				// Add bindings to the instance `metaSymbol` to be set up during `mixin-initialize-bindings`
				this[metaSymbol$9]._bindings.push({
					binding,
					siblingBindingData: {
						parent: {
							source: "scope",
							exports: true
						},
						child: {
							source: "viewModel",
							exports: true,
							name: propName
						},
						bindingAttributeName: propName
					}
				});
			});

			if (super.initialize) {
				super.initialize(props);
			}
		}
	}

	// To prevent inifinite loop, use a named function so we can differentiate
	// make it writable so it can be set elsewhere  
	Object.defineProperty(BindingPropsClass.prototype, 'attributeChangedCallback', {
		value: baseAttributeChangedCallback,
		writable: true
	});

	return BindingPropsClass;
};

// We can't set `observedAttributes` on the `StacheElement.prototype` as static properties are
// not copied over with `Object.create`
var initializeObservedAttributes = function initializeObservedAttributes (ctr) {
	Object.defineProperty(ctr, 'observedAttributes', {
		get () {
			// We only want to return `observedAttributes` if we have a `bind` on the
			// property definition
			let hasBindDefinition = false;
			// Run finalizeClass to set up the property definitions
			mixins$6.finalizeClass(this);
			
			if(this[metaSymbol$9] === undefined) {
				this[metaSymbol$9] = {};
			}
			if(this[metaSymbol$9]._uninitializedBindings === undefined) {
				this[metaSymbol$9]._uninitializedBindings = {};
			}

			// Check that we have property definitions
			const definitions = this.prototype._define && this.prototype._define.definitions;
			if (definitions) {
				// Run through all defitions so we can check if they have a `bind` function
				Object.keys(definitions).forEach(propName => {
					const definition = definitions[propName];
					if (typeof definition.bind === 'function') {
						const bindFn = definition.bind(propName, this);
						// Set up the bindings so that they can be called during initialize
						// to setup binding starts
						this[metaSymbol$9]._uninitializedBindings[propName] = bindFn;
						hasBindDefinition = true;
					}
				});
			}
			// Only return `this.observedAttributes` if we have binds otherwise
			// we create an inifinite loop
			return hasBindDefinition ? this.observedAttributes : [];
		}
	});
};
mixinBindBehaviour.initializeObservedAttributes = initializeObservedAttributes;

const { initializeObservedAttributes: initializeObservedAttributes$1 } = mixinBindBehaviour;


const { createConstructorFunction: createConstructorFunction$3 } = mixins;

const initializeSymbol = Symbol.for("can.initialize");
const teardownHandlersSymbol$1 = Symbol.for("can.teardownHandlers");
const isViewSymbol$3 = Symbol.for("can.isView");


// Calling a renderer like {{foo()}} gets the template scope
// added no matter what. This checks for that condition.
// https://github.com/canjs/can-stache/issues/719
function rendererWasCalledWithData(scope) {
	return scope instanceof canViewScope_4_13_7_canViewScope &&
		scope._parent &&
		scope._parent._context instanceof canViewScope_4_13_7_canViewScope.TemplateContext;
}

function addContext(rawRenderer, tagData) {
	function renderer(data) {
		if(rendererWasCalledWithData(data)) {
			return rawRenderer(tagData.scope.addLetContext(data._context));
		} else {
			// if it was called programmatically (not in stache), just add the data
			return rawRenderer(tagData.scope.addLetContext(data));
		}
	}
	// Marking as a view will add the template scope ... but it should
	// already be present in `tagData.scope`.
	// However, I mark this as a renderer because that is what it is.
	renderer[isViewSymbol$3] = true;
	return renderer;
}

function DeriveElement(BaseElement = HTMLElement) {
	class StacheElement extends
	// add lifecycle methods
	// this needs to happen after other mixins that implement these methods
	// so that this.<lifecycleMethod> is the actual lifecycle method which
	// controls whether the methods farther "down" the chain are called
	mixinLifecycleMethods(
		// mixin .bindings() method and behavior
		mixinBindings(
			// Find all prop definitions and extract `{ bind: () => {} }` for binding initialization
			mixinBindBehaviour(
				// Initialize the bindings
				mixinInitializeBindings(
					// mix in viewModel symbol used by can-stache-bindings
					mixinViewmodelSymbol(
						// mix in stache renderer from `static view` property
						mixinStacheView(
							// add getters/setters from `static props` property
							mixinProps(BaseElement)
						)
					)
				)
			)
		)
	) {
		[initializeSymbol](el, tagData) {


			const teardownBindings = canStacheBindings_5_0_5_canStacheBindings.behaviors.viewModel(
				el,
				tagData,
				function makeViewModel(initialViewmodelData) {
					for(let prop in tagData.templates) {
						// It's ok to modify the argument. The argument is created
						// just for what gets passed into creating the VM.
						initialViewmodelData[prop] = addContext(tagData.templates[prop], tagData);
					}
					el.render(initialViewmodelData);
					return el;
				}
			);


			if (el[teardownHandlersSymbol$1]) {
				el[teardownHandlersSymbol$1].push(teardownBindings);
			}
		}
	}

	const StacheElementConstructorFunction = createConstructorFunction$3(
		StacheElement
	);

	// Initialize the `observedAttributes`
	initializeObservedAttributes$1(StacheElementConstructorFunction);

	return StacheElementConstructorFunction;
}

var canStacheElement = canNamespace_1_0_0_canNamespace.StacheElement = DeriveElement();

var Compute$1 = function(newVal) {
	if (arguments.length) {
		return canReflect_1_19_2_canReflect.setValue(this, newVal);
	} else {
		return canReflect_1_19_2_canReflect.getValue(this);
	}
};

var translationHelpers = new WeakMap();

var makeCompute = function(observable) {
	var compute = Compute$1.bind(observable);
	compute.on = compute.bind = compute.addEventListener = function(
		event,
		handler
	) {
		var translationHandler = translationHelpers.get(handler);
		if (!translationHandler) {
			translationHandler = function(newVal, oldVal) {
				handler.call(compute, { type: "change" }, newVal, oldVal);
			};
			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				Object.defineProperty(translationHandler, "name", {
					value:
						"translationHandler(" +
						event +
						")::" +
						canReflect_1_19_2_canReflect.getName(observable) +
						".onValue(" +
						canReflect_1_19_2_canReflect.getName(handler) +
						")"
				});
			}
			//!steal-remove-end
			translationHelpers.set(handler, translationHandler);
		}
		canReflect_1_19_2_canReflect.onValue(observable, translationHandler);
	};
	compute.off = compute.unbind = compute.removeEventListener = function(
		event,
		handler
	) {
		canReflect_1_19_2_canReflect.offValue(observable, translationHelpers.get(handler));
	};

	canReflect_1_19_2_canReflect.assignSymbols(compute, {
		"can.getValue": function() {
			return canReflect_1_19_2_canReflect.getValue(observable);
		},
		"can.setValue": function(newVal) {
			return canReflect_1_19_2_canReflect.setValue(observable, newVal);
		},
		"can.onValue": function(handler, queue) {
			return canReflect_1_19_2_canReflect.onValue(observable, handler, queue);
		},
		"can.offValue": function(handler, queue) {
			return canReflect_1_19_2_canReflect.offValue(observable, handler, queue);
		},
		"can.valueHasDependencies": function() {
			return canReflect_1_19_2_canReflect.valueHasDependencies(observable);
		},
		"can.getPriority": function() {
			return canReflect_1_19_2_canReflect.getPriority(observable);
		},
		"can.setPriority": function(newPriority) {
			canReflect_1_19_2_canReflect.setPriority(observable, newPriority);
		},
		"can.isValueLike": true,
		"can.isFunctionLike": false
	});
	compute.isComputed = true;
	return compute;
};

// # String Coercion Helper Functions

// ## stringify
// Converts an object, array, Map or List to a string.
// It attempts the following flow to convert to a string:
// if `obj` is an object:
//   - call `.serialize` on `obj`, if available
//   - shallow copy `obj` using `.slice` or `can-reflect.assign`
//   - convert each proprety to a string recursively
// else
//   - call `.toString` on `obj`, if available.
function stringify(obj) {
	if (obj && typeof obj === "object") {
		if ("serialize" in obj) {
			obj = obj.serialize();

		// Get array from array-like or shallow-copy object.
		} else if (typeof obj.slice === "function") {
			obj = obj.slice();
		} else {
			canReflect_1_19_2_canReflect.assign({}, obj);
		}

		// Convert each object property or array item into a string.
		canReflect_1_19_2_canReflect.eachKey(obj, function(val, prop) {
			obj[prop] = stringify(val);
		});

	// If `obj` supports `.toString` call it.
	} else if (obj !== undefined && obj !== null && (typeof obj.toString === "function" )) {
		obj = obj.toString();
	}

	return obj;
}

// ## stringCoercingMapDecorator
// Coercies the arguments of `can-map.attr` to strings.
// everything in the backing Map is a string
// add type coercion during Map setter to coerce all values to strings so unexpected conflicts don't happen.
// https://github.com/canjs/canjs/issues/2206
// A proposal to change this behavior is currently open:
// https://github.com/canjs/can-route/issues/125
function stringCoercingMapDecorator(map) {
	var decoratorSymbol = canSymbol_1_7_0_canSymbol.for("can.route.stringCoercingMapDecorator");

	if (!map.attr[decoratorSymbol]) {
		var attrUndecoratedFunction = map.attr;

		map.attr = function(key) {

			var serializable = typeof key === "string" &&
				(this.define === undefined || this.define[key] === undefined || !!this.define[key].serialize),
				args;

			if (serializable) { // if setting non-str non-num attr
				args = stringify(Array.apply(null, arguments));
			} else {
				args = arguments;
			}

			return attrUndecoratedFunction.apply(this, args);
		};

		canReflect_1_19_2_canReflect.setKeyValue(map.attr, decoratorSymbol, true);
	}

	return map;
}

var stringCoercingMapDecorator_1 = stringCoercingMapDecorator;
var stringify_1 = stringify;

var stringCoercion = {
	stringCoercingMapDecorator: stringCoercingMapDecorator_1,
	stringify: stringify_1
};

var stringify$1 = stringCoercion.stringify;

var Stringify = {};
Stringify[canSymbol_1_7_0_canSymbol.for("can.new")] = function(value) {
	return stringify$1(value);
};
Stringify[canSymbol_1_7_0_canSymbol.for("can.isMember")] = function(value) {
	return typeof value === "string";
};

class RouteData extends canObservableObject {
	static get propertyDefaults() {
		return {
			type: Stringify
		};
	}
}

var routedata = RouteData;

var urlDataObservable = new canSimpleObservable_2_5_0_canSimpleObservable(null);

canReflect_1_19_2_canReflect.setName(urlDataObservable, "route.urlData");

var bindingProxy = {
	defaultBinding: null,
	urlDataObservable: urlDataObservable,
	bindings: {},
	call: function() {
		var args = canReflect_1_19_2_canReflect.toArray(arguments),
			prop = args.shift(),
			binding = urlDataObservable.value;
		if (binding === null) {
			throw new Error("there is no current binding!!!");
		}
		var method = binding[prop.indexOf("can.") === 0 ? canSymbol_1_7_0_canSymbol.for(prop) : prop];
		if (method.apply) {
			return method.apply(binding, args);
		} else {
			return method;
		}
	}
};
var bindingProxy_1 = bindingProxy;

var regexps = {
	curlies: /\{\s*([\w.]+)\s*\}/g,
	colon: /\:([\w.]+)/g
};

/**
 * @module {function} can-diff/map/map
 * @parent can-diff
 *
 * @description Return a difference of two maps or objects.
 *
 * @signature `diffMap(oldObject, newObject)`
 *
 * Find the differences between two objects, based on properties and values.
 *
 * ```js
 * var diffObject = require("can-diff/map/map");
 *
 * diffMap({a: 1, b: 2}, {b: 3, c: 4})) // ->
 *   [{key: "a", type: "remove"},
 *    {key: "b", type: "set": value: 3},
 *    {key: "c", type: "add", "value": 4}]
 * ```
 *
 * @param {Object} oldObject The object to diff from.
 * @param {Object} newObject The object to diff to.
 * @return {Array} An array of object-[can-symbol/types/Patch patch] objects
 *
 * The object-patch object format has the following keys:
 * - **type**:  the type of operation on this property: add, remove, or set
 * - **key**:   the mutated property on the new object
 * - **value**: the new value (if type is "add" or "set")
 *
 */
var map$2 = function(oldObject, newObject){
	var oldObjectClone,
		patches = [];

	// clone oldObject so properties can be deleted
	oldObjectClone = canReflect_1_19_2_canReflect.assignMap({}, oldObject);

    canReflect_1_19_2_canReflect.eachKey(newObject, function(value, newProp){
        // look for added properties
        if (!oldObject || !oldObject.hasOwnProperty(newProp)) {
            patches.push({
                key: newProp,
                type: 'add',
                value: value
            });
        // look for changed properties
        } else if (newObject[newProp] !== oldObject[newProp]) {
            patches.push({
                key: newProp,
                type: 'set',
                value: value
            });
        }

        // delete properties found in newObject
        // so we can find removed properties
        delete oldObjectClone[newProp];
    });

	// loop over removed properties
	for (var oldProp in oldObjectClone) {
		patches.push({
			key: oldProp,
			type: 'delete'
		});
	}

	return patches;
};

// This file contains the function that allows the registration of routes










// `RegExp` used to match route variables of the type '{name}'.
// Any word character or a period is matched.

// ### removeBackslash
// Removes all backslashes (`\`) from a string.
function removeBackslash(string) {
	return string.replace(/\\/g, "");
}

// ### wrapQuote
// Converts input to a string and readies string for regex
// input by escaping the following special characters: `[ ] ( ) { } \ ^ $ . | ? * +`.
function wrapQuote(string) {
	return (string + "")
		.replace(/([.?*+\^$\[\]\\(){}|\-])/g, "\\$1");
}

var RouteRegistry = {
	routes:  {},
	register: function(url, defaults) {
		// If the root ends with a forward slash (`/`)
		// and url starts with a forward slash (`/`), remove the leading
		// forward slash (`/`) of the url.
		var root = bindingProxy_1.call("root");

		if ( root.lastIndexOf("/") === root.length - 1 && url.indexOf("/") === 0 ) {
			url = url.substr(1);
		}

		// `matcher` will be a regex
		// fall back to legacy `:foo` RegExp if necessary
		var matcher;
		if (regexps.colon.test(url)) {
			//!steal-remove-start
			if (process.env.NODE_ENV !== "production") {
				dev.warn("update route \"" + url + "\" to \"" + url.replace(regexps.colon, function(name, key) {
					return "{" + key + "}";
				}) + "\"");
			}
			//!steal-remove-end

			matcher = regexps.colon;
		} else {
			matcher = regexps.curlies;
		}

		defaults = defaults || {};

		// Extract the variable names and replace with `RegExp` that will match
		// an actual URL with values.
		var lastIndex = matcher.lastIndex = 0,
			names = [],
			res,
			test = "",
			next,
			querySeparator = bindingProxy_1.call("querySeparator"),
			matchSlashes = bindingProxy_1.call("matchSlashes");

		// res will be something like ["{foo}","foo"]
		while (res = matcher.exec(url)) {
			names.push(res[1]);
			test += removeBackslash(url.substring(lastIndex, matcher.lastIndex - res[0].length));
			// If matchSlashes is false (the default) don't greedily match any slash in the string, assume its part of the URL
			next = "\\" + (removeBackslash(url.substr(matcher.lastIndex, 1)) || querySeparator+(matchSlashes? "": "|/"));
			// A name without a default value HAS to have a value.
			// A name that has a default value can be empty.
			// The `\\` is for string-escaping giving single `\` for `RegExp` escaping.
			test += "([^" + next + "]" + (defaults[res[1]] ? "*" : "+") + ")";
			lastIndex = matcher.lastIndex;
		}
		test += removeBackslash(url.substr(lastIndex));

		//!steal-remove-start
		if (process.env.NODE_ENV !== "production") {
			// warn if new route uses same map properties as an existing route
			canReflect_1_19_2_canReflect.eachKey(RouteRegistry.routes, function(r) {
				var existingKeys = r.names.concat(Object.keys(r.defaults)).sort(),
					keys = names.concat(Object.keys(defaults)).sort(),
					sameMapKeys = !list(existingKeys, keys).length,
					sameDefaultValues = !map$2(r.defaults, defaults).length,
					//the regex removes the trailing slash
					matchingRoutesWithoutTrailingSlash = r.route.replace(/\/$/, "") === url.replace(/\/$/, "");

				if (sameMapKeys && sameDefaultValues && !matchingRoutesWithoutTrailingSlash) {
					dev.warn("two routes were registered with matching keys:\n" +
						"\t(1) route.register(\"" + r.route + "\", " + JSON.stringify(r.defaults) + ")\n" +
						"\t(2) route.register(\"" + url + "\", " + JSON.stringify(defaults) + ")\n" +
						"(1) will always be chosen since it was registered first");
				}
			});
		}
		//!steal-remove-end

		// Add route in a form that can be easily figured out.
		return RouteRegistry.routes[url] = {
			// A regular expression that will match the route when variable values
			// are present; i.e. for (`{page}/{type}`) the `RegExp` is `/([\w\.]*)/([\w\.]*)/` which
			// will match for any value of `{page}` and `{type}` (word chars or period).
			test: new RegExp("^" + test + "($|" + wrapQuote(querySeparator) + ")"),
			// The original URL, same as the index for this entry in routes.
			route: url,
			// An `array` of all the variable names in this route.
			names: names,
			// Default values provided for the variables.
			defaults: defaults,
			// The number of parts in the URL separated by `/`.
			length: url.split("/").length
		};
	}
};

var register = RouteRegistry;

var digitTest = /^\d+$/,
	keyBreaker = /([^\[\]]+)|(\[\])/g,
	paramTest = /([^?#]*)(#.*)?$/,
	entityRegex = /%([^0-9a-f][0-9a-f]|[0-9a-f][^0-9a-f]|[^0-9a-f][^0-9a-f])/i,
	startChars = {"#": true,"?": true},
	prep = function (str) {
		if (startChars[str.charAt(0)] === true) {
			str = str.substr(1);
		}
		str = str.replace(/\+/g, ' ');

		try {
			return decodeURIComponent(str);
		}
		catch (e) {
			return decodeURIComponent(str.replace(entityRegex, function(match, hex) {
				return '%25' + hex;
			}));
		}
	};

function isArrayLikeName(name) {
	return digitTest.test(name) || name === '[]';
}


function idenity(value){ return value; }

var canDeparam_1_2_3_canDeparam = canNamespace_1_0_0_canNamespace.deparam = function (params, valueDeserializer) {
	valueDeserializer = valueDeserializer || idenity;
	var data = {}, pairs, lastPart;
	if (params && paramTest.test(params)) {
		pairs = params.split('&');
		pairs.forEach(function (pair) {
			var parts = pair.split('='),
				key = prep(parts.shift()),
				value = prep(parts.join('=')),
				current = data;
			if (key) {
				parts = key.match(keyBreaker);
				for (var j = 0, l = parts.length - 1; j < l; j++) {
					var currentName = parts[j],
						nextName = parts[j + 1],
						currentIsArray = isArrayLikeName(currentName) && current instanceof Array;
					if (!current[currentName]) {
						if(currentIsArray) {
							current.push( isArrayLikeName(nextName) ? [] : {} );
						} else {
							// If what we are pointing to looks like an `array`
							current[currentName] = isArrayLikeName(nextName) ? [] : {};
						}

					}
					if(currentIsArray) {
						current = current[current.length - 1];
					} else {
						current = current[currentName];
					}

				}
				lastPart = parts.pop();
				if ( isArrayLikeName(lastPart) ) {
					current.push(valueDeserializer(value));
				} else {
					current[lastPart] = valueDeserializer(value);
				}
			}
		});
	}
	return data;
};

// ## Helper Functions

// ### decode
// Restore escaped HTML from its URI value.
// It isn't compatable with named character references (`&copy;`, etc).
function decode(str) {
	try {
		return decodeURIComponent(str);
	} catch(ex) {
		return unescape(str);
	}
}

// ### toURLFragment
// If the `root` ends with `/` and the url starts with it, remove `/`.
// TODO: I'm not totally sure this belongs here. This might be shifted to can-route-pushstate.
function toURLFragment(url) {
	var root = bindingProxy_1.call("root");
	if (root.lastIndexOf("/") === root.length - 1 && url.indexOf("/") === 0) {
		url = url.substr(1);
	}
	return url;
}

// ### canRoute_getRule
function canRoute_getRule(url) {
	url = toURLFragment(url);
	// See if the url matches any routes by testing it against the `route.test` `RegExp`.
	// By comparing the URL length the most specialized route that matches is used.
	var route = {
		length: -1
	};
	canReflect_1_19_2_canReflect.eachKey(register.routes, function(temp, name) {
		if (temp.test.test(url) && temp.length > route.length) {
			route = temp;
		}
	});
	// If a route was matched.
	if (route.length > -1) {
		return route;
	}
}

function canRoute_deparam(url) {

	var route = canRoute_getRule(url),
		querySeparator = bindingProxy_1.call("querySeparator"),
		paramsMatcher = bindingProxy_1.call("paramsMatcher");

	url = toURLFragment(url);

	// If a route was matched.
	if (route) {
		// Since `RegExp` backreferences are used in `route.test` (parens)
		// the parts will contain the full matched string and each variable (back-referenced) value.
		var parts = url.match(route.test),
			// Start will contain the full matched string; parts contain the variable values.
			start = parts.shift(),
			// The remainder will be the `&amp;key=value` list at the end of the URL.
			remainder = url.substr(start.length - (parts[parts.length - 1] === querySeparator ? 1 : 0)),
			// If there is a remainder and it contains a `&amp;key=value` list deparam it.
			obj = (remainder && paramsMatcher.test(remainder)) ? canDeparam_1_2_3_canDeparam(remainder.slice(1)) : {};

		// Add the default values for this route.
		obj = canReflect_1_19_2_canReflect.assignDeep(canReflect_1_19_2_canReflect.assignDeep({}, route.defaults), obj);
		// Overwrite each of the default values in `obj` with those in
		// parts if that part is not empty.
		parts.forEach(function (part, i) {
			if (part && part !== querySeparator) {
				obj[route.names[i]] = decode(part);
			}
		});
		return obj;
	}
	// If no route was matched, it is parsed as a `&amp;key=value` list.
	if (url.charAt(0) !== querySeparator) {
		url = querySeparator + url;
	}
	return paramsMatcher.test(url) ? canDeparam_1_2_3_canDeparam(url.slice(1)) : {};
}

canRoute_deparam.getRule = canRoute_getRule;

var deparam_1 = canRoute_deparam;

var canParam_1_2_0_canParam = createCommonjsModule(function (module) {


var standardsMode = false;

function buildParam(prefix, obj, add) {
	if (Array.isArray(obj)) {
		for (var i = 0, l = obj.length; i < l; ++i) {
			var inner = obj[i];
			var shouldIncludeIndex = typeof inner === 'object';
			var arrayIndex = shouldIncludeIndex ? '[' + i + ']' : '[]';
			buildParam(prefix + arrayIndex, inner, add);
		}
	} else if ( obj && typeof obj === "object" ) {
		for (var name in obj) {
			buildParam(prefix + '[' + name + ']', obj[name], add);
		}
	} else {
		add(prefix, obj);
	}
}

if ( canNamespace_1_0_0_canNamespace.param ) {
	throw new Error( "You can't have two versions of can-param, check your dependencies" );
} else {
	module.exports = canNamespace_1_0_0_canNamespace.param = function param(object) {
		var pairs = [],
			add = function (key, value) {
				value = standardsMode && value == null ? '' : value;
				pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
			};
		for (var name in object) {
			if (!standardsMode || typeof object[name] !== 'undefined') {
				buildParam(name, object[name], add);
			}
		}
		return pairs.join('&')
			.replace(/%20/g, '+');
	};

	/**
	 * @function can-param.setStandardsMode setStandardsMode
	 * @parent can-param.methods
	 * @description Set whether to treat null and undefined specially when serializing
	 * 
	 * @signature `param.setStandardsMode(boolean)`
	 *
	 * Set whether to serialize values in a manner more consistent with jQuery[1] and URLSearchParams[2], or to use the classic
	 * can-param value serialization.  By default this value is false (classic mode).
	 *
	 * The differences between the two are:
	 * - `null` serializes to an empty string in standards mode, "null" in classic mode
	 * - `undefined` is removed from the serialized form entirely in standards mode, serialized to "undefined" in classic mode
	 *
	 * All other values are treated the same in both modes.
	 *
	 * @param  {boolean} value `true` to use DOM/jQuery style param serialization, `false` to use classic can-param serializtion
	 *
	 * @body
	 * <hr>
	 * [1] [https://api.jquery.com/jquery.param/]
   * 
	 * [2] [https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams]
	 */
	canNamespace_1_0_0_canNamespace.param.setStandardsMode = function (value) {
		standardsMode = !!value;
	};
}
});

// ## matchesData
// Checks if a route matches the data provided. If any route variable
// is not present in the data, the route does not match. If all route
// variables are present in the data, the number of matches is returned
// to allow discerning between general and more specific routes.
function matchesData(route, data) {
	var count = 0,
		defaults = {};

	// Look at default route values, if they match increment count
	for (var name in route.defaults) {
		if (route.defaults[name] === data[name]) {
			defaults[name] = 1;
			count++;
		}
	}

	for (var i = 0; i < route.names.length; i++) {
		// If a route name isn't present in data, the route doesn't match.
		if (!data.hasOwnProperty(route.names[i])) {
			return -1;
		}
		if (!defaults[route.names[i]]) {
			count++;
		}
	}

	return count;
}

// ## getMatchedRoute

function getMatchedRoute(data, routeName) {
	// Check if the provided data keys match the names in any routes;
	// Get the one with the most matches.
	var route,
		// Need to have at least 1 match.
		matches = 0,
		matchCount,
		propCount = 0;

	delete data.route;

	canReflect_1_19_2_canReflect.eachKey(data, function () {
		propCount++;
	});
	// Otherwise find route.
	canReflect_1_19_2_canReflect.eachKey(register.routes, function (temp, name) {
		// best route is the first with all defaults matching

		matchCount = matchesData(temp, data);
		if (matchCount > matches) {
			route = temp;
			matches = matchCount;
		}
		if (matchCount >= propCount) {
			return false;
		}
	});
	// If we have a route name in our `register` data, and it's
	// just as good as what currently matches, use that
	if (register.routes[routeName] && matchesData(register.routes[routeName], data) === matches) {
		route = register.routes[routeName];
	}
	// If this is match...
	return route;
}
function paramFromRoute(route, data) {
	var cpy,
		res,
		after,
		matcher;
	if (route) {

		cpy = canReflect_1_19_2_canReflect.assignMap({}, data);
		// fall back to legacy :foo RegExp if necessary
		matcher = regexps.colon.test(route.route) ? regexps.colon : regexps.curlies;
		// Create the url by replacing the var names with the provided data.
		// If the default value is found an empty string is inserted.
		res = route.route.replace(matcher, function (whole, name) {
			delete cpy[name];
			return data[name] === route.defaults[name] ? "" : encodeURIComponent(data[name]);
		})
		.replace("\\", "");
		// Remove matching default values
		canReflect_1_19_2_canReflect.eachKey(route.defaults, function (val, name) {
			if (cpy[name] === val) {
				delete cpy[name];
			}
		});
		// The remaining elements of data are added as
		// `&amp;` separated parameters to the url.
		after = canParam_1_2_0_canParam(cpy);
		// if we are paraming for setting the hash
		// we also want to make sure the route value is updated
		//if (_setRoute) {
		//    register.matched(route.route);
		//}
		return res + (after ? bindingProxy_1.call("querySeparator") + after : "");
	}
	// If no route was found, there is no hash URL, only paramters.
	return canReflect_1_19_2_canReflect.size(data) === 0 ? "" :bindingProxy_1.call("querySeparator") + canParam_1_2_0_canParam(data);
}

function canRoute_param(data, currentRouteName) {
 	return paramFromRoute(getMatchedRoute(data, currentRouteName), data);
}
var param_1 = canRoute_param;
canRoute_param.paramFromRoute = paramFromRoute;
canRoute_param.getMatchedRoute = getMatchedRoute;

// ### formatAttributes
// Creates HTML-like attributes from an object.
// It escapes hyperlink references.
function formatAttributes(props) {
	var tags = [];
	canReflect_1_19_2_canReflect.eachKey(props, function(value, name) {
		// Converts `"className"` to `"class"`.
		var attributeName = name === "className" ? "class" : name,

			// Escapes `value` if `name` is `"href"`.
			attributeValue = name === "href" ? value : canString_1_1_0_canString.esc(value);

		tags.push(attributeName + "=\"" + attributeValue + "\"");
	});
	return tags.join(" ");
}

// ### matchCheck
// It recursively compares property values in `matcher` to those in `source`.
// It returns `false` if there's a property in `source` that's not in `matcher`,
// or if the two values aren't loosely equal.
function matchCheck(source, matcher) {
	/*jshint eqeqeq:false*/
	for(var property in source) {
		var sourceProperty = source[property],
			matcherProperty = matcher[property];

		if (sourceProperty && matcherProperty &&
			typeof sourceProperty === "object" && typeof matcher === "object"
		) {
			return matchCheck(sourceProperty, matcherProperty);
		}

		if (sourceProperty != matcherProperty) {
			return false;
		}
	}
	return true;
}

// ### canRoute_url
function canRoute_url(options, merge) {
	if (merge) {
		var baseOptions = deparam_1( bindingProxy_1.call("can.getValue") );
		options = canReflect_1_19_2_canReflect.assignMap(canReflect_1_19_2_canReflect.assignMap({}, baseOptions), options);
	}
	return bindingProxy_1.call("root") + param_1(options);
}

var urlHelpers = {
	url: canRoute_url,

	link: function canRoute_link(name, options, props, merge) {
		return "<a " + formatAttributes(
			canReflect_1_19_2_canReflect.assignMap({
				href: canRoute_url(options, merge)
			}, props)) + ">" + name + "</a>";
	},

	isCurrent: function canRoute_isCurrent(options, subsetMatch) {
		var getValueSymbol = bindingProxy_1.call("can.getValue");

		if (subsetMatch) {
			// Everything in `options` shouhld be in `baseOptions`.
			var baseOptions = deparam_1( getValueSymbol );
			return matchCheck(options, baseOptions);
		} else {
			return getValueSymbol === param_1(options);
		}
	}
};

// Regular expression for identifying &amp;key=value lists.
var paramsMatcher = /^(?:&[^=]+=[^&]*)+/;











function getHash(){
    var loc = location_1();
    return loc.href.split(/#!?/)[1] || "";
}

function HashchangeObservable() {
    var dispatchHandlers =  this.dispatchHandlers.bind(this);
    var self = this;
		this._value = "";
    this.handlers = new canKeyTree_1_2_2_canKeyTree([Object,Array],{
        onFirst: function(){
            self._value = getHash();
            canDomEvents_1_3_13_canDomEvents.addEventListener(window, 'hashchange', dispatchHandlers);
        },
        onEmpty: function(){
            canDomEvents_1_3_13_canDomEvents.removeEventListener(window, 'hashchange', dispatchHandlers);
        }
    });
}
HashchangeObservable.prototype = Object.create(canSimpleObservable_2_5_0_canSimpleObservable.prototype);
HashchangeObservable.constructor = HashchangeObservable;
canReflect_1_19_2_canReflect.assign(HashchangeObservable.prototype,{
    // STUFF NEEDED FOR can-route integration
    paramsMatcher: paramsMatcher,
    querySeparator: "&",
    // don't greedily match slashes in routing rules
    matchSlashes: false,
    root: "#!",
    dispatchHandlers: function() {
        var old = this._value;
        this._value = getHash();
        if(old !== this._value) {
            canQueues_1_3_2_canQueues.enqueueByQueue(this.handlers.getNode([]), this, [this._value, old]
                //!steal-remove-start
                /* jshint laxcomma: true */
                , null
                , [ canReflect_1_19_2_canReflect.getName(this), "changed to", this._value, "from", old ]
                /* jshint laxcomma: false */
                //!steal-remove-end
            );
        }
    },
    get: function(){
        canObservationRecorder_1_3_1_canObservationRecorder.add(this);
        return getHash();
    },
    set: function(path){
        var loc = location_1();
        if(!path && !loc.hash) {

        } else if(loc.hash !== "#" + path) {
            loc.hash = "!" + path;
        }
        return path;
    }
});

Object.defineProperty(HashchangeObservable.prototype, "value", {
	get: function(){
		return canReflect_1_19_2_canReflect.getValue(this);
	},
	set: function(value){
		canReflect_1_19_2_canReflect.setValue(this, value);
	}
});

canReflect_1_19_2_canReflect.assignSymbols(HashchangeObservable.prototype,{
	"can.getValue": HashchangeObservable.prototype.get,
	"can.setValue": HashchangeObservable.prototype.set,
	"can.onValue": HashchangeObservable.prototype.on,
	"can.offValue": HashchangeObservable.prototype.off,
	"can.isMapLike": false,
	"can.valueHasDependencies": function(){
		return true;
	},
	//!steal-remove-start
	"can.getName": function() {
		return "HashchangeObservable<" + this._value + ">";
	},
	//!steal-remove-end
});

var canRouteHash_1_0_2_canRouteHash = HashchangeObservable;

/* globals WorkerGlobalScope */
// A bit of weirdness to avoid complaining linters
var funcConstructor = Function;


/**
 * @module {function} can-globals/is-browser-window/is-web-worker is-web-worker
 * @parent can-globals/modules
 * @signature `isWebWorker()`
 *
 * Returns `true` if the code is running within a [web worker](https://developer.mozilla.org/en-US/docs/Web/API/Worker).
 *
 * ```js
 * var isWebWorker = require("can-globals/is-web-worker/is-web-worker");
 * var GLOBAL = require("can-globals/global/global");
 *
 * if(isWebWorker()) {
 *   ...
 * }
 * ```
 *
 * @return {Boolean} True if the environment is a web worker.
 */

canGlobals_1_2_2_canGlobalsInstance.define('isWebWorker', function(){
    var global = funcConstructor('return this')();
    return typeof WorkerGlobalScope !== "undefined" &&
        (global instanceof WorkerGlobalScope);
});

var isWebWorker = canGlobals_1_2_2_canGlobalsInstance.makeExport('isWebWorker');

var stringCoercingMapDecorator$1 = stringCoercion.stringCoercingMapDecorator;











// ## hashchangeObservable
// `hashchangeObservable` is an instance of `Hashchange`, instances of
// `Hashchange` are two-way bound to `window.location.hash` once the
// instances have a listener.
var hashchangeObservable = new canRouteHash_1_0_2_canRouteHash();
bindingProxy_1.bindings.hashchange = hashchangeObservable;
bindingProxy_1.defaultBinding = "hashchange";
bindingProxy_1.urlDataObservable.value = hashchangeObservable;


// ## canRoute
function canRoute(url, defaults) {
	//!steal-remove-start
	if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
		dev.warn("Call route.register(url,defaults) instead of calling route(url, defaults)");
	}
	//!steal-remove-end
	register.register(url, defaults);
	return canRoute;
}


// ## Helper Functions
// A ~~throttled~~ debounced function called multiple times will only fire once the
// timer runs down. Each call resets the timer.
var timer;
// A dummy events object used to dispatch url change events on.
var currentRuleObservable = new canObservation_4_2_0_canObservation(function canRoute_matchedRoute() {
	var url = bindingProxy_1.call("can.getValue");
	return canRoute.rule(url);
});

// ### updateUrl
// If the `route.data` changes, update the hash.
// Using `.serialize()` retrieves the raw data contained in the `observable`.
// This function is ~~throttled~~ debounced so it only updates once even if multiple values changed.
// This might be able to use batchNum and avoid this.
function updateUrl(serializedData) {
	// collect attributes that are changing
	clearTimeout(timer);
	timer = setTimeout(function () {
		// indicate that the hash is set to look like the data
		var serialized = canReflect_1_19_2_canReflect.serialize( canRoute.data ),
			currentRouteName = currentRuleObservable.get(),
			route = param_1.getMatchedRoute(serialized, currentRouteName),
			path = param_1.paramFromRoute(route, serialized);

		bindingProxy_1.call("can.setValue", path);
		var onStartComplete = canRoute._onStartComplete;
		if (onStartComplete) {
			canRoute._onStartComplete = undefined;
			onStartComplete();
		}
	}, 10);
}

// ### updateRouteData
// Deparameterizes the portion of the hash of interest and assign the
// values to the `route.data` removing existing values no longer in the hash.
// updateRouteData is called typically by hashchange which fires asynchronously
// So it’s possible that someone started changing the data before the
// hashchange event fired.  For this reason, it will not set the route data
// if the data is changing or the hash already matches the hash that was set.
function updateRouteData() {
	var hash = bindingProxy_1.call("can.getValue");
	// if the hash data is currently changing, or
	// the hash is what we set it to anyway, do NOT change the hash

	canQueues_1_3_2_canQueues.batch.start();

	var state = canRoute.deparam(hash);
	delete state.route;
	canReflect_1_19_2_canReflect.update(canRoute.data,state);
	canQueues_1_3_2_canQueues.batch.stop();

}


/**
 * @static
 */
Object.defineProperty(canRoute, "routes", {
	/**
	 * @property {Object} routes
	 * @hide
	 *
	 * A list of routes recognized by the router indixed by the url used to add it.
	 * Each route is an object with these members:
	 *
	 *  - test - A regular expression that will match the route when variable values
	 *    are present; i.e. for {page}/{type} the `RegExp` is /([\w\.]*)/([\w\.]*)/ which
	 *    will match for any value of {page} and {type} (word chars or period).
	 *
	 *  - route - The original URL, same as the index for this entry in routes.
	 *
	 *  - names - An array of all the variable names in this route
	 *
	 *  - defaults - Default values provided for the variables or an empty object.
	 *
	 *  - length - The number of parts in the URL separated by '/'.
	 */
 	get: function() {
 		return register.routes;
 	},
	set: function(newVal) {
		return register.routes = newVal;
	}
});

// ## canRoute.defaultBinding
Object.defineProperty(canRoute, "defaultBinding", {
 	get: function() {
		return bindingProxy_1.defaultBinding;
	},
	set: function(newVal) {
		bindingProxy_1.defaultBinding = newVal;
		var observable = bindingProxy_1.bindings[bindingProxy_1.defaultBinding];
		if (observable) {
			bindingProxy_1.urlDataObservable.value = observable;
		}
	}
});

// ## canRoute.urlData
Object.defineProperty(canRoute, "urlData", {
 	get: function() {
		return bindingProxy_1.urlDataObservable.value;
	},
	set: function(newVal) {
		canRoute._teardown();
		bindingProxy_1.urlDataObservable.value = newVal;
	}
});

canReflect_1_19_2_canReflect.assignMap(canRoute, {
	// ## canRoute.param
	param: param_1,
	// ## canRoute.deparam
	deparam: deparam_1,
	// ## canRoute.map
	map: function(data) {
		//!steal-remove-start
		if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
			dev.warn("Set route.data directly instead of calling route.map");
		}
		//!steal-remove-end
		canRoute.data = data;
	},

	// ## canRoute.start
	start: function (val) {
		if (canRoute.data instanceof routedata) {
			var routeData = canRoute.data;
			var definePropertyWithDefault = function(defaults, name) {
				var defaultValue = defaults[name];
				var propertyType = defaultValue != null ? canType_1_1_6_canType.maybeConvert(defaultValue.constructor) : canType_1_1_6_canType.maybeConvert(String);
				canReflect_1_19_2_canReflect.defineInstanceKey(routeData.constructor, name, {
					type: propertyType
				});
			};

			canReflect_1_19_2_canReflect.eachKey(canRoute.routes, function(route) {
				canReflect_1_19_2_canReflect.eachIndex(route.names, function (name) {
					definePropertyWithDefault(route.defaults, name);
				});

				canReflect_1_19_2_canReflect.eachKey(route.defaults, function(value, key) {
					definePropertyWithDefault(route.defaults, key);
				});
			});
		}

		if (val !== true) {
			canRoute._setup();
			if (isBrowserWindow() || isWebWorker()) {
				// We can't use updateRouteData because we want to merge the route data
				// into .data
				var hash = bindingProxy_1.call("can.getValue");
				canQueues_1_3_2_canQueues.batch.start();
				// get teh data
				var state = canRoute.deparam(hash);
				delete state.route;

				canReflect_1_19_2_canReflect.assign(canRoute.data,state);
				canQueues_1_3_2_canQueues.batch.stop();
				updateUrl();
			}
		}
		
		return canRoute;
	},
	// ## canRoute.url
	url: urlHelpers.url,
	link: urlHelpers.link,
	isCurrent: urlHelpers.isCurrent,
	bindings: bindingProxy_1.bindings,

	// ready calls setup
	// setup binds and listens to data changes
	// bind listens to whatever you should be listening to
	// data changes tries to set the path

	// we need to be able to
	// easily kick off calling updateRouteData
	// 	teardown whatever is there
	//  turn on a particular binding

	// called when the route is ready
	_setup: function () {
		if (!canRoute._canBinding) {

			var bindingOptions = {

				// The parent is the hashchange observable
				parent: bindingProxy_1.urlDataObservable.value,
				setParent: updateUrl,

				// The child is route.data
				child: canRoute.serializedObservation,
				setChild: updateRouteData,

				// On init, we do not want the child set to the parent’s value; this is
				// handled by start() for reasons mentioned there.
				onInitDoNotUpdateChild: true,

				// Cycles are allowed because updateUrl is async; if another change
				// happens during its setTimeout, then without cycles the change would
				// be ignored :( TODO: Can this be removed if updateUrl stops using
				// setTimeout in a major version?
				cycles: 1,

				// Listen for changes in the notify queue
				queue: "notify"

			};

			// For debugging: the names that will be assigned to the updateChild and
			// updateParent functions within can-bind
			//!steal-remove-start
			if (typeof process !== "undefined" && process.env.NODE_ENV !== "production") {
				bindingOptions.updateChildName = "can-route.updateRouteData";
				bindingOptions.updateParentName = "can-route.updateUrl";
			}
			//!steal-remove-end

			// Create a new binding with can-bind
			canRoute._canBinding = new canBind_1_5_1_canBind(bindingOptions);

			// …and turn it on!
			canRoute._canBinding.start();

		}
	},
	_teardown: function () {
		if (canRoute._canBinding) {
			canRoute._canBinding.stop();
			canRoute._canBinding = null;
		}
		clearTimeout(timer);
	},

	stop: function() {
		this._teardown();
		return canRoute;
	},

	currentRule: makeCompute( currentRuleObservable ),
	register: register.register,
	rule: function(url) {
		var rule = deparam_1.getRule(url);
		if (rule) {
			return rule.route;
		}
	}
});

// The functions in the following list applied to `canRoute` (e.g. `canRoute.attr('...')`) will
// instead act on the `canRoute.data` observe.

var bindToCanRouteData = function (name, args) {
	if (!canRoute.data[name]) {
		return canRoute.data.addEventListener.apply(canRoute.data, args);
	}
	return canRoute.data[name].apply(canRoute.data, args);
};

["addEventListener","removeEventListener","bind", "unbind", "on", "off"].forEach(function(name) {
	// exposing all internal eventQueue evt’s to canRoute
	canRoute[name] = function(eventName, handler) {
		if (eventName === "__url") {
			return bindingProxy_1.call("can.onValue", handler );
		}
		return bindToCanRouteData(name, arguments);
	};
});

["delegate", "undelegate", "removeAttr", "compute", "_get", "___get", "each"].forEach(function (name) {
	canRoute[name] = function () {
		// `delegate` and `undelegate` require
		// the `can/map/delegate` plugin
		return bindToCanRouteData(name, arguments);
	};
});


var routeData,
	serializedObservation,
	serializedCompute;

function setRouteData(data) {
	routeData = data;
	return routeData;
}

Object.defineProperty(canRoute, "serializedObservation", {
	get: function() {
		if (!serializedObservation) {
			serializedObservation = new canObservation_4_2_0_canObservation(function canRoute_data_serialized() {
				return canReflect_1_19_2_canReflect.serialize( canRoute.data );
			});
		}
		return serializedObservation;
	}
});
Object.defineProperty(canRoute, "serializedCompute", {
	get: function() {
		if (!serializedCompute) {
			serializedCompute = makeCompute(canRoute.serializedObservation);
		}
		return serializedCompute;
	}
});

var viewModelSymbol$3 = canSymbol_1_7_0_canSymbol.for("can.viewModel");
Object.defineProperty(canRoute, "data", {
	get: function() {
		if (routeData) {
			return routeData;
		} else {
			return setRouteData(new routedata());
		}
	},
	set: function(data) {
		if ( canReflect_1_19_2_canReflect.isConstructorLike(data) ) {
			data = new data();
		}
		if (data && data[viewModelSymbol$3] !== undefined) {
			data = data[viewModelSymbol$3];
		}
		// if it’s a map, we make it always set strings for backwards compat
		if ( "attr" in data ) {
			setRouteData( stringCoercingMapDecorator$1(data) );
		} else {
			setRouteData(data);
		}
	}
});

canRoute.attr = function(prop, value) {
	console.warn("can-route: can-route.attr is deprecated. Use methods on can-route.data instead.");
	if ("attr" in canRoute.data) {
		return canRoute.data.attr.apply(canRoute.data, arguments);
	} else {
		if (arguments.length > 1) {
			canReflect_1_19_2_canReflect.setKeyValue(canRoute.data, prop, value);
			return canRoute.data;
		} else if (typeof prop === "object") {
			canReflect_1_19_2_canReflect.assignDeep(canRoute.data,prop);
			return canRoute.data;
		} else if (arguments.length === 1) {
			return canReflect_1_19_2_canReflect.getKeyValue(canRoute.data, prop);
		} else {
			return canReflect_1_19_2_canReflect.unwrap(canRoute.data);
		}
	}
};


canReflect_1_19_2_canReflect.setKeyValue(canRoute, canSymbol_1_7_0_canSymbol.for("can.isFunctionLike"), false);

// LEGACY
canRoute.matched = canRoute.currentRule;
canRoute.current = canRoute.isCurrent;

var canRoute_5_0_2_canRoute = canNamespace_1_0_0_canNamespace.route = canRoute;

var looksLikeOptions = core$1.looksLikeOptions;

var calculateArgs = function(){
	var finalParams,
		finalMerge,
		optionsArg;

	canReflect_1_19_2_canReflect.eachIndex(arguments, function(arg){
		if(typeof arg === "boolean") {
			finalMerge = arg;
		} else if( arg && typeof arg === "object"  ) {
			if(!looksLikeOptions(arg) ) {
				finalParams = core$1.resolveHash(arg);
			} else {
				optionsArg = arg;
			}
		}
	});

	if(!finalParams && optionsArg) {
		finalParams = core$1.resolveHash(optionsArg.hash);
	}
	return {
		finalParams: finalParams || {},
		finalMerge: finalMerge,
		optionsArg: optionsArg
	};
};


// go through arguments ... if there's a boolean ... if there's a plain object
var routeUrl = function(){
	var args = calculateArgs.apply(this, arguments);

	return canRoute_5_0_2_canRoute.url(args.finalParams, typeof args.finalMerge === "boolean" ? args.finalMerge : undefined);
};
core$1.registerHelper('routeUrl', routeUrl);

var routeCurrent = function(){

	var args = calculateArgs.apply(this, arguments);
	var result = canRoute_5_0_2_canRoute.isCurrent( args.finalParams, typeof args.finalMerge === "boolean" ? args.finalMerge : undefined );

	if( args.optionsArg && !(args.optionsArg instanceof expression_1.Call) ) {
		if( result ) {
			return args.optionsArg.fn();
		} else {
			return args.optionsArg.inverse();
		}
	} else {
		return result;
	}
};
routeCurrent.callAsMethod = true;

core$1.registerHelper('routeCurrent', routeCurrent);

var canStacheRouteHelpers_2_0_0_canStacheRouteHelpers = {
	routeUrl: routeUrl,
	routeCurrent: routeCurrent
};

/**
 * @module {function} can-key/sub/sub
 * @parent can-key
 * @hide
 *
 * Replace templated parts of a string with values.
 *
 * @signature `sub(str, data, remove)`
 *
 * `sub` is used to replace templated parts of a string with values.
 *
 * ```js
 * var sub = require("can-key/sub/sub");
 *
 * sub("foo_{bar}", {bar: "baz"}); // -> "foo_baz"
 * ```
 *
 * If `null` or `undefined` values are found, `null` is returned:
 *
 * ```js
 * sub("foo_{bar}", {}); // -> null
 * ```
 *
 * If an object value is found, the templated part of the string is replace with `""`
 * and the object is added to an array that is returned.
 *
 * ```js
 * var data = {element: div, selector: "li" }
 * var res = sub("{element} {selector} click", data);
 * res //-> [" li click", div]
 * ```
 *
 * @param {String} str   a string with {curly brace} delimited property names
 * @param {Object} data  an object from which to read properties
 * @return {String|null|Array} the supplied string with delimited properties replaced with their values
 *                       if all properties exist on the object, null otherwise
 *
 * If `remove` is true, the properties found in delimiters in `str` are removed from `data`.
 *
 *
 */
var sub = function sub(str, data, remove) {
	var obs = [];
	str = str || '';
	obs.push(str.replace(canKey_1_2_1_utils.strReplacer, function (whole, inside) {
		// Convert inside to type.
		var ob = get_1(data, inside);

		if(remove === true) {
			_delete(data, inside);
		}

		if (ob === undefined || ob === null) {
			obs = null;
			return '';
		}
		// If a container, push into objs (which will return objects found).
		if (!canReflect_1_19_2_canReflect.isPrimitive(ob) && obs) {
			obs.push(ob);
			return '';
		}
		return '' + ob;
	}));
	return obs === null ? obs : obs.length <= 1 ? obs[0] : obs;
};

// # can-query-logic/set.js
// This file defines the set mechanics of types.
// It provides ways for types to define how to perform
// `union`, `difference`, `intersection` operations.
//
// It also derives other operators (`isEqual`, `isSubset`, etc) from these
// core operators.
//
// `.memberOf` is a property that defines if a value is within the set. It's
// currently a different thing.





// This is what we are defining
var set$2;

// ## HELPERS =========
//
// Used to make sure an object serializes to itself.
// This makes sure the empty object won't try to clone itself.
var addSerializeToThis = function(obj) {
	return canReflect_1_19_2_canReflect.assignSymbols(obj, {
		"can.serialize": function() {
			return this;
		}
	});
};

// Reverses the arguments of a function.
function reverseArgs(fn) {
	return function(first, second) {
		return fn.call(this, second, first);
	};
}

// This symbol is put on constructor functions to track the comparator operators
// available to that type.
var setComparisonsSymbol = canSymbol_1_7_0_canSymbol.for("can.setComparisons");

// Adds comparators to a type. They are stored like:
// Type[@can.setComparisons] = Map({
//    [type1]: Map({[type2]: {union, different, intersection}})
// })
//
// Why do we need the outer object?
function addComparators(type1, type2, comparators) {
	var comparisons = type1[setComparisonsSymbol];
	if (!type1[setComparisonsSymbol]) {
		comparisons = type1[setComparisonsSymbol] = new Map();
	}
	var subMap = comparisons.get(type1);

	if (!subMap) {
		subMap = new Map();
		comparisons.set(type1, subMap);
	}
	var existingComparators = subMap.get(type2);
	if (existingComparators) {
		for (var prop in comparators) {
			if (existingComparators.hasOwnProperty(prop)) {
				console.warn("Overwriting " + type1.name + " " + prop + " " + type2.name + " comparitor");
			}
			existingComparators[prop] = comparators[prop];
		}
	} else {
		subMap.set(type2, comparators);
	}
}


// This type is used for primitives in JS, but it can be used for
// any value that should only === itself.
function Identity() {}

var typeMap = {
	"number": Identity,
	"string": Identity,
	"undefined": Identity,
	"boolean": Identity
};

// `get.intersection`, etc is used to look within the types
// maps and get the right comparator operators.
var get$1 = {};
/*
var algebraSymbol = {
    "intersection": "∩",
    "union": "∪",
    "difference": "\\"
};
*/

["intersection", "difference", "union"].forEach(function(prop) {
	get$1[prop] = function(forwardComparators, value1, value2) {

		if (value2 === set$2.UNIVERSAL) {
			if (prop === "intersection") {
				return value1;
			}
			if (prop === "union") {
				return set$2.UNIVERSAL;
			}
			if (prop === "difference") {
				return set$2.EMPTY;
			}
		}
		if (value1 === set$2.UNIVERSAL) {
			if (prop === "intersection") {
				return value1;
			}
			if (prop === "union") {
				return set$2.UNIVERSAL;
			}
		}

		if (forwardComparators && forwardComparators[prop]) {
			var result = forwardComparators[prop](value1, value2);
			// console.log("",/*name1,*/ value1, algebraSymbol[prop], /*name2,*/ value2,"=", result);
			if (result === undefined && forwardComparators.undefinedIsEmptySet === true) {
				return set$2.EMPTY;
			} else {
				return result;
			}
		} else {
			throw new Error("Unable to perform " + prop + " between " + set$2.getType(value1).name + " and " + set$2.getType(value2).name);
		}

	};
});



set$2 = {
	// The special types

	// All values within the "universe". Other sets can equal UNIVERSAL.
	UNIVERSAL: canReflect_1_19_2_canReflect.assignSymbols({
		name: "UNIVERSAL"
	}, {
		"can.serialize": function() {
			return this;
		},
		"can.isMember": function(){
			return true;
		}
	}),
	// Nothing
	EMPTY: canReflect_1_19_2_canReflect.assignSymbols({
		name: "EMPTY"
	}, {
		"can.serialize": function() {
			return this;
		},
		"can.isMember": function(){
			return false;
		}
	}),
	// The set exists, but we lack the language to represent it.
	UNDEFINABLE: addSerializeToThis({
		name: "UNDEFINABLE"
	}),
	// We don't know if this exists. Intersection between two paginated sets.
	UNKNOWABLE: addSerializeToThis({
		name: "UNKNOWABLE"
	}),
	Identity: Identity,
	isSpecial: function(setA) {
		return setA === set$2.UNIVERSAL || setA === set$2.EMPTY ||
			setA === set$2.UNDEFINABLE || setA === set$2.UNKNOWABLE;
	},
	isDefinedAndHasMembers: function(setA) {
		if (setA !== set$2.EMPTY && setA !== set$2.UNDEFINABLE && setA !== set$2.UNKNOWABLE) {
			return !!setA;
		} else {
			return false;
		}
	},
	getType: function(value) {
		if (value === set$2.UNIVERSAL) {
			return set$2.UNIVERSAL;
		}
		if (value === set$2.EMPTY) {
			return set$2.EMPTY;
		}
		if (value === set$2.UNKNOWABLE) {
			return set$2.UNKNOWABLE;
		}
		if (value === null) {
			return Identity;
		}
		if (typeMap.hasOwnProperty(typeof value)) {
			return typeMap[typeof value];
		}
		return value.constructor;
	},
	// This tries to get two comparable values from objects.
	// In many ways this is similar to what JavaScript does if it sees
	// `new Date() > new Date()`, it tries to coerce one value into the other value.
	ownAndMemberValue: function(startOwnValue, startMemberValue) {
		// If either side has a value, then try to type-coerse.
		if (startOwnValue != null || startMemberValue != null) {
			// First try to get `.valueOf` from either side
			var ownValue = startOwnValue != null ? startOwnValue.valueOf() : startOwnValue,
				memberValue = startMemberValue != null ? startMemberValue.valueOf() : startMemberValue;

			// If we ot passed a null on either side, return extracted values
			if (startOwnValue == null || startMemberValue == null) {
				return {
					own: ownValue,
					member: memberValue
				};
			}
			// If we read the values, but they aren't the same type ...
			// we will try to convert the member to the same type as the `startOwnValue`'s type.
			// And then read `.valueOf()` from that.
			if (ownValue == null || ownValue.constructor !== memberValue.constructor) {
				memberValue = new startOwnValue.constructor(memberValue).valueOf();
			}
			return {
				own: ownValue,
				member: memberValue
			};
		}
		return {
			own: startMemberValue,
			member: startOwnValue
		};
	},
	getComparisons: function(Type1, Type2) {
		var comparisons = Type1[setComparisonsSymbol];
		if (comparisons) {
			var subMap = comparisons.get(Type1);

			if (subMap) {
				return subMap.get(Type2);
			}
		}
	},
	hasComparisons: function(Type) {
		return !!Type[setComparisonsSymbol];
	},
	defineComparison: function(type1, type2, comparators) {
		addComparators(type1, type2, comparators);
		if (type1 !== type2) {
			var reverse = {};
			for (var prop in comparators) {
				// difference can not be reversed
				if (prop !== "difference") {
					reverse[prop] = reverseArgs(comparators[prop]);
				}

			}
			addComparators(type2, type1, reverse);
		}
	},
	/**
	 * Checks if A is a subset of B.  If A is a subset of B if:
	 * - A \ B = EMPTY (A has nothing outside what's in B)
	 * - A ∩ B = defined
	 */
	isSubset: function(value1, value2) {
		// check primary direction
		if (value1 === value2) {
			return true;
		}
		var Type1 = set$2.getType(value1),
			Type2 = set$2.getType(value2);
		var forwardComparators = set$2.getComparisons(Type1, Type2);
		if (forwardComparators) {
			// A set is a subset, if it intersects with the set, and it has nothing
			// outside the other set.
			var intersection = get$1.intersection(forwardComparators, value1, value2);
			// [a, b] \ [a, b, c]
			var difference = get$1.difference(forwardComparators, value1, value2);
			// they intersect, but value2 has nothing value1 outside value2
			if (intersection === set$2.UNKNOWABLE || difference === set$2.UNKNOWABLE) {
				// {sort: "a", page: 0-2} E {sort: "b", page: 2-3}
				return undefined;
			} else if (intersection !== set$2.EMPTY && difference === set$2.EMPTY) {
				return true;
			} else {
				return false;
			}
		} else {
			throw new Error("Unable to perform subset comparison between " + Type1.name + " and " + Type2.name);
		}
	},
	isProperSubset: function(setA, setB) {
		return set$2.isSubset(setA, setB) && !set$2.isEqual(setA, setB);
	},
	isEqual: function(value1, value2) {
		if (value1 === set$2.UNKNOWABLE || value2 === set$2.UNKNOWABLE) {
			return set$2.UNKNOWABLE;
		}
		//console.group("is", value1, "==", value2);
		var isSpecial1 = set$2.isSpecial(value1),
			isSpecial2 = set$2.isSpecial(value2);

		// Both have to be specail because some other sets will be equal to UNIVERSAL without being UNIVERSAL
		if (isSpecial1 && isSpecial2) {
			return isSpecial1 === isSpecial2;
		}
		var Type1 = set$2.getType(value1),
			Type2 = set$2.getType(value2);
		if (value1 === value2) {
			return true;
		}
		var forwardComparators = set$2.getComparisons(Type1, Type2);
		var reverseComparators = set$2.getComparisons(Type2, Type1);
		if (forwardComparators && reverseComparators) {

			// Two sets are equal if there's an intersection, but not difference
			var intersection = get$1.intersection(forwardComparators, value1, value2);
			var difference = get$1.difference(forwardComparators, value1, value2);
			if (intersection !== set$2.EMPTY && difference === set$2.EMPTY) {
				var reverseIntersection = get$1.intersection(reverseComparators, value2, value1);
				var reverseDifference = get$1.difference(reverseComparators, value2, value1);
				//console.groupEnd();
				return reverseIntersection !== set$2.EMPTY && reverseDifference === set$2.EMPTY;
			} else {
				//console.groupEnd();
				return false;
			}
		} else {
			var values = set$2.ownAndMemberValue(value1, value2);
			if (canReflect_1_19_2_canReflect.isPrimitive(values.own) && canReflect_1_19_2_canReflect.isPrimitive(values.member)) {
				return values.own === values.member;
			} else {
				// try to convert ...
				throw new Error("Unable to perform equal comparison between " + Type1.name + " and " + Type2.name);
			}

		}
	},

	union: function(value1, value2) {
		if (value1 === set$2.UNIVERSAL || value2 === set$2.UNIVERSAL) {
			return set$2.UNIVERSAL;
		}
		if (value1 === set$2.EMPTY) {
			return value2;
		} else if (value2 === set$2.EMPTY) {
			return value1;
		}
		if (value1 === set$2.UNKNOWABLE || value2 === set$2.UNKNOWABLE) {
			return set$2.UNKNOWABLE;
		}
		var Type1 = set$2.getType(value1),
			Type2 = set$2.getType(value2);
		var forwardComparators = set$2.getComparisons(Type1, Type2);
		return get$1.union(forwardComparators, value1, value2);
	},

	intersection: function(value1, value2) {
		if (value1 === set$2.UNIVERSAL) {
			return value2;
		}
		if (value2 === set$2.UNIVERSAL) {
			return value1;
		}
		if (value1 === set$2.EMPTY || value2 === set$2.EMPTY) {
			return set$2.EMPTY;
		}
		if (value1 === set$2.UNKNOWABLE || value2 === set$2.UNKNOWABLE) {
			return set$2.UNKNOWABLE;
		}
		var Type1 = set$2.getType(value1),
			Type2 = set$2.getType(value2);
		var forwardComparators = set$2.getComparisons(Type1, Type2);
		if (forwardComparators) {
			return get$1.intersection(forwardComparators, value1, value2);
		} else {
			throw new Error("Unable to perform intersection comparison between " + Type1.name + " and " + Type2.name);
		}
	},
	difference: function(value1, value2) {
		if (value1 === set$2.EMPTY) {
			return set$2.EMPTY;
		}
		if (value2 === set$2.EMPTY) {
			return value1;
		}
		if (value1 === set$2.UNKNOWABLE || value2 === set$2.UNKNOWABLE) {
			return set$2.UNKNOWABLE;
		}
		var Type1 = set$2.getType(value1),
			Type2 = set$2.getType(value2);
		var forwardComparators = set$2.getComparisons(Type1, Type2);
		if (forwardComparators) {
			return get$1.difference(forwardComparators, value1, value2);
		} else {
			throw new Error("Unable to perform difference comparison between " + Type1.name + " and " + Type2.name);
		}
	},

	indexWithEqual: function(arr, value) {
		for (var i = 0, len = arr.length; i < len; i++) {
			if (set$2.isEqual(arr[i], value)) {
				return i;
			}
		}
		return -1;
	}

};



function identityIntersection(v1, v2) {
	return v1 === v2 ? v1 : set$2.EMPTY;
}

function identityDifference(v1, v2) {
	return v1 === v2 ? set$2.EMPTY : v1;
}

function identityUnion(v1, v2) {
	return v1 === v2 ? v1 : set$2.UNDEFINABLE;
}
var identityComparitor = {
	intersection: identityIntersection,
	difference: identityDifference,
	union: identityUnion
};
set$2.defineComparison(Identity, Identity, identityComparitor);

set$2.defineComparison(set$2.UNIVERSAL, set$2.UNIVERSAL, identityComparitor);

var set_1$1 = set$2;

var replacer =  /\{([^\}]+)\}/g;
// Returns data from a url, given a fixtue URL. For example, given
// "todo/{id}" and "todo/5", it will return an object with an id property
// equal to 5.
var canFixture_3_1_7_dataFromUrl = function dataFromUrl(fixtureUrl, url) {
	if(!fixtureUrl) {
		// if there's no url, it's a match
		return {};
	}

	var order = [],
		// Sanitizes fixture URL
		fixtureUrlAdjusted = fixtureUrl.replace('.', '\\.')
			.replace('?', '\\?'),
		// Creates a regular expression out of the adjusted fixture URL and
		// runs it on the URL we passed in.
		res = new RegExp(fixtureUrlAdjusted.replace(replacer, function (whole, part) {
			order.push(part);
			return "([^\/]+)";
		}) + "$")
			.exec(url),
		data = {};

	// If there were no matches, return null;
	if (!res) {
		return null;
	}

	// Shift off the URL and just keep the data.
	res.shift();
	order.forEach( function (name) {
		// Add data from regular expression onto data object.
		data[name] = res.shift();
	});
	return data;
};

function getValue(value){
    return value == null ? value : value.valueOf();
}

var arrayUnionIntersectionDifference = function arrayUnionIntersectionDifference(arr1, arr2){
    var set = new Set();

    var intersection = [];
    var union = [];
    var difference = arr1.slice(0);


    arr1.forEach(function(value){
        set.add(getValue(value));
        union.push(value);
    });

    arr2.forEach(function(value){
        if(set.has(getValue(value))) {
            intersection.push(value);
            var index = set_1$1.indexWithEqual(difference, value);
            if(index !== -1) {
                difference.splice(index, 1);
            }
        } else {
            union.push(value);
        }
    });

    return {
        intersection: intersection,
        union: union,
        difference: difference
    };
};

function isMemberThatUsesTestOnValues(value) {
	return this.constructor.test(this.values, value);
}

var isMemberThatUsesTestOnValues_1 = isMemberThatUsesTestOnValues;

var comparisonsCommon = {
	isMemberThatUsesTestOnValues: isMemberThatUsesTestOnValues_1
};

/*
 * # types
 * This folder is for SetTypes that are used to compare against a single value.
 * For example, `new comparisons.GreaterThan(5)` is used to compare against 
 */



// this is a placeholder for types that have cycle dependencies
var types = {};

function NotIdentity(value) {
    this.value = value;
}

// Not comparisons ---------
var Identity$1 = set_1$1.Identity;

// Only difference is needed w/ universal
set_1$1.defineComparison(set_1$1.UNIVERSAL, Identity$1,{
    // A \ B -> what's in b, but not in A
    difference: function(universe, value){
        return new NotIdentity(value);
    }
});

// Only difference is needed w/ universal
set_1$1.defineComparison(set_1$1.UNIVERSAL, NotIdentity,{
    // A \ B -> what's in b, but not in A
    difference: function(universe, not){
        return not.value;
    }
});

set_1$1.defineComparison(NotIdentity, NotIdentity,{
    /*
    // not 5 and not 6
    union: function(obj1, obj2){
        // must unroll the value

    },
    // {foo: zed, abc: d}
    intersection: function(obj1, obj2){

    },
    // A \ B -> what's in b, but not in A
    difference: function(obj1, obj2){

    }
    */
});



set_1$1.defineComparison(NotIdentity, Identity$1,{
    // not 5 and not 6
    union: function(not, primitive){
        // NOT(5) U 5
        if( set_1$1.isEqual( not.value, primitive) ) {
            return set_1$1.UNIVERSAL;
        }
        // NOT(4) U 6
        else {
            throw new Error("Not,Identity Union is not filled out");
        }
    },
    // {foo: zed, abc: d}
    intersection: function(not, primitive){
        return set_1$1.isEqual( !not.value, primitive ) ? primitive: set_1$1.EMPTY;
    },
    // A \ B -> what's in b, but not in A
    difference: function difference(not, primitive){
        // NOT(5) \ 3 -> UNDEFINABLE
        // NOT(3) \ 3 -> NOT(3)
        if(set_1$1.isEqual( not.value, primitive )) {
            return not;
        } else {
            return set_1$1.UNDEFINABLE;
        }
    }
});

set_1$1.defineComparison(Identity$1, NotIdentity,{
    difference: function(primitive, not){
        if(set_1$1.isEqual(primitive, not.value)) {
            return primitive;
        } else {
            return set_1$1.UNDEFINABLE;
        }
    }
});

NotIdentity.prototype.isMember = function(value){
	if(this.value  && typeof this.value.isMember === "function") {
		return !this.value.isMember(value);
	} else {
		var values = set_1$1.ownAndMemberValue(this.value, value);
		return values.own !== values.member;
	}

};

var valuesNot = types.Not = NotIdentity;

var comparisons = {
	All: function(values){
		this.values = values;
	}
};

comparisons.All.prototype.isMember = comparisonsCommon.isMemberThatUsesTestOnValues;

var is = comparisons;

comparisons.All.test = function(allValues, recordValues) {
	return allValues.every(function(allValue) {
		return recordValues.some(function(recordValue){
			var values = set_1$1.ownAndMemberValue(allValue, recordValue);
			return values.own === values.member;
		});
	});
};

function makeThrowCannotCompare(type, left, right) {
	return function() {
		throw new Error("can-query-logic: Cannot perform " + type + " between " + left + " and " + right);
	};
}

function throwComparatorAllTypes(type1, type2) {
	return {
		union: makeThrowCannotCompare("union", type1,  type2),
		difference: makeThrowCannotCompare("difference", type1, type2),
		intersection: makeThrowCannotCompare("intersection", type1, type2)
	};
}

function throwComparatorDifference(type1, type2) {
	return {
		difference: makeThrowCannotCompare("difference", type1, type2)
	};
}

var comparators = {
	UNIVERSAL_All: {
		difference: function(universe, all) {
			return new valuesNot(all);
		}
	},
	All_UNIVERSAL: {
		difference: function() {
			return set_1$1.EMPTY;
		}
	},
	All_All: {
		union: function(a, b) {
			return new is.Or([a, b]);
		}
	},
	In_All: throwComparatorDifference("In", "All"),
	All_In: throwComparatorAllTypes("All", "In"),
	NotIn_All: throwComparatorDifference("NotIn", "All"),
	All_NotIn: throwComparatorAllTypes("All", "NotIn"),
	GreaterThan_All: throwComparatorDifference("GreaterThan", "All"),
	All_GreaterThan: throwComparatorAllTypes("All", "GreaterThan"),
	GreaterThanEqual_All: throwComparatorDifference("GreaterThanEqual", "All"),
	All_GreaterThanEqual: throwComparatorAllTypes("All", "GreaterThanEqual"),
	LessThan_All: throwComparatorDifference("LessThan", "All"),
	All_LessThan: throwComparatorAllTypes("All", "LessThan"),
	LessThanEqual_All: throwComparatorDifference("LessThanEqual", "All"),
	All_LessThanEqual: throwComparatorAllTypes("All", "LessThanEqual"),
	All_And: throwComparatorDifference("All", "And"),
	And_All: throwComparatorAllTypes("And",	 "All"),
	All_Or: throwComparatorDifference("All", "Or"),
	Or_All: throwComparatorAllTypes("Or", "All")
};

var comparisons_1 = comparisons;
var comparators_1 = comparators;

var arrayComparisons = {
	comparisons: comparisons_1,
	comparators: comparators_1
};

var isMemberSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.isMember");
// $ne	Matches all values that are not equal to a specified value.
// $eq	Matches values that are equal to a specified value.
//
// $gt	Matches values that are greater than a specified value.
// $gte	Matches values that are greater than or equal to a specified value.

// $lt	Matches values that are less than a specified value.
// $lte	Matches values that are less than or equal to a specified value.

// $in	Matches any of the values specified in an array.
// $nin	Matches none of the values specified in an array.

var comparisons$1 = canReflect_1_19_2_canReflect.assign(arrayComparisons.comparisons, {
	In: function In(values) {
		// TODO: change this to store as `Set` later.
		this.values = values;
	},
	NotIn: function NotIn(values) {
		this.values = values;
	},
	GreaterThan: function GreaterThan(value) {
		this.value = value;
	},
	GreaterThanEqual: function GreaterThanEqual(value) {
		this.value = value;
	},
	LessThan: function LessThan(value) {
		this.value = value;
	},
	LessThanEqual: function LessThanEqual(value) {
		this.value = value;
	},
	// This is used to And something like `GT(3)` n `LT(4)`.
	// These are all value comparisons.
	And: function ValueAnd(ands) {
		this.values = ands;
	},
	// This is used to OR something like `GT(4)` n `LT(3)`.
	// These are all value comparisons.
	Or: function ValueOr(ors) {
		this.values = ors;
	}
});

comparisons$1.Or.prototype.orValues = function() {
	return this.values;
};

comparisons$1.In.test = function(values, b) {
	return values.some(function(value) {
		var values = set_1$1.ownAndMemberValue(value, b);
		return values.own === values.member;
	});
};

comparisons$1.NotIn.test = function(values, b) {
	return !comparisons$1.In.test(values, b);
};
comparisons$1.NotIn.testValue = function(value, b) {
	return !comparisons$1.In.testValue(value, b);
};

function nullIsFalse(test) {
	return function(arg1, arg2) {
		if (arg1 == null || arg2 == null) {
			return false;
		} else {
			return test(arg1, arg2);
		}
	};
}

function nullIsFalseTwoIsOk(test) {
	return function(arg1, arg2) {
		if (arg1 === arg2) {
			return true;
		} else if (arg1 == null || arg2 == null) {
			return false;
		} else {
			return test(arg1, arg2);
		}
	};
}

comparisons$1.GreaterThan.test = nullIsFalse(function(a, b) {
	return a > b;
});
comparisons$1.GreaterThanEqual.test = nullIsFalseTwoIsOk(function(a, b) {
	return a >= b;
});
comparisons$1.LessThan.test = nullIsFalse(function(a, b) {
	return a < b;
});
comparisons$1.LessThanEqual.test = nullIsFalseTwoIsOk(function(a, b) {
	return a <= b;
});

function isMemberThatUsesTest(value) {
	var values = set_1$1.ownAndMemberValue(this.value, value);
	return this.constructor.test(values.member, values.own);
}
[comparisons$1.GreaterThan, comparisons$1.GreaterThanEqual, comparisons$1.LessThan, comparisons$1.LessThanEqual, comparisons$1.LessThan].forEach(function(Type) {
	Type.prototype.isMember = isMemberThatUsesTest;
});

[comparisons$1.In, comparisons$1.NotIn].forEach(function(Type) {
	Type.prototype.isMember = comparisonsCommon.isMemberThatUsesTestOnValues;
});

comparisons$1.And.prototype.isMember = function(value) {
	return this.values.every(function(and) {
		return and.isMember(value);
	});
};
comparisons$1.Or.prototype.isMember = function(value) {
	return this.values.some(function(and) {
		return and.isMember(value);
	});
};
Object.keys(comparisons$1).forEach(function(name) {
	comparisons$1[name].prototype[isMemberSymbol$2] = comparisons$1[name].prototype.isMember;
});

var is$1 = comparisons$1;

function makeNot(Type) {
	return {
		test: function(vA, vB) {
			return !Type.test(vA, vB);
		}
	};
}


function makeEnum(type, Type, emptyResult) {
	return function(a, b) {
		var result = arrayUnionIntersectionDifference(a.values, b.values);
		if (result[type].length) {
			return new Type(result[type]);
		} else {
			return emptyResult || set_1$1.EMPTY;
		}
	};
}

function swapArgs(fn) {
	return function(a, b) {
		return fn(b, a);
	};
}


function makeSecondValue(Type, prop) {
	return function(universe, value) {
		return new Type(value[prop || "value"]);
	};
}

function returnBiggerValue(gtA, gtB) {
	if (gtA.value < gtB.value) {
		return gtB;
	} else {
		return gtA;
	}
}

function returnSmallerValue(gtA, gtB) {
	if (gtA.value > gtB.value) {
		return gtB;
	} else {
		return gtA;
	}
}

function makeAndIf(Comparison, Type) {
	return function(ltA, ltB) {
		if (Comparison.test(ltA.value, ltB.value)) {
			return makeAnd([ltA, new Type(ltB.value)]);
		} else {
			return set_1$1.EMPTY;
		}
	};
}

function make_InIfEqual_else_andIf(Comparison, Type) {
	var elseCase = makeAndIf(Comparison, Type);
	return function(a, b) {
		if (a.value === b.value) {
			return new is$1.In([a.value]);
		} else {
			return elseCase(a, b);
		}
	};
}

function make_filterFirstValueAgainstSecond(Comparison, Type, defaultReturn) {
	return function(inSet, gt) {
		var values = inSet.values.filter(function(value) {
			return Comparison.test(gt, value);
		});
		return values.length ?
			new Type(values) : defaultReturn || set_1$1.EMPTY;
	};
}

var isMemberTest = {
	test: function isMemberTest(set, value) {
		return set.isMember(value);
	}
};

function isOr(value) {
	return (value instanceof is$1.Or);
}

function isAnd(value) {
	return (value instanceof is$1.And);
}

function isAndOrOr(value) {
	return isAnd(value) || isOr(value);
}


// `value` - has a test function to check values
// `with` - the type we use to combined with the "other" value.
// `combinedUsing` - If there are values, how do we stick it together with `with`

function combineFilterFirstValuesAgainstSecond(options) {
	return function(inSet, gt) {
		var values = inSet.values.filter(function(value) {
			return options.values.test(gt, value);
		});
		var range;
		if (options.complement) {
			range = set_1$1.difference(set_1$1.UNIVERSAL, gt);
		} else if (options.with) {
			range = new options.with(gt.value);
		} else {
			range = gt;
		}
		return values.length ?
			options.combinedUsing([new options.arePut(values), range]) : range;
	};
}

function makeOrUnless(Comparison, result) {
	return function(setA, setB) {
		if (Comparison.test(setA.value, setB.value)) {
			return result || set_1$1.UNIVERSAL;
		} else {
			return makeOr([setA, setB]);
		}
	};
}

function makeAndUnless(Comparison, result) {
	return function(setA, setB) {
		if (Comparison.test(setA.value, setB.value)) {
			return result || set_1$1.EMPTY;
		} else {
			return makeAnd([setA, setB]);
		}
	};
}

function makeComplementSecondArgIf(Comparison) {
	return function(setA, setB) {
		if (Comparison.test(setA.value, setB.value)) {
			return set_1$1.difference(set_1$1.UNIVERSAL, setB);
		} else {
			return setA;
		}
	};
}


function makeAnd(ands) {
	return comparisons$1.And ? new comparisons$1.And(ands) : set_1$1.UNDEFINABLE;
}

function makeOr(ors) {
	return comparisons$1.Or ? new comparisons$1.Or(ors) : set_1$1.UNDEFINABLE;
}

function combineValueWithRangeCheck(inSet, rangeSet, RangeOrEqType) {
	var gte = new RangeOrEqType(rangeSet.value);
	var leftValues = inSet.values.filter(function(value) {
		return !gte.isMember(value);
	});
	if (!leftValues.length) {
		return gte;
	}

	if (leftValues.length < inSet.values.length) {
		return makeOr([new is$1.In(leftValues), gte]);
	} else {
		return makeOr([inSet, rangeSet]);
	}
}

// This tries to unify In([1]) with GT(1) -> GTE(1)
function makeOrWithInAndRange(inSet, rangeSet) {
	if (rangeSet instanceof is$1.Or) {
		var firstResult = makeOrWithInAndRange(inSet, rangeSet.values[0]);
		if ( !(firstResult instanceof is$1.Or) ) {
			return set_1$1.union(firstResult, rangeSet.values[1]);
		}
		var secondResult = makeOrWithInAndRange(inSet, rangeSet.values[1]);
		if ( !(secondResult instanceof is$1.Or) ) {
			return set_1$1.union(secondResult, rangeSet.values[0]);
		}
		return makeOr([inSet, rangeSet]);
	} else {
		if (rangeSet instanceof is$1.GreaterThan) {
			return combineValueWithRangeCheck(inSet, rangeSet, is$1.GreaterThanEqual);
		}
		if (rangeSet instanceof is$1.LessThan) {
			return combineValueWithRangeCheck(inSet, rangeSet, is$1.LessThanEqual);
		}
		return makeOr([inSet, rangeSet]);
	}
}

var In_RANGE = {
	union: combineFilterFirstValuesAgainstSecond({
		values: makeNot(isMemberTest),
		arePut: is$1.In,
		combinedUsing: function(ors) {
			return makeOrWithInAndRange(ors[0], ors[1]);
		}
	}),
	intersection: make_filterFirstValueAgainstSecond(isMemberTest, is$1.In, set_1$1.EMPTY),
	difference: make_filterFirstValueAgainstSecond(makeNot(isMemberTest), is$1.In, set_1$1.EMPTY)
};
var RANGE_IN = {
	difference: swapArgs(combineFilterFirstValuesAgainstSecond({
		values: isMemberTest,
		arePut: is$1.NotIn,
		combinedUsing: makeAnd
	}))
};

var NotIn_RANGE = function() {
	return {
		union: make_filterFirstValueAgainstSecond(makeNot(isMemberTest), is$1.NotIn, set_1$1.UNIVERSAL),
		intersection: combineFilterFirstValuesAgainstSecond({
			values: isMemberTest,
			arePut: is$1.NotIn,
			combinedUsing: makeAnd
		}),
		difference: combineFilterFirstValuesAgainstSecond({
			values: makeNot(isMemberTest),
			arePut: is$1.NotIn,
			combinedUsing: makeAnd,
			complement: true
		})
	};
};
var RANGE_NotIn = {
	difference: swapArgs(make_filterFirstValueAgainstSecond(isMemberTest, is$1.In, set_1$1.EMPTY))
};

var RANGE_And_Union = function(gt, and) {

	var union1 = set_1$1.union(gt, and.values[0]);
	var union2 = set_1$1.union(gt, and.values[1]);

	if (!isAndOrOr(union1) && !isAndOrOr(union2)) {
		return set_1$1.intersection(union1, union2);
	} else {
		return new is$1.Or([gt, and]);
	}
};
var RANGE_And_Intersection = function(gt, and) {
	var and1 = and.values[0],
		and2 = and.values[1];
	var intersection1 = set_1$1.intersection(gt, and1);
	var intersection2 = set_1$1.intersection(gt, and2);
	if (intersection1 === set_1$1.EMPTY || intersection2 === set_1$1.EMPTY) {
		return set_1$1.EMPTY;
	}
	if (!isAndOrOr(intersection1)) {
		return new set_1$1.intersection(intersection1, and2);
	}

	if (!isAndOrOr(intersection2)) {
		return new set_1$1.intersection(intersection2, and1);
	} else {
		return new is$1.And([gt, and]);
	}

};

var RANGE_And_Difference = function(gt, and) {
	var and1 = and.values[0],
		and2 = and.values[1];
	var difference1 = set_1$1.difference(gt, and1);
	var difference2 = set_1$1.difference(gt, and2);
	if (difference1 === set_1$1.EMPTY) {
		return difference2;
	}
	if (difference2 === set_1$1.EMPTY) {
		return difference1;
	}
	return new is$1.Or([difference1, difference2]);
};

var And_RANGE_Difference = function(and, gt) {
	var and1 = and.values[0],
		and2 = and.values[1];
	var difference1 = set_1$1.difference(and1, gt);
	var difference2 = set_1$1.difference(and2, gt);

	return set_1$1.intersection(difference1, difference2);
};

var RANGE_Or = {
	union: function(gt, or) {
		var or1 = or.values[0],
			or2 = or.values[1];
		var union1 = set_1$1.union(gt, or1);
		if (!isAndOrOr(union1)) {
			return set_1$1.union(union1, or2);
		}
		var union2 = set_1$1.union(gt, or2);
		if (!isAndOrOr(union2)) {
			return set_1$1.union(or1, union2);
		} else {
			return new is$1.Or([gt, or]);
		}
	},
	intersection: function(gt, or) {
		var or1 = or.values[0],
			or2 = or.values[1];
		var intersection1 = set_1$1.intersection(gt, or1);
		var intersection2 = set_1$1.intersection(gt, or2);
		if (intersection1 === set_1$1.EMPTY) {
			return intersection2;
		}
		if (intersection2 === set_1$1.EMPTY) {
			return intersection1;
		}
		return set_1$1.union(intersection1, intersection2);
	},
	// v \ (a || b) -> (v \ a) n (v \ b)
	difference: function(gt, or) {

		var or1 = or.values[0],
			or2 = or.values[1];
		var difference1 = set_1$1.difference(gt, or1);
		var difference2 = set_1$1.difference(gt, or2);
		return set_1$1.intersection(difference1, difference2);
	}
};

var Or_RANGE = {
	// ( a || b ) \ v -> (a \ v) U (b \ v)
	difference: function(or, gt) {
		var or1 = or.values[0],
			or2 = or.values[1];
		var difference1 = set_1$1.difference(or1, gt);
		var difference2 = set_1$1.difference(or2, gt);
		return set_1$1.union(difference1, difference2);
	}
};

var comparators$1 = canReflect_1_19_2_canReflect.assign(arrayComparisons.comparators, {
	// In
	In_In: {
		union: makeEnum("union", is$1.In),
		intersection: makeEnum("intersection", is$1.In),
		difference: makeEnum("difference", is$1.In)
	},
	UNIVERSAL_In: {
		difference: makeSecondValue(is$1.NotIn, "values")
	},

	In_NotIn: {
		union: swapArgs(makeEnum("difference", is$1.NotIn, set_1$1.UNIVERSAL)),
		// what does In have on its own
		intersection: makeEnum("difference", is$1.In),
		difference: makeEnum("intersection", is$1.In)
	},
	NotIn_In: {
		difference: makeEnum("union", is$1.NotIn)
	},

	In_GreaterThan: In_RANGE,
	GreaterThan_In: RANGE_IN,

	In_GreaterThanEqual: In_RANGE,
	GreaterThanEqual_In: RANGE_IN,

	In_LessThan: In_RANGE,
	LessThan_In: RANGE_IN,

	In_LessThanEqual: In_RANGE,
	LessThanEqual_In: RANGE_IN,
	In_And: In_RANGE,
	And_In: RANGE_IN,

	In_Or: In_RANGE,
	Or_In: RANGE_IN,

	// NotIn ===============================
	NotIn_NotIn: {
		union: makeEnum("intersection", is$1.NotIn, set_1$1.UNIVERSAL),
		intersection: makeEnum("union", is$1.NotIn),
		difference: makeEnum("difference", is$1.In)
	},
	UNIVERSAL_NotIn: {
		difference: makeSecondValue(is$1.In, "values")
	},

	NotIn_GreaterThan: NotIn_RANGE(),
	GreaterThan_NotIn: RANGE_NotIn,

	NotIn_GreaterThanEqual: NotIn_RANGE(),
	GreaterThanEqual_NotIn: RANGE_NotIn,

	NotIn_LessThan: NotIn_RANGE(),
	LessThan_NotIn: RANGE_NotIn,

	NotIn_LessThanEqual: NotIn_RANGE(),
	LessThanEqual_NotIn: RANGE_NotIn,

	NotIn_And: NotIn_RANGE(),
	And_NotIn: RANGE_NotIn,

	NotIn_Or: NotIn_RANGE(),
	Or_NotIn: RANGE_NotIn,

	// GreaterThan ===============================
	GreaterThan_GreaterThan: {
		union: returnSmallerValue,
		intersection: returnBiggerValue,
		// {$gt:5} \ {gt: 6} -> AND( {$gt:5}, {$lte: 6} )
		difference: makeAndIf(is$1.LessThan, is$1.LessThanEqual)
	},
	UNIVERSAL_GreaterThan: {
		difference: makeSecondValue(is$1.LessThanEqual)
	},

	GreaterThan_GreaterThanEqual: {
		union: returnSmallerValue,
		intersection: returnBiggerValue,
		// {$gt:5} \ {gte: 6} -> AND( {$gt:5}, {$lt: 6} )
		difference: makeAndIf(is$1.LessThan, is$1.LessThan)
	},
	GreaterThanEqual_GreaterThan: {
		difference: make_InIfEqual_else_andIf(is$1.LessThan, is$1.LessThanEqual)
	},

	GreaterThan_LessThan: {
		union: (function() {
			var makeOrUnlessLessThan = makeOrUnless(is$1.LessThan);
			return function greaterThan_lessThan_union(a, b) {
				if ( comparisons$1.In.test([a.value], b.value) ) {
					return new is$1.NotIn([a.value]);
				} else {
					return makeOrUnlessLessThan(a, b);
				}
			};
		})(),
		intersection: makeAndUnless(is$1.GreaterThan),
		difference: makeComplementSecondArgIf(is$1.LessThan)
	},
	LessThan_GreaterThan: {
		difference: makeComplementSecondArgIf(is$1.GreaterThan)
	},

	GreaterThan_LessThanEqual: {
		union: makeOrUnless(is$1.LessThanEqual),
		intersection: makeAndUnless(is$1.GreaterThanEqual),
		difference: makeComplementSecondArgIf(is$1.LessThanEqual)
	},
	LessThanEqual_GreaterThan: {
		difference: makeComplementSecondArgIf(is$1.GreaterThanEqual)
	},

	GreaterThan_And: {
		union: RANGE_And_Union,
		intersection: RANGE_And_Intersection,
		difference: RANGE_And_Difference
	},
	And_GreaterThan: {
		difference: And_RANGE_Difference
	},
	GreaterThan_Or: RANGE_Or,
	Or_GreaterThan: Or_RANGE,

	// GreaterThanEqual =========
	GreaterThanEqual_GreaterThanEqual: {
		union: returnSmallerValue,
		intersection: returnBiggerValue,
		// {gte: 2} \ {gte: 3} = {gte: 2} AND {lt: 3}
		difference: makeAndIf(is$1.LessThan, is$1.LessThan)
	},
	UNIVERSAL_GreaterThanEqual: {
		difference: makeSecondValue(is$1.LessThan)
	},

	GreaterThanEqual_LessThan: {
		union: makeOrUnless(is$1.LessThanEqual),
		intersection: makeAndUnless(is$1.GreaterThanEqual),
		difference: makeComplementSecondArgIf(is$1.LessThanEqual)
	},
	LessThan_GreaterThanEqual: {
		difference: makeComplementSecondArgIf(is$1.GreaterThanEqual)
	},

	GreaterThanEqual_LessThanEqual: {
		union: makeOrUnless(is$1.LessThanEqual),
		// intersect on a number
		intersection: (function() {
			var makeAnd = makeAndUnless(is$1.GreaterThan);
			return function gte_lte_intersection(gte, lte) {
				var inSet = new is$1.In([gte.value]);
				if (inSet.isMember(lte.value)) {
					return inSet;
				} else {
					return makeAnd(gte, lte);
				}
			};
		})(),
		difference: makeComplementSecondArgIf(is$1.LessThanEqual)
	},
	LessThanEqual_GreaterThanEqual: {
		difference: makeComplementSecondArgIf(is$1.GreaterThanEqual)
	},

	GreaterThanEqual_And: {
		union: RANGE_And_Union,
		intersection: RANGE_And_Intersection,
		difference: RANGE_And_Difference
	},
	And_GreaterThanEqual: {
		difference: And_RANGE_Difference
	},
	GreaterThanEqual_Or: RANGE_Or,
	Or_GreaterThanEqual: Or_RANGE,

	// LessThan
	LessThan_LessThan: {
		union: returnBiggerValue,
		intersection: returnSmallerValue,
		difference: makeAndIf(is$1.GreaterThan, is$1.GreaterThanEqual)
	},
	UNIVERSAL_LessThan: {
		difference: makeSecondValue(is$1.GreaterThanEqual)
	},

	LessThan_LessThanEqual: {
		union: returnBiggerValue,
		intersection: returnSmallerValue,
		// {lt: 3} \ {lte: 2} -> {lt: 3} AND {gt: 2}
		difference: makeAndIf(is$1.GreaterThan, is$1.GreaterThan)
	},
	LessThanEqual_LessThan: {
		difference: make_InIfEqual_else_andIf(is$1.GreaterThanEqual, is$1.GreaterThanEqual)
	},

	LessThan_And: {
		union: RANGE_And_Union,
		intersection: RANGE_And_Intersection,
		difference: RANGE_And_Difference
	},
	And_LessThan: {
		difference: And_RANGE_Difference
	},
	LessThan_Or: RANGE_Or,
	Or_LessThan: Or_RANGE,

	// LessThanEqual
	LessThanEqual_LessThanEqual: {
		union: returnBiggerValue,
		intersection: returnSmallerValue,
		difference: function(lteA, lteB) {
			if (lteA.value >= lteB.value) {
				return makeAnd([lteA, new is$1.GreaterThan(lteB.value)]);
			} else {
				return set_1$1.EMPTY;
			}
		}
	},
	UNIVERSAL_LessThanEqual: {
		difference: makeSecondValue(is$1.GreaterThan)
	},

	LessThanEqual_And: {
		union: RANGE_And_Union,
		intersection: RANGE_And_Intersection,
		difference: RANGE_And_Difference
	},
	And_LessThanEqual: {
		difference: And_RANGE_Difference
	},
	LessThanEqual_Or: RANGE_Or,
	Or_LessThanEqual: Or_RANGE,

	// AND =====
	And_And: {
		// (a n b) U (c n d) => (a U c) n (b U d)?
		// union both ways ... if one is unviersal, the other is the result.
		// (a ∩ b) ∪ (c ∩ d) where Z = (a ∩ b)
		// -> Z ∪ (c ∩ d)
		// -> (Z ∪ c) ∩ (Z ∪ d)
		// -> ((a ∩ b) ∪ c) ∪ ((a ∩ b) ∪ d)
		union: function(and1, and2) {
			var union1 = set_1$1.union(and1, and2.values[0]);
			var union2 = set_1$1.union(and1, and2.values[1]);

			if (isAndOrOr(union1) || isAndOrOr(union2)) {
				// try the other direction
				union1 = set_1$1.union(and2, and1.values[0]);
				union2 = set_1$1.union(and2, and1.values[1]);
			}
			if (isAndOrOr(union1) || isAndOrOr(union2)) {
				return new is$1.Or([and1, and2]);
			} else {
				return set_1$1.intersection(union1, union2);
			}

			/*
			var combo1 = [
					set.union(and1.values[0], and2.values[0]),
					set.union(and1.values[1], and2.values[1])
				],
				combo2 = [
					set.union(and1.values[0], and2.values[1]),
					set.union(and1.values[1], and2.values[0])
				];
			if (combo1.every(function(aSet) {
				return set.isEqual(set.UNIVERSAL, aSet);
			})) {
				return set.intersection.apply(set, combo2);
			}
			if (combo2.every(function(aSet) {
				return set.isEqual(set.UNIVERSAL, aSet);
			})) {
				return set.intersection.apply(set, combo1);
			}
			return new is.Or([and1, and2]);*/
		},

		intersection: function(and1, and2) {
			var intersection1 = set_1$1.intersection(and1.values[0], and2.values[0]);
			var intersection2 = set_1$1.intersection(and1.values[1], and2.values[1]);

			if (!isAndOrOr(intersection1) || !isAndOrOr(intersection2)) {
				return set_1$1.intersection(intersection1, intersection2);
			}
			intersection1 = set_1$1.intersection(and1.values[0], and2.values[1]);
			intersection2 = set_1$1.intersection(and1.values[1], and2.values[0]);

			if (!isAndOrOr(intersection1) || !isAndOrOr(intersection2)) {
				return set_1$1.intersection(intersection1, intersection2);
			} else {
				return new is$1.And([and1, and2]);
			}
		},
		// (a ∩ b) \ (c ∩ d) where Z = (a ∩ b)
		// -> Z \ (c ∩ d)
		// -> (Z \ c) ∪ (Z \ d)
		// -> ((a ∩ b) \ c) ∪ ((a ∩ b) \ d)
		difference: (function() {

			return function(and1, and2) {
				var d1 = set_1$1.difference(and1, and2.values[0]);
				var d2 = set_1$1.difference(and1, and2.values[1]);
				return set_1$1.union(d1, d2);
			};
			/*
			function getDiffIfPartnerIsEmptyAndOtherComboNotDisjoint(inOrderDiffs, reverseOrderDiffs, diffedAnd) {
				var diff;
				if (inOrderDiffs[0] === set.EMPTY) {
					diff = inOrderDiffs[1];
				}
				if (inOrderDiffs[1] === set.EMPTY) {
					diff = inOrderDiffs[0];
				}
				if (diff) {
					// check if a diff equals itself (and therefor is disjoint)

					if (set.isEqual(diffedAnd.values[0], reverseOrderDiffs[0] ) ) {
						// is disjoint
						return diffedAnd;
					}
					if ( set.isEqual(diffedAnd.values[1], reverseOrderDiffs[1] ) ) {
						return diffedAnd;
					}
					return diff;
				}
			}
			return function(and1, and2) {
				var inOrderDiffs = [
						set.difference(and1.values[0], and2.values[0]),
						set.difference(and1.values[1], and2.values[1])
					],
					reverseOrderDiffs = [
						set.difference(and1.values[0], and2.values[1]),
						set.difference(and1.values[1], and2.values[0])
					];

				var diff = getDiffIfPartnerIsEmptyAndOtherComboNotDisjoint(inOrderDiffs, reverseOrderDiffs, and1);
				if (diff) {
					return diff;
				}
				diff = getDiffIfPartnerIsEmptyAndOtherComboNotDisjoint(reverseOrderDiffs, inOrderDiffs, and1);
				if (diff) {
					return diff;
				} else {
					// if one is a double And ... that's the outer \\ inner
					if (isAndOrOr(inOrderDiffs[0]) && isAndOrOr(inOrderDiffs[1])) {
						return new is.Or([inOrderDiffs[0], inOrderDiffs[1]]);
					} else if ( isAndOrOr(reverseOrderDiffs[0]) && isAndOrOr(reverseOrderDiffs[1]) ) {
						return new is.Or([reverseOrderDiffs[0], reverseOrderDiffs[1]]);
					}
					return set.UNKNOWABLE;
				}
			};*/
		})()
	},
	And_Or: {
		// (a ∩ b) ∪ (c u d) where Z = (c u d)
		// -> Z u (a ∩ b)
		// -> (Z u a) ∩ (Z u b)
		// -> ((c u d) u a) ∩ ((c u d) u b)
		union: function(and, or) {
			var aUnion = set_1$1.union(and.values[0], or);
			var bUnion = set_1$1.union(and.values[1], or);

			if (!isAndOrOr(aUnion) || !isAndOrOr(bUnion)) {
				return set_1$1.intersection(aUnion, bUnion);
			}

			return new is$1.Or([and, or]);
		},
		// (a ∩ b) ∩ (c u d) where Z = (a ∩ b)
		// -> Z ∩ (c u d)
		// -> (Z ∩ c) u (Z ∩ d)
		// -> (a ∩ b ∩ c) u (a ∩ b ∩ d)
		intersection: function(and, or) {
			var aIntersection = set_1$1.intersection(and, or.values[0]);
			var bIntersection = set_1$1.intersection(and, or.values[1]);
			if (!isOr(aIntersection) && !isOr(bIntersection)) {
				return set_1$1.union(aIntersection, bIntersection);
			}
			return new is$1.And([and, or]);
		},
		// (a ∩ b) \ (c u d) where Z = (a ∩ b)
		// -> Z \ (c u d)
		// -> (Z \ c) ∩ (Z \ d)
		// -> ((a ∩ b) \ c) ∩ ((a ∩ b) \ d)
		difference: function(and, or) {
			var aDiff = set_1$1.difference(and, or.values[0]);
			var bDiff = set_1$1.difference(and, or.values[1]);
			return set_1$1.intersection(aDiff, bDiff);
		}
	},
	Or_And: {
		// (a ∪ b) \ (c ∩ d) where Z = (a ∪ b)
		// -> Z \ (c ∩ d)
		// -> (Z \ c) ∪ (Z \ d)
		// -> ((a ∪ b) \ c) ∪ ((a ∪ b) \ d)
		difference: function(or, and) {
			var aDiff = set_1$1.difference(or, and.values[0]);
			var bDiff = set_1$1.difference(or, and.values[1]);
			return set_1$1.union(aDiff, bDiff);
		}
	},
	UNIVERSAL_And: {
		difference: function(universe, and) {
			var inverseFirst = set_1$1.difference(universe, and.values[0]),
				inverseSecond = set_1$1.difference(universe, and.values[1]);
			return set_1$1.union(inverseFirst, inverseSecond);
		}
	},
	Or_Or: {
		// (a ∪ b) ∪ (c ∪ d)
		union: function(or1, or2) {
			var union1 = set_1$1.union(or1.values[0], or2.values[0]);
			var union2 = set_1$1.union(or1.values[1], or2.values[1]);

			if (!isAndOrOr(union1) || !isAndOrOr(union2)) {
				return set_1$1.union(union1, union2);
			}
			union1 = set_1$1.union(or1.values[0], or2.values[1]);
			union2 = set_1$1.union(or1.values[1], or2.values[0]);

			if (!isAndOrOr(union1) || !isAndOrOr(union2)) {
				return set_1$1.union(union1, union2);
			} else {
				return new is$1.Or([or1, or2]);
			}
		},
		// (a ∪ b) ∩ (c ∪ d) where Z = (a ∪ b)
		// -> Z ∩ (c ∪ d)
		// -> (Z ∩ c) ∪ (Z ∪ d)
		// -> ((a ∪ b) ∩ c) ∪ ((a ∪ b) ∩ d)
		intersection: function(or1, or2) {
			var c = or2.values[0],
				d = or2.values[1];

			var intersection1 = set_1$1.intersection(or1, c);
			var intersection2 = set_1$1.intersection(or1, d);

			if (!isOr(intersection1) || !isOr(intersection2)) {
				return set_1$1.union(intersection1, intersection2);
			}
			intersection1 = set_1$1.union(or2, or1.values[0]);
			intersection2 = set_1$1.union(or2, or1.values[1]);

			if (!isOr(intersection1) || !isOr(intersection2)) {
				return set_1$1.union(intersection1, intersection2);
			} else {
				return new is$1.Or([or1, or2]);
			}
		},
		// (a ∪ b) \ (c ∪ d) where Z = (a ∪ b)
		// -> Z \ (c ∪ d)
		// -> (Z \ c) ∩ (Z \ d)
		// -> ((a ∪ b) \ c) ∩ ((a ∪ b) \ d)
		difference: function(or1, or2) {
			var d1 = set_1$1.difference(or1, or2.values[0]);
			var d2 = set_1$1.difference(or1, or2.values[1]);
			return set_1$1.intersection(d1, d2);
		}
	},
	UNIVERSAL_Or: {
		difference: function(universe, or) {
			var inverseFirst = set_1$1.difference(universe, or.values[0]),
				inverseSecond = set_1$1.difference(universe, or.values[1]);
			return set_1$1.intersection(inverseFirst, inverseSecond);
		}
	}
});

// Registers all the comparisons above
var names = Object.keys(comparisons$1);
names.forEach(function(name1, i) {
	if (!comparators$1[name1 + "_" + name1]) {
		console.warn("no " + name1 + "_" + name1);
	} else {
		set_1$1.defineComparison(comparisons$1[name1], comparisons$1[name1], comparators$1[name1 + "_" + name1]);
	}

	if (!comparators$1["UNIVERSAL_" + name1]) {
		console.warn("no UNIVERSAL_" + name1);
	} else {
		set_1$1.defineComparison(set_1$1.UNIVERSAL, comparisons$1[name1], comparators$1["UNIVERSAL_" + name1]);
	}

	for (var j = i + 1; j < names.length; j++) {
		var name2 = names[j];
		if (!comparators$1[name1 + "_" + name2]) {
			console.warn("no " + name1 + "_" + name2);
		} else {
			set_1$1.defineComparison(comparisons$1[name1], comparisons$1[name2], comparators$1[name1 + "_" + name2]);
		}
		if (!comparators$1[name2 + "_" + name1]) {
			console.warn("no " + name2 + "_" + name1);
		} else {
			set_1$1.defineComparison(comparisons$1[name2], comparisons$1[name1], comparators$1[name2 + "_" + name1]);
		}
	}
});

var comparisons_1$1 = comparisons$1;

// THIS IS REALLY INTEGERS!!!

var makeRealNumberRangeInclusive = function(min, max) {




    function RealNumberRangeInclusive(start, end){

        this.start =  arguments.length > 0 ? +start : min;
        this.end = arguments.length > 1 ? +end : max;
		this.range = new comparisons_1$1.And([
			new comparisons_1$1.GreaterThanEqual( this.start ),
			new comparisons_1$1.LessThanEqual( this.end )
		]);
    }

	var universeRange = new RealNumberRangeInclusive( min , max );

    function isUniversal(range) {
        return set_1$1.isSubset(universeRange.range, range.range);
    }

	function rangeFromAnd(aSet) {
		var values = {};
		aSet.values.forEach(function(value){
			if(value instanceof comparisons_1$1.GreaterThanEqual) {
				values.start = value.value;
			}
			if(value instanceof comparisons_1$1.GreaterThan) {
				values.start = value.value+1;
			}
			if(value instanceof comparisons_1$1.LessThanEqual) {
				values.end = value.value;
			}
			if(value instanceof comparisons_1$1.LessThan) {
				values.end = value.value-1;
			}
		});
		if("start" in values && "end" in values) {
			return new RealNumberRangeInclusive(values.start, values.end );
		}
	}

	function toRange(aSet) {
		var range;
		if(aSet instanceof comparisons_1$1.And) {
			range = rangeFromAnd(aSet);
		}
		if(aSet instanceof comparisons_1$1.Or) {
			// check if next to each other ...
			var first = rangeFromAnd(aSet.values[0]),
				second = rangeFromAnd(aSet.values[1]);
			if(first && second) {
				var firstValues = first.range.values,
					secondValues = second.range.values;
				if(firstValues[1].value + 1 === secondValues[0].value) {
					range = new RealNumberRangeInclusive(firstValues[0].value, secondValues[1].value );
				}
				else if(secondValues[1].value + 1 === firstValues[0].value) {
					range = new RealNumberRangeInclusive(secondValues[0].value, firstValues[1].value );
				} else {
					return set_1$1.UNDEFINABLE;
				}
			} else {
				return set_1$1.UNDEFINABLE;
			}
		}
		if(range && isUniversal(range)) {
			return set_1$1.UNIVERSAL;
		} else {
			return range;
		}
	}

    function intersection(range1, range2){
		var intersection = toRange(set_1$1.intersection(range1.range, range2.range));
		if(intersection) {
			return intersection;
		} else {
            return set_1$1.EMPTY;
        }
    }

    function difference(range1, range2){

		var difference = toRange( set_1$1.difference(range1.range, range2.range) );
		if(difference) {
			return difference;
		} else {
            return set_1$1.EMPTY;
        }
    }

    set_1$1.defineComparison(RealNumberRangeInclusive, RealNumberRangeInclusive,{
        union: function(range1, range2){
			var union = toRange( set_1$1.union(range1.range, range2.range) );
			if(union) {
				return union;
			} else {
	            return set_1$1.EMPTY;
	        }
        },
        intersection: intersection,
        difference: difference
    });

    set_1$1.defineComparison(set_1$1.UNIVERSAL,RealNumberRangeInclusive, {
        difference: function(universe, range){
            if(isUniversal(range)) {
                return set_1$1.EMPTY;
            } else {
                return difference(universeRange, range);
            }
        }
    });

    return RealNumberRangeInclusive;
};

// this is intended to be used for $or ... it
// ors expected key values
// `{age: 22}` U `{name: "Justin"}`
function ValuesOr(values) {
    // the if values can be unioned into a single value
    this.values = values;
}

ValuesOr.prototype.isMember = function(props){
    return this.values.some(function(value){
            return value && value.isMember ?
                value.isMember( props ) : value === props;
    });
};


// Or comparisons
set_1$1.defineComparison(set_1$1.UNIVERSAL, ValuesOr,{
    difference: function(){
        return set_1$1.UNDEFINABLE;
    }
});


var valuesOr = types.ValuesOr = ValuesOr;

function ValuesAnd(values) {
	this.values = values;
}

ValuesAnd.prototype.isMember = function(props) {
	return this.values.every(function(value){
            return value && value.isMember ?
                value.isMember( props ) : value === props;
    });
};

// Or comparisons
set_1$1.defineComparison(set_1$1.UNIVERSAL, ValuesAnd, {
    difference: function(){
        return set_1$1.UNDEFINABLE;
    }
});

var valuesAnd = types.ValuesAnd = ValuesAnd;

// Define the sub-types that BasicQuery will use
function KeysAnd(values) {
	var vals = this.values = {};
	canReflect_1_19_2_canReflect.eachKey(values, function(value, key) {
		if (canReflect_1_19_2_canReflect.isPlainObject(value) && !set_1$1.isSpecial(value)) {
			vals[key] = new KeysAnd(value);
		} else {
			vals[key] = value;
		}
	});
}

var isMemberSymbol$3 = canSymbol_1_7_0_canSymbol.for("can.isMember");


KeysAnd.prototype.isMember = function(props, root, rootKey) {
	var equal = true;
	var preKey = rootKey ? rootKey + "." : "";
	canReflect_1_19_2_canReflect.eachKey(this.values, function(value, key) {
		var isMember = value && (value[isMemberSymbol$3] || value.isMember);
		if (isMember) {
			if (!isMember.call(value, get_1(props, key), root || props, preKey + key)) {
				equal = false;
			}
		} else {
			if (value !== get_1(props, key)) {
				equal = false;
			}
		}
	});
	return equal;
};


// ====== DEFINE COMPARISONS ========

// Helpers ----------------------------
function checkIfUniversalAndReturnUniversal(setA) {
	return set_1$1.isEqual(setA, set_1$1.UNIVERSAL) ? set_1$1.UNIVERSAL : setA;
}

var MISSING = {};

function eachInUnique(a, acb, b, bcb, defaultReturn) {
	var bCopy = canAssign_1_3_3_canAssign({}, b),
		res;
	for (var prop in a) {
		res = acb(prop, a[prop], (prop in b) ? b[prop] : MISSING, a, b);
		if (res !== undefined) {
			return res;
		}
		delete bCopy[prop];
	}
	for (prop in bCopy) {
		res = bcb(prop, MISSING, b[prop], a, b);
		if (res !== undefined) {
			return res;
		}
	}
	return defaultReturn;
}

function keyDiff(valuesA, valuesB) {
	var keyResults = arrayUnionIntersectionDifference(
		Object.keys(valuesA),
		Object.keys(valuesB));
	return {
		aOnlyKeys: keyResults.difference,
		aAndBKeys: keyResults.intersection,
		bOnlyKeys: arrayUnionIntersectionDifference(
			Object.keys(valuesB),
			Object.keys(valuesA)).difference
	};
}

function notEmpty(value) {
	return value !== set_1$1.EMPTY;
}

// Difference of two ANDs is used two places
function difference(objA, objB) {

	var valuesA = objA.values,
		valuesB = objB.values,
		diff = keyDiff(valuesA, valuesB),
		aOnlyKeys = diff.aOnlyKeys,
		aAndBKeys = diff.aAndBKeys,
		bOnlyKeys = diff.bOnlyKeys;

	// check if all aAndB are equal

	// With the shared keys, perform vA \ vB difference. If the DIFFERENCE is:
	// - EMPTY: vA has nothing outside vB. vA is equal or subset of vB.
	//   - IF sB has keys not in sA, the shared keys will be part of the result;
	//     OTHERWISE, if all empty, sA is subset of sB, EMPTY will be returned
	//                (even if sA has some extra own keys)
	// - NON-EMPTY: something in sA that is not in sB
	//   Now we need to figure out if it's "product-able" or not.
	//   Product-able -> some part of B is in A.
	//   Perform B ∩ A intersection.  INTERSECTION is:
	//   - EMPTY: NOT "product-able". DISJOINT.  Must return something.
	//   - non-EMPTY: Use to performa  product (in the future.)
	var sharedKeysAndValues = {},
		productAbleKeysAndData = {},
		disjointKeysAndValues = {};
	aAndBKeys.forEach(function(key) {
		var difference = set_1$1.difference(valuesA[key], valuesB[key]);
		if (difference === set_1$1.EMPTY) {
			sharedKeysAndValues[key] = valuesA[key];
		} else {
			var intersection = set_1$1.intersection(valuesA[key], valuesB[key]);
			var isProductable = intersection !== set_1$1.EMPTY;
			if (isProductable) {
				productAbleKeysAndData[key] = {
					// Products with `difference U intersection` would be subtracted
					// from produts with `intersection`
					difference: difference,
					intersection: intersection
				};
			} else {
				disjointKeysAndValues[key] = valuesA[key];
			}
		}
	});
	var productAbleKeys = Object.keys(productAbleKeysAndData);
	var singleProductKeyAndValue;
	if (productAbleKeys.length === 1) {
		singleProductKeyAndValue = {};
		singleProductKeyAndValue[productAbleKeys[0]] = productAbleKeysAndData[productAbleKeys[0]].difference;
	}

	// Now that we've got the shared keys organized
	// we can make decisions based on this information
	// and A-only and B-only keys.

	// if we have any disjoint keys, these sets can not intersect
	// {age: 21, ...} \ {age: 22, ...} ->  {age: 21, ...}
	if (Object.keys(disjointKeysAndValues).length) {
		return objA;
	}

	// contain all the same keys
	if ((aOnlyKeys.length === 0) && (bOnlyKeys.length === 0)) {
		if (productAbleKeys.length > 1) {
			return set_1$1.UNDEFINABLE;
		}
		// {color: [RED, GREEN], ...X...} \ {color: [RED], ...X...} -> {color: [GREEN], ...X...}
		else if (productAbleKeys.length === 1) {
			canAssign_1_3_3_canAssign(sharedKeysAndValues, singleProductKeyAndValue);
			return new KeysAnd(sharedKeysAndValues);
		} else {
			// {...X...} \ {...X...} -> EMPTY
			return set_1$1.EMPTY;
		}
	}
	// sA is likely a subset of sB
	if (aOnlyKeys.length > 0 && bOnlyKeys.length === 0) {
		if (productAbleKeys.length > 1) {
			return set_1$1.UNDEFINABLE;
		}
		// {age: 35, color: [RED, GREEN], ...X...} \ {color: [RED], ...X...} -> {age: 35, color: [GREEN], ...X...}
		else if (productAbleKeys.length === 1) {
			canAssign_1_3_3_canAssign(sharedKeysAndValues, singleProductKeyAndValue);
			aOnlyKeys.forEach(function(key) {
				sharedKeysAndValues[key] = valuesA[key];
			});
			return new KeysAnd(sharedKeysAndValues);
		} else {
			// sharedKeysAndValues
			return set_1$1.EMPTY;
		}
	}
	// sB is likely subset of sA
	// {}, {foo: "bar"} -> {foo: NOT("bar")}
	if (aOnlyKeys.length === 0 && bOnlyKeys.length > 0) {
		// Lets not figure out productAbleKeys right now.
		// Example:
		// {color: [RED, GREEN], ...X...}
		// \ {age: 35, color: [RED], ...X...}
		// = OR( {color: [GREEN], ...X...}, {age: NOT(35), color: [RED], ...X...} )
		if (productAbleKeys.length > 1) {
			return set_1$1.UNDEFINABLE;
		}
		var productAbleOr;
		if (productAbleKeys.length === 1) {
			// we add the intersection to the AND
			// the difference is the or
			var productableKey = productAbleKeys[0];
			productAbleOr = canAssign_1_3_3_canAssign({}, sharedKeysAndValues);
			productAbleOr[productableKey] = productAbleKeysAndData[productableKey].difference;
			sharedKeysAndValues[productableKey] = productAbleKeysAndData[productableKey].intersection;
		}

		var ands = bOnlyKeys.map(function(key) {
			var shared = canAssign_1_3_3_canAssign({}, sharedKeysAndValues);
			var result = shared[key] = set_1$1.difference(set_1$1.UNIVERSAL, valuesB[key]);
			return result === set_1$1.EMPTY ? result : new KeysAnd(shared);
		}).filter(notEmpty);

		if (productAbleOr) {
			ands.push(new KeysAnd(productAbleOr));
		}

		// {c: "g"}
		// \ {c: "g", age: 22, name: "justin"}
		// = OR[ AND(name: NOT("justin"), c:"g"), AND(age: NOT(22), c: "g") ]
		if (ands.length > 1) {
			return new types.ValuesOr(ands);
		} else if (ands.length === 1) {
			// {c: "g"}
			// \ {c: "g", age: 22}
			// = AND(age: NOT(22), c: "g")
			return ands[0];
		} else {
			return set_1$1.EMPTY;
		}
	}

	// {name: "Justin"} \\ {age: 35} -> {name: "Justin", age: NOT(35)}
	if (aOnlyKeys.length > 0 && bOnlyKeys.length > 0) {
		if (productAbleKeys.length) {
			throw new Error("Can't handle any productable keys right now");
		}
		// add everything in sA into the result:
		aOnlyKeys.forEach(function(key) {
			sharedKeysAndValues[key] = valuesA[key];
		});

		if (bOnlyKeys.length === 1) {
			// TODO: de-duplicate below
			var key = bOnlyKeys[0];
			var shared = canAssign_1_3_3_canAssign({}, sharedKeysAndValues);
			shared[key] = set_1$1.difference(set_1$1.UNIVERSAL, valuesB[key]);
			return new KeysAnd(shared);
		}
		// {foo: "bar"} \\ {name: "Justin", age: 35} -> UNDEFINABLE
		else {
			return set_1$1.UNDEFINABLE;
		}

	}
}

// KeysAnd comaprisons




set_1$1.defineComparison(KeysAnd, KeysAnd, {
	// {name: "Justin"} or {age: 35} -> new OR[{name: "Justin"},{age: 35}]
	// {age: 2} or {age: 3} -> {age: new OR[2,3]}
	// {age: 3, name: "Justin"} OR {age: 4} -> {age: 3, name: "Justin"} OR {age: 4}
	union: function(objA, objB) {
		// first see if we can union a single property
		// {age: 21, color: ["R"]} U {age: 21, color: ["B"]} -> {age: 21, color: ["R","B"]}

		var diff = keyDiff(objA.values, objB.values);


		// find the different keys
		var aAndBKeysThatAreNotEqual = [],
			sameKeys = {};

		diff.aAndBKeys.forEach(function(key) {
			if (!set_1$1.isEqual(objA.values[key], objB.values[key])) {
				aAndBKeysThatAreNotEqual.push(key);
			} else {
				sameKeys[key] = objA.values[key];
			}
		});
		var aUnequal = {}, bUnequal = {};
		aAndBKeysThatAreNotEqual.forEach(function(key){
			aUnequal[key] = objA.values[key];
			bUnequal[key] = objB.values[key];
		});

		// if all keys are shared
		if (!diff.aOnlyKeys.length && !diff.bOnlyKeys.length) {

			if (aAndBKeysThatAreNotEqual.length === 1) {
				var keyValue = aAndBKeysThatAreNotEqual[0];

				var result = sameKeys[keyValue] = set_1$1.union(objA.values[keyValue], objB.values[keyValue]);

				// if there is only one property, we can just return the universal set
				return canReflect_1_19_2_canReflect.size(sameKeys) === 1 && set_1$1.isEqual(result, set_1$1.UNIVERSAL) ?
					set_1$1.UNIVERSAL : new KeysAnd(sameKeys);
			} else if (aAndBKeysThatAreNotEqual.length === 0) {
				// these things are equal
				return objA;
			}
		}
		// If everything shared is the same
		if (aAndBKeysThatAreNotEqual.length === 0) {
			// the set with the extra keys is a subset
			if (diff.aOnlyKeys.length > 0 && diff.bOnlyKeys.length === 0) {
				return checkIfUniversalAndReturnUniversal(objB);
			} else if (diff.aOnlyKeys.length === 0 && diff.bOnlyKeys.length > 0) {
				return checkIfUniversalAndReturnUniversal(objA);
			}
		}
		// (count > 5 && age > 25 ) || (count > 7 && age > 35 && name > "Justin" )
		//
		// ( age > 25 ) || ( name > "Justin" && age > 35)  A U (B & C) => (A U B) & (A U C)
		// ( age > 25 || name > "Justin" ) && (age > 25)
		// lets see if one side is different
		if (diff.aOnlyKeys.length > 0 && diff.bOnlyKeys.length === 0) {
			// collect shared value
			if( set_1$1.isSubset(new KeysAnd(aUnequal), new KeysAnd(bUnequal) )) {
				return objB;
			}
		}
		if (diff.bOnlyKeys.length > 0 && diff.aOnlyKeys.length === 0) {
			// collect shared value
			if( set_1$1.isSubset(new KeysAnd(bUnequal),  new KeysAnd(aUnequal) )) {
				return objA;
			}
		}

		return new types.ValuesOr([objA, objB]);
	},
	// {foo: zed, abc: d}
	intersection: function(objA, objB) {
		// combine all properties ... if the same property, try to take
		// an intersection ... if an intersection isn't possible ... freak out?
		var valuesA = objA.values,
			valuesB = objB.values,
			foundEmpty = false;
		var resultValues = {};
		eachInUnique(valuesA,
			function(prop, aVal, bVal) {
				resultValues[prop] = bVal === MISSING ? aVal : set_1$1.intersection(aVal, bVal);
				if (resultValues[prop] === set_1$1.EMPTY) {
					foundEmpty = true;
				}
			},
			valuesB,
			function(prop, aVal, bVal) {
				resultValues[prop] = bVal;
				if (resultValues[prop] === set_1$1.EMPTY) {
					foundEmpty = true;
				}
			});
		if (foundEmpty) {
			return set_1$1.EMPTY;
		} else {
			return new KeysAnd(resultValues);
		}

	},
	// A \ B -> what's in A, but not in B
	difference: difference
});

set_1$1.defineComparison(set_1$1.UNIVERSAL, KeysAnd, {
	// A \ B -> what's in A, but not in B
	difference: function(universe, and) {
		return difference({
			values: {}
		}, and);
	}
});


var keysAnd = types.KeysAnd = KeysAnd;

var andOrNot = {
    KeysAnd: keysAnd,
    ValuesOr: valuesOr,
    ValuesNot: valuesNot,
	ValuesAnd: valuesAnd
};

// mongo puts these first https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#bson-types-comparison-order
var typeNumber = {"undefined": 0, "null": 1, "number": 3, "string": 4, "object": 5, "boolean": 6};
var getTypeNumber = function(obj) {
	var type = typeof obj;
	if(obj === null) {
		type = "null";
	}
	return typeNumber[type];
};

var typeCompare = {
	$gt: function(valueA, valueB) {
		return getTypeNumber(valueA) > getTypeNumber(valueB);
	},
	$lt: function(valueA, valueB) {
		return getTypeNumber(valueA) < getTypeNumber(valueB);
	}
};

var defaultCompare = {
	$gt: function(valueA, valueB) {
		if(valueA == null || valueB == null) {
			return typeCompare.$gt(valueA, valueB);
		}
		return valueA > valueB;
	},
	$lt: function(valueA, valueB) {
		if(valueA == null || valueB == null) {
			return typeCompare.$gt(valueA, valueB);
		}
		return valueA < valueB;
	}
};

var helpers$3 = {

	// given two arrays of items, combines and only returns the unique ones
	uniqueConcat: function(itemsA, itemsB, getId) {
		var ids = new Set();
		return itemsA.concat(itemsB).filter(function(item) {
			var id = getId(item);
			if (!ids.has(id)) {
				ids.add(id);
				return true;
			} else {
				return false;
			}
		});
	},
	// Get the index of an item by it's identity
	// Starting from the middle of the items
	// return the index of match in the right direction
	// or in the left direction
	// otherwise return the last index
	// see getIdentityIndexByDirection
	getIdentityIndex: function(compare, items, props, startIndex, schema) {
		var identity = canReflect_1_19_2_canReflect.getIdentity(props, schema),
			starterItem = items[startIndex];
		// check if the middle has a match
		if (compare(props, starterItem) === 0) {
			if (identity === canReflect_1_19_2_canReflect.getIdentity(starterItem, schema)) {
				return startIndex;
			}
		}
		
		var rightResult = this.getIdentityIndexByDirection(compare, items, props, startIndex+1, 1, schema),
			leftResult;
		if(rightResult.index) {
			return rightResult.index;
		} else {
			leftResult = this.getIdentityIndexByDirection(compare, items, props, startIndex-1, -1, schema);
		}
		if(leftResult.index !== undefined) {
			return leftResult.index;
		}
		// put at the last index item that doesn't match an identity
		return rightResult.lastIndex;
	},
	// Get the index of an item by it's identity
	// for a given direction (right or left)
	// 1 for right
	// -1 for left
	getIdentityIndexByDirection: function(compare, items, props, startIndex, direction, schema) {
		var currentIndex = startIndex;
		var identity = canReflect_1_19_2_canReflect.getIdentity(props, schema);
		while(currentIndex >= 0 && currentIndex < items.length) {
			var currentItem = items[currentIndex];
			var computed = compare(props, currentItem);
			if(computed === 0) {
				if( identity === canReflect_1_19_2_canReflect.getIdentity(currentItem, schema)) {
					return {index: currentIndex};
				}
			} else {
				return {lastIndex: currentIndex - direction};
			}
			currentIndex = currentIndex + direction;
		}
		return {lastIndex: currentIndex - direction};
	},
	//
	getIndex: function(compare, items, props, schema) {
		if(!items){
			return undefined;
		}
		if (items.length === 0) {
			return 0;
		}
		// check the start and the end
		if (compare(props, items[0]) === -1) {
			return 0;
		} else if (compare(props, items[items.length - 1]) === 1) {
			return items.length;
		}

		var low = 0,
			high = items.length;

		// From lodash lodash 4.6.1 <https://lodash.com/>
		// Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
		while (low < high) {
			var mid = (low + high) >>> 1,
				item = items[mid],
				computed = compare(props, item);
			if (computed === 0) {
				return this.getIdentityIndex(compare, items, props, mid, schema);
			} else if (computed === -1) {
				high = mid;
			} else {
				low = mid + 1;
			}
		}
		return high;
		// bisect by calling sortFunc
	},
	sortData: function(sortPropValue) {
		if (sortPropValue[0] === "-") {
			return {
				prop: sortPropValue.slice(1),
				desc: true
			};
		} else {
			return {
				prop: sortPropValue,
				desc: false
			};
		}
	},
	defaultCompare: defaultCompare,
	typeCompare: typeCompare,
	sorter: function(sortPropValue, sorters) {
		var data = helpers$3.sortData(sortPropValue);
		var compare;
		if (sorters && sorters[data.prop]) {
			compare = sorters[data.prop];
		} else {
			compare = defaultCompare;
		}
		return function(item1, item2) {
			var item1Value = canReflect_1_19_2_canReflect.getKeyValue(item1, data.prop);
			var item2Value = canReflect_1_19_2_canReflect.getKeyValue(item2, data.prop);
			var temp;

			if (data.desc) {
				temp = item1Value;
				item1Value = item2Value;
				item2Value = temp;
			}

			if (compare.$lt(item1Value, item2Value)) {
				return -1;
			}

			if (compare.$gt(item1Value, item2Value)) {
				return 1;
			}

			return 0;
		};
	},
	valueHydrator: function(value) {
		if (canReflect_1_19_2_canReflect.isBuiltIn(value)) {
			return value;
		} else {
			throw new Error("can-query-logic doesn't support comparison operator: " + JSON.stringify(value));
		}
	}
};
var helpers_1$3 = helpers$3;

// TYPES FOR FILTERING
var KeysAnd$1 = andOrNot.KeysAnd,
	Or = andOrNot.ValuesOr,
	Not = andOrNot.ValuesNot,
	And = andOrNot.ValuesAnd;

// TYPES FOR PAGINATION
var RecordRange = makeRealNumberRangeInclusive(0, Infinity);


// ## makeSort
// Takes:
// - `schemaKeys` - a schema
// - `hydrateAndValue` - Useful to create something like `new GreaterThan( new MaybeDate("10-20-82") )`
//
// Makes a `new Sort(key)` constructor function. This constructor function is used like:
//
// ```
// new Sort("dueDate")
// ```
//
// That constructor function has all the comparison methods (union, intersection, difference)
// built to compare against the `key` value.
//
// Instances of `Sort` have a `compare` method that will
// return a function that can be passed to `Array.prototype.sort`.
//
// That compare function will read the right property and return `-1` or `1`

// WILL MAKE A TYPE FOR SORTING
function makeSort(schema, hydrateAndValue) {
	var schemaKeys = schema.keys;
	// Makes gt and lt functions that `helpers.sorter` can use
	// to make a `compare` function for `Array.sort(compare)`.`
	var sorters = {};
	canReflect_1_19_2_canReflect.eachKey(schemaKeys, function(schemaProp, key) {

		sorters[key] = {
			// valueA is GT valueB
			$gt: function(valueA, valueB) {
				// handle sorting with null / undefined values
				if(valueA == null || valueB == null) {
					return helpers_1$3.typeCompare.$gt(valueA, valueB);
				}
				// The following can certainly be done faster
				var $gt = hydrateAndValue({
						$gt: valueB
					}, key, schemaProp,
					helpers_1$3.valueHydrator);

				var $eq = hydrateAndValue({
						$eq: valueA
					}, key, schemaProp,
					helpers_1$3.valueHydrator);

				return set_1$1.isEqual( set_1$1.union($gt, $eq), $gt );
				/*
				var hydratedIn =  hydrateAndValue({
						$eq: valueA
					}, key, schemaProp,
					helpers.valueHydrator);
				return $gt[require("can-symbol").for("can.isMember")](hydratedIn.values[0]);*/
			},
			$lt: function(valueA, valueB) {
				if(valueA == null || valueB == null) {
					return helpers_1$3.typeCompare.$lt(valueA, valueB);
				}


				var $lt = hydrateAndValue({
						$lt: valueB
					}, key, schemaProp,
					helpers_1$3.valueHydrator);

				var $eq = hydrateAndValue({
						$eq: valueA
					}, key, schemaProp,
					helpers_1$3.valueHydrator);

				return set_1$1.isEqual( set_1$1.union($lt, $eq), $lt );
				/*
				// This doesn't work because it will try to create new SetType(new In([]))
				var hydratedValue =  hydrateAndValue({
						$eq: valueA
					}, key, schemaProp,
					helpers.valueHydrator);
				return $lt[require("can-symbol").for("can.isMember")](hydratedValue);*/

				/*
				// This doesn't work because of maybe types.
				var hydratedIn =  hydrateAndValue({
						$eq: valueA
					}, key, schemaProp,
					helpers.valueHydrator);
				return $lt[require("can-symbol").for("can.isMember")](hydratedIn.values[0]); */
			}
		};
	});

	function Sort(key) {
		this.key = key;
		this.schema = schema;
		this.compare = helpers_1$3.sorter(key, sorters);
	}

	function identityIntersection(v1, v2) {
		return v1.key === v2.key ? v1 : set_1$1.EMPTY;
	}

	function identityDifference(v1, v2) {
		return v1.key === v2.key ? set_1$1.EMPTY : v1;
	}

	function identityUnion(v1, v2) {
		return v1.key === v2.key ? v1 : set_1$1.UNDEFINABLE;
	}
	set_1$1.defineComparison(Sort, Sort, {
		intersection: identityIntersection,
		difference: identityDifference,
		union: identityUnion
	});
	return Sort;
}

var DefaultSort = makeSort({ keys: {}, identity: ["id"] });


// Define the BasicQuery type
function BasicQuery(query) {
	canAssign_1_3_3_canAssign(this, query);
	if (!this.filter) {
		this.filter = set_1$1.UNIVERSAL;
	}
	if (!this.page) {
		this.page = new RecordRange();
	}
	if (!this.sort) {
		this.sort = "id";
	}
	if (typeof this.sort === "string") {
		this.sort = new DefaultSort(this.sort);
	}
}

// BasicQuery's static properties
BasicQuery.KeysAnd = KeysAnd$1;
BasicQuery.Or = Or;
BasicQuery.Not = Not;
BasicQuery.And = And;
BasicQuery.RecordRange = RecordRange;
BasicQuery.makeSort = makeSort;

// BasicQuery's prototype methods.
// These are "additional" features beyond what `set` provides.
// These typically pertain to actual data results of a query.
canReflect_1_19_2_canReflect.assignMap(BasicQuery.prototype, {
	count: function() {
		return this.page.end - this.page.start + 1;
	},
	sortData: function(data) {
		return data.slice(0).sort(this.sort.compare);
	},
	filterMembersAndGetCount: function(bData, parentQuery) {
		var parentIsUniversal;
		if (parentQuery) {
			parentIsUniversal = set_1$1.isEqual(parentQuery.page, set_1$1.UNIVERSAL);
			if ((parentIsUniversal &&
				!set_1$1.isEqual(parentQuery.filter, set_1$1.UNIVERSAL)) &&
				!set_1$1.isSubset(this, parentQuery)) {
				throw new Error("can-query-logic: Unable to get members from a set that is not a superset of the current set.");
			}
		} else {
			parentQuery = new BasicQuery();
		}

		// reduce response to items in data that meet where criteria
		var aData = bData.filter(function(data) {
			return this.filter.isMember(data);
		}, this);

		var count = aData.length;

		// sort the data if needed
		if (count && (this.sort.key !== parentQuery.sort.key)) {
			aData = this.sortData(aData);
		}

		var thisIsUniversal = set_1$1.isEqual(this.page, set_1$1.UNIVERSAL);
		if(parentIsUniversal == null) {
			parentIsUniversal = set_1$1.isEqual(parentQuery.page, set_1$1.UNIVERSAL);
		}

		if (parentIsUniversal) {
			if (thisIsUniversal) {
				return {
					data: aData,
					count: count
				};
			} else {
				return {
					data: aData.slice(this.page.start, this.page.end + 1),
					count: count
				};
			}
		}
		// everything but range is equal
		else if (this.sort.key === parentQuery.sort.key && set_1$1.isEqual(parentQuery.filter, this.filter)) {
			return {
				data: aData.slice(this.page.start - parentQuery.page.start, this.page.end - parentQuery.page.start + 1),
				count: count
			};
		} else {
			// parent starts at something ...
			throw new Error("can-query-logic: Unable to get members from the parent set for this subset.");
		}
	},
	filterFrom: function(bData, parentQuery) {
		return this.filterMembersAndGetCount(bData, parentQuery).data;
	},
	merge: function(b, aItems, bItems, getId) {
		var union = set_1$1.union(this, b);

		if (union === set_1$1.UNDEFINABLE) {
			return undefined;
		} else {
			var combined = helpers_1$3.uniqueConcat(aItems, bItems, getId);
			return union.sortData(combined);
		}
	},
	index: function(props, items) {
		// make sure we have the property
		var data = helpers_1$3.sortData(this.sort.key);
		if (!canReflect_1_19_2_canReflect.hasOwnKey(props, data.prop)) {
			return undefined;
		}
		// use the passed sort's compare function
		return helpers_1$3.getIndex(this.sort.compare, items, props, this.sort.schema);
	},
	isMember: function(props) {
		// Use the AND type for it's isMember method
		return this.filter.isMember(props);
	},
	removePagination: function() {
		this.page = new RecordRange();
	}
});

// Helpers used for the `set` comparators
var CLAUSE_TYPES = ["filter", "page", "sort"];

function getDifferentClauseTypes(queryA, queryB) {
	var differentTypes = [];

	CLAUSE_TYPES.forEach(function(clause) {
		if (!set_1$1.isEqual(queryA[clause], queryB[clause])) {
			differentTypes.push(clause);
		}
	});

	return differentTypes;
}

function isSubset(subLetter, superLetter, meta) {
	if (meta[subLetter + "FilterIsSubset"]) {
		if (meta[superLetter + "PageIsUniversal"]) {
			return true;
		} else {
			return meta[subLetter + "PageIsSubset"] && meta.sortIsEqual;
		}
	} else {
		return false;
	}
}

// This type contains a bunch of lazy getters that
// cache their value after being read.
// This helps performance.
function MetaInformation(queryA, queryB) {
	this.queryA = queryA;
	this.queryB = queryB;
}

canReflect_1_19_2_canReflect.eachKey({
	"pageIsEqual": function() {
		return set_1$1.isEqual(this.queryA.page, this.queryB.page);
	},
	"aPageIsUniversal": function() {
		return set_1$1.isEqual(this.queryA.page, set_1$1.UNIVERSAL);
	},
	"bPageIsUniversal": function() {
		return set_1$1.isEqual(this.queryB.page, set_1$1.UNIVERSAL);
	},
	"pagesAreUniversal": function() {
		return this.pageIsEqual && this.aPageIsUniversal;
	},
	"sortIsEqual": function() {
		return this.queryA.sort.key === this.queryB.sort.key;
	},
	"aFilterIsSubset": function() {
		return set_1$1.isSubset(this.queryA.filter, this.queryB.filter);
	},
	"bFilterIsSubset": function() {
		return set_1$1.isSubset(this.queryB.filter, this.queryA.filter);
	},
	"aPageIsSubset": function() {
		return set_1$1.isSubset(this.queryA.page, this.queryB.page);
	},
	"bPageIsSubset": function() {
		return set_1$1.isSubset(this.queryB.page, this.queryA.page);
	},
	"filterIsEqual": function() {
		return set_1$1.isEqual(this.queryA.filter, this.queryB.filter);
	},
	"aIsSubset": function() {
		return isSubset("a", "b", this);
	},
	"bIsSubset": function() {
		return isSubset("b", "a", this);
	}
}, function(def, prop) {
	canDefineLazyValue_1_1_1_defineLazyValue(MetaInformation.prototype, prop, def);
});

function metaInformation(queryA, queryB) {
	var meta = new MetaInformation(queryA, queryB);
	return meta;
}


// Define comparators
set_1$1.defineComparison(BasicQuery, BasicQuery, {
	union: function(queryA, queryB) {

		var meta = metaInformation(queryA, queryB);


		var filterUnion = set_1$1.union(queryA.filter, queryB.filter);

		if (meta.pagesAreUniversal) {
			// We ignore the sort.
			return new BasicQuery({
				filter: filterUnion,
				sort: meta.sortIsEqual ? queryA.sort.key : undefined
			});
		}


		if (meta.filterIsEqual) {
			if (meta.sortIsEqual) {
				return new BasicQuery({
					filter: queryA.filter,
					sort: queryA.sort.key,
					page: set_1$1.union(queryA.page, queryB.page)
				});
			} else {
				if (meta.aIsSubset) {
					return queryB;
				} else if (meta.bIsSubset) {
					return queryA;
				}
				// we can't specify which pagination would bring in everything.
				// but a union does exist.
				return set_1$1.UNDEFINABLE;
			}
		} else {
			throw new Error("different filters, non-universal pages");
		}
	},
	intersection: function(queryA, queryB) {

		// {age: 35} U {name: "JBM"} -> {age: 35, name: "JBM"}

		// { filter: {age: 35},
		//   page: {0, 10},
		//   sort: "foo" }
		// U
		// { filter: {name: "JBM"},
		//   page: {0, 10},
		//   sort: "foo" }

		var meta = metaInformation(queryA, queryB);

		if (meta.pagesAreUniversal) {
			// We ignore the sort.
			var filterResult = set_1$1.intersection(queryA.filter, queryB.filter);
			if (set_1$1.isDefinedAndHasMembers(filterResult)) {
				return new BasicQuery({
					filter: filterResult,
					sort: meta.sortIsEqual ? queryA.sort.key : undefined
				});

			} else {
				return filterResult;
			}
		}



		// check if disjoint wheres
		if (set_1$1.intersection(queryA.filter, queryB.filter) === set_1$1.EMPTY) {
			return set_1$1.EMPTY;
		}

		if (meta.filterIsEqual) {
			if (meta.sortIsEqual) {
				return new BasicQuery({
					filter: queryA.filter,
					sort: queryA.sort.key,
					page: set_1$1.intersection(queryA.page, queryB.page)
				});
			} else {
				if (meta.aIsSubset) {
					return queryA;
				} else if (meta.bIsSubset) {
					return queryB;
				}
				return set_1$1.UNKNOWABLE;
				//throw new Error("same filter, different sorts, non universal pages");
			}
		} else {
			if (meta.aIsSubset) {
				return queryA;
			} else if (meta.bIsSubset) {
				return queryB;
			} else {
				// filters are different, both pagination isn't universal
				return set_1$1.UNDEFINABLE;
			}

		}

	},
	difference: function(queryA, queryB) {

		var differentClauses = getDifferentClauseTypes(queryA, queryB);
		var meta = metaInformation(queryA, queryB);
		var clause;
		if (differentClauses.length > 1) {
			if (meta.aIsSubset) {
				return set_1$1.EMPTY;
			}
			if (meta.pagesAreUniversal) {
				return new BasicQuery({
					filter: set_1$1.difference(queryA.filter, queryB.filter),
					sort: queryA.sort.key
				});
			}

			return set_1$1.UNDEFINABLE;
		} else {
			switch (clause = differentClauses[0]) {
				// if all the clauses are the same, then there can't be a difference
				case undefined:
					{
						return set_1$1.EMPTY;
					}
				case "sort":
					{
						// if order is the only difference, then there can't be a difference
						// if items are paged but the order is different, though, the sets are not comparable
						// Either way, the result is false
						if (meta.pagesAreUniversal) {
							return set_1$1.EMPTY;
						} else {
							return set_1$1.UNKNOWABLE;
						}


					}
					break;
				case "page":
				case "filter":
					{
						// if there's only one clause to evaluate or the clauses are where + id,
						// then we can try to determine the difference set.
						// Note that any difference in the ID clause will cause the result to be
						// true (if A has no ID but B has ID) or false (any case where A has ID)
						var result = set_1$1.difference(queryA[clause],
							queryB[clause]);

						if (set_1$1.isSpecial(result)) {
							return result;
						} else {
							var query = {
								filter: queryA.filter,
								page: queryA.page,
								sort: queryA.sort.key
							};
							query[clause] = result;
							return new BasicQuery(query);
						}
					}
			}
		}
	}
});


var basicQuery = BasicQuery;

var Serializer = function(entries){
	var serializers = this.serializers = new Map();
	if (entries) {
		entries.forEach(function(entry) {
			var key = entry[0], value = entry[1];
			serializers.set(key, value);
		});
	}
    this.serialize = this.serialize.bind(this);
};
Serializer.prototype.add = function(serializers){
    canReflect_1_19_2_canReflect.assign( this.serializers, serializers instanceof Serializer ? serializers.serializers : serializers );
};


Serializer.prototype.serialize = function(item) {
    if(!item) {
        return item;
    }
    var Type = item.constructor;
    var serializer = this.serializers.get(Type);
    if(!serializer) {
        return canReflect_1_19_2_canReflect.serialize(item);
    } else {
        return serializer(item, this.serialize);
    }
};

var serializer = Serializer;

function makeNew(Constructor) {
	return function(value) {
		return new Constructor(value);
	};
}
var hydrateMap = {};
function addHydrateFrom(key, hydrate) {
	hydrateMap[key] = function(value, unknownHydrator) {
		return hydrate( unknownHydrator ? unknownHydrator(value[key]) : value[key]);
	};
	Object.defineProperty(hydrateMap[key], "name", {
		value: "hydrate "+key,
		writable: true
	});
}

function addHydrateFromValues(key, hydrate) {
	hydrateMap[key] = function(value, unknownHydrator) {
		var clones = value[key];
		if(unknownHydrator) {
			clones = clones.map(function(value) {
				return unknownHydrator(value);
			});
		}
		return hydrate( clones );
	};
	Object.defineProperty(hydrateMap[key], "name", {
		value: "hydrate "+key,
		writable: true
	});
}

// https://docs.mongodb.com/manual/reference/operator/query-comparison/
addHydrateFrom("$eq", function(value) {
	return new comparisons_1$1.In([value]);
});
addHydrateFrom("$ne", function(value) {
	return new comparisons_1$1.NotIn([value]);
});

addHydrateFrom("$gt", makeNew(comparisons_1$1.GreaterThan));
addHydrateFrom("$gte", makeNew(comparisons_1$1.GreaterThanEqual));
addHydrateFromValues("$in", makeNew(comparisons_1$1.In));
addHydrateFrom("$lt", makeNew(comparisons_1$1.LessThan));
addHydrateFrom("$lte", makeNew(comparisons_1$1.LessThanEqual));

addHydrateFromValues("$all", makeNew(comparisons_1$1.All));

// This is a mapping of types to their opposite. The $not hydrator
// uses this to create a more specific type, since they are logical opposites.
var oppositeTypeMap = {
	LessThan: { Type: comparisons_1$1.GreaterThanEqual, prop: "value" },
	LessThanEqual: { Type: comparisons_1$1.GreaterThan, prop: "value" },
	GreaterThan: { Type: comparisons_1$1.LessThanEqual, prop: "value" },
	GreaterThanEqual: { Type: comparisons_1$1.LessThan, prop: "value" },
	In: { Type: comparisons_1$1.NotIn, prop: "values" },
	NotIn: { Type: comparisons_1$1.In, prop: "values" }
};

hydrateMap.$not = function(value, unknownHydrator) {
	// Many nots can be hydrated to their opposite.
	var hydratedValue = hydrateValue(value.$not, unknownHydrator);
	var typeName = hydratedValue.constructor.name || hydratedValue.constructor.toString().match(/^\s*function\s*(\S*)\s*\(/)[1];

	if(oppositeTypeMap[typeName]) {
		var options = oppositeTypeMap[typeName];
		var OppositeConstructor = options.Type;
		var prop = options.prop;

		return new OppositeConstructor(hydratedValue[prop]);
	}

	return new valuesNot(hydratedValue);
};

addHydrateFromValues("$nin", makeNew(comparisons_1$1.NotIn));


var serializer$1 = new serializer([
	[comparisons_1$1.In,function(isIn, serialize) {
		return isIn.values.length === 1 ?
			serialize(isIn.values[0]) :
			{$in: isIn.values.map(serialize)};
	}],
	[comparisons_1$1.NotIn,function(notIn, serialize) {
		return notIn.values.length === 1 ?
			{$ne: serialize(notIn.values[0])} : {$nin: notIn.values.map(serialize)};
	}],
	[comparisons_1$1.GreaterThan, function(gt, serialize) { return {$gt: serialize(gt.value) }; }],
	[comparisons_1$1.GreaterThanEqual, function(gte, serialize) { return {$gte: serialize(gte.value) }; }],
	[comparisons_1$1.LessThan, function(lt, serialize) { return {$lt: serialize(lt.value) }; }],
	[comparisons_1$1.LessThanEqual, function(lt, serialize) { return {$lte: serialize(lt.value) }; }],
	[comparisons_1$1.And, function(and, serialize) {
		var obj = {};
		and.values.forEach(function(clause) {
			canReflect_1_19_2_canReflect.assignMap(obj, serialize(clause) );
		});
		return obj;
	}],
	[comparisons_1$1.All, function(all, serialize) {
		return {
			$all: serialize(all.values)
		};
	}]
	/*[is.Or, function(or, serialize) {
		return {
			$or: or.values.map(function(value) {
				return serialize(value, serialize);
			})
		};
	}]*/
]);

function hydrateValue(value, hydrateUnknown) {
	if(!hydrateUnknown) {
		hydrateUnknown = function() {
			throw new Error("can-query-logic doesn't recognize operator: "+JSON.stringify(value));
		};
	}
	if(Array.isArray(value)) {
		return new comparisons_1$1.In(value.map(function(value) {
			return hydrateUnknown(value);
		}));
	}
	else if(value && typeof value === "object") {
		var keys = Object.keys(value);
		var allKeysAreComparisons = keys.every(function(key) {
			return hydrateMap[key];
		});
		if(allKeysAreComparisons) {
			var andClauses = keys.map(function(key) {
				var part = {};
				part[key] = value[key];
				var hydrator = hydrateMap[key];
				return hydrator(part, hydrateUnknown);
			});
			if(andClauses.length > 1) {
				return new comparisons_1$1.And(andClauses);
			} else {
				return andClauses[0];
			}
		} else {
			return hydrateUnknown(value);
		}
	} else {
		return new comparisons_1$1.In([hydrateUnknown(value)]);
	}
}

var comparisons$2 = {
	// value - something from a query, for example {$in: [1,2]}
	hydrate: hydrateValue,
	serializer: serializer$1
};

var schemaHelpers;
var schemaHelpers_1 = schemaHelpers = {

    // Number is a ranged type
    isRangedType: function(Type){
        return Type && canReflect_1_19_2_canReflect.isConstructorLike(Type) &&
            !set_1$1.hasComparisons(Type) &&
            !Type[canSymbol_1_7_0_canSymbol.for("can.SetType")] &&
            Type.prototype.valueOf && Type.prototype.valueOf !== Object.prototype.valueOf;
    },
    categorizeOrValues: function categorizeOrValues(values){

    	var categories = {
    		primitives: [],
    		valueOfTypes: [],
    		others: []
    	};

    	values.forEach(function(value){
    		if( canReflect_1_19_2_canReflect.isPrimitive( value ) ) {
    			categories.primitives.push(value);
    		}
    		else if( schemaHelpers.isRangedType(value) ) {
    			categories.valueOfTypes.push(value);
    		}
    		else {
    			categories.others.push(value);
    		}
    	});
    	return categories;
    }
};

var comparisonSetTypeSymbol = canSymbol_1_7_0_canSymbol.for("can.ComparisonSetType");
var isMemberSymbol$4 = canSymbol_1_7_0_canSymbol.for("can.isMember");

// This helper function seperates out sets that relate to the "maybe" values
// like `null` or `undefined`. For example, if `rangeToBeSplit`
// is `In([null, 3])`, it will produce `{enum: In([null]), range: In(3)}`
function splitByRangeAndEnum(maybeUniverse, rangeToBeSplit) {
	var enumSet;

	// If it's an AND
	if (rangeToBeSplit instanceof comparisons_1$1.And) {
		// recursively split each value
		var sets = rangeToBeSplit.values.map(function(setInAnd) {
			return splitByRangeAndEnum(maybeUniverse, setInAnd);
		});
		// take the intersections
		return sets.reduce(function(last, maybe) {
			return {
				range: set_1$1.intersection(last.range, maybe.range),
				enum: set_1$1.intersection(last.enum, maybe.enum)
			};
		}, {
			range: set_1$1.UNIVERSAL,
			enum: maybeUniverse
		});

	} else if (rangeToBeSplit instanceof comparisons_1$1.In) {

		var shouldBeInValues = rangeToBeSplit.values.filter(function(value) {
			return maybeUniverse.isMember(value);
		});
		if (shouldBeInValues.length) {
			var valuesCopy = rangeToBeSplit.values.slice(0);
			canReflect_1_19_2_canReflect.removeValues(valuesCopy, shouldBeInValues);

			return {
				enum: new comparisons_1$1.In(shouldBeInValues),
				range: valuesCopy.length ? new comparisons_1$1.In(valuesCopy) : set_1$1.EMPTY
			};
		} else {
			return {
				enum: set_1$1.EMPTY,
				range: rangeToBeSplit
			};
		}
	} else if (rangeToBeSplit instanceof comparisons_1$1.NotIn) {

		// Gets the 'maybe' values in the range
		enumSet = set_1$1.intersection(maybeUniverse, rangeToBeSplit);

		// We should remove all the values within $in matching an in values.
		var rangeValues = rangeToBeSplit.values.filter(function(value) {
			return !maybeUniverse.isMember(value);
		});
		return {
			range: rangeValues.length ? new comparisons_1$1.NotIn(rangeValues) : set_1$1.UNIVERSAL,
			enum: enumSet
		};
	} else {
		return {
			enum: set_1$1.EMPTY,
			range: rangeToBeSplit
		};
	}
}

// Builds a type for ranged values plus some other enum values.
// This is great for 'maybe' values. For example, it might be a string OR `null` OR `undefined`
// `makeMaybe([null, undefined])`
function makeMaybe(inValues, makeChildType) {


	var maybeUniverse = new comparisons_1$1.In(inValues);

	function Maybe(values) {

		// Maybe has two sub-sets:
		// - `.range` - Selects the non-enum values. Ex: `GreaterThan(3)`
		// - `.enum` - Selects the enum values. This is ALWAYS an `In`. Ex: `In([null])`.
		// Maybe is effectively an OR with these two properties.
		var result = splitByRangeAndEnum(maybeUniverse, values.range);
		this.range = result.range || set_1$1.EMPTY;
		if (values.enum) {
			if (result.enum !== set_1$1.EMPTY) {
				this.enum = set_1$1.union(result.enum, values.enum);
			} else {
				this.enum = values.enum;
			}
		} else {
			this.enum = result.enum;
		}
		if(this.enum === set_1$1.EMPTY && this.range === set_1$1.EMPTY) {
			return set_1$1.EMPTY;
		}
	}
	Maybe.prototype.orValues = function() {
		var values = [];
		if( this.range !== set_1$1.EMPTY ) {
			values.push(this.range);
		}
		if( this.enum !== set_1$1.EMPTY ) {
			values.push(this.enum);
		}
		return values;
	};
	Maybe.prototype[isMemberSymbol$4] = function isMember() {
		var rangeIsMember = this.range[isMemberSymbol$4] || this.range.isMember,
			enumIsMember = this.enum[isMemberSymbol$4] || this.enum.isMember;
		return rangeIsMember.apply(this.range, arguments) || enumIsMember.apply(this.enum, arguments);
	};



	set_1$1.defineComparison(Maybe, Maybe, {
		union: function(maybeA, maybeB) {
			var enumSet = set_1$1.union(maybeA.enum, maybeB.enum);
			var range = set_1$1.union(maybeA.range, maybeB.range);

			return new Maybe({
				enum: enumSet,
				range: range
			});
		},
		difference: function(maybeA, maybeB) {
			var enumSet = set_1$1.difference(maybeA.enum, maybeB.enum);
			var range = set_1$1.difference(maybeA.range, maybeB.range);

			return new Maybe({
				enum: enumSet,
				range: range
			});
		},
		intersection: function(maybeA, maybeB) {
			var enumSet = set_1$1.intersection(maybeA.enum, maybeB.enum);
			var range = set_1$1.intersection(maybeA.range, maybeB.range);

			return new Maybe({
				enum: enumSet,
				range: range
			});
		}
	});
	Maybe.inValues = inValues;

	set_1$1.defineComparison(set_1$1.UNIVERSAL, Maybe, {
		difference: function(universe, maybe) {
			var primary,
				secondary;

			if (maybe.range === set_1$1.UNIVERSAL) {
				// there is only the enum
				return new Maybe({
					range: maybe.range,
					enum: set_1$1.difference(maybeUniverse, maybe.enum)
				});
			}
			// there is only a primary
			if (maybe.enum === set_1$1.EMPTY) {
				var rangeSet = set_1$1.difference(set_1$1.UNIVERSAL, maybe.range);
				var notPresent = set_1$1.difference(maybeUniverse, maybe.range);
				// make sure they are included
				var enumSet = set_1$1.difference(notPresent, rangeSet);


				return new Maybe({
					range: rangeSet,
					enum: enumSet
				});
				// check enum things that aren't included in primary

			} else {
				primary = set_1$1.difference(universe, maybe.range);
				secondary = set_1$1.difference(maybeUniverse, maybe.enum);
			}
			return new Maybe({
				enum: secondary,
				range: primary
			});
		}
	});
	makeChildType = makeChildType || function(v) {
		return v;
	};

	Maybe.hydrate = function(value, childHydrate) {
		return new Maybe({
			range: childHydrate(value, makeChildType)
		});
	};

	return Maybe;
}



makeMaybe.canMakeMaybeSetType = function(Type) {
	var schema = canReflect_1_19_2_canReflect.getSchema(Type);
	if (schema && schema.type === "Or") {
		var categories = schemaHelpers_1.categorizeOrValues(schema.values);

		return categories.valueOfTypes.length === 1 &&
			(categories.valueOfTypes.length + categories.primitives.length === schema.values.length);
	}
	return false;
};

// Given an __Or__ type like:
// ```
// var MaybeString = {
//   "can.new"(val){ ... },
// 	 "can.getSchema"(){ return  { type: "Or", values: [String, undefined, null] }
// });
// ```
//
// This creates two types:
// - `Value` - A value type used for what's within `GreaterThan`, etc.
// - `Maybe` - A SetType for this property. It will have `GreaterThan` within its
//            `{enum, range}` sub values.
//
// This creates the outer `SetType` and the innermost `Value` type while the Comparisons
// are used inbetween.
//
// The `MaybeString` could probably be directly used to hydrate values to what they should be.
makeMaybe.makeMaybeSetTypes = function(Type) {
	var schema = canReflect_1_19_2_canReflect.getSchema(Type);
	var categories = schemaHelpers_1.categorizeOrValues(schema.values);
	var ComparisonSetType;

	// No need to build the comparison type if we are given it.
	if (Type[comparisonSetTypeSymbol]) {
		ComparisonSetType = Type[comparisonSetTypeSymbol];
	} else {

		ComparisonSetType = function(value) {
			this.setValue = value;
			this.value = canReflect_1_19_2_canReflect.new(Type, value);
		};

		ComparisonSetType.prototype.valueOf = function() {
			return this.value && typeof this.value.valueOf === "function" ?
				this.value.valueOf() : this.value;
		};
		canReflect_1_19_2_canReflect.assignSymbols(ComparisonSetType.prototype, {
			"can.serialize": function() {
				return this.setValue;
			}
		});
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			Object.defineProperty(ComparisonSetType, "name", {
				value: "Or[" + categories.valueOfTypes[0].name + "," + categories.primitives.map(String).join(" ") + "]"
			});
		}
		//!steal-remove-end
	}

	return {
		Maybe: makeMaybe(categories.primitives, function hydrateMaybesValueType(value) {
			return new ComparisonSetType(value);
		}),
		ComparisonSetType: ComparisonSetType
	};
};


var makeMaybe_1 = makeMaybe;

var setTypeSymbol = canSymbol_1_7_0_canSymbol.for("can.SetType"),
	isMemberSymbol$5 = canSymbol_1_7_0_canSymbol.for("can.isMember"),
	newSymbol$2 = canSymbol_1_7_0_canSymbol.for("can.new");

function makeEnumSetType(allValues, hydrate) {
	function Enum(values) {
		var arr = Array.isArray(values) ? values : [values];
		this.values = hydrate ? arr.map(hydrate) : arr;
	}
	canReflect_1_19_2_canReflect.assignSymbols(Enum.prototype, {
		"can.serialize": function() {
			return this.values.length === 1 ? this.values[0] : this.values;
		}
	});

	Enum.prototype[isMemberSymbol$5] = function(value) {
		return this.values.some(function(val) {
			return set_1$1.isEqual(val, value);
		});
	};

	Enum.UNIVERSAL = new Enum(allValues);

	var difference = function(enum1, enum2) {
		var result = arrayUnionIntersectionDifference(enum1.values, enum2.values);
		if (result.difference.length) {
			return new Enum(result.difference);
		} else {
			return set_1$1.EMPTY;
		}
	};

	set_1$1.defineComparison(Enum, Enum, {
		union: function(enum1, enum2) {
			var result = arrayUnionIntersectionDifference(enum1.values, enum2.values);
			if (result.union.length) {
				return new Enum(result.union);
			} else {
				return set_1$1.EMPTY;
			}
		},
		intersection: function(enum1, enum2) {
			var result = arrayUnionIntersectionDifference(enum1.values, enum2.values);
			if (result.intersection.length) {
				return new Enum(result.intersection);
			} else {
				return set_1$1.EMPTY;
			}
		},
		difference: difference
	});

	set_1$1.defineComparison(Enum, set_1$1.UNIVERSAL, {
		difference: function(enumA) {
			return difference(enumA, {
				values: allValues.slice(0)
			});
		}
	});

	set_1$1.defineComparison(set_1$1.UNIVERSAL, Enum, {
		difference: function(universe, enumB) {
			return difference({
				values: allValues.slice(0)
			}, enumB);
		}
	});

	return Enum;
}

function makeEnum$1(Type, allValues, hydrate) {

	var Enum = makeEnumSetType(allValues, hydrate);

	Type[setTypeSymbol] = Enum;
	Type[isMemberSymbol$5] = function(value) {
		return allValues.some(function(val) {
			return set_1$1.isEqual(val, value);
		});
	};

	return Enum;
}

makeEnum$1.canMakeEnumSetType = function(Type) {
	var schema = canReflect_1_19_2_canReflect.getSchema(Type);
	if (schema && schema.type === "Or") {
		var categories = schemaHelpers_1.categorizeOrValues(schema.values);
		return categories.primitives.length === schema.values.length;
	}
	return false;
};

makeEnum$1.makeEnumSetType = function(Type) {
	var schema = canReflect_1_19_2_canReflect.getSchema(Type);
	var categories = schemaHelpers_1.categorizeOrValues(schema.values);
	var hydrate = Type[newSymbol$2] ? Type[newSymbol$2].bind(Type) : undefined;
	return makeEnumSetType(categories.primitives, hydrate);
};

var makeEnum_1 = makeEnum$1;

var setTypeSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.SetType");
var schemaSymbol = canSymbol_1_7_0_canSymbol.for("can.getSchema");

var defaultQuery = new basicQuery({});


function getSchemaProperties(value) {
	var constructor = value.constructor;
	if (constructor && constructor[schemaSymbol]) {
		var schema = constructor[schemaSymbol]();
		return schema.keys || {};
	} else {
		return {};
	}
}

function hydrateFilter(values, schemaProperties, hydrateUnknown) {
	var valuesIsObject = values && typeof values === "object";
	if (valuesIsObject && ("$or" in values)) {
		return hydrateOrs(values.$or, schemaProperties, hydrateUnknown);
	} else if(valuesIsObject && ("$and" in values)) {
		return hydrateAnds(values.$and, schemaProperties, hydrateUnknown);
	} else {
		return hydrateAndValues(values, schemaProperties, hydrateUnknown);
	}
}

var setTypeMap = new WeakMap();

// This is used to hydrate a value directly within a `filter`'s And.
function hydrateAndValue(value, prop, SchemaType, hydrateChild) {
	// The `SchemaType` is the type of value on `instances` of
	// the schema. `Instances` values are different from `Set` values.
	if (SchemaType) {
		// If there's a `SetType`, we will use that
		var SetType = SchemaType[setTypeSymbol$1];
		if (SetType) {
			/// If it exposes a hydrate, this means it can use the current hydrator to
			// hydrate its children.
			// I'm not sure why it's not taking the `unknown` hydrator instead.
			if (SetType.hydrate) {
				return SetType.hydrate(value, comparisons$2.hydrate);
			}
			// If the SetType implemented `union`, `intersection`, `difference`
			// We can create instances of it directly.
			else if (set_1$1.hasComparisons(SetType)) {
				// Todo ... canReflect.new
				return new SetType(value);
			}
			// If the SetType did not implement the comparison methods,
			// it's probably just a "Value" comparison type. We will hydrate
			// as a comparison converter, but create an instance of this `"Value"`
			// comparison type within the comparison converter.
			else {
				// inner types
				return comparisons$2.hydrate(value, function(value) {
					return new SetType(value);
				});
			}

		} else {
			// There is a `SchemaType`, but it doesn't have a `SetType`.
			// Can we create the SetType from the `SchemaType`?
			if (makeEnum_1.canMakeEnumSetType(SchemaType)) {
				if (!setTypeMap.has(SchemaType)) {
					setTypeMap.set(SchemaType, makeEnum_1.makeEnumSetType(SchemaType));
				}
				SetType = setTypeMap.get(SchemaType);
				return new SetType(value);
			}
			// It could also have a `ComparisonSetType` which are the values
			// within the Maybe type.
			else if (makeMaybe_1.canMakeMaybeSetType(SchemaType)) {
				if (!setTypeMap.has(SchemaType)) {
					setTypeMap.set(SchemaType, makeMaybe_1.makeMaybeSetTypes(SchemaType));
				}
				SetType = setTypeMap.get(SchemaType).Maybe;
				return SetType.hydrate(value, comparisons$2.hydrate);
			}
			// We can't create the `SetType`, so lets hydrate with the default behavior.
			else {
				return comparisons$2.hydrate(value, hydrateChild);
			}
		}
	} else {
		// HERE {$gt: 1} -> new is.GreaterThan(1)
		return comparisons$2.hydrate(value, hydrateChild);
	}
}

function hydrateAndValues(values, schemaProperties, hydrateUnknown) {
	schemaProperties = schemaProperties || {};

	function hydrateChild(value) {
		if (value) {
			if (Array.isArray(value)) {
				return value.map(hydrateUnknown);
			} else if (canReflect_1_19_2_canReflect.isPlainObject(value)) {
				// lets try to get the schema ...
				return hydrateAndValues(value, getSchemaProperties(value));
			}
		}
		if (hydrateUnknown) {
			return hydrateUnknown(value);
		} else {
			return value;
		}
	}
	var clone = {};
	canReflect_1_19_2_canReflect.eachKey(values, function(value, prop) {
		clone[prop] = hydrateAndValue(value, prop, schemaProperties[prop], hydrateChild);
	});

	return new basicQuery.KeysAnd(clone);

}
// This tries to combine a bunch of OR-ed ANDS into a single AND.
// Example: [{name: "j", age: 3},{name: "j", age: 4}] //-> {name: "j", age: in[3,4]}
function combineAnds(ands) {
	var firstKeys = Object.keys(ands[0].values);
	var keys = {};

	var keysCompare = new comparisons_1$1.In(firstKeys);

	firstKeys.map(function(key) {
		keys[key] = [];
	});

	var sameKeys = ands.every(function(and) {
		// have to have the same keys
		if (!set_1$1.isEqual(keysCompare, new comparisons_1$1.In(Object.keys(and.values)))) {
			return false;
		}
		canReflect_1_19_2_canReflect.eachKey(and.values, function(value, key) {
			keys[key].push(value);
		});
		return true;
	});
	if (!sameKeys) {
		return;
	}
	// now try to union everything and see if it simplifies ...
	var unequalKeys = [];
	firstKeys.forEach(function(key) {
		var isEqual = keys[key].reduce(function(newSet, lastSetOrFalse) {
			if (lastSetOrFalse === false) {
				return false;
			}
			if (lastSetOrFalse === undefined) {
				return newSet;
			}
			var res = set_1$1.isEqual(newSet, lastSetOrFalse);
			return res ? newSet : false;
		});
		if (!isEqual) {
			unequalKeys.push(key);
		}
	});

	if (unequalKeys.length !== 1) {
		return;
	}
	var unionKey = unequalKeys[0];
	// lets see if we can union that one value
	var unioned = keys[unionKey].reduce(function(cur, last) {
		return set_1$1.union(cur, last);
	}, set_1$1.EMPTY);

	var result = {};
	firstKeys.map(function(key) {
		result[key] = keys[key][0];
	});
	result[unionKey] = unioned;
	return new basicQuery.KeysAnd(result);
}

function hydrateOrs(values, schemaProperties, hydrateUnknown) {
	var comparisons = values.map(function(value) {
		return hydrateAndValues(value, schemaProperties, hydrateUnknown);
	});
	var combined = combineAnds(comparisons);
	if (combined) {
		return combined;
	}
	return new basicQuery.Or(comparisons);
}

function hydrateAnds(values, schemaProperties, hydrateUnknown) {
	var comparisons = values.map(function(value) {
		return hydrateAndValues(value, schemaProperties, hydrateUnknown);
	});
	return new basicQuery.And(comparisons);
}

function recursivelyAddOrs(ors, value, serializer$$1, key){
    value.orValues().forEach(function(orValue){
        if(typeof orValue.orValues === "function") {
            recursivelyAddOrs(ors, orValue, serializer$$1, key);
        } else {
            var result = {};
            result[key] = serializer$$1(orValue);
            ors.push( result );
        }
    });
}

var basicQuery$1 = function(schema) {

	var id = schema.identity && schema.identity[0];
	var keys = schema.keys;

	var serializeMap = [
		[basicQuery.Or, function(or, serializer$$1) {
			return or.values.map(function(value) {
				return serializer$$1(value);
			});
		}],
		[basicQuery.And, function(and, serializer$$1) {
			return { $and: and.values.map(function(value) {
				return serializer$$1(value);
			}) };
		}],
		[basicQuery.Not, function(nots, serializer$$1) {
			return { $not: serializer$$1(nots.value) };
		}],
		// this destructures ANDs with OR-like clauses
		[basicQuery.KeysAnd, function(and, serializer$$1) {
			var ors = [];
			var result = {};
			canReflect_1_19_2_canReflect.eachKey(and.values, function(value, key) {
				// is value universal ... if not, we don't need to add anything

				if (typeof value.orValues === "function") {
					recursivelyAddOrs(ors, value, serializer$$1, key);
				} else {
					result[key] = serializer$$1(value);
				}
			});

			if (ors.length) {
				if (ors.length === 1) {
					return ors[0];
				} else {
					return {
						$or: ors.map(function(orPart) {
							return canReflect_1_19_2_canReflect.assign(canReflect_1_19_2_canReflect.serialize(result), orPart);
						})
					};
				}
			} else {
				return result;
			}

		}],
		[basicQuery.RecordRange, function(range) {
			return {
				start: range.start,
				end: range.end
			};
		}],
		[basicQuery, function(basicQuery$$1, childSerializer) {

			var filter = set_1$1.isEqual(basicQuery$$1.filter, set_1$1.UNIVERSAL) ? {} : childSerializer(basicQuery$$1.filter);

			var res = {};
			if (canReflect_1_19_2_canReflect.size(filter) !== 0) {
				res.filter = filter;
			}

			if (!set_1$1.isEqual(basicQuery$$1.page, defaultQuery.page)) {
				// we always provide the start, even if it's 0
				res.page = {
					start: basicQuery$$1.page.start
				};
				if (basicQuery$$1.page.end !== defaultQuery.page.end) {
					res.page.end = basicQuery$$1.page.end;
				}
			}

			if (basicQuery$$1.sort.key !== id) {
				res.sort = basicQuery$$1.sort.key;
			}
			return res;

		}]
	];



	// Makes a sort type that can make a compare function using the SetType
	var Sort = basicQuery.makeSort(schema, hydrateAndValue);
	var serializer$$1 = new serializer(serializeMap);
	serializer$$1.add(comparisons$2.serializer);

	return {
		hydrate: function(data) {

			//!steal-remove-start
			if (process.env.NODE_ENV !== 'production') {
				var AcceptedFields = makeEnum_1(function() {}, ["filter", "sort", "page"]);
				var diff = set_1$1.difference(new AcceptedFields(Object.keys(data)), AcceptedFields.UNIVERSAL);
				if (diff.values && diff.values.length) {
					dev.warn(
						"can-query-logic: Ignoring keys: " + diff.values.join(", ") + "."
					);
				}
			}
			//!steal-remove-end


			var filter = canReflect_1_19_2_canReflect.serialize(data.filter);

			// this mutates
			var filterAnd = hydrateFilter(filter, keys, helpers_1$3.valueHydrator);

			// Conver the filter arguments

			var query = {
				filter: filterAnd
			};
			if (data.page) {
				query.page = new basicQuery.RecordRange(data.page.start, data.page.end);
			}
			if (data.sort) {
				query.sort = new Sort(data.sort);
			} else {
				query.sort = new Sort(id);
			}
			return new basicQuery(query);
		},
		serializer: serializer$$1
	};
};

var schemaSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.getSchema");
var newSymbol$3 = canSymbol_1_7_0_canSymbol.for("can.new");



// Creates an algebra used to convert primitives to types and back
function QueryLogic(Type, options){
    Type = Type || {};
    var passedHydrator = options && options.toQuery;
    var passedSerializer = options && options.toParams;
    var schema;
    if(Type[schemaSymbol$1]) {
        schema = Type[schemaSymbol$1]();
    } else {
        schema = Type;
    }

    // check that the basics are here

    var id = schema.identity && schema.identity[0];
    if(!id) {
        //console.warn("can-query given a type without an identity schema.  Using `id` as the identity id.");
        schema.identity = ["id"];
    }

    var converter = basicQuery$1(schema),
        hydrate,
        serialize;

    if(passedHydrator) {
        hydrate = function(query){
            return converter.hydrate(passedHydrator(query));
        };
    } else {
        hydrate = converter.hydrate;
    }

    if(passedSerializer) {
        serialize = function(query){
            return passedSerializer(converter.serializer.serialize(query));
        };
    } else {
        serialize = converter.serializer.serialize;
    }
    this.hydrate = hydrate;
    this.serialize = serialize;
    this.schema = schema;

}

function makeNewSet(prop){
    return function(qA, qB){
        var queryA = this.hydrate(qA),
            queryB = this.hydrate(qB);
        var unionQuery = set_1$1[prop](queryA , queryB );
        return this.serialize( unionQuery );
    };
}

function makeReturnValue(prop) {
    return function(qA, qB){
        var queryA = this.hydrate(qA),
            queryB = this.hydrate(qB);
        return set_1$1[prop](queryA , queryB );
    };
}

canReflect_1_19_2_canReflect.assignSymbols(QueryLogic.prototype,{
    "can.getSchema": function(){
        return this.schema;
    }
});

canReflect_1_19_2_canReflect.assign(QueryLogic.prototype,{
    union: makeNewSet("union"),
    difference: makeNewSet("difference"),
    intersection: makeNewSet("intersection"),

    isEqual: makeReturnValue("isEqual"),
    isProperSubset: makeReturnValue("isProperSubset"),
    isSubset: makeReturnValue("isSubset"),

    isSpecial: set_1$1.isSpecial,
    isDefinedAndHasMembers: set_1$1.isDefinedAndHasMembers,

    count: function(a){
        var queryA = this.hydrate(a);
        return queryA.page.end - queryA.page.start + 1;
    },

    // identity keys
    identityKeys: function(){
        //console.warn("you probably can get the identity keys some other way");
        return this.schema.identity;
    },

    filterMembers: function(a, b, bData){
        var queryA = this.hydrate(a);
        if(arguments.length >= 3) {
            var queryB = this.hydrate(b);
            return queryA.filterFrom(bData, queryB);
        } else {
            return queryA.filterFrom(b);
        }

    },
    // filterMembersAndGetCount
    filterMembersAndGetCount: function(a, b, bData) {
        var queryA = this.hydrate(a),
            queryB = this.hydrate(b);
        return queryA.filterMembersAndGetCount(bData, queryB);
    },
    // unionMembers
    unionMembers: function(a, b, aData, bData) {
        var queryA = this.hydrate(a),
            queryB = this.hydrate(b);

        var schema = this.schema;
        return queryA.merge(queryB, aData, bData, function(obj){
            return canReflect_1_19_2_canReflect.getIdentity(obj, schema);
        });
    },
    // isMember
    isMember: function(query, props) {
        return this.hydrate(query).isMember(props);
    },

    memberIdentity: function(props) {
        // console.warn("you probably can get the member identity some other way");
        return canReflect_1_19_2_canReflect.getIdentity(props, this.schema);
    },
    index: function(query, items, props){
        return this.hydrate(query).index(props, items);
    },

    insert: function(query, items, item){
    	var index = this.index(query, items, item);
    	if(index === undefined) {
    		index = items.length;
    	}

    	var copy = items.slice(0);
    	copy.splice(index, 0, item);

    	return copy;
    },

    isPaginated: function(query) {
        var basicQuery$$1 = this.hydrate(query);
        return !set_1$1.isEqual(basicQuery$$1.page, set_1$1.UNIVERSAL);
    },
    removePagination: function(query) {
        var basicQuery$$1 = this.hydrate(query);
        basicQuery$$1.removePagination();
        return this.serialize( basicQuery$$1 );
    },

});

// Copy everything on `set` to QueryLogic
for(var prop in set_1$1) {
    if(QueryLogic[prop] === undefined) {
        QueryLogic[prop] = set_1$1[prop];
    }
}



QueryLogic.makeEnum = function(values){
    var Type = function(){};
		Type[newSymbol$3] = function(val) { return val; };
    makeEnum_1(Type, values);
    return Type;
};



QueryLogic.KeysAnd = basicQuery.KeysAnd;
QueryLogic.ValuesOr = basicQuery.Or;



QueryLogic.In = comparisons_1$1.In;
QueryLogic.NotIn = comparisons_1$1.NotIn;
QueryLogic.GreaterThan = comparisons_1$1.GreaterThan;
QueryLogic.GreaterThanEqual = comparisons_1$1.GreaterThanEqual;
QueryLogic.LessThan = comparisons_1$1.LessThan;
QueryLogic.LessThanEqual = comparisons_1$1.LessThanEqual;
QueryLogic.ValueAnd = comparisons_1$1.And;
QueryLogic.ValueOr = comparisons_1$1.Or;

var canQueryLogic_1_2_4_canQueryLogic = QueryLogic;

function deepMatches(a, b) {
	if(a === b) {
		return true;
	} else if(Array.isArray(a) && Array.isArray(b)) {

		return a.every(function(aVal, i){
			return deepMatches(aVal, b[i]);
		});

	} else if(a && b && canReflect_1_19_2_canReflect.isPlainObject(a) && canReflect_1_19_2_canReflect.isPlainObject(b)) {

		for(var prop in a) {
			if(!b.hasOwnProperty(prop)) {
				return false;
			}
			if(!deepMatches(a[prop], b[prop])) {
				return false;
			}
		}
		return true;

	} else {
		return false
	}
}

function removeFixtureAndXHR(query) {
	if(query.fixture || query.xhr || query.data) {
		var clone = canReflect_1_19_2_canReflect.serialize(query);
		delete clone.fixture;
		delete clone.xhr;
		delete clone.data;
		return clone;
	} else {
		return query;
	}
}

function identityIntersection$1(v1, v2) {
    return v1.value === v2.value ? v1 : set_1$1.EMPTY;
}
function identityDifference$1(v1, v2){
    return v1.value === v2.value ? set_1$1.EMPTY : v1;
}
function identityUnion$1(v1, v2) {
    return v1.value === v2.value ? v1 : set_1$1.UNDEFINABLE;
}
var identityComparitor$1 = {
    intersection: identityIntersection$1,
    difference: identityDifference$1,
    union: identityUnion$1
};



function makeComparatorType(compare) {
	var Type = function(){};
	var SetType = function(value) {
		this.value = value;
	};
	SetType.prototype.isMember = function(value, root, keys){
	    return compare(this.value, value, root, keys);
	};
	canReflect_1_19_2_canReflect.assignSymbols(Type,{
		"can.SetType": SetType
	});

	set_1$1.defineComparison(SetType,SetType, identityComparitor$1);

	set_1$1.defineComparison(set_1$1.UNIVERSAL,SetType,{
		difference: function(){
			return set_1$1.UNDEFINABLE;
		}
	});
	return Type;
}

function quickEqual(queryA, queryB){
	var dataA = queryA.data,
		dataB = queryB.data;
	if(dataA && dataB) {
		if(!deepMatches(dataA, dataB)) {
			return false;
		}
	}
	var q1 = new canQueryLogic_1_2_4_canQueryLogic.KeysAnd(removeFixtureAndXHR(queryA)),
		q2 = new canQueryLogic_1_2_4_canQueryLogic.KeysAnd(removeFixtureAndXHR(queryB));
	return set_1$1.isEqual( q1, q2 );
}

function quickSubset(queryA, queryB){
	return set_1$1.isSubset( new canQueryLogic_1_2_4_canQueryLogic.KeysAnd(queryA), new canQueryLogic_1_2_4_canQueryLogic.KeysAnd(queryB) );
}

// Define types
var types$1 = {};
canReflect_1_19_2_canReflect.eachKey({
	IsEmptyOrNull: function(a, b){
		if( a == null && canReflect_1_19_2_canReflect.size(b) === 0 ) {
			return true;
		} else if( b == null && canReflect_1_19_2_canReflect.size(a) === 0 ) {
			return true;
		} else {
			return quickEqual(a, b);
		}
	},
	isEmptyOrSubset: function(a, b) {
		if( a == null && canReflect_1_19_2_canReflect.size(b) === 0 ) {
			return true;
		} else if( b == null && canReflect_1_19_2_canReflect.size(a) === 0 ) {
			return true;
		} else {
			return quickSubset(a, b);
		}
	},
	TemplateUrl: function(a, b) {
		return !!canFixture_3_1_7_dataFromUrl(a, b);
	},
	StringIgnoreCase: function(a, b){
		return b && a ? a.toLowerCase() === b.toLowerCase() : b === a;
	},
	Ignore: function(){
		return true;
	}
}, function(compare, name){
	types$1[name] = makeComparatorType(compare);
});





var schema$1 = {
	identity: ["id"],
	keys: {
		url: types$1.TemplateUrl,
		fixture: types$1.Ignore,
		xhr: types$1.Ignore,
		type: types$1.StringIgnoreCase,
		method: types$1.StringIgnoreCase,
		helpers: types$1.Ignore,
		headers: types$1.IsEmptyOrNull,
		data: types$1.IsEmptyOrSubset
	}
};

var query = new canQueryLogic_1_2_4_canQueryLogic(schema$1);




var canFixture_3_1_7_matches = {
	fixture: quickEqual,
	request: function(requestData, fixtureData) {
		return query.isMember({filter: fixtureData}, requestData);
	},
	matches: function(settings, fixture, exact) {
		if (exact) {
			return this.fixture(settings, fixture);
		} else {
			return this.request(settings, fixture)
		}
	},
	makeComparatorType: makeComparatorType
};

function getItems(data){
	if(Array.isArray(data)) {
		return data;
	} else {
		return data.data;
	}
}

function indexOf$1(records, identity, queryLogic ){
	var schema = canReflect_1_19_2_canReflect.getSchema( queryLogic );
	for(var i = 0 ; i < records.length; i++) {
		if(identity === canReflect_1_19_2_canReflect.getIdentity(records[i],  schema) ) {
			return i;
		}
	}
	return -1;
}

// update could remove all other records that would be in the set
function makeSimpleStore(baseConnection) {
    baseConnection.constructor = makeSimpleStore;
    var behavior = Object.create(baseConnection);

    // this stores data like:
    // queries: {[queryKey]: {queryKey, query, recordIds}}
    // records
    return canReflect_1_19_2_canReflect.assignMap(behavior, {
        getRecordFromParams: function(record) {
        	var id = canReflect_1_19_2_canReflect.getIdentity(record, this.queryLogic.schema);
        	return this.getRecord(id);
        },

        log: function(){
			this._log = true;
		},

        getSets: function(){
			return this.getQueries();
		},
		getQueries: function(){
			return Promise.resolve(this.getQueriesSync());
		},
		getQueriesSync: function(){
			return this.getQueryDataSync().map(function(queryData){
				return queryData.query;
			});
		},

        getListData: function(query){
        	query = query || {};
        	var listData = this.getListDataSync(query);
        	if(listData) {
        		return Promise.resolve(listData);
        	}
        	return Promise.reject({
        		title: "no data",
        		status: "404",
        		detail: "No data available for this query.\nAvailable queries: "+
        			JSON.stringify(this.getQueriesSync())
        	});
        },
		getPaginatedListDataSync: function(superSetQueryData) {
			var records = this.getAllRecords();
			var queryWithoutPagination = this.queryLogic.removePagination(superSetQueryData.query);
			var matchingSuperRecordsNoPagination = this.queryLogic.filterMembersAndGetCount(queryWithoutPagination, {}, records);
			var startIndex = indexOf$1(matchingSuperRecordsNoPagination.data, superSetQueryData.startIdentity, this.queryLogic);
			var matchingSuperRecords = matchingSuperRecordsNoPagination.data.slice(startIndex, startIndex+ this.queryLogic.count(superSetQueryData.query));
			return {
				count: matchingSuperRecordsNoPagination.data.length,
				data: matchingSuperRecords
			};
		},
        getListDataSync: function(query){
			var queryData = this.getQueryDataSync(),
				superSetQueryData,
				isPaginated = this.queryLogic.isPaginated(query);

			for(var i = 0; i < queryData.length; i++) {
        		var checkSet = queryData[i].query;
        		if( this.queryLogic.isSubset(query, checkSet) ) {
					superSetQueryData = queryData[i];
        		}
        	}
			var records = this.getAllRecords();

			if(isPaginated && this.queryLogic.isPaginated(superSetQueryData.query) ) {
				var result = this.getPaginatedListDataSync(superSetQueryData);
				return this.queryLogic.filterMembersAndGetCount(query, superSetQueryData.query, result.data);
			}

            var matching = this.queryLogic.filterMembersAndGetCount(query, {}, records);
            if(matching && matching.count) {
                return matching;
            }
            // now check if we have a query  for it
        	if(superSetQueryData) {
				return {count: 0, data: []};
			}
        },

        updateListData: function(data, query){
			var queryData = this.getQueryDataSync();
        	query = query || {};
            var clonedData = canReflect_1_19_2_canReflect.serialize(data);
        	var records = getItems(clonedData);
			// Update or create all records
			this.updateRecordsSync(records);
			var isPaginated = this.queryLogic.isPaginated(query);
			var identity = records.length ? canReflect_1_19_2_canReflect.getIdentity(records[0],  this.queryLogic.schema) : undefined;
			if(isPaginated) {
				// we are going to merge with some paginated set
				for(var i = 0; i < queryData.length; i++) {
	        		var checkSet = queryData[i].query;
					var union = this.queryLogic.union(checkSet, query);
					if( this.queryLogic.isDefinedAndHasMembers(union)  ) {
						var siblingRecords = this.getPaginatedListDataSync(queryData[i]);
						var res = this.queryLogic.unionMembers(checkSet, query, siblingRecords.data, records );
						identity = canReflect_1_19_2_canReflect.getIdentity(res[0],  this.queryLogic.schema);
						queryData[i] = {
							query: union,
							startIdentity: identity
						};
						this.updateQueryDataSync(queryData);
						return Promise.resolve();
					}
	        	}

				queryData.push({
					query: query,
					startIdentity: identity
				});
				this.updateQueryDataSync(queryData);
				return Promise.resolve();
			}

            // we need to remove everything that would have matched this query before, but that's not in data
            // but what if it's in another set -> we remove it
            var allRecords = this.getAllRecords();
            var curretMatching = this.queryLogic.filterMembers(query, allRecords);
            if(curretMatching.length) {
                var toBeDeleted = new Map();
                curretMatching.forEach(function(record){
                    toBeDeleted.set( canReflect_1_19_2_canReflect.getIdentity(record, this.queryLogic.schema), record );
                }, this);

                // remove what's in records
                records.forEach(function(record){
                    toBeDeleted.delete( canReflect_1_19_2_canReflect.getIdentity(record, this.queryLogic.schema) );
                }, this);

                this.destroyRecords( canReflect_1_19_2_canReflect.toArray(toBeDeleted) );
            }

            // the queries that are not consumed by query
            var allQueries = this.getQueryDataSync();
            var notSubsets = allQueries.filter(function(existingQueryData){
                    return !this.queryLogic.isSubset(existingQueryData.query, query);
                }, this),
                superSets = notSubsets.filter(function(existingQueryData){
                    return this.queryLogic.isSubset(query, existingQueryData.query);
                }, this);

			// would need to note the first record ... so we can do a query w/o pagination
			//

            // if there are sets that are parents of query
            if(superSets.length) {
                this.updateQueryDataSync(notSubsets);
            } else {
                this.updateQueryDataSync(notSubsets.concat([{
					query: query,
					startIdentity:identity
				}]));
            }

        	// setData.push({query: query, items: data});
        	return Promise.resolve();
        },

        getData: function(params){
        	var id = canReflect_1_19_2_canReflect.getIdentity(params, canReflect_1_19_2_canReflect.getSchema( this.queryLogic ) );
        	var res = this.getRecord(id);
        	if(res){
        		return Promise.resolve( res );
        	} else {
        		return Promise.reject({
        			title: "no data",
        			status: "404",
        			detail: "No record with matching identity ("+id+")."
        		});
        	}
        },
        createData: function(record){
			this.updateRecordsSync([record]);

			return Promise.resolve(canReflect_1_19_2_canReflect.assignMap({}, this.getRecordFromParams(record) ));
		},

		updateData: function(record){

			if(this.errorOnMissingRecord && !this.getRecordFromParams(record)) {
				var id = canReflect_1_19_2_canReflect.getIdentity(record, this.queryLogic.schema);
				return Promise.reject({
					title: "no data",
					status: "404",
					detail: "No record with matching identity ("+id+")."
				});
			}

			this.updateRecordsSync([record]);

			return Promise.resolve(canReflect_1_19_2_canReflect.assignMap({},this.getRecordFromParams(record) ));
		},

		destroyData: function(record){
			var id = canReflect_1_19_2_canReflect.getIdentity(record,  this.queryLogic.schema),
				savedRecord = this.getRecordFromParams(record);

			if(this.errorOnMissingRecord && !savedRecord) {

				return Promise.reject({
					title: "no data",
					status: "404",
					detail: "No record with matching identity ("+id+")."
				});
			}
            this.destroyRecords([record]);
			return Promise.resolve(canReflect_1_19_2_canReflect.assignMap({},savedRecord || record));
		}
    });
}

var canMemoryStore_1_0_3_makeSimpleStore = makeSimpleStore;

var canMemoryStore_1_0_3_canMemoryStore = canNamespace_1_0_0_canNamespace.memoryStore = function memoryStore(baseConnection){
    baseConnection.constructor = memoryStore;
    var behavior = Object.create(canMemoryStore_1_0_3_makeSimpleStore(baseConnection));

    canReflect_1_19_2_canReflect.assignMap(behavior, {
		clear: function(){
			this._instances = {};
			this._queryData = [];
		},
		_queryData: [],
		updateQueryDataSync: function(queries){
			this._queryData = queries;
		},
		getQueryDataSync: function(){
			return this._queryData;
		},

		_instances: {},
		getRecord: function(id){
			return this._instances[id];
		},
		getAllRecords: function(){
			var records = [];
			for(var id in this._instances) {
				records.push(this._instances[id]);
			}
			return records;
		},
		destroyRecords: function(records) {
			canReflect_1_19_2_canReflect.eachIndex(records, function(record){
				var id = canReflect_1_19_2_canReflect.getIdentity(record, this.queryLogic.schema);
				delete this._instances[id];
			}, this);
		},
		updateRecordsSync: function(records){
			records.forEach(function(record){
				var id = canReflect_1_19_2_canReflect.getIdentity(record, this.queryLogic.schema);
				this._instances[id] = record;
			},this);
		},

		// ## External interface

		/**
		 * @function can-memory-store.getQueries getQueries
		 * @parent can-memory-store.data-methods
		 *
		 * Returns the queries contained within the cache.
		 *
		 * @signature `connection.getQueries()`
		 *
		 *   Returns the queries added by [can-memory-store.updateListData].
		 *
		 *   @return {Promise<Array<can-query-logic/query>>} A promise that resolves to the list of queries.
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * ```js
		 * connection.getSets() //-> Promise( [{type: "completed"},{user: 5}] )
		 * ```
		 *
		 */

		/**
		 * @function can-memory-store.clear clear
		 * @parent can-memory-store.data-methods
		 *
		 * Resets the memory store so it contains nothing.
		 *
		 * @signature `connection.clear()`
		 *
		 *   Removes all instances and lists being stored in memory.
		 *
		 *   ```js
		 *   memoryStore({queryLogic: new QueryLogic()});
		 *
		 *   cacheConnection.updateInstance({id: 5, name: "justin"});
		 *
		 *   cacheConnection.getData({id: 5}).then(function(data){
		 *     data //-> {id: 5, name: "justin"}
		 *     cacheConnection.clear();
		 *     cacheConnection.getData({id: 5}).catch(function(err){
		 *       err -> {message: "no data", error: 404}
		 *     });
		 *   });
		 *   ```
		 *
		 */

		/**
		 * @function can-memory-store.getListData getListData
		 * @parent can-memory-store.data-methods
		 *
		 * Gets a list of data from the memory store.
		 *
		 * @signature `connection.getListData(query)`
		 *
		 *   Goes through each query add by [can-memory-store.updateListData]. If
		 *   `query` is a subset, uses [can-connect/base/base.queryLogic] to get the data for the requested `query`.
		 *
		 *   @param {can-query-logic/query} query An object that represents the data to load.
		 *
		 *   @return {Promise<can-connect.listData>} A promise that resolves if `query` is a subset of
		 *   some data added by [can-memory-store.updateListData].  If it is not,
		 *   the promise is rejected.
		 */

		/**
		 * @function can-connect/data/memory-cache.getListDataSync getListDataSync
		 * @parent can-connect/data/memory-cache.data-methods
		 *
		 * Synchronously gets a query of data from the memory cache.
		 *
		 * @signature `connection.getListDataSync(query)`
		 * @hide
		 */


		/**
		 * @function can-memory-store.updateListData updateListData
		 * @parent can-memory-store.data-methods
		 *
		 * Saves a query of data in the cache.
		 *
		 * @signature `connection.updateListData(listData, query)`
		 *
		 *   Tries to merge this query of data with any other saved queries of data. If
		 *   unable to merge this data, saves the query by itself.
		 *
		 *   @param {can-connect.listData} listData The data that belongs to `query`.
		 *   @param {can-query-logic/query} query The query `listData` belongs to.
		 *   @return {Promise} Promise resolves if and when the data has been successfully saved.
		 */


		/**
		 * @function can-memory-store.getData getData
		 * @parent can-memory-store.data-methods
		 *
		 * Get an instance's data from the memory cache.
		 *
		 * @signature `connection.getData(params)`
		 *
		 *   Looks in the instance store for the requested instance.
		 *
		 *   @param {Object} params An object that should have the [conenction.id] of the element
		 *   being retrieved.
		 *
		 *   @return {Promise} A promise that resolves to the item if the memory cache has this item.
		 *   If the memory cache does not have this item, it rejects the promise.
		 */




		/**
		 * @function can-memory-store.createData createData
		 * @parent can-memory-store.data-methods
		 *
		 * Called when an instance is created and should be added to cache.
		 *
		 * @signature `connection.createData(record)`
		 *
		 *   Adds `record` to the stored list of instances. Then, goes
		 *   through every query and adds record the queries it belongs to.
		 */


		/**
		 * @function can-memory-store.updateData updateData
		 * @parent can-memory-store.data-methods
		 *
		 * Called when an instance is updated.
		 *
		 * @signature `connection.updateData(record)`
		 *
		 *   Overwrites the stored instance with the new record. Then, goes
		 *   through every query and adds or removes the instance if it belongs or not.
		 */

		/**
		 * @function can-memory-store.destroyData destroyData
		 * @parent can-memory-store.data-methods
		 *
		 * Called when an instance should be removed from the cache.
		 *
		 * @signature `connection.destroyData(record)`
		 *
		 *   Goes through each query of data and removes any data that matches
		 *   `record`'s [can-connect/base/base.id]. Finally removes this from the instance store.
		 */

	});

	return behavior;

};

// Returns a function that calls the method on a connection.
// Wires up fixture signature to a connection signature.
var connectToConnection = function(method, convert){
	return function(req, res){
		// have to get data from
		this.connection[method]( convert.call(this, req.data) ).then(function(data){
			res(data);
		}, function(err){
			res(parseInt(err.status, 10), err);
		});
	};
};
// Returns a new makeItems function for a different baseItems;
var makeMakeItems = function(baseItems, idProp){
	return function () {
		// clone baseItems
		var items = [],
			maxId = 0,
			idType = "number";
		baseItems.forEach(function(item){
			items.push(canReflect_1_19_2_canReflect.serialize(item) );
			var type = typeof item[idProp];
			if(type === "number") {
				maxId = Math.max(item[idProp], maxId) ;
			} else {
				idType = type;
			}
		});

		return {
			maxId: maxId,
			items: items,
			idType: idType
		};
	};
};

var stringToAny = function(str){
	switch(str) {
		case "NaN":
		case "Infinity":
			return +str;
		case "null":
			return null;
		case "undefined":
			return undefined;
		case "true":
		case "false":
			return str === "true";
		default:
			var val = +str;
			if(!isNaN(val)) {
				return val;
			} else {
				return str;
			}
	}
};

// A store constructor function
var Store = function(connection, makeItems, idProp){
	var schema = connection.queryLogic.schema;
	var identityKey = schema.identity[0],
		keys = schema.keys;

	if(!keys || !keys[identityKey]) {
		console.warn("No type specified for identity key. Going to convert strings to reasonable type.");
	}

	this.connection = connection;
	this.makeItems = makeItems;
	this.idProp = idProp;
	this.reset();
	// we have to make sure the methods can be called without their context
	for(var method in Store.prototype) {
		this[method] = this[method].bind(this);
	}
};

var doNotConvert = function(v){ return v; };

function typeConvert(data){
	var schema = this.connection.queryLogic.schema;
	var idType = this.idType;
	var identityKey = schema.identity[0],
		keys = schema.keys;
	if(!keys || !keys[identityKey]) {
		keys = {};
		keys[identityKey] = function(value) {
			if(idType === "string") {
				return ""+value;
			} else {
				return typeof value === "string" ? stringToAny(value) : value;
			}

		};
	}
		// this probably needs to be recursive, but this is ok for now
	var copy = {};
	canReflect_1_19_2_canReflect.eachKey(data, function(value, key){
		if(keys[key]) {
			copy[key] = canReflect_1_19_2_canReflect.serialize(canReflect_1_19_2_canReflect.convert(value, keys[key]));
		} else {
			copy[key] = value;
		}
	});
	// clone the data

	return copy;

}

canReflect_1_19_2_canReflect.assignMap(Store.prototype,{
	getListData: connectToConnection("getListData",doNotConvert),
	getData: connectToConnection( "getData",typeConvert),

	// used
	createData: function(req, res){
		var idProp = this.idProp;
		// add an id
		req.data[idProp] = ++this.maxId;

		this.connection.createData( typeConvert.call(this,req.data) ).then(function(data){
			res(data);
		}, function(err){
			res(403, err);
		});
	},
	createInstance: function(record){
		var idProp = this.idProp;
		if(!(idProp in record)) {
			record[idProp] = ++this.maxId;
		}
		return this.connection.createData( record );
	},
	updateData: connectToConnection("updateData",typeConvert),
	updateInstance: function(record) {
		return this.connection.updateData(record);
	},
	destroyInstance: function(record) {
		return this.connection.destroyData(record);
	},
	destroyData: connectToConnection("destroyData",typeConvert),
	reset: function(newItems){
		if(newItems) {
			this.makeItems = makeMakeItems(newItems, this.idProp);
		}
		var itemData =  this.makeItems();
		this.maxId = itemData.maxId;
		this.idType = itemData.idType;
		this.connection.updateListData(itemData.items, {});
	},
	get: function (params) {
		var id = this.connection.queryLogic.memberIdentity(params);
		return this.connection.getRecord(id);
	},
	getList: function(set){
		return this.connection.getListDataSync(set);
	}
});

function looksLikeAQueryLogic(obj){
	return obj && ("identityKeys" in obj);
}

// ## fixture.store
// Make a store of objects to use when making requests against fixtures.
Store.make = function (count, make, queryLogic) {
	/*jshint eqeqeq:false */


	// Figure out makeItems which populates data
	var makeItems,
		idProp;
	if(typeof count === "number") {
		if(!queryLogic) {
			queryLogic = new canQueryLogic_1_2_4_canQueryLogic({});
		} else if(!looksLikeAQueryLogic(queryLogic)) {
			queryLogic = new canQueryLogic_1_2_4_canQueryLogic(queryLogic);
		}
		idProp = queryLogic.identityKeys()[0] || "id";
		makeItems = function () {
			var items = [];
			var maxId = 0;
			for (var i = 0; i < (count); i++) {
				//call back provided make
				var item = make(i, items);

				if (!item[idProp]) {
					item[idProp] = i;
				}
				maxId = Math.max(item[idProp] , maxId);
				items.push(item);
			}

			return {
				maxId: maxId,
				items: items
			};
		};
	} else if(Array.isArray(count)){
		queryLogic = make;
		if(!queryLogic) {
			queryLogic = new canQueryLogic_1_2_4_canQueryLogic({});
		} else if(!looksLikeAQueryLogic(queryLogic)) {
			queryLogic = new canQueryLogic_1_2_4_canQueryLogic(queryLogic);
		}
		idProp = queryLogic.identityKeys()[0] || "id";
		makeItems = makeMakeItems(count, idProp);
	}

	var connection = canMemoryStore_1_0_3_canMemoryStore({
		queryLogic: queryLogic,
		errorOnMissingRecord: true
	});

	return new Store(connection, makeItems, idProp);
};

var canFixture_3_1_7_store = Store;

var canFixture_3_1_7_core = createCommonjsModule(function (module, exports) {
// Adds









var fixtures = [];
exports.fixtures = fixtures;

function isStoreLike (fixture) {
	return fixture && (fixture.getData || fixture.getListData);
}

var methodMapping = {
	item: {
		'GET': 'getData',
		'PUT': 'updateData',
		'DELETE': 'destroyData',
	},
	list: {
		'GET': 'getListData',
		'POST': 'createData'
	}
};

function getMethodAndPath (route) {
	// Match URL if it has GET, POST, PUT, DELETE or PATCH.
	var matches = route.match(/(GET|POST|PUT|DELETE|PATCH) (.+)/i);
	if (!matches) {
		return [undefined, route];
	}
	var method = matches[1];
	var path = matches[2];
	return [method, path];
}

function inferIdProp (url) {
	var wrappedInBraces = /\{(.*)\}/;
	var matches = url.match(wrappedInBraces);
	var isUniqueMatch = matches && matches.length === 2;
	if (isUniqueMatch) {
		return matches[1];
	}
}

function getItemAndListUrls (url, idProp) {
	idProp = idProp || inferIdProp(url);
	if (!idProp) {
		return [undefined, url];
	}
	var itemRegex = new RegExp('\\/\\{' + idProp+"\\}.*" );
	var rootIsItemUrl = itemRegex.test(url);
	var listUrl = rootIsItemUrl ? url.replace(itemRegex, "") : url;
	var itemUrl = rootIsItemUrl ? url : (url.trim() + "/{" + idProp + "}");
	return [itemUrl, listUrl];
}

function addStoreFixture (root, store) {
	var settings = {};
	var typeAndUrl = getMethodAndPath(root);
	var type = typeAndUrl[0];
	var url = typeAndUrl[1];

	var itemAndListUrls = getItemAndListUrls(url, store.idProp);
	var itemUrl = itemAndListUrls[0];
	var listUrl = itemAndListUrls[1];

	if (type) {
		var warning = [
			'fixture("' + root + '", fixture) must use a store method, not a store directly.',
		];
		if (itemUrl) {
			var itemAction = methodMapping.item[type];
			if (itemAction) {
				settings[type + ' ' + itemUrl] = store[itemAction];
				var itemWarning = 'Replace with fixture("' + type + ' ' + itemUrl + '", fixture.' + itemAction + ') for items.';
				warning.push(itemWarning);
			}
		}
		var listAction = methodMapping.list[type];
		if (listAction) {
			settings[type + ' ' + listUrl] = store[listAction];
			var listWarning = 'Replace with fixture("' + type + ' ' + listUrl + '", fixture.' + listAction + ') for lists.';
			warning.push(listWarning);
		}
		var message = warning.join(' ');
		dev.warn(message);
	} else {
		var itemMapping = methodMapping.item;
		for (var itemMethod in itemMapping) {
			var storeItemMethod = itemMapping[itemMethod];
			settings[itemMethod + ' ' + itemUrl] = store[storeItemMethod];
		}
		var listMapping = methodMapping.list;
		for (var listMethod in listMapping) {
			var storeListMethod = listMapping[listMethod];
			settings[listMethod + ' ' + listUrl] = store[storeListMethod];
		}
	}

	return settings;
}

function getSettingsFromString (route) {
	var typeAndUrl = getMethodAndPath(route);
	var type = typeAndUrl[0];
	var url = typeAndUrl[1];
	if (type) {
		return {
			type: type,
			url: url
		};
	}
	return {
		url: url
	};
}

// Check if the same fixture was previously added, if so, we remove it
// from our array of fixture overwrites.
function upsertFixture (fixtureList, settings, fixture) {
	var index = exports.index(settings, true);
	var oldFixture;
	if (index > -1) {
		oldFixture = fixtures.splice(index, 1);
	}
	if (fixture == null) {
		return oldFixture;
	}
	if(typeof fixture === "object") {
		var data = fixture;
		fixture = function(){
			return data;
		};
	}
	settings.fixture = fixture;
	fixtures.unshift(settings);
	return oldFixture;
}

// Adds a fixture to the list of fixtures.
exports.add = function (settings, fixture) {
	// If a fixture isn't provided, we assume that settings is
	// an array of fixtures, and we should iterate over it, and set up
	// the new fixtures.
	if (fixture === undefined) {
		var oldFixtures = [];
		if(Array.isArray(settings)) {
			canReflect_1_19_2_canReflect.eachIndex(settings, function(ajaxSettings){
				var fixture = ajaxSettings.fixture;
				ajaxSettings = canReflect_1_19_2_canReflect.assignMap({}, ajaxSettings);
				delete ajaxSettings.fixture;
				return exports.add(ajaxSettings, fixture);
			});
		} else {
			canReflect_1_19_2_canReflect.eachKey(settings, function (fixture, url) {
				oldFixtures = oldFixtures.concat(exports.add(url, fixture));
			});
			return oldFixtures;
		}
	}

	// When a fixture is passed a store like:
	// `fixture("/things/{id}", store)`
	if (isStoreLike(fixture)) {
		settings = addStoreFixture(settings, fixture);
		return exports.add(settings);
	}

	if (typeof settings === 'string') {
		settings = getSettingsFromString(settings);
	}
	return upsertFixture(fixtures, settings, fixture);
};

var $fixture = exports.add;
$fixture.on = true;
$fixture.delay =10;

function FixtureResponse(fixture, response){
	this.statusCode= response[0];
	this.responseBody= response[1];
	this.headers= response[2];
	this.statusText= response[3];
	this.fixture= fixture;
}

// Calls a dynamic fixture and calls `cb` with the response data.
exports.callDynamicFixture = function(xhrSettings, fixtureSettings, cb){
	// this is for legacy.  In the future, people should get it from fixtureSettings probably.
	xhrSettings.data = fixtureSettings.data;

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		var json = JSON.stringify(xhrSettings.data);
		canLog_1_0_2_canLog.log("" + xhrSettings.type.toUpperCase() + " " + xhrSettings.url+" "+json.substr(0,50)+" -> handler(req,res)");
	}
	//!steal-remove-end

	var response = function(){
		var res = exports.extractResponse.apply(xhrSettings, arguments);
		//!steal-remove-start
		canLog_1_0_2_canLog.log("can-fixture: " + xhrSettings.type.toUpperCase() + " " + xhrSettings.url+" ",xhrSettings.data," => ",new FixtureResponse(fixtureSettings.fixture,res));
		//!steal-remove-end
		return cb.apply(this, res);
	};
	var callFixture = function () {
		// fall the fixture
		var result = fixtureSettings.fixture(xhrSettings, response, xhrSettings.headers, fixtureSettings);

		if (canReflect_1_19_2_canReflect.isPromise(result)) {
			// If we have a promise, wait for it to resolve
			result.then(function (result) {
				if (result !== undefined) {
					// Resolve with fixture results
					response(200, result );
				}
			});
		} else {
			if (result !== undefined) {
				// Resolve with fixture results
				response(200, result );
			}
		}
	};

	if(!xhrSettings.async) {
		callFixture();
		return null;
	} else {
		return setTimeout(callFixture, $fixture.delay);
	}
};

exports.index = function (settings, exact) {
	for (var i = 0; i < fixtures.length; i++) {
		if (canFixture_3_1_7_matches.matches(settings, fixtures[i], exact)) {
			return i;
		}
	}
	return -1;
};
exports.get = function(xhrSettings) {
	if ( !$fixture.on ) {
		return;
	}
	// First try an exact match
	var index = exports.index(xhrSettings, true);

	// If that doesn't work, try a looser match.
	if(index === -1) {
		index = exports.index(xhrSettings, false);
	}

	var fixtureSettings = index >=0 ? canReflect_1_19_2_canReflect.assignMap({},fixtures[index]) : undefined;
	if(fixtureSettings) {
		var url = fixtureSettings.fixture,
			data = canFixture_3_1_7_dataFromUrl(fixtureSettings.url, xhrSettings.url);
		if(typeof fixtureSettings.fixture === "string") {
			// check that we might have a replacement

			// here we could read data from first url and translate into next
			if (data) {
				// Template static fixture URLs
				url = sub(url, data);
			}

			// Override the AJAX settings, changing the URL to the fixture file,
			// removing the data, and changing the type to GET.
			fixtureSettings.url = url;
			fixtureSettings.data = null;
			fixtureSettings.type = "GET";
			if (!fixtureSettings.error) {
				// If no error handling is provided, we provide one and throw an
				// error.
				fixtureSettings.error = function (xhr, error$$1, message) {
					throw "fixtures.js Error " + error$$1 + " " + message;
				};
			}

		} else if (canReflect_1_19_2_canReflect.isPlainObject(xhrSettings.data) || xhrSettings.data == null) {
			var xhrData = canReflect_1_19_2_canReflect.assignMap({}, xhrSettings.data || {});
			fixtureSettings.data = canReflect_1_19_2_canReflect.assignMap(xhrData, data);

		} else {
			fixtureSettings.data = xhrSettings.data;
		}
	}

	return fixtureSettings;
};

exports.matches = canFixture_3_1_7_matches;




// A helper function that takes what's called with response
// and moves some common args around to make it easier to call
exports.extractResponse = function (status, response, headers, statusText) {
	// if we get response(RESPONSE, HEADERS)
	if (typeof status !== "number") {
		headers = response;
		response = status;
		status = 200;
	}
	// if we get response(200, RESPONSE, STATUS_TEXT)
	if (typeof headers === "string") {
		statusText = headers;
		headers = {};
	}
	return [status, response, headers, statusText];
};
});
var canFixture_3_1_7_core_1 = canFixture_3_1_7_core.fixtures;
var canFixture_3_1_7_core_2 = canFixture_3_1_7_core.add;
var canFixture_3_1_7_core_3 = canFixture_3_1_7_core.callDynamicFixture;
var canFixture_3_1_7_core_4 = canFixture_3_1_7_core.index;
var canFixture_3_1_7_core_5 = canFixture_3_1_7_core.get;
var canFixture_3_1_7_core_6 = canFixture_3_1_7_core.matches;
var canFixture_3_1_7_core_7 = canFixture_3_1_7_core.extractResponse;

/* global require, window, global */
/* global setTimeout, clearTimeout, XMLHttpRequest */

// This overwrites the default XHR with a mock XHR object.
// The mock XHR object's `.send` method is able to
// call the fixture callbacks or create a real XHR request
// and then respond normally.





// Save the real XHR object as XHR
var XHR = XMLHttpRequest,
// Get a global reference.
	GLOBAL = typeof commonjsGlobal !== "undefined"? commonjsGlobal : window;

// Figure out props and events on XHR object
// but start with some defaults
var props$2 = [
	"type", "url", "async", "response", "responseText", "responseType",
	"responseXML", "responseURL", "status", "statusText", "readyState"
];
var events = ["abort", "error", "load", "loadend", "loadstart",  "progress", "readystatechange"];
(function(){
	var x = new XHR();
	for(var prop in x) {
		if(prop.indexOf("on") === 0) {
			if (events.indexOf(prop.substr(2)) === -1) {
				events.push(prop.substr(2));
			}
		} else if (props$2.indexOf(prop) === -1 && typeof x[prop] !== 'function') {
			props$2.push(prop);
		}
	}
})();
// DEFINE HELPERS

// Call all of an event for an XHR object
function callEvents(xhr, ev) {
	var evs = xhr.__events[ev] || [], fn;
	for(var i = 0, len = evs.length; i < len; i++) {
		fn = evs[i];
		fn.call(xhr);
	}
}

function defineNonEnumerable$2(obj, prop, value) {
	Object.defineProperty(obj, prop, {
		enumerable: false,
		configurable: true,
		writable: true,
		value: value
	});
}

GLOBAL.XMLHttpRequest = function() {
	var mockXHR = this;
	var realXHR = new XHR();

	// store real xhr on mockXHR
	defineNonEnumerable$2(this, "_xhr", realXHR);

	// create other properties needed by prototype functions
	defineNonEnumerable$2(this, "_requestHeaders", {});
	defineNonEnumerable$2(this, "__events", {});

	// wire up events to forward from real xhr to fake xhr
	events.forEach(function(eventName) {
		realXHR["on" + eventName] = function() {
			callEvents(mockXHR, eventName);
			if(mockXHR["on"+eventName]) {
				return mockXHR["on"+eventName].apply(mockXHR, arguments);
			}
		};
	});

	// The way code detects if the browser supports onload is to check
	// if a new XHR object has the onload property, so setting it to null
	// passes that check.
	this.onload = null;
};
GLOBAL.XMLHttpRequest._XHR = XHR;

// Methods on the mock XHR:
canReflect_1_19_2_canReflect.assignMap(XMLHttpRequest.prototype,{
	setRequestHeader: function(name, value){
		this._requestHeaders[name] = value;
	},
	open: function(type, url, async){
		this.type = type;
		this.url = url;
		this.async = async === false ? false : true;
	},
	getAllResponseHeaders: function(){
		return this._xhr.getAllResponseHeaders.apply(this._xhr, arguments);
	},
	addEventListener: function(ev, fn){
		var evs = this.__events[ev] = this.__events[ev] || [];
		evs.push(fn);
	},
	removeEventListener: function(ev, fn){
		var evs = this.__events[ev] = this.__events[ev] || [];
		var idx = evs.indexOf(fn);
		if(idx >= 0) {
			evs.splice(idx, 1);
		}
	},
	setDisableHeaderCheck: function(val){
		this._disableHeaderCheck = !!val;
	},
	getResponseHeader: function(key){
		return this._xhr.getResponseHeader(key);
	},
	abort: function() {
		var xhr = this._xhr;

		// If we are aborting a delayed fixture we have to make the fake
		// steps that are expected for `abort` to
		if(this.timeoutId !== undefined) {
			clearTimeout(this.timeoutId);
			xhr.open(this.type, this.url, this.async === false ? false : true);
			xhr.send();
		}

		return xhr.abort();
	},
	// This needs to compile the information necessary to see if
	// there is a corresponding fixture.
	// If there isn't a fixture, this should create a real XHR object
	// linked to the mock XHR instance and make a data request.
	// If there is a fixture, depending on the type of fixture the following happens:
	// - dynamic fixtures - call the dynamic fixture, use the result to update the
	//   mock XHR object and trigger its callbacks.
	// - redirect fixtures - create a real XHR linked to the mock XHR for the new url.
	send: function(data) {
		// derive the XHR settings object from the XHR object
		var type = this.type.toLowerCase() || 'get';
		var xhrSettings = {
			url: this.url,
			data: data,
			headers: this._requestHeaders,
			type: type,
			method: type,
			async: this.async,
			xhr: this
		};
		// if get or delete, the url should not include the querystring.
		// the querystring should be the data.
		if(!xhrSettings.data && xhrSettings.type === "get" || xhrSettings.type === "delete") {
			xhrSettings.data = canDeparam_1_2_3_canDeparam( xhrSettings.url.split("?")[1] );
			xhrSettings.url = xhrSettings.url.split("?")[0];
		}

		// Try to convert the request body to POJOs.
		if(typeof xhrSettings.data === "string") {
			try {
				xhrSettings.data = JSON.parse(xhrSettings.data);
			} catch(e) {
				xhrSettings.data = canDeparam_1_2_3_canDeparam( xhrSettings.data );
			}
		}

		// See if the XHR settings match a fixture.
		var fixtureSettings = canFixture_3_1_7_core.get(xhrSettings);
		var mockXHR = this;

		// If a dynamic fixture is being used, we call the dynamic fixture function and then
		// copy the response back onto the `mockXHR` in the right places.
		if(fixtureSettings && typeof fixtureSettings.fixture === "function") {

			this.timeoutId = canFixture_3_1_7_core.callDynamicFixture(xhrSettings, fixtureSettings, function(status, body, headers, statusText){
				body = typeof body === "string" ? body :  JSON.stringify(body);

				// we are no longer using the real XHR
				// set it to an object so that props like readyState can be set
				mockXHR._xhr = {
					open: function(){},
					send: function() {},
					abort: function(){},
					getResponseHeader: function(){}
				};

				canReflect_1_19_2_canReflect.assignMap(mockXHR, {
					readyState: 4,
					status: status
				});

				var success = (status >= 200 && status < 300 || status === 304);
				if ( success ) {
					canReflect_1_19_2_canReflect.assignMap(mockXHR,{
						statusText: statusText || "OK",
						responseText: body
					});
				} else {
					canReflect_1_19_2_canReflect.assignMap(mockXHR,{
						statusText: statusText || "error",
						responseText: body
					});
				}

				mockXHR.getAllResponseHeaders = function() {
					var ret = [];
					canReflect_1_19_2_canReflect.eachKey(headers || {}, function(value, name) {
						Array.prototype.push.apply(ret, [name, ': ', value, '\r\n']);
					});
					return ret.join('');
				};

				if(mockXHR.onreadystatechange) {
					mockXHR.onreadystatechange({ target: mockXHR });
				}

				// fire progress events
				callEvents(mockXHR, "progress");
				if(mockXHR.onprogress) {
					mockXHR.onprogress();
				}

				callEvents(mockXHR, "load");
				if(mockXHR.onload) {
					mockXHR.onload();
				}

				callEvents(mockXHR, "loadend");
				if(mockXHR.onloadend) {
					mockXHR.onloadend();
				}
			});

			return;
		}
		// At this point there is either not a fixture or a redirect fixture.
		// Either way we are doing a request.
		var makeRequest = function() {
			mockXHR._xhr.open(mockXHR._xhr.type, mockXHR._xhr.url, mockXHR._xhr.async);
			if(mockXHR._requestHeaders) {
				Object.keys(mockXHR._requestHeaders).forEach(function(key) {
					mockXHR._xhr.setRequestHeader(key, mockXHR._requestHeaders[key]);
				});
			}
			return mockXHR._xhr.send(data);
		};

		if(fixtureSettings && typeof fixtureSettings.fixture === "number") {
			canLog_1_0_2_canLog.log("can-fixture: "+xhrSettings.url+" => delay " + fixtureSettings.fixture+"ms");
			this.timeoutId = setTimeout(makeRequest, fixtureSettings.fixture);
			return;
		}

		// if we do have a fixture, update the real XHR object.
		if(fixtureSettings) {
			canLog_1_0_2_canLog.log("can-fixture: "+xhrSettings.url+" => " + fixtureSettings.url);
			canReflect_1_19_2_canReflect.assignMap(mockXHR, fixtureSettings);
		}

		// Make the request.
		return makeRequest();
	}
});

// when props of mockXHR are get/set, return the prop from the real XHR
props$2.forEach(function(prop) {
	Object.defineProperty(XMLHttpRequest.prototype, prop, {
		get: function(){
			return this._xhr[prop];
		},
		set: function(newVal){
			try {
				this._xhr[prop] = newVal;
			} catch(e) {}
		}
	});
});

var fixture = canFixture_3_1_7_core.add;





// HELPERS START

var noop$2 = function(){};

canReflect_1_19_2_canReflect.assignMap(fixture, {
	rand: function randomize (arr, min, max) {
		if (typeof arr === 'number') {
			if (typeof min === 'number') {
				return arr + Math.floor(Math.random() * (min - arr+1));
			} else {
				return Math.floor(Math.random() * (arr+1));
			}

		}
		// clone the array because we will remove items from it.
		var choices = arr.slice(0);

		// get a random set
		if (min === undefined) {
			min = 1;
			max = choices.length;
		} else if(max === undefined){
			max = min;
		}
		// get a random selection of arr
		var result = [];

		// set max
		//random max
		var selectedCount = min + Math.round(randomize(max - min));
		for (var i = 0; i < selectedCount; i++) {
			var selectedIndex = randomize(choices.length - 1),
				selected = choices.splice(selectedIndex, 1)[0];
			result.push(selected);
		}
		return result;
	},
	xhr: function (xhr) {
		return canReflect_1_19_2_canReflect.assignMap({}, {
			abort: noop$2,
			getAllResponseHeaders: function () {
				return "";
			},
			getResponseHeader: function () {
				return "";
			},
			open: noop$2,
			overrideMimeType: noop$2,
			readyState: 4,
			responseText: "",
			responseXML: null,
			send: noop$2,
			setRequestHeader: noop$2,
			status: 200,
			statusText: "OK"
		}, xhr);
	},
	store: canFixture_3_1_7_store.make,
	fixtures: canFixture_3_1_7_core.fixtures
});

if(typeof window !== "undefined" && typeof commonjsRequire.resolve !== "function") {

	window.fixture = function(){
		dev.warn("You are using the global fixture. Make sure you import can-fixture.");

		return fixture.apply(this, arguments);
	};	
}


var canFixture_3_1_7_fixture = canNamespace_1_0_0_canNamespace.fixture = fixture;

var behaviorsMap = {};

function behavior(name, behavior){
	if(typeof name !== "string") {
		behavior = name;
		name = undefined;
	}
	var behaviorMixin = function(base){
		// basically Object.create
		var Behavior = function(){};
		Object.defineProperty(Behavior,"name",{
			value: name,
			configurable: true
		});
		Behavior.prototype = base;
		var newBehavior = new Behavior();
		// allows behaviors to be a simple object, not always a function
		var res = typeof behavior === "function" ? behavior.apply(newBehavior, arguments) : behavior;
		for(var prop in res) {
			if(res.hasOwnProperty(prop)) {
				Object.defineProperty(newBehavior, prop, Object.getOwnPropertyDescriptor(res, prop));
			} else {
				// we only copy values from up the proto chain
				newBehavior[prop] = res[prop];
			}
		}
		newBehavior.__behaviorName = name;
		return newBehavior;
	};
	if(name) {
		behaviorMixin.behaviorName = name;
		behaviorsMap[name] = behaviorMixin;
	}
	behaviorMixin.isBehavior = true;
	return behaviorMixin;
}
behavior.map = behaviorsMap;
var canConnect_4_0_6_behavior = behavior;

var behavior$1 = canConnect_4_0_6_behavior;

/**
 *
 * @param {Array<String,Behavior,function>} behaviors - An array of behavior names or custom behaviors.
 * The order of named execution gets run in order.
 * @param {Object} options
 * @hide
 */
var connect = function(behaviors, options){

	behaviors = behaviors.map(function(behavior, index){
		var sortedIndex = -1;
		if(typeof behavior === "string") {
			sortedIndex = connect.order.indexOf(behavior);
			behavior = behavior.map[behavior];
		} else if(behavior.isBehavior) {
			sortedIndex = connect.order.indexOf(behavior.behaviorName);
		} else {
			behavior = connect.behavior(behavior);
		}

		return {
			originalIndex: index,
			sortedIndex: sortedIndex,
			behavior: behavior
		};
	});

	behaviors.sort(function(b1, b2){
		// if both have a sorted index
		if(~b1.sortedIndex && ~b2.sortedIndex) {
			return b1.sortedIndex - b2.sortedIndex;
		}
		return b1.originalIndex - b2.originalIndex;
	});

	behaviors = behaviors.map(function(b){
		return b.behavior;
	});

	var behavior = connect.base( connect.behavior("options",function(){return options; })() );

	behaviors.forEach(function(behave){
		behavior = behave(behavior);
	});
	if(behavior.init) {
		behavior.init();
	}
	return behavior;
};



connect.order = ["data/localstorage-cache","data/url","data/parse","cache-requests","data/combine-requests",

	"constructor","constructor/store","can/map","can/ref",
	"fall-through-cache",

	"data/worker","real-time",

	"data/callbacks-cache","data/callbacks","constructor/callbacks-once"
];

connect.behavior = behavior$1;



var canConnect_4_0_6_connect= connect;

/**
 * @module can-connect/base/base base
 * @group can-connect/base/base.options 0 behavior options
 * @group can-connect/base/base.identifiers 1 identifiers
 * @parent can-connect.behaviors
 *
 * The first behavior added to every `can-connect` connection. Provides methods to uniquely identify instances and
 * lists.
 *
 * @signature `base(connectionOptions)`
 *
 * Provides instance and list identifiers. Added automatically to every connection created by the `connect` helper.
 * So even if we do:
 *
 * ```js
 * var connection = connect([],{});
 * ```
 *
 * The connection still has the identification functionality provided by `base`:
 *
 * ```js
 * connection.id({id: 1, ...}) //-> 1
 * ```
 *
 * `can-connect` connections are typically created by the `connect` helper rather than by calling the behaviors directly.
 * This ensures the behaviors are called in the required order and is more elegant than requiring the user to chain
 * together the calls to all the behaviors.
 *
 * See the [can-connect/base/base.id id] and [can-connect/base/base.listQuery listQuery] methods for more specifics on
 * how ids are determined.
 *
 * @param {Object} connectionOptions Object containing the configuration for the behaviors of the connection. Added to the
 * prototype of the returned connection object. `base` is almost always configured with an [can-connect/base/base.queryLogic] option since it
 * [can-connect/base/base.id defines how to read the identity properties] and the majority of behaviors also require the queryLogic.
 *
 * @return {Object} A `can-connect` connection containing the methods provided by `base`.
 */
var base = canConnect_4_0_6_behavior("base",function(baseConnection){
	var setQueryLogic;
	return {
		/**
		 * @function can-connect/base/base.id id
		 * @parent can-connect/base/base.identifiers
		 *
		 * Uniquely identify an instance or raw instance data.
		 *
		 * @signature `connection.id(instance)`
		 *
		 *   Returns the instance id as determined by [can-connect/base/base.queryLogic]'s id values.
		 *
		 *   @param {Instance|Object} instance An instance or raw properties for an instance.
		 *
		 *   @return {String|Number} A string or number uniquely representing `instance`.
		 *
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * Many behaviors, such as the [can-connect/constructor/store/store], need to have a unique identifier for an
		 * instance or instance data.  This `connection.id` method should return that.
		 *
		 * Typically, an item's id is a simply property value on the object. For example, "Todo" data might look like:
		 *
		 * ```js
		 * {_id: 5, name: "do the dishes"}
		 * ```
		 *
		 * In this case, [can-connect/base/base.queryLogic]'s `id` property should be set to "_id":
		 *
		 * ```js
		 * import QueryLogic from "can-query-logic";
		 *
		 * var queryLogic = new QueryLogic({
		 *   identity: ["_id"]
	 	 * });
		 *
		 * connect([...],{queryLogic: queryLogic});
		 * ```
		 *
		 */
		id: function(instance){
			if(this.queryLogic) {
				return canReflect_1_19_2_canReflect.getIdentity(instance, this.queryLogic.schema);
			} else if(this.idProp) {
				return instance[this.idProp];
			} else {
				throw new Error("can-connect/base/base - Please add a queryLogic option.");
			}
		},

		/**
		 * @function can-connect/base/base.listQuery listQuery
		 * @parent can-connect/base/base.identifiers
		 *
		 * Uniquely identify the set of data a list contains.
		 *
		 * @signature `connection.listQuery(list)`
		 *
		 *   Returns the value of the property referenced by [can-connect/base/base.listQueryProp] if it exists.
		 *   By default, this will return `list[Symbol.for("can.listQuery")]`.
		 *
		 *   @param {can-connect.List} list A list instance.
		 *
		 *   @return {can-query-logic/query} An object that can be passed to `JSON.stringify` to represent the list.
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * Many behaviors, such as the [can-connect/constructor/store/store], need to have a unique identifier for a list.
		 * This `connection.listQuery` method should return that.
		 *
		 * Typically, a list's set identifier is a property on the list object.  As example, a list of Todos might look like
		 * the following:
		 *
		 * ```js
		 * var dueTodos = todoConnection.getList({filter: {due: "today"}});
		 * dueTodos; // [{_id: 5, name: "do dishes", due:"today"}, {_id: 6, name: "walk dog", due:"today"}, ...]
		 * dueTodos[Symbol.for("can.listQuery")]; //-> {filter: {due: "today"}}
		 * todoConnection.listQuery(dueTodos); //-> {filter: {due: "today"}}
		 * ```
		 *
		 * In the above example the [can-connect/base/base.listQueryProp] would be the default `@can.listQuery`.
		 */
		listQuery: function(list){
			return list[this.listQueryProp];
		},

		/**
		 * @property {Symbol} can-connect/base/base.listQueryProp listQueryProp
		 * @parent can-connect/base/base.identifiers
		 *
		 * Specifies the property that uniquely identifies a list.
		 *
		 * @option {Symbol} The property that uniquely identifies the list.
		 * Defaults to `Symbol.for("can.listQuery")`.
		 *
		 * ```js
		 * var dataUrl = require("can-connect/data/url/");
		 * var connection = connect([dataUrl], {
		 *   listQueryProp: "set"
		 * });
		 *
		 * var list = [{id: 1, ...}, {id: 2, ...}]
		 * list.set = {complete: true};
		 *
		 * connection.listQuery(list) //-> {complete: true}
		 * ```
		 *
		 */
		listQueryProp: canSymbol_1_7_0_canSymbol.for("can.listQuery"),

		init: function(){},


		/**
		 * @property {can-query-logic} can-connect/base/base.queryLogic queryLogic
		 * @parent can-connect/base/base.options
		 *
		 * Configuration for list comparison, instance identification and membership
		 * calculations. A way for the `can-connect` behaviors to understand what the properties of a request mean and act
		 * on them.
		 *
		 * @option {can-query-logic} A [can-query-logic queryLogic] that is used to perform calculations using set
		 * definition objects passed to [can-connect/connection.getListData] and [can-connect/connection.getList].
		 * Needed to enable [can-connect/fall-through-cache/fall-through-cache caching],
		 * [can-connect/data/combine-requests/combine-requests request combining], [can-connect/real-time/real-time] and other
		 * behaviors. By default no queryLogic is provided.
		 *
		 * An example of the types of calculations behaviors will make using the queryLogic:
		 * ```js
		 * var queryLogic = new QueryLogic({
		 *   identity: ['_uid'],
		 *   keys: {
		 *     _uid: Number
		 *   }
		 * });
		 *
		 * var todoConnection = connect([...behaviors...],{
		 *   queryLogic: queryLogic
		 * });
		 *
		 * todoConnection.queryLogic.memberIdentity({_uid: 5, ...}); //-> 5
		 * todoConnection.id({_uid: 5, ...}); //-> 5
		 * todoConnection.queryLogic.intersection(
		 *   {page: {first: 0, last: 10}},
		 *   {page: {first:  d5, last: 20}}); //-> {first:5, last:10}
		 * ```
		 */

		get queryLogic(){
			if(setQueryLogic) {
				return setQueryLogic;
			} else if(baseConnection.queryLogic) {
				return baseConnection.queryLogic;
			} else if(baseConnection.algebra) {
				return baseConnection.algebra;
			}
		},
		set queryLogic(newVal) {
			setQueryLogic = newVal;
		}

		/**
		 * @property {can-query-logic} can-connect/base/base.algebra algebra
		 * @parent can-connect/base/base.options
		 *
		 * @description Legacy configuration for [can-set-legacy]. Use [can-connect/base/base.queryLogic] instead.
		 */

		/**
		 * @property {can-connect/DataInterface} can-connect/base/base.cacheConnection cacheConnection
		 * @parent can-connect/base/base.options
		 *
		 * An underlying `can-connect` connection used when fetching data from a cache.
		 *
		 * @option {can-connect/DataInterface} A connection that provides access to a cache via [can-connect/DataInterface]
		 * requests. Several behaviors including [can-connect/fall-through-cache/fall-through-cache] expect this property.
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * ```js
		 * import {memoryStore, connect, QueryLogic} from "can";
		 *
		 * var cacheConnection = memoryStore({
		 *   queryLogic: new QueryLogic({identity: ["id"]})
		 * });
		 *
		 * var todoConnection = connect([...behaviors...],{
		 *   cacheConnection: cacheConnection
		 * });
		 * ```
		 */
	};
});

canConnect_4_0_6_connect.base = base;

var canConnect_4_0_6_canConnect = canNamespace_1_0_0_canNamespace.connect = canConnect_4_0_6_connect;

var assign$1 = canReflect_1_19_2_canReflect.assignMap;

/**
 * @module {function} can-connect/helpers/weak-reference-map WeakReferenceMap
 * @parent can-connect.modules
 *
 * Provides a map that only contains keys that are referenced.
 *
 * @signature `new WeakReferenceMap()`
 *
 *   Creates a new weak reference map.
 *
 * @body
 *
 * ## Use
 *
 * ```
 * var WeakReferenceMap = require("can-connect/helpers/weak-reference-map");
 * var wrm = new WeakReferenceMap();
 * var task1 = {id: 1, name: "do dishes"};
 *
 * wrm.addReference("1", task1);
 * wrm.has("1") //-> true
 * wrm.addReference("1", task1);
 * wrm.has("1") //-> true
 * wrm.deleteReference("1");
 * wrm.has("1") //-> true
 * wrm.deleteReference("1");
 * wrm.has("1") //-> false
 * ```
 */

var WeakReferenceMap = function(){
	this.set = {};
};

// if weakmap, we can add and never worry ...
// otherwise, we need to have a count ...

assign$1(WeakReferenceMap.prototype,
/**
 * @prototype
 */
	{
	/**
	 * @function can-connect/helpers/weak-reference-map.prototype.has has
	 * @signature `weakReferenceMap.has(key)`
	 *
	 *   Returns if key is in the set.
	 *
	 *   @param  {String} key A key to look for.
	 *   @return {Boolean} If the key exists.
	 */
	has: function(key){
		return !!this.set[key];
	},
	/**
	 * @function can-connect/helpers/weak-reference-map.prototype.addReference addReference
	 * @signature `WeakReferenceMap.addReference(key, item)`
	 *
	 *   Adds a reference to item as key and increments the reference count. This should be called
	 *   when a value should be managed by something, typically the [can-connect/constructor/store/store].
	 *
	 *   @param  {String} key The key of the item in the store.
	 */
	addReference: function(key, item, referenceCount){
		// !steal-remove-start
		if (typeof key === 'undefined'){
			throw new Error("can-connect: You must provide a key to store a value in a WeakReferenceMap");
		}
		// !steal-remove-end
		var data = this.set[key];
		if(!data) {
			data = this.set[key] = {
				item: item,
				referenceCount: 0,
				key: key
			};
		}
		data.referenceCount += (referenceCount || 1);
	},
	referenceCount: function(key) {
		var data = this.set[key];
		if(data) {
			return data.referenceCount;
		}
	},
	/**
	 * @function can-connect/helpers/weak-reference-map.prototype.deleteReference deleteReference
	 * @signature `weakReferenceMap.deleteReference(key)`
	 *
	 *   Decrements the reference count for key and removes it if the reference count is `0`. This should be called
	 *   when a value should not be managed by something, typically the [can-connect/constructor/store/store].
	 *
	 *   @param  {String} key The key of the item in the store.
	 */
	deleteReference: function(key){
		var data = this.set[key];
		if(data){
			data.referenceCount--;
			if( data.referenceCount === 0 ) {
				delete this.set[key];
			}
		}
	},
	/**
	 * @function can-connect/helpers/weak-reference-map.prototype.get get
	 * @signature `weakReferenceMap.get(key)`
	 *
	 *   Returns the value stored at key if it's in the store.
	 *
	 *   @param  {String} key The key of the item in the store.
	 *   @return {*|undefined} The item if it's available.
	 */
	get: function(key){
		var data = this.set[key];
		if(data) {
			return data.item;
		}
	},
	/**
	 * @function can-connect/helpers/weak-reference-map.prototype.forEach forEach
	 * @signature `weakReferenceMap.forEach(callback)`
	 *
	 *   Calls `callback` for every value in the store.
	 *
	 *   @param  {function(*,String)} callback(item,key) A callback handler.
	 */
	forEach: function(cb){
		for(var id in this.set) {
			cb(this.set[id].item, id);
		}
	}
});

var weakReferenceMap = WeakReferenceMap;

var updateDeepExceptIdentity = function updateExceptIdentity(obj, data, schema) {
    if(!schema) {
        schema = canReflect_1_19_2_canReflect.getSchema(obj);
    }
    if(!schema) {
        throw new Error("can-diff/update-except-id is unable to update without a schema.");
    }
    // copy the keys onto data
    schema.identity.forEach(function(key){
        var id = canReflect_1_19_2_canReflect.getKeyValue(obj, key);
        if(id!== undefined) {
            canReflect_1_19_2_canReflect.setKeyValue(data, key, id );
        }
    });

    canReflect_1_19_2_canReflect.updateDeep(obj, data);
};

var idMerge = function(list$$1, update, id, make){

	var patches = list(list$$1, update, function(a, b){
		return id(a) === id(b);
	});
	patches.forEach(function(patch){
		canReflect_1_19_2_canReflect.splice(list$$1, patch.index, patch.deleteCount, patch.insert.map(make));
	});
};

/**
 * @module {connect.Behavior} can-connect/constructor/constructor constructor
 * @parent can-connect.behaviors
 * @group can-connect/constructor/constructor.options 1 behavior options
 * @group can-connect/constructor/constructor.crud 2 CRUD methods
 * @group can-connect/constructor/constructor.callbacks 3 CRUD callbacks
 * @group can-connect/constructor/constructor.hydrators 4 hydrators
 * @group can-connect/constructor/constructor.serializers 5 serializers
 * @group can-connect/constructor/constructor.helpers 6 helpers
 *
 * Adds an interface to interact with custom types via the connection instead of plain Objects and Arrays.
 *
 * @signature `constructor( baseConnection )`
 *
 * Adds an interface that allows the connection to operate on custom types. These fall into the categories:
 * - [can-connect/constructor/constructor#CRUDMethods CRUD Methods] - create, read, update and delete typed instances via the data source
 * - [can-connect/constructor/constructor#CRUDCallbacks CRUD Callbacks] - activities run on typed instances following data source operations
 * - [can-connect/constructor/constructor#Hydrator Hydrators] - conversion of raw data to typed data
 * - [can-connect/constructor/constructor#Serializers Serializers] - conversion of typed data to raw data
 *
 * @param {{}} baseConnection `can-connect` connection object that is having the `constructor` behavior added
 * on to it.
 *
 * @return {Object} A `can-connect` connection containing the method implementations provided by `constructor`.
 *
 * @body
 *
 * ## Use
 *
 * The `constructor` behavior allows you to instantiate the raw representation of the data source's data into a
 * custom typed representation with additional methods and behaviors.

 * An example might be loading data from a `"/todos"` service and being able to call `.timeLeft()`  on the todos that
 * you get back like:
 *
 * ```js
 * todoConnection.get({id: 6}).then(function(todo){
 *   todo.timeLeft() //-> 60000
 * })
 * ```
 *
 * The following creates a `todoConnection` that does exactly that:
 *
 * ```js
 * // require connection plugins
 * var constructor = require("can-connect/constructor/");
 * var dataUrl = require("can-connect/data/url/");
 *
 * // define type constructor function
 * var Todo = function(data){
 *   // add passed properties to new instance
 *   for(var prop in data) {
 *    this[prop] = data;
 *   }
 * };
 *
 * // add method to get time left before due, in milliseconds
 * Todo.prototype.timeLeft = function(){
 *   return new Date() - this.dueDate
 * };
 *
 * // create connection, passing function to instantiate new instances
 * var todoConnection = connect([constuctor, dataUrl], {
 *   url: "/todos",
 *   instance: function(data){
 *     return new Todo(data);
 *   }
 * });
 * ```
 *
 * The `constructor` behavior is still useful even if you want to keep your data as untyped objects (which is the
 * default behavior when no [can-connect/constructor/constructor.instance `instance`] implementation is provided).  The
 * behavior provides an interface to the data held by the client. For example,
 * [can-connect/constructor/constructor.updatedInstance] provides an extension point for logic that needs to be executed
 * after an instance held by the client finishes an update request. This is valuable whether that instance is typed or not.
 * Extensions like [can-connect/real-time/real-time] or [can-connect/fall-through-cache/fall-through-cache]
 * require this interface for advanced behavior.
 *
 * ## Interface
 *
 * `constructor` provides the following categories of methods to interact with typed data:
 *
 * ### <span id="CRUDMethods">CRUD Methods</span>
 *
 * Methods that create, read, update and delete (CRUD) typed representations of raw connection data:
 *
 * - [can-connect/constructor/constructor.get] - retrieve a single typed instance from the data source
 * - [can-connect/constructor/constructor.getList] - retrieve a typed list of instances from the data source
 * - [can-connect/constructor/constructor.save] - save a typed instance's data to the data source
 * - [can-connect/constructor/constructor.destroy] - delete a typed instance's data from the data source
 *
 * ### <span id="CRUDCallbacks">CRUD Callbacks</span>
 *
 * "CRUD Methods" call these methods with request response data and a related instance. Their implementation here
 * updates the related instance with that data:
 *
 * - [can-connect/constructor/constructor.createdInstance] - after [can-connect/constructor/constructor.save saving] new instance to data source, update that instance with response data
 * - [can-connect/constructor/constructor.updatedInstance] - after [can-connect/constructor/constructor.save saving] existing instance to data source, update that instance with response data
 * - [can-connect/constructor/constructor.destroyedInstance] - after [can-connect/constructor/constructor.destroy deleting] instance from data source, update that instance with response data
 * - [can-connect/constructor/constructor.updatedList] - after new data is read from the data source, update an existing list with instances created from that data
 *
 * ### <span id="CRUDMethods">Hydrators</span>
 *
 * These methods are used to create a typed instance or typed list given raw data objects:
 * - [can-connect/constructor/constructor.hydrateInstance] - create a typed instance given raw instance data
 * - [can-connect/constructor/constructor.hydrateList] - create a typed list of typed instances given given raw list data
 *
 * ### <span id="Serializers">Serializers</span>
 *
 * These methods convert a typed instance or typed list into a raw object:
 * - [can-connect/constructor/constructor.serializeInstance] - return raw data representing the state of the typed instance argument
 * - [can-connect/constructor/constructor.serializeList] - return raw data representing the state of the typed list argument
 *
 */

var makeArray = canReflect_1_19_2_canReflect.toArray;
var assign$2 = canReflect_1_19_2_canReflect.assignMap;






var constructor_1 = canConnect_4_0_6_behavior("constructor",function(baseConnection){

	var behavior = {
		// stores references to instances
		// for now, only during create
		/**
		 * @property {can-connect/helpers/weak-reference-map} can-connect/constructor/constructor.cidStore cidStore
		 * @parent can-connect/constructor/constructor.helpers
		 *
		 * Temporarily hold references to new instances via their [can-cid] while they are undergoing creation.
		 *
		 * @option {can-connect/helpers/weak-reference-map} Temporarily holds references to instances by
		 * [can-cid] when they are in the process of being created and don't yet have an `id`s. This is typically
		 * accessed in `createdData` handlers (e.g [can-connect/real-time/real-time.createdData real-time.createdData]) that
		 * need to lookup the instance that was being created during a particular request.
		 */
		cidStore: new weakReferenceMap(),
		_cid: 0,

		/**
		 * @function can-connect/constructor/constructor.get get
		 * @parent can-connect/constructor/constructor.crud
		 *
		 * Retrieve a single instance from the connection data source.
		 *
		 * @signature `connection.get(params)`
		 *
		 * Retrieves instance data from [can-connect/connection.getData], runs the resulting data through
		 * [can-connect/constructor/constructor.hydrateInstance], creating a typed instance with the retrieved data.
		 *
		 * @param {Object} params data specifying the instance to retrieve.  Normally, this is something like like:
		 * `{id: 5}`.
		 *
		 * @return {Promise<can-connect/Instance>} `Promise` resolving to the instance returned by
		 * [can-connect/constructor/constructor.hydrateInstance].
		 *
		 * ### Usage
		 *
		 * Call `.get()` with the parameters that identify the instance you want to load.  `.get()` will return a promise
		 * that resolves to that instance:
		 * ```js
		 * todoConnection.get({id: 6}).then(function(todo){
		 *   todo.id; // 6
		 *   todo.name; // 'Take out the garbage'
		 * });
		 * ```
		 *
		 * `.get()` above will call [can-connect/connection.getData `getData`] on the [can-connect/data/url/url]
		 * behavior, which will make an HTTP GET request to `/todos/6`.
		 */
		get: function(params) {
			var self = this;
			return this.getData(params).then(function(data){
				return self.hydrateInstance(data);
			});
		},

		/**
		 * @function can-connect/constructor/constructor.getList getList
		 * @parent can-connect/constructor/constructor.crud
		 *
		 * Retrieve a list of instances from the connection data source.
		 *
		 * @signature `connection.getList(set)`
		 *
		 * Retrieves list data from [can-connect/connection.getListData] and runs the resulting data through
		 * [can-connect/constructor/constructor.hydrateList], creating a typed list of typed instances from  the retrieved
		 * data.
		 *
		 * @param {can-query-logic/query} query data specifying the range of instances to retrieve. This might look something like:
		 * ```{start: 0, end: 50, due: 'today'}```
		 *
		 * @return {Promise<can-connect.List<can-connect/Instance>>} `Promise` resolving to the typed list returned by
		 * [can-connect/constructor/constructor.hydrateList].
		 *
		 * ### Usage
		 *
		 * Call `getList` with the parameters that specify the set of data you want to load.  `.getList()` will return
		 * a promise that resolves to a [can-connect.List] created from that set.
		 *
		 * ```js
		 * todoConnection.getList({due: 'today'}).then(function(todos){
		 *   todos[0].name; // 'Take out the garbage'
		 *   todos[0].due > startOfDay && todos[0].due < endOfDay; // true
		 * })
		 * ```
		 *
		 */
		getList: function(set) {
			set = set ||  {};
			var self = this;
			return this.getListData( set ).then(function(data){
				return self.hydrateList(data, set);
			});
		},


		/**
		 * @function can-connect/constructor/constructor.hydrateList hydrateList
		 * @parent can-connect/constructor/constructor.hydrators
		 *
		 * Produce a typed list from the provided raw list data.
		 *
		 * @signature `connection.hydrateList(listData, set)`
		 *
		 *   Call [can-connect/constructor/constructor.hydrateInstance] for each item in the raw list data, and then call
		 *   [can-connect/constructor/constructor.list] with an array of the typed instances returned from
		 *   [can-connect/constructor/constructor.hydrateInstance] .  If [can-connect/constructor/constructor.list] is not
		 *   provided as an argument or implemented by another behavior, a normal array is created.
		 *
		 *   @param {can-connect.listData} listData the raw list data returned by the data source, often via [can-connect/connection.getListData]
		 *   @param {can-query-logic/query} query description of the set of data `listData` represents
		 *
		 *   @return {can-connect.List} a typed list containing typed instances generated from `listData`
		 */
		hydrateList: function(listData, set){
			if(Array.isArray(listData)) {
				listData = {data: listData};
			}

			var arr = [];
			for(var i = 0; i < listData.data.length; i++) {
				arr.push( this.hydrateInstance(listData.data[i]) );
			}
			listData.data = arr;
			if(this.list) {
				return this.list(listData, set);
			} else {
				var list = listData.data.slice(0);
				list[this.listQueryProp || "__listQuery"] = set;
				copyMetadata(listData, list);
				return list;
			}
		},

		/**
		 * @function can-connect/constructor/constructor.hydrateInstance hydrateInstance
		 * @parent can-connect/constructor/constructor.hydrators
		 *
		 * Produce a typed object containing the provided raw data.
		 *
		 * @signature `connection.hydrateInstance(props)`
		 *
		 * If [can-connect/constructor/constructor.instance] has been passed as an option, or defined by another behavior,
		 * pass `props` to it and return the value. Otherwise, return a clone of `props`.
		 *
		 * @param {Object} props the raw instance data returned by the data source, often via [can-connect/connection.getData]
		 * @return {can-connect/Instance} a typed instance containing the data from `props`
		 */
		hydrateInstance: function(props){
			if(this.instance) {
				return this.instance(props);
			}  else {
				return assign$2({}, props);
			}
		},
		/**
		 * @function can-connect/constructor/constructor.save save
		 * @parent can-connect/constructor/constructor.crud
		 *
		 * @description Create or update an instance on the connection data source
		 *
		 * @signature `connection.save( instance )`
		 *
		 *   First checks if the instance has an [can-connect/base/base.id] or not.  If it has an id, the instance will be
		 *   updated; otherwise, it will be created.
		 *
		 *   When creating an instance, the instance is added to the [can-connect/constructor/constructor.cidStore], and its
		 *   [can-connect/constructor/constructor.serializeInstance serialized data] is passed to
		 *   [can-connect/connection.createData].  If `createData`'s promise resolves to anything other than `undefined`,
		 *   [can-connect/constructor/constructor.createdInstance] is called with that data.
		 *
		 *   When updating an instance, its [can-connect/constructor/constructor.serializeInstance serialized data] is
		 *   passed to [can-connect/connection.updateData]. If `updateData`'s promise resolves to anything other than
		 *   `undefined`, [can-connect/constructor/constructor.updatedInstance] is called with that data.
		 *
		 *   @param {can-connect/Instance} instance the instance to create or save
		 *
		 *   @return {Promise<can-connect/Instance>} `Promise` resolving to the same instance that was passed to `save`
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * To use `save` to create an instance, create a connection, then an instance, and call `.save()` on it:
		 *
		 * ```js
		 * // Create a connection
	     * var constructor = require('can-connect/constructor/');
		 * var dataUrl = require('can-connect/data/url/');
		 * var todoConnection = connect([dataUrl, constructor], {
		 *   url: "/todos"
		 * });
		 *
		 * // Create an instance
		 * var todo = {name: "do dishes"};
		 *
		 * // Call .save()
		 * todoConnection.save(todo)
		 * ```
		 *
		 * `.save(todo)` above will call [can-connect/data/url/url.createData `createData`] on the [can-connect/data/url/url]
		 * behavior, which will make an HTTP POST request to `/todos` with the serialized `todo` data.  The server response
		 * data may look something like:
		 *
		 * ```js
		 * {
		 *  id: 5,
		 *  ownerId: 9
		 * }
		 * ```
		 *
		 * That data will be passed to [can-connect/constructor/constructor.createdInstance] which by default
		 * adds those properties to `todo`, resulting in `todo` looking like:
		 *
		 * ```js
		 * {
		 *  name: "do dishes",
		 *  id: 5,
		 *  ownerId: 9
		 * }
		 * ```
		 *
		 * As an example of updating an instance, change a property on `todo` and call `.save()` again:
		 *
		 * ```js
		 * // Change a property
		 * todo.name = "Do dishes now!!";
		 *
		 * // Call .save()
		 * todoConnection.save(todo)
		 * ```
		 *
		 * The `.save(todo)` above will call [can-connect/data/url/url.updateData `updateData`] on the
		 * [can-connect/data/url/url] behavior, which will make an HTTP PUT request to `/todos` with the serialized `todo`
		 * data.
		 *
		 * A successful server response body should look something like:
		 *
		 * ```js
		 * {
		 *  name: "Do dishes now!!",
		 *  id: 5,
		 *  ownerId: 9
		 * }
		 * ```
		 *
		 * This data will be passed to [can-connect/constructor/constructor.updatedInstance] which by default sets
		 * all of `todo`'s properties to look like the response data, even removing properties that are missing from the
		 * response data.
		 */
		save: function(instance){
			var serialized = this.serializeInstance(instance);
			var id = this.id(instance);
			var self = this;
			if(id === undefined) {
				// If `id` is undefined, we are creating this instance.
				// It should be given a local id and temporarily added to the cidStore
				// so other hooks can get back the instance that's being created.
				var cid = this._cid++;
				// cid is really a token to be able to reference this transaction.
				this.cidStore.addReference(cid, instance);
				
				// Call the data layer.
				// If the data returned is undefined, don't call `createdInstance`
				return this.createData(serialized, cid).then(function(data){
					canQueues_1_3_2_canQueues.batch.start();
					// if undefined is returned, this can't be created, or someone has taken care of it
					if(data !== undefined) {
						self.createdInstance(instance, data);
					}
					self.cidStore.deleteReference(cid, instance);
					canQueues_1_3_2_canQueues.batch.stop();
					return instance;
				});
			} else {
				return this.updateData(serialized).then(function(data){
					canQueues_1_3_2_canQueues.batch.start();
					if(data !== undefined) {
						self.updatedInstance(instance, data);
					}
					canQueues_1_3_2_canQueues.batch.stop();
					return instance;
				});
			}
		},
		/**
		 * @function can-connect/constructor/constructor.destroy destroy
		 * @parent can-connect/constructor/constructor.crud
		 * @description Delete an instance from the connection data source
		 *
		 * @signature `connection.destroy( instance )`
		 *
		 *   To destroy an instance, it's [can-connect/constructor/constructor.serializeInstance serialized data] is passed
		 *   to [can-connect/connection.destroyData]. If [can-connect/connection.destroyData]'s promise resolves to anything
		 *   other than `undefined`, [can-connect/constructor/constructor.destroyedInstance] is called.
		 *
		 *   @param {can-connect/Instance} instance the instance being deleted from the data source
		 *
		 *   @return {Promise<can-connect/Instance>} `Promise` resolving to the same instance that was passed to `destroy`
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * To use `destroy`, create a connection, retrieve an instance, and then call `.destroy()` with it.
		 *
		 * ```js
		 * // create a connection
		 * var constructor = require('can-connect/constructor/');
		 * var dataUrl = require('can-connect/data/url/');
		 * var todoConnection = connect([dataUrl, constructor], {
		 *   url: "/todos"
		 * })
		 *
		 * // retrieve a todo instance
		 * todoConnection.get({id: 5}).then(function(todo){
		 *   // Call .destroy():
		 *   todoConnection.destroy(todo)
		 * });
		 * ```
		 *
		 * `.destroy()` above will call [can-connect/connection.destroyData `destroyData`] on the [can-connect/data/url/url]
		 * behavior, which will make an HTTP DELETE request to `/todos/5` with the serialized `todo` data.  The server
		 * response data may look something like:
		 *
		 * ```js
		 * {
		 *   deleted: true
		 * }
		 * ```
		 *
		 * That response data will be passed to [can-connect/constructor/constructor.destroyedInstance], which by default
		 * adds those properties to `todo`.
		 */
		// ## destroy
		// Calls the data interface `destroyData` and as long as it
		// returns something, uses that data to call `destroyedInstance`.
		destroy: function(instance){
			var serialized = this.serializeInstance(instance),
				self = this,
				id = this.id(instance);

			if (id !== undefined) {
				return this.destroyData(serialized).then(function (data) {
					if (data !== undefined) {
						self.destroyedInstance(instance, data);
					}
					return instance;
				});
			} else {
				this.destroyedInstance(instance, {});
				return Promise.resolve(instance);
			}
		},

		/**
		 * @function can-connect/constructor/constructor.createdInstance createdInstance
		 * @parent can-connect/constructor/constructor.callbacks
		 *
		 * A method run whenever a new instance has been saved to the data source. Updates the instance with response data.
		 *
		 * @signature `connection.createdInstance( instance, props )`
		 *
		 * `createdInstance` is run whenever a new instance is saved to the data source. This implementation updates the
		 * instance with the data returned by [can-connect/connection.createData] which made the request to save the raw
		 * instance data.
		 *
		 * @param {can-connect/Instance} instance the instance that was created
		 * @param {Object} props the data returned from [can-connect/connection.createData] that will update the properties of `instance`
		 */
		createdInstance: function(instance, props){
			assign$2(instance, props);
		},

		/**
		 * @function can-connect/constructor/constructor.updatedInstance updatedInstance
		 * @parent can-connect/constructor/constructor.callbacks
		 *
		 * A method run whenever an existing instance has been saved to the data source. Overwrites the instance with response
		 * data.
		 *
		 * @signature `connection.updatedInstance( instance, props )`
		 *
		 * `updatedInstance` is run whenever an existing instance is saved to the data source. This implementation overwrites
		 * the instance with the data returned bu [can-connect/connection.updatedData] which made the request to save the
		 * modified instance data.
		 *
		 * @param {can-connect/Instance} instance the instance that was updated
		 * @param {Object} props the data from [can-connect/connection.updateData] that will overwrite the properties of `instance`
		 */
		updatedInstance: function(instance, data){
			updateDeepExceptIdentity(instance, data, this.queryLogic.schema);
		},

		/**
		 * @function can-connect/constructor/constructor.updatedList updatedList
		 * @parent can-connect/constructor/constructor.callbacks
		 *
		 * A method run whenever new data for an existing list is retrieved from the data source. Updates the list to
		 * include the new data.
		 *
		 * @signature `connection.updatedList( list, listData, set )`
		 *
		 * [can-connect/constructor/constructor.hydrateInstance Hydrates instances] from `listData`'s data and attempts to
		 * merge them into `list`.  The merge is able to identify simple insertions and removals of elements instead of
		 * replacing the entire list.
		 *
		 * @param {can-connect/Instance} list an existing list
		 * @param {can-connect.listData} listData raw data that should be included as part of `list` after conversion to typed instances
		 * @param {can-query-logic/query} query description of the set of data `list` represents
		 */
		updatedList: function(list, listData, set) {
			var instanceList = [];
			for(var i = 0; i < listData.data.length; i++) {
				instanceList.push( this.hydrateInstance(listData.data[i]) );
			}
			// This only works with "referenced" instances because it will not
			// update and assume the instance is already updated
			// this could be overwritten so that if the ids match, then a merge of properties takes place
			idMerge(list, instanceList, this.id.bind(this), this.hydrateInstance.bind(this));

			copyMetadata(listData, list);
		},

		/**
		 * @function can-connect/constructor/constructor.destroyedInstance destroyedInstance
		 * @parent can-connect/constructor/constructor.callbacks
		 *
		 * A method run whenever an instance has been deleted from the data source. Overwrites the instance with response data.
		 *
		 * @signature `connection.destroyedInstance( instance, props )`
		 *
		 * `destroyedInstance` is run whenever an existing instance is deleted from the data source. This implementation
		 * overwrites the instance with the data returned by [can-connect/connection.destroyData] which made the request to
		 * delete the raw instance data.
		 *
		 * @param {can-connect/Instance} instance the instance that was deleted
		 * @param {Object} props the data returned from [can-connect/connection.destroyData] that will overwrite the
		 * properties of `instance`
		 */
		destroyedInstance: function(instance, data){
			updateDeepExceptIdentity(instance, data, this.queryLogic.schema);
		},

		/**
		 * @function can-connect/constructor/constructor.serializeInstance serializeInstance
		 * @parent can-connect/constructor/constructor.serializers
		 *
		 * @description Generate the serialized form of a typed instance.
		 *
		 * @signature `connection.serializeInstance( instance )`
		 *
		 *   Generate a raw object representation of a typed instance. This default implementation simply clones the
		 *   `instance` object, copying all the properties of the object (excluding properties of it's prototypes) to a new
		 *   object. This is equivalent to `Object.assign({}, instance)`.
		 *
		 * @param {can-connect/Instance} instance the instance to serialize
		 * @return {Object} a serialized representation of the instance
		 */
		serializeInstance: function(instance){
			return assign$2({}, instance);
		},

		/**
		 * @function can-connect/constructor/constructor.serializeList serializeList
		 * @parent can-connect/constructor/constructor.serializers
		 *
		 * @description Generate the serialized form of a typed list.
		 *
		 * @signature `connection.serializeList( list )`
		 *
		 *   Generate a raw array representation of a typed list. This default implementation simply returns a plain `Array`
		 *   containing the result of calling [can-connect/constructor/constructor.serializeInstance] on each item in the
		 *   typed list.
		 *
		 * @param {can-connect.List} list The instance to serialize.
		 * @return {Object|Array} A serialized representation of the list.
		 */
		serializeList: function(list){
			var self = this;
			return makeArray(list).map(function(instance){
				return self.serializeInstance(instance);
			});
		},

		/**
		 * @function can-connect/constructor/constructor.isNew isNew
		 * @parent can-connect/constructor/constructor.helpers
		 *
		 * Returns if the instance has not been loaded from or saved to the data source.
		 *
		 * @signature `connection.isNew(instance)`
		 * @param {Object} instance the instance to test
		 * @return {Boolean} `true` if [can-connect/base/base.id] is `null` or `undefined`
		 */
		isNew: function(instance){
			var id = this.id(instance);
			return !(id || id === 0);
		}

		/**
		 * @property can-connect/constructor/constructor.list list
		 * @parent can-connect/constructor/constructor.options
		 *
		 * Behavior option provided to create a typed list from a raw array.
		 *
		 * @signature `connection.list( listData, set )`
		 *
		 * Takes a `listData` argument with a `data` property, that is an array of typed instances, each produced by
		 * [can-connect/constructor/constructor.hydrateInstance], and returns a new typed list containing those typed
		 * instances.
		 * This method is passed as an option to the connection.
		 * Called by [can-connect/constructor/constructor.hydrateList].
		 *
		 * @param {can-connect.listData} listData an object with a `data` property, which is an array of instances.
		 * @param {can-query-logic/query} query the set description of this list
		 * @return {can-connect.List} a typed list type containing the typed instances
		 *
		 * ### Usage
		 *
		 * The following example makes the connection produce `MyList` typed lists including a `completed` method:
		 *
		 * ```js
		 * var constructor = require("can-connect/constructor/");
		 * var dataUrl = require("can-connect/data/url/");
		 *
		 * // define custom list type constructor
		 * var MyList = function(items) {
		 *  this.push.apply(this, items);
		 * }
		 * // inherit Array functionality
		 * MyList.prototype = Object.create(Array.prototype);
		 * // add custom methods to new list type
		 * MyList.prototype.completed = function(){
		 *  return this.filter(function(){ return this.completed });
		 * };
		 *
		 * // create connection
		 * var todosConnection = connect([constructor, dataUrl], {
		 *   url: "/todos",
		 *   list: function(listData, set){
		 *     // create custom list instance
		 *     var collection = new MyList(listData.data);
		 *     // add set info for use by other behaviors
		 *     collection.__listQuery = set;
		 *     return collection;
		 *   }
		 * });
		 *
		 * // use connection to get typed list & use custom method
		 * todosConnection.getList({}).then(function(todoList){
		 *   console.log("There are", todoList.completed().length, "completed todos");
		 * });
		 * ```
		 *
		 * **Note:** we added the [can-connect/base/base.listQueryProp] property (`Symbol.for("can.listQuery")` by default) on the list. This is
		 * expected by other behaviors.
		 */

		/**
		 * @property can-connect/constructor/constructor.instance instance
		 * @parent can-connect/constructor/constructor.options
		 *
		 * Behavior option provided to create a typed form of passed raw data.
		 *
		 * @signature `connection.instance( props )`
		 *
		 * Creates a typed instance for the passed raw data object. This method is passed as an option to the connection.
		 * Called by [can-connect/constructor/constructor.hydrateInstance].
		 *
		 * @param {Object} props a raw object containing the properties from the data source
		 * @return {can-connect/Instance} the typed instance created from the passed `props` object
		 *
		 * ### Usage
		 *
		 * The following example makes the connection produce `Todo` typed objects including a `complete` method:
		 *
		 * ```js
		 * var constructor = require("can-connect/constructor/");
		 * var dataUrl = require("can-connect/data/url/");
		 *
		 * // define type constructor
		 * var Todo = function(rawData){
		 *   // add raw data to new instance
		 *   Object.assign(this, rawData);
		 * };
		 *
		 * // add methods to custom type
		 * Todo.prototype.complete = function(){
		 *   this.completed = true;
		 * }
		 *
		 * // create connection
		 * var todosConnection = connect([constructor, dataUrl], {
		 *   url: "/todos",
		 *   instance: function(rawData) {
		 *     return new Todo(rawData);
		 *   }
		 * });
		 *
		 * // use connection to get typed instance & use custom method
		 * todosConnection.get({id: 5}).then(function(todo){
		 *   todo.completed; // false
		 *   todo.complete();
		 *   todo.completed; // true
		 * });
		 * ```
		 *
		 */
	};

	return behavior;

});

function copyMetadata(listData, list){
	for(var prop in listData) {
		if(prop !== "data") {
			// this is map infultrating constructor, but it's alright here.
			if(typeof list.set === "function") {
				list.set(prop, listData[prop]);
			} else if(typeof list.attr === "function") {
				list.attr(prop, listData[prop]);
			} else {
				list[prop] = listData[prop];
			}

		}
	}
}

var assignDeepExceptIdentity = function assignExceptIdentity(obj, data, schema) {
    if(!schema) {
        schema = canReflect_1_19_2_canReflect.getSchema(obj);
    }
    if(!schema) {
        throw new Error("can-diff/update-except-id is unable to update without a schema.");
    }
    // copy the keys onto data
    schema.identity.forEach(function(key){
        var id = canReflect_1_19_2_canReflect.getKeyValue(obj, key);
        if(id!== undefined) {
            canReflect_1_19_2_canReflect.setKeyValue(data, key, id );
        }
    });

    canReflect_1_19_2_canReflect.assignDeep(obj, data);
};

function smartMerge(instance, props) {

	props = canReflect_1_19_2_canReflect.serialize(props);

	if (canReflect_1_19_2_canReflect.isMoreListLikeThanMapLike(instance)) {
		mergeList(instance, props);
	} else {
		mergeMap(instance, props);
	}
	return instance;
}

// date is expected to be mutable here
function mergeMap(instance, data) {

	// for each key in
	canReflect_1_19_2_canReflect.eachKey(instance, function(value, prop) {
		if(!canReflect_1_19_2_canReflect.hasKey(data, prop)) {
			canReflect_1_19_2_canReflect.deleteKeyValue(instance, prop);
			return;
		}
		var newValue = canReflect_1_19_2_canReflect.getKeyValue(data, prop);
		canReflect_1_19_2_canReflect.deleteKeyValue(data, prop);

		// cases:
		// a. list
		// b. map
		// c. primitive

		// if the data is typed, we would just replace it
		if (canReflect_1_19_2_canReflect.isPrimitive(value)) {
			canReflect_1_19_2_canReflect.setKeyValue(instance, prop, newValue);
			return;
		}


		var newValueIsList = Array.isArray(newValue),
			currentValueIsList = canReflect_1_19_2_canReflect.isMoreListLikeThanMapLike(value);

		if (currentValueIsList && newValueIsList) {

			mergeList(value, newValue);

		} else if (!newValueIsList && !currentValueIsList && canReflect_1_19_2_canReflect.isMapLike(value) && canReflect_1_19_2_canReflect.isPlainObject(newValue)) {

			// TODO: the `TYPE` should probably be infered from the `_define` property definition.
			var schema = canReflect_1_19_2_canReflect.getSchema(value);
			if (schema && schema.identity && schema.identity.length) {
				var id = canReflect_1_19_2_canReflect.getIdentity(value, schema);
				if (id != null && id === canReflect_1_19_2_canReflect.getIdentity(newValue, schema)) {
					mergeMap(value, newValue);
					return;
				}
			}
			canReflect_1_19_2_canReflect.setKeyValue(instance, prop, canReflect_1_19_2_canReflect.new(value.constructor, newValue));
		} else {
			canReflect_1_19_2_canReflect.setKeyValue(instance, prop, newValue);
		}
	});
	canReflect_1_19_2_canReflect.eachKey(data, function(value, prop) {
		canReflect_1_19_2_canReflect.setKeyValue(instance, prop, value);
	});
}

function mergeList(list$$1, data) {
	var ItemType, itemSchema;
	var listSchema = canReflect_1_19_2_canReflect.getSchema(list$$1);
	if (listSchema) {
		ItemType = listSchema.values;
	}

	if (ItemType) {
		itemSchema = canReflect_1_19_2_canReflect.getSchema(ItemType);
	}
	if (!itemSchema && canReflect_1_19_2_canReflect.size(list$$1) > 0) {
		itemSchema = canReflect_1_19_2_canReflect.getSchema(canReflect_1_19_2_canReflect.getKeyValue(list$$1, 0));
	}

	var identity;
	if(itemSchema && itemSchema.identity && itemSchema.identity.length) {
		identity = function(a, b) {
		   var aId = canReflect_1_19_2_canReflect.getIdentity(a, itemSchema),
			   bId = canReflect_1_19_2_canReflect.getIdentity(b, itemSchema);
		   var eq = aId === bId;
		   if (eq) {
			   // If id is the same we merge data in. Case #2
			   mergeMap(a, b);
		   }
		   return eq;
	   };
   } else {
	   identity = function(a, b) {
		  var eq = a === b;
		  if (eq) {
			  // If id is the same we merge data in. Case #2
			  if(! canReflect_1_19_2_canReflect.isPrimitive(a) ) {
				   mergeMap(a, b);
			  }

		  }
		  return eq;
	  };
   }


	var patches = list(list$$1, data, identity);



	var hydrate = ItemType ? canReflect_1_19_2_canReflect.new.bind(canReflect_1_19_2_canReflect, ItemType) : function(v) {
		return v;
	};


	// If there are no patches then data contains only updates for all of the existing items, and we just leave.
	if (!patches.length) {
		return list$$1;
	}

	// Apply patches (add new, remove) #3. For any insertion use a hydrator.
	patches.forEach(function(patch) {
		applyPatch(list$$1, patch, hydrate);
	});
}

function applyPatch(list$$1, patch, makeInstance) {
	// Splice signature compared to patch:
	//   array.splice(start, deleteCount, item1, item2, ...)
	//   patch = {index: 1, deleteCount: 0, insert: [1.5]}
	var insert = makeInstance && patch.insert.map(function(val){
		return makeInstance(val);
	}) || patch.insert;

	var args = [patch.index, patch.deleteCount].concat(insert);
	list$$1.splice.apply(list$$1, args);

	return list$$1;
}

smartMerge.applyPatch = applyPatch;

var mergeDeep = smartMerge;

function flatten(arrays) {
	return arrays.reduce(function(ret, val) {
		return ret.concat(val);
	}, []);
}

// return a function that validates it's argument has all the properties in the interfacePropArrays
function makeInterfaceValidator(interfacePropArrays) {
	var props = flatten(interfacePropArrays);

	return function(base) {
			var missingProps = props.reduce(function(missing, prop) {
				return prop in base ? missing : missing.concat(prop);
			}, []);

		return missingProps.length ? {message:"missing expected properties", related: missingProps} : undefined;
	};
}

var canValidateInterface_1_0_3_index = makeInterfaceValidator;

// return wrapped can-connect behavior mixin that validates interface of the input behavior being extended
// deprecate this and use can-validate-interface decorator once available



var validate = function(extendingBehavior, interfaces){
	var validatedBehaviour = validateArgumentInterface(extendingBehavior, 0, interfaces, function(errors, baseBehavior) {
		throw new BehaviorInterfaceError(baseBehavior, extendingBehavior, errors);
	});

	// copy properties on behavior to validator wrapped behavior
	Object.keys(extendingBehavior).forEach(function (k) {
		validatedBehaviour[k] = extendingBehavior[k];
	});
	// add interfaces for building behavior ordering
	validatedBehaviour.__interfaces = interfaces;

	return validatedBehaviour;
};

function validateArgumentInterface(func, argIndex, interfaces, errorHandler) {
	return function() {
		var errors = canValidateInterface_1_0_3_index(interfaces)(arguments[argIndex]);
		if (errors && errorHandler) {
			errorHandler(errors, arguments[argIndex]);
		}

		return func.apply(this, arguments);
	};
}


// change to 'BehaviourInterfaceError extends Error' once we drop support for pre-ES2015
function BehaviorInterfaceError(baseBehavior, extendingBehavior, missingProps) {
	var extendingName = extendingBehavior.behaviorName || 'anonymous behavior',
		baseName = baseBehavior.__behaviorName || 'anonymous behavior',
		message = 'can-connect: Extending behavior "' + extendingName + '" found base behavior "' + baseName + '" was missing required properties: ' + JSON.stringify(missingProps.related),
		instance = new Error(message);

	if (Object.setPrototypeOf){
		Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
	}
	return instance;
}
BehaviorInterfaceError.prototype = Object.create(Error.prototype, {
	constructor: {value: Error}
});
if (Object.setPrototypeOf){
	Object.setPrototypeOf(BehaviorInterfaceError, Error);
} else {
	/* jshint proto: true */
	BehaviorInterfaceError.__proto__ = Error;
}

var map$3 = createCommonjsModule(function (module) {


var each = canReflect_1_19_2_canReflect.each;
var isPlainObject = canReflect_1_19_2_canReflect.isPlainObject;













var getNameSymbol = canSymbol_1_7_0_canSymbol.for("can.getName");

function smartMergeExceptIdentity(dest, source, schema) {
	if(!schema) {
        schema = canReflect_1_19_2_canReflect.getSchema(dest);
    }
    if(!schema) {
        throw new Error("can-connect/can/map/ is unable to update without a schema.");
    }
	schema.identity.forEach(function(key){
        var id = canReflect_1_19_2_canReflect.getKeyValue(dest, key);
        if(id!== undefined) {
            canReflect_1_19_2_canReflect.setKeyValue(source, key, id );
        }
    });
	mergeDeep(dest, source);
}

var canMapBehavior = canConnect_4_0_6_behavior("can/map",function(baseConnection){

	// overwrite
	var behavior = {
		init: function(){
			if(!this.Map) {
				if (this.ObjectType) {
					this.Map = this.ObjectType;
				} else {
					throw new Error("can-connect/can/map/map must be configured with a Map or ObjectType type");
				}
			}
			if(!this[getNameSymbol]) {
				this[getNameSymbol] = function(){
					if(this.name) {
						return "Connection{"+this.name+"}";
					} else if(this.Map) {
						return "Connection{"+canReflect_1_19_2_canReflect.getName(this.Map)+"}";
					} else if(typeof this.url === "string") {
						return "Connection{"+this.url+"}";
					} else {
						return "Connection{}";
					}
				};
			}

			this.List = this.List || this.ArrayType || this.Map.List;
			var hasList = Boolean(this.List);

			if (!hasList) {
				Object.defineProperty(this, 'List', {
					get: function () {
						throw new Error("can-connect/can/map/map - "+canReflect_1_19_2_canReflect.getName(this)+" should be configured with an ArrayType or List type.");
					}
				});
			}

			overwrite(this, this.Map, mapOverwrites);
			if (hasList) {
				overwrite(this, this.List, listOverwrites);
			}

			if(!this.queryLogic) {
				this.queryLogic = new canQueryLogic_1_2_4_canQueryLogic(this.Map);
			}


			var connection = this;

			// ### Setup store updates
			if(this.Map[canSymbol_1_7_0_canSymbol.for("can.onInstanceBoundChange")]) {
				var canConnectMap_onMapBoundChange = function (instance, isBound){
					var method = isBound ? "addInstanceReference" : "deleteInstanceReference";
					if(connection[method]) {
						connection[method](instance);
					}
				};
				//!steal-remove-start
				Object.defineProperty(canConnectMap_onMapBoundChange, "name", {
					value: canReflect_1_19_2_canReflect.getName(this.Map) + " boundChange",
					configurable: true
				});
				//!steal-remove-end
				this.Map[canSymbol_1_7_0_canSymbol.for("can.onInstanceBoundChange")](canConnectMap_onMapBoundChange);
			} else {
				console.warn("can-connect/can/map is unable to listen to onInstanceBoundChange on the Map type");
			}

			if (hasList) {
				if(this.List[canSymbol_1_7_0_canSymbol.for("can.onInstanceBoundChange")]) {
					var canConnectMap_onListBoundChange = function(list, isBound){
						var method = isBound ? "addListReference" : "deleteListReference";
						if(connection[method]) {
							connection[method](list);
						}
					};
					//!steal-remove-start
					Object.defineProperty(canConnectMap_onListBoundChange, "name", {
						value: canReflect_1_19_2_canReflect.getName(this.List) + " boundChange",
						configurable: true
					});
					//!steal-remove-end
					this.List[canSymbol_1_7_0_canSymbol.for("can.onInstanceBoundChange")](canConnectMap_onListBoundChange);
				} else {
					console.warn("can-connect/can/map is unable to listen to onInstanceBoundChange on the List type");
				}
			}

			// Adds the instance when its `id` property is set
			if(this.Map[canSymbol_1_7_0_canSymbol.for("can.onInstancePatches")]) {
				this.Map[canSymbol_1_7_0_canSymbol.for("can.onInstancePatches")](function canConnectMap_onInstancePatches(instance, patches){
					patches.forEach(function(patch){
						if( (patch.type === "add" || patch.type === "set") &&
							patch.key === connection.idProp &&
							instance[canSymbol_1_7_0_canSymbol.for("can.isBound")]()) {
							connection.addInstanceReference(instance);
						}
					});
				});
			} else {
				console.warn("can-connect/can/map is unable to listen to onInstancePatches on the Map type");
			}
			baseConnection.init.apply(this, arguments);
		},
		/**
		 * @function can-connect/can/map/map.serializeInstance serializeInstance
		 * @parent can-connect/can/map/map.serializers
		 *
		 * Returns the properties of an instance that should be sent to the data source when saving. Done by calling
		 * [can-define/map/map.prototype.serialize `instance.serialize()`].
		 *
		 * @signature `connection.serializeInstance(instance)`
		 * Simply calls [can-define/map/map.prototype.serialize] on the `instance` argument.
		 *
		 * @param {can-connect/can/map/map._Map} instance the instance to serialize
		 * @return {Object} the result of calling [can-define/map/map.prototype.serialize `instance.serialize()`]
		 */
		serializeInstance: function(instance){
			return canReflect_1_19_2_canReflect.serialize(instance);
		},
		/**
		 * @function can-connect/can/map/map.serializeList serializeList
		 * @parent can-connect/can/map/map.serializers
		 *
		 * Returns the properties of a list that should be sent to the data source when saving. Done by calling
		 * [can-define/list/list.prototype.serialize `list.serialize()`].
		 *
		 * @signature `connection.serializeList(list)`
		 * Simply calls [can-define/list/list.prototype.serialize] on the `list` argument.
		 *
		 * @param {can-connect/can/map/map._List} list the list to serialize
		 * @return {Object} the result of calling [can-define/list/list.prototype.serialize `list.serialize()`]
		 */
		serializeList: function(list){
			return canReflect_1_19_2_canReflect.serialize(list);
		},
		/**
		 * @property {Boolean} can-connect/can/map/map.updateInstanceWithAssignDeep updateInstanceWithAssignDeep
		 * @parent can-connect/can/map/map.options
		 *
		 * Use the response from `save()` and `destroy()` to assign properties, never delete them.
		 *
		 * @option {Boolean}
		 *
		 * Setting `updateInstanceWithAssignDeep` to `true` changes how instances get updated. Instead of using
		 * [can-diff/merge-deep/merge-deep], records will be updated with [can-reflect.assignDeep].
		 *
		 * The following example shows that the response from `.save()` only includes the `id`
		 * property. Normally, this would delete all other properties (`name`).  But setting `updateInstanceWithAssignDeep`
		 * to `true` prevents this:
		 *
		 * **Usage:**
		 *
		 * ```js
		 * import {DefineMap, restModel} from "can";
		 *
		 * var Todo = DefineMap.extend({
		 *   id: {type: "number", identity: true},
		 *   name: "string"
		 * });
		 *
		 * // restModel uses `can-connect/can/map/map`
		 * restModel({
		 *   Map: Todo,
		 *   url: "/todos",
		 *   updateInstanceWithAssignDeep: true
		 * });
		 *
		 *
		 * var todo = new Todo({name: "learn canjs"})
		 *
		 * var savePromise = todo.save()
		 * // SERVER SENDS
		 * // -> POST /todos {name: "learn canjs"}
		 *
		 * // SERVER RESPONDS WITH:
		 * // <- {id: 5}
		 *
		 * savePromise.then(function(){
		 *   // Name still exists even though the server did not
		 *   // respond with it.
		 *   todo.name //-> "learn canjs"
		 * })
		 * ```
		 *
		 * __NOTE__: [can-diff/merge-deep/merge-deep] is able to work _MUCH_ better with nested
		 * data than [can-reflect.assignDeep]. Specifically, it is able to better
		 * prevent overwriting one instance's data with another. The _Use_ section of [can-diff/merge-deep/merge-deep]
		 * goes over this ability. Make sure you understand its capabilities before turning it off.
		 */

		/**
		 * @property {connection.Map} can-connect/can/map/map._Map Map
		 * @parent can-connect/can/map/map.options
		 *
		 * Specify the type of the `[can-define/map/map DefineMap]` that should be instantiated by the connection.
		 *
		 * @option {connection.Map}
		 *
		 * **Usage:**
		 *
		 * ```js
		 * var DefineMap = require("can-define/map/map");
		 * var canMap = require("can-connect/can/map/map");
		 * var constructor = require("can-connect/constructor/constructor");
		 * var dataUrl = require("can-connect/data/url/url");
		 *
		 * var Todo = DefineMap.extend({
		 *   completed: "boolean",
		 *   complete: function(){
		 *     this.completed = true
		 *   }
		 * });
		 *
		 * var todoConnection = connect([dataUrl, constructor, canMap], {
		 *   Map: Todo,
		 *   url: "/todos"
		 * });
		 *
		 * todoConnect.get({id:1}).then(function(item) {
		 *   item instanceof Todo // true
		 * });
		 * ```
		 */

		/**
		 * @property {connection.List} can-connect/can/map/map._List List
		 * @parent can-connect/can/map/map.options
		 *
		 * Specify the type of the `[can-define/list/list DefineList]` that should be instantiated by the connection.
		 *
		 * @option {connection.List} If this option is not specified it defaults to the [can-connect/can/map/map._Map Map].List
		 * property.
		 *
		 * **Usage:**
		 * ```js
		 * var DefineMap = require("can-define/map/map");
		 * var DefineList = require("can-define/list/list");
		 * var canMap = require("can-connect/can/map/map");
		 * var constructor = require("can-connect/constructor/constructor");
		 * var dataUrl = require("can-connect/data/url/url");
		 *
		 * var Todo = DefineMap.extend({
		 *   completed: "boolean",
		 *   complete: function(){
		 *     this.completed = true
		 *   }
		 * });
		 *
		 * var Todo.List = DefineList.extend({
		 *   "#": Todo,
		 *   completed: function(){
		 *     this.filter(function(todo){
		 *       return todo.completed;
		 *     });
		 *   }
		 * });
		 *
		 * var todoConnection = connect([dataUrl, constructor, canMap],{
		 *   Map: Todo,
		 *   List: Todo.List,
		 *   url: "/todos"
		 * });
		 *
		 * todoConnection.getList({}).then(function(list) {
		 *   list instanceOf Todo.List // true
		 * })
		 * ```
		 *
		 */

		/**
		 * @function can-connect/can/map/map.instance instance
		 * @parent can-connect/can/map/map.hydrators
		 *
		 * Creates a [can-connect/can/map/map._Map] instance given raw data.
		 *
		 * @signature `connection.instance(props)`
		 *
		 *   Create an instance of [can-connect/can/map/map._Map].
		 *
		 *   @param {Object} props the raw instance data.
		 *   @return [can-connect/can/map/map._Map] a [can-connect/can/map/map._Map] instance containing the `props`.
		 */
		instance: function(props){
			var _Map = this.Map;
			return new _Map(props);
		},

		/**
		 * @function can-connect/can/map/map.list list
		 * @parent can-connect/can/map/map.hydrators
		 *
		 * Creates a [can-connect/can/map/map._List] instance given raw data.
		 *
		 * @signature `connection.list(listData, set)`
		 *
		 *   Creates an instance of [can-connect/can/map/map._List] if available, otherwise creates
		 *   [can-connect/can/map/map._Map].List if available.
		 *
		 *   This will add properties on the raw `listData` array to the created list instance. e.g:
		 *   ```js
		 *   var listData = [{id: 1, name:"do dishes"}, ...];
		 *   listData.loadedFrom; // "shard 5"
		 *
		 *   var todoList = todoConnection.list(listData, {});
		 *   todoList.loadedFrom; // "shard 5"
		 *   ```
		 *
		 *   @param {can-connect.listData} listData the raw list data.
		 *   @param {can-query-logic/query} query the set the data belongs to.
		 *   @return {can-connect.List} a [can-connect/can/map/map._List] instance containing instances of
		 *   [can-connect/can/map/map._Map] built from the list items in `listData`.
		 */
		list: function(listData, set){
			var _List = this.List || (this.Map && this.Map.List);
			var list = canReflect_1_19_2_canReflect.new(_List, listData.data);
			canReflect_1_19_2_canReflect.eachKey(listData, function (val, prop) {
				if (prop !== 'data') {
					canReflect_1_19_2_canReflect.setKeyValue(list, prop, val);
				}
			});

			list[this.listQueryProp] = set;
			return list;
		},

		/**
		 * @function can-connect/can/map/map.updatedList updatedList
		 * @parent can-connect/can/map/map.instance-callbacks
		 *
		 * Implements the [can-connect/constructor/constructor.updatedList] callback so it updates the list and it's items
		 * during a single [can-event/batch/batch batched event].
		 *
		 * @signature `connection.updatedList(list, listData, set)`
		 *
		 *   Updates the list and the items within it during a single [can-event/batch/batch batched event].
		 *
		 *   @param {can-connect.List} list the list to be updated.
		 *   @param {can-connect.listData} listData raw list data.
		 *   @param {can-query-logic/query} query the set of the list being updated.
		 */
		updatedList: function(list, listData, set){
			canQueues_1_3_2_canQueues.batch.start();
			var enqueueOptions = {};
			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				enqueueOptions = {
    				reasonLog: ["set", set,"list", list,"updated with", listData]
  				};
			}
			//!steal-remove-end

			canQueues_1_3_2_canQueues.mutateQueue.enqueue(baseConnection.updatedList, this, arguments, enqueueOptions);
			canQueues_1_3_2_canQueues.batch.stop();

		},
		save: function(instance){
			canReflect_1_19_2_canReflect.setKeyValue(instance, "_saving", true);
			//canEvent.dispatch.call(instance, "_saving", [true, false]);
			var done = function(){
				canReflect_1_19_2_canReflect.setKeyValue(instance, "_saving", false);
				//canEvent.dispatch.call(instance, "_saving", [false, true]);
			};
			var base = baseConnection.save.apply(this, arguments);
			base.then(done,done);
			return base;
		},
		destroy: function(instance){
			canReflect_1_19_2_canReflect.setKeyValue(instance, "_destroying", true);
			//canEvent.dispatch.call(instance, "_destroying", [true, false]);
			var done = function(){
				canReflect_1_19_2_canReflect.setKeyValue(instance, "_destroying", false);
				//canEvent.dispatch.call(instance, "_destroying", [false, true]);
			};
			var base = baseConnection.destroy.apply(this, arguments);
			base.then(done,done);
			return base;
		}
	};

	each([
		/**
		 * @function can-connect/can/map/map.createdInstance createdInstance
		 * @parent can-connect/can/map/map.instance-callbacks
		 *
		 * Implements the [can-connect/constructor/constructor.createdInstance] callback so it dispatches an event and
		 * updates the instance.
		 *
		 * @signature `connection.createdInstance(instance, props)`
		 *
		 *   Updates the instance with `props` and dispatches a "created" event on the instance and the instances's
		 *   constructor function ([can-connect/can/map/map._Map]).
		 *
		 *   Calls [can-connect/constructor/store/store.stores.moveCreatedInstanceToInstanceStore] to ensure new instances
		 *   are moved into the [can-connect/constructor/store/store.instanceStore] after being saved.
		 *
		 *   @param {can-connect/can/map/map._Map} instance a [can-connect/can/map/map._Map] instance
		 *   @param {Object} props the data in the response from [can-connect/connection.createData]
		 */
		"created",
		/**
		 * @function can-connect/can/map/map.updatedInstance updatedInstance
		 * @parent can-connect/can/map/map.instance-callbacks
		 *
		 * Implements the [can-connect/constructor/constructor.updatedInstance] callback so it dispatches an event and
		 * updates the instance.
		 *
		 * @signature `connection.updatedInstance(instance, props)`
		 *
		 *   Updates the instance with `props` and dispatches an "updated" event on the instance and the instances's
		 *   constructor function ([can-connect/can/map/map._Map]).
		 *
		 *   @param {can-connect/can/map/map._Map} instance a [can-connect/can/map/map._Map] instance
		 *   @param {Object} props the data in the response from [can-connect/connection.updateData]
		 */
		"updated",
		/**
		 * @function can-connect/can/map/map.destroyedInstance destroyedInstance
		 * @parent can-connect/can/map/map.instance-callbacks
		 *
		 * Implements the [can-connect/constructor/constructor.destroyedInstance] callback so it dispatches an event and
		 * updates the instance.
		 *
		 * @signature `connection.destroyedInstance(instance, props)`
		 *
		 *   Updates the instance with `props` and dispatches a "destroyed" event on the instance and the instances's
		 *   constructor function ([can-connect/can/map/map._Map]).
		 *
		 *   @param {can-connect/can/map/map._Map} instance a [can-connect/can/map/map._Map] instance
		 *   @param {Object} props the data in the response from [can-connect/connection.destroyData]
		 */
		"destroyed"
	], function (funcName) {
		// Each of these is pretty much the same, except for the events they trigger.
		behavior[funcName+"Instance"] = function (instance, props) {

			// Update attributes if attributes have been passed
			if(props && typeof props === 'object') {

				if(funcName === "destroyed" && canReflect_1_19_2_canReflect.size(props) === 0) {
					// If destroy is passed an empty object, ignore update
					// This isn't tested except by can-rest-model.
				} else {
					if(this.constructor.removeAttr) {
						updateDeepExceptIdentity(instance, props, this.queryLogic.schema);
					}
					// this is legacy
					else if(this.updateInstanceWithAssignDeep){
						assignDeepExceptIdentity(instance, props, this.queryLogic.schema);
					}
					else {
						smartMergeExceptIdentity( instance, props, this.queryLogic.schema);
					}
				}

			}
			// This happens in constructor/store, but we don't call base, so we have to do it ourselves.
			if(funcName === "created" && this.moveCreatedInstanceToInstanceStore) {
				this.moveCreatedInstanceToInstanceStore(instance);
			}

			canMapBehavior.callbackInstanceEvents(funcName, instance);
		};
	});


	return behavior;

});

/**
 * @function can-connect/can/map/map.callbackInstanceEvents callbackInstanceEvents
 * @parent can-connect/can/map/map.static
 *
 * Utility function to dispatch events for instance callbacks, e.g. [can-connect/can/map/map.updatedInstance].
 *
 * @signature `connection.callbackInstanceEvents(cbName, instance)`
 *
 *   Used to dispatch events as part of instance callbacks implementations. This method could be useful in other
 *   behaviors that implement instance callbacks. E.g. a behavior overriding the
 *   [can-connect/can/map/map.updatedInstance `updatedInstance`] callback:
 *
 *   ```
 *   connect([canMap, {
 *       updatedInstance: function(instance, props) {
 *           instance = smartMerge(instance, props);
 *           canMapBehavior.callbackInstanceEvents("updated", instance);
 *       }
 *   }], {})
 *   ```
 *
 *   @param {String} eventName name of the the event to be triggered
 *   @param {can-connect/can/map/map._Map} instance a [can-connect/can/map/map._Map] instance.
 */
canMapBehavior.callbackInstanceEvents = function (funcName, instance) {
	var constructor = instance.constructor;

	// triggers change event that bubble's like
	// handler( 'change','1.destroyed' ). This is used
	// to remove items on destroyed from Model Lists.
	// but there should be a better way.
	canQueues_1_3_2_canQueues.batch.start();
	map$1.dispatch.call(instance, {type: funcName, target: instance});

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		if (this.id) {
			dev.log("can-connect/can/map/map.js - " + (constructor.shortName || this.name) + " " + this.id(instance) + " " + funcName);
		}
	}
	//!steal-remove-end

	// Call event on the instance's Class
	map$1.dispatch.call(constructor, funcName, [instance]);
	canQueues_1_3_2_canQueues.batch.stop();
};


var mapOverwrites = {
	static: {
		/**
		 * @function can-connect/can/map/map.getList getList
		 * @parent can-connect/can/map/map.map-static
		 *
		 * Retrieve a list of instance.
		 *
		 * @signature `Map.getList(query)`
		 *
		 * `.getList` is added to the configured [can-connect/can/map/map._Map] type. Retrieves a [can-connect/can/map/map._List] of
		 * [can-connect/can/map/map._Map] instances via the connection.
		 *
		 * ```js
		 * // import connection plugins
		 * var canMap = require("can-connect/can/map/map");
		 * var constructor = require("can-connect/constructor/constructor");
		 * var dataUrl = require("can-connect/data/url/url");
		 *
		 * // define connection types
		 * var Todo = DefineMap.extend({
		 *   id: "number",
		 *   complete: "boolean",
		 *   name: "string"
		 * });
		 *
		 * Todo.List = DefineList.extend({
		 *   completed: function() {
		 *     return this.filter(function(item) { return item.completed; });
		 *   }
		 * });
		 *
		 * // create connection
		 * connect([canMap, constructor, dataUrl],{
		 *   Map: Todo,
		 *   url: "/todos"
		 * })
		 *
		 * // retrieve instances
		 * Todo.getList({filter: {due: "today"}}).then(function(todos){
		 *   ...
		 * });
		 * ```
		 *
		 * @param {can-query-logic/query} query Definition of the list being retrieved.
		 * @return {Promise<Map>} `Promise` returning the [can-connect/can/map/map._List] of instances being retrieved
		 *
		 *
		 *
		 *
		 */
		getList: function (base, connection) {
			return function(set) {
				return connection.getList(set);
			};
		},
		/**
		 * @function can-connect/can/map/map.findAll findAll
		 * @parent can-connect/can/map/map.map-static
		 * @hide
		 *
		 * Alias of [can-connect/can/map/map.getList]. You should use `.getList()`.
		 */
		findAll: function (base, connection) {
			return function(set) {
				return connection.getList(set);
			};
		},
		/**
		 * @function can-connect/can/map/map.get get
		 * @parent can-connect/can/map/map.map-static
		 *
		 * Use it to get a single instance by id.
		 *
		 * @signature `Map.get(params)`
		 *
		 * `.get()` is added to the configured [can-connect/can/map/map._Map] type.
		 * Use it to get a single instance by the identity keys of the Map type.
		 *
		 * ```js
		 * // import connection plugins
		 * var canMap = require("can-connect/can/map/map");
		 * var constructor = require("can-connect/constructor/constructor");
		 * var dataUrl = require("can-connect/data/url/url");
		 *
		 * // define connection type
		 * var Todo = DefineMap.extend({
		 *   id: "number",
		 *   complete: "boolean",
		 *   name: "string"
		 * });
		 *
		 * // create connection
		 * connect([canMap, constructor, dataUrl],{
		 *   Map: Todo,
		 *   url: "/todos"
		 * })
		 *
		 * // retrieve instance
		 * Todo.get({id: 5}).then(function(todo){
		 *   ...
		 * });
		 * ```
		 *
		 * @param {Object} params Identifying parameters of the instance to retrieve. Typically, this is an object
		 * with the identity property and its value like: `{_id: 5}`.
		 * @return {Promise<Map>} `Promise` returning the [can-connect/can/map/map._Map] instance being retrieved
		 *
		 * @body
		 *
		 * ## Get a single record by filtering non-identity keys
		 *
		 * Sometimes, you want a single record, but by filtering non-identity keys.  Instead of using
		 * `.get`, use `.getList` like:
		 *
		 * ```js
		 * var firstCompleteTodo = Todo.getList({
		 *   filter: {complete: false},
		 *   page: {start: 0, end: 0}
		 * }).then(function(list){
		 *   return list.length ? list[0] : Promise.reject({message: "reject message"});
		 * });
		 * ```
		 *
		 */
		get: function (base, connection) {
			return function(params) {
				// adds .then for compat
				return connection.get(params);
			};
		},
		/**
		 * @function can-connect/can/map/map.findOne findOne
		 * @parent can-connect/can/map/map.map-static
		 * @hide
		 *
		 * Alias of [can-connect/can/map/map.get]. You should use `.get()`.
		 */
		findOne: function (base, connection) {
			return function(params) {
				// adds .then for compat
				return connection.get(params);
			};
		}
	},
	prototype: {
		isNew: function (base, connection) {
			/**
			 * @function can-connect/can/map/map.prototype.isNew isNew
			 * @parent can-connect/can/map/map.map
			 *
			 * If the data is not in the dat
			 *
			 * @signature `instance.isNew()`
			 *
			 * Returns if the instance has not been loaded from or saved to the data source.
			 *
			 * ```js
			 * connect([...],{
			 *   Map: Todo
			 * });
			 *
			 * var todo = new Todo();
			 * todo.isNew()   //-> true
			 *
			 * todo.save().then(function(){
			 *   todo.isNew() //-> false
			 * })
			 * ```
			 *
			 * @return {Boolean} Returns `true` if [can-connect/base/base.id] is `null` or `undefined`.
			 */
			return function () {
				return connection.isNew(this);
			};
		},

		isSaving: function (base, connection) {
			/**
			 * @function can-connect/can/map/map.prototype.isSaving isSaving
			 * @parent can-connect/can/map/map.map
			 *
			 * Returns if the instance is currently being saved.
			 *
			 * @signature `instance.isSaving()`
			 *
			 * Observes if a promise returned by [can-connect/connection.save `connection.save`] is in progress for this
			 * instance.  This is often used in a template like:
			 *
			 * ```html
			 * <button on:click="todo.save()"
			 *    disabled:from="todo.isSaving()">
			 *   Save Changes
			 * </button>
			 * ```
			 *
			 *   @return {Boolean} Returns `true` if [can-connect/connection.save `connection.save`] has been called for this
			 *   instance but the returned promise has not yet resolved.
			 */
			return function () {
				return !!canReflect_1_19_2_canReflect.getKeyValue(this,"_saving");
			};
		},

		isDestroying: function (base, connection) {
			/**
			 * @function can-connect/can/map/map.prototype.isDestroying isDestroying
			 * @parent can-connect/can/map/map.map
			 *
			 * Returns if the instance is currently being destroyed.
			 *
			 * @signature `instance.isDestroying()`
			 *
			 * Observes if a promise returned by [can-connect/connection.destroy `connection.destroy`] is in progress for this
			 * instance.  This is often used in a template like:
			 *
			 * ```html
			 * <button on:click="todo.destroy()"
			 *         disabled:from="todo.isDestroying()">
			 *   Delete
			 * </button>
			 * ```
			 *
			 *   @return {Boolean} `true` if [can-connect/connection.destroy `connection.destroy`] has been called for this
			 *   instance but the returned promise has not resolved.
			 */
			return function () {
				return !!canReflect_1_19_2_canReflect.getKeyValue(this,"_destroying");
			};
		},

		save: function (base, connection) {
			/**
			 * @function can-connect/can/map/map.prototype.save save
			 * @parent can-connect/can/map/map.map
			 *
			 * Save or update client data to the persisted data source.
			 *
			 * @signature `instance.save(success, error)`
			 *
			 * Calls [can-connect/connection.save].
			 *
			 * ```js
			 * // import connection plugins
			 * var canMap = require("can-connect/can/map/map");
			 * var constructor = require("can-connect/constructor/constructor");
			 * var dataUrl = require("can-connect/data/url/url");
			 *
			 * // define connection types
			 * var Todo = DefineMap.extend({
			 *   id: "number",
			 *   complete: "boolean",
			 *   name: "string"
			 * });
			 *
			 * // create connection
			 * connect([canMap, constructor, dataUrl], {
			 *   Map: Todo,
			 *   url: "/todos"
			 * })
			 *
			 * new Todo({name: "dishes"}).save();
			 * ```
			 *
			 *   @param {function} success A function that is called if the save is successful.
			 *   @param {function} error A function that is called if the save is rejected.
			 *   @return {Promise<Instance>} A promise that resolves to the instance if successful.
			 *
			 *
			 */
			return function(success, error){
				// return only one item for compatability
				var promise = connection.save(this);
				promise.then(success,error);
				return promise;
			};
		},
		destroy: function (base, connection) {
			/**
			 * @function can-connect/can/map/map.prototype.destroy destroy
			 * @parent can-connect/can/map/map.map
			 *
			 * Delete an instance from the service via the connection.
			 *
			 * @signature `instance.destroy(success, error)`
			 *
			 * Calls [can-connect/connection.destroy] for the `instance`.
			 *
			 * ```js
			 * // import connection plugins
			 * var canMap = require("can-connect/can/map/map");
			 * var constructor = require("can-connect/constructor/constructor");
			 * var dataUrl = require("can-connect/data/url/url");
			 *
			 * // define connection types
			 * var Todo = DefineMap.extend({
			 *   id: "number",
			 *   complete: "boolean",
			 *   name: "string"
			 * });
			 *
			 * // create connection
			 * connect([canMap, constructor, dataUrl],{
			 *   Map: Todo,
			 *   url: "/todos"
			 * })
			 *
			 * // read instance
			 * Todo.get({id: 5}).then(function(todo){
			 *   if (todo.complete) {
			 *     // delete instance
			 *     todo.destroy();
			 *   }
			 * });
			 * ```
			 *
			 * @param {function} success a function that is called if the [can-connect/connection.destroy] call is successful.
			 * @param {function} error a function that is called if the [can-connect/connection.destroy] call is rejected.
			 * @return {Promise<Instance>} a promise that resolves to the instance if successful
			 *
			 *
			 */
			return function(success, error){
				var promise = connection.destroy(this);
				promise.then(success,error);
				return promise;
			};
		}
	},
	properties: {
		_saving: {enumerable: false, value: false, configurable: true, writable: true},
		_destroying: {enumerable: false, value: false, configurable: true, writable: true}
	}
};

var listOverwrites = {
	static:  {
		_bubbleRule: function(base, connection) {
			return function(eventName, list) {
				var bubbleRules = base(eventName, list);
				bubbleRules.push('destroyed');
				return bubbleRules;
			};
		}
	},
	prototype: {
		setup: function(base, connection){
			return function (params) {
				// If there was a plain object passed to the List constructor,
				// we use those as parameters for an initial getList.
				if (isPlainObject(params) && !Array.isArray(params)) {
					this[connection.listQueryProp] = params;
					base.apply(this);
					this.replace(canReflect_1_19_2_canReflect.isPromise(params) ? params : connection.getList(params));
				} else {
					// Otherwise, set up the list like normal.
					base.apply(this, arguments);
				}
			};
		}
	},
	properties: {}
};

var overwrite = function( connection, Constructor, overwrites) {
	var prop;
	for(prop in overwrites.properties) {
		canReflect_1_19_2_canReflect.defineInstanceKey(Constructor, prop, overwrites.properties[prop]);
	}
	for(prop in overwrites.prototype) {
		Constructor.prototype[prop] = overwrites.prototype[prop](Constructor.prototype[prop], connection);
	}
	if(overwrites.static) {
		for(prop in overwrites.static) {
			Constructor[prop] = overwrites.static[prop](Constructor[prop], connection);
		}
	}
};

module.exports = canMapBehavior;

//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var validate$$1 = validate;

	module.exports = validate$$1(
		canMapBehavior,
		[
			'id', 'get', 'updatedList', 'destroy', 'save', 'getList'
		]
	);
}
//!steal-remove-end
});

var assign$3 = canReflect_1_19_2_canReflect.assignMap;


var WeakReferenceSet = function(){
	this.set = [];
};

// if weakmap, we can add and never worry ...
// otherwise, we need to have a count ...

assign$3(WeakReferenceSet.prototype,{

	has: function(item){
		return this._getIndex(item) !== -1;
	},
	addReference: function(item, referenceCount){

		var index = this._getIndex(item);
		var data = this.set[index];

		if(!data) {
			data = {
				item: item,
				referenceCount: 0
			};
			this.set.push(data);
		}
		data.referenceCount += (referenceCount || 1);
	},
	deleteReference: function(item){
		var index = this._getIndex(item);
		var data = this.set[index];
		if(data){
			data.referenceCount--;
			if( data.referenceCount === 0 ) {
				this.set.splice(index,1);
			}
		}
	},
	delete: function(item){
		var index = this._getIndex(item);
		if(index !== -1) {
			this.set.splice(index,1);
		}
	},
	get: function(item){
		var data = this.set[this._getIndex(item)];
		if(data) {
			return data.item;
		}
	},
	referenceCount: function(item) {
		var data = this.set[this._getIndex(item)];
		if(data) {
			return data.referenceCount;
		}
	},
	_getIndex: function(item){
		var index;
		this.set.every(function(data, i){
			if(data.item === item) {

				index = i;
				return false;
			}
			return true;
		});
		return index !== undefined ? index : -1;
	},
	/**
	 * @function can-connect/helpers/weak-reference-map.prototype.forEach forEach
	 * @signature `weakReferenceMap.forEach(callback)`
	 *
	 *   Calls `callback` for every value in the store.
	 *
	 *   @param  {function(*,String)} callback(item,key) A callback handler.
	 */
	forEach: function(cb){
		return this.set.forEach(cb);
	}
});

var weakReferenceSet = WeakReferenceSet;

var sortedSetJson = function(set){
	if(set == null) {
		return set;
	} else {
		return JSON.stringify(canReflect_1_19_2_canReflect.cloneKeySort(set));
	}

};

var store = createCommonjsModule(function (module) {
/**
 * @module {connect.Behavior} can-connect/constructor/store/store constructor/store
 * @parent can-connect.behaviors
 * @group can-connect/constructor/store/store.stores 0 stores
 * @group can-connect/constructor/store/store.callbacks 1 CRUD callbacks
 * @group can-connect/constructor/store/store.crud 2 CRUD methods
 * @group can-connect/constructor/store/store.hydrators 3 hydrators
 *
 * Adds support for keeping references to active lists and instances. Prevents different copies of an instance from
 * being used by the application at once. Allows other behaviors to look up instances currently active in the
 * application.
 *
 *
 * @signature `constructorStore( baseConnection )`
 *
 * Overwrites `baseConnection` so it contains a store for instances and lists.  This behavior:
 * - extends the [can-connect/constructor/store/store.hydrateInstance] and
 * [can-connect/constructor/store/store.hydrateList] methods to return instances or lists from the store, if available
 * - overwrites "CRUD" methods to make sure that while requests are pending, new lists and instances have references
 * kept in the store. This prevents duplicated instances from being created during concurrent requests.
 * - provides methods to add and remove items in the store by counting references
 *
 * @param {{}} baseConnection `can-connect` connection object that is having the `constructor/store` behavior added
 * on to it. Should already contain a behavior that provides the InstanceInteface
 * (e.g [can-connect/constructor/constructor]). If the `connect` helper is used to build the connection, the behaviors
 * will automatically be ordered as required.
 *
 * @return {Object} a `can-connect` connection containing the method implementations provided by `constructor/store`.
 *
 * @body
 *
 * ## Use
 *
 * The `constructor-store` behavior is used to:
 *  - provide a store of instances and lists in use by the client
 *  - prevent multiple instances from being generated for the same [can-connect/base/base.id] or multiple
 *    lists for the same [can-connect/base/base.listQuery].
 *
 * The store provides access to an instance by its [can-connect/base/base.id] or a list by its
 * [can-connect/base/base.listQuery]. This is used by other behaviors to lookup instances that should have changes applied.
 * Two examples, when there is a new instance that should be added to a list ([can-connect/real-time/real-time]) or
 * when newer data is available for a cached instance that is used in the page
 * ([can-connect/fall-through-cache/fall-through-cache]).
 *
 * Below you can see how `constructor-store`'s behavior be used to prevent multiple instances from being generated. This
 * example allows you to create multiple instances of a `todoEditor` that loads and edits a todo instance:
 *
 * @demo demos/can-connect/constructor-store.html
 *
 * You can see in this example that you can edit one todo and the other todos update.  This is because each `todoEditor`
 * is acting on same instance in memory. When it updates the todo's name here:
 *
 * ```
 * var updateData = function(newName) {
 *   todo.name = newName; // update name on todo instance
 *   ...
 * };
 * ```
 *
 * The other widgets update because they are bound to the same instance:
 *
 * ```
 * todo.on("name", updateElement); // when todo name changes update input element
 * todosConnection.addInstanceReference(todo); // previous line is a new usage of todo, so increase reference count
 * ```
 *
 * Each `todoEditor` receives the same instance because it was added to the
 * [can-connect/constructor/store/store.instanceStore connnection.instanceStore] by
 * [can-connect/constructor/store/store.addInstanceReference]. During all instance retrievals, a connection using the
 * `constructor/store` behavior checks the [can-connect/constructor/store/store.instanceStore] for an instance with a
 * matching `id` and return that if it exists. This example always requests `id: 5`, so all the `todoEditor`s use the
 * same instance held in the [can-connect/constructor/store/store.instanceStore].
 *
 * This widget cleans itself up when it is removed by removing the listener on the `todo` instance and
 * [can-connect/constructor/store/store.deleteInstanceReference reducing the instance reference count]:
 *
 * ```
 * todo.off("name", updateElement); // stop listening to todo name change
 * todosConnection.deleteInstanceReference(todo); // previous line removed a usage of todo, so reduce reference count
 * ```
 * This is done to prevent a memory leak produced by keeping instances in the `instanceStore` when they are no longer
 * needed by the application.
 *
 * **Note:** a hazard of sharing the same instance is that if new instance data is loaded from the server during
 * on-going editing of the instance, the new server data will replace the data that is edited but not yet saved.
 * This is because whenever data is loaded from the server, it is passed to
 * [can-connect/constructor/constructor.updatedInstance] which updates the shared instance properties with the new
 * server data.
 */






// shared across all connections
var pendingRequests = 0;
var noRequestsTimer = null;
var requests = {
	increment: function(connection){
		pendingRequests++;
		clearTimeout(noRequestsTimer);
	},
	decrement: function(connection){
		pendingRequests--;
		if(pendingRequests === 0) {
			noRequestsTimer = setTimeout(function(){
				requests.dispatch("end");
			},module.exports.requestCleanupDelay);
		}
		if(pendingRequests < 0) {
			pendingRequests = 0;
		}
	},
	count: function(){
		return pendingRequests;
	}
};
map$1(requests);


var constructorStore = canConnect_4_0_6_canConnect.behavior("constructor/store",function(baseConnection){

	var behavior = {
		/**
		 * @property {can-connect/helpers/weak-reference-map} can-connect/constructor/store/store.instanceStore instanceStore
		 * @parent can-connect/constructor/store/store.stores
		 *
		 * A mapping of instances keyed by their [can-connect/base/base.id].
		 *
		 * @type {can-connect/helpers/weak-reference-map}
		 *
		 * Stores instances by their [can-connect/base/base.id]. Holds instances based on reference counts which
		 * are incremented by [can-connect/constructor/store/store.addInstanceReference] and decremented by
		 * [can-connect/constructor/store/store.deleteInstanceReference]. Once a reference count is 0, the instance is no
		 * longer held in the store. Once a reference count is greater than 0, the instance is added to the store.
		 *
		 * ```js
		 * connection.addInstanceReference(todo5);
		 * connection.instanceStore.get("5") //-> todo5
		 * ```
		 */
		instanceStore: new weakReferenceMap(),
		// This really should be a set ... we just need it "weak" so we know how many references through binding
		// it has.
		newInstanceStore: new weakReferenceSet(),
		/**
		 * @property {can-connect/helpers/weak-reference-map} can-connect/constructor/store/store.listStore listStore
		 * @parent can-connect/constructor/store/store.stores
		 *
		 * A mapping of lists keyed by their [can-connect/base/base.listQuery].
		 *
		 * @type {can-connect/helpers/weak-reference-map}
		 *
		 * Stores lists by their [can-connect/base/base.listQuery]. Hold lists based on reference counts which are incremented
		 * by [can-connect/constructor/store/store.addListReference] and decremented by
		 * [can-connect/constructor/store/store.deleteListReference]. Once a reference count is 0, the list is no
		 * longer held in the store. Once a reference count is greater than 0, the list is added to the store.
		 *
		 * ```js
		 * connection.addInstanceReference(allTodos, {});
		 * connection.instanceStore.get({}) //-> allTodos
		 * ```
		 */
		listStore: new weakReferenceMap(),
		 // Set up the plain objects for tracking requested lists and instances for this connection,
		 // and add a handler to the requests counter to flush list and instance references when all
		 // requests have completed
		 //
		 // This function is called automatically when connect() is called on this behavior,
		 // and should not need to be called manually.
		init: function() {
			if(baseConnection.init) {
				baseConnection.init.apply(this, arguments);
			}

			if(!this.hasOwnProperty("_requestInstances")) {
				this._requestInstances = {};
			}
			if(!this.hasOwnProperty("_requestLists")) {
				this._requestLists = {};
			}

			requests.on("end", function onRequestsEnd_deleteStoreReferences(){
				var id;
				for(id in this._requestInstances) {
					this.instanceStore.deleteReference(id);
				}
				this._requestInstances = {};
				for(id in this._requestLists) {
					this.listStore.deleteReference(id);
					this._requestLists[id].forEach(this.deleteInstanceReference.bind(this));
				}
				this._requestLists = {};
			}.bind(this));
		},
		_finishedRequest: function(){
			requests.decrement(this);
		},

		/**
		 * @function can-connect/constructor/store/store.addInstanceReference addInstanceReference
		 * @parent can-connect/constructor/store/store.stores
		 *
		 * Add a reference to the [can-connect/constructor/store/store.instanceStore] so an instance can be easily looked up.
		 *
		 * @signature `connection.addInstanceReference( instance )`
		 * Adds a reference to an instance by [can-connect/base/base.id] to the [can-connect/constructor/store/store.instanceStore].
		 * Keeps a count of the number of references, removing the instance from the store when the count reaches 0.
		 *
		 * @param {can-connect/Instance} instance the instance to add
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * The [can-connect/constructor/store/store.instanceStore] contains a mapping of instances keyed by their
		 * [can-connect/base/base.id]. The [can-connect/constructor/store/store.instanceStore] is used to prevent creating
		 * the same instance multiple times, and for finding active instance for a given id.  Instances need to be added to
		 * this store for this to work.  To do this, call `addInstanceReference`:
		 *
		 * ```
		 * // a basic connection
		 * var constructorStore = require("can-connect/constructor/store/");
		 * var constructor = require("can-connect/constructor/");
		 * var dataUrl = require("can-connect/data/url/");
		 * var todoConnection = connect([dataUrl, constructorStore, constructor], {
		 *   url: "/todos"
		 * });
		 *
		 * var originalTodo;
		 *
		 * // get a todo
		 * todoConnection.get({id: 5}).then(function( todo ){
		 *   // add it to the store
		 *   todoConnection.addInstanceReference(todo);
		 *   originalTodo = todo;
		 * });
		 * ```
		 *
		 * Now, if you were to retrieve the same data sometime later, it would be the same instance:
		 *
		 * ```
		 * todoConnection.get({id: 5}).then(function( todo ){
		 *   todo === originalTodo // true
		 * });
		 * ```
		 *
		 * The `.getData` response data (underlying the call to `todoConnection.get`) is passed, along with the existing todo
		 * instance (`originalTodo`) to [can-connect/constructor/constructor.updatedInstance]. That updates the shared
		 * instance with the newly retrieved data.
		 *
		 * All the referenced instances are held in memory.  Use
		 * [can-connect/constructor/store/store.deleteInstanceReference] to remove them.
		 *
		 * Typically, `addInstanceReference` is called when something expresses interest in the instance, such
		 * as an event binding, and `deleteInstanceReference` is called when the interest is removed.
		 */
		addInstanceReference: function(instance, id) {
			var ID = id || this.id(instance);
			if(ID === undefined) {
				// save in the newInstanceStore store temporarily.
				this.newInstanceStore.addReference(instance);
			} else {
				this.instanceStore.addReference( ID, instance );
			}

		},

		/**
		 * @function can-connect/constructor/store/store.callbacks.createdInstance createdInstance
		 * @parent can-connect/constructor/store/store.callbacks
		 *
		 * Calls `createdInstance` on the underlying behavior and moves the new instance from the `newInstanceStore` to
		 * `instanceStore` if needed.
		 *
		 * @signature `connection.createdInstance( instance, props )`
		 * Calls the base behavior. Then calls [can-connect/constructor/store/store.stores.moveCreatedInstanceToInstanceStore]
		 * to move any pre-creation instance references to the standard instance reference store.
		 *
		 * @param {can-connect/Instance} instance the instance that was created
		 * @param {Object} props the data returned from [can-connect/connection.createData]
		 */
		createdInstance: function(instance, props){
			// when an instance is created, and it is in the newInstance store
			// transfer it to the instanceStore
			baseConnection.createdInstance.apply(this, arguments);
			this.moveCreatedInstanceToInstanceStore(instance);
		},

		/**
		 * @function can-connect/constructor/store/store.stores.moveCreatedInstanceToInstanceStore moveCreatedInstanceToInstanceStore
		 * @parent can-connect/constructor/store/store.stores
		 *
		 * Moves recently created instances into the [can-connect/constructor/store/store.instanceStore].
		 *
		 * @signature `moveCreatedInstanceToInstanceStore( instance )`
		 * Checks if an instance has an `id` and is in the `newInstanceStore`. If so, it adds it into the
		 * [can-connect/constructor/store/store.instanceStore] and removes it from the `newInstanceStore`.
		 *
		 * A new instances may have been added to the `newInstanceStore` if [can-connect/constructor/store/store.addInstanceReference]
		 * is called on is before the instance has been saved. This is done so we can keep track of references for unsaved
		 * instances and update the references to be keyed by `id` when one is available. Without this a request for a
		 * currently referenced instance that was just saved for the first time will erroneously result in a new instance.
		 *
		 * @param {can-connect/Instance} instance an instance.  If it was "referenced" (bound to) prior to
		 * being created, this will check for that condition and move this instance into the
		 * [can-connect/constructor/store/store.instanceStore].
		 */
		moveCreatedInstanceToInstanceStore: function(instance){
			var ID = this.id(instance);
			if(this.newInstanceStore.has(instance) && ID !== undefined) {
				var referenceCount = this.newInstanceStore.referenceCount(instance);
				this.newInstanceStore.delete(instance);
				this.instanceStore.addReference( ID, instance, referenceCount );
			}
		},
		addInstanceMetaData: function(instance, name, value){
			var data = this.instanceStore.set[this.id(instance)];
			if(data) {
				data[name] = value;
			}
		},
		getInstanceMetaData: function(instance, name){
			var data = this.instanceStore.set[this.id(instance)];
			if(data) {
				return data[name];
			}
		},
		deleteInstanceMetaData: function(instance, name){
			var data = this.instanceStore.set[this.id(instance)];

			delete data[name];
		},
		/**
		 * @function can-connect/constructor/store/store.deleteInstanceReference deleteInstanceReference
		 * @parent can-connect/constructor/store/store.stores
		 *
		 * Remove a reference from the [can-connect/constructor/store/store.instanceStore] so an instance can be garbage
		 * collected.
		 *
		 * @signature `connection.addInstanceReference( instance )`
		 * Decrements the number of references to an instance in the [can-connect/constructor/store/store.instanceStore].
		 * Removes the instance if there are no longer any references.
		 *
		 * @param {can-connect/Instance} instance the instance to remove
		 *
		 * ### Usage
		 *
		 * `deleteInstanceReference` is called to remove references to instances in the
		 * [can-connect/constructor/store/store.instanceStore] so that instances maybe garbage collected.  It's usually
		 * called when the application or some part of the application no longer is interested in an instance.
		 *
		 * [can-connect/constructor/store/store.addInstanceReference] has an example of adding an instance to the store.
		 * The following continues that example to remove the `originalTodo` instance from the store:
		 *
		 * ```
		 * todoConnection.deleteInstanceReference(originalTodo);
		 * ```
		 *
		 * Also see the [can-connect/constructor/store/store#Use usage example on the index page] for a more complete
		 * example of the lifecycle of a reference.
		 */
		deleteInstanceReference: function(instance) {
			var ID = this.id(instance);
			if(ID === undefined) {
				// if there is no id, remove this from the newInstanceStore
				this.newInstanceStore.deleteReference(instance);
			} else {
				this.instanceStore.deleteReference( this.id(instance), instance );
			}

		},
		/**
		 * @property {WeakReferenceMap} can-connect/constructor/store/store.addListReference addListReference
		 * @parent can-connect/constructor/store/store.stores
		 *
		 * Add a reference to the [can-connect/constructor/store/store.listStore] so a list can be easily looked up.
		 *
		 * @signature `connection.addListReference( list[, set] )`
		 * Adds a reference to a list by `set` (or by [can-connect/base/base.listQuery]) to the
		 * [can-connect/constructor/store/store.listStore].  Keeps a count of the number of references, removing the list
		 * from the store when the count reaches 0.
		 *
		 * @param {can-connect.List} list The list to add.
		 * @param {can-query-logic/query} [query] The set this list represents if it can't be identified with [can-connect/base/base.listQuery].
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * The [can-connect/constructor/store/store.listStore] contains a mapping of lists keyed by their `set`. The
		 * [can-connect/constructor/store/store.listStore] is used to prevent creating the same list multiple times and for
		 * identifying a list for a given set. Lists need to be added to this store for this to work.  To do this, call
		 * `addListReference`:
		 *
		 * ```
		 * // A basic connection:
		 * var constructorStore = require("can-connect/constructor/store/");
		 * var constructor = require("can-connect/constructor/");
		 * var dataUrl = require("can-connect/data/url/");
		 * var todoConnection = connect([dataUrl, constructorStore, constructor], {
		 *   url: "/todos"
		 * });
		 *
		 * var dueToday;
		 *
		 * // get a todo list
		 * todoConnection.getList({due: "today"}).then(function( todos ){
		 *   // add it to the store
		 *   todoConnection.addListReference(todos, {due: "today"});
		 *   dueToday = todos;
		 * });
		 * ```
		 *
		 * Now, if you were to retrieve the same set of data sometime later, it would be the same list instance:
		 *
		 * ```
		 * todoConnection.get({due: "today"}).then(function( todos ){
		 *   todos === dueToday //-> true
		 * });
		 * ```
		 *
		 * The `.getListData`  response data (underlying the call to `todoConnection.getList`) is passed, along with the
		 * existing list (`dueToday`) to [can-connect/constructor/constructor.updatedList]. That updates the shared list
		 * instance with the newly retrieved data.
		 *
		 * All the referenced lists stay in memory.  Use [can-connect/constructor/store/store.deleteListReference]
		 * to remove them.
		 *
		 * Typically, `addListReference` is called when something expresses interest in the list, such
		 * as an event binding, and `deleteListReference` is called when interest is removed.
		 *
		 */
		addListReference: function(list, set) {
			var id = sortedSetJson( set || this.listQuery(list) );
			if(id) {
				this.listStore.addReference( id, list );
				list.forEach(function(instance) {
					this.addInstanceReference(instance);
				}.bind(this));
			}
		},
		/**
		 * @function can-connect/constructor/store/store.deleteListReference deleteListReference
		 * @parent can-connect/constructor/store/store.stores
		 *
		 * Removes a reference from the [can-connect/constructor/store/store.listStore] so a list can can be garbage
		 * collected.
		 *
		 * @signature `connection.addInstanceReference( instance )`
		 * Decrements the number of references to a list in the [can-connect/constructor/store/store.listStore].
		 * Removes the list if there are no longer any references.
		 *
		 * @param {can-connect/Instance} list the list to remove
		 *
		 * ### Usage
		 *
		 * `deleteListReference` is called to remove references to instances in the
		 * [can-connect/constructor/store/store.listStore] so that lists maybe garbage collected.  It's usually called when
		 * the application or some part of the application no longer is interested in a list.
		 *
		 * [can-connect/constructor/store/store.addListReference] has an example of adding a list to the store.  The
		 * following continues that example to remove the `dueToday` list from the store:
		 *
		 * ```
		 * todoConnection.deleteListReference(dueToday);
		 * ```
		 *
		 * Also see the [can-connect/constructor/store/store#Use usage example on the index page] for a more complete
		 * example of the lifecycle of a reference.
		 */
		deleteListReference: function(list, set) {
			var id = sortedSetJson( set || this.listQuery(list) );
			if(id) {
				this.listStore.deleteReference( id, list );
				list.forEach(this.deleteInstanceReference.bind(this));
			}
		},
		/**
		 * @function can-connect/constructor/store/store.hydratedInstance hydratedInstance
		 * @parent can-connect/constructor/store/store.hydrators
		 *
		 * Keeps new instances in the [can-connect/constructor/store/store.instanceStore] for the lifetime of any
		 * concurrent requests.
		 *
		 * @signature `hydratedInstance(instance)`
		 * Adds a reference for new instances for the lifetime of any concurrent requests. Called when a new instance is
		 * created during [can-connect/constructor/store/store.hydrateInstance hydration]. This prevents concurrent requests
		 * for the same data from returning different instances.
		 *
		 * @param {can-connect/Instance} instance the newly hydrated instance
		 */
		// ## hydratedInstance
		hydratedInstance: function(instance){
			if( requests.count() > 0) {
				var id = this.id(instance);
				if(! this._requestInstances[id] ) {
					this.addInstanceReference(instance);
					this._requestInstances[id] = instance;
				}

			}
		},

		/**
		 * @function can-connect/constructor/store/store.hydrateInstance hydrateInstance
		 * @parent can-connect/constructor/store/store.hydrators
		 *
		 * Returns an instance given raw data, returning it from the [can-connect/constructor/store/store.instanceStore] if
		 * available.
		 *
		 * @signature `connection.hydrateInstance(props)`
		 * Overwrites the base `hydrateInstance` so that if a matching instance is in the
		 * [can-connect/constructor/store/store.instanceStore], that instance will be
		 * [can-connect/constructor/constructor.updatedInstance updated] with `props` and returned.  If there isn't a
		 * matching instance, the base `hydrateInstance` will be called.
		 *
		 * @param {Object} props the raw data used to create an instance
		 * @return {can-connect/Instance} a typed instance either created or updated with the data from `props`.
		 */
		hydrateInstance: function(props){
			var id = this.id(props);
			if((id || id === 0) && this.instanceStore.has(id) ) {
				var storeInstance = this.instanceStore.get(id);
				// TODO: find a way to prevent this from being called so many times.
				this.updatedInstance(storeInstance, props);
				return storeInstance;
			}
			var instance = baseConnection.hydrateInstance.call(this, props);
			this.hydratedInstance(instance);
			return instance;
		},

		/**
		 * @function can-connect/constructor/store/store.hydratedList hydratedList
		 * @parent can-connect/constructor/store/store.hydrators
		 *
		 * Keeps new lists in the [can-connect/constructor/store/store.listStore] for the lifetime of any concurrent
		 * requests.
		 *
		 * @signature `hydratedList(list)`
		 * Adds a reference for new lists for the lifetime of any concurrent requests. Called when a new list is
		 * created during [can-connect/constructor/store/store.hydrateList hydration]. This prevents concurrent requests
		 * for the same data from returning different instances.
		 *
		 * @param {can-connect.List} list the newly hydrated list
		 */
		hydratedList: function(list, set){
			if( requests.count() > 0) {
				var id = sortedSetJson( set || this.listQuery(list) );
				if(id) {
					if(! this._requestLists[id] ) {
						this.addListReference(list, set);
						this._requestLists[id] = list;
					}
				}
			}
		},

		/**
		 * @function can-connect/constructor/store/store.hydrateList hydrateList
		 * @parent can-connect/constructor/store/store.hydrators
		 *
		 * Returns a list given raw data, returning it from the [can-connect/constructor/store/store.listStore] if
		 * available.
		 *
		 * @signature `connection.hydrateList( listData, set )`
		 *
		 *   Overwrites the base `hydrateList` so that if a matching list is in the
		 *   [can-connect/constructor/store/store.listStore], that list will be
		 *   [can-connect/constructor/constructor.updatedList updated] with `listData` and returned.
		 *   If there isn't a matching list, the base `hydrateList` will be called.
		 *
		 *   @param {can-connect.listData} listData raw list data to hydrate into a list type
		 *   @param {can-query-logic/query} query the parameters that represent the set of data in `listData`
		 *   @return {List} a typed list from either created or updated with the data from `listData`
		 */
		hydrateList: function(listData, set){
			set = set || this.listQuery(listData);
			var id = sortedSetJson( set );

			if( id && this.listStore.has(id) ) {
				var storeList = this.listStore.get(id);
				this.updatedList(storeList, listData, set);
				return storeList;
			}
			var list = baseConnection.hydrateList.call(this, listData, set);
			this.hydratedList(list, set);
			return list;
		},

		/**
		 * @function can-connect/constructor/store/store.getList getList
		 * @parent can-connect/constructor/store/store.crud
		 *
		 * Extends the underlying [can-connect/connection.getList] so any [can-connect/constructor/store/store.hydrateInstance instances hydrated]
		 * or [can-connect/constructor/store/store.hydrateList lists hydrated] during this request are kept in the store until
		 * all the concurrent requests complete.
		 *
		 * @signature `connection.getList( set )`
		 * Increments an internal request counter so instances hydrated during this request will be stored, and then
		 * decrements the counter after the request is complete. This prevents concurrent requests for the same data from
		 * returning different instances.
		 *
		 * @param {can-query-logic/query} listQuery parameters specifying the list to retrieve
		 * @return {Promise<can-connect/Instance>} `Promise` returned by the underlying behavior's [can-connect/connection.getList]
		 */
		getList: function(listQuery) {
			var self = this;
			requests.increment(this);
			var promise = baseConnection.getList.call(this, listQuery);

			promise.then(function(instances){
				self._finishedRequest();
			}, function(){
				self._finishedRequest();
			});
			return promise;
		},

		/**
		 * @function can-connect/constructor/store/store.get get
		 * @parent can-connect/constructor/store/store.crud
		 *
		 * Extends the underlying [can-connect/connection.get] so any [can-connect/constructor/store/store.hydrateInstance instances hydrated]
		 * during this request are kept in the store until all the concurrent requests complete.
		 *
		 * @signature `connection.get( params )`
		 * Increments an internal request counter so instances hydrated during this request will be stored, and then
		 * decrements the counter after the request is complete. This prevents concurrent requests for the same data from
		 * returning different instances.
		 *
		 * @param {Object} params params used to specify which instance to retrieve.
		 * @return {Promise<can-connect/Instance>} `Promise` returned by the underlying behavior's [can-connect/connection.get]
		 */
		get: function(params) {
			var self = this;
			requests.increment(this);
			var promise = baseConnection.get.call(this, params);

			promise.then(function(instance){
				self._finishedRequest();
			}, function(){
				self._finishedRequest();
			});
			return promise;

		},
		/**
		 * @function can-connect/constructor/store/store.save save
		 * @parent can-connect/constructor/store/store.crud
		 *
		 * Extends the underlying [can-connect/connection.save] so any [can-connect/constructor/store/store.hydrateInstance instances hydrated]
		 * during this request are kept in the store until all the concurrent requests complete.
		 *
		 * @signature `connection.save( instance )`
		 *
		 * Increments an internal request counter so instances hydrated during this request will be stored, and then
		 * decrements the counter after the request is complete. This prevents concurrent requests for the same data from
		 * returning different instances.
		 *
		 * @param {Object} instance a typed instance being saved
		 * @return {Promise<can-connect/Instance>} `Promise` returned by the underlying behavior's [can-connect/connection.save]
		 */
		save: function(instance) {
			var self = this;
			requests.increment(this);

			var updating = !this.isNew(instance);
			if(updating) {
				this.addInstanceReference(instance);
			}

			var promise = baseConnection.save.call(this, instance);

			promise.then(function(instances){
				if(updating) {
					self.deleteInstanceReference(instance);
				}
				self._finishedRequest();
			}, function(){
				self._finishedRequest();
			});
			return promise;
		},
		/**
		 * @function can-connect/constructor/store/store.destroy destroy
		 * @parent can-connect/constructor/store/store.crud
		 *
		 * Extends the underlying [can-connect/connection.destroy] so any [can-connect/constructor/store/store.hydrateInstance instances hydrated]
		 * during this request are kept in the store until all the concurrent requests complete.
		 *
		 * @signature `connection.destroy( instance )`
		 * Increments an internal request counter so instances hydrated during this request will be stored, and then
		 * decrements the counter after the request is complete. This prevents concurrent requests for the same data from
		 * returning different instances.
		 *
		 * @param {Object} instance a typed instance being deleted
		 * @return {Promise<can-connect/Instance>} `Promise` returned by the underlying behavior's [can-connect/connection.destroy]
		 */
		destroy: function(instance) {
			var self = this;
			// Add to instance store, for the duration of the
			// destroy callback
			this.addInstanceReference(instance);
			requests.increment(this);
			var promise = baseConnection.destroy.call(this, instance);

			promise.then(function(instance){
				self._finishedRequest();
				self.deleteInstanceReference(instance);
			}, function(){
				self._finishedRequest();
			});
			return promise;

		},
		/**
		 * @function can-connect/constructor/store/store.updatedList updatedList
		 * @parent can-connect/constructor/store/store.callbacks
		 *
		 * Extends the underlying [can-connect/connection.updatedList] so any instances that have been added or removed
		 * from the list have their reference counts updated accordingly.
		 *
		 * @signature `connection.updatedList( list, listData, set )`
		 * Increments an internal request counter so instances on this list during this request will be stored, and decrements
		 * the same counter for all items previously on the list (found in `listData.data`).
		 *
		 * @param {can-connect.List} list a typed list of instances being updated
		 * @param {Object} listData an object representing the previous state of the list
		 * @param {Object} set the retrieval set used to get the list
		 */
		updatedList: function(list, listData, set) {
			var oldList = list.slice(0);
			if(!listData.data && typeof listData.length === "number") {
				listData = { data: listData };
			}
			if(baseConnection.updatedList) {
				baseConnection.updatedList.call(this, list, listData, set);
				list.forEach(function(instance) {
					this.addInstanceReference(instance);
				}.bind(this));
			} else if(listData.data) {
				listData.data.forEach(function(instance) {
					this.addInstanceReference(instance);
				}.bind(this));
			}
			oldList.forEach(this.deleteInstanceReference.bind(this));
		}
	};

	return behavior;

});
constructorStore.requests = requests;
// The number of ms to wait after all known requests have finished,
//  before starting request cleanup.
// If a new request comes in before timeout, wait until that request
//  has finished (+ delay) before starting cleanup.
// This is configurable, for use cases where more waiting is desired,
//  or for the can-connect tests which expect everything to clean up
//  in 1ms.
constructorStore.requestCleanupDelay = 10;

module.exports = constructorStore;

//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var validate$$1 = validate;
	module.exports = validate$$1(constructorStore, ['hydrateInstance', 'hydrateList', 'getList', 'get', 'save', 'destroy']);
}
//!steal-remove-end
});

var callbacks = createCommonjsModule(function (module) {
/**
 * @module can-connect/data/callbacks/callbacks data/callbacks
 * @parent can-connect.behaviors
 *
 * Extend [can-connect/DataInterface] methods to call callbacks with the raw response data.
 *
 * @signature `dataCallbacks( baseConnection )`
 *
 * Extends the [can-connect/DataInterface] create, update, read & delete methods to call 'callback' methods following
 * their execution. Callbacks are called with the data returned from the underlying behavior's [can-connect/DataInterface]
 * implementation.
 *
 * For example:
 * ```
 * var dataUrl = require("can-connect/data/url/");
 * var dataCallbacks = require("can-connect/data/url");
 * var logging = {
 *   createdData: function(responseData) {
 *     console.log('New Todo Saved: ', responseData);
 *     return responseData;
 *   }
 * };
 * var todoConnection = connect([dataUrl, dataCallbacks, logging}],  {
 *   url: '/todos'
 * });
 *
 * // create a new todo
 * todoConnection.createData({name: "do the dishes", completed: false}).then(function(responseData) {
 *   responseData; // {id: 5}
 * });
 *
 * // after create request is completed, following is logged by the "logging" createdData callback:
 * // > New Todo Saved: {id: 5}
 * ```
 *
 * @param {{}} baseConnection `can-connect` connection object that is having the `data/callbacks` behavior added
 * on to it. Should already contain a behavior that provides the DataInterface (e.g [can-connect/data/url/url]). If
 * the `connect` helper is used to build the connection, the behaviors will automatically be ordered as required.
 *
 * @return {{}} a `can-connect` connection containing the method implementations provided by `data/callbacks`.
 */

var each = canReflect_1_19_2_canReflect.each;

// wires up the following methods
var pairs = {
	/**
	 * @function can-connect/data/callbacks/callbacks.getListData getListData
	 * @parent can-connect/data/callbacks/callbacks
	 *
	 * Call `gotListData` with the data returned from underlying behavior's implementation of
	 * [can-connect/connection.gotListData].
	 *
	 * @signature `getListData(listQuery)`
	 *
	 *   Extends the underlying behavior's [can-connect/connection.getListData] to call `gotListData` with the returned
	 *   response data. The result of the call to `gotListData` will be used as the new response data.
	 *
	 *   @param {Object} listQuery an object that represents the set of data to be loaded
	 *   @return {Promise<Object>} `Promise` resolving the raw response data, possibly modified by `gotListData`.
	 */
	getListData: "gotListData",

	/**
	 * @function can-connect/data/callbacks/callbacks.createData createData
	 * @parent can-connect/data/callbacks/callbacks
	 *
	 * Call `createdData` with the data returned from underlying behavior's implementation of
	 * [can-connect/connection.createData].
	 *
	 * @signature `createData(instanceData, cid)`
	 *
	 *   Extends the underlying behavior's [can-connect/connection.createData] to call `createdData` with the returned
	 *   response data. The result of the call to `createdData` will be used as the new response data.
	 *
	 *   @param {Object} instanceData the raw data of an instance
	 *   @param {Number} cid unique id that represents the instance that is being created
	 *   @return {Promise<Object>} `Promise` resolving the raw response data, possibly modified by `createdData`.
	 */
	createData: "createdData",

	/**
	 * @function can-connect/data/callbacks/callbacks.updateData updatedData
	 * @parent can-connect/data/callbacks/callbacks
	 *
	 * Call `updatedData` with the data returned from underlying behavior's implementation of
	 * [can-connect/connection.updateData].
	 *
	 * @signature `updateData(instanceData)`
	 *
	 *   Extends the underlying behavior's [can-connect/connection.updateData] to call `updatedData` with the returned
	 *   response data. The result of the call to `updatedData` will be used as the new response data.
	 *
	 *   @param {Object} instanceData the raw data of an instance
	 *   @return {Promise<Object>} `Promise` resolving the raw response data, possibly modified by `updatedData`.
	 */
	updateData: "updatedData",

	/**
	 * @function can-connect/data/callbacks/callbacks.destroyData destroyData
	 * @parent can-connect/data/callbacks/callbacks
	 *
	 * Call `destroyedData` with the data returned from underlying behavior's implementation of
	 * [can-connect/connection.destroyData].
	 *
	 * @signature `destroyData(params, cid)`
	 *
	 *   Extends the underlying behavior's [can-connect/connection.destroyData] to call `destroyedData` with the returned
	 *   response data. The result of the call to `destroyedData` will be used as the new response data.
	 *
	 *   @param {Object} instanceData the raw data of an instance
	 *   @return {Promise<Object>} `Promise` resolving the raw response data, possibly modified by `destroyedData`.
	 */
	destroyData: "destroyedData"
};

var dataCallbackBehavior = canConnect_4_0_6_canConnect.behavior("data/callbacks",function(baseConnection){

	var behavior = {
	};

	// overwrites createData to createdData
	each(pairs, function(callbackName, name){

		behavior[name] = function(params, cid){
			var self = this;

			return baseConnection[name].call(this, params).then(function(data){
				if(self[callbackName]) {
					return self[callbackName].call(self,data, params, cid );
				} else {
					return data;
				}
			});
		};

	});
	return behavior;
});

module.exports = dataCallbackBehavior;

//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var validate$$1 = validate;
	module.exports = validate$$1(dataCallbackBehavior, [
		"getListData", "createData", "updateData", "destroyData"
	]);
}
//!steal-remove-end
});

/**
 * @module {connect.Behavior} can-connect/data/parse/parse
 * @parent can-connect.behaviors
 *
 * Extract response data into a format needed for other extensions.
 *
 * @signature `dataParse( baseConnection )`
 *
 *   Overwrites the [can-connect/DataInterface] methods to run their results through
 *   either [can-connect/data/parse/parse.parseInstanceData] or [can-connect/data/parse/parse.parseListData].
 *
 *   @param {{}} baseConnection The base connection.
 *
 * @body
 *
 * ## Use
 *
 * `data/parse` is used to modify the response data of "data interface" methods to comply with what
 * is expected by "instance interface" methods.  For example, if a service was returning list data
 * at the `/services/todos` url like:
 *
 * ```
 * {
 *   todos: [
 *     {todo: {id: 0, name: "dishes"}},
 *     {todo: {id: 2, name: "lawn"}}
 *   ]
 * }
 * ```
 *
 * That service does not return [can-connect.listData] in the right format which should look like:
 *
 * ```
 * {
 *   data: [
 *     {id: 0, name: "dishes"},
 *     {id: 2, name: "lawn"}
 *   ]
 * }
 * ```
 *
 * To correct this, you can configure `data-parse` to use the [can-connect/data/parse/parse.parseListProp] and [can-connect/data/parse/parse.parseInstanceProp]
 * as follows:
 *
 * ```
 * connect([
 *   require("can-connect/data/parse/parse"),
 *   require("can-connect/data/url/url")
 * ],{
 *  parseListProp: "todos",
 *  parseInstanceProp: "todo"
 * })
 * ```
 *
 */
var each$1 = canReflect_1_19_2_canReflect.each;



var parse$1 = canConnect_4_0_6_behavior("data/parse",function(baseConnection){

	var behavior = {
    /**
     * @function can-connect/data/parse/parse.parseListData parseListData
     * @parent can-connect/data/parse/parse
     *
     * @description Given a response from [can-connect/connection.getListData] returns its data in the
     * proper [can-connect.listData] format.
     *
     * @signature `connection.parseListData(responseData)`
     *
     *   This function uses [can-connect/data/parse/parse.parseListProp] to find the array
     *   containing the data for each instance.  Then it uses [can-connect/data/parse/parse.parseInstanceData]
     *   on each item in the array  Finally, it returns data in the
     *   [can-connect.listData] format.
     *
     *   @param {Object} responseData The response data from the AJAX request.
     *
     *   @return {can-connect.listData} An object like `{data: [props, props, ...]}`.
     *
     * @body
     *
     * ## Use
     *
     * `parseListData` comes in handy when dealing with an irregular API
     * that can be improved with data transformation.
     *
     * Suppose an endpoint responds with a status of 200 OK, even when the
     * request generates an empty result set. Worse yet, instead of representing
     * an emtpy set with an empty list, it removes the property.
     *
     * A request to `/services/todos` may return:
     *
     * ```js
     * {
     *   todos: [
     *     {todo: {id: 0, name: "dishes"}},
     *     {todo: {id: 2, name: "lawn"}}
     *   ]
     * }
     * ```
     *
     * What if a request for `/services/todos?filterName=bank` responds with
     * 200 OK:
     *
     * ```
     * {
     * }
     * ```
     *
     * This response breaks its own schema. One way to bring it in line
     * with a format compatible with [can-connect.listData] is:
     *
     * ```js
     * connect([
     *   require("can-connect/data/parse/parse"),
     *   require("can-connect/data/url/url")
     * ],{
     *   parseListProp: "todos",
     *   parseListData(responseData) {
     *     if (responseData && !responseData.todos) {
     *       responseData = { todos: [] };
     *     }
     *
     *     return responseData;
     *   }
     * })
     * ```
     */
		parseListData: function( responseData ) {

			// call any base parseListData
			if(baseConnection.parseListData) {
			   responseData = baseConnection.parseListData.apply(this, arguments);
			}

			var result;
			if( Array.isArray(responseData) ) {
				result = {data: responseData};
			} else {
				var prop = this.parseListProp || 'data';

				responseData.data = get_1(responseData, prop);
				result = responseData;
				if(prop !== "data") {
					delete responseData[prop];
				}
				if(!Array.isArray(result.data)) {
					throw new Error('Could not get any raw data while converting using .parseListData');
				}

			}
			var arr = [];
			for(var i =0 ; i < result.data.length; i++) {
				arr.push( this.parseInstanceData(result.data[i]) );
			}
			result.data = arr;
			return result;
		},
    /**
     * @function can-connect/data/parse/parse.parseInstanceData parseInstanceData
     * @parent can-connect/data/parse/parse
     *
     * @description Returns the properties that should be used to [can-connect/constructor/constructor.hydrateInstance make an instance]
     * given the results of [can-connect/connection.getData], [can-connect/connection.createData], [can-connect/connection.updateData],
     * and [can-connect/connection.destroyData].
     *
     * @signature `connection.parseInstanceData(responseData)`
     *
     *   This function will use [can-connect/data/parse/parse.parseInstanceProp] to find the data object
     *   representing the instance that will be created.
     *
     *   @param {Object} responseData The response data from [can-connect/connection.getData], [can-connect/connection.createData], or [can-connect/connection.updateData].
     *
     *   @return {Object} The data that should be passed to [can-connect/constructor/constructor.hydrateInstance].
     *
     * @body
     *
     * ## Use
     *
     * `parseInstanceData` comes in handy when dealing with an irregular API
     * that can be improved with data transformation.
     *
     * Suppose a request to `/services/todos` returns:
     * ```
     * {
     *   baseUrl: "/proxy/share",
     *   todo: {
     *     id: 0,
     *     name: "dishes",
     *     friendFaceUrl: "friendface?id=0",
     *     fiddlerUrl: "fiddler?id=0"
     *   }
     * }
     * ```
     *
     * The baseUrl property is meta-data that needs to be incorporated into the
     * instance data. One way to deal with this is:
     *
     * ```
     * connect([
     *   require("can-connect/data/parse/parse"),
     *   require("can-connect/data/url/url")
     * ],{
     *   parseInstanceProp: "todo",
     *   parseInstanceData(responseData) {
     *     ['friendFaceUrl', 'fiddlerUrl'].map(urlProp => {
     *       responseData.todo[urlProp] = [
     *         responseData.baseUrl,
     *         responseData.todo[urlProp]
     *       ].join('/');
     *     });
     *
     *     return responseData;
     *   }
     * })
     * ```
     *
     * This results in an object like:
     *
     * ```js
     * {
     *   id: 0,
     *   name: "dishes",
     *   friendFaceUrl: "/proxy/share/friendface?id=0",
     *   fiddlerUrl: "/proxy/share/fiddler?id=0"
     * }
     * ```
     */
		parseInstanceData: function( props ) {
			// call any base parseInstanceData
			if(baseConnection.parseInstanceData) {
				// It's possible this might be looking for a property that only exists in some
				// responses. So if it doesn't return anything, go back to using props.
			   props = baseConnection.parseInstanceData.apply(this, arguments) || props;
			}
			return this.parseInstanceProp ? get_1(props, this.parseInstanceProp) || props : props;
		}
		/**
		 * @property {String} can-connect/data/parse/parse.parseListProp parseListProp
		 * @parent can-connect/data/parse/parse
		 *
		 * The property to find the array-like data that represents each instance item.
		 *
		 * @option {String} [can-connect/data/parse/parse.parseListData] uses this property to find an array-like data struture
		 * on the result of [can-connect/connection.getListData].
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * Set `parseListProp` if your response data does not look like: `{data: [props, props]}`.
		 *
		 * For example, if [can-connect/connection.getListData] returns data like:
		 *
		 * ```
		 * {
		 * 	  todos: [{id: 1, name: "dishes"}, {id: 2, name: "lawn"}]
		 * }
		 * ```
		 *
		 * Set `parseListProp` to `"todos"` like:
		 *
		 * ```
		 * connect([
         *   require("can-connect/data/parse/parse"),
         *   require("can-connect/data/url/url")
         * ],{
		 *   url : "/todos",
		 *   parseListProp: "todos"
		 * });
		 * ```
		 *
		 */
		/**
		 * @property {String} can-connect/data/parse/parse.parseInstanceProp parseInstanceProp
		 * @parent can-connect/data/parse/parse
		 *
		 * The property to find the data that represents an instance item.
		 *
		 * @option {String} [can-connect/data/parse/parse.parseInstanceData] uses this property's value to
		 * [can-connect/constructor/constructor.hydrateInstance make an instance].
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * Set `parseInstanceData` if your response data does not directly contain the data you would like to pass to
		 * [connection.hydrateInstance].
		 *
		 * For example, if [can-connect/connection.getData] returns data like:
		 *
		 * ```
		 * {
		 *   todo: {
		 * 	   id: 1,
		 *     name: "dishes"
		 *   }
		 * }
		 * ```
		 *
		 * Set `parseInstanceProp` to `"todo"` like:
		 *
		 * ```
		 * connect([
         *   require("can-connect/data/parse/parse"),
         *   require("can-connect/data/url/url")
         * ],{
		 *   url : "/todos",
		 *   parseInstanceProp: "todo"
		 * });
		 * ```
		 */

	};

	each$1(pairs, function(parseFunction, name){
		behavior[name] = function(params){
			var self = this;
			return baseConnection[name].call(this, params).then(function(){
				return self[parseFunction].apply(self, arguments);
			});
		};
	});

	return behavior;

});

var pairs = {
	getListData: "parseListData",
	getData: "parseInstanceData",
	createData: "parseInstanceData",
	updateData: "parseInstanceData",
	destroyData: "parseInstanceData"
};

/**
 * @module {function} can-ajax can-ajax
 * @parent can-dom-utilities
 * @collection can-infrastructure
 * @package ./package.json
 *
 * Make an asynchronous HTTP (AJAX) request.
 *
 * @signature `ajax( ajaxOptions )`
 *
 *    Is used to make an asynchronous HTTP (AJAX) request similar to [jQuery.ajax()](http://api.jquery.com/jQuery.ajax/).
 *
 *    ```js
 *    import { ajax } from "can";
 *
 *    ajax({
 *      url: "http://query.yahooapis.com/v1/public/yql",
 *      data: {
 *        format: "json",
 *        q: 'select * from geo.places where text="sunnyvale, ca"'
 *      }
 *    }).then(function(response){
 *      console.log( response.query.count ); // => 2
 *    });
 *    ```
 *
 *    @param {Object} ajaxOptions Configuration options for the AJAX request.
 *      - __url__ `{String}` The requested url.
 *      - __type__ `{String}` The method of the request. Ex: `GET`, `PUT`, `POST`, etc. Capitalization is ignored. _Default is `GET`_.
 *      - __data__ `{Object}` The data of the request. If data needs to be urlencoded (e.g. for GET requests or for CORS) it is serialized with [can-param].
 *      - __dataType__ `{String}` Type of data. _Default is `json`_.
 *      - __crossDomain__ `{Boolean}` If you wish to force a crossDomain request (such as JSONP) on the same domain, set the value of crossDomain to true. This allows, for example, server-side redirection to another domain. Default: `false` for same-domain requests, `true` for cross-domain requests.
 *      - __xhrFields__ `{Object}` Any fields to be set directly on the xhr request, [https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest] such as the withCredentials attribute that indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies or authorization headers.
 *      - __beforeSend__ `{callback}` A pre-request callback function that can be used to modify the XHR object before it is sent. Use this to set custom headers, etc. The XHR and settings objects are passed as arguments.
 *      - __success__ `{callback}` A callback passed the response body when the request completes without error.  Using the promise returned from ajax() should be preferred to passing a success callback
 *      - __error__ `{callback}` A callback passed the XHR object when the request fails to complete correctly.  Using the promise returned from ajax() should be preferred to passing an error callback
 *      - __async__ `{Boolean}` Set `async` to `false` to create a synchronous XHR that blocks the thread until the request completes. success() or error() is called synchronously on completion, but promise callbacks are still resolved asychronously.  Synchronous AJAX calls are **not recommended** and are only supported here for legacy reasons.
 * 
 *    @return {Promise} A Promise that resolves to the data. The Promise instance is abortable and exposes an `abort` method. Invoking abort on the Promise instance indirectly rejects it.
 *
 *
 * @signature `ajaxSetup( ajaxOptions )`
 *
 *    Is used to persist ajaxOptions across all ajax requests and they can be over-written in the ajaxOptions of the actual request.
 *    [https://api.jquery.com/jquery.ajaxsetup/]
 *
 *    ```js
 *    import { ajax } from "can";
 *
 *    ajax.ajaxSetup({xhrFields: {withCredentials: true}});
 *
 *    ajax({
 *      url: "http://query.yahooapis.com/v1/public/yql",
 *      data: {
 *        format: "json",
 *        q: 'select * from geo.places where text="sunnyvale, ca"'
 *      }
 *    }).then(function(response){
 *      console.log( response.query.count ); // => 2
 *    });
 *    ```
 */

// from https://gist.github.com/mythz/1334560
var xhrs = [
		function () { return new XMLHttpRequest(); },
		function () { return new ActiveXObject("Microsoft.XMLHTTP"); },
		function () { return new ActiveXObject("MSXML2.XMLHTTP.3.0"); },
		function () { return new ActiveXObject("MSXML2.XMLHTTP"); }
	],
	_xhrf = null;
// used to check for Cross Domain requests
var originUrl = canParseUri_1_2_2_canParseUri(global_1().location.href);

var globalSettings = {};

var makeXhr = function () {
	if (_xhrf != null) {
		return _xhrf();
	}
	for (var i = 0, l = xhrs.length; i < l; i++) {
		try {
			var f = xhrs[i], req = f();
			if (req != null) {
				_xhrf = f;
				return req;
			}
		} catch (e) {
			continue;
		}
	}
	return function () { };
};

var contentTypes = {
	json: "application/json",
	form: "application/x-www-form-urlencoded"
};

var _xhrResp = function (xhr, options) {

	try{
		var type = (options.dataType || xhr.getResponseHeader("Content-Type").split(";")[0]);
		
		if(type && (xhr.responseText || xhr.responseXML)){
			
			switch (type) {
				case "text/xml":
				case "xml":
					return xhr.responseXML;
				case "text/json":
				case "application/json":
				case "text/javascript":
				case "application/javascript":
				case "application/x-javascript":
				case "json":
					return xhr.responseText && JSON.parse(xhr.responseText);
				default:
					return xhr.responseText;
			}
		} else {
			return xhr;
		}
	} catch(e){
		return xhr;
	}
};

function ajax(o) {
	var xhr = makeXhr(), timer, n = 0;
	var deferred = {}, isFormData;
	var promise = new Promise(function(resolve,reject){
		deferred.resolve = resolve;
		deferred.reject = reject;
	});
	var requestUrl;
	var isAborted = false;

	promise.abort = function () {
		isAborted = true;
		xhr.abort();
	};

	o = [{
			userAgent: "XMLHttpRequest",
			lang: "en",
			type: "GET",
			data: null,
			dataType: "json"
	}, globalSettings, o].reduce(function(a,b,i) {
		return canReflect_1_19_2_canReflect.assignDeep(a,b);
	});

	var async = o.async !== false;

	// Set the default contentType
	if(!o.contentType) {
		o.contentType = o.type.toUpperCase() === "GET" ?
			contentTypes.form : contentTypes.json;
	}
	//how jquery handles check for cross domain
	if(o.crossDomain == null){
		try {
			requestUrl = canParseUri_1_2_2_canParseUri(o.url);
			o.crossDomain = !!((requestUrl.protocol && requestUrl.protocol !== originUrl.protocol) ||
				(requestUrl.host && requestUrl.host !== originUrl.host));

		} catch (e){
			o.crossDomain = true;
		}
	}
	if (o.timeout) {
		timer = setTimeout(function () {
			xhr.abort();
			if (o.timeoutFn) {
				o.timeoutFn(o.url);
			}
		}, o.timeout);
	}
	xhr.onreadystatechange = function () {
	
		try {
			if (xhr.readyState === 4) {
				if (timer) {
					clearTimeout(timer);
				}
				if (xhr.status < 300) {
					if (o.success) {
						o.success( _xhrResp(xhr, o) );
					}
				}
				else if (o.error) {
					o.error(xhr, xhr.status, xhr.statusText);
				}
				if (o.complete) {
					o.complete(xhr, xhr.statusText);
				}

				if (xhr.status >= 200 && xhr.status < 300) {
					deferred.resolve( _xhrResp(xhr, o) );
				} else {
					deferred.reject( _xhrResp(xhr, o) );
				}
			}
			else if (o.progress) {
				o.progress(++n);
			}
		} catch(e) {
			deferred.reject(e);
		}
	};
	var url = o.url, data = null, type = o.type.toUpperCase();
	var isJsonContentType = o.contentType === contentTypes.json;
	var isPost = type === "POST" || type === "PUT" || type === "PATCH";
	if (!isPost && o.data) {
		url += "?" + (isJsonContentType ? JSON.stringify(o.data) : canParam_1_2_0_canParam(o.data));
	}
	xhr.open(type, url, async);
	// For CORS to send a "simple" request (to avoid a preflight check), the following methods are allowed: GET/POST/HEAD,
	// see https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#Simple_requests

	var isSimpleCors = o.crossDomain && ['GET', 'POST', 'HEAD'].indexOf(type) !== -1;
	isFormData = typeof FormData !== "undefined" && o.data instanceof FormData;

	if (isPost) {
		if (isFormData) {
			// do not set "Content-Type" let the browser handle it
			// do not stringify FormData XHR handles it natively
			data = o.data;
		} else {
			if (isJsonContentType && !isSimpleCors) {
				data = typeof o.data === "object" ? JSON.stringify(o.data) : o.data;
				xhr.setRequestHeader("Content-Type", "application/json");
			} else {
				data = canParam_1_2_0_canParam(o.data);
				// CORS simple: `Content-Type` has to be `application/x-www-form-urlencoded`:
				xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			}
		}
	} else {
		xhr.setRequestHeader("Content-Type", o.contentType);
	}

	// CORS simple: no custom headers, so we don't add `X-Requested-With` header:
	if (!isSimpleCors){
		xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
	}

	if (o.xhrFields) {
		for (var f in o.xhrFields) {
			xhr[f] = o.xhrFields[f];
		}
	}
	function send () {
		if(!isAborted) {
			xhr.send(data);
		}
	}

	if(o.beforeSend){
		var result = o.beforeSend.call( o, xhr, o );
		if(canReflect_1_19_2_canReflect.isPromise(result)) {
			result.then(send).catch(deferred.reject);
			return promise;
		}
	}
	
	send();
	return promise;
}

var canAjax_2_4_8_canAjax = canNamespace_1_0_0_canNamespace.ajax = ajax;
var ajaxSetup = function (o) {
    globalSettings = o || {};
};
canAjax_2_4_8_canAjax.ajaxSetup = ajaxSetup;

var methodMapping = {
	item: {
		'GET': 'getData',
		'PUT': 'updateData',
		'DELETE': 'destroyData',
	},
	list: {
		'GET': 'getListData',
		'POST': 'createData'
	}
};


function inferIdProp (url) {
	var wrappedInBraces = /\{(.*)\}/;
	var matches = url.match(wrappedInBraces);
	var isUniqueMatch = matches && matches.length === 2;
	if (isUniqueMatch) {
		return matches[1];
	}
}

function getItemAndListUrls (url, idProp) {
	idProp = idProp || inferIdProp(url) || "id";
	var itemRegex = new RegExp('\\/\\{' + idProp+"\\}.*" );
	var rootIsItemUrl = itemRegex.test(url);
	var listUrl = rootIsItemUrl ? url.replace(itemRegex, "") : url;
	var itemUrl = rootIsItemUrl ? url : (url.trim() + "/{" + idProp + "}");
	return {item: itemUrl, list: listUrl};
}



var canMakeRest_0_1_4_canMakeRest = function(url, idProp){
	var data= {};
	canReflect_1_19_2_canReflect.eachKey( getItemAndListUrls(url, idProp), function(url, type){
		canReflect_1_19_2_canReflect.eachKey(methodMapping[type], function(interfaceMethod, method){
			data[interfaceMethod] = {
				method: method,
				url: url
			};
		});
	});
	return data;
};

var makePromise = function(obj){
	if (obj && typeof obj.then === "function" && !canReflect_1_19_2_canReflect.isPromise(obj)) {
		return new Promise(function(resolve, reject) {
			obj.then(resolve, reject);
		});
	}
	else {
		return obj;
	}
};

var url = createCommonjsModule(function (module) {
/**
 * @module {connect.Behavior} can-connect/data/url/url data/url
 * @parent can-connect.behaviors
 * @group can-connect/data/url/url.data-methods data methods
 * @group can-connect/data/url/url.option options
 *
 * @option {connect.Behavior}
 *
 * Uses the [can-connect/data/url/url.url] option to implement the behavior of
 * [can-connect/connection.getListData],
 * [can-connect/connection.getData],
 * [can-connect/connection.createData],
 * [can-connect/connection.updateData], and
 * [can-connect/connection.destroyData] to make an AJAX request
 * to urls.
 *
 * @body
 *
 * ## Use
 *
 * The `data/url` behavior implements many of the [can-connect/DataInterface]
 * methods to send instance data to a URL.
 *
 * For example, the following `todoConnection`:
 *
 * ```js
 * var todoConnection = connect([
 *   require("can-connect/data/url/url")
 * ],{
 *   url: {
 *     getListData: "GET /todos",
 *     getData: "GET /todos/{id}",
 *     createData: "POST /todos",
 *     updateData: "PUT /todos/{id}",
 *     destroyData: "DELETE /todos/{id}"
 *   }
 * });
 * ```
 *
 * Will make the following request when the following
 * methods are called:
 *
 * ```
 * // GET /todos?due=today
 * todoConnection.getListData({due: "today"});
 *
 * // GET /todos/5
 * todosConnection.getData({id: 5})
 *
 * // POST /todos \
 * // name=take out trash
 * todosConnection.createData({
 *   name: "take out trash"
 * });
 *
 * // PUT /todos/5 \
 * // name=do the dishes
 * todosConnection.updateData({
 *   name: "do the dishes",
 *   id: 5
 * });
 *
 * // DELETE /todos/5
 * todosConnection.destroyData({
 *   id: 5
 * });
 * ```
 *
 * There's a few things to notice:
 *
 * 1. URL values can include simple templates like `{id}`
 *    that replace that part of the URL with values in the data
 *    passed to the method.
 * 2. GET and DELETE request data is put in the URL using [can-param].
 * 3. POST and PUT requests put data that is not templated in the URL in POST or PUT body
 *    as JSON-encoded data.  To use form-encoded requests instead, add the property
 *    `contentType:'application/x-www-form-urlencoded'` to your [can-connect/data/url/url.url].
 * 4. If a provided URL doesn't include the method, the following default methods are provided:
 *    - `getListData` - `GET`
 *    - `getData` - `GET`
 *    - `createData` - `POST`
 *    - `updateData` - `PUT`
 *    - `destroyData` - `DELETE`
 *
 * If [can-connect/data/url/url.url] is provided as a string like:
 *
 * ```js
 * var todoConnection = connect([
 *   require("can-connect/data/url/url")
 * ],{
 *   url: "/todos"
 * });
 * ```
 *
 * This does the same thing as the first `todoConnection` example.
 */







var defaultRest = canMakeRest_0_1_4_canMakeRest("/resource/{id}");



// # can-connect/data/url/url
// For each pair, create a function that checks the url object
// and creates an ajax request.
var urlBehavior = canConnect_4_0_6_behavior("data/url", function(baseConnection) {
	var behavior = {};
	canReflect_1_19_2_canReflect.eachKey(defaultRest, function(defaultData, dataInterfaceName){
		behavior[dataInterfaceName] = function(params) {
			var meta = methodMetaData[dataInterfaceName];
			var defaultBeforeSend;

			if(typeof this.url === "object") {
				defaultBeforeSend = this.url.beforeSend;

				if(typeof this.url[dataInterfaceName] === "function") {

					return makePromise(this.url[dataInterfaceName](params));
				}
				else if(this.url[dataInterfaceName]) {
					var promise = makeAjax(
							this.url[dataInterfaceName],
							params,
							defaultData.method,
							this.ajax || canAjax_2_4_8_canAjax,
							findContentType(this.url, defaultData.method),
							meta,
							defaultBeforeSend
					);
					return makePromise(promise);
				}
			}

			var resource = typeof this.url === "string" ? this.url : this.url.resource;
			if( resource ) {
				var idProps = canReflect_1_19_2_canReflect.getSchema(this.queryLogic).identity;
				var resourceWithoutTrailingSlashes = resource.replace(/\/+$/, "");
				var result = canMakeRest_0_1_4_canMakeRest(resourceWithoutTrailingSlashes, idProps[0])[dataInterfaceName];
				return makePromise(makeAjax(
					result.url,
					params,
					result.method,
					this.ajax || canAjax_2_4_8_canAjax,
					findContentType(this.url, result.method),
					meta,
					defaultBeforeSend
				));
			}

			return baseConnection[name].call(this, params);
		};
	});

	return behavior;
});
/**
 * @property {String|Object} can-connect/data/url/url.url url
 * @parent can-connect/data/url/url.option
 *
 * Specify the url and methods that should be used for the "Data Methods".
 *
 * @option {String} If a string is provided, it's assumed to be a RESTful interface. For example,
 * if the following is provided:
 *
 * ```
 * url: "/services/todos"
 * ```
 *
 * ... the following methods and requests are used:
 *
 *  - `getListData` - `GET /services/todos`
 *  - `getData` - `GET /services/todos/{id}`
 *  - `createData` - `POST /services/todos`
 *  - `updateData` - `PUT /services/todos/{id}`
 *  - `destroyData` - `DELETE /services/todos/{id}`
 *
 * @option {Object} If an object is provided, it can customize each method and URL directly
 * like:
 *
 * ```js
 * url: {
 *   getListData: "GET /services/todos",
 *   getData: "GET /services/todo/{id}",
 *   createData: "POST /services/todo",
 *   updateData: "PUT /services/todo/{id}",
 *   destroyData: "DELETE /services/todo/{id}"
 * }
 * ```
 *
 * You can provide a `resource` property that works like providing `url` as a string, but overwrite
 * other values like:
 *
 * ```js
 * url: {
 *   resource: "/services/todo",
 *   getListData: "GET /services/todos"
 * }
 * ```
 *
 * You can also customize per-method the parameters passed to the [can-connect/data/url/url.ajax ajax implementation], like:
 * ```js
 * url: {
 *   resource: "/services/todos",
 *   getListData: {
 *     url: "/services/todos",
 *     type: "GET",
 *     beforeSend: () => {
 *       return fetch('/services/context').then(processContext);
 *     }
 *   }
 * }
 * ```
 * This can be particularly useful for passing a handler for the [can-ajax <code>beforeSend</code>] hook.
 *
 * The [can-ajax <code>beforeSend</code>] hook can also be passed for all request methods. This can be useful when
 * attaching a session token header to a request:
 * 
 * ```js
 * url: {
 *   resource: "/services/todos",
 *   beforeSend: (xhr) => {
 *     xhr.setRequestHeader('Authorization', `Bearer: ${Session.current.token}`);
 *   }
 * }
 * ```
 *
 * Finally, you can provide your own method to totally control how the request is made:
 *
 * ```js
 * url: {
 *   resource: "/services/todo",
 *   getListData: "GET /services/todos",
 *   getData: function(param){
 *     return new Promise(function(resolve, reject){
 *       $.get("/services/todo", {identifier: param.id}).then(resolve, reject);
 *     });
 *   }
 * }
 * ```
 */


 /**
  * @property {function} can-connect/data/url/url.ajax ajax
  * @parent can-connect/data/url/url.option
  *
  * Specify the ajax functionality that should be used to make the request.
  *
  * @option {function} Provides an alternate function to be used to make
  * ajax requests.  By default [can-ajax] provides the ajax
  * functionality. jQuery's ajax method can be substituted as follows:
  *
  * ```js
  * connect([
  *   require("can-connect/data/url/url")
  * ],{
  *   url: "/things",
  *   ajax: $.ajax
  * });
  * ```
  *
  *   @param {Object} settings Configuration options for the AJAX request.
  *   @return {Promise} A Promise that resolves to the data.
  */

// ## methodMetaData
// Metadata on different methods that is passed to makeAjax
var methodMetaData = {
	/**
	 * @function can-connect/data/url/url.getListData getListData
	 * @parent can-connect/data/url/url.data-methods
	 *
	 * @signature `getListData(set)`
	 *
	 *   Retrieves list data for a particular set given the [can-connect/data/url/url.url] settings.
	 *   If `url.getListData` is a function, that function will be called.  If `url.getListData` is a
	 *   string, a request to that string will be made. If `url` is a string, a `GET` request is made to
	 *   `url`.
	 *
	 *   @param {can-query-logic/query} query A object that represents the set of data needed to be loaded.
	 *   @return {Promise<can-connect.listData>} A promise that resolves to the ListData format.
	 */
	getListData: {},
	/**
	 * @function can-connect/data/url/url.getData getData
	 * @parent can-connect/data/url/url.data-methods
	 *
	 * @signature `getData(params)`
	 *
	 *   Retrieves raw instance data given the [can-connect/data/url/url.url] settings.
	 *   If `url.getData` is a function, that function will be called.  If `url.getData` is a
	 *   string, a request to that string will be made. If `url` is a string, a `GET` request is made to
	 *   `url+"/"+IDPROP`.
	 *
	 *   @param {Object} params A object that represents the set of data needed to be loaded.
	 *   @return {Promise<Object>} A promise that resolves to the instance data.
	 */
	getData: {},
	/**
	 * @function can-connect/data/url/url.createData createData
	 * @parent can-connect/data/url/url.data-methods
	 *
	 * @signature `createData(instanceData, cid)`
	 *
	 *   Creates instance data given the serialized form of the data and
	 *   the [can-connect/data/url/url.url] settings.
	 *   If `url.createData` is a function, that function will be called.  If `url.createData` is a
	 *   string, a request to that string will be made. If `url` is a string, a `POST` request is made to
	 *   `url`.
	 *
	 *   @param {Object} instanceData The serialized data of the instance.
	 *   @param {Number} cid A unique id that represents the instance that is being created.
	 *   @return {Promise<Object>} A promise that resolves to the newly created instance data.
	 */
	createData: {},
	/**
	 * @function can-connect/data/url/url.updateData updateData
	 * @parent can-connect/data/url/url.data-methods
	 *
	 * @signature `updateData(instanceData)`
	 *
	 * Updates instance data given the serialized form of the data and
	 *   the [can-connect/data/url/url.url] settings.
	 *   If `url.updateData` is a function, that function will be called.  If `url.updateData` is a
	 *   string, a request to that string will be made. If `url` is a string, a `PUT` request is made to
	 *   `url+"/"+IDPROP`.
	 *
	 *   @param {Object} instanceData The serialized data of the instance.
	 *   @return {Promise<Object>} A promise that resolves to the updated instance data.
	 */
	updateData: {},
	/**
	 * @function can-connect/data/url/url.destroyData destroyData
	 * @parent can-connect/data/url/url.data-methods
	 *
	 * @signature `destroyData(instanceData)`
	 *
	 * Deletes instance data given the serialized form of the data and
	 *   the [can-connect/data/url/url.url] settings.
	 *   If `url.destroyData` is a function, that function will be called.  If `url.destroyData` is a
	 *   string, a request to that string will be made. If `url` is a string, a `DELETE` request is made to
	 *   `url+"/"+IDPROP`.
	 *
	 *   @param {Object} instanceData The serialized data of the instance.
	 *   @return {Promise<Object>} A promise that resolves to the deleted instance data.
	 */
	destroyData: {includeData: false}
};

var findContentType = function( url, method ) {
	if ( typeof url === 'object' && url.contentType ) {
		var acceptableType = url.contentType === 'application/x-www-form-urlencoded' ||
			url.contentType === 'application/json';
		if ( acceptableType ) {
			return url.contentType;
		} else {
			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				dev.warn("Unacceptable contentType on can-connect request. " +
					"Use 'application/json' or 'application/x-www-form-urlencoded'");
			}
			//!steal-remove-end
		}
	}
	return method === "GET" ? "application/x-www-form-urlencoded" : "application/json";
};

function urlParamEncoder (key, value) {
	return encodeURIComponent(value);
}

var makeAjax = function ( ajaxOb, data, type, ajax, contentType, reqOptions, defaultBeforeSend ) {

	var params = {};

	// A string here would be something like `"GET /endpoint"`.
	if (typeof ajaxOb === 'string') {
		// Split on spaces to separate the HTTP method and the URL.
		var parts = ajaxOb.split(/\s+/);
		params.url = parts.pop();
		if (parts.length) {
			params.type = parts.pop();
		}
	} else {
		// If the first argument is an object, just load it into `params`.
		canReflect_1_19_2_canReflect.assignMap(params, ajaxOb);
	}

	// If the `data` argument is a plain object, copy it into `params`.
	params.data = typeof data === "object" && !Array.isArray(data) ?
		canReflect_1_19_2_canReflect.assignMap(params.data || {}, data) : data;

	// Substitute in data for any templated parts of the URL.
	params.url = replaceWith(params.url, params.data, urlParamEncoder, true);
	params.contentType = contentType;

	if(reqOptions.includeData === false) {
		delete params.data;
	}

	return ajax(canReflect_1_19_2_canReflect.assignMap({
		type: type || 'post',
		dataType: 'json',
		beforeSend: defaultBeforeSend,
	}, params));
};

module.exports = urlBehavior;

//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var validate$$1 = validate;
	module.exports = validate$$1(urlBehavior, ['url']);
}
//!steal-remove-end
});

var indexByIdentity = function(items, item, schema){
    var length = canReflect_1_19_2_canReflect.size(items);
    if(!schema && length > 0) {
        schema = canReflect_1_19_2_canReflect.getSchema( items[0] );
    }
    if(!schema) {
        schema = canReflect_1_19_2_canReflect.getSchema( item );
    }
    if(!schema) {
        throw new Error("No schema to use to get identity.");
    }

	var id = canReflect_1_19_2_canReflect.getIdentity(item, schema);

	for(var i = 0; i < length; i++) {
		var connId = canReflect_1_19_2_canReflect.getIdentity(items[i], schema);
        // this was ==
		if( id === connId) {
			return i;
		}
	}
	return -1;
};

/**
 * @module can-connect/real-time/real-time real-time
 * @parent can-connect.behaviors
 * @group can-connect/real-time/real-time.methods 0 methods
 * @group can-connect/real-time/real-time.callbacks 1 data callbacks
 *
 * Update lists to include or exclude instances based
 * on set logic.
 *
 * @signature `realTime( baseConnection )`
 *
 *   Overwrites the "data callback" methods and provides
 *   [can-connect/real-time/real-time.createInstance],
 *   [can-connect/real-time/real-time.updateInstance], and
 *   [can-connect/real-time/real-time.destroyInstance] methods
 *   that
 *   update lists to include or exclude a created,
 *   updated, or destroyed instance.
 *
 *   An instance is put in a list if it is a
 *   [can-query-logic/queryLogic.prototype.isSubset]
 *   of the [can-connect/base/base.listQuery].  The item is inserted using [can-query-logic.prototype.index].
 *
 * @body
 *
 * ## Use
 *
 * To use `real-time`, create a connection with its dependent
 * behaviors like:
 *
 * ```js
 * var todoConnection = connect(
 *    ["data/callbacks",
 *     "real-time",
 *     "constructor/callbacks-once",
 *     "constructor/store",
 *     "constructor",
 *     "data/url"],{
 *   url: "/todos"
 * });
 * ```
 *
 * Next, use the connection to load lists and save those lists in the
 * store:
 *
 * ```js
 * todoConnection.getList({complete: false}).then(function(todos){
 *   todoConnection.addListReference(todos);
 * })
 * ```
 *
 * Finally, use one of the  [can-connect/real-time/real-time.createInstance],
 * [can-connect/real-time/real-time.updateInstance], and
 * [can-connect/real-time/real-time.destroyInstance] methods to tell the connection
 * that data has changed.  The connection will update (by calling splice)
 * each list accordingly.
 *
 *
 * ## Example
 *
 * The following demo shows two lists that use this connection.  The
 * "Run Code" button sends the connection data changes which the
 * connection will then update lists accordingly:
 *
 *
 * @demo demos/can-connect/real-time.html
 *
 * This example creates a `todoList` function and `todoItem` function
 * that manage the behavior of a list of todos and a single todo respectfully.
 * It uses [Object.observe](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/observe)
 * to observe changes in the todo list and individual todo data. Other
 * frameworks will typically provide their own observable system.
 *
 * ### todoList
 *
 * When `todoList` is created, it is passed the `set` of data to load.  It uses
 * this to get todos from the `todoConnection` like:
 *
 *
 * ```js
 * todosConnection.getList(set).then(function(retrievedTodos){
 * ```
 *
 * It then adds those `todos` to the [can-connect/constructor/store/store.listStore] so
 * they can be updated automatically.  And, it listens to changes in `todos` and calls an `update` function:
 *
 * ```js
 * todosConnection.addListReference(todos);
 * Object.observe(todos, update, ["add", "update", "delete"] );
 * ```
 *
 * The update function is able to inserted new `todoItem`s in the page when items are added
 * to or removed from `todos`.  We exploit that by calling `update` as if it just added
 * each todo in the list:
 *
 * ```js
 * update(todos.map(function(todo, i){
 *   return {
 *     type: "add",
 *     name: ""+i
 *   };
 * }));
 * ```
 *
 * ### todoItem
 *
 * The `todoItem` creates an element that updates with changes
 * in its `todo`.  It listens to changes in the `todo` and saves
 * the todo in the [can-connect/constructor/store/store.instanceStore] with the
 * following:
 *
 * ```js
 * Object.observe(todo, update, ["add", "update", "delete"] );
 * todosConnection.addInstanceReference(todo);
 * ```
 *
 * A `todoItem` needs to be able to stop listening on the `todo` and remove itself from the
 * `instanceStore` if the `todo` is removed from the page.  To provide this teardown
 * functionality, `todoItem` listens to a `"removed"` event on its element and
 * `unobserves` the todo and removes it from the `instanceStore`:
 *
 * ```js
 * $(li).bind("removed", function(){
 *   Object.unobserve(todo, update, ["add", "update", "delete"] );
 *   todosConnection.deleteInstanceReference(todo);
 * });
 * ```
 */






var spliceSymbol = canSymbol_1_7_0_canSymbol.for("can.splice");

function updateList(list, getRecord, currentIndex, newIndex) {

	if(currentIndex === -1) { // item is not in the list

		if(newIndex !== -1) { // item should be in the list
			canReflect_1_19_2_canReflect.splice(list, newIndex, 0, [getRecord()]);
		} else {
			canReflect_1_19_2_canReflect.splice(list, 0, 0, [getRecord()]);
		}
	}
	else { // item is already in the list
		if(newIndex === -1) { // item should be removed from the lists
			canReflect_1_19_2_canReflect.splice(list, currentIndex, 1, []);
		}
		else if(newIndex !== currentIndex){ // item needs to be moved

			if(currentIndex < newIndex) {
				canReflect_1_19_2_canReflect.splice(list, newIndex, 0, [getRecord()]);
				canReflect_1_19_2_canReflect.splice(list, currentIndex, 1, []);
			} else {
				canReflect_1_19_2_canReflect.splice(list, currentIndex,1, []);
				canReflect_1_19_2_canReflect.splice(list, newIndex, 0, [getRecord()]);
			}
		}
		else { // item in the same place

		}
	}
}


function updateListWithItem(list, recordData, currentIndex, newIndex, connection, set){
	// this is cleaning up a bug with QueryLogic.index where it can return undefined
	if( newIndex === undefined ) {
		newIndex = -1;
	}
	// we are inserting right where we already are.
	if(currentIndex !== -1 && (newIndex === currentIndex + 1 || newIndex === currentIndex)) {
		return;
	}
	if(list[spliceSymbol] !== undefined) {
		updateList(list, function(){
			return connection.hydrateInstance(recordData);
		},currentIndex, newIndex);

	} else {
		var copy = connection.serializeList(list);
		updateList(copy, function(){
			return recordData;
		},currentIndex, newIndex);
		connection.updatedList(list,  { data: copy }, set);
	}
}


var realTime = canConnect_4_0_6_canConnect.behavior("real-time",function(baseConnection){

	var createPromise = Promise.resolve();
	var behavior;

	behavior = {
		createData: function(){
			var promise = baseConnection.createData.apply(this, arguments);
			var cleanPromise = promise.catch(function () { return ''; });
			createPromise = Promise.all([createPromise, cleanPromise]);
			return promise;
		},
		/**
		 * @function can-connect/real-time/real-time.createInstance createInstance
		 * @parent can-connect/real-time/real-time.methods
		 *
		 * Programatically indicate a new instance has been created.
		 *
		 * @signature `connection.createInstance(props)`
		 *
		 *   If there is no instance in the [can-connect/constructor/store/store.instanceStore]
		 *   for `props`'s [can-connect/base/base.id], an instance is [can-connect/constructor/constructor.hydrateInstance hydrated],
		 *   added to the store, and then [can-connect/real-time/real-time.createdData] is called with
		 *   `props` and the hydrated instance's serialized data. [can-connect/real-time/real-time.createdData]
		 *   will add this instance to any lists the instance belongs to.
		 *
		 *   If this instance has already been created, calls
		 *   [can-connect/real-time/real-time.updateInstance] with `props`.
		 *
		 *   @param {Object} props The raw properties of the instance was created.
		 *
		 *   @return {Promise<Instance>} A promise that resolves to the created instance.
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * With a `real-time` connection, call `createInstance` when an instance is created that
		 * the connection itself did not make.  For instance, the following might listen to
		 * [socket.io](http://socket.io/) for when a `todo` is created and update the connection
		 * accordingly:
		 *
		 * ```js
		 * socket.on('todo created', function(todo){
		 *   todoConnection.createInstance(todo);
		 * });
		 * ```
		 *
		 */
		createInstance: function(props){
			var self = this;
			return new Promise(function(resolve, reject){
				// Wait until all create promises are done
				// so that we can find data in the instance store
				createPromise.then(function(){
					// Allow time for the store to get hydrated
					setTimeout(function(){
						var id = self.id(props);
						var instance = self.instanceStore.get(id);
						var serialized;

						if( instance ) {
							// already created, lets update
							resolve(self.updateInstance(props));
						} else {
							instance = self.hydrateInstance(props);
							serialized = self.serializeInstance(instance);

							self.addInstanceReference(instance);

							Promise.resolve( self.createdData(props, serialized) ).then(function(){
								self.deleteInstanceReference(instance);
								resolve(instance);
							});
						}
					}, 1);
				});
			});
		},

		/**
		 * @function can-connect/real-time/real-time.createdData createdData
		 * @parent can-connect/real-time/real-time.callbacks
		 *
		 * Called whenever instance data is created.
		 *
		 * @signature `connection.createdData(props, params, [cid])`
		 *
		 *   Updates lists with the created instance.
		 *
		 *   Gets the instance created for this request. Then, updates the instance with
		 *   the response data `props`.
		 *
		 *   Next, it goes through every list in the [can-connect/constructor/store/store.listStore],
		 *   test if the instance's data belongs in that list.  If it does,
		 *   adds the instance's data to the serialized list data and
		 *   [can-connect/constructor/constructor.updatedList updates the list].
		 */
		createdData: function(props, params, cid){
			var instance;
			if(cid !== undefined) {
				instance = this.cidStore.get(cid);
			} else {
				instance = this.instanceStore.get( this.id(props) );
			}
			// pre-register so everything else finds this even if it doesn't have an id
			this.addInstanceReference(instance, this.id(props));
			this.createdInstance(instance, props);
			create.call(this, this.serializeInstance(instance));
			this.deleteInstanceReference(instance);
			return undefined;
		},

		/**
		 * @function can-connect/real-time/real-time.updatedData updatedData
		 * @parent can-connect/real-time/real-time.callbacks
		 *
		 * Called whenever instance data is updated.
		 *
		 * @signature `connection.updatedData(props, params)`
		 *
		 *   Gets the instance that is updated, updates
		 *   it with `props` and the adds or removes it to
		 *   lists it belongs in.
		 *
		 *   @return {undefined} Returns `undefined` to prevent `.save` from calling `updatedInstance`.
		 */
		// Go through each list in the listStore and see if there are lists that should have this,
		// or a list that shouldn't.
		updatedData: function(props, params){

			var instance = this.instanceStore.get( this.id(params) );
			this.updatedInstance(instance, props);
			update$1.call(this, this.serializeInstance(instance));

			// Returning undefined prevents other behaviors from running.
			return undefined;
		},
		/**
		 * @function can-connect/real-time/real-time.updateInstance updateInstance
		 * @parent can-connect/real-time/real-time.methods
		 *
		 * Programatically indicate a new instance has been updated.
		 *
		 * @signature `connection.updateInstance(props)`
		 *
		 *   Calls [can-connect/real-time/real-time.updatedData] in the right way so
		 *   that the instance is updated and added to or removed from
		 *   any lists it belongs in.
		 *
		 *   @param {Object} props The properties of the instance that needs to be updated.
		 *
		 *   @return {Promise<Instance>} the updated instance.
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * ```js
		 * socket.on('todo updated', function(todo){
		 *   todoConnection.updateInstance(todo);
		 * });
		 * ```
		 */
		updateInstance: function(props){
			var id = this.id(props);
			var instance = this.instanceStore.get(id);
			if( !instance ) {
				instance = this.hydrateInstance(props);
			}
			this.addInstanceReference(instance);

			var serialized = this.serializeInstance(instance),
				self = this;

			return Promise.resolve( this.updatedData(props, serialized) ).then(function(){

				self.deleteInstanceReference(instance);
				return instance;
			});
		},
		/**
		 * @function can-connect/real-time/real-time.destroyedData destroyedData
		 * @parent can-connect/real-time/real-time.callbacks
		 *
		 * @signature `connection.destroyedData(props, params)`
		 *
		 * Gets the instance for this request.  Then tests if the instance
		 * is in any list in the [can-connect/constructor/store/store.listStore].  If
		 * it is, removes the instance from the list.
		 *
		 * @param {Object} props The properties of the destroyed instance.
		 * @param {Object} [params] The parameters used to destroy the data.
		 */
		destroyedData: function(props, params){
			var id = this.id(params || props);
			var instance = this.instanceStore.get(id);
			if( !instance ) {
				instance = this.hydrateInstance(props);
			}
			var serialized = this.serializeInstance(instance);
			this.destroyedInstance(instance, props);
			// we can pre-register it so everything else finds it
			destroy.call(this, serialized);
			return undefined;
		},
		/**
		 * @function can-connect/real-time/real-time.destroyInstance destroyInstance
		 * @parent can-connect/real-time/real-time.methods
		 *
		 * Programatically indicate a new instance has been destroyed.
		 *
		 * @signature `connection.destroyInstance(props)`
		 *
		 *   Gets or creates an instance from `props` and uses
		 *   it to call [can-connect/real-time/real-time.destroyedData]
		 *   correctly.
		 *
		 * @param {Object} props The properties of the destroyed instance.
		 * @return {Promise<Instance>}  A promise with the destroyed instance.
		 *
		 * @body
		 * ## Use
		 *
		 * ```js
		 * socket.on('todo destroyed', function(todo){
		 *   todoConnection.destroyInstance(todo);
		 * });
		 * ```
		 */
		destroyInstance: function(props){
			var id = this.id(props);
			var instance = this.instanceStore.get(id);
			if( !instance ) {
				instance = this.hydrateInstance(props);
			}
			this.addInstanceReference(instance);

			var serialized = this.serializeInstance(instance),
				self = this;

			return Promise.resolve( this.destroyedData(props, serialized) ).then(function(){

				self.deleteInstanceReference(instance);
				return instance;
			});
		}
	};

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		behavior.gotListData = function(items, set) {
			var self = this;
			if (this.queryLogic) {
				if(Array.isArray(items)) {
					items = {data: items};
				}
				for(var item, i = 0, l = items.data.length; i < l; i++) {
					item = items.data[i];
					if( !self.queryLogic.isMember(set, item) ) {
						var msg = [
							"One or more items were retrieved which do not match the 'Set' parameters used to load them. ",
							"Read the docs for more information: https://canjs.com/doc/can-query-logic.html#TestingyourQueryLogic",
							"\n\nBelow are the 'query' parameters:",
							"\n" + dev.stringify(set),
							"\n\nAnd below is an item which does not match those parameters:",
							"\n" + dev.stringify(item)
						].join("");
						dev.warn(msg);
						break;
					}
				}
			}

			return Promise.resolve(items);
		};
	}
	//!steal-remove-end

	return behavior;
});

var create = function(props){
	var self = this;
	// go through each list
	this.listStore.forEach(function(list, id){
		var set = JSON.parse(id);
		// ideally there should be speed up ... but this is fine for now.


		var index = indexByIdentity(list, props, self.queryLogic.schema);

		if(self.queryLogic.isMember(set, props)) {
			var newIndex = self.queryLogic.index(set, list, props);

			updateListWithItem(list, props, index, newIndex, self, set);
		}

	});
};

// ## update
// Goes through each list and sees if the list should be updated
// with the new.
var update$1 = function(props) {
	var self = this;

	this.listStore.forEach(function(list, id){
		var set = JSON.parse(id);
		// ideally there should be speed up ... but this is fine for now.


		var currentIndex = indexByIdentity(list, props, self.queryLogic.schema);

		if(self.queryLogic.isMember( set, props )) {

			var newIndex = self.queryLogic.index(set, list, props);

			updateListWithItem(list, props, currentIndex, newIndex, self, set);

		}  else if(currentIndex !== -1){ // its still in the list
			// otherwise remove it
			updateListWithItem(list, props, currentIndex, -1, self, set);
		}

	});
};

var destroy = function(props) {
	var self = this;
	this.listStore.forEach(function(list, id){
		var set = JSON.parse(id);
		// ideally there should be speed up ... but this is fine for now.

		var currentIndex = indexByIdentity(list, props, self.queryLogic.schema);

		if(currentIndex !== -1){
			// otherwise remove it
			updateListWithItem(list, props, currentIndex, -1, self, set);
		}

	});
};

var callbacksOnce = createCommonjsModule(function (module) {
/**
 * @module {function} can-connect/constructor/callbacks-once/callbacks-once constructor/callbacks-once
 * @parent can-connect.behaviors
 *
 * Prevents duplicate calls to the instance callback methods.
 *
 * @signature `callbacksOnce( baseConnection )`
 *
 *   Prevents duplicate calls to the instance callback methods by tracking the last data the methods were called with.
 *   If called with the same data again, it does not call the base connection's instance callback.
 *
 *   @param {{}} baseConnection `can-connect` connection object that is having the `callbacks-once` behavior added
 *   on to it. Should already contain the behaviors that provide the Instance Callbacks
 *   (e.g [can-connect/constructor/constructor]). If the `connect` helper is used to build the connection, the
 *   behaviors will automatically be ordered as required.
 *
 *   @return {Object} A `can-connect` connection containing the methods provided by `callbacks-once`.
 *
 */


var forEach = [].forEach;

// wires up the following methods
var callbacks = [
	/**
	 * @function can-connect/constructor/callbacks-once/callbacks-once.createdInstance createdInstance
	 * @parent can-connect/constructor/callbacks-once/callbacks-once
	 *
	 * `createdInstance` callback handler that prevents sequential calls with the same arguments.
	 *
	 * @signature `createdInstance(instance, data)`
	 * Called with the instance created by [can-connect/constructor/constructor.save `connection.save`] and the response data of the
	 * underlying request. Prevents sequential calls to the underlying `createdInstance` handlers with the same arguments.
	 *
	 * @param {} instance the instance created by `connection.save`
	 * @param {} data the response data returned during `connection.save`
	 */
	"createdInstance",
	/**
	 * @function can-connect/constructor/callbacks-once/callbacks-once.updatedInstance updatedInstance
	 * @parent can-connect/constructor/callbacks-once/callbacks-once
	 *
	 * `updatedInstance` callback handler that prevents sequential calls with the same arguments.
	 *
	 * @signature `updatedInstance(instance, data)`
	 * Called with the instance updated by [can-connect/constructor/constructor.save`connection.save`] and the response data of the
	 * underlying request. Prevents sequential calls to the underlying `updatedInstance` handlers with the same arguments.
	 *
	 * @param {} instance the instance created by `connection.save`
	 * @param {} data the response data returned during `connection.save`
	 */
	"updatedInstance",
	/**
	 * @function can-connect/constructor/callbacks-once/callbacks-once.destroyedInstance destroyedInstance
	 * @parent can-connect/constructor/callbacks-once/callbacks-once
	 *
	 * `destroyedInstance` callback handler that prevents sequential calls with the same arguments.
	 *
	 * @signature `destroyedInstance(instance, data)`
	 * Called with the instance created by [can-connect/constructor/constructor.destroy `connection.destroy`] and the response data of the
	 * underlying request. Prevents sequential calls to the underlying `destroyedInstance` handlers with the same arguments.
	 *
	 * @param {} instance the instance created by `connection.destroy`
	 * @param {} data the response data returned during `connection.destroy`
	 */
	"destroyedInstance"
];



var callbacksOnceBehavior = canConnect_4_0_6_canConnect.behavior("constructor/callbacks-once",function(baseConnection){

	var behavior = {};

	forEach.call(callbacks, function(name){
		behavior[name] = function(instance, data ){

			var lastSerialized = this.getInstanceMetaData(instance, "last-data-" + name);

			var serialize = sortedSetJson(data);
			if(lastSerialized !== serialize) {
				var result =  baseConnection[name].apply(this, arguments);
				this.addInstanceMetaData(instance, "last-data-" + name, serialize);
				return result;
			}
		};

	});

	return behavior;
});

module.exports = callbacksOnceBehavior;

//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var validate$$1 = validate;
	module.exports = validate$$1(callbacksOnceBehavior, callbacks);
}
//!steal-remove-end
});

function realtimeRestModel(optionsOrUrl) {

	// If optionsOrUrl is a string, make options = {url: optionsOrUrl}
	var options = (typeof optionsOrUrl === "string") ? {url: optionsOrUrl} : optionsOrUrl;

	// If options.ObjectType or .ArrayType aren’t provided, define them
	if (typeof options.ObjectType === "undefined") {
		options.ObjectType = class DefaultObjectType extends canObservableObject {};
	}
	if (typeof options.ArrayType === "undefined") {
		options.ArrayType = class DefaultArrayType extends canObservableArray {
			static get items() {
				return canType_1_1_6_canType.convert(options.ObjectType);
			}
		};
	}

	var behaviors = [
		constructor_1,
		map$3,
		store,
		callbacks,
		parse$1,
		url,
		realTime,
		callbacksOnce
	];

	return canConnect_4_0_6_canConnect(behaviors,options);
}

var canRealtimeRestModel_2_0_0_canRealtimeRestModel = canNamespace_1_0_0_canNamespace.realtimeRestModel = realtimeRestModel;

function restModel(optionsOrUrl) {

	// If optionsOrUrl is a string, make options = {url: optionsOrUrl}
	var options = (typeof optionsOrUrl === "string") ? {url: optionsOrUrl} : optionsOrUrl;

	// If options.ObjectType or .ArrayType aren’t provided, define them
	if (typeof options.ObjectType === "undefined") {
		options.ObjectType = class DefaultObjectType extends canObservableObject {};
	}
	if (typeof options.ArrayType === "undefined") {
		options.ArrayType = class DefaultArrayType extends canObservableArray {
			static get items() {
				return canType_1_1_6_canType.convert(options.ObjectType);
			}
		};
	}

	var connection = [base,url, parse$1, constructor_1, map$3].reduce(function(prev, behavior){
		return behavior(prev);
	}, options);
	connection.init();
	return connection;
}

var canRestModel_2_0_0_canRestModel = canNamespace_1_0_0_canNamespace.restModel = restModel;

var getItems$1 = function(data){
	if(Array.isArray(data)) {
		return data;
	} else {
		return data.data;
	}
};

var cacheRequests = createCommonjsModule(function (module) {
var forEach = Array.prototype.forEach;


/**
 * @module can-connect/cache-requests/cache-requests cache-requests
 * @parent can-connect.behaviors
 * @group can-connect/cache-requests/cache-requests.data data interface
 * @group can-connect/cache-requests/cache-requests.queryLogic queryLogic
 *
 * Cache response data and use it to prevent unnecessary future requests or make future requests smaller.
 *
 * @signature `cacheRequests( baseConnection )`
 *
 *   Provide an implementation of [can-connect/cache-requests/cache-requests.getListData] that uses [can-connect/base/base.queryLogic] to
 *   determine what data is already in the [can-connect/base/base.cacheConnection cache] and what data needs to be
 *   loaded from the base connection.
 *
 *   It then gets data from the cache and the base connection (if needed), merges it, and returns it. Any data returned
 *   from the base connection is added to the cache.
 *
 *   @param {{}} baseConnection `can-connect` connection object that is having the `cache-requests` behavior added
 *   on to it. Should already contain the behaviors that provide the [can-connect/DataInterface]
 *   (e.g [can-connect/data/url/url]). If the `connect` helper is used to build the connection, the behaviors will
 *   automatically be ordered as required.
 *
 *   @return {Object} A `can-connect` connection containing the methods provided by `cache-requests`.
 *
 *
 * @body
 *
 * ## Use
 *
 * Use `cache-requests` in combination with a cache like [can-connect/data/memory-cache/memory-cache] or
 * [can-connect/data/localstorage-cache/localstorage-cache].  For example, to make it so response data is cached
 * in memory:
 *
 * ```js
 * var memoryStore = require("can-memory-store");
 * var dataUrl = require("can-connect/data/url/url");
 * var cacheRequests = require("can-connect/cache-requests/cache-requests");
 * var queryLogic = require("can-query-logic");
 *
 * var todoQueryLogic = new QueryLogic({});
 *
 * var cacheConnection = memoryStore({queryLogic: todoQueryLogic});
 * var todoConnection = connect([dataUrl, cacheRequests],{
 *   cacheConnection: cacheConnection,
 *   url: "/todos",
 *   queryLogic: todoQueryLogic
 * });
 * ```
 *
 * Now if today's todos are loaded:
 *
 * ```js
 * todoConnection.getListData({filter: {due: "today"}});
 * ```
 *
 * And later, a subset of those todos are loaded:
 *
 * ```js
 * todoConnection.getListData({filter: {due: "today", status: "critical"}});
 * ```
 *
 * The second request will be created from the original request's data.
 *
 * ## QueryLogic Usage
 *
 * `cache-requests` will "fill-in" the `cacheConnection` using [can-query-logic queryLogic].
 *
 * For example, if you requested paginated data like:
 *
 * ```
 * todoConnection.getListData({filter: {status: "critical"}})
 * ```
 *
 * And then later requested:
 *
 * ```
 * todoConnection.getListData({})
 * ```
 *
 * `cache-requests` will only request `{filter: {status: ["low","medium"]}}`, merging
 * that response with the data already present in the cache.
 *
 * That configuration looks like:
 *
 * ```js
 * var memoryStore = require("can-memory-store");
 * var dataUrl = require("can-connect/data/url/url");
 * var cacheRequests = require("can-connect/cache-requests/cache-requests");
 * var queryLogic = require("can-query-logic");
 *
 * var todoQueryLogic = new QueryLogic({
 *   keys: {
 *     status: QueryLogic.makeEnum(["low","medium","critical"])
 *   }
 * });
 *
 * var cacheConnection = memoryStore({queryLogic: todoQueryLogic});
 * var todoConnection = connect([dataUrl, cacheRequests], {
 *   cacheConnection: cacheConnection,
 *   url: "/todos",
 *   queryLogic: todoQueryLogic
 * })
 * ```
 *
 * **Note:** `cacheConnection` shares the same queryLogic configuration as the primary connection.
 */
var cacheRequestsBehaviour = canConnect_4_0_6_canConnect.behavior("cache-requests",function(baseConnection){

	return {

		/**
		 * @function can-connect/cache-requests/cache-requests.getDiff getDiff
		 * @parent can-connect/cache-requests/cache-requests.queryLogic
		 *
		 * Compares the cached queries to the requested query and returns a description of what subset can be loaded from the
		 * cache and what subset must be loaded from the base connection.
		 *
		 * @signature `connection.getDiff( query, availableQueries )`
		 *
		 *   This determines the minimal amount of data that must be loaded from the base connection by going through each
		 *   cached query (`availableQueries`) and doing a [can-query-logic.prototype.isSubset isSubset] check and a
		 *   [can-query-logic.prototype.difference query difference] with the requested query (`query`).
		 *
		 *   If `query` is a subset of an `availableSet`, `{cached: query}` will be returned.
		 *
		 *   If `query` is neither a subset of, nor intersects with any `availableQueries`, `{needed: query}` is returned.
		 *
		 *   If `query` has an intersection with one or more `availableQueries`, a description of the difference that has the fewest
		 *   missing elements will be returned. An example diff description looks like:
		 *
		 *   ```
		 *   {
		 *     needed: {start: 50, end: 99}, // the difference, the query that is not cached
		 *     cached: {start: 0, end: 49}, // the intersection, the query that is cached
		 *     count: 49 // the size of the needed query
		 *   }
		 *   ```
		 *
		 *   @param {can-query-logic/query} query The query that is being requested.
		 *   @param {Array<can-query-logic/query>} availableQueries An array of [can-connect/connection.getSets available queries] in the
		 *     [can-connect/base/base.cacheConnection cache].
		 *   @return {Promise<{needed: can-query-logic/query, cached: can-query-logic/query, count: Integer}>} a difference description object. Described above.
		 *
		 */
		getDiff: function( params, availableQueries ){

			var minSets,
				self = this;

			forEach.call(availableQueries, function(query){
				var curSets;
				var difference = self.queryLogic.difference(params, query );
				if( self.queryLogic.isDefinedAndHasMembers(difference) ) {
					var intersection = self.queryLogic.intersection(params, query);
					curSets = {
						needed: difference,
						cached: self.queryLogic.isDefinedAndHasMembers(intersection) ? intersection : false,
						count: self.queryLogic.count(difference)
					};
				} else if( self.queryLogic.isSubset(params, query) ){
					curSets = {
						cached: params,
						count: 0
					};
				}
				if(curSets) {
					if(!minSets || curSets.count < minSets.count) {
						minSets = curSets;
					}
				}
			});

			if(!minSets) {
				return {
					needed: params
				};
			} else {
				return {
					needed: minSets.needed,
					cached: minSets.cached
				};
			}
		},

		/**
		 * @function can-connect/cache-requests/cache-requests.unionMembers unionMembers
		 * @parent can-connect/cache-requests/cache-requests.queryLogic
		 *
		 * Create the requested data set, a union of the cached and un-cached data.
		 *
		 * @signature `connection.unionMembers(set, diff, neededData, cachedData)`
		 *
		 *   Uses [can-query-logic.prototype.unionMembers] to merge the two queries of data (`neededData` & `cachedData`).
		 *
		 * @param {can-query-logic/query} query The parameters of the data set requested.
		 * @param {Object} diff The result of [can-connect/cache-requests/cache-requests.getDiff].
		 * @param {can-connect.listData} neededData The data loaded from the base connection.
		 * @param {can-connect.listData} cachedData The data loaded from the [can-connect/base/base.cacheConnection].
		 *
		 * @return {can-connect.listData} A merged [can-connect.listData] representation of the the cached and requested data.
		 */
		unionMembers: function(params, diff, neededItems, cachedItems){
			// using the diff, re-construct everything
			return {data: this.queryLogic.unionMembers(diff.needed, diff.cached, getItems$1(neededItems), getItems$1(cachedItems))};
		},

		/**
		 * @function can-connect/cache-requests/cache-requests.getListData getListData
		 * @parent can-connect/cache-requests/cache-requests.data
		 *
		 * Only request data that isn't already present in the [can-connect/base/base.cacheConnection cache].
		 *
		 * @signature `connection.getListData(set)`
		 *
		 *   Overwrites a base connection's `getListData` to use data in the [can-connect/base/base.cacheConnection cache]
		 *   whenever possible.  This works by [can-connect/connection.getSets getting the stored queries]
		 *   from the [can-connect/base/base.cacheConnection cache] and
		 *   doing a [can-connect/cache-requests/cache-requests.getDiff diff] to see what needs to be loaded from the base
		 *   connection and what can be loaded from the [can-connect/base/base.cacheConnection cache].
		 *
		 *   With that information, this `getListData` requests data from the cache or the base connection as needed.
		 *   Data loaded from different sources is combined via [can-connect/cache-requests/cache-requests.unionMembers].
		 *
		 * @param {can-query-logic/query} query the parameters of the list that is being requested.
		 * @return {Promise<can-connect.listData>} a promise that returns an object conforming to the [can-connect.listData] format.
		 */
		getListData: function(set){
			set = set || {};
			var self = this;

			return this.cacheConnection.getSets(set).then(function(queries){

				var diff = self.getDiff(set, queries);

				if(!diff.needed) {
					return self.cacheConnection.getListData(diff.cached);
				} else if(!diff.cached) {
					return baseConnection.getListData(diff.needed).then(function(data){

						return self.cacheConnection.updateListData(getItems$1(data), diff.needed ).then(function(){
							return data;
						});

					});
				} else {
					var cachedPromise = self.cacheConnection.getListData(diff.cached);
					var needsPromise = baseConnection.getListData(diff.needed);

					var savedPromise = needsPromise.then(function(data){
						return self.cacheConnection.updateListData(  getItems$1(data), diff.needed ).then(function(){
							return data;
						});
					});
					// start the combine while we might be saving param and adding to cache
					var combinedPromise = Promise.all([
						cachedPromise,
						needsPromise
					]).then(function(result){
						var cached = result[0],
							needed = result[1];
						return self.unionMembers( set, diff, needed, cached);
					});

					return Promise.all([combinedPromise, savedPromise]).then(function(data){
						return data[0];
					});
				}

			});
		}
	};

});

module.exports = cacheRequestsBehaviour;

//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var validate$$1 = validate;
	module.exports = validate$$1(cacheRequestsBehaviour, ['getListData', 'cacheConnection']);
}
//!steal-remove-end
});

var callbacksCache = createCommonjsModule(function (module) {
/**
 * @module can-connect/data/callbacks-cache/callbacks-cache data/callbacks-cache
 * @parent can-connect.behaviors
 *
 * Implements the data interface callbacks to call the [can-connect/base/base.cacheConnection]
 * [can-connect/DataInterface]. These calls keep the [can-connect/base/base.cacheConnection] contents
 * up to date.
 *
 * @signature `dataCallbacksCache( baseConnection )`
 * Implements the data interface callbacks so that a corresponding [can-connect/DataInterface] method is called on the
 * [can-connect/base/base.cacheConnection]. This updates the [can-connect/base/base.cacheConnection] contents whenever
 * data is updated on the primary connection.
 *
 * @param {{}} baseConnection `can-connect` connection object that is having the `data/callbacks-cache` behavior added
 * on to it.
 *
 * @return {{}} a `can-connect` connection containing the method implementations provided by `data/callbacks-cache`.
 *
 * ### Example
 * Shows synchronization between primary connection and cacheConnection data when using this behavior:
 * ```
 * import dataUrl from "can-connect/data/url/";
 * import dataCallbacks from "can-connect/data/callbacks/";
 * import cacheCallbacks from "can-connect/data/callbacks-cache/";
 * import memoryCache from "can-connect/data/memory-cache/";
 *
 * var cacheConnection = connect([memoryCache], {});
 * var todoConnection = connect([dataUrl, dataCallback, cacheCallbacks], {
 *   cacheConnection,
 *   url: "/todo"
 * });
 *
 * todoConnection.createData({name:'do the dishes', completed: false}).then(function(data) {
 *   todoConnection.cacheConnection.getData({id: data.id}).then(function(cachedData) {
 *     // data returned from connection and data returned from cache have the same contents
 *     data.id === cachedData.id; // true
 *     data.name === cachedData.name; // true
 *     data.completed === cachedData.completed; // true
 *     data === cachedData; // false, since callbacks-cache creates a copy of the data when adding it to the cache
 *   })
 * });
 * ```
 */

var assign = canReflect_1_19_2_canReflect.assignMap;
var each = canReflect_1_19_2_canReflect.each;

// wires up the following methods
var pairs = {
	/**
	 * @function can-connect/data/callbacks-cache/callbacks-cache.createdData createdData
	 * @parent can-connect/data/callbacks-cache/callbacks-cache
	 *
	 * Data callback that updates the [can-connect/base/base.cacheConnection cache] when a new data record is created.
	 *
	 * @signature `connection.createdData(responseData, requestData, cid)`
	 *
	 * Calls `createData` on the [can-connect/base/base.cacheConnection] to add a newly created data record to the cache.
	 * Calls and returns the response from any underlying behavior's `createdData` callback.
	 *
	 * @param {{}} responseData the data returned by the data creation request
	 * @param {{}} requestData the data that was passed to the data creation request
	 * @param {Number} cid the unique identifier for this data. Used before data has a [can-connect/base/base.id] added
	 * at creation time.
	 *
	 * @return {{}} the data returned from an underlying behavior's `createdData` callback, if one exists. Otherwise
	 * returns the `responseData`.
	 */
	createdData: "createData",

	/**
	 * @function can-connect/data/callbacks-cache/callbacks-cache.updatedData updatedData
	 * @parent can-connect/data/callbacks-cache/callbacks-cache
	 *
	 * Data callback that updates the [can-connect/base/base.cacheConnection cache] when a data record is modified.
	 *
	 * @signature `connection.updatedData(responseData, requestData)`
	 *
	 * Calls `updateData` on the [can-connect/base/base.cacheConnection] to modify a data record stored in the cache.
	 * Calls and returns the response from any underlying behavior's `updatedData` callback.
	 *
	 * @param {{}} responseData the data returned by the data update request
	 * @param {{}} requestData the data that was passed to the data update request
	 *
	 * @return {{}} the data returned from an underlying behavior's `updatedData` callback, if one exists. Otherwise
	 * returns the `responseData`.
	 */
	updatedData: "updateData",

	/**
	 * @function can-connect/data/callbacks-cache/callbacks-cache.destroyedData destroyedData
	 * @parent can-connect/data/callbacks-cache/callbacks-cache
	 *
	 * Data callback that updates the [can-connect/base/base.cacheConnection cache] when a data record is deleted.
	 *
	 * @signature `connection.destroyedData(responseData, requestData)`
	 *
	 * Calls `destroyData` on the [can-connect/base/base.cacheConnection] to remove a data record stored in the cache.
	 * Calls and returns the response from any underlying behavior's `destroyedData` callback.
	 *
	 * @param {{}} responseData the data returned by the data destroy request
	 * @param {{}} requestData the data that was passed to the data destroy request
	 *
	 * @return {{}} the data returned from an underlying behavior's `destroyedData` callback, if one exists. Otherwise
	 * returns the `responseData`.
	 */
	destroyedData: "destroyData"
};



var callbackCache = canConnect_4_0_6_canConnect.behavior("data/callbacks-cache",function(baseConnection){
	var behavior = {};

	each(pairs, function(crudMethod, dataCallback){
		behavior[dataCallback] = function(data, params, cid){

			// update the data in the cache
			this.cacheConnection[crudMethod]( assign(assign({}, params), data) );

			// return underlying dataCallback implementation if one exists or return input data
			if (baseConnection[dataCallback]) {
				return baseConnection[dataCallback].call(this, data, params, cid);
			} else {
				return data;
			}
		};
	});

	return behavior;
});

module.exports = callbackCache;

//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var validate$$1 = validate;
	module.exports = validate$$1(callbackCache, []);
}
//!steal-remove-end
});

var deferred = function(){
	var def = {};
	def.promise = new Promise(function(resolve, reject){
		def.resolve = resolve;
		def.reject = reject;
	});
	return def;
};

var forEach = [].forEach;
/**
 * @module can-connect/data/combine-requests/combine-requests combine-requests
 * @parent can-connect.behaviors
 * @group can-connect/data/combine-requests.options 1 behavior options
 * @group can-connect/data/combine-requests.types 2 types
 * @group can-connect/data/combine-requests.data-methods 3 data methods
 * @group can-connect/data/combine-requests.queryLogic 4 queryLogic methods
 *
 * Combines multiple incoming lists requests into a single list request when possible.
 *
 * @signature `combineRequests( baseConnection )`
 *
 * Implements [can-connect/data/combine-requests.getListData] to collect the requested sets for some
 * [can-connect/data/combine-requests.time].  Once the configured amount of time has passed, it tries to take the
 * [can-connect/data/combine-requests.unionPendingRequests union] of the requested sets. It then makes requests with
 * those unified sets. Once the unified set requests have returned, the original requests are resolved by taking
 * [can-connect/data/combine-requests.filterMembers subsets] of the unified response data.
 *
 * @param {{}} baseConnection `can-connect` connection object that is having the `combine-requests` behavior added
 * on to it. Should already contain a behavior that provides `getListData` (e.g [can-connect/data/url/url]). If
 * the `connect` helper is used to build the connection, the behaviors will automatically be ordered as required.
 *
 * @return {{}} a `can-connect` connection containing the method implementations provided by `combine-requests`.
 *
 * @body
 *
 * ## Use
 *
 * Create a connection with the `combine-requests` plugin:
 *
 * ```
 * var combineRequests = require("can-connect/data/combine-requests/");
 * var dataUrl = require("can-connect/data/url/");
 * var todosConnection = connect([dataUrl, combineRequests], {
 *   url: "/todos"
 * });
 * ```
 * Since the configuration above doesn't include the [can-connect/data/combine-requests.time] option, the following
 * will only make a single request if all requests are made during the same "thread of execution" (i.e. before the
 * browser takes a break from executing the current JavaScript):
 *
 * ```
 * todosConnection.getListData({})
 * todosConnection.getListData({filter: {userId: 5}});
 * todosConnection.getListData({filter: {userId: 5, type: "critical"}});
 * ```
 *
 * The above requests can all be joined since [can-set] intuitively knows that
 * `({filter: {userId: 5}}` and `{filter: {userId: 5, type: "critical"}}` are subsets of the complete set of todos, `{}`.
 *
 * For more advanced combining, a [can-query-logic queryLogic] must be configured. This allows `combine-requests` to understand
 * what certain parameters of a set mean, and how they might be combined.
 *
 *
 *
 */
var combineRequests = canConnect_4_0_6_canConnect.behavior("data/combine-requests",function(baseConnection){
	var pendingRequests; //[{set, deferred}]

	return {
		/**
		 * @function can-connect/data/combine-requests.unionPendingRequests unionPendingRequests
		 * @parent can-connect/data/combine-requests.queryLogic
		 *
		 * Group pending requests by the request that they are a subset of.
		 *
		 * @signature `connection.unionPendingRequests( pendingRequests )`
		 *
		 * This is called by [can-connect/data/combine-requests.getListData] to determine which pending requests can be unified
		 * into a broader request. This produces a grouping of 'parent' sets to 'child' requests whose data will be
		 * derived from the data retrieved by the parent.
		 *
		 * After this grouping is returned, [can-connect/data/combine-requests.getListData] executes requests for the parent
		 * sets. After a parent request succeeds, the child requests will have their data calculated from the parent data.
		 *
		 * @param {Array<can-connect/data/combine-requests.PendingRequest>} pendingRequests
		 * an array of objects, each containing:
		 *   - `set` - the requested set
		 *   - `deferred` - a wrapper around a `Promise` that will be resolved with this sets data
		 *
		 * @return {Array<{set: Set, pendingRequests: can-connect/data/combine-requests.PendingRequest}>}
		 * an array of each of the unified requests to be made.  Each unified request should have:
		 *   - `set` - the set to request
		 *   - `pendingRequests` - the array of [can-connect/data/combine-requests.PendingRequest pending requests] the `set` satisfies
		 *
		 * ### Example
		 *
		 * This function converts something like:
		 *
		 * ```
		 * [
		 *   {set: {completed: false}, deferred: def1},
		 *   {set: {completed: true}, deferred: def2}
		 * ]
		 * ```
		 *
		 * to:
		 *
		 * ```
		 * [
		 *   {
		 *    set: {},
		 *    pendingRequests: [
		 *      {set: {completed: false}, deferred: def1},
		 *      {set: {completed: true}, deferred: def2}
		 *    ]
		 *   }
		 * ]
		 * ```
		 *
		 */
		unionPendingRequests: function(pendingRequests){
			// this should try to merge existing param requests, into an array of
			// others to send out
			// but this data structure keeps the original promises.


			// we need the "biggest" sets first so they can swallow up everything else
			// O(n log n)
			var self = this;

			pendingRequests.sort(function(pReq1, pReq2){

				if(self.queryLogic.isSubset(pReq1.set, pReq2.set)) {
					return 1;
				} else if( self.queryLogic.isSubset(pReq2.set, pReq1.set) ) {
					return -1;
				} else {
					return 0;
				}

			});

			// O(n^2).  This can probably be made faster, but there are rarely lots of pending requests.
			var combineData = [];
			var current;

			doubleLoop(pendingRequests, {
				start: function(pendingRequest){
					current = {
						set: pendingRequest.set,
						pendingRequests: [pendingRequest]
					};
					combineData.push(current);
				},
				iterate: function(pendingRequest){
					var combined = self.queryLogic.union(current.set, pendingRequest.set);
					if( self.queryLogic.isDefinedAndHasMembers(combined) ) {
						// add next
						current.set = combined;
						current.pendingRequests.push(pendingRequest);
						// removes this from iteration
						return true;
					}
				}
			});

			return Promise.resolve(combineData);
		},

		/**
		 * @property {Number} can-connect/data/combine-requests.time time
		 * @parent can-connect/data/combine-requests.options
		 *
		 * Specifies the amount of time to wait to combine requests.
		 *
		 * @option {Number} Defaults to `1`, meaning only requests made within the same "thread of execution" will be
		 * combined (i.e. requests made before the browser takes a break from the ongoing JavaScript execution).
		 *
		 * Increasing this number will mean that requests are delayed that length of time in case other requests
		 * are made. In general, we advise against increasing this amount of time except in cases where loads take a
		 * significant amount of time and the increased delay is unlikely to be noticed.
		 *
		 * ```
		 * var combineRequests = require("can-connect/data/combine-requests/");
		 * connect([... combineRequests, ...],{
		 *   time: 100
		 * })
		 * ```
		 */
		time:1,

		/**
		 * @function can-connect/data/combine-requests.getListData getListData
		 * @parent can-connect/data/combine-requests.data-methods
		 *
		 * Combines multiple list data requests into a single request, when possible.
		 *
		 * @signature `connection.getListData( set )`
		 *
		 * Extension of [can-connect/connection.getListData `getListData`] that tries to combine calls to it into a single
		 * call. The calls are fulfilled by an underlying behavior's `getListData` implementation.
		 *
		 * Waits for a configured [can-connect/data/combine-requests.time] then tries to unify the sets requested during it.
		 * After unification, calls for the unified sets are made to the underlying `getListData`. Once the unified
		 * data has returned, the individual calls to `getListData` are resolved with a
		 * [can-query-logic.prototype.filterMembers calculated subset] of the unified data.
		 *
		 * @param {can-query-logic/query} query the parameters of the requested set of data
		 * @return {Promise<can-connect.listData>} `Promise` resolving the data of the requested set
		 */
		getListData: function(set){
			set = set || {};
			var self = this;

			if(!pendingRequests) {

				pendingRequests = [];

				setTimeout(function(){

					var combineDataPromise = self.unionPendingRequests(pendingRequests);
					pendingRequests = null;
					combineDataPromise.then(function(combinedData){
						// farm out requests
						forEach.call(combinedData, function(combined){
							// clone combine.set to prevent mutations by baseConnection.getListData
							var combinedSet = canReflect_1_19_2_canReflect.serialize(combined.set);

							baseConnection.getListData(combinedSet).then(function(data){
								if(combined.pendingRequests.length === 1) {
									combined.pendingRequests[0].deferred.resolve(data);
								} else {
									forEach.call(combined.pendingRequests, function(pending){
										// get the subset using the combine.set property before being passed down
										// to baseConnection.getListData which might mutate it causing combinedRequests
										// to resolve with an `undefined` value instead of an actual set
										// https://github.com/canjs/can-connect/issues/139
										pending.deferred.resolve( {data: self.queryLogic.filterMembers(pending.set, combined.set, getItems$1(data))} );
									});
								}
							}, function(err){
								if(combined.pendingRequests.length === 1) {
									combined.pendingRequests[0].deferred.reject(err);
								} else {
									forEach.call(combined.pendingRequests, function(pending){
										pending.deferred.reject(err);
									});
								}

							});
						});
					});


				}, this.time || 1);
			}
			var deferred$$1 = deferred();

			pendingRequests.push({deferred: deferred$$1, set: set});

			return deferred$$1.promise;
		}
	};
});

var combineRequests_1 = combineRequests;

//!steal-remove-start

var combineRequests_1 = validate(combineRequests, ['getListData']);
//!steal-remove-end

/**
 * @typedef {PendingRequest} can-connect/data/combine-requests.PendingRequest PendingRequest
 * @parent can-connect/data/combine-requests.types
 *
 * @description Type to keep track of the multiple requests that were unified into a single request.
 *
 * @type {PendingRequest} Record of an individual request that has been unified as part of the combined request. After
 * the unified request completes instances of these types are processed to complete the individual requests with the
 * subset of the unified data.
 *
 * @option {can-query-logic/query} query a requested [can-set/Set set] of data that has been unified into the combined request
 * @option {{}} deferred a type that keeps track of the individual [can-connect/data/combine-requests.getListData]
 * promise that will be resolved after the unified request completes
 */

// ### doubleLoop
var doubleLoop = function(arr, callbacks){
	var i = 0;
	while(i < arr.length) {
		callbacks.start(arr[i]);
		var j = i+1;
		while( j < arr.length ) {
			if(callbacks.iterate(arr[j]) === true) {
				arr.splice(j, 1);
			} else {
				j++;
			}
		}
		i++;
	}
};

var combineRequests$1 = combineRequests_1;

var canLocalStore_1_0_1_canLocalStore = canNamespace_1_0_0_canNamespace.localStore = function localStore(baseConnection){
    baseConnection.constructor = localStore;
    var behavior = Object.create(canMemoryStore_1_0_3_makeSimpleStore(baseConnection));

    canReflect_1_19_2_canReflect.assignMap(behavior, {
		clear: function(){
			localStorage.removeItem(this.name+"/queries");
			localStorage.removeItem(this.name+"/records");
            this._recordsMap = null;
            return Promise.resolve();
		},
		updateQueryDataSync: function(queries){
			localStorage.setItem(this.name+"/queries", JSON.stringify(queries) );
		},
		getQueryDataSync: function(){
			return JSON.parse( localStorage.getItem(this.name+"/queries") ) || [];
		},

		getRecord: function(id){
			// a little side-effectual mischeif for performance
			if(!this._recordsMap) {
				this.getAllRecords();
			}

			return this._recordsMap[id];
		},
		getAllRecords: function(){
			// this._records is a in memory representation so things can be fast
            // Must turn on `cacheLocalStorageReads` for this to work.
			if(!this.cacheLocalStorageReads || !this._recordsMap) {
				var recordsMap = JSON.parse( localStorage.getItem(this.name+"/records") ) || {};
				this._recordsMap = recordsMap;
			}

			var records = [];
			for(var id in this._recordsMap) {
				records.push(this._recordsMap[id]);
			}
			return records;
		},
		destroyRecords: function(records) {
            if(!this._recordsMap) {
				this.getAllRecords();
			}
			canReflect_1_19_2_canReflect.eachIndex(records, function(record){
				var id = canReflect_1_19_2_canReflect.getIdentity(record, this.queryLogic.schema);
				delete this._recordsMap[id];
			}, this);
			localStorage.setItem(this.name+"/records", JSON.stringify(this._recordsMap) );
		},
		updateRecordsSync: function(records){
            if(!this._recordsMap) {
				this.getAllRecords();
			}
			records.forEach(function(record){
				var id = canReflect_1_19_2_canReflect.getIdentity(record, this.queryLogic.schema);
				this._recordsMap[id] = record;
			},this);
			localStorage.setItem(this.name+"/records", JSON.stringify(this._recordsMap) );
		}
		// ## Identifiers

		/**
		 * @property {String} can-connect/data/localstorage-cache/localstorage-cache.name name
		 * @parent can-connect/data/localstorage-cache/localstorage-cache.identifiers
		 *
		 * Specify a name to use when saving data in localstorage.
		 *
		 * @option {String} This name is used to find and save data in
		 * localstorage. Instances are saved in `{name}/instance/{id}`
		 * and sets are saved in `{name}/set/{set}`.
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * ```
		 * var cacheConnection = connect(["data-localstorage-cache"],{
		 *   name: "todos"
		 * });
		 * ```
		 */


		// ## External interface

		/**
		 * @function can-connect/data/localstorage-cache/localstorage-cache.clear clear
		 * @parent can-connect/data/localstorage-cache/localstorage-cache.data-methods
		 *
		 * Resets the memory cache so it contains nothing.
		 *
		 * @signature `connection.clear()`
		 *
		 */



		/**
		 * @function can-connect/data/localstorage-cache/localstorage-cache.getSets getSets
		 * @parent can-connect/data/localstorage-cache/localstorage-cache.data-methods
		 *
		 * Returns the sets contained within the cache.
		 *
		 * @signature `connection.getSets(set)`
		 *
		 *   Returns the sets added by [can-connect/data/localstorage-cache/localstorage-cache.updateListData].
		 *
		 *   @return {Promise<Array<Set>>} A promise that resolves to the list of sets.
		 *
		 * @body
		 *
		 * ## Use
		 *
		 * ```
		 * connection.getSets() //-> Promise( [{type: "completed"},{user: 5}] )
		 * ```
		 *
		 */

		/**
		 * @function can-connect/data/localstorage-cache/localstorage-cache.getListData getListData
		 * @parent can-connect/data/localstorage-cache/localstorage-cache.data-methods
		 *
		 * Gets a set of data from localstorage.
		 *
		 * @signature `connection.getListData(set)`
		 *
		 *   Goes through each set add by [can-connect/data/memory-cache.updateListData]. If
		 *   `set` is a subset, uses [can-connect/base/base.queryLogic] to get the data for the requested `set`.
		 *
		 *   @param {can-query-logic/query} query An object that represents the data to load.
		 *
		 *   @return {Promise<can-connect.listData>} A promise that resolves if `set` is a subset of
		 *   some data added by [can-connect/data/memory-cache.updateListData].  If it is not,
		 *   the promise is rejected.
		 */

		/**
		 * @function can-connect/data/localstorage-cache.getListDataSync getListDataSync
		 * @parent can-connect/data/localstorage-cache.data-methods
		 *
		 * Synchronously gets a set of data from localstorage.
		 *
		 * @signature `connection.getListDataSync(set)`
		 * @hide
		 */

		/**
		 * @function can-connect/data/localstorage-cache/localstorage-cache.getData getData
		 * @parent can-connect/data/localstorage-cache/localstorage-cache.data-methods
		 *
		 * Get an instance's data from localstorage.
		 *
		 * @signature `connection.getData(params)`
		 *
		 *   Looks in localstorage for the requested instance.
		 *
		 *   @param {Object} params An object that should have the [conenction.id] of the element
		 *   being retrieved.
		 *
		 *   @return {Promise} A promise that resolves to the item if the memory cache has this item.
		 *   If localstorage does not have this item, it rejects the promise.
		 */


		/**
		 * @function can-connect/data/localstorage-cache/localstorage-cache.updateListData updateListData
		 * @parent can-connect/data/localstorage-cache/localstorage-cache.data-methods
		 *
		 * Saves a set of data in the cache.
		 *
		 * @signature `connection.updateListData(listData, set)`
		 *
		 *   Tries to merge this set of data with any other saved sets of data. If
		 *   unable to merge this data, saves the set by itself.
		 *
		 *   @param {can-connect.listData} listData
		 *   @param {can-query-logic/query} query
		 *   @return {Promise} Promise resolves if and when the data has been successfully saved.
		 */


		/**
		 * @function can-connect/data/localstorage-cache/localstorage-cache.createData createData
		 * @parent can-connect/data/localstorage-cache/localstorage-cache.data-methods
		 *
		 * Called when an instance is created and should be added to cache.
		 *
		 * @signature `connection.createData(props)`
		 *
		 *   Adds `props` to the stored list of instances. Then, goes
		 *   through every set and adds props the sets it belongs to.
		 */


		/**
		 * @function can-connect/data/localstorage-cache/localstorage-cache.updateData updateData
		 * @parent can-connect/data/localstorage-cache/localstorage-cache.data-methods
		 *
		 * Called when an instance is updated.
		 *
		 * @signature `connection.updateData(props)`
		 *
		 *   Overwrites the stored instance with the new props. Then, goes
		 *   through every set and adds or removes the instance if it belongs or not.
		 */


		/**
		 * @function can-connect/data/localstorage-cache/localstorage-cache.destroyData destroyData
		 * @parent can-connect/data/localstorage-cache/localstorage-cache.data-methods
		 *
		 * Called when an instance should be removed from the cache.
		 *
		 * @signature `connection.destroyData(props)`
		 *
		 *   Goes through each set of data and removes any data that matches
		 *   `props`'s [can-connect/base/base.id]. Finally removes this from the instance store.
		 */

	});

	return behavior;

};

/**
 * @module can-connect/data/localstorage-cache/localstorage-cache localstorage-cache
 * @parent can-connect.deprecated
 * @group can-connect/data/localstorage-cache/localstorage-cache.identifiers 0 identifiers
 * @group can-connect/data/localstorage-cache/localstorage-cache.data-methods 1 data methods
 *
 * Saves raw data in localStorage.
 *
 * @deprecated {5.0} Use [can-local-store] instead.
 *
 * @signature `localStorage( baseConnection )`
 *
 *   Creates a cache of instances and a cache of sets of instances that is
 *   accessible to read via [can-connect/data/localstorage-cache/localstorage-cache.getSets],
 *   [can-connect/data/localstorage-cache/localstorage-cache.getData], and [can-connect/data/localstorage-cache/localstorage-cache.getListData].
 *   The caches are updated via [can-connect/data/localstorage-cache/localstorage-cache.createData],
 *   [can-connect/data/localstorage-cache/localstorage-cache.updateData], [can-connect/data/localstorage-cache/localstorage-cache.destroyData],
 *   and [can-connect/data/localstorage-cache/localstorage-cache.updateListData].
 *
 *   [can-connect/data/localstorage-cache/localstorage-cache.createData],
 *   [can-connect/data/localstorage-cache/localstorage-cache.updateData],
 *   [can-connect/data/localstorage-cache/localstorage-cache.destroyData] are able to move items in and out
 *   of sets.
 *
 * @body
 *
 * ## Use
 *
 * `data/localstorage-cache` is often used with a caching strategy like [can-connect/fall-through-cache/fall-through-cache] or
 * [can-connect/cache-requests/cache-requests].  Make sure you configure the connection's [can-connect/data/localstorage-cache/localstorage-cache.name].
 *
 * ```
 * var cacheConnection = connect([
 *   require("can-connect/data/localstorage-cache/localstorage-cache")
 * ],{
 *   name: "todos"
 * });
 *
 * var todoConnection = connect([
 *   require("can-connect/data/url/url"),
 *   require("can-connect/fall-through-cache/fall-through-cache")
 * ],
 * {
 *   url: "/services/todos",
 *   cacheConnection: cacheConnection
 * });
 * ```
 *
 */
 
var localstorageCache = canLocalStore_1_0_1_canLocalStore;

/**
 * @module can-connect/data/memory-cache/memory-cache memory-cache
 * @parent can-connect.deprecated
 * @group can-connect/data/memory-cache/memory-cache.data-methods data methods
 *
 * Saves raw data in JavaScript memory that disappears when the page refreshes.
 *
 * @deprecated {5.0} Use [can-memory-store] instead.
 *
 * @signature `memoryCache( baseConnection )`
 *
 *   Creates a cache of instances and a cache of sets of instances that is
 *   accessible to read via [can-connect/data/memory-cache/memory-cache.getSets],
 *   [can-connect/data/memory-cache/memory-cache.getData], and [can-connect/data/memory-cache/memory-cache.getListData].
 *   The caches are updated via [can-connect/data/memory-cache/memory-cache.createData],
 *   [can-connect/data/memory-cache/memory-cache.updateData], [can-connect/data/memory-cache/memory-cache.destroyData],
 *   and [can-connect/data/memory-cache/memory-cache.updateListData].
 *
 *   [can-connect/data/memory-cache/memory-cache.createData],
 *   [can-connect/data/memory-cache/memory-cache.updateData],
 *   [can-connect/data/memory-cache/memory-cache.destroyData] are able to move items in and out
 *   of sets.
 *
 * @body
 *
 * ## Use
 *
 * `data/memory-cache` is often used with a caching strategy like [can-connect/fall-through-cache/fall-through-cache] or
 * [can-connect/cache-requests/cache-requests].
 *
 * ```js
 * var cacheConnection = connect([
 *   require("can-connect/data/memory-cache/memory-cache")
 * ],{});
 *
 * var todoConnection = connect([
 *   require("can-connect/data/url/url"),
 *   require("can-connect/fall-through-cache/fall-through-cache")
 * ],
 * {
 *   url: "/services/todos",
 *   cacheConnection: cacheConnection
 * });
 * ```
 */


var memoryCache = canMemoryStore_1_0_3_canMemoryStore;

var fallThroughCache_1 = createCommonjsModule(function (module) {
/**
 * @module can-connect/fall-through-cache/fall-through-cache fall-through-cache
 * @parent can-connect.behaviors
 * @group can-connect/fall-through-cache/fall-through-cache.data data callbacks
 * @group can-connect/fall-through-cache/fall-through-cache.hydrators hydrators
 *
 * Add fall-through caching with the `cacheConnection`.
 *
 * @signature `fallThroughCache( baseConnection )`
 *
 *   Implements a `getData` and `getListData` that
 *   check their [can-connect/base/base.cacheConnection] for data. If there is data,
 *   this data will be immediately returned.
 *   In the background, the `baseConnection` method will be called and used to update the instance or list.
 *
 * @body
 *
 * ## Use
 *
 * To use the `fall-through-cache`, create a connection with a
 * [can-connect/base/base.cacheConnection] and a behavior that implements
 * [can-connect/connection.getData] and [can-connect/connection.getListData].
 *
 * ```js
 * var QueryLogic = require("can-query-logic");
 *
 * var queryLogic = new QueryLogic();
 *
 * var cache = connect([
 *   require("can-local-store")
 * ],{
 *   name: "todos",
 *   queryLogic: queryLogic
 * });
 *
 * var todoConnection = connect([
 *    require("can-connect/fall-through-cache/fall-through-cache"),
 *    require("can-connect/data/url/url"),
 *    require("can-connect/constructor/constructor"),
 *    require("can-connect/constructor/store/store")
 *   ], {
 *   url: "/todos",
 *   cacheConnection: cache,
 *   queryLogic: queryLogic
 * });
 * ```
 *
 * Then, make requests.  If the cache has the data,
 * it will be returned immediately, and then the item or list updated later
 * with the response from the base connection:
 *
 * ```js
 * todoConnection.getList({due: "today"}).then(function(todos){
 *
 * })
 * ```
 *
 * ## Demo
 *
 * The following shows the `fall-through-cache` behavior.
 *
 * @demo demos/can-connect/fall-through-cache.html
 *
 * Clicking
 * "Completed" or "Incomplete" will make one of the following requests and
 * display the results in the page:
 *
 * ```
 * todoConnection.getList({completed: true});
 * todoConnection.getList({completed: false});
 * ```
 *
 * If you click back and forth between "Completed" and "Incomplete" multiple times
 * you'll notice that the old data is displayed immediately and then
 * updated after about a second.
 *
 */




var fallThroughCache = canConnect_4_0_6_canConnect.behavior("fall-through-cache",function(baseConnection){

	var behavior = {
		/**
		 * @function can-connect/fall-through-cache/fall-through-cache.hydrateList hydrateList
		 * @parent can-connect/fall-through-cache/fall-through-cache.hydrators
		 *
		 * Returns a List instance given raw data.
		 *
		 * @signature `connection.hydrateList(listData, set)`
		 *
		 *   Calls the base `hydrateList` to create a List for `listData`.
		 *
		 *   Then, Looks for registered hydrateList callbacks for a given `set` and
		 *   calls them.
		 *
		 *   @param {can-connect.listData} listData
		 *   @param {can-query-logic/query} query
		 *   @return {can-connect.List}
		 */
		hydrateList: function(listData, set){
			set = set || this.listQuery(listData);
			var id = sortedSetJson( set );
			var list = baseConnection.hydrateList.call(this, listData, set);

			if(this._getHydrateListCallbacks[id]) {
				this._getHydrateListCallbacks[id].shift()(list);
				if(!this._getHydrateListCallbacks[id].length){
					delete this._getHydrateListCallbacks[id];
				}
			}
			return list;
		},
		_getHydrateListCallbacks: {},
		_getHydrateList: function(set, callback){
			var id = sortedSetJson( set );
			if(!this._getHydrateListCallbacks[id]) {
				this._getHydrateListCallbacks[id]= [];
			}
			this._getHydrateListCallbacks[id].push(callback);
		},
		/**
		 * @function can-connect/fall-through-cache/fall-through-cache.getListData getListData
		 * @parent can-connect/fall-through-cache/fall-through-cache.data
		 *
		 * Get raw data from the cache if available, and then update
		 * the list later with data from the base connection.
		 *
		 * @signature `connection.getListData(set)`
		 *
		 *   Checks the [can-connect/base/base.cacheConnection] for `set`'s data.
		 *
		 *   If the cache connection has data, the cached data is returned. Prior to
		 *   returning the data, the [can-connect/constructor.hydrateList] method
		 *   is intercepted so we can get a handle on the list that's being created
		 *   for the returned data. Once the intercepted list is retrieved,
		 *   we use the base connection to get data and update the intercepted list and
		 *   the cacheConnection.
		 *
		 *   If the cache connection does not have data, the base connection
		 *   is used to load the data and the cached connection is updated with that
		 *   data.
		 *
		 *   @param {can-query-logic/query} query The set to load.
		 *
		 *   @return {Promise<can-connect.listData>} A promise that returns the
		 *   raw data.
		 */
		// if we do getList, the cacheConnection runs on
		// if we do getListData, ... we need to register the list that is going to be created
		// so that when the data is returned, it updates this
		getListData: function(set){
			set = set || {};
			var self = this;
			return this.cacheConnection.getListData(set).then(function(data){

				// get the list that is going to be made
				// it might be possible that this never gets called, but not right now
				self._getHydrateList(set, function(list){
					self.addListReference(list, set);

					setTimeout(function(){
						baseConnection.getListData.call(self, set).then(function(listData){

							self.cacheConnection.updateListData(listData, set);
							self.updatedList(list, listData, set);
							self.deleteListReference(list, set);

						}, function(e){
							// what do we do here?  self.rejectedUpdatedList ?
							canLog_1_0_2_canLog.log("REJECTED", e);
						});
					},1);
				});
				// TODO: if we wired up all responses to updateListData, this one should not
				// updateListData with itself.
				// But, how would we do a bypass?
				return data;
			}, function(){

				var listData = baseConnection.getListData.call(self, set);
				listData.then(function(listData){

					self.cacheConnection.updateListData(listData, set);
				});

				return listData;
			});
		},
		/**
		 * @function can-connect/fall-through-cache/fall-through-cache.hydrateInstance hydrateInstance
		 * @parent can-connect/fall-through-cache/fall-through-cache.hydrators
		 *
		 * Returns an instance given raw data.
		 *
		 * @signature `connection.hydrateInstance(props)`
		 *
		 *   Calls the base `hydrateInstance` to create an Instance for `props`.
		 *
		 *   Then, Looks for registered hydrateInstance callbacks for a given [can-connect/base/base.id] and
		 *   calls them.
		 *
		 *   @param {Object} props
		 *   @return {can-connect/Instance}
		 */
		hydrateInstance: function(props){

			var id = this.id( props );
			var instance = baseConnection.hydrateInstance.apply(this, arguments);

			if(this._getMakeInstanceCallbacks[id]) {
				this._getMakeInstanceCallbacks[id].shift()(instance);
				if(!this._getMakeInstanceCallbacks[id].length){
					delete this._getMakeInstanceCallbacks[id];
				}
			}
			return instance;
		},
		_getMakeInstanceCallbacks: {},
		_getMakeInstance: function(id, callback){
			if(!this._getMakeInstanceCallbacks[id]) {
				this._getMakeInstanceCallbacks[id]= [];
			}
			this._getMakeInstanceCallbacks[id].push(callback);
		},
		/**
		 * @function can-connect/fall-through-cache/fall-through-cache.getData getData
		 * @parent can-connect/fall-through-cache/fall-through-cache.data
		 *
		 * Get raw data from the cache if available, and then update
		 * the instance later with data from the base connection.
		 *
		 * @signature `connection.getData(params)`
		 *
		 *   Checks the [can-connect/base/base.cacheConnection] for `params`'s data.
		 *
		 *   If the cache connection has data, the cached data is returned. Prior to
		 *   returning the data, the [can-connect/constructor/constructor.hydrateInstance] method
		 *   is intercepted so we can get a handle on the instance that's being created
		 *   for the returned data. Once the intercepted instance is retrieved,
		 *   we use the base connection to get data and update the intercepted instance and
		 *   the cacheConnection.
		 *
		 *   If the cache connection does not have data, the base connection
		 *   is used to load the data and the cached connection is updated with that
		 *   data.
		 *
		 *   @param {Object} params The set to load.
		 *
		 *   @return {Promise<Object>} A promise that returns the
		 *   raw data.
		 */
		getData: function(params){
			// first, always check the cache connection
			var self = this;
			return this.cacheConnection.getData(params).then(function(instanceData){

				// get the list that is going to be made
				// it might be possible that this never gets called, but not right now
				self._getMakeInstance(self.id(instanceData) || self.id(params), function(instance){
					self.addInstanceReference(instance);

					setTimeout(function(){
						baseConnection.getData.call(self, params).then(function(instanceData2){

							self.cacheConnection.updateData(instanceData2);
							self.updatedInstance(instance, instanceData2);
							self.deleteInstanceReference(instance);

						}, function(e){
							// what do we do here?  self.rejectedUpdatedList ?
							canLog_1_0_2_canLog.log("REJECTED", e);
						});
					},1);
				});

				return instanceData;
			}, function(){
				var listData = baseConnection.getData.call(self, params);
				listData.then(function(instanceData){
					self.cacheConnection.updateData(instanceData);
				});

				return listData;
			});
		}

	};

	return behavior;

});

module.exports = fallThroughCache;

//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	var validate$$1 = validate;
	module.exports = validate$$1(fallThroughCache, ['hydrateList', 'hydrateInstance', 'getListData', 'getData']);
}
//!steal-remove-end
});

var canStringToAny_1_2_1_canStringToAny = function(str){
	switch(str) {
		case "NaN":
		case "Infinity":
			return +str;
		case "null":
			return null;
		case "undefined":
			return undefined;
		case "true":
		case "false":
			return str === "true";
		default:
			var val = +str;
			if(!isNaN(val)) {
				return val;
			} else {
				return str;
			}
	}
};

function toBoolean(val) {
	if(val == null) {
		return val;
	}
	if (val === 'false' || val === '0' || !val) {
		return false;
	}
	return true;
}

var maybeBoolean = canReflect_1_19_2_canReflect.assignSymbols(toBoolean,{
	"can.new": toBoolean,
	"can.getSchema": function(){
		return {
			type: "Or",
			values: [true, false, undefined, null]
		};
	},
    "can.getName": function(){
        return "MaybeBoolean";
    },
	"can.isMember": function(value) {
		return value == null || typeof value === "boolean";
	}
});

function toDate(str) {
	var type = typeof str;
	if (type === 'string') {
		str = Date.parse(str);
		return isNaN(str) ? null : new Date(str);
	} else if (type === 'number') {
		return new Date(str);
	} else {
		return str;
	}
}

function DateStringSet(dateStr){
	this.setValue = dateStr;
	var date = toDate(dateStr);
	this.value = date == null ? date : date.getTime();
}
DateStringSet.prototype.valueOf = function(){
	return this.value;
};
canReflect_1_19_2_canReflect.assignSymbols(DateStringSet.prototype,{
	"can.serialize": function(){
		return this.setValue;
	}
});

var maybeDate = canReflect_1_19_2_canReflect.assignSymbols(toDate,{
	"can.new": toDate,
	"can.getSchema": function(){
		return {
			type: "Or",
			values: [Date, undefined, null]
		};
	},
	"can.ComparisonSetType": DateStringSet,
    "can.getName": function(){
        return "MaybeDate";
    },
	"can.isMember": function(value) {
		return value == null || (value instanceof Date);
	}
});

function toNumber(val) {
	if (val == null) {
		return val;
	}
	return +(val);
}

var maybeNumber = canReflect_1_19_2_canReflect.assignSymbols(toNumber,{
	"can.new": toNumber,
	"can.getSchema": function(){
		return {
			type: "Or",
			values: [Number, undefined, null]
		};
	},
    "can.getName": function(){
        return "MaybeNumber";
    },
	"can.isMember": function(value) {
		return value == null || typeof value === "number";
	}
});

function toString$2(val) {
	if (val == null) {
		return val;
	}
	return '' + val;
}

var maybeString = canReflect_1_19_2_canReflect.assignSymbols(toString$2,{
	"can.new": toString$2,
	"can.getSchema": function(){
		return {
			type: "Or",
			values: [String, undefined, null]
		};
	},
    "can.getName": function(){
        return "MaybeString";
    },
	"can.isMember": function(value) {
		return value == null || typeof value === "string";
	}
});

var newSymbol$4 = canSymbol_1_7_0_canSymbol.for("can.new"),
	serializeSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.serialize"),
	inSetupSymbol$6 = canSymbol_1_7_0_canSymbol.for("can.initializing");

var eventsProto$1, define$1,
	make$1, makeDefinition$1, getDefinitionsAndMethods$1, getDefinitionOrMethod$1;

// UTILITIES
function isDefineType$1(func){
	return func && (func.canDefineType === true || func[newSymbol$4] );
}

var peek$4 = canObservationRecorder_1_3_1_canObservationRecorder.ignore(canReflect_1_19_2_canReflect.getValue.bind(canReflect_1_19_2_canReflect));

var Object_defineNamedPrototypeProperty$1 = Object.defineProperty;
//!steal-remove-start
if(process.env.NODE_ENV !== 'production') {
	Object_defineNamedPrototypeProperty$1 = function(obj, prop, definition) {
		if (definition.get) {
			Object.defineProperty(definition.get, "name", {
				value: "get "+canReflect_1_19_2_canReflect.getName(obj) + "."+prop,
				writable: true,
				configurable: true
			});
		}
		if (definition.set) {
			Object.defineProperty(definition.set, "name", {
				value:  "set "+canReflect_1_19_2_canReflect.getName(obj) + "."+prop,
				configurable: true
			});
		}
		return Object.defineProperty(obj, prop, definition);
	};
}
//!steal-remove-end


function defineConfigurableAndNotEnumerable$1(obj, prop, value) {
	Object.defineProperty(obj, prop, {
		configurable: true,
		enumerable: false,
		writable: true,
		value: value
	});
}

function eachPropertyDescriptor$1(map, cb){
	for(var prop in map) {
		if(map.hasOwnProperty(prop)) {
			cb.call(map, prop, Object.getOwnPropertyDescriptor(map,prop));
		}
	}
}

function getEveryPropertyAndSymbol$1(obj) {
	var props = Object.getOwnPropertyNames(obj);
	var symbols = ("getOwnPropertySymbols" in Object) ?
	  Object.getOwnPropertySymbols(obj) : [];
	return props.concat(symbols);
}

function cleanUpDefinition(prop, definition, shouldWarn, typePrototype){
	// cleanup `value` -> `default`
	if(definition.value !== undefined && ( typeof definition.value !== "function" || definition.value.length === 0) ){

		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			if(shouldWarn) {
				dev.warn(
					"can-define: Change the 'value' definition for " + canReflect_1_19_2_canReflect.getName(typePrototype)+"."+prop + " to 'default'."
				);
			}
		}
		//!steal-remove-end

		definition.default = definition.value;
		delete definition.value;
	}
	// cleanup `Value` -> `DEFAULT`
	if(definition.Value !== undefined  ){
		//!steal-remove-start
		if(process.env.NODE_ENV !== 'production') {
			if(shouldWarn) {
				dev.warn(
					"can-define: Change the 'Value' definition for " + canReflect_1_19_2_canReflect.getName(typePrototype)+"."+prop + " to 'Default'."
				);
			}
		}
		//!steal-remove-end
		definition.Default = definition.Value;
		delete definition.Value;
	}
}

function isValueResolver(definition) {
	// there's a function and it has one argument
	return typeof definition.value === "function" && definition.value.length;
}

var canDefine_2_8_1_canDefine = define$1 = canNamespace_1_0_0_canNamespace.define = function(typePrototype, defines, baseDefine) {
	// default property definitions on _data
	var prop,
		dataInitializers = Object.create(baseDefine ? baseDefine.dataInitializers : null),
		// computed property definitions on _computed
		computedInitializers = Object.create(baseDefine ? baseDefine.computedInitializers : null);

	var result = getDefinitionsAndMethods$1(defines, baseDefine, typePrototype);
	result.dataInitializers = dataInitializers;
	result.computedInitializers = computedInitializers;


	// Goes through each property definition and creates
	// a `getter` and `setter` function for `Object.defineProperty`.
	canReflect_1_19_2_canReflect.eachKey(result.definitions, function(definition, property){
		define$1.property(typePrototype, property, definition, dataInitializers, computedInitializers, result.defaultDefinition);
	});

	// Places a `_data` on the prototype that when first called replaces itself
	// with a `_data` object local to the instance.  It also defines getters
	// for any value that has a default value.
	if(typePrototype.hasOwnProperty("_data")) {
		for (prop in dataInitializers) {
			canDefineLazyValue_1_1_1_defineLazyValue(typePrototype._data, prop, dataInitializers[prop].bind(typePrototype), true);
		}
	} else {
		canDefineLazyValue_1_1_1_defineLazyValue(typePrototype, "_data", function() {
			var map = this;
			var data = {};
			for (var prop in dataInitializers) {
				canDefineLazyValue_1_1_1_defineLazyValue(data, prop, dataInitializers[prop].bind(map), true);
			}
			return data;
		});
	}

	// Places a `_computed` on the prototype that when first called replaces itself
	// with a `_computed` object local to the instance.  It also defines getters
	// that will create the property's compute when read.
	if(typePrototype.hasOwnProperty("_computed")) {
		for (prop in computedInitializers) {
			canDefineLazyValue_1_1_1_defineLazyValue(typePrototype._computed, prop, computedInitializers[prop].bind(typePrototype));
		}
	} else {
		canDefineLazyValue_1_1_1_defineLazyValue(typePrototype, "_computed", function() {
			var map = this;
			var data = Object.create(null);
			for (var prop in computedInitializers) {
				canDefineLazyValue_1_1_1_defineLazyValue(data, prop, computedInitializers[prop].bind(map));
			}
			return data;
		});
	}

	// Add necessary event methods to this object.
	getEveryPropertyAndSymbol$1(eventsProto$1).forEach(function(prop){
		Object.defineProperty(typePrototype, prop, {
			enumerable: false,
			value: eventsProto$1[prop],
			configurable: true,
			writable: true
		});
	});
	// also add any symbols
	// add so instance defs can be dynamically added
	Object.defineProperty(typePrototype,"_define",{
		enumerable: false,
		value: result,
		configurable: true,
		writable: true
	});

	// Places Symbol.iterator or @@iterator on the prototype
	// so that this can be iterated with for/of and canReflect.eachIndex
	var iteratorSymbol = canSymbol_1_7_0_canSymbol.iterator || canSymbol_1_7_0_canSymbol.for("iterator");
	if(!typePrototype[iteratorSymbol]) {
		defineConfigurableAndNotEnumerable$1(typePrototype, iteratorSymbol, function(){
			return new define$1.Iterator(this);
		});
	}

	return result;
};

var onlyType$1 = function(obj){
	for(var prop in obj) {
		if(prop !== "type") {
			return false;
		}
	}
	return true;
};

define$1.extensions = function () {};

// typePrototype - the prototype of the type we are defining `prop` on.
// `definition` - the user provided definition
define$1.property = function(typePrototype, prop, definition, dataInitializers, computedInitializers, defaultDefinition) {
	var propertyDefinition = define$1.extensions.apply(this, arguments);

	if (propertyDefinition) {
		definition = makeDefinition$1(prop, propertyDefinition, defaultDefinition || {}, typePrototype);
	}

	var type = definition.type;

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		var hasZeroArgGetter = definition.get && definition.get.length === 0;
		var noSetter = !definition.set;
		var defaultInDefinition = ( "default" in definition || "Default" in definition );
		var typeInDefinition = (definition.type && defaultDefinition && definition.type !== defaultDefinition.type) ||
			(definition.Type && defaultDefinition && definition.Type !== defaultDefinition.Type);

		if(hasZeroArgGetter && noSetter && defaultInDefinition) {
			var defaultOrDefault = "default" in definition ? "default" : "Default";
				dev.warn("can-define: " + defaultOrDefault + " value for property " +
						canReflect_1_19_2_canReflect.getName(typePrototype)+"."+ prop +
						" ignored, as its definition has a zero-argument getter");
		}

		if(hasZeroArgGetter && noSetter && typeInDefinition) {
			var typeOrType = definition.type ? "type" : "Type";
			dev.warn("can-define: " + typeOrType + " value for property " +
					canReflect_1_19_2_canReflect.getName(typePrototype)+"."+ prop +
					" ignored, as its definition has a zero-argument getter");
		}

		if (type && canReflect_1_19_2_canReflect.isConstructorLike(type) && !isDefineType$1(type)) {
			dev.warn(
				"can-define: the definition for " + canReflect_1_19_2_canReflect.getName(typePrototype) + "."+
                prop +
				" uses a constructor for \"type\". Did you mean \"Type\"?"
			);
		}
	}
	//!steal-remove-end

	// Special case definitions that have only `type: "*"`.
	if (type && onlyType$1(definition) && type === define$1.types["*"]) {
		Object_defineNamedPrototypeProperty$1(typePrototype, prop, {
			get: make$1.get.data(prop),
			set: make$1.set.events(prop, make$1.get.data(prop), make$1.set.data(prop), make$1.eventType.data(prop)),
			enumerable: true,
			configurable: true
		});
		return;
	}
	definition.type = type;

	// Where the value is stored.  If there is a `get` the source of the value
	// will be a compute in `this._computed[prop]`.  If not, the source of the
	// value will be in `this._data[prop]`.
	var dataProperty = definition.get || isValueResolver(definition) ? "computed" : "data",

		// simple functions that all read/get/set to the right place.
		// - reader - reads the value but does not observe.
		// - getter - reads the value and notifies observers.
		// - setter - sets the value.
		reader = make$1.read[dataProperty](prop),
		getter = make$1.get[dataProperty](prop),
		setter = make$1.set[dataProperty](prop),
		getInitialValue;

	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		if (definition.get) {
			Object.defineProperty(definition.get, "name", {
				value: canReflect_1_19_2_canReflect.getName(typePrototype) + "'s " + prop + " getter",
				configurable: true
			});
		}
		if (definition.set) {
			Object.defineProperty(definition.set, "name", {
				value: canReflect_1_19_2_canReflect.getName(typePrototype) + "'s " + prop + " setter",
				configurable: true
			});
		}
		if(isValueResolver(definition)) {
			Object.defineProperty(definition.value, "name", {
				value: canReflect_1_19_2_canReflect.getName(typePrototype) + "'s " + prop + " value",
				configurable: true
			});
		}
	}
	//!steal-remove-end

	// Determine the type converter
	var typeConvert = function(val) {
		return val;
	};

	if (definition.Type) {
		typeConvert = make$1.set.Type(prop, definition.Type, typeConvert);
	}
	if (type) {
		typeConvert = make$1.set.type(prop, type, typeConvert);
	}

	// make a setter that's going to fire of events
	var eventsSetter = make$1.set.events(prop, reader, setter, make$1.eventType[dataProperty](prop));
	if(isValueResolver(definition)) {
		computedInitializers[prop] = make$1.valueResolver(prop, definition, typeConvert);
	}
	// Determine a function that will provide the initial property value.
	else if ((definition.default !== undefined || definition.Default !== undefined)) {

		//!steal-remove-start
		if (process.env.NODE_ENV !== 'production') {
			// If value is an object or array, give a warning
			if (definition.default !== null && typeof definition.default === 'object') {
				dev.warn("can-define: The default value for " + canReflect_1_19_2_canReflect.getName(typePrototype)+"."+prop + " is set to an object. This will be shared by all instances of the DefineMap. Use a function that returns the object instead.");
			}
			// If value is a constructor, give a warning
			if (definition.default && canReflect_1_19_2_canReflect.isConstructorLike(definition.default)) {
				dev.warn("can-define: The \"default\" for " + canReflect_1_19_2_canReflect.getName(typePrototype)+"."+prop + " is set to a constructor. Did you mean \"Default\" instead?");
			}
		}
		//!steal-remove-end

		getInitialValue = canObservationRecorder_1_3_1_canObservationRecorder.ignore(make$1.get.defaultValue(prop, definition, typeConvert, eventsSetter));
	}

	// If property has a getter, create the compute that stores its data.
	if (definition.get) {
		computedInitializers[prop] = make$1.compute(prop, definition.get, getInitialValue);
	}
	// If the property isn't a getter, but has an initial value, setup a
	// default value on `this._data[prop]`.
	else if (getInitialValue) {
		dataInitializers[prop] = getInitialValue;
	}


	// Define setter behavior.

	// If there's a `get` and `set`, make the setter get the `lastSetValue` on the
	// `get`'s compute.
	if (definition.get && definition.set) {
		// the compute will set off events, so we can use the basic setter
		setter = make$1.set.setter(prop, definition.set, make$1.read.lastSet(prop), setter, true);

        // If there's zero-arg `get`, warn on all sets in dev mode
        if (definition.get.length === 0 ) {
            //!steal-remove-start
            if(process.env.NODE_ENV !== 'production') {
                dev.warn("can-define: Set value for property " +
                    canReflect_1_19_2_canReflect.getName(typePrototype)+"."+ prop +
                    " ignored, as its definition has a zero-argument getter");
            }
            //!steal-remove-end
        }
	}
	// If there's a `set` and no `get`,
	else if (definition.set) {
		// Add `set` functionality to the eventSetter.
		setter = make$1.set.setter(prop, definition.set, reader, eventsSetter, false);
	}
	// If there's neither `set` or `get` or `value` (resolver)
	else if (dataProperty === "data") {
		// make a set that produces events.
		setter = eventsSetter;
	}
	// If there's zero-arg `get` but not `set`, warn on all sets in dev mode
	else if (definition.get && definition.get.length < 1) {
		setter = function() {
			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				dev.warn("can-define: Set value for property " +
					canReflect_1_19_2_canReflect.getName(typePrototype)+"."+ prop +
					" ignored, as its definition has a zero-argument getter and no setter");
			}
			//!steal-remove-end
		};
	}

	// Add type behavior to the setter.
	if (type) {
		setter = make$1.set.type(prop, type, setter);
	}
	if (definition.Type) {
		setter = make$1.set.Type(prop, definition.Type, setter);
	}

	// Define the property.
	Object_defineNamedPrototypeProperty$1(typePrototype, prop, {
		get: getter,
		set: setter,
		enumerable: "serialize" in definition ? !!definition.serialize : !definition.get,
		configurable: true
	});
};
define$1.makeDefineInstanceKey = function(constructor) {
	constructor[canSymbol_1_7_0_canSymbol.for("can.defineInstanceKey")] = function(property, value) {
		var defineResult = this.prototype._define;
		if(typeof value === "object") {
			// change `value` to default.
			cleanUpDefinition(property, value, false, this);
		}
		var definition = getDefinitionOrMethod$1(property, value, defineResult.defaultDefinition, this);
		if(definition && typeof definition === "object") {
			define$1.property(constructor.prototype, property, definition, defineResult.dataInitializers, defineResult.computedInitializers, defineResult.defaultDefinition);
			defineResult.definitions[property] = definition;
		} else {
			defineResult.methods[property] = definition;
		}

		this.prototype.dispatch({
			action: "can.keys",
			type: "can.keys", // TODO: Remove in 6.0
			target: this.prototype
		});
	};
};

// Makes a simple constructor function.
define$1.Constructor = function(defines, sealed) {
	var constructor = function DefineConstructor(props) {
		Object.defineProperty(this, inSetupSymbol$6, {
			configurable: true,
			enumerable: false,
			value: true,
			writable: true
		});
		define$1.setup.call(this, props, sealed);
		this[inSetupSymbol$6] = false;
	};
	var result = define$1(constructor.prototype, defines);
	type$1(constructor);
	define$1.makeDefineInstanceKey(constructor, result);
	return constructor;
};

// A bunch of helper functions that are used to create various behaviors.
make$1 = {

	computeObj: function(map, prop, observable) {
		var computeObj = {
			oldValue: undefined,
			compute: observable,
			count: 0,
			handler: function(newVal) {
				var oldValue = computeObj.oldValue;
				computeObj.oldValue = newVal;

				map.dispatch({
					action: "set",
					key: "prop",
					target: map,
					value: newVal,
					oldValue: oldValue,
					type: prop, // TODO: Remove in 6.0
				}, [newVal, oldValue]);
			}
		};
		return computeObj;
	},
	valueResolver: function(prop, definition, typeConvert) {
		var getDefault = make$1.get.defaultValue(prop, definition, typeConvert);
		return function(){
			var map = this;
			var defaultValue = getDefault.call(this);
			var computeObj = make$1.computeObj(map, prop, new resolver(definition.value, map, defaultValue));
			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				Object.defineProperty(computeObj.handler, "name", {
					value: canReflect_1_19_2_canReflect.getName(definition.value).replace('value', 'event emitter')
				});
			}
			//!steal-remove-end
			return computeObj;
		};
	},
	// Returns a function that creates the `_computed` prop.
	compute: function(prop, get, defaultValueFn) {

		return function() {
			var map = this,
				defaultValue = defaultValueFn && defaultValueFn.call(this),
				observable, computeObj;

			if(get.length === 0) {
				observable = new canObservation_4_2_0_canObservation(get, map);
			} else if(get.length === 1) {
				observable = new settable(get, map, defaultValue);
			} else {
				observable = new async(get, map, defaultValue);
			}

			computeObj = make$1.computeObj(map, prop, observable);

			//!steal-remove-start
			if(process.env.NODE_ENV !== 'production') {
				Object.defineProperty(computeObj.handler, "name", {
					value: canReflect_1_19_2_canReflect.getName(get).replace('getter', 'event emitter')
				});
			}
			//!steal-remove-end

			return computeObj;
		};
	},
	// Set related helpers.
	set: {
		data: function(prop) {
			return function(newVal) {
				this._data[prop] = newVal;
			};
		},
		computed: function(prop) {
			return function(val) {
				canReflect_1_19_2_canReflect.setValue( this._computed[prop].compute, val );
			};
		},
		events: function(prop, getCurrent, setData, eventType) {
			return function(newVal) {
				if (this[inSetupSymbol$6]) {
					setData.call(this, newVal);
				}
				else {
					var current = getCurrent.call(this);
					if (newVal === current) {
						return;
					}
					var dispatched;
					setData.call(this, newVal);

						dispatched = {
							patches: [{type: "set", key: prop, value: newVal}],
							target: this,
							action: "set",
							value: newVal,
							oldValue: current,
							key: prop,
							type: prop // TODO: Remove in 6.0
						};

					//!steal-remove-start
					if(process.env.NODE_ENV !== 'production') {
						var lastItem, lastFn;
						dispatched.reasonLog = [ canReflect_1_19_2_canReflect.getName(this) + "'s", prop, "changed to", newVal, "from", current ];

						// If there are observations currently recording, this isn't a good time to
						//   mutate values: it's likely a cycle, and even if it doesn't cycle infinitely,
						//   it will likely cause unnecessary recomputation of derived values.  Warn the user.
						if(canObservationRecorder_1_3_1_canObservationRecorder.isRecording() && canQueues_1_3_2_canQueues.stack().length && !this[inSetupSymbol$6]) {
							lastItem = canQueues_1_3_2_canQueues.stack()[canQueues_1_3_2_canQueues.stack().length - 1];
							lastFn = lastItem.context instanceof canObservation_4_2_0_canObservation ? lastItem.context.func : lastItem.fn;
							var mutationWarning = "can-define: The " + prop + " property on " +
								canReflect_1_19_2_canReflect.getName(this) +
								" is being set in " +
								(canReflect_1_19_2_canReflect.getName(lastFn) || canReflect_1_19_2_canReflect.getName(lastItem.fn)) +
								". This can cause infinite loops and performance issues. " +
								"Use the value() behavior for " +
								prop +
								" instead, and listen to other properties and observables with listenTo(). https://canjs.com/doc/can-define.types.value.html";
							dev.warn(mutationWarning);
							canQueues_1_3_2_canQueues.logStack();
						}
					}
					//!steal-remove-end

					this.dispatch(dispatched, [newVal, current]);
				}
			};
		},
		setter: function(prop, setter, getCurrent, setEvents, hasGetter) {
			return function(value) {
				//!steal-remove-start
				var asyncTimer;
				//!steal-remove-end

				var self = this;

				// call the setter, if returned value is undefined,
				// this means the setter is async so we
				// do not call update property and return right away

				canQueues_1_3_2_canQueues.batch.start();
				var setterCalled = false,
					current = getCurrent.call(this),
					setValue = setter.call(this, value, function(value) {
						setEvents.call(self, value);

						setterCalled = true;
						//!steal-remove-start
						if(process.env.NODE_ENV !== 'production') {
							clearTimeout(asyncTimer);
						}
						//!steal-remove-end
					}, current);

				if (setterCalled) {
					canQueues_1_3_2_canQueues.batch.stop();
				} else {
					if (hasGetter) {
						// we got a return value
						if (setValue !== undefined) {
							// if the current `set` value is returned, don't set
							// because current might be the `lastSetVal` of the internal compute.
							if (current !== setValue) {
								setEvents.call(this, setValue);
							}
							canQueues_1_3_2_canQueues.batch.stop();
						}
						// this is a side effect, it didn't take a value
						// so use the original set value
						else if (setter.length === 0) {
							setEvents.call(this, value);
							canQueues_1_3_2_canQueues.batch.stop();
							return;
						}
						// it took a value
						else if (setter.length === 1) {
							// if we have a getter, and undefined was returned,
							// we should assume this is setting the getters properties
							// and we shouldn't do anything.
							canQueues_1_3_2_canQueues.batch.stop();
						}
						// we are expecting something
						else {
							//!steal-remove-start
							if(process.env.NODE_ENV !== 'production') {
								asyncTimer = setTimeout(function() {
									dev.warn('can-define: Setter "' + canReflect_1_19_2_canReflect.getName(self)+"."+prop + '" did not return a value or call the setter callback.');
								}, dev.warnTimeout);
							}
							//!steal-remove-end
							canQueues_1_3_2_canQueues.batch.stop();
							return;
						}
					} else {
						// we got a return value
						if (setValue !== undefined) {
							// if the current `set` value is returned, don't set
							// because current might be the `lastSetVal` of the internal compute.
							setEvents.call(this, setValue);
							canQueues_1_3_2_canQueues.batch.stop();
						}
						// this is a side effect, it didn't take a value
						// so use the original set value
						else if (setter.length === 0) {
							setEvents.call(this, value);
							canQueues_1_3_2_canQueues.batch.stop();
							return;
						}
						// it took a value
						else if (setter.length === 1) {
							// if we don't have a getter, we should probably be setting the
							// value to undefined
							setEvents.call(this, undefined);
							canQueues_1_3_2_canQueues.batch.stop();
						}
						// we are expecting something
						else {
							//!steal-remove-start
							if(process.env.NODE_ENV !== 'production') {
								asyncTimer = setTimeout(function() {
									dev.warn('can/map/setter.js: Setter "' + canReflect_1_19_2_canReflect.getName(self)+"."+prop + '" did not return a value or call the setter callback.');
								}, dev.warnTimeout);
							}
							//!steal-remove-end
							canQueues_1_3_2_canQueues.batch.stop();
							return;
						}
					}


				}
			};
		},
		type: function(prop, type, set) {
			function setter(newValue) {
				return set.call(this, type.call(this, newValue, prop));
			}
			if(isDefineType$1(type)) {
				// TODO: remove this `canDefineType` check in a future release.
				if(type.canDefineType) {
					return setter;
				} else {
					return function setter(newValue){
						return set.call(this, canReflect_1_19_2_canReflect.convert(newValue, type));
					};
				}
			}
			// If type is a nested object: `type: {foo: "string", bar: "number"}`
			if (typeof type === "object") {
				return make$1.set.Type(prop, type, set);
			} else {
				return setter;
			}
		},
		Type: function(prop, Type, set) {
			// `type`: {foo: "string"}
			if(Array.isArray(Type) && define$1.DefineList) {
				Type = define$1.DefineList.extend({
					"#": Type[0]
				});
			} else if (typeof Type === "object") {
				if(define$1.DefineMap) {
					Type = define$1.DefineMap.extend(Type);
				} else {
					Type = define$1.Constructor(Type);
				}
			}
			return function(newValue) {
				if (newValue instanceof Type || newValue == null) {
					return set.call(this, newValue);
				} else {
					return set.call(this, new Type(newValue));
				}
			};
		}
	},
	// Helpes that indicate what the event type should be.  These probably aren't needed.
	eventType: {
		data: function(prop) {
			return function(newVal, oldVal) {
				return oldVal !== undefined || this._data.hasOwnProperty(prop) ? "set" : "add";
			};
		},
		computed: function() {
			return function() {
				return "set";
			};
		}
	},
	// Helpers that read the data in a non-observable way.
	read: {
		data: function(prop) {
			return function() {
				return this._data[prop];
			};
		},
		computed: function(prop) {
			// might want to protect this
			return function() {
				return canReflect_1_19_2_canReflect.getValue( this._computed[prop].compute );
			};
		},
		lastSet: function(prop) {
			return function() {
				var observable = this._computed[prop].compute;
				if(observable.lastSetValue) {
					return canReflect_1_19_2_canReflect.getValue(observable.lastSetValue);
				}
			};
		}
	},
	// Helpers that read the data in an observable way.
	get: {
		// uses the default value
		defaultValue: function(prop, definition, typeConvert, callSetter) {
			return function() {
				var value = definition.default;
				if (value !== undefined) {
					if (typeof value === "function") {
						value = value.call(this);
					}
					value = typeConvert.call(this, value);
				}
				else {
					var Default = definition.Default;
					if (Default) {
						value = typeConvert.call(this,new Default());
					}
				}
				if(definition.set) {
					// TODO: there's almost certainly a faster way of making this happen
					// But this is maintainable.

					var VALUE;
					var sync = true;

					var setter = make$1.set.setter(prop, definition.set, function(){}, function(value){
						if(sync) {
							VALUE = value;
						} else {
							callSetter.call(this, value);
						}
					}, definition.get);

					setter.call(this,value);
					sync= false;

					// VALUE will be undefined if the callback is never called.
					return VALUE;


				}
				return value;
			};
		},
		data: function(prop) {
			return function() {
				if (!this[inSetupSymbol$6]) {
					canObservationRecorder_1_3_1_canObservationRecorder.add(this, prop);
				}

				return this._data[prop];
			};
		},
		computed: function(prop) {
			return function(val) {
				var compute = this._computed[prop].compute;
				if (canObservationRecorder_1_3_1_canObservationRecorder.isRecording()) {
					canObservationRecorder_1_3_1_canObservationRecorder.add(this, prop);
					if (!canReflect_1_19_2_canReflect.isBound(compute)) {
						canObservation_4_2_0_canObservation.temporarilyBind(compute);
					}
				}

				return peek$4(compute);
			};
		}
	}
};

define$1.behaviors = ["get", "set", "value", "Value", "type", "Type", "serialize"];

// This cleans up a particular behavior and adds it to the definition
var addBehaviorToDefinition$1 = function(definition, behavior, value) {
	if(behavior === "enumerable") {
		// treat enumerable like serialize
		definition.serialize = !!value;
	}
	else if(behavior === "type") {
		var behaviorDef = value;
		if(typeof behaviorDef === "string") {
			behaviorDef = define$1.types[behaviorDef];
			if(typeof behaviorDef === "object" && !isDefineType$1(behaviorDef)) {
				canAssign_1_3_3_canAssign(definition, behaviorDef);
				behaviorDef = behaviorDef[behavior];
			}
		}
		if (typeof behaviorDef !== 'undefined') {
			definition[behavior] = behaviorDef;
		}
	}
	else {
		definition[behavior] = value;
	}
};

// This is called by `define.property` AND `getDefinitionOrMethod` (which is called by `define`)
// Currently, this is adding default behavior
// copying `type` over, and even cleaning up the final definition object
makeDefinition$1 = function(prop, def, defaultDefinition, typePrototype) {

	var definition = {};

	canReflect_1_19_2_canReflect.eachKey(def, function(value, behavior) {
		addBehaviorToDefinition$1(definition, behavior, value);
	});
	// only add default if it doesn't exist
	canReflect_1_19_2_canReflect.eachKey(defaultDefinition, function(value, prop){
		if(definition[prop] === undefined) {
			if(prop !== "type" && prop !== "Type") {
				definition[prop] = value;
			}
		}
	});

	// normalize Type that implements can.new
	if(def.Type) {
		var value = def.Type;

		var serialize = value[serializeSymbol$1];
		if(serialize) {
			definition.serialize = function(val){
				return serialize.call(val);
			};
		}
		if(value[newSymbol$4]) {
			definition.type = value;
			delete definition.Type;
		}
	}

	// We only want to add a defaultDefinition if def.type is not a string
	// if def.type is a string it is handled in addDefinition
	if(typeof def.type !== 'string') {
		// if there's no type definition, take it from the defaultDefinition
		if(!definition.type && !definition.Type) {
            var defaultsCopy = canReflect_1_19_2_canReflect.assignMap({},defaultDefinition);
            definition = canReflect_1_19_2_canReflect.assignMap(defaultsCopy, definition);
		}

		if( canReflect_1_19_2_canReflect.size(definition) === 0 ) {
			definition.type = define$1.types["*"];
		}
	}
	cleanUpDefinition(prop, definition, true, typePrototype);
	return definition;
};

// called by `can.defineInstanceKey` and `getDefinitionsAndMethods`
// returns the value or the definition object.
// calls makeDefinition
// This is dealing with a string value
getDefinitionOrMethod$1 = function(prop, value, defaultDefinition, typePrototype){
	// Clean up the value to make it a definition-like object
	var definition;
	if(typeof value === "string") {
		definition = {type: value};
	}
    // copies a `Type`'s methods over
	else if(value && (value[serializeSymbol$1] || value[newSymbol$4]) ) {
		definition = { Type: value };
	}
	else if(typeof value === "function") {
		if(canReflect_1_19_2_canReflect.isConstructorLike(value)) {
			definition = {Type: value};
		}
		// or leaves as a function
	} else if( Array.isArray(value) ) {
		definition = {Type: value};
	} else if( canReflect_1_19_2_canReflect.isPlainObject(value) ){
		definition = value;
	}

	if(definition) {
		return makeDefinition$1(prop, definition, defaultDefinition, typePrototype);
	}
	else {
		return value;
	}
};
// called by can.define
getDefinitionsAndMethods$1 = function(defines, baseDefines, typePrototype) {
	// make it so the definitions include base definitions on the proto
	var definitions = Object.create(baseDefines ? baseDefines.definitions : null);
	var methods = {};
	// first lets get a default if it exists
	var defaults = defines["*"],
		defaultDefinition;
	if(defaults) {
		delete defines["*"];
		defaultDefinition = getDefinitionOrMethod$1("*", defaults, {});
	} else {
		defaultDefinition = Object.create(null);
	}

	eachPropertyDescriptor$1(defines, function( prop, propertyDescriptor ) {

		var value;
		if(propertyDescriptor.get || propertyDescriptor.set) {
			value = {get: propertyDescriptor.get, set: propertyDescriptor.set};
		} else {
			value = propertyDescriptor.value;
		}

		if(prop === "constructor") {
			methods[prop] = value;
			return;
		} else {
			var result = getDefinitionOrMethod$1(prop, value, defaultDefinition, typePrototype);
			if(result && typeof result === "object" && canReflect_1_19_2_canReflect.size(result) > 0) {
				definitions[prop] = result;
			}
			else {
				// Removed adding raw values that are not functions
				if (typeof result === 'function') {
					methods[prop] = result;
				}
				//!steal-remove-start
				else if (typeof result !== 'undefined') {
					if(process.env.NODE_ENV !== 'production') {
                    	// Ex: {prop: 0}
						dev.error(canReflect_1_19_2_canReflect.getName(typePrototype)+"."+prop + " does not match a supported propDefinition. See: https://canjs.com/doc/can-define.types.propDefinition.html");
					}
				}
				//!steal-remove-end
			}
		}
	});
	if(defaults) {
		// we should move this property off the prototype.
		defineConfigurableAndNotEnumerable$1(defines,"*", defaults);
	}
	return {definitions: definitions, methods: methods, defaultDefinition: defaultDefinition};
};

eventsProto$1 = map$1({});

function setupComputed$1(instance, eventName) {
	var computedBinding = instance._computed && instance._computed[eventName];
	if (computedBinding && computedBinding.compute) {
		if (!computedBinding.count) {
			computedBinding.count = 1;
			canReflect_1_19_2_canReflect.onValue(computedBinding.compute, computedBinding.handler, "notify");
			computedBinding.oldValue = peek$4(computedBinding.compute);
		} else {
			computedBinding.count++;
		}

	}
}
function teardownComputed$1(instance, eventName){
	var computedBinding = instance._computed && instance._computed[eventName];
	if (computedBinding) {
		if (computedBinding.count === 1) {
			computedBinding.count = 0;
			canReflect_1_19_2_canReflect.offValue(computedBinding.compute, computedBinding.handler,"notify");
		} else {
			computedBinding.count--;
		}
	}
}

var canMetaSymbol$1 = canSymbol_1_7_0_canSymbol.for("can.meta");
canAssign_1_3_3_canAssign(eventsProto$1, {
	_eventSetup: function() {},
	_eventTeardown: function() {},
	addEventListener: function(eventName, handler, queue) {
		setupComputed$1(this, eventName);
		return map$1.addEventListener.apply(this, arguments);
	},

	// ### unbind
	// Stops listening to an event.
	// If this is the last listener of a computed property,
	// stop forwarding events of the computed property to this map.
	removeEventListener: function(eventName, handler) {
		teardownComputed$1(this, eventName);
		return map$1.removeEventListener.apply(this, arguments);

	}
});
eventsProto$1.on = eventsProto$1.bind = eventsProto$1.addEventListener;
eventsProto$1.off = eventsProto$1.unbind = eventsProto$1.removeEventListener;


var onKeyValueSymbol$6 = canSymbol_1_7_0_canSymbol.for("can.onKeyValue");
var offKeyValueSymbol$4 = canSymbol_1_7_0_canSymbol.for("can.offKeyValue");

canReflect_1_19_2_canReflect.assignSymbols(eventsProto$1,{
	"can.onKeyValue": function(key){
		setupComputed$1(this, key);
		return map$1[onKeyValueSymbol$6].apply(this, arguments);
	},
	"can.offKeyValue": function(key){
		teardownComputed$1(this, key);
		return map$1[offKeyValueSymbol$4].apply(this, arguments);
	}
});

delete eventsProto$1.one;

define$1.setup = function(props, sealed) {
	Object.defineProperty(this,"constructor", {value: this.constructor, enumerable: false, writable: false});
	Object.defineProperty(this,canMetaSymbol$1, {value: Object.create(null), enumerable: false, writable: false});

	/* jshint -W030 */

	var definitions = this._define.definitions;
	var instanceDefinitions = Object.create(null);
	var map = this;
	canReflect_1_19_2_canReflect.eachKey(props, function(value, prop){
		if(definitions[prop] !== undefined) {
			map[prop] = value;
		} else {
			define$1.expando(map, prop, value);
		}
	});
	if(canReflect_1_19_2_canReflect.size(instanceDefinitions) > 0) {
		defineConfigurableAndNotEnumerable$1(this, "_instanceDefinitions", instanceDefinitions);
	}
	// only seal in dev mode for performance reasons.
	//!steal-remove-start
	if(process.env.NODE_ENV !== 'production') {
		this._data;
		this._computed;
		if(sealed !== false) {
			Object.seal(this);
		}
	}
	//!steal-remove-end
};


var returnFirstArg$1 = function(arg){
	return arg;
};

define$1.expando = function(map, prop, value) {
	if(define$1._specialKeys[prop]) {
		// ignores _data and _computed
		return true;
	}
	// first check if it's already a constructor define
	var constructorDefines = map._define.definitions;
	if(constructorDefines && constructorDefines[prop]) {
		return;
	}
	// next if it's already on this instances
	var instanceDefines = map._instanceDefinitions;
	if(!instanceDefines) {
		if(Object.isSealed(map)) {
			return;
		}
		Object.defineProperty(map, "_instanceDefinitions", {
			configurable: true,
			enumerable: false,
			writable: true,
			value: {}
		});
		instanceDefines = map._instanceDefinitions;
	}
	if(!instanceDefines[prop]) {
		var defaultDefinition = map._define.defaultDefinition || {type: define$1.types.observable};
		define$1.property(map, prop, defaultDefinition, {},{});
		// possibly convert value to List or DefineMap
		if(defaultDefinition.type) {
			map._data[prop] = define$1.make.set.type(prop, defaultDefinition.type, returnFirstArg$1).call(map, value);
		} else if (defaultDefinition.Type && canReflect_1_19_2_canReflect.isConstructorLike(defaultDefinition.Type)) {
			map._data[prop] = define$1.make.set.Type(prop, defaultDefinition.Type, returnFirstArg$1).call(map, value);
		} else {
			map._data[prop] = define$1.types.observable(value);
		}

		instanceDefines[prop] = defaultDefinition;
		if(!map[inSetupSymbol$6]) {
			canQueues_1_3_2_canQueues.batch.start();
			map.dispatch({
				action: "can.keys",
				target: map,
				type: "can.keys" // TODO: Remove in 6.0
			});
			if(Object.prototype.hasOwnProperty.call(map._data, prop)) {
				map.dispatch({
					action: "add",
					target: map,
					value:  map._data[prop],
					oldValue: undefined,
					key: prop,
					type: prop, // TODO: Remove in 6.0
					patches: [{type: "add", key: prop, value: map._data[prop]}],
				},[map._data[prop], undefined]);
			} else {
				map.dispatch({
					type: "set",
					target: map,
					patches: [{type: "add", key: prop, value: map._data[prop]}],
				},[map._data[prop], undefined]);
			}
			canQueues_1_3_2_canQueues.batch.stop();
		}
		return true;
	}
};
define$1.replaceWith = canDefineLazyValue_1_1_1_defineLazyValue;
define$1.eventsProto = eventsProto$1;
define$1.defineConfigurableAndNotEnumerable = defineConfigurableAndNotEnumerable$1;
define$1.make = make$1;
define$1.getDefinitionOrMethod = getDefinitionOrMethod$1;
define$1._specialKeys = {_data: true, _computed: true};
var simpleGetterSetters$1 = {};
define$1.makeSimpleGetterSetter = function(prop){
	if(simpleGetterSetters$1[prop] === undefined) {

		var setter = make$1.set.events(prop, make$1.get.data(prop), make$1.set.data(prop), make$1.eventType.data(prop) );

		simpleGetterSetters$1[prop] = {
			get: make$1.get.data(prop),
			set: function(newVal){
				return setter.call(this, define$1.types.observable(newVal));
			},
			enumerable: true,
            configurable: true
		};
	}
	return simpleGetterSetters$1[prop];
};

define$1.Iterator = function(obj){
	this.obj = obj;
	this.definitions = Object.keys(obj._define.definitions);
	this.instanceDefinitions = obj._instanceDefinitions ?
		Object.keys(obj._instanceDefinitions) :
		Object.keys(obj);
	this.hasGet = typeof obj.get === "function";
};

define$1.Iterator.prototype.next = function(){
	var key;
	if(this.definitions.length) {
		key = this.definitions.shift();

		// Getters should not be enumerable
		var def = this.obj._define.definitions[key];
		if(def.get) {
			return this.next();
		}
	} else if(this.instanceDefinitions.length) {
		key = this.instanceDefinitions.shift();
	} else {
		return {
			value: undefined,
			done: true
		};
	}

	return {
		value: [
			key,
			this.hasGet ? this.obj.get(key) : this.obj[key]
		],
		done: false
	};
};



function isObservableValue(obj){
	return canReflect_1_19_2_canReflect.isValueLike(obj) && canReflect_1_19_2_canReflect.isObservableLike(obj);
}

define$1.types = {
	// To be made into a type ... this is both lazy {time: '123-456'}
	'date': maybeDate,
	'number': maybeNumber,
	'boolean': maybeBoolean,
	'observable': function(newVal) {
			if(Array.isArray(newVal) && define$1.DefineList) {
					newVal = new define$1.DefineList(newVal);
			}
			else if(canReflect_1_19_2_canReflect.isPlainObject(newVal) &&  define$1.DefineMap) {
					newVal = new define$1.DefineMap(newVal);
			}
			return newVal;
	},
	'stringOrObservable': function(newVal) {
		if(Array.isArray(newVal)) {
			return new define$1.DefaultList(newVal);
		}
		else if(canReflect_1_19_2_canReflect.isPlainObject(newVal)) {
			return new define$1.DefaultMap(newVal);
		}
		else {
			return canReflect_1_19_2_canReflect.convert( newVal, define$1.types.string);
		}
	},
	/**
	 * Implements HTML-style boolean logic for attribute strings, where
	 * any string, including "", is truthy.
	 */
	'htmlbool': function(val) {
		if (val === '') {
			return true;
		}
		return !!canStringToAny_1_2_1_canStringToAny(val);
	},
	'*': function(val) {
		return val;
	},
	'any': function(val) {
		return val;
	},
	'string': maybeString,

	'compute': {
		set: function(newValue, setVal, setErr, oldValue) {
			if (isObservableValue(newValue) ) {
				return newValue;
			}
			if (isObservableValue(oldValue)) {
				canReflect_1_19_2_canReflect.setValue(oldValue,newValue);
				return oldValue;
			}
			return newValue;
		},
		get: function(value) {
			return isObservableValue(value) ? canReflect_1_19_2_canReflect.getValue(value) : value;
		}
	}
};

define$1.updateSchemaKeys = function(schema, definitions) {
	for(var prop in definitions) {
		var definition = definitions[prop];
		if(definition.serialize !== false ) {
			if(definition.Type) {
				schema.keys[prop] = definition.Type;
			} else if(definition.type) {
				schema.keys[prop] = definition.type;
			} else {
				schema.keys[prop] = function(val){ return val; };
			}
			 // some unknown type
			if(definitions[prop].identity === true) {
				schema.identity.push(prop);
			}
		}
	}
	return schema;
};

/**
 * @module {connect.Behavior} can-connect/can/ref/ref can/ref
 * @parent can-connect.behaviors
 * @group can-connect/can/ref/ref.hydrators hydrators
 * @group can-connect/can/ref/ref.methods methods
 *
 * @description Handle references to instances in the data returned by the server. Allows several means of
 * loading referenced instances, determined on-the-fly.
 *
 * @signature `canRef( baseConnection )`
 *
 * Adds a reference type to [can-connect/can/map/map._Map `connection.Map`] that loads the related type or holds onto
 * an existing one. This handles circular references and loads relevant data as needed. The reference type can be loaded
 * by:
 * - it's data being included in the response for the referencing instance
 * - having an existing instance available in the [can-connect/constructor/store/store.instanceStore]
 * - lazy loading via the connection for the reference type
 *
 * @param {{}} baseConnection `can-connect` connection object that is having the `can/ref` behavior added on to it.
 * Expects the [can-connect/can/map/map] behavior to already be added to this base connection. If the `connect` helper
 * is used to build the connection, the behaviors will automatically be ordered as required.
 *
 * @return {{}} a connection with the [can-connect/can/map/map._Map `Map`] having the reference type property
 * (`Map.Ref.type`) created by `can/ref`.
 *
 * @body
 *
 * ## Use
 *
 * `can/ref` is useful when the server might return either a reference to
 * a value or the value itself.  For example, in a MongoDB setup,
 * a request like `GET /game/5` might return:
 *
 * ```
 * {
 *   id: 5,
 *   teamRef: 7,
 *   score: 21
 * }
 * ```
 *
 * But a request like `GET /game/5?$populate=teamRef` might return:
 *
 * ```
 * {
 *   id: 5,
 *   teamRef: {id: 7, name: "Cubs"},
 *   score: 21
 * }
 * ```
 *
 * `can/ref` can handle this ambiguity and even make lazy loading possible.
 *
 * To use `can/ref`, first create a Map and a connection for the referenced type:
 *
 * ```
 * var Team = DefineMap.extend({
 *   id: 'string'
 * });
 *
 * connect([
 *   require("can-connect/constructor/constructor"),
 *   require("can-connect/constructor/store/store"),
 *   require("can-connect/can/map/map"),
 *   require("can-connect/can/ref/ref")
 * ],{
 *     Map: Team,
 *     List: Team.List,
 *     ...
 * })
 * ```
 *
 * The connection is necessary because it creates an instance store which will
 * hold instances of `Team` that the `Team.Ref` type will be able to access.
 *
 * Now we can create a reference to the Team within a Game map and the Game's connection:
 *
 * ```
 * var Game = DefineMap.extend({
 *   id: 'string',
 *   teamRef: {type: Team.Ref.type},
 *   score: "number"
 * });
 *
 * superMap({
 *   Map: Game,
 *   List: Game.List
 * })
 * ```
 *
 * Now, `teamRef` is a [can-connect/can/ref/ref.Map.Ref] type, which will
 * house the id of the reference no matter how the server returns data, e.g.
 * `game.teamRef.id`.
 *
 * For example, without populating the team data:
 *
 * ```
 * Game.get({id: 5}).then(function(game){
 *   game.teamRef.id //-> 7
 * });
 * ```
 *
 * With populating the team data:
 *
 * ```
 * Game.get({id: 5, $populate: "teamRef"}).then(function(game){
 *   game.teamRef.id //-> 7
 * });
 * ```
 *
 * The values of other properties and methods on the [can-connect/can/ref/ref.Map.Ref] type
 * are determined by if the reference was populated or the referenced item already exists
 * in the [can-connect/constructor/store/store.instanceStore].
 *
 * For example, `value`, which points to the referenced instance, will be populated if the reference was populated:
 *
 * ```
 * Game.get({id: 5, $populate: "teamRef"}).then(function(game){
 *   game.teamRef.value.name //-> 5
 * });
 * ```
 *
 * Or, it will be populated if that instance had been loaded through another means and
 * it’s in the instance store:
 *
 * ```
 * Team.get({id: 7}).then(function(team){
 *   // binding adds things to the store
 *   team.on("name", function(){})
 * }).then(function(){
 *   Game.get({id: 5}).then(function(game){
 *     game.teamRef.value.name //-> 5
 *   });
 * })
 * ```
 *
 * `value` is an [can-define.types.get asynchronous getter], which means that even if
 * the referenced value isn't populated or loaded through the store, it can be lazy loaded. This
 * is generally most useful in a template.
 *
 * The following will make an initial request for game `5`, but when the template
 * tried to read and listen to `game.teamRef.value.name`, a request for team `7`
 * will be made.
 *
 * ```
 * var template = stache("{{game.teamRef.value.name}} scored {{game.score}} points");
 * Game.get({id: 5}).then(function(game){
 *   template({game: game});
 * });
 * ```
 *
 *
 */







var makeRef = function(connection) {
	var idProp = canReflect_1_19_2_canReflect.getSchema(connection.queryLogic).identity[0];
	/**
	 * @property {constructor} can-connect/can/ref/ref.Map.Ref Map.Ref
	 * @parent can-connect/can/ref/ref.hydrators
	 * @group can-connect/can/ref/ref.Map.Ref.static static
	 * @group can-connect/can/ref/ref.Map.Ref.prototype prototype
	 *
	 * A reference type with `instanceRef.value` primed to return an existing instance of the
	 * [can-connect/can/map/map._Map] type, if available, or lazy load an instance upon accessing `instanceRef.value`.
	 *
	 * @signature `new Map.Ref(id, value)`
	 * @param  {string} id    string representing the record id
	 * @param  {Object} value properties to be loaded / hydrated
	 * @return {Map.Ref}       instance reference object for the id
	 */
	var Ref = (function(){
		return function(id, value) {
			if (typeof id === "object") {
				value = id;
				id = value[idProp];
			}
			// check if this is in the store
			var storeRef = Ref.store.get(id);
			if (storeRef) {
				if (value && !storeRef._value) {
					if (value instanceof connection.Map) {
						storeRef._value = value;
					} else {
						storeRef._value = connection.hydrateInstance(value);
					}
				}
				return storeRef;
			}
			// if not, create it
			this[idProp] = id;
			if (value) {
				// if the value is already an instance, use it.

				if (value instanceof connection.Map) {
					this._value = value;
				} else {
					this._value = connection.hydrateInstance(value);
				}
			}


			// check if this is being made during a request
			// if it is, save it
			if (store.requests.count() > 0) {
				if (!Ref._requestInstances[id]) {
					Ref.store.addReference(id, this);
					Ref._requestInstances[id] = this;
				}
			}
		};
	})();
	/**
	 * @property {can-connect/helpers/weak-reference-map} can-connect/can/ref/ref.Map.Ref.store store
	 * @parent can-connect/can/ref/ref.Map.Ref.static
	 * @hide // not something that needs to be documented for the average user
	 * A WeakReferenceMap that contains instances being created by their `._cid` property.
	 */
	Ref.store = new weakReferenceMap();
	Ref._requestInstances = {};
	/**
	 * @function can-connect/can/ref/ref.Map.Ref.type type
	 * @parent can-connect/can/ref/ref.Map.Ref.static
	 *
	 * Returns a new instance of `Map.Ref`.
	 *
	 * @signature `Map.Ref.type(reference)`
	 *
	 *   @param {Object|String|Number} reference either data or an id for an instance of [can-connect/can/map/map._Map].
	 *   @return {can-connect/can/ref/ref.Map.Ref} reference instance for the passed data or identifier.
	 */
	Ref.type = function(ref) {
		if (ref && typeof ref !== "object") {
			// get or make the existing reference from the store
			return new Ref(ref);
		} else {
			// get or make the reference in the store, update the instance too
			return new Ref(ref[idProp], ref);
		}
	};
	var defs = {
		/**
		 * @property {Promise} can-connect/can/ref/ref.Map.Ref.prototype.promise promise
		 * @parent can-connect/can/ref/ref.Map.Ref.prototype
		 * @hide // don't know if this is part of the public API
		 *
		 * Returns a resolved promise if the referenced instance is already available, if not, returns a new promise
		 * to retrieve the instance by the id.
		 *
		 * @signature `ref.promise`
		 * @return {Promise} Promise resolving the instance referenced
		 */
		promise: {
			get: function() {
				if (this._value) {
					return Promise.resolve(this._value);
				} else {
					var props = {};
					props[idProp] = this[idProp];
					return connection.Map.get(props);
				}
			}
		},

		_state: {
			get: function(lastSet, resolve) {
				if (resolve) {
					this.promise.then(function() {
						resolve("resolved");
					}, function() {
						resolve("rejected");
					});
				}

				return "pending";
			}
		},

		/**
		 * @property {*} can-connect/can/ref/ref.Map.Ref.prototype.value value
		 * @parent can-connect/can/ref/ref.Map.Ref.prototype
		 *
		 * Returns the actual instance the reference points to. Returns `undefined` if the instance is still being loaded.
		 * Accessing this property will start lazy loading if the instance isn't already available.
		 *
		 * @signature `ref.value`
		 * @return {object} actual instance referenced or `undefined` if lazy loading ongoing
		 */
		value: {
			get: function(lastSet, resolve) {
				if (this._value) {
					return this._value;
				} else if (resolve) {
					this.promise.then(function(value) {
						resolve(value);
					});
				}
			}
		},

		/**
		 * @property {*} can-connect/can/ref/ref.Map.Ref.prototype.reason reason
		 * @parent can-connect/can/ref/ref.Map.Ref.prototype
		 *
		 * Returns the failure message from the lazy loading promise. Returns `undefined` if the referenced instance is
		 * available or loading is ongoing.
		 *
		 * @signature `ref.reason`
		 * @return {Object} error message if the promise is rejected
		 */
		reason: {
			get: function(lastSet, resolve) {
				if (this._value) {
					return undefined;
				} else {
					this.promise.catch(function(value) {
						resolve(value);
					});
				}
			}
		}
	};
	defs[idProp] = {
		type: "*",
		set: function() {
			this._value = undefined;
		}
	};

	canDefine_2_8_1_canDefine(Ref.prototype, defs);

	Ref.prototype.unobservedId = canObservationRecorder_1_3_1_canObservationRecorder.ignore(function() {
		return this[idProp];
	});
	/**
	 * @function can-connect/can/ref/ref.Map.Ref.prototype.isResolved isResolved
	 * @parent can-connect/can/ref/ref.Map.Ref.prototype
	 *
	 * Observable property typically for use in templates to indicate to the user if lazy loading has succeeded.
	 *
	 * @signature `ref.isResolved`
	 * @return {boolean} `true` if the lazy loading promise was resolved.
	 */
	Ref.prototype.isResolved = function() {
		return !!this._value || this._state === "resolved";
	};
	/**
	 * @function can-connect/can/ref/ref.Map.Ref.prototype.isRejected isRejected
	 * @parent can-connect/can/ref/ref.Map.Ref.prototype
	 *
	 * Observable property typically for use in templates to indicate to the user if lazy loading has failed.
	 *
	 * @signature `ref.isRejected`
	 * @return {boolean} `true` if the lazy loading promise was rejected.
	 */
	Ref.prototype.isRejected = function() {
		return this._state === "rejected";
	};

	/**
	 * @function can-connect/can/ref/ref.Map.Ref.prototype.isPending isPending
	 * @parent can-connect/can/ref/ref.Map.Ref.prototype
	 *
	 * Observable property typically for use in templates to indicate to the user if lazy loading is ongoing.
	 *
	 * @signature `ref.isPending`
	 * @return {boolean} `true` if the lazy loading promise state is not resolved or rejected.
	 */
	Ref.prototype.isPending = function() {
		return !this._value && (this._state !== "resolved" || this._state !== "rejected");
	};

	/**
	 * @function can-connect/can/ref/ref.Map.Ref.prototype.serialize serialize
	 * @parent can-connect/can/ref/ref.Map.Ref.prototype
	 *
	 * Return the id of the referenced instance when serializing. Prevents the referenced instance from
	 * being entirely serialized when serializing the referencing instance.
	 *
	 * @signature `ref.serialize`
	 * @return {string} id the id of the referenced instance
	 */
	Ref.prototype.serialize = function() {
		return this[idProp];
	};
	canReflect_1_19_2_canReflect.assignSymbols(Ref.prototype, {
		"can.serialize": Ref.prototype.serialize,
		"can.getName": function(){
			return canReflect_1_19_2_canReflect.getName(this.constructor)+"{"+this[idProp]+"}";
		}
	});

	var baseEventSetup = Ref.prototype._eventSetup;
	Ref.prototype._eventSetup = function() {
		Ref.store.addReference(this.unobservedId(), this);
		return baseEventSetup.apply(this, arguments);
	};
	var baseTeardown = Ref.prototype._eventTeardown;
	Ref.prototype._eventTeardown = function() {
		Ref.store.deleteReference(this.unobservedId(), this);
		return baseTeardown.apply(this, arguments);
	};


	store.requests.on("end", function() {
		for (var id in Ref._requestInstances) {
			Ref.store.deleteReference(id);
		}
		Ref._requestInstances = {};
	});

	//!steal-remove-start
	Object.defineProperty(Ref, "name", {
		value: canReflect_1_19_2_canReflect.getName(connection.Map) + "Ref",
		configurable: true
	});
	//!steal-remove-end

	return Ref;
};


var ref = canConnect_4_0_6_canConnect.behavior("can/ref", function(baseConnection) {
	return {
		/**
		 * @can-connect/can/ref/ref.init init
		 * @parent can-connect/can/ref/ref.methods
		 *
		 * @signature `connection.init()`
		 *
		 * Initializes the base connection and then creates and sets [can-connect/can/ref/ref.Map.Ref].
		 * Typically called by the `connect` helper after the connection behaviors have been assembled.
		 *
		 * @return {undefined} no return value
		 **/
		init: function() {
			baseConnection.init.apply(this, arguments);
			this.Map.Ref = makeRef(this);
		}
	};
});

var $$1 = global_1().$;

canConnect_4_0_6_canConnect.superMap = function(options){

	var behaviors = [
		constructor_1,
		map$3,
		ref,
		store,
		callbacks,
		combineRequests$1,
		parse$1,
		url,
		realTime,
		callbacksOnce];

	if(typeof localStorage !== "undefined") {
		if(!options.cacheConnection) {
			options.cacheConnection = canConnect_4_0_6_canConnect([localstorageCache],{
				name: options.name+"Cache",
				idProp: options.idProp,
				queryLogic: options.queryLogic
			});
		}
		behaviors.push(callbacksCache,fallThroughCache_1);
	}
	// Handles if jQuery isn't provided.
	if($$1 && $$1.ajax) {
		options.ajax = $$1.ajax;
	}
	return canConnect_4_0_6_canConnect(behaviors,options);
};

var superMap = canConnect_4_0_6_canConnect.superMap;

var $$2 = global_1().$;

canConnect_4_0_6_canConnect.baseMap = function(options){

	var behaviors = [
		constructor_1,
		map$3,
		ref,
		store,
		callbacks,
		parse$1,
		url,
		realTime,
		callbacksOnce
	];

	// Handles if jQuery isn't provided.
	if($$2 && $$2.ajax) {
		options.ajax = $$2.ajax;
	}

	return canConnect_4_0_6_canConnect(behaviors,options);
};

var baseMap = canConnect_4_0_6_canConnect.baseMap;

canConnect_4_0_6_canConnect.cacheRequests = cacheRequests;

canConnect_4_0_6_canConnect.constructor = constructor_1;
canConnect_4_0_6_canConnect.constructorCallbacksOnce = callbacksOnce;
canConnect_4_0_6_canConnect.constructorStore = store;
canConnect_4_0_6_canConnect.dataCallbacks = callbacks;
canConnect_4_0_6_canConnect.dataCallbacksCache = callbacksCache;
canConnect_4_0_6_canConnect.dataCombineRequests = combineRequests$1;
canConnect_4_0_6_canConnect.dataLocalStorageCache = localstorageCache;
canConnect_4_0_6_canConnect.dataMemoryCache = memoryCache;
canConnect_4_0_6_canConnect.dataParse = parse$1;
canConnect_4_0_6_canConnect.dataUrl = url;
canConnect_4_0_6_canConnect.fallThroughCache = fallThroughCache_1;
canConnect_4_0_6_canConnect.realTime = realTime;

canConnect_4_0_6_canConnect.canMap = map$3;

canConnect_4_0_6_canConnect.superMap = superMap;
canConnect_4_0_6_canConnect.baseMap = baseMap;

var canConnect_4_0_6_all = canConnect_4_0_6_canConnect;

// ## methodsToOverwrite
// Method names on `history` that will be overwritten
// during teardown these are reset to their original functions.
var methodsToOverwrite = ["pushState", "replaceState"],
	// This symbol is used in dispatchHandlers.
	dispatchSymbol$3 = canSymbol_1_7_0_canSymbol.for("can.dispatch");

// ## Helpers
// The following are helper functions useful to `can-route-pushstate`'s main methods.

// ### cleanRoot
// Start of `location.pathname` is the root. 
// Returns the root minus the domain.
function cleanRoot() {
	var location = location_1(),
		domain = location.protocol + "//" + location.host,
		// pulls root from route.urlData
		root = bindingProxy_1.call("root"),
		index = root.indexOf(domain);

	if (index === 0) {
		return root.substr(domain.length);
	}
	return root;
}

// ### getCurrentUrl
// Gets the current url after the root.
// `root` is defined in the PushstateObservable constructor.
function getCurrentUrl() {
	var root = cleanRoot(),
		location = location_1(),
		loc = (location.pathname + location.search),
		index = loc.indexOf(root);

	return loc.substr(index + root.length);
}

// ## PushstateObservable
function PushstateObservable() {
	// Keys passed into `replaceStateOnce` will be stored in `replaceStateOnceKeys`.
	this.replaceStateOnceKeys = [];
	// Keys passed into `replaceStateOn` will be stored in `replaceStateKeys`.
	this.replaceStateKeys = [];
	this.dispatchHandlers = this.dispatchHandlers.bind(this);
	this.anchorClickHandler = function(event) {
		var shouldCallPushState = PushstateObservable.prototype.shouldCallPushState.call(this, this, event);
		if (shouldCallPushState) {
			PushstateObservable.prototype.anchorClickHandler.call(this, this, event);
		}
	};

	// ### `keepHash`
	// Currently is neither a feature that's documented,
	// nor is it toggled. [Issue #133](https://github.com/canjs/can-route-pushstate/issues/133)
	// is the discourse on it's removal.
	this.keepHash = true;
}

PushstateObservable.prototype = Object.create(canSimpleObservable_2_5_0_canSimpleObservable.prototype);
PushstateObservable.constructor = PushstateObservable;
canReflect_1_19_2_canReflect.assign(PushstateObservable.prototype, {

	// ### root
	// Start of `location.pathname` is the root.
	// (Can be configured via `route.urlData.root`)
	// The default is `"#!"` set in can-route-hash.
	root: "/",

	// ### matchSlashes
	// The default is `false` set in can-route-hash.
	// Don't greedily match slashes in routing rules.
	matchSlashes: false,

	// ### paramsMatcher
	// Matches things like:
	//  - ?foo=bar
	//  - ?foo=bar&framework=canjs
	//  - ?foo=&bar=
	paramsMatcher: /^\?(?:[^=]+=[^&]*&)*[^=]+=[^&]*/,

	// ### querySeparator
	// Used in `can-route` for building regular expressions to match routes, or
	// return url substrings of routes.
	querySeparator: "?",

	// ### dispatchHandlers
	// Updates `this._value` to the current url and 
	// dispatches event handlers that are on the object.
	// `dispatchHandlers` is called if `pushState` or `replaceState`
	// are called, it is also an event handler on `'popstate'`.
	dispatchHandlers: function() {
		var old = this._value;
		this._value = getCurrentUrl();

		if (old !== this._value) {
			// PushstateObservable inherits from `SimpleObservable` which
			// is using the `can-event-queue/value/value` mixin, and is called
			// using the `can.dispatch` symbol.
			this[dispatchSymbol$3](this._value, old);
		}
	},

	// ### shouldCallPushState
	// Checks if a route is matched, if one is, returns true
	shouldCallPushState: function(node, event) {
		if (!(event.isDefaultPrevented ? event.isDefaultPrevented() : event.defaultPrevented === true)) {
			// If href has some JavaScript in it, let it run.
			if (node.href === "javascript://") {
				return;
			}

			// Do not pushstate if target is for blank window.
			if (node.target === "_blank") {
				return;
			}

			// Do not pushstate if meta key was pressed, mimicking standard browser behavior.
			if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
				return;
			}

			// linksHost is a Fix for IE showing blank host, but blank host means current host.
			var linksHost = node.host || window.location.host;

			// If link is within the same domain and descendant of `root`.
			if (window.location.host === linksHost) {
				var root = cleanRoot(),
					pathname,
					href,
					nodePathWithSearch;

				if (node instanceof HTMLAnchorElement) {
					pathname = node.pathname;
					href = node.href;
					nodePathWithSearch = pathname + node.search;
				} else if (node.namespaceURI === "http://www.w3.org/1999/xlink") {
					pathname = href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href");
					nodePathWithSearch = href;
				}

				// If the link is within the `root`.
				if (pathname !== undefined && pathname.indexOf(root) === 0) {
					var url = nodePathWithSearch.substr(root.length);

					// If a matching route exists.
					if (canRoute_5_0_2_canRoute.rule(url) !== undefined) {
						// Makes it possible to have a link with a hash.
						// Calling .pushState will dispatch events, causing
						// `can-route` to update its data, and then try to set back
						// the url without the hash.  We need to retain that.
						if (href.indexOf("#") >= 0) {
							this.keepHash = true;
						}

						// We do not want to call preventDefault() if the link is to the
						// same page and just a different hash; see can-route-pushstate#75.
						var windowPathWithSearch = window.location.pathname + window.location.search;
						var shouldCallPreventDefault = nodePathWithSearch !== windowPathWithSearch || node.hash === window.location.hash;

						// Test if you can preventDefault.
						if (shouldCallPreventDefault && event.preventDefault) {
							event.preventDefault();
						}
						return true;
					}
					return false;
				}
			}
		}
	},

	// ### anchorClickHandler
	// Handler function for `click` events.
	anchorClickHandler: function(node, event) {
		var href = node.href ? node.href : node.getAttributeNS("http://www.w3.org/1999/xlink", "href");
		// Update `window.location`.
		window.history.pushState(null, null, href);
	},

	// ### onBound
	// Initalizes this._value.
	// Sets up event listeners to capture `click` events on `<a>` elements.
	// Overwrites the history api methods `.pushState` and `.replaceState`.
	onBound: function() {
		// if running in Node.js, don't setup.
		if (isNode()) {
			return;
		}

		var document = document$1(),
			window = global_1();

		this._value = getCurrentUrl();

		// Intercept routable links.
		canDomEvents_1_3_13_canDomEvents.addDelegateListener(document.documentElement, "click", "a", this.anchorClickHandler);
		var originalMethods = this.originalMethods = {};
		var dispatchHandlers = this.dispatchHandlers;

		// Rewrites original `pushState`/`replaceState` methods on `history`
		// and keeps pointer to original methods.
		canReflect_1_19_2_canReflect.eachKey(methodsToOverwrite, function(method) {
			this.originalMethods[method] = window.history[method];
			window.history[method] = function(state, title, url) {

				// Avoid doubled history states (with pushState).
				var absolute = url.indexOf("http") === 0;
				var location = location_1();
				var searchHash = location.search + location.hash;

				// If url differs from current call original history method and update `route` state.
				if ((!absolute && url !== location.pathname + searchHash) ||
					(absolute && url !== location.href + searchHash)) {
					originalMethods[method].apply(window.history, arguments);
					dispatchHandlers();
				}
			};
		}, this);

		// Bind dispatchHandlers to the `popstate` event, so they will fire
		// when `history.back()` or `history.forward()` methods are called.
		canDomEvents_1_3_13_canDomEvents.addEventListener(window, "popstate", this.dispatchHandlers);
	},

	// ### onUnbound
	// removes the event listerns for capturing routable links.
	// Sets `.pushState` and `.replacState` to their original methods.
	onUnbound: function() {
		// If running in Node.js, don't teardown.
		if(isNode()) {
			return;
		}

		var document = document$1(),
			window = global_1();

		canDomEvents_1_3_13_canDomEvents.removeDelegateListener(document.documentElement, "click", "a", this.anchorClickHandler);

		// Reset the changed `window.history` methods to their original values.
		canReflect_1_19_2_canReflect.eachKey(methodsToOverwrite, function(method) {
			window.history[method] = this.originalMethods[method];
		}, this);

		canDomEvents_1_3_13_canDomEvents.removeEventListener(window, "popstate", this.dispatchHandlers);
	},

	// ### get
	// Allows `PushstateObservable` to be observable by can-observations,
	// and returns the current url.
	get: function get() {
		canObservationRecorder_1_3_1_canObservationRecorder.add(this);
		return getCurrentUrl();
	},

	// ### set
	// Calls either pushState or replaceState on the difference
	// in properties between `oldProps` and `newProps`.
	set: function(path) {
		var newProps = canRoute_5_0_2_canRoute.deparam(path),
			oldProps = canRoute_5_0_2_canRoute.deparam(getCurrentUrl()),
			method = "pushState",
			changed = {};

		// Adds window.location.hash to path if it's not already in path.
		if (this.keepHash && path.indexOf("#") === -1 && window.location.hash) {
			path += window.location.hash;
		}

		// The old state and new state are diffed 
		// to figure out which keys are changing.
		map$2(oldProps, newProps)
			.forEach(function(patch) {
				// `patch.key` refers to the mutated property name on `newProps`.
				return changed[patch.key] = true;
			});

		// If any of the changed properties are in `replaceStateKeys` or 
		// `replaceStateOnceKeys` change the method to `'replaceState'`.
		if (this.replaceStateKeys.length) {
			this.replaceStateKeys.forEach(function(replaceKey) {
				if (changed[replaceKey]) {
					method = "replaceState";
				}
			});
		}
		
		if (this.replaceStateOnceKeys.length) {
			this.replaceStateOnceKeys
				.forEach(function(replaceOnceKey, index, thisArray) {
					if (changed[replaceOnceKey]) {
						method = "replaceState";
						// Remove so we don't attempt to replace 
						// the state on this key again.
						thisArray.splice(index, 1);
					}
				});
		}
		window.history[method](null, null, bindingProxy_1.call("root") + path);
	},

	// ### replaceStateOn
	// Adds given arguments to `this.replaceStateKeys`.
	replaceStateOn: function() {
		canReflect_1_19_2_canReflect.addValues(this.replaceStateKeys, canReflect_1_19_2_canReflect.toArray(arguments));
	},

	// ### replaceStateOnce
	// Adds given arguments to `this.replaceStateOnceKeys`.
	// Keys in `this.replaceStateOnceKeys` will be removed
	// from the array the first time a changed route contains that key.
	replaceStateOnce: function() {
		canReflect_1_19_2_canReflect.addValues(this.replaceStateOnceKeys, canReflect_1_19_2_canReflect.toArray(arguments));
	},

	// ### replaceStateOff
	// Removes given arguments from both `this.replaceStateKeys` and
	// `this.replaceOnceKeys`.
	replaceStateOff: function() {
		canReflect_1_19_2_canReflect.removeValues(this.replaceStateKeys, canReflect_1_19_2_canReflect.toArray(arguments));
		canReflect_1_19_2_canReflect.removeValues(this.replaceStateOnceKeys, canReflect_1_19_2_canReflect.toArray(arguments));
	}
});

canReflect_1_19_2_canReflect.assignSymbols(PushstateObservable.prototype, {
	"can.getValue": PushstateObservable.prototype.get,
	"can.setValue": PushstateObservable.prototype.set,
});

var canRoutePushstate_6_0_0_canRoutePushstate = PushstateObservable;

function shouldCheckSet(patch, destVal, sourceVal) {
    return patch.type === "set" && destVal && sourceVal &&
        typeof destVal === "object" &&
        typeof sourceVal === "object";
}

function makeIdentityFromMapSchema$1(typeSchema) {
    if(typeSchema.identity && typeSchema.identity.length) {
        return function identityCheck(a, b) {
            var aId = canReflect_1_19_2_canReflect.getIdentity(a, typeSchema),
                bId = canReflect_1_19_2_canReflect.getIdentity(b, typeSchema);
            return aId === bId;
        };
    }
}

function makeDiffListIdentityComparison(oldList, newList, parentKey, nestedPatches) {
    var listSchema = canReflect_1_19_2_canReflect.getSchema(oldList),
        typeSchema,
        identityCheckFromSchema,
        oldListLength = canReflect_1_19_2_canReflect.size( oldList );
    if(listSchema != null) {
        if(listSchema.values != null) {
            typeSchema = canReflect_1_19_2_canReflect.getSchema(listSchema.values);
        }
    }
    if(typeSchema == null && oldListLength > 0) {
        typeSchema = canReflect_1_19_2_canReflect.getSchema( canReflect_1_19_2_canReflect.getKeyValue(oldList, 0) );
    }
    if(typeSchema) {
        identityCheckFromSchema = makeIdentityFromMapSchema$1(typeSchema);
    }


    return function(a, b, aIndex) {
        if(canReflect_1_19_2_canReflect.isPrimitive(a)) {
            return a === b;
        }
        if(canReflect_1_19_2_canReflect.isPrimitive(b)) {
            return a === b;
        }
        if(identityCheckFromSchema) {
            if(identityCheckFromSchema(a, b)) {
                var patches = diffDeep(a, b, parentKey ? parentKey+"."+aIndex : ""+aIndex);
                nestedPatches.push.apply(nestedPatches, patches);
                return true;
            }
        }
        return diffDeep(a, b).length === 0;
    };
}

function diffDeep(dest, source, parentKey){

    if (dest && canReflect_1_19_2_canReflect.isMoreListLikeThanMapLike(dest)) {
        var nestedPatches = [],
            diffingIdentity = makeDiffListIdentityComparison(dest, source, parentKey, nestedPatches);

        var primaryPatches = list(dest, source, diffingIdentity).map(function(patch){
            if(parentKey) {
                patch.key = parentKey;
            }
            return patch;
        });

		return nestedPatches.concat(primaryPatches);
	} else {
        parentKey = parentKey ? parentKey+".": "";
		var patches = map$2(dest, source);
        // any sets we are going to recurse within
        var finalPatches = [];
        patches.forEach(function(patch){
            var key = patch.key;

            patch.key = parentKey + patch.key;
            var destVal = dest && canReflect_1_19_2_canReflect.getKeyValue(dest, key),
                sourceVal = source && canReflect_1_19_2_canReflect.getKeyValue(source, key);
            if(shouldCheckSet(patch, destVal, sourceVal)) {

                var deepPatches = diffDeep(destVal, sourceVal, patch.key);
                finalPatches.push.apply(finalPatches, deepPatches);
            } else {
                finalPatches.push(patch);
            }
        });
        return finalPatches;
	}
}

var deep = diffDeep;

var diff = {
    deep: deep,
    list: list,
    map: map$2,
    mergeDeep: mergeDeep,
    Patcher: patcher
};

var canDiff_1_5_1_canDiff = canNamespace_1_0_0_canNamespace.diff = diff;

/**
 * @module {function} can-make-map can-make-map
 * @parent can-js-utilities
 * @collection can-infrastructure
 * @package ./package.json
 * @description Convert a comma-separated string into a plain JavaScript object.
 * @signature `makeMap( string )`
 * @param  {String} string A comma separated list of values
 * @return {Object} A JavaScript object with the same keys as the passed-in comma-separated values
 *
 * makeMap takes a comma-separated string (can-list, NodeList, etc.) and converts it to a JavaScript object
 */
function makeMap$2(str) {
	var obj = {}, items = str.split(",");
	items.forEach(function(name){
		obj[name] = true;
	});
	return obj;
}

var canMakeMap_1_2_2_canMakeMap = makeMap$2;

/**
 * @function can-dom-events/helpers/add-jquery-events ./helpers/add-jquery-events
 * @parent can-dom-events.helpers
 * @description Add jQuery’s special events to the global registry.
 * @signature `addJQueryEvents(jQuery)`
 * @param {jQuery} jQuery Your instance of jQuery.
 * @return {function} The callback to remove the jQuery events from the registry.
 *
 * @body
 *
 * ```js
 * const $ = require("jquery");
 * const addJQueryEvents = require("can-dom-events/helpers/add-jquery-events");
 * const domEvents = require("can-dom-events");
 * // Require another module that registers itself with jQuery.event.special,
 * // e.g. jQuery++ registers events such as draginit, dragmove, etc.
 *
 * const removeJQueryEvents = addJQueryEvents($);
 *
 * // Listen for an event in code; this might also be accomplished through a
 * // can-stache-binding such as <li on:draginit="listener()">
 * domEvents.addEventListener(listItemElement, "draginit", function listener() {
 *   // Will fire after a jQuery draginit event has been fired
 * });
 *
 * // Some other code that fires a jQuery event; this will probably be in the
 * // package you’re using…
 * $(listItemElement).trigger("draginit");
 *
 * // Later in your code… ready to stop listening for those jQuery events? Call
 * // the function returned by addJQueryEvents()
 * removeJQueryEvents();
 * ```
 */
var addJqueryEvents = canNamespace_1_0_0_canNamespace.addJQueryEvents = function addJQueryEvents(jQuery) {
	var jQueryEvents = jQuery.event.special;
	var removeEvents = [];

	for (var eventType in jQueryEvents) {
		if (!canDomEvents_1_3_13_canDomEvents._eventRegistry.has(eventType)) {
			var eventDefinition = {
				defaultEventType: eventType,
				addEventListener: function (target, eventType, handler) {
					$(target).on(eventType, handler);
				},
				removeEventListener: function (target, eventType, handler) {
					$(target).off(eventType, handler);
				}
			};
			var removeEvent = canDomEvents_1_3_13_canDomEvents.addEvent(eventDefinition);
			removeEvents.push(removeEvent);
		}
	}

	return function removeJQueryEvents() {
		removeEvents.forEach(function(removeEvent) {
			removeEvent();
		});
	};
};

/**
 * @module {{}} can-dom-mutate/events/events
 * @parent can-dom-mutate/modules
 * 
 * @description This adds attributes, inserted and removed attributes to the DOM.
 * @signature `domMutateEvents`
 * 
 * `can-dom-mutate/events/events` Exports an object that allows to listen ```attributes```, ```inserted``` and ```removed``` events 
 *  in the DOM using [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
 * 
 * ```js
 * import domMutateEvents from "can-dom-mutate/events/events";
 * import domEvents from "can-dom-events";
 *
 * domMutateEvents //->
 * {
 *   attributes: {defaultEventType, addEventListener(), removeEventListener()},
 *   inserted: {defaultEventType, addEventListener(), removeEventListener},
 *   removed: {defaultEventType, addEventListener(), removeEventListener()},
 * }
 *
 * // listen to inserted change within an element:
 * // add inserted event to registry
 * domEvents.addEvent(domMutateEvents.inserted);
 * domEvent.addEventListener(document.querySelector("#foo"), "inserted", handler () => {})
 * ```
 */

function makeMutationEvent (defaultEventType, subscription, bubbles) {
	var elementSubscriptions = new Map();
	return {
		_subscriptions: elementSubscriptions,
		defaultEventType: defaultEventType,
		addEventListener: function (target, eventType, handler) {
			var dispatch = this.dispatch;
			var data = elementSubscriptions.get(target);
			if (!data) {
				data = {
					removeListener: null,
					listeners: new Set()
				};
				elementSubscriptions.set(target, data);
			}

			if (data.listeners.size === 0) {
				data.removeListener = subscription(target, function (mutation) {
					var eventData = {type: eventType};
					for (var key in mutation) {
						eventData[key] = mutation[key];
					}

					dispatch(target, eventData, bubbles !== false);
				});
			}

			data.listeners.add(handler);
			target.addEventListener(eventType, handler);
		},
		removeEventListener: function (target, eventType, handler) {
			target.removeEventListener(eventType, handler);
			var data = elementSubscriptions.get(target);
			if (data) {
				data.listeners['delete'](handler);
				if (data.listeners.size === 0) {
					data.removeListener();
					elementSubscriptions['delete'](target);
				}
			}		
		}
	};
}

var events$1 = canNamespace_1_0_0_canNamespace.domMutateDomEvents = {
	attributes: makeMutationEvent('attributes', canDomMutate_2_0_9_canDomMutate.onNodeAttributeChange),
	inserted: makeMutationEvent('inserted', canDomMutate_2_0_9_canDomMutate.onNodeConnected, false),
	removed: makeMutationEvent('removed', canDomMutate_2_0_9_canDomMutate.onNodeDisconnected)
};

// backwards compatibility
var canDomMutate_2_0_9_domEvents = canNamespace_1_0_0_canNamespace.domMutateDomEvents = events$1;

var warned = false;

var proxyNamespace = function proxyNamespace(namespace) {
	return new Proxy(namespace, {
		get: function get(target, name) {
			if (!warned) {
				console.warn("Warning: use of 'can' global should be for debugging purposes only.");
				warned = true;
			}
			return target[name];
		}
	});
};

var onValueSymbol$5 = canSymbol_1_7_0_canSymbol.for("can.onValue");
var offValueSymbol$3 = canSymbol_1_7_0_canSymbol.for("can.offValue");
var onKeyValueSymbol$7 = canSymbol_1_7_0_canSymbol.for("can.onKeyValue");
var offKeyValueSymbol$5 = canSymbol_1_7_0_canSymbol.for("can.offKeyValue");

var noop$3 = function noop() {};

function isFunction$2(value) {
	return typeof value === "function";
}

function withKey(obj, key, fn) {
	var result;

	if (isFunction$2(obj[onKeyValueSymbol$7])) {
		canReflect_1_19_2_canReflect.onKeyValue(obj, key, noop$3);
	}

	result = fn(obj, key);

	if (isFunction$2(obj[offKeyValueSymbol$5])) {
		canReflect_1_19_2_canReflect.offKeyValue(obj, key, noop$3);
	}

	return result;
}

function withoutKey(obj, fn) {
	var result;

	if (isFunction$2(obj[onValueSymbol$5])) {
		canReflect_1_19_2_canReflect.onValue(obj, noop$3);
	}

	result = fn(obj);

	if (isFunction$2(obj[offValueSymbol$3])) {
		canReflect_1_19_2_canReflect.offValue(obj, noop$3);
	}

	return result;
}

// Takes a function with signature `fn(obj, [key])`
// Makes sure that the argument is bound before calling 
// the function and unbinds it after the call is done.
var temporarilyBind$1 = function temporarilyBind(fn) {
	return function(obj, key) {
		var gotKey = arguments.length === 2;
		return gotKey ? withKey(obj, key, fn) : withoutKey(obj, fn);
	};
};

function Graph() {
	this.nodes = [];
	this.arrows = new Map();
	this.arrowsMeta = new Map();
}

// Adds the node, but it does not check if the node exists, callers will have
// to check that through [findNode]
Graph.prototype.addNode = function addNode(node) {
	this.nodes.push(node);
	this.arrows.set(node, new Set());
};

// Adds an arrow from head to tail with optional metadata
// The method does not check whether head and tail are already
// nodes in the graph, this should be done by the caller.
Graph.prototype.addArrow = function addArrow(head, tail, meta) {
	var graph = this;

	graph.arrows.get(head).add(tail);

	// optional
	if (meta) {
		addArrowMeta(graph, head, tail, meta);
	}
};

// Tests whether there is an arrow from head to tail
Graph.prototype.hasArrow = function hasArrow(head, tail) {
	return this.getNeighbors(head).has(tail);
};

// Returns the metadata associated to the head -> tail arrow
Graph.prototype.getArrowMeta = function getArrowMeta(head, tail) {
	return this.arrowsMeta.get(head) && this.arrowsMeta.get(head).get(tail);
};

// Sets metadata about the arrow from head to tail
// Merges the passed object into existing metadata
Graph.prototype.setArrowMeta = function setArrowMeta(head, tail, meta) {
	addArrowMeta(this, head, tail, meta);
};

// Returns a Set of all nodes 'y' such that there is an arrow
// from the node 'x' to the node 'y'.
Graph.prototype.getNeighbors = function getNeighbors(node) {
	return this.arrows.get(node);
};

// Returns the first node that satisfies the provided testing function.
// The Graph is traversed using depth first search
Graph.prototype.findNode = function findNode(cb) {
	var found = null;
	var graph = this;
	var i, node;

	for (i=0; i<graph.nodes.length; i++) {
		node = graph.nodes[i];
		if (cb(node)) {
			found = node;
			break;
		}
	}

	return found;
};

Graph.prototype.bfs = function bfs(visit) {
	var graph = this;

	var node = graph.nodes[0];
	var queue = [node];
	var visited = new Map();
	visited.set(node, true);

	while (queue.length) {
		node = queue.shift();

		visit(node);

		graph.arrows.get(node).forEach(function(adj) {
			if (!visited.has(adj)) {
				queue.push(adj);
				visited.set(adj, true);
			}
		});
	}
};

Graph.prototype.dfs = function dfs(visit) {
	var graph = this;

	var node = graph.nodes[0];
	var stack = [node];
	var visited = new Map();

	while (stack.length) {
		node = stack.pop();

		visit(node);

		if (!visited.has(node)) {
			visited.set(node, true);
			graph.arrows.get(node).forEach(function(adj) {
				stack.push(adj);
			});
		}
	}
};

// Returns a new graph where the arrows point to the opposite direction, that is:
// For each arrow (u, v) in [this], there will be a (v, u) in the returned graph
// This is also called Transpose or Converse a graph
Graph.prototype.reverse = function reverse() {
	var graph = this;
	var reversed = new Graph();

	// copy over the nodes
	graph.nodes.forEach(reversed.addNode.bind(reversed));

	graph.nodes.forEach(function(node) {
		graph.getNeighbors(node).forEach(function(adj) {
			// add the arrow in the opposite direction, copy over metadata
			var meta = graph.getArrowMeta(node, adj);
			reversed.addArrow(adj, node, meta);
		});
	});

	return reversed;
};

// Helpers
function addArrowMeta(graph, head, tail, meta) {
	var entry = graph.arrowsMeta.get(head);

	if (entry) {
		var arrowMeta = entry.get(tail);
		if (!arrowMeta) {
			arrowMeta = {};
		}
		entry.set(tail, canAssign_1_3_3_canAssign(arrowMeta, meta));
	} else {
		entry = new Map();
		entry.set(tail, meta);
		graph.arrowsMeta.set(head, entry);
	}
}

var graph = Graph;

var makeNode = function makeNode(obj, key) {
	var gotKey = arguments.length === 2;

	var node = {
		obj: obj,
		name: canReflect_1_19_2_canReflect.getName(obj),
		value: gotKey ? canReflect_1_19_2_canReflect.getKeyValue(obj, key) : canReflect_1_19_2_canReflect.getValue(obj)
	};

	if (gotKey) {
		node.key = key;
	}

	return node;
};

// Returns a directed graph of the dependencies of obj (key is optional)
//
// Signature:
//	getDirectedGraph(obj)
//	getDirectedGraph(obj, key)
var getGraph = function getGraph(obj, key) {
	var order = 0;
	var graph$$1 = new graph();
	var gotKey = arguments.length === 2;

	var addArrow = function addArrow(direction, parent, child, meta) {
		switch (direction) {
			case "whatIChange":
				graph$$1.addArrow(parent, child, meta); break;
			case "whatChangesMe":
				graph$$1.addArrow(child, parent, meta); break;
			default:
				throw new Error("Unknown direction value: ", meta.direction);
		}
	};

	// keyDependencies :: Map<obj, Set<key>>
	var visitKeyDependencies = function visitKeyDependencies(source, meta, cb) {
		canReflect_1_19_2_canReflect.eachKey(source.keyDependencies || {}, function(keys, obj) {
			canReflect_1_19_2_canReflect.each(keys, function(key) {
				cb(obj, meta, key);
			});
		});
	};

	// valueDependencies :: Set<obj>
	var visitValueDependencies = function visitValueDependencies(source, meta, cb) {
		canReflect_1_19_2_canReflect.eachIndex(source.valueDependencies || [], function(obj) {
			cb(obj, meta);
		});
	};

	var visit = function visit(obj, meta, key) {
		var gotKey = arguments.length === 3;

		var node = graph$$1.findNode(function(node) {
			return gotKey ?
				node.obj === obj && node.key === key :
				node.obj === obj;
		});

		// if there is a node already in the graph, add the arrow and prevent
		// infinite calls to `visit` by returning early
		if (node) {
			if (meta.parent) {
				addArrow(meta.direction, meta.parent, node, {
					kind: meta.kind,
					direction: meta.direction
				});
			}
			return graph$$1;
		}

		// create and add a node to the graph
		order += 1;
		node = gotKey ? makeNode(obj, key) : makeNode(obj);
		node.order = order;
		graph$$1.addNode(node);

		// if there is a known parent node, add the arrow in the given direction
		if (meta.parent) {
			addArrow(meta.direction, meta.parent, node, {
				kind: meta.kind,
				direction: meta.direction
			});
		}

		// get the dependencies of the new node and recursively visit those
		var nextMeta;
		var data = gotKey ?
			canReflectDependencies_1_1_2_canReflectDependencies.getDependencyDataOf(obj, key) :
			canReflectDependencies_1_1_2_canReflectDependencies.getDependencyDataOf(obj);

		if (data && data.whatIChange) {
			nextMeta = { direction: "whatIChange", parent: node };

			// kind :: derive | mutate
			canReflect_1_19_2_canReflect.eachKey(data.whatIChange, function(dependencyRecord, kind) {
				nextMeta.kind = kind;
				visitKeyDependencies(dependencyRecord, nextMeta, visit);
				visitValueDependencies(dependencyRecord, nextMeta, visit);
			});
		}

		if (data && data.whatChangesMe) {
			nextMeta = { direction: "whatChangesMe", parent: node };

			// kind :: derive | mutate
			canReflect_1_19_2_canReflect.eachKey(data.whatChangesMe, function(dependencyRecord, kind) {
				nextMeta.kind = kind;
				visitKeyDependencies(dependencyRecord, nextMeta, visit);
				visitValueDependencies(dependencyRecord, nextMeta, visit);
			});
		}

		return graph$$1;
	};

	return gotKey ? visit(obj, {}, key) : visit(obj, {});
};

// Converts the graph into a data structure that vis.js requires to draw the graph
var formatGraph = function formatGraph(graph) {
	// { [node]: Number }
	var nodeIdMap = new Map();
	graph.nodes.forEach(function(node, index) {
		nodeIdMap.set(node, index + 1);
	});

	// collects nodes in the shape of { id: Number, label: String }
	var nodesDataSet = graph.nodes.map(function(node) {
		return {
			shape: "box",
			id: nodeIdMap.get(node),
			label:
				canReflect_1_19_2_canReflect.getName(node.obj) +
				(node.key ? "." + node.key : "")
		};
	});

	var getArrowData = function getArrowData(meta) {
		var regular = { arrows: "to" };
		var withDashes = { arrows: "to", dashes: true };

		var map = {
			derive: regular,
			mutate: withDashes
		};

		return map[meta.kind];
	};

	// collect edges in the shape of { from: Id, to: Id }
	var visited = new Map();
	var arrowsDataSet = [];
	graph.nodes.forEach(function(node) {
		var visit = function(node) {
			if (!visited.has(node)) {
				visited.set(node, true);
				var arrows = graph.arrows.get(node);
				var headId = nodeIdMap.get(node);

				arrows.forEach(function(neighbor) {
					var tailId = nodeIdMap.get(neighbor);
					var meta = graph.arrowsMeta.get(node).get(neighbor);

					arrowsDataSet.push(
						canAssign_1_3_3_canAssign(
							{ from: headId, to: tailId },
							getArrowData(meta)
						)
					);

					visit(neighbor);
				});
			}
		};

		visit(node);
	});
	
	return {
		nodes: nodesDataSet,
		edges: arrowsDataSet
	};
};

var quoteString$1 = function quoteString(x) {
	return typeof x === "string" ? JSON.stringify(x) : x;
};

var logData = function log(data) {
	var node = data.node;
	var nameParts = [node.name, "key" in node ? "." + node.key : ""];

	console.group(nameParts.join(""));
	console.log("value  ", quoteString$1(node.value));
	console.log("object ", node.obj);

	if (data.derive.length) {
		console.group("DERIVED FROM");
		canReflect_1_19_2_canReflect.eachIndex(data.derive, log);
		console.groupEnd();
	}

	if (data.mutations.length) {
		console.group("MUTATED BY");
		canReflect_1_19_2_canReflect.eachIndex(data.mutations, log);
		console.groupEnd();
	}

	if (data.twoWay.length) {
		console.group("TWO WAY");
		canReflect_1_19_2_canReflect.eachIndex(data.twoWay, log);
		console.groupEnd();
	}

	console.groupEnd();
};

// Returns a new graph with all the arrows not involved in a circuit
var labelCycles = function labelCycles(graph$$1) {
	var visited = new Map();
	var result = new graph();

	// copy over all nodes
	graph$$1.nodes.forEach(function(node) {
		result.addNode(node);
	});

	var visit = function visit(node) {
		visited.set(node, true);

		graph$$1.getNeighbors(node).forEach(function(adj) {
			// back arrow found
			if (visited.has(adj)) {
				// if isTwoWay is false it means the cycle involves more than 2 nodes,
				// e.g: A -> B -> C -> A
				// what to do in these cases? (currently ignoring these)
				var isTwoWay = graph$$1.hasArrow(node, adj);

				if (isTwoWay) {
					result.addArrow(adj, node, { kind: "twoWay" });
				}
			// copy over arrows not involved in a cycle
			} else {
				result.addArrow(node, adj, graph$$1.getArrowMeta(node, adj));
				visit(adj);
			}
		});
	};

	visit(graph$$1.nodes[0]);
	return result;
};

var isDisconnected = function isDisconnected(data) {
	return (
		!data.derive.length &&
		!data.mutations.length &&
		!data.twoWay.length
	);
};

// Returns a deeply nested object from the graph
var getData = function getDebugData(inputGraph, direction) {
	var visited = new Map();

	var graph = labelCycles(
		direction === "whatChangesMe" ? inputGraph.reverse() : inputGraph
	);

	var visit = function visit(node) {
		var data = { node: node, derive: [], mutations: [], twoWay: [] };

		visited.set(node, true);

		graph.getNeighbors(node).forEach(function(adj) {
			var meta = graph.getArrowMeta(node, adj);

			if (!visited.has(adj)) {
				switch (meta.kind) {
					case "twoWay":
						data.twoWay.push(visit(adj));
						break;

					case "derive":
						data.derive.push(visit(adj));
						break;

					case "mutate":
						data.mutations.push(visit(adj));
						break;

					default:
						throw new Error("Unknow meta.kind value: ", meta.kind);
				}
			}
		});

		return data;
	};

	// discard data if there are no arrows registered, this happens when
	// [direction] is passed in and no arrow metadada matches its value
	var result = visit(graph.nodes[0]);
	return isDisconnected(result) ? null : result;
};

// key :: string | number | null | undefined
var whatIChange = function logWhatIChange(obj, key) {
	var gotKey = arguments.length === 2;

	var data = getData(
		gotKey ? getGraph(obj, key) : getGraph(obj),
		"whatIChange"
	);

	if (data) {
		logData(data);
	}
};

// key :: string | number | null | undefined
var whatChangesMe = function logWhatChangesMe(obj, key) {
	var gotKey = arguments.length === 2;

	var data = getData(
		gotKey ? getGraph(obj, key) : getGraph(obj),
		"whatChangesMe"
	);

	if (data) {
		logData(data);
	}
};

var getWhatIChange$1 = function getWhatChangesMe(obj, key) {
	var gotKey = arguments.length === 2;

	return getData(
		gotKey ? getGraph(obj, key) : getGraph(obj),
		"whatIChange"
	);
};

var getWhatChangesMe$1 = function getWhatChangesMe(obj, key) {
	var gotKey = arguments.length === 2;

	return getData(
		gotKey ? getGraph(obj, key) : getGraph(obj),
		"whatChangesMe"
	);
};

var global$5 = canGlobals_1_2_2_canGlobals.getKeyValue("global");

var devtoolsRegistrationComplete = false;
function registerWithDevtools() {
	if (devtoolsRegistrationComplete) {
		return;
	}

	var devtoolsGlobalName =  "__CANJS_DEVTOOLS__";
	var devtoolsCanModules = {
		Observation: canObservation_4_2_0_canObservation,
		Reflect: canReflect_1_19_2_canReflect,
		Symbol: canSymbol_1_7_0_canSymbol,
		formatGraph: canNamespace_1_0_0_canNamespace.debug.formatGraph,
		getGraph: canNamespace_1_0_0_canNamespace.debug.getGraph,
		mergeDeep: mergeDeep,
		queues: canQueues_1_3_2_canQueues
	};

	if (global$5[devtoolsGlobalName]) {
		global$5[devtoolsGlobalName].register(devtoolsCanModules);
	} else {
		Object.defineProperty(global$5, devtoolsGlobalName, {
			set: function(devtoolsGlobal) {
				Object.defineProperty(global$5, devtoolsGlobalName, {
					value: devtoolsGlobal
				});

				devtoolsGlobal.register(devtoolsCanModules);
			},
			configurable: true
		});
	}

	devtoolsRegistrationComplete = true;
}

var canDebug_2_0_7_canDebug = function() {
	canNamespace_1_0_0_canNamespace.debug = {
		formatGraph: temporarilyBind$1(formatGraph),
		getGraph: temporarilyBind$1(getGraph),
		getWhatIChange: temporarilyBind$1(getWhatIChange$1),
		getWhatChangesMe: temporarilyBind$1(getWhatChangesMe$1),
		logWhatIChange: temporarilyBind$1(whatIChange),
		logWhatChangesMe: temporarilyBind$1(whatChangesMe)
	};

	registerWithDevtools();

	global$5.can = typeof Proxy !== "undefined" ? proxyNamespace(canNamespace_1_0_0_canNamespace) : canNamespace_1_0_0_canNamespace;

	return canNamespace_1_0_0_canNamespace.debug;
};

//!steal-remove-start
if (process.env.NODE_ENV !== 'production') {
	canDebug_2_0_7_canDebug();
}
//!steal-remove-end

// __ Observables __
//!steal-remove-end

export default canNamespace_1_0_0_canNamespace;
export { canValue_1_1_2_canValue as value, canObservation_4_2_0_canObservation as Observation, canObservationRecorder_1_3_1_canObservationRecorder as ObservationRecorder, canSimpleMap_4_3_3_canSimpleMap as SimpleMap, canObservableObject as ObservableObject, canObservableArray as ObservableArray, canObservableBindings_1_3_3_fromAttribute as fromAttribute, canBind_1_5_1_canBind as bind, map$1 as mapEventBindings, value as valueEventBindings, canSimpleObservable_2_5_0_canSimpleObservable as SimpleObservable, async as AsyncObservable, key as keyObservable, resolver as ResolverObservable, settable as SettableObservable, setter as SetterObservable, canStacheElement as StacheElement, canStache_5_1_1_canStache as stache, canStacheBindings_5_0_5_canStacheBindings as stacheBindings, canStacheRouteHelpers_2_0_0_canStacheRouteHelpers as stacheRouteHelpers, canViewCallbacks_5_0_0_canViewCallbacks as viewCallbacks, canViewLive_5_0_5_canViewLive as viewLive, canViewModel_4_0_3_canViewModel as viewModel, canViewParser_4_1_3_canViewParser as viewParser, canViewScope_4_13_7_canViewScope as Scope, canViewTarget_5_0_0_canViewTarget as target, canFixture_3_1_7_fixture as fixture, canQueryLogic_1_2_4_canQueryLogic as QueryLogic, canRealtimeRestModel_2_0_0_canRealtimeRestModel as realtimeRestModel, canRestModel_2_0_0_canRestModel as restModel, canConnect_4_0_6_all as connect, canLocalStore_1_0_1_canLocalStore as localStore, canMemoryStore_1_0_3_canMemoryStore as memoryStore, canRoute_5_0_2_canRoute as route, canRouteHash_1_0_2_canRouteHash as RouteHash, canRoutePushstate_6_0_0_canRoutePushstate as RoutePushstate, canParam_1_2_0_canParam as param, canDeparam_1_2_3_canDeparam as deparam, canAssign_1_3_3_canAssign as assign, canDefineLazyValue_1_1_1_defineLazyValue as defineLazyValue, canDiff_1_5_1_canDiff as diff, canGlobals_1_2_2_canGlobals as globals, canKey_1_2_1_canKey as key, canKeyTree_1_2_2_canKeyTree as KeyTree, canMakeMap_1_2_2_canMakeMap as makeMap, canParseUri_1_2_2_canParseUri as parseURI, canQueues_1_3_2_canQueues as queues, canString_1_1_0_canString as string, canStringToAny_1_2_1_canStringToAny as stringToAny, canAjax_2_4_8_canAjax as ajax, canAttributeEncoder_1_1_4_canAttributeEncoder as attributeEncoder, canChildNodes_1_2_1_canChildNodes as childNodes, canDomData_1_0_3_canDomData as domData, canDomEvents_1_3_13_canDomEvents as domEvents, addJqueryEvents as addJQueryEvents, canDomMutate_2_0_9_canDomMutate as domMutate, canDomMutate_2_0_9_node as domMutateNode, canDomMutate_2_0_9_domEvents as domMutateDomEvents, canFragment_1_3_1_canFragment as fragment, canValidateInterface_1_0_3_index as makeInterfaceValidator, canCid_1_3_1_canCid as cid, canConstruct_3_5_7_canConstruct as Construct, maybeBoolean as MaybeBoolean, maybeDate as MaybeDate, maybeNumber as MaybeNumber, maybeString as MaybeString, canNamespace_1_0_0_canNamespace as can, canReflect_1_19_2_canReflect as Reflect, canReflectDependencies_1_1_2_canReflectDependencies as reflectDependencies, canReflectPromise_2_2_1_canReflectPromise as reflectPromise, canType_1_1_6_canType as type };
