react-refresh
Advanced tools
Comparing version 0.0.0-a1dbb852c to 0.0.0-a703c3f7e
@@ -1,2 +0,2 @@ | ||
/** @license React v0.0.0-a1dbb852c | ||
/** @license React vundefined | ||
* react-refresh-babel.development.js | ||
@@ -12,4 +12,2 @@ * | ||
if (process.env.NODE_ENV !== "production") { | ||
@@ -19,8 +17,11 @@ (function() { | ||
var ReactFreshBabelPlugin = function (babel) { | ||
if (typeof babel.getEnv === 'function') { | ||
function ReactFreshBabelPlugin (babel) { | ||
var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
if (typeof babel.env === 'function') { | ||
// Only available in Babel 7. | ||
var env = babel.getEnv(); | ||
if (env !== 'development') { | ||
throw new Error('React Refresh Babel transform should only be enabled in development environment. ' + 'Instead, the environment is: "' + env + '".'); | ||
var env = babel.env(); | ||
if (env !== 'development' && !opts.skipEnvCheck) { | ||
throw new Error('React Refresh Babel transform should only be enabled in development environment. ' + 'Instead, the environment is: "' + env + '". If you want to override this check, pass {skipEnvCheck: true} as plugin options.'); | ||
} | ||
@@ -30,10 +31,13 @@ } | ||
var t = babel.types; | ||
var refreshReg = t.identifier(opts.refreshReg || '$RefreshReg$'); | ||
var refreshSig = t.identifier(opts.refreshSig || '$RefreshSig$'); | ||
var registrationsByProgramPath = new Map(); | ||
var registrationsByProgramPath = new Map(); | ||
function createRegistration(programPath, persistentID) { | ||
var handle = programPath.scope.generateUidIdentifier('c'); | ||
if (!registrationsByProgramPath.has(programPath)) { | ||
registrationsByProgramPath.set(programPath, []); | ||
} | ||
var registrations = registrationsByProgramPath.get(programPath); | ||
@@ -53,2 +57,3 @@ registrations.push({ | ||
var node = path.node; | ||
switch (node.type) { | ||
@@ -59,8 +64,10 @@ case 'Identifier': | ||
return false; | ||
} | ||
// export default hoc(Foo) | ||
} // export default hoc(Foo) | ||
// const X = hoc(Foo) | ||
callback(inferredName, node, null); | ||
return true; | ||
} | ||
case 'FunctionDeclaration': | ||
@@ -74,2 +81,3 @@ { | ||
} | ||
case 'ArrowFunctionExpression': | ||
@@ -79,8 +87,10 @@ { | ||
return false; | ||
} | ||
// let Foo = () => {} | ||
} // let Foo = () => {} | ||
// export default hoc1(hoc2(() => {})) | ||
callback(inferredName, node, path); | ||
return true; | ||
} | ||
case 'FunctionExpression': | ||
@@ -94,9 +104,13 @@ { | ||
} | ||
case 'CallExpression': | ||
{ | ||
var argsPath = path.get('arguments'); | ||
if (argsPath === undefined || argsPath.length === 0) { | ||
return false; | ||
} | ||
var calleePath = path.get('callee'); | ||
switch (calleePath.node.type) { | ||
@@ -110,10 +124,13 @@ case 'MemberExpression': | ||
var foundInside = findInnerComponents(innerName, firstArgPath, callback); | ||
if (!foundInside) { | ||
return false; | ||
} | ||
// const Foo = hoc1(hoc2(() => {})) | ||
} // const Foo = hoc1(hoc2(() => {})) | ||
// export default memo(React.forwardRef(function() {})) | ||
callback(inferredName, node, path); | ||
return true; | ||
} | ||
default: | ||
@@ -125,12 +142,17 @@ { | ||
} | ||
case 'VariableDeclarator': | ||
{ | ||
var init = node.init; | ||
if (init === null) { | ||
return false; | ||
} | ||
var name = node.id.name; | ||
if (!isComponentishName(name)) { | ||
return false; | ||
} | ||
switch (init.type) { | ||
@@ -141,2 +163,3 @@ case 'ArrowFunctionExpression': | ||
break; | ||
case 'CallExpression': | ||
@@ -148,2 +171,3 @@ { | ||
var calleeType = callee.type; | ||
if (calleeType === 'Import') { | ||
@@ -156,38 +180,45 @@ return false; | ||
return false; | ||
} | ||
// Neither require nor import. Might be a HOC. | ||
} // Neither require nor import. Might be a HOC. | ||
// Pass through. | ||
} else if (calleeType === 'MemberExpression') { | ||
// Could be something like React.forwardRef(...) | ||
// Pass through. | ||
} else { | ||
// More complicated call. | ||
return false; | ||
} | ||
break; | ||
} | ||
case 'TaggedTemplateExpression': | ||
// Maybe something like styled.div`...` | ||
break; | ||
default: | ||
return false; | ||
} | ||
var initPath = path.get('init'); | ||
var _foundInside = findInnerComponents(inferredName, initPath, callback); | ||
if (_foundInside) { | ||
return true; | ||
} | ||
// See if this identifier is used in JSX. Then it's a component. | ||
} // See if this identifier is used in JSX. Then it's a component. | ||
var binding = path.scope.getBinding(name); | ||
if (binding === undefined) { | ||
return; | ||
} | ||
var isLikelyUsedAsType = false; | ||
var referencePaths = binding.referencePaths; | ||
for (var i = 0; i < referencePaths.length; i++) { | ||
var ref = referencePaths[i]; | ||
if (ref.node.type !== 'JSXIdentifier' && ref.node.type !== 'Identifier') { | ||
if (ref.node && ref.node.type !== 'JSXIdentifier' && ref.node.type !== 'Identifier') { | ||
continue; | ||
} | ||
var refParent = ref.parent; | ||
if (refParent.type === 'JSXOpeningElement') { | ||
@@ -198,2 +229,3 @@ isLikelyUsedAsType = true; | ||
var fnName = void 0; | ||
switch (_callee.type) { | ||
@@ -203,2 +235,3 @@ case 'Identifier': | ||
break; | ||
case 'MemberExpression': | ||
@@ -208,2 +241,3 @@ fnName = _callee.property.name; | ||
} | ||
switch (fnName) { | ||
@@ -218,2 +252,3 @@ case 'createElement': | ||
} | ||
if (isLikelyUsedAsType) { | ||
@@ -227,2 +262,3 @@ // const X = ... + later <X /> | ||
} | ||
return false; | ||
@@ -249,7 +285,8 @@ } | ||
case 'React.useContext': | ||
case 'useImperativeMethods': | ||
case 'React.useImperativeMethods': | ||
case 'useImperativeHandle': | ||
case 'React.useImperativeHandle': | ||
case 'useDebugValue': | ||
case 'React.useDebugValue': | ||
return true; | ||
default: | ||
@@ -262,5 +299,7 @@ return false; | ||
var fnHookCalls = hookCalls.get(functionNode); | ||
if (fnHookCalls === undefined) { | ||
return null; | ||
} | ||
return { | ||
@@ -278,8 +317,8 @@ key: fnHookCalls.map(function (call) { | ||
var hasForceResetCommentByFile = new WeakMap(); | ||
var hasForceResetCommentByFile = new WeakMap(); // We let user do /* @refresh reset */ to reset state in the whole file. | ||
// We let user do /* @refresh reset */ to reset state in the whole file. | ||
function hasForceResetComment(path) { | ||
var file = path.hub.file; | ||
var hasForceReset = hasForceResetCommentByFile.get(file); | ||
if (hasForceReset !== undefined) { | ||
@@ -291,4 +330,6 @@ return hasForceReset; | ||
var comments = file.ast.comments; | ||
for (var i = 0; i < comments.length; i++) { | ||
var cmt = comments[i]; | ||
if (cmt.value.indexOf('@refresh reset') !== -1) { | ||
@@ -307,4 +348,2 @@ hasForceReset = true; | ||
customHooks = signature.customHooks; | ||
var forceReset = hasForceResetComment(scope.path); | ||
@@ -314,3 +353,4 @@ var customHooksInScope = []; | ||
// Check if a corresponding binding exists where we emit the signature. | ||
var bindingName = void 0; | ||
var bindingName; | ||
switch (callee.type) { | ||
@@ -321,3 +361,5 @@ case 'MemberExpression': | ||
} | ||
break; | ||
case 'Identifier': | ||
@@ -327,2 +369,3 @@ bindingName = callee.name; | ||
} | ||
if (scope.hasBinding(bindingName)) { | ||
@@ -336,13 +379,25 @@ customHooksInScope.push(callee); | ||
}); | ||
var finalKey = key; | ||
var args = [node, t.stringLiteral(key)]; | ||
if (typeof require === 'function' && !opts.emitFullSignatures) { | ||
// Prefer to hash when we can (e.g. outside of ASTExplorer). | ||
// This makes it deterministically compact, even if there's | ||
// e.g. a useState initializer with some code inside. | ||
// We also need it for www that has transforms like cx() | ||
// that don't understand if something is part of a string. | ||
finalKey = require('crypto').createHash('sha1').update(key).digest('base64'); | ||
} | ||
var args = [node, t.stringLiteral(finalKey)]; | ||
if (forceReset || customHooksInScope.length > 0) { | ||
args.push(t.booleanLiteral(forceReset)); | ||
} | ||
if (customHooksInScope.length > 0) { | ||
args.push( | ||
// TODO: We could use an arrow here to be more compact. | ||
args.push( // TODO: We could use an arrow here to be more compact. | ||
// However, don't do it until AMA can run them natively. | ||
t.functionExpression(null, [], t.blockStatement([t.returnStatement(t.arrayExpression(customHooksInScope))]))); | ||
} | ||
return args; | ||
@@ -354,3 +409,2 @@ } | ||
var seenForOutro = new WeakSet(); | ||
var hookCalls = new WeakMap(); | ||
@@ -360,8 +414,7 @@ var HookCallsVisitor = { | ||
var node = path.node; | ||
var callee = node.callee; | ||
// Note: this visitor MUST NOT mutate the tree in any way. | ||
var callee = node.callee; // Note: this visitor MUST NOT mutate the tree in any way. | ||
// It runs early in a separate traversal and should be very fast. | ||
var name = null; | ||
switch (callee.type) { | ||
@@ -371,2 +424,3 @@ case 'Identifier': | ||
break; | ||
case 'MemberExpression': | ||
@@ -376,24 +430,31 @@ name = callee.property.name; | ||
} | ||
if (name === null || !/^use[A-Z]/.test(name)) { | ||
return; | ||
} | ||
var fnScope = path.scope.getFunctionParent(); | ||
if (fnScope === null) { | ||
return; | ||
} | ||
} // This is a Hook call. Record it. | ||
// This is a Hook call. Record it. | ||
var fnNode = fnScope.block; | ||
if (!hookCalls.has(fnNode)) { | ||
hookCalls.set(fnNode, []); | ||
} | ||
var hookCallsForFn = hookCalls.get(fnNode); | ||
var key = ''; | ||
if (path.parent.type === 'VariableDeclarator') { | ||
// TODO: if there is no LHS, consider some other heuristic. | ||
key = path.parentPath.get('id').getSource(); | ||
} | ||
} // Some built-in Hooks reset on edits to arguments. | ||
// Some built-in Hooks reset on edits to arguments. | ||
var args = path.get('arguments'); | ||
if (name === 'useState' && args.length > 0) { | ||
@@ -414,3 +475,2 @@ // useState second argument is initial state. | ||
}; | ||
return { | ||
@@ -422,2 +482,3 @@ visitor: { | ||
var declPath = path.get('declaration'); | ||
if (decl.type !== 'CallExpression') { | ||
@@ -429,12 +490,11 @@ // For now, we only support possible HOC calls here. | ||
return; | ||
} | ||
} // Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
// Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
if (seenForRegistration.has(node)) { | ||
return; | ||
} | ||
seenForRegistration.add(node); | ||
// Don't mutate the tree above this point. | ||
seenForRegistration.add(node); // Don't mutate the tree above this point. | ||
// This code path handles nested cases like: | ||
@@ -446,2 +506,3 @@ // export default memo(() => {}) | ||
// export default memo(function Named() {}) | ||
var inferredName = '%default%'; | ||
@@ -457,2 +518,3 @@ var programPath = path.parentPath; | ||
} | ||
var handle = createRegistration(programPath, persistentID); | ||
@@ -462,8 +524,8 @@ targetPath.replaceWith(t.assignmentExpression('=', handle, targetExpr)); | ||
}, | ||
FunctionDeclaration: { | ||
enter: function (path) { | ||
var node = path.node; | ||
var programPath = void 0; | ||
var insertAfterPath = void 0; | ||
var programPath; | ||
var insertAfterPath; | ||
switch (path.parent.type) { | ||
@@ -474,2 +536,3 @@ case 'Program': | ||
break; | ||
case 'ExportNamedDeclaration': | ||
@@ -479,2 +542,3 @@ insertAfterPath = path.parentPath; | ||
break; | ||
case 'ExportDefaultDeclaration': | ||
@@ -484,6 +548,9 @@ insertAfterPath = path.parentPath; | ||
break; | ||
default: | ||
return; | ||
} | ||
var id = node.id; | ||
if (id === null) { | ||
@@ -493,17 +560,19 @@ // We don't currently handle anonymous default exports. | ||
} | ||
var inferredName = id.name; | ||
if (!isComponentishName(inferredName)) { | ||
return; | ||
} | ||
} // Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
// Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
if (seenForRegistration.has(node)) { | ||
return; | ||
} | ||
seenForRegistration.add(node); | ||
// Don't mutate the tree above this point. | ||
seenForRegistration.add(node); // Don't mutate the tree above this point. | ||
// export function Named() {} | ||
// function Named() {} | ||
findInnerComponents(inferredName, path, function (persistentID, targetExpr) { | ||
@@ -517,34 +586,34 @@ var handle = createRegistration(programPath, persistentID); | ||
var id = node.id; | ||
if (id === null) { | ||
return; | ||
} | ||
var signature = getHookCallsSignature(node); | ||
if (signature === null) { | ||
return; | ||
} | ||
} // Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
// Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
if (seenForSignature.has(node)) { | ||
return; | ||
} | ||
seenForSignature.add(node); | ||
// Don't mutate the tree above this point. | ||
seenForSignature.add(node); // Don't mutate the tree above this point. | ||
var sigCallID = path.scope.generateUidIdentifier('_s'); | ||
path.scope.parent.push({ | ||
id: sigCallID, | ||
init: t.callExpression(t.identifier('$RefreshSig$'), []) | ||
}); | ||
// The signature call is split in two parts. One part is called inside the function. | ||
init: t.callExpression(refreshSig, []) | ||
}); // The signature call is split in two parts. One part is called inside the function. | ||
// This is used to signal when first render happens. | ||
path.get('body').unshiftContainer('body', t.expressionStatement(t.callExpression(sigCallID, []))); | ||
// The second call is around the function itself. | ||
path.get('body').unshiftContainer('body', t.expressionStatement(t.callExpression(sigCallID, []))); // The second call is around the function itself. | ||
// This is used to associate a type with a signature. | ||
// Unlike with $RefreshReg$, this needs to work for nested | ||
// declarations too. So we need to search for a path where | ||
// we can insert a statement rather than hardcoding it. | ||
// we can insert a statement rather than hard coding it. | ||
var insertAfterPath = null; | ||
@@ -557,2 +626,3 @@ path.find(function (p) { | ||
}); | ||
if (insertAfterPath === null) { | ||
@@ -569,25 +639,27 @@ return; | ||
var signature = getHookCallsSignature(node); | ||
if (signature === null) { | ||
return; | ||
} | ||
} // Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
// Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
if (seenForSignature.has(node)) { | ||
return; | ||
} | ||
seenForSignature.add(node); | ||
// Don't mutate the tree above this point. | ||
seenForSignature.add(node); // Don't mutate the tree above this point. | ||
var sigCallID = path.scope.generateUidIdentifier('_s'); | ||
path.scope.parent.push({ | ||
id: sigCallID, | ||
init: t.callExpression(t.identifier('$RefreshSig$'), []) | ||
}); | ||
// The signature call is split in two parts. One part is called inside the function. | ||
init: t.callExpression(refreshSig, []) | ||
}); // The signature call is split in two parts. One part is called inside the function. | ||
// This is used to signal when first render happens. | ||
path.get('body').unshiftContainer('body', t.expressionStatement(t.callExpression(sigCallID, []))); | ||
// The second call is around the function itself. | ||
if (path.node.body.type !== 'BlockStatement') { | ||
path.node.body = t.blockStatement([t.returnStatement(path.node.body)]); | ||
} | ||
path.get('body').unshiftContainer('body', t.expressionStatement(t.callExpression(sigCallID, []))); // The second call is around the function itself. | ||
// This is used to associate a type with a signature. | ||
@@ -603,6 +675,6 @@ | ||
}); | ||
if (insertAfterPath === null) { | ||
return; | ||
} | ||
// Special case when a function would get an inferred name: | ||
} // Special case when a function would get an inferred name: | ||
// let Foo = () => {} | ||
@@ -612,8 +684,8 @@ // let Foo = function() {} | ||
// we don't mess up the inferred 'Foo' function name. | ||
insertAfterPath.insertAfter(t.expressionStatement(t.callExpression(sigCallID, createArgumentsForSignature(path.parent.id, signature, insertAfterPath.scope)))); | ||
// Result: let Foo = () => {}; __signature(Foo, ...); | ||
insertAfterPath.insertAfter(t.expressionStatement(t.callExpression(sigCallID, createArgumentsForSignature(path.parent.id, signature, insertAfterPath.scope)))); // Result: let Foo = () => {}; __signature(Foo, ...); | ||
} else { | ||
// let Foo = hoc(() => {}) | ||
path.replaceWith(t.callExpression(sigCallID, createArgumentsForSignature(node, signature, path.scope))); | ||
// Result: let Foo = hoc(__signature(() => {}, ...)) | ||
path.replaceWith(t.callExpression(sigCallID, createArgumentsForSignature(node, signature, path.scope))); // Result: let Foo = hoc(__signature(() => {}, ...)) | ||
} | ||
@@ -624,4 +696,5 @@ } | ||
var node = path.node; | ||
var programPath = void 0; | ||
var insertAfterPath = void 0; | ||
var programPath; | ||
var insertAfterPath; | ||
switch (path.parent.type) { | ||
@@ -632,2 +705,3 @@ case 'Program': | ||
break; | ||
case 'ExportNamedDeclaration': | ||
@@ -637,2 +711,3 @@ insertAfterPath = path.parentPath; | ||
break; | ||
case 'ExportDefaultDeclaration': | ||
@@ -642,18 +717,21 @@ insertAfterPath = path.parentPath; | ||
break; | ||
default: | ||
return; | ||
} | ||
} // Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
// Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
if (seenForRegistration.has(node)) { | ||
return; | ||
} | ||
seenForRegistration.add(node); | ||
// Don't mutate the tree above this point. | ||
seenForRegistration.add(node); // Don't mutate the tree above this point. | ||
var declPaths = path.get('declarations'); | ||
if (declPaths.length !== 1) { | ||
return; | ||
} | ||
var declPath = declPaths[0]; | ||
@@ -669,19 +747,21 @@ var inferredName = declPath.node.id.name; | ||
} | ||
var handle = createRegistration(programPath, persistentID); | ||
if ((targetExpr.type === 'ArrowFunctionExpression' || targetExpr.type === 'FunctionExpression') && targetPath.parent.type === 'VariableDeclarator') { | ||
// Special case when a function would get an inferred name: | ||
if (targetPath.parent.type === 'VariableDeclarator') { | ||
// Special case when a variable would get an inferred name: | ||
// let Foo = () => {} | ||
// let Foo = function() {} | ||
// let Foo = styled.div``; | ||
// We'll register it on next line so that | ||
// we don't mess up the inferred 'Foo' function name. | ||
insertAfterPath.insertAfter(t.expressionStatement(t.assignmentExpression('=', handle, declPath.node.id))); | ||
// Result: let Foo = () => {}; _c1 = Foo; | ||
// (eg: with @babel/plugin-transform-react-display-name or | ||
// babel-plugin-styled-components) | ||
insertAfterPath.insertAfter(t.expressionStatement(t.assignmentExpression('=', handle, declPath.node.id))); // Result: let Foo = () => {}; _c1 = Foo; | ||
} else { | ||
// let Foo = hoc(() => {}) | ||
targetPath.replaceWith(t.assignmentExpression('=', handle, targetExpr)); | ||
// Result: let Foo = _c1 = hoc(() => {}) | ||
targetPath.replaceWith(t.assignmentExpression('=', handle, targetExpr)); // Result: let Foo = hoc(_c1 = () => {}) | ||
} | ||
}); | ||
}, | ||
Program: { | ||
@@ -697,15 +777,17 @@ enter: function (path) { | ||
var registrations = registrationsByProgramPath.get(path); | ||
if (registrations === undefined) { | ||
return; | ||
} | ||
} // Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
// Make sure we're not mutating the same tree twice. | ||
// This can happen if another Babel plugin replaces parents. | ||
var node = path.node; | ||
if (seenForOutro.has(node)) { | ||
return; | ||
} | ||
seenForOutro.add(node); | ||
// Don't mutate the tree above this point. | ||
seenForOutro.add(node); // Don't mutate the tree above this point. | ||
registrationsByProgramPath.delete(path); | ||
@@ -717,4 +799,3 @@ var declarators = []; | ||
persistentID = _ref.persistentID; | ||
path.pushContainer('body', t.expressionStatement(t.callExpression(t.identifier('$RefreshReg$'), [handle, t.stringLiteral(persistentID)]))); | ||
path.pushContainer('body', t.expressionStatement(t.callExpression(refreshReg, [handle, t.stringLiteral(persistentID)]))); | ||
declarators.push(t.variableDeclarator(handle)); | ||
@@ -726,15 +807,6 @@ }); | ||
}; | ||
}; | ||
} | ||
var ReactFreshBabelPlugin$1 = Object.freeze({ | ||
default: ReactFreshBabelPlugin | ||
}); | ||
var ReactFreshBabelPlugin$2 = ( ReactFreshBabelPlugin$1 && ReactFreshBabelPlugin ) || ReactFreshBabelPlugin$1; | ||
// This is hacky but makes it work with both Rollup and Jest. | ||
var babel = ReactFreshBabelPlugin$2.default || ReactFreshBabelPlugin$2; | ||
module.exports = babel; | ||
module.exports = ReactFreshBabelPlugin; | ||
})(); | ||
} |
@@ -1,2 +0,2 @@ | ||
/** @license React v0.0.0-a1dbb852c | ||
/** @license React vundefined | ||
* react-refresh-babel.production.min.js | ||
@@ -9,15 +9,14 @@ * | ||
*/ | ||
'use strict';function v(q){function r(a,b){var d=a.scope.generateUidIdentifier("c");l.has(a)||l.set(a,[]);l.get(a).push({handle:d,persistentID:b});return d}function t(a){return"string"===typeof a&&"A"<=a[0]&&"Z">=a[0]}function m(a,b,d){var c=b.node;switch(c.type){case "Identifier":if(!t(c.name))break;d(a,c,null);return!0;case "FunctionDeclaration":return d(a,c.id,null),!0;case "ArrowFunctionExpression":if("ArrowFunctionExpression"===c.body.type)break;d(a,c,b);return!0;case "FunctionExpression":return d(a, | ||
c,b),!0;case "CallExpression":var f=b.get("arguments");if(void 0===f||0===f.length)break;var g=b.get("callee");switch(g.node.type){case "MemberExpression":case "Identifier":g=g.getSource();if(!m(a+"$"+g,f[0],d))return!1;d(a,c,b);return!0;default:return!1}case "VariableDeclarator":if(f=c.init,null!==f&&(g=c.id.name,t(g))){switch(f.type){case "ArrowFunctionExpression":case "FunctionExpression":break;case "CallExpression":c=f.callee;var e=c.type;if("Import"===e)return!1;if("Identifier"===e){if(0===c.name.indexOf("require")|| | ||
0===c.name.indexOf("import"))return!1}else if("MemberExpression"!==e)return!1;break;case "TaggedTemplateExpression":break;default:return!1}c=b.get("init");if(m(a,c,d))return!0;g=b.scope.getBinding(g);if(void 0===g)return;b=!1;g=g.referencePaths;for(e=0;e<g.length;e++){var h=g[e];if("JSXIdentifier"===h.node.type||"Identifier"===h.node.type){h=h.parent;if("JSXOpeningElement"===h.type)b=!0;else if("CallExpression"===h.type){h=h.callee;var k=void 0;switch(h.type){case "Identifier":k=h.name;break;case "MemberExpression":k= | ||
h.property.name}switch(k){case "createElement":case "jsx":case "jsxDEV":case "jsxs":b=!0}}if(b)return d(a,f,c),!0}}}}return!1}function w(a){a=n.get(a);return void 0===a?null:{key:a.map(function(a){return a.name+"{"+a.key+"}"}).join("\n"),customHooks:a.filter(function(a){a:switch(a.name){case "useState":case "React.useState":case "useReducer":case "React.useReducer":case "useEffect":case "React.useEffect":case "useLayoutEffect":case "React.useLayoutEffect":case "useMemo":case "React.useMemo":case "useCallback":case "React.useCallback":case "useRef":case "React.useRef":case "useContext":case "React.useContext":case "useImperativeMethods":case "React.useImperativeMethods":case "useDebugValue":case "React.useDebugValue":a= | ||
!0;break a;default:a=!1}return!a}).map(function(a){return e.cloneDeep(a.callee)})}}function C(a){a=a.hub.file;var b=x.get(a);if(void 0!==b)return b;b=!1;for(var d=a.ast.comments,c=0;c<d.length;c++)if(-1!==d[c].value.indexOf("@refresh reset")){b=!0;break}x.set(a,b);return b}function u(a,b,d){var c=b.key;b=b.customHooks;var f=C(d.path),g=[];b.forEach(function(a){var b=void 0;switch(a.type){case "MemberExpression":"Identifier"===a.object.type&&(b=a.object.name);break;case "Identifier":b=a.name}d.hasBinding(b)? | ||
g.push(a):f=!0});a=[a,e.stringLiteral(c)];(f||0<g.length)&&a.push(e.booleanLiteral(f));0<g.length&&a.push(e.functionExpression(null,[],e.blockStatement([e.returnStatement(e.arrayExpression(g))])));return a}if("function"===typeof q.getEnv){var y=q.getEnv();if("development"!==y)throw Error('React Refresh Babel transform should only be enabled in development environment. Instead, the environment is: "'+y+'".');}var e=q.types,l=new Map,x=new WeakMap,k=new WeakSet,p=new WeakSet,z=new WeakSet,n=new WeakMap, | ||
D={CallExpression:function(a){var b=a.node.callee,d=null;switch(b.type){case "Identifier":d=b.name;break;case "MemberExpression":d=b.property.name}if(null!==d&&/^use[A-Z]/.test(d)&&(b=a.scope.getFunctionParent(),null!==b)){b=b.block;n.has(b)||n.set(b,[]);b=n.get(b);var c="";"VariableDeclarator"===a.parent.type&&(c=a.parentPath.get("id").getSource());var f=a.get("arguments");"useState"===d&&0<f.length?c+="("+f[0].getSource()+")":"useReducer"===d&&1<f.length&&(c+="("+f[1].getSource()+")");b.push({callee:a.node.callee, | ||
name:d,key:c})}}};return{visitor:{ExportDefaultDeclaration:function(a){var b=a.node,d=b.declaration,c=a.get("declaration");if("CallExpression"===d.type&&!k.has(b)){k.add(b);var f=a.parentPath;m("%default%",c,function(a,b,c){null!==c&&(a=r(f,a),c.replaceWith(e.assignmentExpression("=",a,b)))})}},FunctionDeclaration:{enter:function(a){var b=a.node,d=void 0,c=void 0;switch(a.parent.type){case "Program":c=a;d=a.parentPath;break;case "ExportNamedDeclaration":c=a.parentPath;d=c.parentPath;break;case "ExportDefaultDeclaration":c= | ||
a.parentPath;d=c.parentPath;break;default:return}var f=b.id;null!==f&&(f=f.name,t(f)&&!k.has(b)&&(k.add(b),m(f,a,function(a,b){a=r(d,a);c.insertAfter(e.expressionStatement(e.assignmentExpression("=",a,b)))})))},exit:function(a){var b=a.node,d=b.id;if(null!==d){var c=w(b);if(null!==c&&!p.has(b)){p.add(b);b=a.scope.generateUidIdentifier("_s");a.scope.parent.push({id:b,init:e.callExpression(e.identifier("$RefreshSig$"),[])});a.get("body").unshiftContainer("body",e.expressionStatement(e.callExpression(b, | ||
[])));var f=null;a.find(function(a){if(a.parentPath.isBlock())return f=a,!0});null!==f&&f.insertAfter(e.expressionStatement(e.callExpression(b,u(d,c,f.scope))))}}}},"ArrowFunctionExpression|FunctionExpression":{exit:function(a){var b=a.node,d=w(b);if(null!==d&&!p.has(b)){p.add(b);var c=a.scope.generateUidIdentifier("_s");a.scope.parent.push({id:c,init:e.callExpression(e.identifier("$RefreshSig$"),[])});a.get("body").unshiftContainer("body",e.expressionStatement(e.callExpression(c,[])));if("VariableDeclarator"=== | ||
a.parent.type){var f=null;a.find(function(a){if(a.parentPath.isBlock())return f=a,!0});null!==f&&f.insertAfter(e.expressionStatement(e.callExpression(c,u(a.parent.id,d,f.scope))))}else a.replaceWith(e.callExpression(c,u(b,d,a.scope)))}}},VariableDeclaration:function(a){var b=a.node,d=void 0,c=void 0;switch(a.parent.type){case "Program":c=a;d=a.parentPath;break;case "ExportNamedDeclaration":c=a.parentPath;d=c.parentPath;break;case "ExportDefaultDeclaration":c=a.parentPath;d=c.parentPath;break;default:return}if(!k.has(b)&& | ||
(k.add(b),a=a.get("declarations"),1===a.length)){var f=a[0];m(f.node.id.name,f,function(a,b,h){null!==h&&(a=r(d,a),"ArrowFunctionExpression"!==b.type&&"FunctionExpression"!==b.type||"VariableDeclarator"!==h.parent.type?h.replaceWith(e.assignmentExpression("=",a,b)):c.insertAfter(e.expressionStatement(e.assignmentExpression("=",a,f.node.id))))})}},Program:{enter:function(a){a.traverse(D)},exit:function(a){var b=l.get(a);if(void 0!==b){var d=a.node;if(!z.has(d)){z.add(d);l.delete(a);var c=[];a.pushContainer("body", | ||
e.variableDeclaration("var",c));b.forEach(function(b){var d=b.handle;b=b.persistentID;a.pushContainer("body",e.expressionStatement(e.callExpression(e.identifier("$RefreshReg$"),[d,e.stringLiteral(b)])));c.push(e.variableDeclarator(d))})}}}}}}}var A={default:v},B=A&&v||A;module.exports=B.default||B; | ||
'use strict';module.exports=function(r){function t(a,b){var d=a.scope.generateUidIdentifier("c");l.has(a)||l.set(a,[]);l.get(a).push({handle:d,persistentID:b});return d}function u(a){return"string"===typeof a&&"A"<=a[0]&&"Z">=a[0]}function m(a,b,d){var c=b.node;switch(c.type){case "Identifier":if(!u(c.name))break;d(a,c,null);return!0;case "FunctionDeclaration":return d(a,c.id,null),!0;case "ArrowFunctionExpression":if("ArrowFunctionExpression"===c.body.type)break;d(a,c,b);return!0;case "FunctionExpression":return d(a, | ||
c,b),!0;case "CallExpression":var f=b.get("arguments");if(void 0===f||0===f.length)break;var g=b.get("callee");switch(g.node.type){case "MemberExpression":case "Identifier":g=g.getSource();if(!m(a+"$"+g,f[0],d))return!1;d(a,c,b);return!0;default:return!1}case "VariableDeclarator":if(f=c.init,null!==f&&(g=c.id.name,u(g))){switch(f.type){case "ArrowFunctionExpression":case "FunctionExpression":break;case "CallExpression":c=f.callee;var e=c.type;if("Import"===e||"Identifier"===e&&(0===c.name.indexOf("require")|| | ||
0===c.name.indexOf("import")))return!1;break;case "TaggedTemplateExpression":break;default:return!1}c=b.get("init");if(m(a,c,d))return!0;g=b.scope.getBinding(g);if(void 0===g)return;b=!1;g=g.referencePaths;for(e=0;e<g.length;e++){var h=g[e];if(!h.node||"JSXIdentifier"===h.node.type||"Identifier"===h.node.type){h=h.parent;if("JSXOpeningElement"===h.type)b=!0;else if("CallExpression"===h.type){h=h.callee;var k=void 0;switch(h.type){case "Identifier":k=h.name;break;case "MemberExpression":k=h.property.name}switch(k){case "createElement":case "jsx":case "jsxDEV":case "jsxs":b= | ||
!0}}if(b)return d(a,f,c),!0}}}}return!1}function w(a){a=n.get(a);return void 0===a?null:{key:a.map(function(a){return a.name+"{"+a.key+"}"}).join("\n"),customHooks:a.filter(function(a){a:switch(a.name){case "useState":case "React.useState":case "useReducer":case "React.useReducer":case "useEffect":case "React.useEffect":case "useLayoutEffect":case "React.useLayoutEffect":case "useMemo":case "React.useMemo":case "useCallback":case "React.useCallback":case "useRef":case "React.useRef":case "useContext":case "React.useContext":case "useImperativeHandle":case "React.useImperativeHandle":case "useDebugValue":case "React.useDebugValue":a= | ||
!0;break a;default:a=!1}return!a}).map(function(a){return e.cloneDeep(a.callee)})}}function B(a){a=a.hub.file;var b=x.get(a);if(void 0!==b)return b;b=!1;for(var d=a.ast.comments,c=0;c<d.length;c++)if(-1!==d[c].value.indexOf("@refresh reset")){b=!0;break}x.set(a,b);return b}function v(a,b,d){var c=b.key;b=b.customHooks;var f=B(d.path),g=[];b.forEach(function(a){switch(a.type){case "MemberExpression":if("Identifier"===a.object.type)var b=a.object.name;break;case "Identifier":b=a.name}d.hasBinding(b)? | ||
g.push(a):f=!0});b=c;"function"!==typeof require||p.emitFullSignatures||(b=require("crypto").createHash("sha1").update(c).digest("base64"));a=[a,e.stringLiteral(b)];(f||0<g.length)&&a.push(e.booleanLiteral(f));0<g.length&&a.push(e.functionExpression(null,[],e.blockStatement([e.returnStatement(e.arrayExpression(g))])));return a}var p=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};if("function"===typeof r.env){var y=r.env();if("development"!==y&&!p.skipEnvCheck)throw Error('React Refresh Babel transform should only be enabled in development environment. Instead, the environment is: "'+ | ||
y+'". If you want to override this check, pass {skipEnvCheck: true} as plugin options.');}var e=r.types,C=e.identifier(p.refreshReg||"$RefreshReg$"),z=e.identifier(p.refreshSig||"$RefreshSig$"),l=new Map,x=new WeakMap,k=new WeakSet,q=new WeakSet,A=new WeakSet,n=new WeakMap,D={CallExpression:function(a){var b=a.node.callee,d=null;switch(b.type){case "Identifier":d=b.name;break;case "MemberExpression":d=b.property.name}if(null!==d&&/^use[A-Z]/.test(d)&&(b=a.scope.getFunctionParent(),null!==b)){b=b.block; | ||
n.has(b)||n.set(b,[]);b=n.get(b);var c="";"VariableDeclarator"===a.parent.type&&(c=a.parentPath.get("id").getSource());var f=a.get("arguments");"useState"===d&&0<f.length?c+="("+f[0].getSource()+")":"useReducer"===d&&1<f.length&&(c+="("+f[1].getSource()+")");b.push({callee:a.node.callee,name:d,key:c})}}};return{visitor:{ExportDefaultDeclaration:function(a){var b=a.node,d=b.declaration,c=a.get("declaration");if("CallExpression"===d.type&&!k.has(b)){k.add(b);var f=a.parentPath;m("%default%",c,function(a, | ||
b,c){null!==c&&(a=t(f,a),c.replaceWith(e.assignmentExpression("=",a,b)))})}},FunctionDeclaration:{enter:function(a){var b=a.node;switch(a.parent.type){case "Program":var d=a;var c=a.parentPath;break;case "ExportNamedDeclaration":d=a.parentPath;c=d.parentPath;break;case "ExportDefaultDeclaration":d=a.parentPath;c=d.parentPath;break;default:return}var f=b.id;null!==f&&(f=f.name,u(f)&&!k.has(b)&&(k.add(b),m(f,a,function(a,b){a=t(c,a);d.insertAfter(e.expressionStatement(e.assignmentExpression("=",a,b)))})))}, | ||
exit:function(a){var b=a.node,d=b.id;if(null!==d){var c=w(b);if(null!==c&&!q.has(b)){q.add(b);b=a.scope.generateUidIdentifier("_s");a.scope.parent.push({id:b,init:e.callExpression(z,[])});a.get("body").unshiftContainer("body",e.expressionStatement(e.callExpression(b,[])));var f=null;a.find(function(a){if(a.parentPath.isBlock())return f=a,!0});null!==f&&f.insertAfter(e.expressionStatement(e.callExpression(b,v(d,c,f.scope))))}}}},"ArrowFunctionExpression|FunctionExpression":{exit:function(a){var b= | ||
a.node,d=w(b);if(null!==d&&!q.has(b)){q.add(b);var c=a.scope.generateUidIdentifier("_s");a.scope.parent.push({id:c,init:e.callExpression(z,[])});"BlockStatement"!==a.node.body.type&&(a.node.body=e.blockStatement([e.returnStatement(a.node.body)]));a.get("body").unshiftContainer("body",e.expressionStatement(e.callExpression(c,[])));if("VariableDeclarator"===a.parent.type){var f=null;a.find(function(a){if(a.parentPath.isBlock())return f=a,!0});null!==f&&f.insertAfter(e.expressionStatement(e.callExpression(c, | ||
v(a.parent.id,d,f.scope))))}else a.replaceWith(e.callExpression(c,v(b,d,a.scope)))}}},VariableDeclaration:function(a){var b=a.node;switch(a.parent.type){case "Program":var d=a;var c=a.parentPath;break;case "ExportNamedDeclaration":d=a.parentPath;c=d.parentPath;break;case "ExportDefaultDeclaration":d=a.parentPath;c=d.parentPath;break;default:return}if(!k.has(b)&&(k.add(b),a=a.get("declarations"),1===a.length)){var f=a[0];m(f.node.id.name,f,function(a,b,h){null!==h&&(a=t(c,a),"VariableDeclarator"=== | ||
h.parent.type?d.insertAfter(e.expressionStatement(e.assignmentExpression("=",a,f.node.id))):h.replaceWith(e.assignmentExpression("=",a,b)))})}},Program:{enter:function(a){a.traverse(D)},exit:function(a){var b=l.get(a);if(void 0!==b){var d=a.node;if(!A.has(d)){A.add(d);l.delete(a);var c=[];a.pushContainer("body",e.variableDeclaration("var",c));b.forEach(function(b){var d=b.handle;a.pushContainer("body",e.expressionStatement(e.callExpression(C,[d,e.stringLiteral(b.persistentID)])));c.push(e.variableDeclarator(d))})}}}}}}}; |
@@ -1,2 +0,2 @@ | ||
/** @license React v0.0.0-a1dbb852c | ||
/** @license React vundefined | ||
* react-refresh-runtime.development.js | ||
@@ -12,4 +12,2 @@ * | ||
if (process.env.NODE_ENV !== "production") { | ||
@@ -19,101 +17,78 @@ (function() { | ||
// ATTENTION | ||
// When adding new symbols to this file, | ||
// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' | ||
// The Symbol used to tag the ReactElement-like types. If there is no native Symbol | ||
// nor polyfill, then a plain number is used for performance. | ||
var hasSymbol = typeof Symbol === 'function' && Symbol.for; | ||
var REACT_ELEMENT_TYPE = 0xeac7; | ||
var REACT_PORTAL_TYPE = 0xeaca; | ||
var REACT_FRAGMENT_TYPE = 0xeacb; | ||
var REACT_STRICT_MODE_TYPE = 0xeacc; | ||
var REACT_PROFILER_TYPE = 0xead2; | ||
var REACT_PROVIDER_TYPE = 0xeacd; | ||
var REACT_CONTEXT_TYPE = 0xeace; | ||
var REACT_FORWARD_REF_TYPE = 0xead0; | ||
var REACT_SUSPENSE_TYPE = 0xead1; | ||
var REACT_SUSPENSE_LIST_TYPE = 0xead8; | ||
var REACT_MEMO_TYPE = 0xead3; | ||
var REACT_LAZY_TYPE = 0xead4; | ||
var REACT_FUNDAMENTAL_TYPE = 0xead5; | ||
var REACT_SCOPE_TYPE = 0xead7; | ||
var REACT_OPAQUE_ID_TYPE = 0xeae0; | ||
var REACT_DEBUG_TRACING_MODE_TYPE = 0xeae1; | ||
var REACT_OFFSCREEN_TYPE = 0xeae2; | ||
var REACT_LEGACY_HIDDEN_TYPE = 0xeae3; | ||
var REACT_CACHE_TYPE = 0xeae4; | ||
// TODO: We don't use AsyncMode or ConcurrentMode anymore. They were temporary | ||
// (unstable) APIs that have been removed. Can we remove the symbols? | ||
var REACT_FORWARD_REF_TYPE = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0; | ||
var REACT_MEMO_TYPE = hasSymbol ? Symbol.for('react.memo') : 0xead3; | ||
/** | ||
* Similar to invariant but only logs a warning if the condition is not met. | ||
* This can be used to log issues in development environments in critical | ||
* paths. Removing the logging code for production environments will keep the | ||
* same logic and follow the same code paths. | ||
*/ | ||
var warningWithoutStack = function () {}; | ||
{ | ||
warningWithoutStack = function (condition, format) { | ||
for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) { | ||
args[_key - 2] = arguments[_key]; | ||
} | ||
if (format === undefined) { | ||
throw new Error('`warningWithoutStack(condition, format, ...args)` requires a warning ' + 'message argument'); | ||
} | ||
if (args.length > 8) { | ||
// Check before the condition to catch violations early. | ||
throw new Error('warningWithoutStack() currently supports at most 8 arguments.'); | ||
} | ||
if (condition) { | ||
return; | ||
} | ||
if (typeof console !== 'undefined') { | ||
var argsWithFormat = args.map(function (item) { | ||
return '' + item; | ||
}); | ||
argsWithFormat.unshift('Warning: ' + format); | ||
// We intentionally don't use spread (or .apply) directly because it | ||
// breaks IE9: https://github.com/facebook/react/issues/13610 | ||
Function.prototype.apply.call(console.error, console, argsWithFormat); | ||
} | ||
try { | ||
// --- Welcome to debugging React --- | ||
// This error was thrown as a convenience so that you can use this stack | ||
// to find the callsite that caused this warning to fire. | ||
var argIndex = 0; | ||
var message = 'Warning: ' + format.replace(/%s/g, function () { | ||
return args[argIndex++]; | ||
}); | ||
throw new Error(message); | ||
} catch (x) {} | ||
}; | ||
if (typeof Symbol === 'function' && Symbol.for) { | ||
var symbolFor = Symbol.for; | ||
REACT_ELEMENT_TYPE = symbolFor('react.element'); | ||
REACT_PORTAL_TYPE = symbolFor('react.portal'); | ||
REACT_FRAGMENT_TYPE = symbolFor('react.fragment'); | ||
REACT_STRICT_MODE_TYPE = symbolFor('react.strict_mode'); | ||
REACT_PROFILER_TYPE = symbolFor('react.profiler'); | ||
REACT_PROVIDER_TYPE = symbolFor('react.provider'); | ||
REACT_CONTEXT_TYPE = symbolFor('react.context'); | ||
REACT_FORWARD_REF_TYPE = symbolFor('react.forward_ref'); | ||
REACT_SUSPENSE_TYPE = symbolFor('react.suspense'); | ||
REACT_SUSPENSE_LIST_TYPE = symbolFor('react.suspense_list'); | ||
REACT_MEMO_TYPE = symbolFor('react.memo'); | ||
REACT_LAZY_TYPE = symbolFor('react.lazy'); | ||
REACT_FUNDAMENTAL_TYPE = symbolFor('react.fundamental'); | ||
REACT_SCOPE_TYPE = symbolFor('react.scope'); | ||
REACT_OPAQUE_ID_TYPE = symbolFor('react.opaque.id'); | ||
REACT_DEBUG_TRACING_MODE_TYPE = symbolFor('react.debug_trace_mode'); | ||
REACT_OFFSCREEN_TYPE = symbolFor('react.offscreen'); | ||
REACT_LEGACY_HIDDEN_TYPE = symbolFor('react.legacy_hidden'); | ||
REACT_CACHE_TYPE = symbolFor('react.cache'); | ||
} | ||
var warningWithoutStack$1 = warningWithoutStack; | ||
var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; // We never remove these associations. | ||
// It's OK to reference families, but use WeakMap/Set for types. | ||
// In old environments, we'll leak previous types after every edit. | ||
var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; | ||
// We never remove these associations. | ||
// It's OK to reference families, but use WeakMap/Set for types. | ||
var allFamiliesByID = new Map(); | ||
var allFamiliesByType = new PossiblyWeakMap(); | ||
var allSignaturesByType = new PossiblyWeakMap(); | ||
// This WeakMap is read by React, so we only put families | ||
var allSignaturesByType = new PossiblyWeakMap(); // This WeakMap is read by React, so we only put families | ||
// that have actually been edited here. This keeps checks fast. | ||
// $FlowIssue | ||
var updatedFamiliesByType = new PossiblyWeakMap(); | ||
// This is cleared on every performReactRefresh() call. | ||
var updatedFamiliesByType = new PossiblyWeakMap(); // This is cleared on every performReactRefresh() call. | ||
// It is an array of [Family, NextType] tuples. | ||
var pendingUpdates = []; | ||
// This is injected by the renderer via DevTools global hook. | ||
var setRefreshHandler = null; | ||
var scheduleRefresh = null; | ||
var scheduleRoot = null; | ||
var findHostInstancesForRefresh = null; | ||
var pendingUpdates = []; // This is injected by the renderer via DevTools global hook. | ||
// We keep track of mounted roots so we can schedule updates. | ||
var mountedRoots = new Set(); | ||
// If a root captures an error, we add its element to this Map so we can retry on edit. | ||
var failedRoots = new Map(); | ||
var didSomeRootFailOnMount = false; | ||
var helpersByRendererID = new Map(); | ||
var helpersByRoot = new Map(); // We keep track of mounted roots so we can schedule updates. | ||
var mountedRoots = new Set(); // If a root captures an error, we remember it so we can retry on edit. | ||
var failedRoots = new Set(); // In environments that support WeakMap, we also remember the last element for every root. | ||
// It needs to be weak because we do this even for roots that failed to mount. | ||
// If there is no WeakMap, we won't attempt to do retrying. | ||
// $FlowIssue | ||
var rootElements = // $FlowIssue | ||
typeof WeakMap === 'function' ? new WeakMap() : null; | ||
var isPerformingRefresh = false; | ||
function computeFullKey(signature) { | ||
@@ -125,3 +100,4 @@ if (signature.fullKey !== null) { | ||
var fullKey = signature.ownKey; | ||
var hooks = void 0; | ||
var hooks; | ||
try { | ||
@@ -140,2 +116,3 @@ hooks = signature.getCustomHooks(); | ||
var hook = hooks[i]; | ||
if (typeof hook !== 'function') { | ||
@@ -147,3 +124,5 @@ // Something's wrong. Assume we need to remount. | ||
} | ||
var nestedHookSignature = allSignaturesByType.get(hook); | ||
if (nestedHookSignature === undefined) { | ||
@@ -154,6 +133,9 @@ // No signature means Hook wasn't in the source code, e.g. in a library. | ||
} | ||
var nestedHookKey = computeFullKey(nestedHookSignature); | ||
if (nestedHookSignature.forceReset) { | ||
signature.forceReset = true; | ||
} | ||
fullKey += '\n---\n' + nestedHookKey; | ||
@@ -173,8 +155,11 @@ } | ||
} | ||
if (prevSignature === undefined || nextSignature === undefined) { | ||
return false; | ||
} | ||
if (computeFullKey(prevSignature) !== computeFullKey(nextSignature)) { | ||
return false; | ||
} | ||
if (nextSignature.forceReset) { | ||
@@ -195,5 +180,7 @@ return false; | ||
} | ||
if (haveEqualSignatures(prevType, nextType)) { | ||
return true; | ||
} | ||
return false; | ||
@@ -205,13 +192,46 @@ } | ||
return updatedFamiliesByType.get(type); | ||
} // If we didn't care about IE11, we could use new Map/Set(iterable). | ||
function cloneMap(map) { | ||
var clone = new Map(); | ||
map.forEach(function (value, key) { | ||
clone.set(key, value); | ||
}); | ||
return clone; | ||
} | ||
function cloneSet(set) { | ||
var clone = new Set(); | ||
set.forEach(function (value) { | ||
clone.add(value); | ||
}); | ||
return clone; | ||
} // This is a safety mechanism to protect against rogue getters and Proxies. | ||
function getProperty(object, property) { | ||
try { | ||
return object[property]; | ||
} catch (err) { | ||
// Intentionally ignore. | ||
return undefined; | ||
} | ||
} | ||
function performReactRefresh() { | ||
{ | ||
if (pendingUpdates.length === 0) { | ||
return null; | ||
} | ||
if (pendingUpdates.length === 0) { | ||
return null; | ||
} | ||
if (isPerformingRefresh) { | ||
return null; | ||
} | ||
isPerformingRefresh = true; | ||
try { | ||
var staleFamilies = new Set(); | ||
var updatedFamilies = new Set(); | ||
var updates = pendingUpdates; | ||
@@ -222,3 +242,2 @@ pendingUpdates = []; | ||
nextType = _ref[1]; | ||
// Now that we got a real edit, we can create associations | ||
@@ -229,5 +248,4 @@ // that will be read by the React reconciler. | ||
updatedFamiliesByType.set(nextType, family); | ||
family.current = nextType; | ||
family.current = nextType; // Determine whether this should be a re-render or a re-mount. | ||
// Determine whether this should be a re-render or a re-mount. | ||
if (canPreserveStateBetween(prevType, nextType)) { | ||
@@ -238,35 +256,46 @@ updatedFamilies.add(family); | ||
} | ||
}); | ||
}); // TODO: rename these fields to something more meaningful. | ||
// TODO: rename these fields to something more meaningful. | ||
var update = { | ||
updatedFamilies: updatedFamilies, // Families that will re-render preserving state | ||
updatedFamilies: updatedFamilies, | ||
// Families that will re-render preserving state | ||
staleFamilies: staleFamilies // Families that will be remounted | ||
}; | ||
helpersByRendererID.forEach(function (helpers) { | ||
// Even if there are no roots, set the handler on first update. | ||
// This ensures that if *new* roots are mounted, they'll use the resolve handler. | ||
helpers.setRefreshHandler(resolveFamily); | ||
}); | ||
var didError = false; | ||
var firstError = null; // We snapshot maps and sets that are mutated during commits. | ||
// If we don't do this, there is a risk they will be mutated while | ||
// we iterate over them. For example, trying to recover a failed root | ||
// may cause another root to be added to the failed list -- an infinite loop. | ||
if (typeof setRefreshHandler !== 'function') { | ||
warningWithoutStack$1(false, 'Could not find the setRefreshHandler() implementation. ' + 'This likely means that injectIntoGlobalHook() was either ' + 'called before the global DevTools hook was set up, or after the ' + 'renderer has already initialized. Please file an issue with a reproducing case.'); | ||
return null; | ||
} | ||
var failedRootsSnapshot = cloneSet(failedRoots); | ||
var mountedRootsSnapshot = cloneSet(mountedRoots); | ||
var helpersByRootSnapshot = cloneMap(helpersByRoot); | ||
failedRootsSnapshot.forEach(function (root) { | ||
var helpers = helpersByRootSnapshot.get(root); | ||
if (typeof scheduleRefresh !== 'function') { | ||
warningWithoutStack$1(false, 'Could not find the scheduleRefresh() implementation. ' + 'This likely means that injectIntoGlobalHook() was either ' + 'called before the global DevTools hook was set up, or after the ' + 'renderer has already initialized. Please file an issue with a reproducing case.'); | ||
return null; | ||
} | ||
if (typeof scheduleRoot !== 'function') { | ||
warningWithoutStack$1(false, 'Could not find the scheduleRoot() implementation. ' + 'This likely means that injectIntoGlobalHook() was either ' + 'called before the global DevTools hook was set up, or after the ' + 'renderer has already initialized. Please file an issue with a reproducing case.'); | ||
return null; | ||
} | ||
var scheduleRefreshForRoot = scheduleRefresh; | ||
var scheduleRenderForRoot = scheduleRoot; | ||
if (helpers === undefined) { | ||
throw new Error('Could not find helpers for a root. This is a bug in React Refresh.'); | ||
} | ||
// Even if there are no roots, set the handler on first update. | ||
// This ensures that if *new* roots are mounted, they'll use the resolve handler. | ||
setRefreshHandler(resolveFamily); | ||
if (!failedRoots.has(root)) {// No longer failed. | ||
} | ||
var didError = false; | ||
var firstError = null; | ||
failedRoots.forEach(function (element, root) { | ||
if (rootElements === null) { | ||
return; | ||
} | ||
if (!rootElements.has(root)) { | ||
return; | ||
} | ||
var element = rootElements.get(root); | ||
try { | ||
scheduleRenderForRoot(root, element); | ||
helpers.scheduleRoot(root, element); | ||
} catch (err) { | ||
@@ -276,9 +305,18 @@ if (!didError) { | ||
firstError = err; | ||
} | ||
// Keep trying other roots. | ||
} // Keep trying other roots. | ||
} | ||
}); | ||
mountedRoots.forEach(function (root) { | ||
mountedRootsSnapshot.forEach(function (root) { | ||
var helpers = helpersByRootSnapshot.get(root); | ||
if (helpers === undefined) { | ||
throw new Error('Could not find helpers for a root. This is a bug in React Refresh.'); | ||
} | ||
if (!mountedRoots.has(root)) {// No longer mounted. | ||
} | ||
try { | ||
scheduleRefreshForRoot(root, update); | ||
helpers.scheduleRefresh(root, update); | ||
} catch (err) { | ||
@@ -288,13 +326,16 @@ if (!didError) { | ||
firstError = err; | ||
} | ||
// Keep trying other roots. | ||
} // Keep trying other roots. | ||
} | ||
}); | ||
if (didError) { | ||
throw firstError; | ||
} | ||
return update; | ||
} finally { | ||
isPerformingRefresh = false; | ||
} | ||
} | ||
function register(type, id) { | ||
@@ -305,18 +346,23 @@ { | ||
} | ||
if (typeof type !== 'function' && typeof type !== 'object') { | ||
return; | ||
} | ||
// This can happen in an edge case, e.g. if we register | ||
} // This can happen in an edge case, e.g. if we register | ||
// return value of a HOC but it returns a cached component. | ||
// Ignore anything but the first registration for each type. | ||
if (allFamiliesByType.has(type)) { | ||
return; | ||
} | ||
// Create family or remember to update it. | ||
} // Create family or remember to update it. | ||
// None of this bookkeeping affects reconciliation | ||
// until the first performReactRefresh() call above. | ||
var family = allFamiliesByID.get(id); | ||
if (family === undefined) { | ||
family = { current: type }; | ||
family = { | ||
current: type | ||
}; | ||
allFamiliesByID.set(id, family); | ||
@@ -326,10 +372,11 @@ } else { | ||
} | ||
allFamiliesByType.set(type, family); | ||
// Visit inner types because we might not have registered them. | ||
allFamiliesByType.set(type, family); // Visit inner types because we might not have registered them. | ||
if (typeof type === 'object' && type !== null) { | ||
switch (type.$$typeof) { | ||
switch (getProperty(type, '$$typeof')) { | ||
case REACT_FORWARD_REF_TYPE: | ||
register(type.render, id + '$render'); | ||
break; | ||
case REACT_MEMO_TYPE: | ||
@@ -342,6 +389,5 @@ register(type.type, id + '$type'); | ||
} | ||
function setSignature(type, key) { | ||
var forceReset = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | ||
var getCustomHooks = arguments[3]; | ||
var getCustomHooks = arguments.length > 3 ? arguments[3] : undefined; | ||
@@ -358,9 +404,9 @@ { | ||
} | ||
} | ||
} // This is lazily called during first render for a type. | ||
// It captures Hook list at that time so inline requires don't break comparisons. | ||
// This is lazily called during first render for a type. | ||
// It captures Hook list at that time so inline requires don't break comparisons. | ||
function collectCustomHooksForSignature(type) { | ||
{ | ||
var signature = allSignaturesByType.get(type); | ||
if (signature !== undefined) { | ||
@@ -371,3 +417,2 @@ computeFullKey(signature); | ||
} | ||
function getFamilyByID(id) { | ||
@@ -378,3 +423,2 @@ { | ||
} | ||
function getFamilyByType(type) { | ||
@@ -385,13 +429,13 @@ { | ||
} | ||
function findAffectedHostInstances(families) { | ||
{ | ||
if (typeof findHostInstancesForRefresh !== 'function') { | ||
warningWithoutStack$1(false, 'Could not find the findHostInstancesForRefresh() implementation. ' + 'This likely means that injectIntoGlobalHook() was either ' + 'called before the global DevTools hook was set up, or after the ' + 'renderer has already initialized. Please file an issue with a reproducing case.'); | ||
return new Set(); | ||
} | ||
var findInstances = findHostInstancesForRefresh; | ||
var affectedInstances = new Set(); | ||
mountedRoots.forEach(function (root) { | ||
var instancesForRoot = findInstances(root, families); | ||
var helpers = helpersByRoot.get(root); | ||
if (helpers === undefined) { | ||
throw new Error('Could not find helpers for a root. This is a bug in React Refresh.'); | ||
} | ||
var instancesForRoot = helpers.findHostInstancesForRefresh(root, families); | ||
instancesForRoot.forEach(function (inst) { | ||
@@ -404,3 +448,2 @@ affectedInstances.add(inst); | ||
} | ||
function injectIntoGlobalHook(globalObject) { | ||
@@ -410,6 +453,6 @@ { | ||
// That code will run before us. So we need to monkeypatch functions on existing hook. | ||
// For React Web, the global hook will be set up by the extension. | ||
// This will also run before us. | ||
var hook = globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__; | ||
if (hook === undefined) { | ||
@@ -419,5 +462,10 @@ // However, if there is no DevTools extension, we'll need to set up the global hook ourselves. | ||
// Otherwise, the renderer will think that there is no global hook, and won't do the injection. | ||
var nextID = 0; | ||
globalObject.__REACT_DEVTOOLS_GLOBAL_HOOK__ = hook = { | ||
renderers: new Map(), | ||
supportsFiber: true, | ||
inject: function () {}, | ||
inject: function (injected) { | ||
return nextID++; | ||
}, | ||
onScheduleFiberRoot: function (id, root, children) {}, | ||
onCommitFiberRoot: function (id, root, maybePriorityLevel, didError) {}, | ||
@@ -428,60 +476,93 @@ onCommitFiberUnmount: function () {} | ||
// Here, we just want to get a reference to scheduleRefresh. | ||
if (hook.isDisabled) { | ||
// This isn't a real property on the hook, but it can be set to opt out | ||
// of DevTools integration and associated warnings and logs. | ||
// Using console['warn'] to evade Babel and ESLint | ||
console['warn']('Something has shimmed the React DevTools global hook (__REACT_DEVTOOLS_GLOBAL_HOOK__). ' + 'Fast Refresh is not compatible with this shim and will be disabled.'); | ||
return; | ||
} // Here, we just want to get a reference to scheduleRefresh. | ||
var oldInject = hook.inject; | ||
hook.inject = function (injected) { | ||
findHostInstancesForRefresh = injected.findHostInstancesForRefresh; | ||
scheduleRefresh = injected.scheduleRefresh; | ||
scheduleRoot = injected.scheduleRoot; | ||
setRefreshHandler = injected.setRefreshHandler; | ||
return oldInject.apply(this, arguments); | ||
var id = oldInject.apply(this, arguments); | ||
if (typeof injected.scheduleRefresh === 'function' && typeof injected.setRefreshHandler === 'function') { | ||
// This version supports React Refresh. | ||
helpersByRendererID.set(id, injected); | ||
} | ||
return id; | ||
}; // Do the same for any already injected roots. | ||
// This is useful if ReactDOM has already been initialized. | ||
// https://github.com/facebook/react/issues/17626 | ||
hook.renderers.forEach(function (injected, id) { | ||
if (typeof injected.scheduleRefresh === 'function' && typeof injected.setRefreshHandler === 'function') { | ||
// This version supports React Refresh. | ||
helpersByRendererID.set(id, injected); | ||
} | ||
}); // We also want to track currently mounted roots. | ||
var oldOnCommitFiberRoot = hook.onCommitFiberRoot; | ||
var oldOnScheduleFiberRoot = hook.onScheduleFiberRoot || function () {}; | ||
hook.onScheduleFiberRoot = function (id, root, children) { | ||
if (!isPerformingRefresh) { | ||
// If it was intentionally scheduled, don't attempt to restore. | ||
// This includes intentionally scheduled unmounts. | ||
failedRoots.delete(root); | ||
if (rootElements !== null) { | ||
rootElements.set(root, children); | ||
} | ||
} | ||
return oldOnScheduleFiberRoot.apply(this, arguments); | ||
}; | ||
// We also want to track currently mounted roots. | ||
var oldOnCommitFiberRoot = hook.onCommitFiberRoot; | ||
hook.onCommitFiberRoot = function (id, root, maybePriorityLevel, didError) { | ||
var current = root.current; | ||
var alternate = current.alternate; | ||
var helpers = helpersByRendererID.get(id); | ||
// We need to determine whether this root has just (un)mounted. | ||
// This logic is copy-pasted from similar logic in the DevTools backend. | ||
// If this breaks with some refactoring, you'll want to update DevTools too. | ||
if (helpers !== undefined) { | ||
helpersByRoot.set(root, helpers); | ||
var current = root.current; | ||
var alternate = current.alternate; // We need to determine whether this root has just (un)mounted. | ||
// This logic is copy-pasted from similar logic in the DevTools backend. | ||
// If this breaks with some refactoring, you'll want to update DevTools too. | ||
if (alternate !== null) { | ||
var wasMounted = alternate.memoizedState != null && alternate.memoizedState.element != null; | ||
var isMounted = current.memoizedState != null && current.memoizedState.element != null; | ||
if (alternate !== null) { | ||
var wasMounted = alternate.memoizedState != null && alternate.memoizedState.element != null; | ||
var isMounted = current.memoizedState != null && current.memoizedState.element != null; | ||
if (!wasMounted && isMounted) { | ||
if (!wasMounted && isMounted) { | ||
// Mount a new root. | ||
mountedRoots.add(root); | ||
failedRoots.delete(root); | ||
} else if (wasMounted && isMounted) ; else if (wasMounted && !isMounted) { | ||
// Unmount an existing root. | ||
mountedRoots.delete(root); | ||
if (didError) { | ||
// We'll remount it on future edits. | ||
failedRoots.add(root); | ||
} else { | ||
helpersByRoot.delete(root); | ||
} | ||
} else if (!wasMounted && !isMounted) { | ||
if (didError) { | ||
// We'll remount it on future edits. | ||
failedRoots.add(root); | ||
} | ||
} | ||
} else { | ||
// Mount a new root. | ||
mountedRoots.add(root); | ||
failedRoots.delete(root); | ||
} else if (wasMounted && isMounted) { | ||
// Update an existing root. | ||
// This doesn't affect our mounted root Set. | ||
} else if (wasMounted && !isMounted) { | ||
// Unmount an existing root. | ||
mountedRoots.delete(root); | ||
if (didError) { | ||
// We'll remount it on future edits. | ||
// Remember what was rendered so we can restore it. | ||
failedRoots.set(root, alternate.memoizedState.element); | ||
} | ||
} else if (!wasMounted && !isMounted) { | ||
if (didError && !failedRoots.has(root)) { | ||
// The root had an error during the initial mount. | ||
// We can't read its last element from the memoized state | ||
// because there was no previously committed alternate. | ||
// Ideally, it would be nice if we had a way to extract | ||
// the last attempted rendered element, but accessing the update queue | ||
// would tie this package too closely to the reconciler version. | ||
// So instead, we just set a flag. | ||
// TODO: Maybe we could fix this as the same time as when we fix | ||
// DevTools to not depend on `alternate.memoizedState.element`. | ||
didSomeRootFailOnMount = true; | ||
} | ||
} | ||
} else { | ||
// Mount a new root. | ||
mountedRoots.add(root); | ||
} | ||
} // Always call the decorated DevTools hook. | ||
return oldOnCommitFiberRoot.apply(this, arguments); | ||
@@ -491,8 +572,7 @@ }; | ||
} | ||
function hasUnrecoverableErrors() { | ||
return didSomeRootFailOnMount; | ||
} | ||
// TODO: delete this after removing dependency in RN. | ||
return false; | ||
} // Exposed for testing. | ||
// Exposed for testing. | ||
function _getMountedRootCount() { | ||
@@ -502,5 +582,3 @@ { | ||
} | ||
} | ||
// This is a wrapper over more primitive functions for setting signature. | ||
} // This is a wrapper over more primitive functions for setting signature. | ||
// Signatures let us decide whether the Hook order has changed on refresh. | ||
@@ -527,20 +605,35 @@ // | ||
// ); | ||
function createSignatureFunctionForTransform() { | ||
{ | ||
var call = 0; | ||
var savedType = void 0; | ||
var hasCustomHooks = void 0; | ||
// We'll fill in the signature in two steps. | ||
// First, we'll know the signature itself. This happens outside the component. | ||
// Then, we'll know the references to custom Hooks. This happens inside the component. | ||
// After that, the returned function will be a fast path no-op. | ||
var status = 'needsSignature'; | ||
var savedType; | ||
var hasCustomHooks; | ||
return function (type, key, forceReset, getCustomHooks) { | ||
switch (call++) { | ||
case 0: | ||
savedType = type; | ||
hasCustomHooks = typeof getCustomHooks === 'function'; | ||
setSignature(type, key, forceReset, getCustomHooks); | ||
switch (status) { | ||
case 'needsSignature': | ||
if (type !== undefined) { | ||
// If we received an argument, this is the initial registration call. | ||
savedType = type; | ||
hasCustomHooks = typeof getCustomHooks === 'function'; | ||
setSignature(type, key, forceReset, getCustomHooks); // The next call we expect is from inside a function, to fill in the custom Hooks. | ||
status = 'needsCustomHooks'; | ||
} | ||
break; | ||
case 1: | ||
case 'needsCustomHooks': | ||
if (hasCustomHooks) { | ||
collectCustomHooksForSignature(savedType); | ||
} | ||
status = 'resolved'; | ||
break; | ||
} | ||
return type; | ||
@@ -550,3 +643,2 @@ }; | ||
} | ||
function isLikelyComponentType(type) { | ||
@@ -563,23 +655,28 @@ { | ||
} | ||
var ownNames = Object.getOwnPropertyNames(type.prototype); | ||
if (ownNames.length > 1 || ownNames[0] !== 'constructor') { | ||
// This looks like a class. | ||
return false; | ||
} | ||
// eslint-disable-next-line no-proto | ||
} // eslint-disable-next-line no-proto | ||
if (type.prototype.__proto__ !== Object.prototype) { | ||
// It has a superclass. | ||
return false; | ||
} | ||
// Pass through. | ||
} // Pass through. | ||
// This looks like a regular function with empty prototype. | ||
} | ||
// For plain functions and arrows, use name as a heuristic. | ||
} // For plain functions and arrows, use name as a heuristic. | ||
var name = type.name || type.displayName; | ||
return typeof name === 'string' && /^[A-Z]/.test(name); | ||
} | ||
case 'object': | ||
{ | ||
if (type != null) { | ||
switch (type.$$typeof) { | ||
switch (getProperty(type, '$$typeof')) { | ||
case REACT_FORWARD_REF_TYPE: | ||
@@ -589,2 +686,3 @@ case REACT_MEMO_TYPE: | ||
return true; | ||
default: | ||
@@ -594,4 +692,6 @@ return false; | ||
} | ||
return false; | ||
} | ||
default: | ||
@@ -605,22 +705,15 @@ { | ||
var ReactFreshRuntime = Object.freeze({ | ||
performReactRefresh: performReactRefresh, | ||
register: register, | ||
setSignature: setSignature, | ||
collectCustomHooksForSignature: collectCustomHooksForSignature, | ||
getFamilyByID: getFamilyByID, | ||
getFamilyByType: getFamilyByType, | ||
findAffectedHostInstances: findAffectedHostInstances, | ||
injectIntoGlobalHook: injectIntoGlobalHook, | ||
hasUnrecoverableErrors: hasUnrecoverableErrors, | ||
_getMountedRootCount: _getMountedRootCount, | ||
createSignatureFunctionForTransform: createSignatureFunctionForTransform, | ||
isLikelyComponentType: isLikelyComponentType | ||
}); | ||
// This is hacky but makes it work with both Rollup and Jest. | ||
var runtime = ReactFreshRuntime.default || ReactFreshRuntime; | ||
module.exports = runtime; | ||
exports._getMountedRootCount = _getMountedRootCount; | ||
exports.collectCustomHooksForSignature = collectCustomHooksForSignature; | ||
exports.createSignatureFunctionForTransform = createSignatureFunctionForTransform; | ||
exports.findAffectedHostInstances = findAffectedHostInstances; | ||
exports.getFamilyByID = getFamilyByID; | ||
exports.getFamilyByType = getFamilyByType; | ||
exports.hasUnrecoverableErrors = hasUnrecoverableErrors; | ||
exports.injectIntoGlobalHook = injectIntoGlobalHook; | ||
exports.isLikelyComponentType = isLikelyComponentType; | ||
exports.performReactRefresh = performReactRefresh; | ||
exports.register = register; | ||
exports.setSignature = setSignature; | ||
})(); | ||
} |
@@ -1,2 +0,2 @@ | ||
/** @license React v0.0.0-a1dbb852c | ||
/** @license React vundefined | ||
* react-refresh-runtime.production.min.js | ||
@@ -9,3 +9,2 @@ * | ||
*/ | ||
'use strict';throw Error("React Refresh runtime should not be included in the production bundle."); |
@@ -7,3 +7,3 @@ { | ||
], | ||
"version": "0.0.0-a1dbb852c", | ||
"version": "0.0.0-a703c3f7e", | ||
"homepage": "https://reactjs.org/", | ||
@@ -21,3 +21,3 @@ "bugs": "https://github.com/facebook/react/issues", | ||
], | ||
"main": "index.js", | ||
"main": "runtime.js", | ||
"repository": { | ||
@@ -30,3 +30,7 @@ "type": "git", | ||
"node": ">=0.10.0" | ||
}, | ||
"devDependencies": { | ||
"react-16-8": "npm:react@16.8.0", | ||
"react-dom-16-8": "npm:react-dom@16.8.0" | ||
} | ||
} | ||
} |
# react-refresh | ||
This is an experimental package for hot reloading. | ||
This package implements the wiring necessary to integrate Fast Refresh into bundlers. Fast Refresh is a feature that lets you edit React components in a running application without losing their state. It is similar to an old feature known as "hot reloading", but Fast Refresh is more reliable and officially supported by React. | ||
**Its API is not as stable as that of React, React Native, or React DOM, and does not follow the common versioning scheme.** | ||
**Use it at your own risk.** | ||
This package is primarily aimed at developers of bundler plugins. If you’re working on one, here is a [rough guide](https://github.com/facebook/react/issues/16604#issuecomment-528663101) for Fast Refresh integration using this package. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
56121
1237
2
9
2
6
3