You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					332 lines
				
				9.2 KiB
			
		
		
			
		
	
	
					332 lines
				
				9.2 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Object.defineProperty(exports, '__esModule', {
							 | 
						||
| 
								 | 
							
								  value: true
							 | 
						||
| 
								 | 
							
								});
							 | 
						||
| 
								 | 
							
								exports.saveInlineSnapshots = void 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _fs = _interopRequireDefault(require('fs'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _path = _interopRequireDefault(require('path'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _semver = _interopRequireDefault(require('semver'));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _types = require('@babel/types');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _utils = require('./utils');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _interopRequireDefault(obj) {
							 | 
						||
| 
								 | 
							
								  return obj && obj.__esModule ? obj : {default: obj};
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
							 | 
						||
| 
								 | 
							
								var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var jestWriteFile =
							 | 
						||
| 
								 | 
							
								  global[Symbol.for('jest-native-write-file')] || _fs.default.writeFileSync;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _objectSpread(target) {
							 | 
						||
| 
								 | 
							
								  for (var i = 1; i < arguments.length; i++) {
							 | 
						||
| 
								 | 
							
								    var source = arguments[i] != null ? arguments[i] : {};
							 | 
						||
| 
								 | 
							
								    var ownKeys = Object.keys(source);
							 | 
						||
| 
								 | 
							
								    if (typeof Object.getOwnPropertySymbols === 'function') {
							 | 
						||
| 
								 | 
							
								      ownKeys = ownKeys.concat(
							 | 
						||
| 
								 | 
							
								        Object.getOwnPropertySymbols(source).filter(function(sym) {
							 | 
						||
| 
								 | 
							
								          return Object.getOwnPropertyDescriptor(source, sym).enumerable;
							 | 
						||
| 
								 | 
							
								        })
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    ownKeys.forEach(function(key) {
							 | 
						||
| 
								 | 
							
								      _defineProperty(target, key, source[key]);
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return target;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function _defineProperty(obj, key, value) {
							 | 
						||
| 
								 | 
							
								  if (key in obj) {
							 | 
						||
| 
								 | 
							
								    Object.defineProperty(obj, key, {
							 | 
						||
| 
								 | 
							
								      value: value,
							 | 
						||
| 
								 | 
							
								      enumerable: true,
							 | 
						||
| 
								 | 
							
								      configurable: true,
							 | 
						||
| 
								 | 
							
								      writable: true
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    obj[key] = value;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return obj;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var Symbol = global['jest-symbol-do-not-touch'] || global.Symbol;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var jestReadFile =
							 | 
						||
| 
								 | 
							
								  global[Symbol.for('jest-native-read-file')] || _fs.default.readFileSync;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const saveInlineSnapshots = (snapshots, prettier, babelTraverse) => {
							 | 
						||
| 
								 | 
							
								  if (!prettier) {
							 | 
						||
| 
								 | 
							
								    throw new Error(
							 | 
						||
| 
								 | 
							
								      `Jest: Inline Snapshots requires Prettier.\n` +
							 | 
						||
| 
								 | 
							
								        `Please ensure "prettier" is installed in your project.`
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  } // Custom parser API was added in 1.5.0
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (_semver.default.lt(prettier.version, '1.5.0')) {
							 | 
						||
| 
								 | 
							
								    throw new Error(
							 | 
						||
| 
								 | 
							
								      `Jest: Inline Snapshots require prettier>=1.5.0.\n` +
							 | 
						||
| 
								 | 
							
								        `Please upgrade "prettier".`
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const snapshotsByFile = groupSnapshotsByFile(snapshots);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var _arr = Object.keys(snapshotsByFile);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (var _i = 0; _i < _arr.length; _i++) {
							 | 
						||
| 
								 | 
							
								    const sourceFilePath = _arr[_i];
							 | 
						||
| 
								 | 
							
								    saveSnapshotsForFile(
							 | 
						||
| 
								 | 
							
								      snapshotsByFile[sourceFilePath],
							 | 
						||
| 
								 | 
							
								      sourceFilePath,
							 | 
						||
| 
								 | 
							
								      prettier,
							 | 
						||
| 
								 | 
							
								      babelTraverse
							 | 
						||
| 
								 | 
							
								    );
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								exports.saveInlineSnapshots = saveInlineSnapshots;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const saveSnapshotsForFile = (
							 | 
						||
| 
								 | 
							
								  snapshots,
							 | 
						||
| 
								 | 
							
								  sourceFilePath,
							 | 
						||
| 
								 | 
							
								  prettier,
							 | 
						||
| 
								 | 
							
								  babelTraverse
							 | 
						||
| 
								 | 
							
								) => {
							 | 
						||
| 
								 | 
							
								  const sourceFile = jestReadFile(sourceFilePath, 'utf8'); // Resolve project configuration.
							 | 
						||
| 
								 | 
							
								  // For older versions of Prettier, do not load configuration.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const config = prettier.resolveConfig
							 | 
						||
| 
								 | 
							
								    ? prettier.resolveConfig.sync(sourceFilePath, {
							 | 
						||
| 
								 | 
							
								        editorconfig: true
							 | 
						||
| 
								 | 
							
								      })
							 | 
						||
| 
								 | 
							
								    : null; // Detect the parser for the test file.
							 | 
						||
| 
								 | 
							
								  // For older versions of Prettier, fallback to a simple parser detection.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const inferredParser = prettier.getFileInfo
							 | 
						||
| 
								 | 
							
								    ? prettier.getFileInfo.sync(sourceFilePath).inferredParser
							 | 
						||
| 
								 | 
							
								    : (config && config.parser) || simpleDetectParser(sourceFilePath); // Insert snapshots using the custom parser API. After insertion, the code is
							 | 
						||
| 
								 | 
							
								  // formatted, except snapshot indentation. Snapshots cannot be formatted until
							 | 
						||
| 
								 | 
							
								  // after the initial format because we don't know where the call expression
							 | 
						||
| 
								 | 
							
								  // will be placed (specifically its indentation).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const newSourceFile = prettier.format(
							 | 
						||
| 
								 | 
							
								    sourceFile,
							 | 
						||
| 
								 | 
							
								    _objectSpread({}, config, {
							 | 
						||
| 
								 | 
							
								      filepath: sourceFilePath,
							 | 
						||
| 
								 | 
							
								      parser: createInsertionParser(snapshots, inferredParser, babelTraverse)
							 | 
						||
| 
								 | 
							
								    })
							 | 
						||
| 
								 | 
							
								  ); // Format the snapshots using the custom parser API.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const formattedNewSourceFile = prettier.format(
							 | 
						||
| 
								 | 
							
								    newSourceFile,
							 | 
						||
| 
								 | 
							
								    _objectSpread({}, config, {
							 | 
						||
| 
								 | 
							
								      filepath: sourceFilePath,
							 | 
						||
| 
								 | 
							
								      parser: createFormattingParser(inferredParser, babelTraverse)
							 | 
						||
| 
								 | 
							
								    })
							 | 
						||
| 
								 | 
							
								  );
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (formattedNewSourceFile !== sourceFile) {
							 | 
						||
| 
								 | 
							
								    jestWriteFile(sourceFilePath, formattedNewSourceFile);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const groupSnapshotsBy = createKey => snapshots =>
							 | 
						||
| 
								 | 
							
								  snapshots.reduce((object, inlineSnapshot) => {
							 | 
						||
| 
								 | 
							
								    const key = createKey(inlineSnapshot);
							 | 
						||
| 
								 | 
							
								    return _objectSpread({}, object, {
							 | 
						||
| 
								 | 
							
								      [key]: (object[key] || []).concat(inlineSnapshot)
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }, {});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const groupSnapshotsByFrame = groupSnapshotsBy(({frame: {line, column}}) =>
							 | 
						||
| 
								 | 
							
								  typeof line === 'number' && typeof column === 'number'
							 | 
						||
| 
								 | 
							
								    ? `${line}:${column - 1}`
							 | 
						||
| 
								 | 
							
								    : ''
							 | 
						||
| 
								 | 
							
								);
							 | 
						||
| 
								 | 
							
								const groupSnapshotsByFile = groupSnapshotsBy(({frame: {file}}) => file);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const indent = (snapshot, numIndents, indentation) => {
							 | 
						||
| 
								 | 
							
								  const lines = snapshot.split('\n'); // Prevent re-identation of inline snapshots.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (
							 | 
						||
| 
								 | 
							
								    lines.length >= 2 &&
							 | 
						||
| 
								 | 
							
								    lines[1].startsWith(indentation.repeat(numIndents + 1))
							 | 
						||
| 
								 | 
							
								  ) {
							 | 
						||
| 
								 | 
							
								    return snapshot;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return lines
							 | 
						||
| 
								 | 
							
								    .map((line, index) => {
							 | 
						||
| 
								 | 
							
								      if (index === 0) {
							 | 
						||
| 
								 | 
							
								        // First line is either a 1-line snapshot or a blank line.
							 | 
						||
| 
								 | 
							
								        return line;
							 | 
						||
| 
								 | 
							
								      } else if (index !== lines.length - 1) {
							 | 
						||
| 
								 | 
							
								        // Do not indent empty lines.
							 | 
						||
| 
								 | 
							
								        if (line === '') {
							 | 
						||
| 
								 | 
							
								          return line;
							 | 
						||
| 
								 | 
							
								        } // Not last line, indent one level deeper than expect call.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return indentation.repeat(numIndents + 1) + line;
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        // The last line should be placed on the same level as the expect call.
							 | 
						||
| 
								 | 
							
								        return indentation.repeat(numIndents) + line;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    })
							 | 
						||
| 
								 | 
							
								    .join('\n');
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const getAst = (parsers, inferredParser, text) => {
							 | 
						||
| 
								 | 
							
								  // Flow uses a 'Program' parent node, babel expects a 'File'.
							 | 
						||
| 
								 | 
							
								  let ast = parsers[inferredParser](text);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (ast.type !== 'File') {
							 | 
						||
| 
								 | 
							
								    ast = (0, _types.file)(ast, ast.comments, ast.tokens);
							 | 
						||
| 
								 | 
							
								    delete ast.program.comments;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return ast;
							 | 
						||
| 
								 | 
							
								}; // This parser inserts snapshots into the AST.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const createInsertionParser = (snapshots, inferredParser, babelTraverse) => (
							 | 
						||
| 
								 | 
							
								  text,
							 | 
						||
| 
								 | 
							
								  parsers,
							 | 
						||
| 
								 | 
							
								  options
							 | 
						||
| 
								 | 
							
								) => {
							 | 
						||
| 
								 | 
							
								  // Workaround for https://github.com/prettier/prettier/issues/3150
							 | 
						||
| 
								 | 
							
								  options.parser = inferredParser;
							 | 
						||
| 
								 | 
							
								  const groupedSnapshots = groupSnapshotsByFrame(snapshots);
							 | 
						||
| 
								 | 
							
								  const remainingSnapshots = new Set(snapshots.map(({snapshot}) => snapshot));
							 | 
						||
| 
								 | 
							
								  const ast = getAst(parsers, inferredParser, text);
							 | 
						||
| 
								 | 
							
								  babelTraverse(ast, {
							 | 
						||
| 
								 | 
							
								    CallExpression({node: {arguments: args, callee}}) {
							 | 
						||
| 
								 | 
							
								      if (
							 | 
						||
| 
								 | 
							
								        callee.type !== 'MemberExpression' ||
							 | 
						||
| 
								 | 
							
								        callee.property.type !== 'Identifier'
							 | 
						||
| 
								 | 
							
								      ) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const _callee$property$loc$ = callee.property.loc.start,
							 | 
						||
| 
								 | 
							
								        line = _callee$property$loc$.line,
							 | 
						||
| 
								 | 
							
								        column = _callee$property$loc$.column;
							 | 
						||
| 
								 | 
							
								      const snapshotsForFrame = groupedSnapshots[`${line}:${column}`];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (!snapshotsForFrame) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (snapshotsForFrame.length > 1) {
							 | 
						||
| 
								 | 
							
								        throw new Error(
							 | 
						||
| 
								 | 
							
								          'Jest: Multiple inline snapshots for the same call are not supported.'
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const snapshotIndex = args.findIndex(
							 | 
						||
| 
								 | 
							
								        ({type}) => type === 'TemplateLiteral'
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								      const values = snapshotsForFrame.map(({snapshot}) => {
							 | 
						||
| 
								 | 
							
								        remainingSnapshots.delete(snapshot);
							 | 
						||
| 
								 | 
							
								        return (0, _types.templateLiteral)(
							 | 
						||
| 
								 | 
							
								          [
							 | 
						||
| 
								 | 
							
								            (0, _types.templateElement)({
							 | 
						||
| 
								 | 
							
								              raw: (0, _utils.escapeBacktickString)(snapshot)
							 | 
						||
| 
								 | 
							
								            })
							 | 
						||
| 
								 | 
							
								          ],
							 | 
						||
| 
								 | 
							
								          []
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								      const replacementNode = values[0];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (snapshotIndex > -1) {
							 | 
						||
| 
								 | 
							
								        args[snapshotIndex] = replacementNode;
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        args.push(replacementNode);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (remainingSnapshots.size) {
							 | 
						||
| 
								 | 
							
								    throw new Error(`Jest: Couldn't locate all inline snapshots.`);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return ast;
							 | 
						||
| 
								 | 
							
								}; // This parser formats snapshots to the correct indentation.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const createFormattingParser = (inferredParser, babelTraverse) => (
							 | 
						||
| 
								 | 
							
								  text,
							 | 
						||
| 
								 | 
							
								  parsers,
							 | 
						||
| 
								 | 
							
								  options
							 | 
						||
| 
								 | 
							
								) => {
							 | 
						||
| 
								 | 
							
								  // Workaround for https://github.com/prettier/prettier/issues/3150
							 | 
						||
| 
								 | 
							
								  options.parser = inferredParser;
							 | 
						||
| 
								 | 
							
								  const ast = getAst(parsers, inferredParser, text);
							 | 
						||
| 
								 | 
							
								  babelTraverse(ast, {
							 | 
						||
| 
								 | 
							
								    CallExpression({node: {arguments: args, callee}}) {
							 | 
						||
| 
								 | 
							
								      if (
							 | 
						||
| 
								 | 
							
								        callee.type !== 'MemberExpression' ||
							 | 
						||
| 
								 | 
							
								        callee.property.type !== 'Identifier' ||
							 | 
						||
| 
								 | 
							
								        callee.property.name !== 'toMatchInlineSnapshot' ||
							 | 
						||
| 
								 | 
							
								        !callee.loc ||
							 | 
						||
| 
								 | 
							
								        callee.computed
							 | 
						||
| 
								 | 
							
								      ) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      let snapshotIndex;
							 | 
						||
| 
								 | 
							
								      let snapshot;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      for (let i = 0; i < args.length; i++) {
							 | 
						||
| 
								 | 
							
								        const node = args[i];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        if (node.type === 'TemplateLiteral') {
							 | 
						||
| 
								 | 
							
								          snapshotIndex = i;
							 | 
						||
| 
								 | 
							
								          snapshot = node.quasis[0].value.raw;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      if (snapshot === undefined || snapshotIndex === undefined) {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const useSpaces = !options.useTabs;
							 | 
						||
| 
								 | 
							
								      snapshot = indent(
							 | 
						||
| 
								 | 
							
								        snapshot,
							 | 
						||
| 
								 | 
							
								        Math.ceil(
							 | 
						||
| 
								 | 
							
								          useSpaces
							 | 
						||
| 
								 | 
							
								            ? callee.loc.start.column / options.tabWidth
							 | 
						||
| 
								 | 
							
								            : callee.loc.start.column / 2 // Each tab is 2 characters.
							 | 
						||
| 
								 | 
							
								        ),
							 | 
						||
| 
								 | 
							
								        useSpaces ? ' '.repeat(options.tabWidth) : '\t'
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								      const replacementNode = (0, _types.templateLiteral)(
							 | 
						||
| 
								 | 
							
								        [
							 | 
						||
| 
								 | 
							
								          (0, _types.templateElement)({
							 | 
						||
| 
								 | 
							
								            raw: snapshot
							 | 
						||
| 
								 | 
							
								          })
							 | 
						||
| 
								 | 
							
								        ],
							 | 
						||
| 
								 | 
							
								        []
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								      args[snapshotIndex] = replacementNode;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								  return ast;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const simpleDetectParser = filePath => {
							 | 
						||
| 
								 | 
							
								  const extname = _path.default.extname(filePath);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (/tsx?$/.test(extname)) {
							 | 
						||
| 
								 | 
							
								    return 'typescript';
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return 'babylon';
							 | 
						||
| 
								 | 
							
								};
							 |