summaryrefslogtreecommitdiffstats
path: root/fastdom-strict.js
diff options
context:
space:
mode:
Diffstat (limited to 'fastdom-strict.js')
-rw-r--r--fastdom-strict.js960
1 files changed, 960 insertions, 0 deletions
diff --git a/fastdom-strict.js b/fastdom-strict.js
new file mode 100644
index 0000000..007521d
--- /dev/null
+++ b/fastdom-strict.js
@@ -0,0 +1,960 @@
+(function webpackUniversalModuleDefinition(root, factory) {
+ if(typeof exports === 'object' && typeof module === 'object')
+ module.exports = factory(require("fastdom"));
+ else if(typeof define === 'function' && define.amd)
+ define(["fastdom"], factory);
+ else if(typeof exports === 'object')
+ exports["fastdom"] = factory(require("fastdom"));
+ else
+ root["fastdom"] = factory(root["fastdom"]);
+})(this, function(__WEBPACK_EXTERNAL_MODULE_2__) {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId])
+/******/ return installedModules[moduleId].exports;
+
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ exports: {},
+/******/ id: moduleId,
+/******/ loaded: false
+/******/ };
+
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+
+/******/ // Flag the module as loaded
+/******/ module.loaded = true;
+
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+
+
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ function(module, exports, __webpack_require__) {
+
+ 'use strict';
+
+ var strictdom = __webpack_require__(1);
+ var fastdom = __webpack_require__(2);
+
+ /**
+ * Mini logger
+ *
+ * @return {Function}
+ */
+ var debug = 0 ? console.log.bind(console, '[fastdom-strict]') : function() {};
+
+ /**
+ * Enabled state
+ *
+ * @type {Boolean}
+ */
+ var enabled = false;
+
+ window.fastdom = module.exports = fastdom.extend({
+ measure: function(task, ctx) {
+ debug('measure');
+ return this.fastdom.measure(function() {
+ if (!enabled) return task();
+ return strictdom.phase('measure', task);
+ }, ctx);
+ },
+
+ mutate: function(task, ctx) {
+ debug('mutate');
+ return this.fastdom.mutate(function() {
+ if (!enabled) return task();
+ return strictdom.phase('mutate', task);
+ }, ctx);
+ },
+
+ strict: function(value) {
+ if (value) {
+ enabled = true;
+ strictdom.enable();
+ } else {
+ enabled = false;
+ strictdom.disable();
+ }
+ }
+ });
+
+ // turn on strict-mode
+ window.fastdom.strict(true);
+
+
+/***/ },
+/* 1 */
+/***/ function(module, exports, __webpack_require__) {
+
+ var __WEBPACK_AMD_DEFINE_RESULT__;!(function() {
+ 'use strict';
+
+ var debug = 0 ? console.log.bind(console, '[strictdom]') : function() {};
+
+ /**
+ * Crude webkit test.
+ *
+ * @type {Boolean}
+ */
+ var isWebkit = !!window.webkitURL;
+
+ /**
+ * List of properties observed.
+ *
+ * @type {Object}
+ */
+ var properties = {
+ prototype: {
+ Document: {
+ execCommand: Mutate,
+ elementFromPoint: Measure,
+ elementsFromPoint: Measure,
+ scrollingElement: Measure
+ },
+
+ Node: {
+ appendChild: {
+ type: Mutate,
+ test: function(dom, parent, args) {
+ var attached = isAttached(parent) || isAttached(args[0]);
+ if (attached && dom.not('mutate')) throw error(3, this.name);
+ }
+ },
+
+ insertBefore: {
+ type: Mutate,
+ test: function(dom, parent, args) {
+ var attached = isAttached(parent) || isAttached(args[0]);
+ if (attached && dom.not('mutate')) throw error(3, this.name);
+ }
+ },
+
+ removeChild: {
+ type: Mutate,
+ test: function(dom, parent, args) {
+ var attached = isAttached(parent) || isAttached(args[0]);
+ if (attached && dom.not('mutate')) throw error(3, this.name);
+ }
+ },
+
+ textContent: Mutate
+ },
+
+ Element: {
+ scrollIntoView: Mutate,
+ scrollBy: Mutate,
+ scrollTo: Mutate,
+ getClientRects: Measure,
+ getBoundingClientRect: Measure,
+ clientLeft: Measure,
+ clientWidth: Measure,
+ clientHeight: Measure,
+ scrollLeft: Accessor,
+ scrollTop: Accessor,
+ scrollWidth: Measure,
+ scrollHeight: Measure,
+ innerHTML: Mutate,
+ outerHTML: Mutate,
+ insertAdjacentHTML: Mutate,
+ remove: Mutate,
+ setAttribute: Mutate,
+ removeAttribute: Mutate,
+ className: Mutate,
+ classList: ClassList
+ },
+
+ HTMLElement: {
+ offsetLeft: Measure,
+ offsetTop: Measure,
+ offsetWidth: Measure,
+ offsetHeight: Measure,
+ offsetParent: Measure,
+ innerText: Accessor,
+ outerText: Accessor,
+ focus: Measure,
+ blur: Measure,
+ style: Style,
+
+ // `element.dataset` is hard to wrap.
+ // We could use `Proxy` but it's not
+ // supported in Chrome yet. Not too
+ // concerned as `data-` attributes are
+ // not often associated with render.
+ // dataset: DATASET
+ },
+
+ CharacterData: {
+ remove: Mutate,
+ data: Mutate
+ },
+
+ Range: {
+ getClientRects: Measure,
+ getBoundingClientRect: Measure
+ },
+
+ MouseEvent: {
+ layerX: Measure,
+ layerY: Measure,
+ offsetX: Measure,
+ offsetY: Measure
+ },
+
+ HTMLButtonElement: {
+ reportValidity: Measure
+ },
+
+ HTMLDialogElement: {
+ showModal: Mutate
+ },
+
+ HTMLFieldSetElement: {
+ reportValidity: Measure
+ },
+
+ HTMLImageElement: {
+ width: Accessor,
+ height: Accessor,
+ x: Measure,
+ y: Measure
+ },
+
+ HTMLInputElement: {
+ reportValidity: Measure
+ },
+
+ HTMLKeygenElement: {
+ reportValidity: Measure
+ },
+
+ SVGSVGElement: {
+ currentScale: Accessor
+ }
+ },
+
+ instance: {
+ window: {
+ getComputedStyle: {
+ type: Measure,
+
+ /**
+ * Throws when the Element is in attached
+ * and strictdom is not in the 'measure' phase.
+ *
+ * @param {StrictDom} strictdom
+ * @param {Window} win
+ * @param {Object} args
+ */
+ test: function(strictdom, win, args) {
+ if (isAttached(args[0]) && strictdom.not('measure')) {
+ throw error(2, 'getComputedStyle');
+ }
+ }
+ },
+
+ innerWidth: {
+ type: isWebkit ? Value : Measure,
+
+ /**
+ * Throws when the window is nested (in <iframe>)
+ * and StrictDom is not in the 'measure' phase.
+ *
+ * @param {StrictDom} strictdom
+ */
+ test: function(strictdom) {
+ var inIframe = window !== window.top;
+ if (inIframe && strictdom.not('measure')) {
+ throw error(2, '`.innerWidth` (in iframe)');
+ }
+ }
+ },
+
+ innerHeight: {
+ type: isWebkit ? Value : Measure,
+
+ /**
+ * Throws when the window is nested (in <iframe>)
+ * and StrictDom is not in the 'measure' phase.
+ *
+ * @param {StrictDom} strictdom
+ */
+ test: function(strictdom) {
+ var inIframe = window !== window.top;
+ if (inIframe && strictdom.not('measure')) {
+ throw error(2, '`.innerHeight` (in iframe)');
+ }
+ }
+ },
+
+ scrollX: isWebkit ? Value : Measure,
+ scrollY: isWebkit ? Value : Measure,
+ scrollBy: Mutate,
+ scrollTo: Mutate,
+ scroll: Mutate,
+ }
+ }
+ };
+
+ /**
+ * The master controller for all properties.
+ *
+ * @param {Window} win
+ */
+ function StrictDom(win) {
+ this.properties = [];
+ this._phase = null;
+ this.win = win;
+
+ this.createPrototypeProperties();
+ this.createInstanceProperties();
+ }
+
+ StrictDom.prototype = {
+
+ /**
+ * Set the current phase.
+ * @param {[type]} value [description]
+ * @return {[type]} [description]
+ */
+ phase: function(type, task) {
+ if (!arguments.length) return this._phase;
+ if (!this.knownPhase(type)) throw error(4, type);
+
+ var previous = this._phase;
+ this._phase = type;
+
+ if (typeof task != 'function') return;
+
+ var result = task();
+ this._phase = previous;
+ return result;
+ },
+
+ knownPhase: function(value) {
+ return !!~['measure', 'mutate', null].indexOf(value);
+ },
+
+ is: function(value) {
+ return this._phase === value;
+ },
+
+ not: function(value) {
+ return !this.is(value);
+ },
+
+ /**
+ * Enable strict mode.
+ *
+ * @public
+ */
+ enable: function() {
+ if (this.enabled) return;
+ debug('enable');
+ var i = this.properties.length;
+ while (i--) this.properties[i].enable();
+ this.enabled = true;
+ },
+
+ /**
+ * Disable strict mode.
+ *
+ * @public
+ */
+ disable: function() {
+ if (!this.enabled) return;
+ debug('disable');
+ var i = this.properties.length;
+ while (i--) this.properties[i].disable();
+ this.enabled = false;
+ this.phase(null);
+ },
+
+ /**
+ * Create wrappers for each of
+ * of the prototype properties.
+ *
+ * @private
+ */
+ createPrototypeProperties: function() {
+ debug('create prototype properties');
+ var props = properties.prototype;
+ for (var key in props) {
+ for (var name in props[key]) {
+ var object = this.win[key] && this.win[key].prototype;
+ if (!object || !object.hasOwnProperty(name)) continue;
+ this.properties.push(this.create(object, name, props[key][name]));
+ }
+ }
+ },
+
+ /**
+ * Create wrappers for each of
+ * of the instance properties.
+ *
+ * @private
+ */
+ createInstanceProperties: function() {
+ debug('create instance properties');
+ var props = properties.instance;
+ for (var key in props) {
+ for (var name in props[key]) {
+ var object = this.win[key];
+ if (!object || !object.hasOwnProperty(name)) continue;
+ this.properties.push(this.create(object, name, props[key][name]));
+ }
+ }
+ },
+
+ /**
+ * Create a wrapped `Property` that
+ * can be individually enabled/disabled.
+ *
+ * @param {Object} object - the parent object (eg. Node.prototype)
+ * @param {String} name - the property name (eg. 'appendChild')
+ * @param {(constructor|Object)} config - from the above property definition
+ * @return {Property}
+ */
+ create: function(object, name, config) {
+ debug('create', name);
+ var Constructor = config.type || config;
+ return new Constructor(object, name, config, this);
+ }
+ };
+
+ /**
+ * Create a new `Property`.
+ *
+ * A wrapper around a property that observes
+ * usage, throwing errors when used in the
+ * incorrect phase.
+ *
+ * @param {Object} object - the parent object (eg. Node.prototype)
+ * @param {[type]} name - the property name (eg. 'appendChild')
+ * @param {(constructor|Object)} config - from the above definition
+ * @param {StrictDom} strictdom - injected as a dependency
+ */
+ function Property(object, name, config, strictdom) {
+ debug('Property', name, config);
+
+ this.strictdom = strictdom;
+ this.object = object;
+ this.name = name;
+
+ var descriptor = this.getDescriptor();
+
+ // defaults can be overriden from config
+ if (typeof config == 'object') Object.assign(this, config);
+
+ this.descriptors = {
+ unwrapped: descriptor,
+ wrapped: this.wrap(descriptor)
+ };
+ }
+
+ Property.prototype = {
+
+ /**
+ * Get the property's descriptor.
+ *
+ * @return {Object}
+ * @private
+ */
+ getDescriptor: function() {
+ debug('get descriptor', this.name);
+ return Object.getOwnPropertyDescriptor(this.object, this.name);
+ },
+
+ /**
+ * Enable observation by replacing the
+ * current descriptor with the wrapped one.
+ *
+ * @private
+ */
+ enable: function() {
+ debug('enable', this.name);
+ Object.defineProperty(this.object, this.name, this.descriptors.wrapped);
+ },
+
+ /**
+ * Disable observation by replacing the
+ * current descriptor with the original one.
+ *
+ * @private
+ */
+ disable: function() {
+ debug('disable', this.name);
+ Object.defineProperty(this.object, this.name, this.descriptors.unwrapped);
+ },
+
+ // to be overwritten by subclass
+ wrap: function() {}
+ };
+
+ /**
+ * A wrapper for properties that measure
+ * geometry data from the DOM.
+ *
+ * Once a `Measure` property is enabled
+ * it can only be used when StrictDom
+ * is in the 'measure' phase, else it
+ * will throw.
+ *
+ * @constructor
+ * @extends Property
+ */
+ function Measure() {
+ Property.apply(this, arguments);
+ }
+
+ Measure.prototype = extend(Property, {
+
+ /**
+ * Return a wrapped descriptor.
+ *
+ * @param {Object} descriptor
+ * @return {Object}
+ */
+ wrap: function(descriptor) {
+ debug('wrap measure', this.name);
+
+ var clone = Object.assign({}, descriptor);
+ var value = descriptor.value;
+ var get = descriptor.get;
+ var self = this;
+
+ if (typeof value == 'function') {
+ clone.value = function() {
+ debug('measure', self.name);
+ self.test(self.strictdom, this, arguments);
+ return value.apply(this, arguments);
+ };
+ } else if (get) {
+ clone.get = function() {
+ debug('measure', self.name);
+ self.test(self.strictdom, this, arguments);
+ return get.apply(this, arguments);
+ };
+ }
+
+ return clone;
+ },
+
+ /**
+ * Throws an Error if the element is attached
+ * and StrictDOM is not in the 'measure' phase.
+ *
+ * If methods/properties are used without
+ * a context (eg. `getComputedStyle()` instead
+ * of `window.getComputedStyle()`) we infer
+ * a `window` context.
+ *
+ * @param {StrictDom} strictdom
+ * @param {Node} ctx
+ */
+ test: function(strictdom, ctx) {
+ if (isAttached(ctx || window) && strictdom.not('measure')) {
+ throw error(2, this.name);
+ }
+ }
+ });
+
+ /**
+ * A wrapper for properties that mutate
+ * to the DOM, triggering style/reflow
+ * operations.
+ *
+ * Once a `Mutate` property is enabled
+ * it can only be used when StrictDom
+ * is in the 'measure' phase, else it
+ * will throw.
+ *
+ * @constructor
+ * @extends Property
+ */
+ function Mutate() {
+ Property.apply(this, arguments);
+ }
+
+ Mutate.prototype = extend(Property, {
+
+ /**
+ * Return a wrapped descriptor.
+ *
+ * @param {Object} descriptor
+ * @return {Object}
+ */
+ wrap: function(descriptor) {
+ debug('wrap mutate', this.name);
+
+ var clone = Object.assign({}, descriptor);
+ var value = descriptor.value;
+ var self = this;
+
+ if (typeof value == 'function') {
+ clone.value = function() {
+ self.test(self.strictdom, this, arguments);
+ return value.apply(this, arguments);
+ };
+ } else if (descriptor.set) {
+ clone.set = function() {
+ self.test(self.strictdom, this, arguments);
+ return descriptor.set.apply(this, arguments);
+ };
+ }
+
+ return clone;
+ },
+
+ /**
+ * Throws an Error if the element is attached
+ * and StrictDOM is not in the 'mutate' phase.
+ *
+ * If methods/properties are used without
+ * a context (eg. `getComputedStyle()` instead
+ * of `window.getComputedStyle()`) we infer
+ * a `window` context.
+ *
+ * @param {StrictDom} strictdom
+ * @param {Node} ctx
+ */
+ test: function(strictdom, ctx) {
+ if (isAttached(ctx || window) && strictdom.not('mutate')) {
+ throw error(3, this.name);
+ }
+ }
+ });
+
+ /**
+ * A wrapper for 'accessor' (get/set) properties.
+ *
+ * An `Accessor` should be used to wrap
+ * properties that can both measure and mutate
+ * the DOM (eg. `element.scrollTop`).
+ *
+ * @constructor
+ * @extends Property
+ */
+ function Accessor() {
+ Property.apply(this, arguments);
+ }
+
+ Accessor.prototype = extend(Property, {
+
+ /**
+ * Return a wrapped descriptor.
+ *
+ * @param {Object} descriptor
+ * @return {Object}
+ */
+ wrap: function(descriptor) {
+ debug('wrap accessor', this.name);
+
+ var clone = Object.assign({}, descriptor);
+ var get = descriptor.get;
+ var set = descriptor.set;
+ var self = this;
+
+ if (get) {
+ clone.get = function() {
+ self.testRead(self.strictdom, this, arguments);
+ return get.apply(this, arguments);
+ };
+ }
+
+ if (descriptor.set) {
+ clone.set = function() {
+ self.testWrite(self.strictdom, this, arguments);
+ return set.apply(this, arguments);
+ };
+ }
+
+ return clone;
+ },
+
+ testRead: Measure.prototype.test,
+ testWrite: Mutate.prototype.test
+ });
+
+ /**
+ * A wrapper for 'value' properties.
+ *
+ * A `Value` should be used to wrap special
+ * values that like `window.innerWidth`, which
+ * in Chrome (not Gecko) are not normal 'getter'
+ * functions, but magical flat getters.
+ *
+ * Value wrappers are a for very special cases.
+ *
+ * @constructor
+ * @extends Property
+ */
+ function Value() {
+ Property.apply(this, arguments);
+ }
+
+ Value.prototype = extend(Property, {
+
+ /**
+ * Calling `Object.getOwnDescriptor()` can
+ * trigger a reflow as it returns the `value`
+ * of the property. So here we just
+ * return an empty object instead.
+ *
+ * @return {Object}
+ * @private
+ */
+ getDescriptor: function() {
+ return {};
+ },
+
+ /**
+ * Value wrappers are disabled by simply
+ * deleting them from the instance,
+ * revealing the original descriptor.
+ *
+ * @private
+ */
+ disable: function() {
+ delete this.object[this.name];
+ },
+
+ /**
+ * Return a wrapped descriptor.
+ *
+ * `Value` properties are actually on the
+ * instance of objects. To wrap them we need
+ * to replace them with a getter which
+ * deletes itself on access, call into the v8
+ * interceptor, and then add themselves back.
+ *
+ * This won't be fast, but these are rarely
+ * accessed so it should be fine.
+ *
+ * @param {Object} descriptor
+ * @return {Object}
+ */
+ wrap: function(descriptor) {
+ debug('wrap value');
+ var name = this.name;
+ var self = this;
+
+ descriptor.get = function() {
+ debug('get value', name);
+ self.test(self.strictdom, this, arguments);
+ self.disable();
+ var result = this[name];
+ self.enable();
+ return result;
+ };
+
+ return descriptor;
+ },
+
+ test: Measure.prototype.test
+ });
+
+ function Style() {
+ Property.apply(this, arguments);
+ }
+
+ Style.prototype = extend(Property, {
+ wrap: function(descriptor) {
+ debug('wrap style');
+ var strictdom = this.strictdom;
+ var clone = Object.assign({}, descriptor);
+ clone.get = function() { return new StrictStyle(this, strictdom); };
+ return clone;
+ }
+ });
+
+ function ClassList() {
+ Property.apply(this, arguments);
+ }
+
+ ClassList.prototype = extend(Property, {
+ wrap: function(descriptor) {
+ debug('wrap style');
+ var strictdom = this.strictdom;
+ var clone = Object.assign({}, descriptor);
+ clone.get = function() { return new StrictClassList(this, strictdom); };
+ return clone;
+ }
+ });
+
+ function StrictStyle(el, strictdom) {
+ this.strictdom = strictdom;
+ this.el = el;
+ }
+
+ StrictStyle.prototype = {
+ _getter: getDescriptor(HTMLElement.prototype, 'style').get,
+ _get: function() {
+ return this._getter.call(this.el);
+ },
+
+ setProperty: function(key, value) {
+ var illegal = isAttached(this.el) && this.strictdom.not('mutate');
+ if (illegal) throw error(1, 'style.' + key);
+ return this._get()[key] = value;
+ },
+
+ removeProperty: function(key) {
+ var illegal = isAttached(this.el) && this.strictdom.not('mutate');
+ if (illegal) throw error(1, 'style.' + key);
+ return this._get().removeProperty(key);
+ }
+ };
+
+ // dynamically construct prototype
+ // from real element.style
+ (function() {
+ var styles = document.createElement('div').style;
+ var proto = {};
+
+ for (var key in styles) {
+ if (styles[key] === '') {
+ Object.defineProperty(StrictStyle.prototype, key, {
+ get: getter(key),
+ set: setter(key)
+ });
+ }
+ }
+
+ [
+ 'item',
+ 'getPropertyValue',
+ 'getPropertyCSSValue',
+ 'getPropertyPriority'
+ ].forEach(function(method) {
+ StrictStyle.prototype[method] = caller(method);
+ });
+
+ function getter(key) {
+ return function() {
+ return this._get()[key];
+ };
+ }
+
+ function setter(key) {
+ return function(value) {
+ var illegal = isAttached(this.el) && this.strictdom.not('mutate');
+ if (illegal) throw error(1, 'style.' + key);
+ return this.setProperty(key, value);
+ };
+ }
+
+ function caller(key) {
+ return function() {
+ var style = this._get();
+ return style[key].apply(style, arguments);
+ };
+ }
+
+ return proto;
+ })();
+
+ function StrictClassList(el, strictdom) {
+ this.strictdom = strictdom;
+ this.el = el;
+ }
+
+ StrictClassList.prototype = {
+ _getter: getDescriptor(Element.prototype, 'classList').get,
+ _get: function() { return this._getter.call(this.el); },
+
+ add: function(className) {
+ var illegal = isAttached(this.el) && this.strictdom.not('mutate');
+ if (illegal) throw error(1, 'class names');
+ this._get().add(className);
+ },
+
+ contains: function(className) {
+ return this._get().contains(className);
+ },
+
+ remove: function(className) {
+ var illegal = isAttached(this.el) && this.strictdom.not('mutate');
+ if (illegal) throw error(1, 'class names');
+ this._get().remove(className);
+ },
+
+ toggle: function() {
+ var illegal = isAttached(this.el) && this.strictdom.not('mutate');
+ if (illegal) throw error(1, 'class names');
+ var classList = this._get();
+ return classList.toggle.apply(classList, arguments);
+ }
+ };
+
+ /**
+ * Utils
+ */
+
+ function error(type) {
+ return new Error({
+ 1: 'Can only set ' + arguments[1] + ' during \'mutate\' phase',
+ 2: 'Can only get ' + arguments[1] + ' during \'measure\' phase',
+ 3: 'Can only call `.' + arguments[1] + '()` during \'mutate\' phase',
+ 4: 'Invalid phase: ' + arguments[1]
+ }[type]);
+ }
+
+ function getDescriptor(object, prop) {
+ return Object.getOwnPropertyDescriptor(object, prop);
+ }
+
+ function extend(parent, props) {
+ return Object.assign(Object.create(parent.prototype), props);
+ }
+
+ function isAttached(el) {
+ return el === window || document.contains(el);
+ }
+
+ /**
+ * Exports
+ */
+
+ // Only ever allow one `StrictDom` per document
+ var exports = window['strictdom'] = (window['strictdom'] || new StrictDom(window)); // jshint ignore:line
+
+ // CJS & AMD support
+ if (("function")[0] == 'f') !(__WEBPACK_AMD_DEFINE_RESULT__ = function() { return exports; }.call(exports, __webpack_require__, exports, module), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ else if ((typeof module)[0] == 'o') module.exports = exports;
+
+ })();
+
+
+/***/ },
+/* 2 */
+/***/ function(module, exports) {
+
+ module.exports = __WEBPACK_EXTERNAL_MODULE_2__;
+
+/***/ }
+/******/ ])
+});
+; \ No newline at end of file