'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var sourceMap = _interopDefault(require('source-map'));
var fs = _interopDefault(require('fs'));
var path = _interopDefault(require('path'));
var loaderUtils = _interopDefault(require('loader-utils'));

var SourceMapGenerator = sourceMap.SourceMapGenerator;

function makeIdentitySourceMap(content, resourcePath) {
  var map = new SourceMapGenerator();
  map.setSourceContent(resourcePath, content);

  content.split('\n').forEach(function (line, index) {
    map.addMapping({
      source: resourcePath,
      original: {
        line: index + 1,
        column: 0
      },
      generated: {
        line: index + 1,
        column: 0
      }
    });
  });

  return map.toJSON();
}

var makeIdentitySourceMap_1 = makeIdentitySourceMap;

var injectionStart = {
  '16.13': ['isCompatibleFamilyForHotReloading(child, element)', 'hotCompareElements(child.elementType, element.type, hotUpdateChild(child), child.type)'],
  '16.10': ['if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : child.elementType === element.type || ( // Keep this check inline so it only runs on the false path:\n        isCompatibleFamilyForHotReloading(child, element)))', 'if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : hotCompareElements(child.elementType, element.type, hotUpdateChild(child), child.type))'],
  '16.9': ['if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : child.elementType === element.type || (\n        // Keep this check inline so it only runs on the false path:\n        isCompatibleFamilyForHotReloading(child, element)))', 'if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : hotCompareElements(child.elementType, element.type, hotUpdateChild(child), child.type))'],
  '16.6': ['if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : child.elementType === element.type)', 'if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : hotCompareElements(child.elementType, element.type, hotUpdateChild(child), child.type))'],
  '16.6-compact': ['if(child.tag===Fragment?element.type===REACT_FRAGMENT_TYPE:child.elementType===element.type)', 'if(child.tag===Fragment?element.type===REACT_FRAGMENT_TYPE:hotCompareElements(child.elementType,element.type, hotUpdateChild(child), child.type))'],
  '16.4': ['if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : child.type === element.type) {', 'if (child.tag === Fragment ? element.type === REACT_FRAGMENT_TYPE : hotCompareElements(child.type, element.type, hotUpdateChild(child), child.type)) {'],
  '16.4-compact': ['if(child.tag===Fragment?element.type===REACT_FRAGMENT_TYPE:child.type===element.type)', 'if(child.tag===Fragment?element.type===REACT_FRAGMENT_TYPE:hotCompareElements(child.type,element.type, hotUpdateChild(child), child.type))']
};

var additional = {
  '16.13-update': ['isCompatibleFamilyForHotReloading(current, element)', 'hotCompareElements(current.elementType, element.type, hotUpdateChild(current), current.type)'],
  '16.10-update': ['current$$1.elementType === element.type || ( // Keep this check inline so it only runs on the false path:\n    isCompatibleFamilyForHotReloading(current$$1, element)))', '(hotCompareElements(current$$1.elementType, element.type, hotUpdateChild(current$$1), current$$1.type)))'],
  '16.9-update': ['current$$1.elementType === element.type || (\n    // Keep this check inline so it only runs on the false path:\n    isCompatibleFamilyForHotReloading(current$$1, element)))', '(hotCompareElements(current$$1.elementType, element.type, hotUpdateChild(current$$1), current$$1.type)))'],
  '16.6-update': ['if (current$$1 !== null && current$$1.elementType === element.type) {', 'if (current$$1 !== null && hotCompareElements(current$$1.elementType, element.type, hotUpdateChild(current$$1),current$$1.type)) {'],
  '16.6-update-compact': ['if(current$$1!==null&&current$$1.elementType===element.type)', 'if(current$$1!==null&&hotCompareElements(current$$1.elementType,element.type,hotUpdateChild(current$$1),current$$1.type))'],
  '16.4-update': ['if (current !== null && current.type === element.type) {', 'if (current !== null && hotCompareElements(current.type, element.type, hotUpdateChild(current),current.type)) {'],
  '16.4-update-compact': ['if (current!== null&&current.type===element.type)', 'if (current!== null&&hotCompareElements(current.type,element.type,hotUpdateChild(current)))'],

  '16.8-type': ['function createFiberFromTypeAndProps(type, // React$ElementType\nkey, pendingProps, owner, mode, expirationTime) {', 'function createFiberFromTypeAndProps(type, // React$ElementType\nkey, pendingProps, owner, mode, expirationTime) {type = hotResolveType(type);'],

  '16.8-type-compact': ['function createFiberFromTypeAndProps(type,// React$ElementType\nkey,pendingProps,owner,mode,expirationTime){', 'function createFiberFromTypeAndProps(type,// React$ElementType\nkey,pendingProps,owner,mode,expirationTime){type = hotResolveType(type);']
};

var reactHotLoaderCode = '\nvar hotUpdateChild = function (child) {\n  return function (newType) {\n    child.type = newType;\n    if (child.alternate) {\n      child.alternate.type = newType;\n    }\n  }\n};\nvar hotResolveType = function (type) {\n  return type;\n};\nvar hotCompareElements = function (oldType, newType) {\n  return oldType === newType\n};\nvar hotCleanupHooks = function () {\n  if (typeof resetHooks !== \'undefined\') {\n    resetHooks();\n  }\n}\n\nvar evalInReactContext = function (injection) {\n  return eval(injection);\n};\nvar hotCleanup = hotCleanupHooks;\nvar hotRenderWithHooks = function (current, render) {\n  hotCleanupHooks();\n\n  if (typeof nextCurrentHook !== \'undefined\' && typeof ReactCurrentDispatcher$1 !== \'undefined\') {\n    nextCurrentHook = current !== null ? current.memoizedState : null;\n    if (typeof firstCurrentHook !== \'undefined\') {\n      firstCurrentHook = nextCurrentHook;\n    }\n\n    ReactCurrentDispatcher$1.current = nextCurrentHook === null ? HooksDispatcherOnMountInDEV : HooksDispatcherOnUpdateInDEV;\n  }\n\n  var rendered = render();\n\n  hotCleanupHooks();\n\n  return rendered;\n}\nvar setHotElementComparator = function (newComparator) {\n  hotCompareElements = newComparator\n};\nvar setHotTypeResolver = function (newResolver) {\n  hotResolveType = newResolver;\n};\n';

var CJS = '\n' + reactHotLoaderCode + ';\n\nvar ReactDOM = {\n  evalInReactContext: evalInReactContext,\n  hotCleanup: hotCleanup,\n  hotRenderWithHooks: hotRenderWithHooks,\n  setHotElementComparator: setHotElementComparator,\n  setHotTypeResolver: setHotTypeResolver,\n';

var commonJSEnd = ['var ReactDOM = {', CJS];
var commonJSEndCompact = ['var ReactDOM={', CJS];

var ESM = '\n' + reactHotLoaderCode + ';\n\nexports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals;\n\nexports.evalInReactContext= evalInReactContext,\nexports.hotCleanup= hotCleanup,\nexports.hotRenderWithHooks= hotRenderWithHooks,\nexports.setHotElementComparator= setHotElementComparator,\nexports.setHotTypeResolver= setHotTypeResolver,\n';

var esmEnd = ['exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals;', ESM];

var injectionEnd = {
  '16.13': esmEnd,
  '16.10': commonJSEnd,
  '16.9': commonJSEnd,
  '16.6': commonJSEnd,
  '16.4': commonJSEnd,
  '16.6-compact': commonJSEndCompact,
  '16.4-compact': commonJSEndCompact
};

var sign = '/* 🔥 this is hot-loader/react-dom 🔥 */';

function additionalTransform(source) {
  for (var key in additional) {
    source = source.split(additional[key][0]).join(additional[key][1]);
  }
  return source;
}

function transform(source) {
  if (source.indexOf('reconcileSingleElement') < 0) {
    // early reject
    return source;
  }
  if (source.indexOf(sign) >= 0) {
    // already patched
    return source;
  }
  for (var key in injectionStart) {
    if (source.indexOf(injectionStart[key][0]) > 0 && source.indexOf(injectionEnd[key][0]) > 0) {
      var result = additionalTransform(source.replace(injectionStart[key][0], injectionStart[key][1]).replace(injectionEnd[key][0], injectionEnd[key][1]));
      return sign + '\n' + result + '\n' + sign;
    }
  }
  return source;
}

var patch = transform;

var SourceNode = sourceMap.SourceNode,
    SourceMapConsumer = sourceMap.SourceMapConsumer;





var tagCommonJSExportsSource = null;

function transform$1(source, map) {
  var callback = this.async();
  var resourcePath = this.resourcePath;
  if (source && source.types && source.types.IfStatement) {
    throw new Error('React Hot Loader: You are erroneously trying to use a Webpack loader ' + 'as a Babel plugin. Replace "react-hot-loader/webpack" with ' + '"react-hot-loader/babel" in the "plugins" section of your .babelrc file. ' + 'While we recommend the above, if you prefer not to use Babel, ' + 'you may remove "react-hot-loader/webpack" from the "plugins" section of ' + 'your .babelrc file altogether, and instead add "react-hot-loader/webpack" ' + 'to the "loaders" section of your Webpack configuration.');
  }

  if (this.cacheable) {
    this.cacheable();
  }

  var options = Object.assign({ withPatch: true }, loaderUtils.getOptions(this));
  if (options.withPatch) {
    source = patch(source);
  }

  if (source.indexOf('reactHotLoader.register') > 0 || options.noRegister) {
    return callback(null, source, map);
  }
  // This is a Webpack loader, but the user put it in the Babel config.

  // Read the helper once.
  if (!tagCommonJSExportsSource) {
    tagCommonJSExportsSource = fs.readFileSync(path.join(__dirname, 'webpackTagCommonJSExports.js'), 'utf8')
    // Babel inserts these.
    // Ideally we'd opt out for one file but this is simpler.
    .replace(/['"]use strict['"];/, '')
    // eslint comments don't need to end up in the output
    .replace(/\/\* (.*) \*\//, '').replace(/\/\/ eslint-disable-line .*\n/g, '\n').replace(/\/\* global.*\*\//, '').split(/\n\s*/).join(' ');
  }

  // Parameterize the helper with the current filename.
  var separator = '\n';
  var appendText = tagCommonJSExportsSource.replace(/__FILENAME__/g, JSON.stringify(resourcePath));

  if (this.sourceMap === false) {
    return callback(null, [source, appendText].join(separator));
  }

  if (!map) {
    map = makeIdentitySourceMap_1(source, resourcePath); // eslint-disable-line no-param-reassign
  }
  var sourceMapConsumer = new SourceMapConsumer(map);

  var onSourceMapReady = function onSourceMapReady(consumedMap) {
    var node = new SourceNode(null, null, null, [SourceNode.fromStringWithSourceMap(source, consumedMap), new SourceNode(null, null, resourcePath, appendText)]).join(separator);
    var result = node.toStringWithSourceMap();
    callback(null, result.code, result.map.toJSON() || undefined);
  };

  if (sourceMapConsumer.then) {
    sourceMapConsumer.then(onSourceMapReady);
  } else {
    onSourceMapReady(sourceMapConsumer);
  }
}

transform$1.patch = patch;

var webpack = transform$1;

exports.default = webpack;
