diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6c47511..ea8de3a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,6 +21,7 @@ jobs: - name: npm install & test run: | npm install + npm run lint npm test env: CI: true diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..37bc7fb --- /dev/null +++ b/.prettierrc @@ -0,0 +1,7 @@ +{ + "semi": false, + "singleQuote": true, + "trailingComma": "es5", + "arrowParens": "always", + "printWidth": 80 +} \ No newline at end of file diff --git a/app/build/deoptigate.js b/app/build/deoptigate.js index d12973c..bb3d341 100644 --- a/app/build/deoptigate.js +++ b/app/build/deoptigate.js @@ -1,33635 +1,49385 @@ -(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.deoptigateRender = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i { - const tgt = event.target - const { markerid, markertype } = tgt.dataset - if (markerid == null) { return } - event.preventDefault() - event.stopPropagation() - this._onmarkerClicked(parseInt(markerid), markertype) - }) - this._maybeScrollIntoView() - } + componentDidMount() { + const rootEl = ReactDOM.findDOMNode(this) + rootEl.addEventListener('click', (event) => { + const tgt = event.target + const { markerid, markertype } = tgt.dataset + if (markerid == null) { + return + } + event.preventDefault() + event.stopPropagation() + this._onmarkerClicked(parseInt(markerid), markertype) + }) + this._maybeScrollIntoView() + } - componentDidUpdate() { - this._maybeScrollIntoView() - } + componentDidUpdate() { + this._maybeScrollIntoView() + } - shouldComponentUpdate(nextProps) { - const props = this.props - return ( - props.code !== nextProps.code - || props.selectedLocation !== nextProps.selectedLocation - || props.includeAllSeverities !== nextProps.includeAllSeverities - || props.highlightCode !== nextProps.highlightCode - ) - } + shouldComponentUpdate(nextProps) { + const props = this.props + return ( + props.code !== nextProps.code || + props.selectedLocation !== nextProps.selectedLocation || + props.includeAllSeverities !== nextProps.includeAllSeverities || + props.highlightCode !== nextProps.highlightCode + ) + } - render() { - const { - className = '' - , ics - , deopts - , codes - , icLocations - , deoptLocations - , codeLocations - , selectedLocation - , includeAllSeverities - } = this.props - - const markerResolver = new MarkerResolver({ - deopts - , deoptLocations - , ics - , icLocations - , codes - , codeLocations - , selectedLocation - , includeAllSeverities - }) - - const theme = new Theme(markerResolver).theme - const highlightedCode = this._tryHighlightCode(theme, markerResolver) - return ( - React.createElement( 'div', { className: className }, - React.createElement( 'div', { dangerouslySetInnerHTML: {__html: highlightedCode} }) - ) - ) - } + render() { + const { + className = '', + ics, + deopts, + codes, + icLocations, + deoptLocations, + codeLocations, + selectedLocation, + includeAllSeverities, + } = this.props + + const markerResolver = new MarkerResolver({ + deopts, + deoptLocations, + ics, + icLocations, + codes, + codeLocations, + selectedLocation, + includeAllSeverities, + }) + + const theme = new Theme(markerResolver).theme + const highlightedCode = this._tryHighlightCode( + theme, + markerResolver + ) + return React.createElement( + 'div', + { className: className }, + React.createElement('div', { + dangerouslySetInnerHTML: { __html: highlightedCode }, + }) + ) + } - _tryHighlightCode(theme, markerResolver) { - const { fileName, code, highlightCode } = this.props - const nohighlight = !highlightCode || code.length > MAX_HIGHLIGHT_LEN - if (nohighlight) { return markOnly(code, markerResolver) } - try { - try { - // Highlighting without jsx support allows peacock to only parse out tokens - // which is faster than building the AST - const jsx = fileName.endsWith('jsx') - return highlight(code, { theme, linenos: true, jsx }) - } catch (err) { - // Higlighting without jsx option failed, try again - return highlight(code, { theme, linenos: true, jsx: true }) - } - } catch (err) { - // Highlighting failed alltogether - try { - return markOnly(code, markerResolver) - } catch (innerErr) { - // Even marking only failed, just show the code :( - return ` + _tryHighlightCode(theme, markerResolver) { + const { fileName, code, highlightCode } = this.props + const nohighlight = + !highlightCode || code.length > MAX_HIGHLIGHT_LEN + if (nohighlight) { + return markOnly(code, markerResolver) + } + try { + try { + // Highlighting without jsx support allows peacock to only parse out tokens + // which is faster than building the AST + const jsx = fileName.endsWith('jsx') + return highlight(code, { theme, linenos: true, jsx }) + } catch (err) { + // Higlighting without jsx option failed, try again + return highlight(code, { theme, linenos: true, jsx: true }) + } + } catch (err) { + // Highlighting failed alltogether + try { + return markOnly(code, markerResolver) + } catch (innerErr) { + // Even marking only failed, just show the code :( + return `

Deoptigate was unable to highlight/mark the below code

${code}
` - } - } - } + } + } + } - _onmarkerClicked(id, type) { - const { onmarkerClicked } = this.props - onmarkerClicked(id, type) - } -} + _onmarkerClicked(id, type) { + const { onmarkerClicked } = this.props + onmarkerClicked(id, type) + } + } -module.exports = { - CodeView -} + module.exports = { + CodeView, + } + }, + { + '../../lib/rendering/mark-only': 66, + '../../lib/rendering/marker-resolver': 67, + '../theme.browser': 56, + assert: 8, + peacock: 16, + react: 46, + 'react-dom': 26, + 'scroll-into-view-if-needed': 54, + }, + ], + 2: [ + function (require, module, exports) { + 'use strict' -},{"../../lib/rendering/mark-only":66,"../../lib/rendering/marker-resolver":67,"../theme.browser":56,"assert":8,"peacock":16,"react":46,"react-dom":26,"scroll-into-view-if-needed":54}],2:[function(require,module,exports){ -'use strict' + const React = require('react') + const { Component } = React -const React = require('react') -const { Component } = React + const { CodeView } = require('./code') + const { SummaryView } = require('./summary') -const { CodeView } = require('./code') -const { SummaryView } = require('./summary') + const assert = require('assert') -const assert = require('assert') + class FileDetailsView extends Component { + constructor(props) { + super(props) -class FileDetailsView extends Component { - constructor(props) { - super(props) + const { onsummaryTabIdxChanged } = props + assert.equal( + typeof onsummaryTabIdxChanged, + 'function', + 'need to pass onsummaryTabIdxChanged function' + ) - const { onsummaryTabIdxChanged } = props - assert.equal(typeof onsummaryTabIdxChanged, 'function', 'need to pass onsummaryTabIdxChanged function') + this._bind() + } - this._bind() - } + _bind() { + this._onmarkerClicked = this._onmarkerClicked.bind(this) + this._onsummaryTabHeaderClicked = this._onsummaryTabHeaderClicked.bind( + this + ) + } - _bind() { - this._onmarkerClicked = this._onmarkerClicked.bind(this) - this._onsummaryTabHeaderClicked = this._onsummaryTabHeaderClicked.bind(this) - } + render() { + const { + groups, + selectedFile, + selectedLocation, + includeAllSeverities, + highlightCode, + className = '', + selectedSummaryTabIdx, + onsummaryClicked, + } = this.props + + const { + ics, + icLocations, + deopts, + deoptLocations, + codes, + codeLocations, + src, + relativePath, + } = groups.get(selectedFile) + + return React.createElement( + 'div', + { className: className }, + React.createElement(CodeView, { + className: 'flex-column vh-85 w-50 code-view', + selectedLocation: selectedLocation, + fileName: selectedFile, + code: src, + ics: ics, + icLocations: icLocations, + deopts: deopts, + deoptLocations: deoptLocations, + codes: codes, + codeLocations: codeLocations, + includeAllSeverities: includeAllSeverities, + highlightCode: highlightCode, + onmarkerClicked: this._onmarkerClicked, + }), + React.createElement(SummaryView, { + className: 'flex-column vh-85 w-50 summary-view', + file: selectedFile, + relativePath: relativePath, + selectedLocation: selectedLocation, + ics: ics, + icLocations: icLocations, + deopts: deopts, + deoptLocations: deoptLocations, + codes: codes, + codeLocations: codeLocations, + includeAllSeverities: includeAllSeverities, + selectedTabIdx: selectedSummaryTabIdx, + ontabHeaderClicked: this._onsummaryTabHeaderClicked, + onsummaryClicked: onsummaryClicked, + }) + ) + } - render() { - const { - groups - , selectedFile - , selectedLocation - , includeAllSeverities - , highlightCode - , className = '' - , selectedSummaryTabIdx - , onsummaryClicked - } = this.props - - const { - ics - , icLocations - , deopts - , deoptLocations - , codes - , codeLocations - , src - , relativePath - } = groups.get(selectedFile) - - return ( - React.createElement( 'div', { className: className }, - React.createElement( CodeView, { - className: 'flex-column vh-85 w-50 code-view', selectedLocation: selectedLocation, fileName: selectedFile, code: src, ics: ics, icLocations: icLocations, deopts: deopts, deoptLocations: deoptLocations, codes: codes, codeLocations: codeLocations, includeAllSeverities: includeAllSeverities, highlightCode: highlightCode, onmarkerClicked: this._onmarkerClicked }), - React.createElement( SummaryView, { - className: 'flex-column vh-85 w-50 summary-view', file: selectedFile, relativePath: relativePath, selectedLocation: selectedLocation, ics: ics, icLocations: icLocations, deopts: deopts, deoptLocations: deoptLocations, codes: codes, codeLocations: codeLocations, includeAllSeverities: includeAllSeverities, selectedTabIdx: selectedSummaryTabIdx, ontabHeaderClicked: this._onsummaryTabHeaderClicked, onsummaryClicked: onsummaryClicked }) - ) - ) - } + _onmarkerClicked(id, type) { + const { + onmarkerClicked, + onsummaryTabIdxChanged, + selectedSummaryTabIdx, + } = this.props + const markerSummaryTabIdx = + type === 'code' + ? SummaryView.OPT_TAB_IDX + : type === 'deopt' + ? SummaryView.DEOPT_TAB_IDX + : SummaryView.ICS_TAB_IDX + onmarkerClicked(id) + if (markerSummaryTabIdx !== selectedSummaryTabIdx) { + onsummaryTabIdxChanged(markerSummaryTabIdx) + } + } - _onmarkerClicked(id, type) { - const { - onmarkerClicked - , onsummaryTabIdxChanged - , selectedSummaryTabIdx - } = this.props - const markerSummaryTabIdx = ( - type === 'code' ? SummaryView.OPT_TAB_IDX - : type === 'deopt' ? SummaryView.DEOPT_TAB_IDX - : SummaryView.ICS_TAB_IDX - ) - onmarkerClicked(id) - if (markerSummaryTabIdx !== selectedSummaryTabIdx) { - onsummaryTabIdxChanged(markerSummaryTabIdx) - } - } + _onsummaryTabHeaderClicked(idx) { + const { onsummaryTabIdxChanged } = this.props + onsummaryTabIdxChanged(idx) + } + } - _onsummaryTabHeaderClicked(idx) { - const { onsummaryTabIdxChanged } = this.props - onsummaryTabIdxChanged(idx) - } -} - -module.exports = { FileDetailsView } - -},{"./code":1,"./summary":4,"assert":8,"react":46}],3:[function(require,module,exports){ -'use strict' - -const React = require('react') -const { Component } = React -const summarizeFile = require('../../lib/grouping/summarize-file') -const assert = require('assert') - -const severityClassNames = [ - 'green i tc' - , 'blue tc' - , 'red b tc' -] - -const underlineTdClass = ' pl2 pr2 underlined ' - -function coloredTds(arr) { - return arr.map((x, idx) => { - const className = x > 0 - ? severityClassNames[idx] + ' tr' + underlineTdClass - : ' pl2 pr2 tc i gray' + underlineTdClass - return React.createElement( 'td', { key: idx, className: className }, x) - }) -} - -function bySeverityScoreDesc(ref, ref$1) { - var s1 = ref.summary; - var s2 = ref$1.summary; - - return s1.severityScore < s2.severityScore ? 1 : -1 -} - -class FilesView extends Component { - constructor(props) { - super(props) - const { onfileClicked } = props - assert.equal(typeof onfileClicked, 'function', 'need to pass onfileClicked function') - } + module.exports = { FileDetailsView } + }, + { './code': 1, './summary': 4, assert: 8, react: 46 }, + ], + 3: [ + function (require, module, exports) { + 'use strict' + + const React = require('react') + const { Component } = React + const summarizeFile = require('../../lib/grouping/summarize-file') + const assert = require('assert') + + const severityClassNames = ['green i tc', 'blue tc', 'red b tc'] + + const underlineTdClass = ' pl2 pr2 underlined ' + + function coloredTds(arr) { + return arr.map((x, idx) => { + const className = + x > 0 + ? severityClassNames[idx] + ' tr' + underlineTdClass + : ' pl2 pr2 tc i gray' + underlineTdClass + return React.createElement( + 'td', + { key: idx, className: className }, + x + ) + }) + } - render() { - const { groups, includeAllSeverities, className = '' } = this.props - const tableHeader = this._renderTableHeader() - const rows = [] - const filesSeverities = Array.from(groups) - .map((ref) => { - var file = ref[0]; - var info = ref[1]; - - const { deopts, ics, codes } = info - const summary = summarizeFile({ ics, deopts, codes }) - return { file, summary } - }) - .filter((ref) => { - var summary = ref.summary; - - return includeAllSeverities || summary.hasCriticalSeverities; - }) - .sort(bySeverityScoreDesc) - - for (const { file, summary } of filesSeverities) { - const { icSeverities, deoptSeverities, codeStates } = summary - const { relativePath } = groups.get(file) - const rendered = this._renderFile({ - file - , relativePath - , icSeverities - , deoptSeverities - , codeStates - }) - rows.push(rendered) - } - return ( - React.createElement( 'div', { className: className }, - React.createElement( 'table', { cellSpacing: '0' }, - tableHeader, - React.createElement( 'tbody', null, rows ) - ) - ) - ) - } + function bySeverityScoreDesc(ref, ref$1) { + var s1 = ref.summary + var s2 = ref$1.summary - _renderTableHeader() { - const topHeaderClass = 'tc header-row pt2 pb1 ' - const subHeaderClass = 'pa1 pl2 pr2 subhead' - return ( - React.createElement( 'thead', null, - React.createElement( 'tr', null, - React.createElement( 'td', { className: topHeaderClass + ' ' }, "File"), - React.createElement( 'td', { colSpan: '3', className: topHeaderClass }, "Optimizations"), - React.createElement( 'td', { colSpan: '3', className: topHeaderClass }, "Deoptimizations"), - React.createElement( 'td', { colSpan: '3', className: topHeaderClass }, "Inline Caches") - ), - React.createElement( 'tr', null, - React.createElement( 'td', { className: subHeaderClass }), - React.createElement( 'td', { className: subHeaderClass }, "Optimized"), - React.createElement( 'td', { className: subHeaderClass }, "Optimizable"), - React.createElement( 'td', { className: subHeaderClass }, "Compiled"), - React.createElement( 'td', { className: subHeaderClass }, "Severity 1"), - React.createElement( 'td', { className: subHeaderClass }, "Severity 2"), - React.createElement( 'td', { className: subHeaderClass }, "Severity 3"), - React.createElement( 'td', { className: subHeaderClass }, "Severity 1"), - React.createElement( 'td', { className: subHeaderClass }, "Severity 2"), - React.createElement( 'td', { className: subHeaderClass }, "Severity 3") - ) - ) - ) - } + return s1.severityScore < s2.severityScore ? 1 : -1 + } - _renderFile(ref) { - var file = ref.file; - var relativePath = ref.relativePath; - var deoptSeverities = ref.deoptSeverities; - var icSeverities = ref.icSeverities; - var codeStates = ref.codeStates; - - const { selectedFile } = this.props - - // Optimized = 3, Compile = 0, but we show them in order of serverity, so we reverse - const codeColumns = coloredTds(codeStates.reverse()) - const deoptColumns = coloredTds(deoptSeverities.slice(1)) - const icColumns = coloredTds(icSeverities.slice(1)) - - const onfileClicked = this._onfileClicked.bind(this, file) - const selectedClass = file === selectedFile ? 'bg-light-yellow' : '' - return ( - React.createElement( 'tr', { key: relativePath, className: 'normalrow ' + selectedClass }, - React.createElement( 'td', { class: 'underlined' }, - React.createElement( 'a', { className: 'items pl2 pr2', href: '#', onClick: onfileClicked }, - relativePath - ) - ), - codeColumns, - deoptColumns, - icColumns - ) - ) - } + class FilesView extends Component { + constructor(props) { + super(props) + const { onfileClicked } = props + assert.equal( + typeof onfileClicked, + 'function', + 'need to pass onfileClicked function' + ) + } - _onfileClicked(file) { - const { onfileClicked } = this.props - onfileClicked(file) - } -} - -module.exports = { FilesView } - -},{"../../lib/grouping/summarize-file":60,"assert":8,"react":46}],4:[function(require,module,exports){ -'use strict' - -const React = require('react') -const { Component } = React -const scrollIntoView = require('scroll-into-view-if-needed') - -const assert = require('assert') -const { nameIcState, severityIcState } = require('../../lib/log-processing/ic-state') -const { - nameOptimizationState - , severityOfOptimizationState -} = require('../../lib/log-processing/optimization-state') -const { MIN_SEVERITY } = require('../../lib/severities') - -const severityClassNames = [ - 'green i' - , 'blue' - , 'red b' -] - -const OPT_TAB_IDX = 0 -const DEOPT_TAB_IDX = 1 -const ICS_TAB_IDX = 2 - -class SummaryView extends Component { - constructor(props) { - super(props) - const { ics, icLocations, deopts, deoptLocations, onsummaryClicked, ontabHeaderClicked } = props - - assert(ics == null || icLocations != null, 'need to provide locations for ics') - assert(deopts == null || deoptLocations != null, 'need to provide locations for deopts') - assert.equal(typeof onsummaryClicked, 'function', 'need to pass onsummaryClicked function') - assert.equal(typeof ontabHeaderClicked, 'function', 'need to pass ontabHeaderClicked function') - - this._bind() - } + render() { + const { + groups, + includeAllSeverities, + className = '', + } = this.props + const tableHeader = this._renderTableHeader() + const rows = [] + const filesSeverities = Array.from(groups) + .map((ref) => { + var file = ref[0] + var info = ref[1] + + const { deopts, ics, codes } = info + const summary = summarizeFile({ ics, deopts, codes }) + return { file, summary } + }) + .filter((ref) => { + var summary = ref.summary + + return includeAllSeverities || summary.hasCriticalSeverities + }) + .sort(bySeverityScoreDesc) + + for (const { file, summary } of filesSeverities) { + const { icSeverities, deoptSeverities, codeStates } = summary + const { relativePath } = groups.get(file) + const rendered = this._renderFile({ + file, + relativePath, + icSeverities, + deoptSeverities, + codeStates, + }) + rows.push(rendered) + } + return React.createElement( + 'div', + { className: className }, + React.createElement( + 'table', + { cellSpacing: '0' }, + tableHeader, + React.createElement('tbody', null, rows) + ) + ) + } - _bind() { - this._renderIc = this._renderIc.bind(this) - this._renderDeopt = this._renderDeopt.bind(this) - this._renderCode = this._renderCode.bind(this) - } + _renderTableHeader() { + const topHeaderClass = 'tc header-row pt2 pb1 ' + const subHeaderClass = 'pa1 pl2 pr2 subhead' + return React.createElement( + 'thead', + null, + React.createElement( + 'tr', + null, + React.createElement( + 'td', + { className: topHeaderClass + ' ' }, + 'File' + ), + React.createElement( + 'td', + { colSpan: '3', className: topHeaderClass }, + 'Optimizations' + ), + React.createElement( + 'td', + { colSpan: '3', className: topHeaderClass }, + 'Deoptimizations' + ), + React.createElement( + 'td', + { colSpan: '3', className: topHeaderClass }, + 'Inline Caches' + ) + ), + React.createElement( + 'tr', + null, + React.createElement('td', { className: subHeaderClass }), + React.createElement( + 'td', + { className: subHeaderClass }, + 'Optimized' + ), + React.createElement( + 'td', + { className: subHeaderClass }, + 'Optimizable' + ), + React.createElement( + 'td', + { className: subHeaderClass }, + 'Compiled' + ), + React.createElement( + 'td', + { className: subHeaderClass }, + 'Severity 1' + ), + React.createElement( + 'td', + { className: subHeaderClass }, + 'Severity 2' + ), + React.createElement( + 'td', + { className: subHeaderClass }, + 'Severity 3' + ), + React.createElement( + 'td', + { className: subHeaderClass }, + 'Severity 1' + ), + React.createElement( + 'td', + { className: subHeaderClass }, + 'Severity 2' + ), + React.createElement( + 'td', + { className: subHeaderClass }, + 'Severity 3' + ) + ) + ) + } - _maybeScrollIntoView() { - const { selectedLocation } = this.props - if (selectedLocation == null) { return } - const summary = document.getElementById(`summary-location-${selectedLocation}`) - if (summary == null) { return } - scrollIntoView(summary, { behavior: 'smooth', scrollMode: 'if-needed' }) - } + _renderFile(ref) { + var file = ref.file + var relativePath = ref.relativePath + var deoptSeverities = ref.deoptSeverities + var icSeverities = ref.icSeverities + var codeStates = ref.codeStates + + const { selectedFile } = this.props + + // Optimized = 3, Compile = 0, but we show them in order of serverity, so we reverse + const codeColumns = coloredTds(codeStates.reverse()) + const deoptColumns = coloredTds(deoptSeverities.slice(1)) + const icColumns = coloredTds(icSeverities.slice(1)) + + const onfileClicked = this._onfileClicked.bind(this, file) + const selectedClass = + file === selectedFile ? 'bg-light-yellow' : '' + return React.createElement( + 'tr', + { key: relativePath, className: 'normalrow ' + selectedClass }, + React.createElement( + 'td', + { class: 'underlined' }, + React.createElement( + 'a', + { + className: 'items pl2 pr2', + href: '#', + onClick: onfileClicked, + }, + relativePath + ) + ), + codeColumns, + deoptColumns, + icColumns + ) + } - componentDidMount() { - this._maybeScrollIntoView() - } + _onfileClicked(file) { + const { onfileClicked } = this.props + onfileClicked(file) + } + } - componentDidUpdate() { - this._maybeScrollIntoView() - } + module.exports = { FilesView } + }, + { '../../lib/grouping/summarize-file': 60, assert: 8, react: 46 }, + ], + 4: [ + function (require, module, exports) { + 'use strict' + + const React = require('react') + const { Component } = React + const scrollIntoView = require('scroll-into-view-if-needed') + + const assert = require('assert') + const { + nameIcState, + severityIcState, + } = require('../../lib/log-processing/ic-state') + const { + nameOptimizationState, + severityOfOptimizationState, + } = require('../../lib/log-processing/optimization-state') + const { MIN_SEVERITY } = require('../../lib/severities') + + const severityClassNames = ['green i', 'blue', 'red b'] + + const OPT_TAB_IDX = 0 + const DEOPT_TAB_IDX = 1 + const ICS_TAB_IDX = 2 + + class SummaryView extends Component { + constructor(props) { + super(props) + const { + ics, + icLocations, + deopts, + deoptLocations, + onsummaryClicked, + ontabHeaderClicked, + } = props + + assert( + ics == null || icLocations != null, + 'need to provide locations for ics' + ) + assert( + deopts == null || deoptLocations != null, + 'need to provide locations for deopts' + ) + assert.equal( + typeof onsummaryClicked, + 'function', + 'need to pass onsummaryClicked function' + ) + assert.equal( + typeof ontabHeaderClicked, + 'function', + 'need to pass ontabHeaderClicked function' + ) + + this._bind() + } - render() { - const { - className = '' - , ics - , icLocations - , deopts - , deoptLocations - , codes - , codeLocations - , selectedTabIdx - } = this.props - const renderedDeopts = this._renderDeopts(deopts, deoptLocations, selectedTabIdx === DEOPT_TAB_IDX) - const renderedIcs = this._renderIcs(ics, icLocations, selectedTabIdx === ICS_TAB_IDX) - const renderedCodes = this._renderCodes(codes, codeLocations, selectedTabIdx === OPT_TAB_IDX) - return ( - React.createElement( 'div', { className: className }, - React.createElement( 'div', { className: 'flex flex-row' }, - this._renderTabHeader('Optimizations', OPT_TAB_IDX), - this._renderTabHeader('Deoptimizations', DEOPT_TAB_IDX), - this._renderTabHeader('Incline Caches', ICS_TAB_IDX) - ), - React.createElement( 'div', null, - renderedCodes, - renderedDeopts, - renderedIcs - ) - ) - ) - } + _bind() { + this._renderIc = this._renderIc.bind(this) + this._renderDeopt = this._renderDeopt.bind(this) + this._renderCode = this._renderCode.bind(this) + } - /* - * Tabs - */ + _maybeScrollIntoView() { + const { selectedLocation } = this.props + if (selectedLocation == null) { + return + } + const summary = document.getElementById( + `summary-location-${selectedLocation}` + ) + if (summary == null) { + return + } + scrollIntoView(summary, { + behavior: 'smooth', + scrollMode: 'if-needed', + }) + } - _renderTabHeader(label, idx) { - const { selectedTabIdx } = this.props - const selected = idx === selectedTabIdx - const baseClass = 'flex flex-column ttu dib link pa3 bt outline-0 tab-header' - const selectedClass = 'b--blue blue' - const unselectedClass = 'white b--white' - const className = selected ? `${baseClass} ${selectedClass}` : `${baseClass} ${unselectedClass}` + componentDidMount() { + this._maybeScrollIntoView() + } - return React.createElement( 'a', { className: className, href: '#', onClick: () => this._ontabHeaderClicked(idx) }, label) - } + componentDidUpdate() { + this._maybeScrollIntoView() + } - _renderDataPoint(data, locations, renderDetails) { - const { selectedLocation, includeAllSeverities, relativePath } = this.props - if (locations.length === 0) { return React.createElement( 'h4', { className: 'ml4' }, "None") } - const rendered = [] - for (const loc of locations) { - const info = data.get(loc) - if (!includeAllSeverities && info.severity <= MIN_SEVERITY) { continue } - - const highlightedClass = selectedLocation === info.id ? 'bg-light-yellow' : 'bg-light-green' - const className = `${highlightedClass} ba br2 bw1 ma3 pa2` - rendered.push( - React.createElement( 'div', { className: className, key: info.id }, - this._summary(info, relativePath), - renderDetails(info) - ) - ) - } - return rendered - } + render() { + const { + className = '', + ics, + icLocations, + deopts, + deoptLocations, + codes, + codeLocations, + selectedTabIdx, + } = this.props + const renderedDeopts = this._renderDeopts( + deopts, + deoptLocations, + selectedTabIdx === DEOPT_TAB_IDX + ) + const renderedIcs = this._renderIcs( + ics, + icLocations, + selectedTabIdx === ICS_TAB_IDX + ) + const renderedCodes = this._renderCodes( + codes, + codeLocations, + selectedTabIdx === OPT_TAB_IDX + ) + return React.createElement( + 'div', + { className: className }, + React.createElement( + 'div', + { className: 'flex flex-row' }, + this._renderTabHeader('Optimizations', OPT_TAB_IDX), + this._renderTabHeader('Deoptimizations', DEOPT_TAB_IDX), + this._renderTabHeader('Incline Caches', ICS_TAB_IDX) + ), + React.createElement( + 'div', + null, + renderedCodes, + renderedDeopts, + renderedIcs + ) + ) + } - _renderIcs(ics, icLocations, selected) { - if (ics == null) { return null } - const className = selected ? '' : 'dn' - const rendered = this._renderDataPoint(ics, icLocations, this._renderIc) - return ( - React.createElement( 'div', { key: 'ics', className: className }, - rendered - ) - ) - } + /* + * Tabs + */ + + _renderTabHeader(label, idx) { + const { selectedTabIdx } = this.props + const selected = idx === selectedTabIdx + const baseClass = + 'flex flex-column ttu dib link pa3 bt outline-0 tab-header' + const selectedClass = 'b--blue blue' + const unselectedClass = 'white b--white' + const className = selected + ? `${baseClass} ${selectedClass}` + : `${baseClass} ${unselectedClass}` + + return React.createElement( + 'a', + { + className: className, + href: '#', + onClick: () => this._ontabHeaderClicked(idx), + }, + label + ) + } - _renderDeopts(deopts, deoptLocations, selected) { - if (deopts == null) { return null } - const className = selected ? '' : 'dn' - const rendered = this._renderDataPoint(deopts, deoptLocations, this._renderDeopt) - return ( - React.createElement( 'div', { key: 'deopts', className: className }, - rendered - ) - ) - } + _renderDataPoint(data, locations, renderDetails) { + const { + selectedLocation, + includeAllSeverities, + relativePath, + } = this.props + if (locations.length === 0) { + return React.createElement('h4', { className: 'ml4' }, 'None') + } + const rendered = [] + for (const loc of locations) { + const info = data.get(loc) + if (!includeAllSeverities && info.severity <= MIN_SEVERITY) { + continue + } - _renderCodes(codes, codeLocations, selected) { - if (codes == null) { return null } - const className = selected ? '' : 'dn' - const rendered = this._renderDataPoint(codes, codeLocations, this._renderCode) - return ( - React.createElement( 'div', { key: 'optimizations', className: className }, - rendered - ) - ) - } + const highlightedClass = + selectedLocation === info.id + ? 'bg-light-yellow' + : 'bg-light-green' + const className = `${highlightedClass} ba br2 bw1 ma3 pa2` + rendered.push( + React.createElement( + 'div', + { className: className, key: info.id }, + this._summary(info, relativePath), + renderDetails(info) + ) + ) + } + return rendered + } - _summary(info, relativePath) { - const { - id - , functionName - , line - , column - } = info - const locationEl = React.createElement( 'span', { className: 'dark-blue f5 mr2' }, id) - const onclicked = e => { - e.preventDefault() - e.stopPropagation() - this._onsummaryClicked(id) - } + _renderIcs(ics, icLocations, selected) { + if (ics == null) { + return null + } + const className = selected ? '' : 'dn' + const rendered = this._renderDataPoint( + ics, + icLocations, + this._renderIc + ) + return React.createElement( + 'div', + { key: 'ics', className: className }, + rendered + ) + } - const fullLoc = ( - React.createElement( 'a', { href: '#', className: 'i items', onClick: onclicked }, - functionName, " at ", relativePath, ":", line, ":", column - ) - ) - return ( - React.createElement( 'div', { id: 'summary-location-' + id }, - locationEl, - fullLoc - ) - ) - } + _renderDeopts(deopts, deoptLocations, selected) { + if (deopts == null) { + return null + } + const className = selected ? '' : 'dn' + const rendered = this._renderDataPoint( + deopts, + deoptLocations, + this._renderDeopt + ) + return React.createElement( + 'div', + { key: 'deopts', className: className }, + rendered + ) + } - _renderDeopt(info) { - const rows = info.updates.map((update, idx) => this._deoptRow(update, idx)) - return ( - React.createElement( 'table', { key: 'deopt:' + info.id }, - React.createElement( 'thead', { className: 'f5 b pt2' }, - React.createElement( 'tr', null, - React.createElement( 'td', { class: 'pt2 pr3 basegreen' }, "Timestamp"), - React.createElement( 'td', { class: 'pt2 pr3 basegreen' }, "Bailout"), - React.createElement( 'td', { class: 'pt2 pr3 basegreen' }, "Reason"), - React.createElement( 'td', { class: 'pt2 pr3 basegreen' }, "Inlined") - ) - ), - React.createElement( 'tbody', null, - rows - ) - ) - ) - } + _renderCodes(codes, codeLocations, selected) { + if (codes == null) { + return null + } + const className = selected ? '' : 'dn' + const rendered = this._renderDataPoint( + codes, + codeLocations, + this._renderCode + ) + return React.createElement( + 'div', + { key: 'optimizations', className: className }, + rendered + ) + } - _deoptRow(info) { - const { - inlined - , bailoutType - , deoptReason - , timestamp - , severity - } = info - const bailoutClassName = severityClassNames[severity - 1] - const timeStampMs = (timestamp / 1E3).toFixed() - return ( - React.createElement( 'tr', { key: timestamp }, - React.createElement( 'td', null, timeStampMs, "ms" ), - React.createElement( 'td', { className: bailoutClassName + ' pr3' }, bailoutType), - React.createElement( 'td', { className: 'pr3' }, deoptReason), - React.createElement( 'td', { className: 'gray pr3' }, inlined ? 'yes' : 'no') - ) - ) - } + _summary(info, relativePath) { + const { id, functionName, line, column } = info + const locationEl = React.createElement( + 'span', + { className: 'dark-blue f5 mr2' }, + id + ) + const onclicked = (e) => { + e.preventDefault() + e.stopPropagation() + this._onsummaryClicked(id) + } - _renderIc(info) { - const rows = info.updates.map((update, idx) => this._icRow(update, idx)) - return ( - React.createElement( 'table', { key: 'ic:' + info.id }, - React.createElement( 'thead', { className: 'f5 b ' }, - React.createElement( 'tr', null, - React.createElement( 'td', { class: 'pt2 pr3 basegreen' }, "Old State"), - React.createElement( 'td', { class: 'pt2 pr3 basegreen' }, "New State"), - React.createElement( 'td', { class: 'pt2 pr3 basegreen' }, "Key"), - React.createElement( 'td', { class: 'pt2 pr3 basegreen' }, "Map") - ) - ), - React.createElement( 'tbody', null, - rows - ) - ) - ) - } + const fullLoc = React.createElement( + 'a', + { href: '#', className: 'i items', onClick: onclicked }, + functionName, + ' at ', + relativePath, + ':', + line, + ':', + column + ) + return React.createElement( + 'div', + { id: 'summary-location-' + id }, + locationEl, + fullLoc + ) + } - _icRow(update, id) { - const { - oldState - , newState - , key - , map - } = update - const oldStateName = nameIcState(oldState) - const severityOldState = severityIcState(oldState) - const oldStateClassName = severityClassNames[severityOldState - 1] - - const newStateName = nameIcState(newState) - const severityNewState = severityIcState(newState) - const newStateClassName = severityClassNames[severityNewState - 1] - - const mapString = `0x${map}` - return ( - React.createElement( 'tr', { key: key + id }, - React.createElement( 'td', { className: oldStateClassName + ' pr3' }, oldStateName), - React.createElement( 'td', { className: newStateClassName + ' pr3' }, newStateName), - React.createElement( 'td', { className: 'black pr3' }, key), - React.createElement( 'td', { className: 'gray pr3' }, mapString) - ) - ) - } + _renderDeopt(info) { + const rows = info.updates.map((update, idx) => + this._deoptRow(update, idx) + ) + return React.createElement( + 'table', + { key: 'deopt:' + info.id }, + React.createElement( + 'thead', + { className: 'f5 b pt2' }, + React.createElement( + 'tr', + null, + React.createElement( + 'td', + { class: 'pt2 pr3 basegreen' }, + 'Timestamp' + ), + React.createElement( + 'td', + { class: 'pt2 pr3 basegreen' }, + 'Bailout' + ), + React.createElement( + 'td', + { class: 'pt2 pr3 basegreen' }, + 'Reason' + ), + React.createElement( + 'td', + { class: 'pt2 pr3 basegreen' }, + 'Inlined' + ) + ) + ), + React.createElement('tbody', null, rows) + ) + } - _renderCode(info) { - const rows = info.updates.map((update, idx) => this._codeRow(update, idx)) - return ( - React.createElement( 'table', { key: 'code:' + info.id }, - React.createElement( 'thead', { className: 'f5 b ' }, - React.createElement( 'tr', null, - React.createElement( 'td', { class: 'pt2 pr3 basegreen' }, "Timestamp"), - React.createElement( 'td', { class: 'pt2 pr3 basegreen' }, "Optimization State") - ) - ), - React.createElement( 'tbody', null, - rows - ) - ) - ) - } + _deoptRow(info) { + const { + inlined, + bailoutType, + deoptReason, + timestamp, + severity, + } = info + const bailoutClassName = severityClassNames[severity - 1] + const timeStampMs = (timestamp / 1e3).toFixed() + return React.createElement( + 'tr', + { key: timestamp }, + React.createElement('td', null, timeStampMs, 'ms'), + React.createElement( + 'td', + { className: bailoutClassName + ' pr3' }, + bailoutType + ), + React.createElement('td', { className: 'pr3' }, deoptReason), + React.createElement( + 'td', + { className: 'gray pr3' }, + inlined ? 'yes' : 'no' + ) + ) + } - _codeRow(info, id) { - const { timestamp, state } = info - const timeStampMs = (timestamp / 1E3).toFixed() - const codeState = nameOptimizationState(state) - const severity = severityOfOptimizationState(state) - const codeStateClassName = severityClassNames[severity - 1] - - return ( - React.createElement( 'tr', { key: timestamp }, - React.createElement( 'td', null, timeStampMs, "ms" ), - React.createElement( 'td', { className: codeStateClassName + ' pr3' }, codeState) - ) - ) - } + _renderIc(info) { + const rows = info.updates.map((update, idx) => + this._icRow(update, idx) + ) + return React.createElement( + 'table', + { key: 'ic:' + info.id }, + React.createElement( + 'thead', + { className: 'f5 b ' }, + React.createElement( + 'tr', + null, + React.createElement( + 'td', + { class: 'pt2 pr3 basegreen' }, + 'Old State' + ), + React.createElement( + 'td', + { class: 'pt2 pr3 basegreen' }, + 'New State' + ), + React.createElement( + 'td', + { class: 'pt2 pr3 basegreen' }, + 'Key' + ), + React.createElement( + 'td', + { class: 'pt2 pr3 basegreen' }, + 'Map' + ) + ) + ), + React.createElement('tbody', null, rows) + ) + } - /* - * Events - */ - _ontabHeaderClicked(idx) { - const { ontabHeaderClicked } = this.props - ontabHeaderClicked(idx) - } + _icRow(update, id) { + const { oldState, newState, key, map } = update + const oldStateName = nameIcState(oldState) + const severityOldState = severityIcState(oldState) + const oldStateClassName = severityClassNames[severityOldState - 1] + + const newStateName = nameIcState(newState) + const severityNewState = severityIcState(newState) + const newStateClassName = severityClassNames[severityNewState - 1] + + const mapString = `0x${map}` + return React.createElement( + 'tr', + { key: key + id }, + React.createElement( + 'td', + { className: oldStateClassName + ' pr3' }, + oldStateName + ), + React.createElement( + 'td', + { className: newStateClassName + ' pr3' }, + newStateName + ), + React.createElement('td', { className: 'black pr3' }, key), + React.createElement('td', { className: 'gray pr3' }, mapString) + ) + } - _onsummaryClicked(id) { - const { onsummaryClicked } = this.props - onsummaryClicked(id) - } + _renderCode(info) { + const rows = info.updates.map((update, idx) => + this._codeRow(update, idx) + ) + return React.createElement( + 'table', + { key: 'code:' + info.id }, + React.createElement( + 'thead', + { className: 'f5 b ' }, + React.createElement( + 'tr', + null, + React.createElement( + 'td', + { class: 'pt2 pr3 basegreen' }, + 'Timestamp' + ), + React.createElement( + 'td', + { class: 'pt2 pr3 basegreen' }, + 'Optimization State' + ) + ) + ), + React.createElement('tbody', null, rows) + ) + } - static get OPT_TAB_IDX() { return OPT_TAB_IDX } - static get DEOPT_TAB_IDX() { return DEOPT_TAB_IDX } - static get ICS_TAB_IDX() { return ICS_TAB_IDX } -} -module.exports = { - SummaryView -} - -},{"../../lib/log-processing/ic-state":64,"../../lib/log-processing/optimization-state":65,"../../lib/severities":68,"assert":8,"react":46,"scroll-into-view-if-needed":54}],5:[function(require,module,exports){ -'use strict' - -const React = require('react') -const { Component } = React - -const assert = require('assert') - -class ToolbarView extends Component { - constructor(props) { - super(props) - const { onincludeAllSeveritiesChanged, onhighlightCodeChanged } = props - assert.equal(typeof onincludeAllSeveritiesChanged, 'function', 'need to pass onincludeAllSeveritiesChanged function') - assert.equal(typeof onhighlightCodeChanged, 'function', 'need to pass onhighlightCodeChanged function') - this._bind() - } + _codeRow(info, id) { + const { timestamp, state } = info + const timeStampMs = (timestamp / 1e3).toFixed() + const codeState = nameOptimizationState(state) + const severity = severityOfOptimizationState(state) + const codeStateClassName = severityClassNames[severity - 1] + + return React.createElement( + 'tr', + { key: timestamp }, + React.createElement('td', null, timeStampMs, 'ms'), + React.createElement( + 'td', + { className: codeStateClassName + ' pr3' }, + codeState + ) + ) + } - _bind() { - this._onincludeAllSeveritiesToggled = this._onincludeAllSeveritiesToggled.bind(this) - this._onhighlightCodeToggled = this._onhighlightCodeToggled.bind(this) - } + /* + * Events + */ + _ontabHeaderClicked(idx) { + const { ontabHeaderClicked } = this.props + ontabHeaderClicked(idx) + } - render() { - const { className = '' } = this.props - return ( - React.createElement( 'div', { className: className }, - React.createElement( 'span', null, - this._renderHighlightCodeOption(), - this._renderSeverityOption() - ) - ) - ) - } + _onsummaryClicked(id) { + const { onsummaryClicked } = this.props + onsummaryClicked(id) + } - _renderSeverityOption() { - const { includeAllSeverities } = this.props - return ( - React.createElement( 'span', { className: 'white pr2 pl2' }, "Low Severities ", React.createElement( 'input', { - className: 'ml1 pointer', type: 'checkbox', defaultChecked: !!includeAllSeverities, onChange: this._onincludeAllSeveritiesToggled }) - ) - ) - } + static get OPT_TAB_IDX() { + return OPT_TAB_IDX + } + static get DEOPT_TAB_IDX() { + return DEOPT_TAB_IDX + } + static get ICS_TAB_IDX() { + return ICS_TAB_IDX + } + } + module.exports = { + SummaryView, + } + }, + { + '../../lib/log-processing/ic-state': 64, + '../../lib/log-processing/optimization-state': 65, + '../../lib/severities': 68, + assert: 8, + react: 46, + 'scroll-into-view-if-needed': 54, + }, + ], + 5: [ + function (require, module, exports) { + 'use strict' + + const React = require('react') + const { Component } = React + + const assert = require('assert') + + class ToolbarView extends Component { + constructor(props) { + super(props) + const { + onincludeAllSeveritiesChanged, + onhighlightCodeChanged, + } = props + assert.equal( + typeof onincludeAllSeveritiesChanged, + 'function', + 'need to pass onincludeAllSeveritiesChanged function' + ) + assert.equal( + typeof onhighlightCodeChanged, + 'function', + 'need to pass onhighlightCodeChanged function' + ) + this._bind() + } - _renderHighlightCodeOption() { - const { highlightCode } = this.props - return ( - React.createElement( 'span', { className: 'white pr2 pl2' }, "Highlight Code ", React.createElement( 'input', { - className: 'ml1 pointer', type: 'checkbox', defaultChecked: !!highlightCode, onChange: this._onhighlightCodeToggled }) - ) - ) - } + _bind() { + this._onincludeAllSeveritiesToggled = this._onincludeAllSeveritiesToggled.bind( + this + ) + this._onhighlightCodeToggled = this._onhighlightCodeToggled.bind( + this + ) + } - _onincludeAllSeveritiesToggled(e) { - const { onincludeAllSeveritiesChanged, includeAllSeverities } = this.props - onincludeAllSeveritiesChanged(!includeAllSeverities) - } + render() { + const { className = '' } = this.props + return React.createElement( + 'div', + { className: className }, + React.createElement( + 'span', + null, + this._renderHighlightCodeOption(), + this._renderSeverityOption() + ) + ) + } - _onhighlightCodeToggled(e) { - const { onhighlightCodeChanged, highlightCode } = this.props - onhighlightCodeChanged(!highlightCode) - } -} - -module.exports = { - ToolbarView -} - -},{"assert":8,"react":46}],6:[function(require,module,exports){ -'use strict' - -/* global location */ -const qs = require('qs') - -function parseNum(s) { - return s === '' ? null : parseInt(s) -} - -function parseBool(s) { - return s === 'true' -} - -function stateFromUrl() { - if (location.search == null || location.search.length < 2) { return null } - const query = location.search.slice(1) - const queryState = qs.parse(query) - const state = { - highlightCode : parseBool(queryState.highlightCode) - , includeAllSeverities : parseBool(queryState.includeAllSeverities) - , selectedFileIdx : parseNum(queryState.selectedFileIdx) - , selectedLocation : parseNum(queryState.selectedLocation) - , selectedTabIdx : parseNum(queryState.selectedTabIdx) - , selectedSummaryTabIdx : parseNum(queryState.selectedSummaryTabIdx) - } - return state -} - -function urlFromState(state) { - const rootUrl = location.origin - const path = location.pathname - const queryString = qs.stringify(state) - const url = `${rootUrl}${path}?${queryString}` - return url -} - -module.exports = { - stateFromUrl - , urlFromState -} - -},{"qs":20}],7:[function(require,module,exports){ -'use strict' - -/* global history */ - -const React = require('react') -const { Component } = React -const { render } = require('react-dom') -const { deoptigate } = require('../') -const { urlFromState, stateFromUrl } = require('./lib/query-state') - -const { ToolbarView } = require('./components/toolbar') -const { FilesView } = require('./components/files') -const { SummaryView } = require('./components/summary') -const { FileDetailsView } = require('./components/file-details') - -const FILES_TAB_IDX = 0 -const DETAILS_TAB_IDX = 1 - -function app() { - // makes React happy - document.body.innerHTML = '' - const el = document.createElement('div') - document.body.appendChild(el) - return el -} - -const initialState = { - selectedFile: null - , selectedLocation: null - , selectedSummaryTabIdx: SummaryView.OPT_TAB_IDX - , includeAllSeverities: false - , highlightCode: true - , selectedTabIdx: FILES_TAB_IDX -} - -class MainView extends Component { - constructor(props) { - super(props) - - const { groups } = props - this._indexedGroups = Array.from(groups) - - this._initialState = Object.assign(initialState, this._stateFromUrl()) - this.state = Object.assign({}, this._initialState) - - this._bind() - window.onpopstate = this._restoreStateFromHistory - } + _renderSeverityOption() { + const { includeAllSeverities } = this.props + return React.createElement( + 'span', + { className: 'white pr2 pl2' }, + 'Low Severities ', + React.createElement('input', { + className: 'ml1 pointer', + type: 'checkbox', + defaultChecked: !!includeAllSeverities, + onChange: this._onincludeAllSeveritiesToggled, + }) + ) + } - _bind() { - this._onlocationSelected = this._onlocationSelected.bind(this) - this._onsummaryTabIdxChanged = this._onsummaryTabIdxChanged.bind(this) - this._onincludeAllSeveritiesChanged = this._onincludeAllSeveritiesChanged.bind(this) - this._onhighlightCodeChanged = this._onhighlightCodeChanged.bind(this) - this._onfileClicked = this._onfileClicked.bind(this) - this._updateUrl = this._updateUrl.bind(this) - this._restoreStateFromHistory = this._restoreStateFromHistory.bind(this) - } + _renderHighlightCodeOption() { + const { highlightCode } = this.props + return React.createElement( + 'span', + { className: 'white pr2 pl2' }, + 'Highlight Code ', + React.createElement('input', { + className: 'ml1 pointer', + type: 'checkbox', + defaultChecked: !!highlightCode, + onChange: this._onhighlightCodeToggled, + }) + ) + } - render() { - const { includeAllSeverities, highlightCode } = this.state - - const tabs = this._renderTabs() - return ( - React.createElement( 'div', { className: 'center pa2' }, - React.createElement( 'div', { className: 'flex flex-row' }, - this._renderTabHeader('Files', FILES_TAB_IDX), - this._renderTabHeader('Details', DETAILS_TAB_IDX), - React.createElement( ToolbarView, { - className: 'flex flex-column self-center ml4 pl4 bl bw1 b--silver', includeAllSeverities: includeAllSeverities, highlightCode: highlightCode, onincludeAllSeveritiesChanged: this._onincludeAllSeveritiesChanged, onhighlightCodeChanged: this._onhighlightCodeChanged }) - ), - tabs - ) - ) - } + _onincludeAllSeveritiesToggled(e) { + const { + onincludeAllSeveritiesChanged, + includeAllSeverities, + } = this.props + onincludeAllSeveritiesChanged(!includeAllSeverities) + } - /* - * Tabs - */ + _onhighlightCodeToggled(e) { + const { onhighlightCodeChanged, highlightCode } = this.props + onhighlightCodeChanged(!highlightCode) + } + } - _renderTabHeader(label, idx) { - const { selectedTabIdx } = this.state - const selected = idx === selectedTabIdx - const baseClass = 'flex flex-column ttu dib link pa3 bt outline-0 tab-header' - const selectedClass = 'b--blue blue' - const unselectedClass = 'white b--white' - const className = selected ? `${baseClass} ${selectedClass}` : `${baseClass} ${unselectedClass}` + module.exports = { + ToolbarView, + } + }, + { assert: 8, react: 46 }, + ], + 6: [ + function (require, module, exports) { + 'use strict' - return React.createElement( 'a', { className: className, href: '#', onClick: () => this._ontabHeaderClicked(idx) }, label) - } + /* global location */ + const qs = require('qs') - _renderTabs() { - const { selectedTabIdx } = this.state - const files = this._renderFiles(selectedTabIdx === FILES_TAB_IDX) - const details = this._renderFileDetails(selectedTabIdx === DETAILS_TAB_IDX) - return ( - React.createElement( 'div', { className: 'flex flex-row vh-100 overflow-scroll' }, - files, - details - ) - ) - } + function parseNum(s) { + return s === '' ? null : parseInt(s) + } - /* - * Contents - */ - _renderFiles(selected) { - const { groups } = this.props - const { selectedFile, includeAllSeverities } = this.state - const display = selected ? 'flex' : 'dn' - const className = `${display} flex-row overflow-scroll pa2` - - return ( - React.createElement( FilesView, { - className: className, selectedFile: selectedFile, groups: groups, includeAllSeverities: includeAllSeverities, onfileClicked: this._onfileClicked }) - ) - } + function parseBool(s) { + return s === 'true' + } - _renderFileDetails(selected) { - const { groups } = this.props - const { - selectedFile - , selectedLocation - , selectedSummaryTabIdx - , includeAllSeverities - , highlightCode - } = this.state - const display = selected ? 'flex' : 'dn' - const className = `${display} flex-row w-100 ma2` - if (selectedFile == null || !groups.has(selectedFile)) { - return ( - React.createElement( 'div', { className: className }, "Please select a file in the Files table") - ) - } + function stateFromUrl() { + if (location.search == null || location.search.length < 2) { + return null + } + const query = location.search.slice(1) + const queryState = qs.parse(query) + const state = { + highlightCode: parseBool(queryState.highlightCode), + includeAllSeverities: parseBool(queryState.includeAllSeverities), + selectedFileIdx: parseNum(queryState.selectedFileIdx), + selectedLocation: parseNum(queryState.selectedLocation), + selectedTabIdx: parseNum(queryState.selectedTabIdx), + selectedSummaryTabIdx: parseNum(queryState.selectedSummaryTabIdx), + } + return state + } - return ( - React.createElement( FileDetailsView, { - groups: groups, selectedFile: selectedFile, selectedLocation: selectedLocation, selectedSummaryTabIdx: selectedSummaryTabIdx, includeAllSeverities: includeAllSeverities, highlightCode: highlightCode, className: className, onmarkerClicked: this._onlocationSelected, onsummaryClicked: this._onlocationSelected, onsummaryTabIdxChanged: this._onsummaryTabIdxChanged }) - ) - } + function urlFromState(state) { + const rootUrl = location.origin + const path = location.pathname + const queryString = qs.stringify(state) + const url = `${rootUrl}${path}?${queryString}` + return url + } - /* - * URL State - */ - _indexFromFile(file) { - for (var i = 0; i < this._indexedGroups.length; i++) { - const key = this._indexedGroups[i][0] - if (key === file) { return i } - } - return -1 - } + module.exports = { + stateFromUrl, + urlFromState, + } + }, + { qs: 20 }, + ], + 7: [ + function (require, module, exports) { + 'use strict' + + /* global history */ + + const React = require('react') + const { Component } = React + const { render } = require('react-dom') + const { deoptigate } = require('../') + const { urlFromState, stateFromUrl } = require('./lib/query-state') + + const { ToolbarView } = require('./components/toolbar') + const { FilesView } = require('./components/files') + const { SummaryView } = require('./components/summary') + const { FileDetailsView } = require('./components/file-details') + + const FILES_TAB_IDX = 0 + const DETAILS_TAB_IDX = 1 + + function app() { + // makes React happy + document.body.innerHTML = '' + const el = document.createElement('div') + document.body.appendChild(el) + return el + } - _fileFromIndex(idx) { - if (idx < 0) { return null } - if (this._indexedGroups[idx] == null) { return null } - return this._indexedGroups[idx][0] - } + const initialState = { + selectedFile: null, + selectedLocation: null, + selectedSummaryTabIdx: SummaryView.OPT_TAB_IDX, + includeAllSeverities: false, + highlightCode: true, + selectedTabIdx: FILES_TAB_IDX, + } - _updateUrl() { - const { - selectedFile - , selectedLocation - , includeAllSeverities - , highlightCode - , selectedTabIdx - , selectedSummaryTabIdx - } = this.state - - const state = { - selectedFileIdx: this._indexFromFile(selectedFile) - , selectedLocation - , includeAllSeverities - , highlightCode - , selectedTabIdx - , selectedSummaryTabIdx - } - try { - history.pushState(state, 'deoptigate', urlFromState(state)) - } catch (e) { - // some browsers like Safari block this in the name of security - // if we opened the index file directly, i.e. the page isn't served - } - } + class MainView extends Component { + constructor(props) { + super(props) - _restoreStateFromHistory(e) { - if (history.state == null) { return null } - - let { - selectedFileIdx - , selectedLocation - , includeAllSeverities - , highlightCode - , selectedTabIdx - , selectedSummaryTabIdx - } = history.state - if (selectedLocation === '') { selectedLocation = null } - - const selectedFile = this._fileFromIndex(selectedFileIdx) - const override = { - includeAllSeverities - , highlightCode - , selectedFile - , selectedTabIdx - , selectedLocation - , selectedSummaryTabIdx - } + const { groups } = props + this._indexedGroups = Array.from(groups) - this.setState(Object.assign(this.state, override)) - } + this._initialState = Object.assign( + initialState, + this._stateFromUrl() + ) + this.state = Object.assign({}, this._initialState) - _stateFromUrl() { - const state = stateFromUrl() - if (state == null) { return null } - const { - selectedFileIdx - , selectedLocation - , includeAllSeverities - , highlightCode - , selectedTabIdx - , selectedSummaryTabIdx - } = state - const selectedFile = this._fileFromIndex(selectedFileIdx) - return { - selectedFile - , selectedLocation - , includeAllSeverities - , highlightCode - , selectedTabIdx - , selectedSummaryTabIdx - } - } + this._bind() + window.onpopstate = this._restoreStateFromHistory + } - /* - * Events - */ - _ontabHeaderClicked(idx) { - this.setState(Object.assign(this.state, { selectedTabIdx: idx }), this._updateUrl) - } + _bind() { + this._onlocationSelected = this._onlocationSelected.bind(this) + this._onsummaryTabIdxChanged = this._onsummaryTabIdxChanged.bind( + this + ) + this._onincludeAllSeveritiesChanged = this._onincludeAllSeveritiesChanged.bind( + this + ) + this._onhighlightCodeChanged = this._onhighlightCodeChanged.bind( + this + ) + this._onfileClicked = this._onfileClicked.bind(this) + this._updateUrl = this._updateUrl.bind(this) + this._restoreStateFromHistory = this._restoreStateFromHistory.bind( + this + ) + } - _onlocationSelected(id) { - this.setState(Object.assign(this.state, { selectedLocation: id }), this._updateUrl) - } + render() { + const { includeAllSeverities, highlightCode } = this.state + + const tabs = this._renderTabs() + return React.createElement( + 'div', + { className: 'center pa2' }, + React.createElement( + 'div', + { className: 'flex flex-row' }, + this._renderTabHeader('Files', FILES_TAB_IDX), + this._renderTabHeader('Details', DETAILS_TAB_IDX), + React.createElement(ToolbarView, { + className: + 'flex flex-column self-center ml4 pl4 bl bw1 b--silver', + includeAllSeverities: includeAllSeverities, + highlightCode: highlightCode, + onincludeAllSeveritiesChanged: this + ._onincludeAllSeveritiesChanged, + onhighlightCodeChanged: this._onhighlightCodeChanged, + }) + ), + tabs + ) + } - _onsummaryTabIdxChanged(idx) { - this.setState(Object.assign(this.state, { selectedSummaryTabIdx: idx }), this._updateUrl) - } + /* + * Tabs + */ + + _renderTabHeader(label, idx) { + const { selectedTabIdx } = this.state + const selected = idx === selectedTabIdx + const baseClass = + 'flex flex-column ttu dib link pa3 bt outline-0 tab-header' + const selectedClass = 'b--blue blue' + const unselectedClass = 'white b--white' + const className = selected + ? `${baseClass} ${selectedClass}` + : `${baseClass} ${unselectedClass}` + + return React.createElement( + 'a', + { + className: className, + href: '#', + onClick: () => this._ontabHeaderClicked(idx), + }, + label + ) + } - _onincludeAllSeveritiesChanged(includeAllSeverities) { - this.setState(Object.assign(this.state, { includeAllSeverities, selectedLocation: null }), this._updateUrl) - } + _renderTabs() { + const { selectedTabIdx } = this.state + const files = this._renderFiles(selectedTabIdx === FILES_TAB_IDX) + const details = this._renderFileDetails( + selectedTabIdx === DETAILS_TAB_IDX + ) + return React.createElement( + 'div', + { className: 'flex flex-row vh-100 overflow-scroll' }, + files, + details + ) + } - _onhighlightCodeChanged(highlightCode) { - this.setState(Object.assign(this.state, { highlightCode }), this._updateUrl) - } + /* + * Contents + */ + _renderFiles(selected) { + const { groups } = this.props + const { selectedFile, includeAllSeverities } = this.state + const display = selected ? 'flex' : 'dn' + const className = `${display} flex-row overflow-scroll pa2` + + return React.createElement(FilesView, { + className: className, + selectedFile: selectedFile, + groups: groups, + includeAllSeverities: includeAllSeverities, + onfileClicked: this._onfileClicked, + }) + } - _onfileClicked(file) { - this.setState(Object.assign(this.state, { - selectedFile: file - , selectedLocation: null - // auto open details view when file is selected - , selectedTabIdx: DETAILS_TAB_IDX - }), this._updateUrl) - } -} - -async function deoptigateRender(groupedByFile) { - try { - const groupedByFileAndLocation = deoptigate(groupedByFile) - - render( - React.createElement( MainView, { groups: groupedByFileAndLocation }) - , app() - ) - } catch (err) { - console.error(err) - } -} - -module.exports = deoptigateRender - -},{"../":57,"./components/file-details":2,"./components/files":3,"./components/summary":4,"./components/toolbar":5,"./lib/query-state":6,"react":46,"react-dom":26}],8:[function(require,module,exports){ -(function (global){ -'use strict'; - -// compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js -// original notice: - -/*! - * The buffer module from node.js, for the browser. - * - * @author Feross Aboukhadijeh - * @license MIT - */ -function compare(a, b) { - if (a === b) { - return 0; - } + _renderFileDetails(selected) { + const { groups } = this.props + const { + selectedFile, + selectedLocation, + selectedSummaryTabIdx, + includeAllSeverities, + highlightCode, + } = this.state + const display = selected ? 'flex' : 'dn' + const className = `${display} flex-row w-100 ma2` + if (selectedFile == null || !groups.has(selectedFile)) { + return React.createElement( + 'div', + { className: className }, + 'Please select a file in the Files table' + ) + } - var x = a.length; - var y = b.length; + return React.createElement(FileDetailsView, { + groups: groups, + selectedFile: selectedFile, + selectedLocation: selectedLocation, + selectedSummaryTabIdx: selectedSummaryTabIdx, + includeAllSeverities: includeAllSeverities, + highlightCode: highlightCode, + className: className, + onmarkerClicked: this._onlocationSelected, + onsummaryClicked: this._onlocationSelected, + onsummaryTabIdxChanged: this._onsummaryTabIdxChanged, + }) + } - for (var i = 0, len = Math.min(x, y); i < len; ++i) { - if (a[i] !== b[i]) { - x = a[i]; - y = b[i]; - break; - } - } + /* + * URL State + */ + _indexFromFile(file) { + for (var i = 0; i < this._indexedGroups.length; i++) { + const key = this._indexedGroups[i][0] + if (key === file) { + return i + } + } + return -1 + } - if (x < y) { - return -1; - } - if (y < x) { - return 1; - } - return 0; -} -function isBuffer(b) { - if (global.Buffer && typeof global.Buffer.isBuffer === 'function') { - return global.Buffer.isBuffer(b); - } - return !!(b != null && b._isBuffer); -} - -// based on node assert, original notice: - -// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 -// -// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! -// -// Originally from narwhal.js (http://narwhaljs.org) -// Copyright (c) 2009 Thomas Robinson <280north.com> -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the 'Software'), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -var util = require('util/'); -var hasOwn = Object.prototype.hasOwnProperty; -var pSlice = Array.prototype.slice; -var functionsHaveNames = (function () { - return function foo() {}.name === 'foo'; -}()); -function pToString (obj) { - return Object.prototype.toString.call(obj); -} -function isView(arrbuf) { - if (isBuffer(arrbuf)) { - return false; - } - if (typeof global.ArrayBuffer !== 'function') { - return false; - } - if (typeof ArrayBuffer.isView === 'function') { - return ArrayBuffer.isView(arrbuf); - } - if (!arrbuf) { - return false; - } - if (arrbuf instanceof DataView) { - return true; - } - if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) { - return true; - } - return false; -} -// 1. The assert module provides functions that throw -// AssertionError's when particular conditions are not met. The -// assert module must conform to the following interface. - -var assert = module.exports = ok; - -// 2. The AssertionError is defined in assert. -// new assert.AssertionError({ message: message, -// actual: actual, -// expected: expected }) - -var regex = /\s*function\s+([^\(\s]*)\s*/; -// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js -function getName(func) { - if (!util.isFunction(func)) { - return; - } - if (functionsHaveNames) { - return func.name; - } - var str = func.toString(); - var match = str.match(regex); - return match && match[1]; -} -assert.AssertionError = function AssertionError(options) { - this.name = 'AssertionError'; - this.actual = options.actual; - this.expected = options.expected; - this.operator = options.operator; - if (options.message) { - this.message = options.message; - this.generatedMessage = false; - } else { - this.message = getMessage(this); - this.generatedMessage = true; - } - var stackStartFunction = options.stackStartFunction || fail; - if (Error.captureStackTrace) { - Error.captureStackTrace(this, stackStartFunction); - } else { - // non v8 browsers so we can have a stacktrace - var err = new Error(); - if (err.stack) { - var out = err.stack; - - // try to strip useless frames - var fn_name = getName(stackStartFunction); - var idx = out.indexOf('\n' + fn_name); - if (idx >= 0) { - // once we have located the function frame - // we need to strip out everything before it (and its line) - var next_line = out.indexOf('\n', idx + 1); - out = out.substring(next_line + 1); - } + _fileFromIndex(idx) { + if (idx < 0) { + return null + } + if (this._indexedGroups[idx] == null) { + return null + } + return this._indexedGroups[idx][0] + } - this.stack = out; - } - } -}; + _updateUrl() { + const { + selectedFile, + selectedLocation, + includeAllSeverities, + highlightCode, + selectedTabIdx, + selectedSummaryTabIdx, + } = this.state + + const state = { + selectedFileIdx: this._indexFromFile(selectedFile), + selectedLocation, + includeAllSeverities, + highlightCode, + selectedTabIdx, + selectedSummaryTabIdx, + } + try { + history.pushState(state, 'deoptigate', urlFromState(state)) + } catch (e) { + // some browsers like Safari block this in the name of security + // if we opened the index file directly, i.e. the page isn't served + } + } -// assert.AssertionError instanceof Error -util.inherits(assert.AssertionError, Error); + _restoreStateFromHistory(e) { + if (history.state == null) { + return null + } -function truncate(s, n) { - if (typeof s === 'string') { - return s.length < n ? s : s.slice(0, n); - } else { - return s; - } -} -function inspect(something) { - if (functionsHaveNames || !util.isFunction(something)) { - return util.inspect(something); - } - var rawname = getName(something); - var name = rawname ? ': ' + rawname : ''; - return '[Function' + name + ']'; -} -function getMessage(self) { - return truncate(inspect(self.actual), 128) + ' ' + - self.operator + ' ' + - truncate(inspect(self.expected), 128); -} - -// At present only the three keys mentioned above are used and -// understood by the spec. Implementations or sub modules can pass -// other keys to the AssertionError's constructor - they will be -// ignored. - -// 3. All of the following functions must throw an AssertionError -// when a corresponding condition is not met, with a message that -// may be undefined if not provided. All assertion methods provide -// both the actual and expected values to the assertion error for -// display purposes. - -function fail(actual, expected, message, operator, stackStartFunction) { - throw new assert.AssertionError({ - message: message, - actual: actual, - expected: expected, - operator: operator, - stackStartFunction: stackStartFunction - }); -} - -// EXTENSION! allows for well behaved errors defined elsewhere. -assert.fail = fail; - -// 4. Pure assertion tests whether a value is truthy, as determined -// by !!guard. -// assert.ok(guard, message_opt); -// This statement is equivalent to assert.equal(true, !!guard, -// message_opt);. To test strictly for the value true, use -// assert.strictEqual(true, guard, message_opt);. - -function ok(value, message) { - if (!value) fail(value, true, message, '==', assert.ok); -} -assert.ok = ok; - -// 5. The equality assertion tests shallow, coercive equality with -// ==. -// assert.equal(actual, expected, message_opt); - -assert.equal = function equal(actual, expected, message) { - if (actual != expected) fail(actual, expected, message, '==', assert.equal); -}; - -// 6. The non-equality assertion tests for whether two objects are not equal -// with != assert.notEqual(actual, expected, message_opt); - -assert.notEqual = function notEqual(actual, expected, message) { - if (actual == expected) { - fail(actual, expected, message, '!=', assert.notEqual); - } -}; - -// 7. The equivalence assertion tests a deep equality relation. -// assert.deepEqual(actual, expected, message_opt); + let { + selectedFileIdx, + selectedLocation, + includeAllSeverities, + highlightCode, + selectedTabIdx, + selectedSummaryTabIdx, + } = history.state + if (selectedLocation === '') { + selectedLocation = null + } -assert.deepEqual = function deepEqual(actual, expected, message) { - if (!_deepEqual(actual, expected, false)) { - fail(actual, expected, message, 'deepEqual', assert.deepEqual); - } -}; + const selectedFile = this._fileFromIndex(selectedFileIdx) + const override = { + includeAllSeverities, + highlightCode, + selectedFile, + selectedTabIdx, + selectedLocation, + selectedSummaryTabIdx, + } -assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { - if (!_deepEqual(actual, expected, true)) { - fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual); - } -}; - -function _deepEqual(actual, expected, strict, memos) { - // 7.1. All identical values are equivalent, as determined by ===. - if (actual === expected) { - return true; - } else if (isBuffer(actual) && isBuffer(expected)) { - return compare(actual, expected) === 0; - - // 7.2. If the expected value is a Date object, the actual value is - // equivalent if it is also a Date object that refers to the same time. - } else if (util.isDate(actual) && util.isDate(expected)) { - return actual.getTime() === expected.getTime(); - - // 7.3 If the expected value is a RegExp object, the actual value is - // equivalent if it is also a RegExp object with the same source and - // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). - } else if (util.isRegExp(actual) && util.isRegExp(expected)) { - return actual.source === expected.source && - actual.global === expected.global && - actual.multiline === expected.multiline && - actual.lastIndex === expected.lastIndex && - actual.ignoreCase === expected.ignoreCase; - - // 7.4. Other pairs that do not both pass typeof value == 'object', - // equivalence is determined by ==. - } else if ((actual === null || typeof actual !== 'object') && - (expected === null || typeof expected !== 'object')) { - return strict ? actual === expected : actual == expected; - - // If both values are instances of typed arrays, wrap their underlying - // ArrayBuffers in a Buffer each to increase performance - // This optimization requires the arrays to have the same type as checked by - // Object.prototype.toString (aka pToString). Never perform binary - // comparisons for Float*Arrays, though, since e.g. +0 === -0 but their - // bit patterns are not identical. - } else if (isView(actual) && isView(expected) && - pToString(actual) === pToString(expected) && - !(actual instanceof Float32Array || - actual instanceof Float64Array)) { - return compare(new Uint8Array(actual.buffer), - new Uint8Array(expected.buffer)) === 0; - - // 7.5 For all other Object pairs, including Array objects, equivalence is - // determined by having the same number of owned properties (as verified - // with Object.prototype.hasOwnProperty.call), the same set of keys - // (although not necessarily the same order), equivalent values for every - // corresponding key, and an identical 'prototype' property. Note: this - // accounts for both named and indexed properties on Arrays. - } else if (isBuffer(actual) !== isBuffer(expected)) { - return false; - } else { - memos = memos || {actual: [], expected: []}; + this.setState(Object.assign(this.state, override)) + } - var actualIndex = memos.actual.indexOf(actual); - if (actualIndex !== -1) { - if (actualIndex === memos.expected.indexOf(expected)) { - return true; - } - } + _stateFromUrl() { + const state = stateFromUrl() + if (state == null) { + return null + } + const { + selectedFileIdx, + selectedLocation, + includeAllSeverities, + highlightCode, + selectedTabIdx, + selectedSummaryTabIdx, + } = state + const selectedFile = this._fileFromIndex(selectedFileIdx) + return { + selectedFile, + selectedLocation, + includeAllSeverities, + highlightCode, + selectedTabIdx, + selectedSummaryTabIdx, + } + } - memos.actual.push(actual); - memos.expected.push(expected); + /* + * Events + */ + _ontabHeaderClicked(idx) { + this.setState( + Object.assign(this.state, { selectedTabIdx: idx }), + this._updateUrl + ) + } - return objEquiv(actual, expected, strict, memos); - } -} - -function isArguments(object) { - return Object.prototype.toString.call(object) == '[object Arguments]'; -} - -function objEquiv(a, b, strict, actualVisitedObjects) { - if (a === null || a === undefined || b === null || b === undefined) - return false; - // if one is a primitive, the other must be same - if (util.isPrimitive(a) || util.isPrimitive(b)) - return a === b; - if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) - return false; - var aIsArgs = isArguments(a); - var bIsArgs = isArguments(b); - if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) - return false; - if (aIsArgs) { - a = pSlice.call(a); - b = pSlice.call(b); - return _deepEqual(a, b, strict); - } - var ka = objectKeys(a); - var kb = objectKeys(b); - var key, i; - // having the same number of owned properties (keys incorporates - // hasOwnProperty) - if (ka.length !== kb.length) - return false; - //the same set of keys (although not necessarily the same order), - ka.sort(); - kb.sort(); - //~~~cheap key test - for (i = ka.length - 1; i >= 0; i--) { - if (ka[i] !== kb[i]) - return false; - } - //equivalent values for every corresponding key, and - //~~~possibly expensive deep test - for (i = ka.length - 1; i >= 0; i--) { - key = ka[i]; - if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects)) - return false; - } - return true; -} + _onlocationSelected(id) { + this.setState( + Object.assign(this.state, { selectedLocation: id }), + this._updateUrl + ) + } -// 8. The non-equivalence assertion tests for any deep inequality. -// assert.notDeepEqual(actual, expected, message_opt); + _onsummaryTabIdxChanged(idx) { + this.setState( + Object.assign(this.state, { selectedSummaryTabIdx: idx }), + this._updateUrl + ) + } -assert.notDeepEqual = function notDeepEqual(actual, expected, message) { - if (_deepEqual(actual, expected, false)) { - fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); - } -}; + _onincludeAllSeveritiesChanged(includeAllSeverities) { + this.setState( + Object.assign(this.state, { + includeAllSeverities, + selectedLocation: null, + }), + this._updateUrl + ) + } -assert.notDeepStrictEqual = notDeepStrictEqual; -function notDeepStrictEqual(actual, expected, message) { - if (_deepEqual(actual, expected, true)) { - fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual); - } -} + _onhighlightCodeChanged(highlightCode) { + this.setState( + Object.assign(this.state, { highlightCode }), + this._updateUrl + ) + } + _onfileClicked(file) { + this.setState( + Object.assign(this.state, { + selectedFile: file, + selectedLocation: null, + // auto open details view when file is selected + selectedTabIdx: DETAILS_TAB_IDX, + }), + this._updateUrl + ) + } + } -// 9. The strict equality assertion tests strict equality, as determined by ===. -// assert.strictEqual(actual, expected, message_opt); + async function deoptigateRender(groupedByFile) { + try { + const groupedByFileAndLocation = deoptigate(groupedByFile) + + render( + React.createElement(MainView, { + groups: groupedByFileAndLocation, + }), + app() + ) + } catch (err) { + console.error(err) + } + } -assert.strictEqual = function strictEqual(actual, expected, message) { - if (actual !== expected) { - fail(actual, expected, message, '===', assert.strictEqual); - } -}; + module.exports = deoptigateRender + }, + { + '../': 57, + './components/file-details': 2, + './components/files': 3, + './components/summary': 4, + './components/toolbar': 5, + './lib/query-state': 6, + react: 46, + 'react-dom': 26, + }, + ], + 8: [ + function (require, module, exports) { + ;(function (global) { + 'use strict' + + // compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js + // original notice: + + /*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ + function compare(a, b) { + if (a === b) { + return 0 + } -// 10. The strict non-equality assertion tests for strict inequality, as -// determined by !==. assert.notStrictEqual(actual, expected, message_opt); + var x = a.length + var y = b.length -assert.notStrictEqual = function notStrictEqual(actual, expected, message) { - if (actual === expected) { - fail(actual, expected, message, '!==', assert.notStrictEqual); - } -}; + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } -function expectedException(actual, expected) { - if (!actual || !expected) { - return false; - } + if (x < y) { + return -1 + } + if (y < x) { + return 1 + } + return 0 + } + function isBuffer(b) { + if ( + global.Buffer && + typeof global.Buffer.isBuffer === 'function' + ) { + return global.Buffer.isBuffer(b) + } + return !!(b != null && b._isBuffer) + } - if (Object.prototype.toString.call(expected) == '[object RegExp]') { - return expected.test(actual); - } + // based on node assert, original notice: + + // http://wiki.commonjs.org/wiki/Unit_Testing/1.0 + // + // THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! + // + // Originally from narwhal.js (http://narwhaljs.org) + // Copyright (c) 2009 Thomas Robinson <280north.com> + // + // Permission is hereby granted, free of charge, to any person obtaining a copy + // of this software and associated documentation files (the 'Software'), to + // deal in the Software without restriction, including without limitation the + // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + // sell copies of the Software, and to permit persons to whom the Software is + // furnished to do so, subject to the following conditions: + // + // The above copyright notice and this permission notice shall be included in + // all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + // AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + var util = require('util/') + var hasOwn = Object.prototype.hasOwnProperty + var pSlice = Array.prototype.slice + var functionsHaveNames = (function () { + return function foo() {}.name === 'foo' + })() + function pToString(obj) { + return Object.prototype.toString.call(obj) + } + function isView(arrbuf) { + if (isBuffer(arrbuf)) { + return false + } + if (typeof global.ArrayBuffer !== 'function') { + return false + } + if (typeof ArrayBuffer.isView === 'function') { + return ArrayBuffer.isView(arrbuf) + } + if (!arrbuf) { + return false + } + if (arrbuf instanceof DataView) { + return true + } + if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) { + return true + } + return false + } + // 1. The assert module provides functions that throw + // AssertionError's when particular conditions are not met. The + // assert module must conform to the following interface. + + var assert = (module.exports = ok) + + // 2. The AssertionError is defined in assert. + // new assert.AssertionError({ message: message, + // actual: actual, + // expected: expected }) + + var regex = /\s*function\s+([^\(\s]*)\s*/ + // based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js + function getName(func) { + if (!util.isFunction(func)) { + return + } + if (functionsHaveNames) { + return func.name + } + var str = func.toString() + var match = str.match(regex) + return match && match[1] + } + assert.AssertionError = function AssertionError(options) { + this.name = 'AssertionError' + this.actual = options.actual + this.expected = options.expected + this.operator = options.operator + if (options.message) { + this.message = options.message + this.generatedMessage = false + } else { + this.message = getMessage(this) + this.generatedMessage = true + } + var stackStartFunction = options.stackStartFunction || fail + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction) + } else { + // non v8 browsers so we can have a stacktrace + var err = new Error() + if (err.stack) { + var out = err.stack + + // try to strip useless frames + var fn_name = getName(stackStartFunction) + var idx = out.indexOf('\n' + fn_name) + if (idx >= 0) { + // once we have located the function frame + // we need to strip out everything before it (and its line) + var next_line = out.indexOf('\n', idx + 1) + out = out.substring(next_line + 1) + } + + this.stack = out + } + } + } - try { - if (actual instanceof expected) { - return true; - } - } catch (e) { - // Ignore. The instanceof check doesn't work for arrow functions. - } + // assert.AssertionError instanceof Error + util.inherits(assert.AssertionError, Error) - if (Error.isPrototypeOf(expected)) { - return false; - } + function truncate(s, n) { + if (typeof s === 'string') { + return s.length < n ? s : s.slice(0, n) + } else { + return s + } + } + function inspect(something) { + if (functionsHaveNames || !util.isFunction(something)) { + return util.inspect(something) + } + var rawname = getName(something) + var name = rawname ? ': ' + rawname : '' + return '[Function' + name + ']' + } + function getMessage(self) { + return ( + truncate(inspect(self.actual), 128) + + ' ' + + self.operator + + ' ' + + truncate(inspect(self.expected), 128) + ) + } - return expected.call({}, actual) === true; -} + // At present only the three keys mentioned above are used and + // understood by the spec. Implementations or sub modules can pass + // other keys to the AssertionError's constructor - they will be + // ignored. + + // 3. All of the following functions must throw an AssertionError + // when a corresponding condition is not met, with a message that + // may be undefined if not provided. All assertion methods provide + // both the actual and expected values to the assertion error for + // display purposes. + + function fail( + actual, + expected, + message, + operator, + stackStartFunction + ) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction, + }) + } -function _tryBlock(block) { - var error; - try { - block(); - } catch (e) { - error = e; - } - return error; -} + // EXTENSION! allows for well behaved errors defined elsewhere. + assert.fail = fail -function _throws(shouldThrow, block, expected, message) { - var actual; + // 4. Pure assertion tests whether a value is truthy, as determined + // by !!guard. + // assert.ok(guard, message_opt); + // This statement is equivalent to assert.equal(true, !!guard, + // message_opt);. To test strictly for the value true, use + // assert.strictEqual(true, guard, message_opt);. - if (typeof block !== 'function') { - throw new TypeError('"block" argument must be a function'); - } + function ok(value, message) { + if (!value) fail(value, true, message, '==', assert.ok) + } + assert.ok = ok - if (typeof expected === 'string') { - message = expected; - expected = null; - } + // 5. The equality assertion tests shallow, coercive equality with + // ==. + // assert.equal(actual, expected, message_opt); - actual = _tryBlock(block); + assert.equal = function equal(actual, expected, message) { + if (actual != expected) + fail(actual, expected, message, '==', assert.equal) + } - message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + - (message ? ' ' + message : '.'); + // 6. The non-equality assertion tests for whether two objects are not equal + // with != assert.notEqual(actual, expected, message_opt); - if (shouldThrow && !actual) { - fail(actual, expected, 'Missing expected exception' + message); - } + assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, '!=', assert.notEqual) + } + } - var userProvidedMessage = typeof message === 'string'; - var isUnwantedException = !shouldThrow && util.isError(actual); - var isUnexpectedException = !shouldThrow && actual && !expected; + // 7. The equivalence assertion tests a deep equality relation. + // assert.deepEqual(actual, expected, message_opt); - if ((isUnwantedException && - userProvidedMessage && - expectedException(actual, expected)) || - isUnexpectedException) { - fail(actual, expected, 'Got unwanted exception' + message); - } + assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected, false)) { + fail(actual, expected, message, 'deepEqual', assert.deepEqual) + } + } - if ((shouldThrow && actual && expected && - !expectedException(actual, expected)) || (!shouldThrow && actual)) { - throw actual; - } -} + assert.deepStrictEqual = function deepStrictEqual( + actual, + expected, + message + ) { + if (!_deepEqual(actual, expected, true)) { + fail( + actual, + expected, + message, + 'deepStrictEqual', + assert.deepStrictEqual + ) + } + } -// 11. Expected to throw an error: -// assert.throws(block, Error_opt, message_opt); + function _deepEqual(actual, expected, strict, memos) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true + } else if (isBuffer(actual) && isBuffer(expected)) { + return compare(actual, expected) === 0 + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (util.isDate(actual) && util.isDate(expected)) { + return actual.getTime() === expected.getTime() + + // 7.3 If the expected value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object with the same source and + // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). + } else if (util.isRegExp(actual) && util.isRegExp(expected)) { + return ( + actual.source === expected.source && + actual.global === expected.global && + actual.multiline === expected.multiline && + actual.lastIndex === expected.lastIndex && + actual.ignoreCase === expected.ignoreCase + ) + + // 7.4. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if ( + (actual === null || typeof actual !== 'object') && + (expected === null || typeof expected !== 'object') + ) { + return strict ? actual === expected : actual == expected + + // If both values are instances of typed arrays, wrap their underlying + // ArrayBuffers in a Buffer each to increase performance + // This optimization requires the arrays to have the same type as checked by + // Object.prototype.toString (aka pToString). Never perform binary + // comparisons for Float*Arrays, though, since e.g. +0 === -0 but their + // bit patterns are not identical. + } else if ( + isView(actual) && + isView(expected) && + pToString(actual) === pToString(expected) && + !( + actual instanceof Float32Array || + actual instanceof Float64Array + ) + ) { + return ( + compare( + new Uint8Array(actual.buffer), + new Uint8Array(expected.buffer) + ) === 0 + ) + + // 7.5 For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else if (isBuffer(actual) !== isBuffer(expected)) { + return false + } else { + memos = memos || { actual: [], expected: [] } -assert.throws = function(block, /*optional*/error, /*optional*/message) { - _throws(true, block, error, message); -}; + var actualIndex = memos.actual.indexOf(actual) + if (actualIndex !== -1) { + if (actualIndex === memos.expected.indexOf(expected)) { + return true + } + } -// EXTENSION! This is annoying to write outside this module. -assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { - _throws(false, block, error, message); -}; + memos.actual.push(actual) + memos.expected.push(expected) -assert.ifError = function(err) { if (err) throw err; }; + return objEquiv(actual, expected, strict, memos) + } + } -var objectKeys = Object.keys || function (obj) { - var keys = []; - for (var key in obj) { - if (hasOwn.call(obj, key)) keys.push(key); - } - return keys; -}; - -}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"util/":11}],9:[function(require,module,exports){ -if (typeof Object.create === 'function') { - // implementation from standard node.js 'util' module - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - ctor.prototype = Object.create(superCtor.prototype, { - constructor: { - value: ctor, - enumerable: false, - writable: true, - configurable: true - } - }); - }; -} else { - // old school shim for old browsers - module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() - ctor.prototype.constructor = ctor - } -} - -},{}],10:[function(require,module,exports){ -module.exports = function isBuffer(arg) { - return arg && typeof arg === 'object' - && typeof arg.copy === 'function' - && typeof arg.fill === 'function' - && typeof arg.readUInt8 === 'function'; -} -},{}],11:[function(require,module,exports){ -(function (process,global){ -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -var formatRegExp = /%[sdj%]/g; -exports.format = function(f) { - if (!isString(f)) { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - objects.push(inspect(arguments[i])); - } - return objects.join(' '); - } + function isArguments(object) { + return ( + Object.prototype.toString.call(object) == '[object Arguments]' + ) + } - var i = 1; - var args = arguments; - var len = args.length; - var str = String(f).replace(formatRegExp, function(x) { - if (x === '%%') return '%'; - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': - try { - return JSON.stringify(args[i++]); - } catch (_) { - return '[Circular]'; - } - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (isNull(x) || !isObject(x)) { - str += ' ' + x; - } else { - str += ' ' + inspect(x); - } - } - return str; -}; - - -// Mark that a method should not be used. -// Returns a modified function which warns once by default. -// If --no-deprecation is set, then it is a no-op. -exports.deprecate = function(fn, msg) { - // Allow for deprecating things in the process of starting up. - if (isUndefined(global.process)) { - return function() { - return exports.deprecate(fn, msg).apply(this, arguments); - }; - } + function objEquiv(a, b, strict, actualVisitedObjects) { + if ( + a === null || + a === undefined || + b === null || + b === undefined + ) + return false + // if one is a primitive, the other must be same + if (util.isPrimitive(a) || util.isPrimitive(b)) return a === b + if ( + strict && + Object.getPrototypeOf(a) !== Object.getPrototypeOf(b) + ) + return false + var aIsArgs = isArguments(a) + var bIsArgs = isArguments(b) + if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) return false + if (aIsArgs) { + a = pSlice.call(a) + b = pSlice.call(b) + return _deepEqual(a, b, strict) + } + var ka = objectKeys(a) + var kb = objectKeys(b) + var key, i + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length !== kb.length) return false + //the same set of keys (although not necessarily the same order), + ka.sort() + kb.sort() + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] !== kb[i]) return false + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i] + if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects)) + return false + } + return true + } - if (process.noDeprecation === true) { - return fn; - } + // 8. The non-equivalence assertion tests for any deep inequality. + // assert.notDeepEqual(actual, expected, message_opt); - var warned = false; - function deprecated() { - if (!warned) { - if (process.throwDeprecation) { - throw new Error(msg); - } else if (process.traceDeprecation) { - console.trace(msg); - } else { - console.error(msg); - } - warned = true; - } - return fn.apply(this, arguments); - } + assert.notDeepEqual = function notDeepEqual( + actual, + expected, + message + ) { + if (_deepEqual(actual, expected, false)) { + fail( + actual, + expected, + message, + 'notDeepEqual', + assert.notDeepEqual + ) + } + } - return deprecated; -}; - - -var debugs = {}; -var debugEnviron; -exports.debuglog = function(set) { - if (isUndefined(debugEnviron)) - debugEnviron = process.env.NODE_DEBUG || ''; - set = set.toUpperCase(); - if (!debugs[set]) { - if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { - var pid = process.pid; - debugs[set] = function() { - var msg = exports.format.apply(exports, arguments); - console.error('%s %d: %s', set, pid, msg); - }; - } else { - debugs[set] = function() {}; - } - } - return debugs[set]; -}; - - -/** - * Echos the value of a value. Trys to print the value out - * in the best way possible given the different types. - * - * @param {Object} obj The object to print out. - * @param {Object} opts Optional options object that alters the output. - */ -/* legacy: obj, showHidden, depth, colors*/ -function inspect(obj, opts) { - // default options - var ctx = { - seen: [], - stylize: stylizeNoColor - }; - // legacy... - if (arguments.length >= 3) ctx.depth = arguments[2]; - if (arguments.length >= 4) ctx.colors = arguments[3]; - if (isBoolean(opts)) { - // legacy... - ctx.showHidden = opts; - } else if (opts) { - // got an "options" object - exports._extend(ctx, opts); - } - // set default options - if (isUndefined(ctx.showHidden)) ctx.showHidden = false; - if (isUndefined(ctx.depth)) ctx.depth = 2; - if (isUndefined(ctx.colors)) ctx.colors = false; - if (isUndefined(ctx.customInspect)) ctx.customInspect = true; - if (ctx.colors) ctx.stylize = stylizeWithColor; - return formatValue(ctx, obj, ctx.depth); -} -exports.inspect = inspect; - - -// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics -inspect.colors = { - 'bold' : [1, 22], - 'italic' : [3, 23], - 'underline' : [4, 24], - 'inverse' : [7, 27], - 'white' : [37, 39], - 'grey' : [90, 39], - 'black' : [30, 39], - 'blue' : [34, 39], - 'cyan' : [36, 39], - 'green' : [32, 39], - 'magenta' : [35, 39], - 'red' : [31, 39], - 'yellow' : [33, 39] -}; - -// Don't use 'blue' not visible on cmd.exe -inspect.styles = { - 'special': 'cyan', - 'number': 'yellow', - 'boolean': 'yellow', - 'undefined': 'grey', - 'null': 'bold', - 'string': 'green', - 'date': 'magenta', - // "name": intentionally not styling - 'regexp': 'red' -}; - - -function stylizeWithColor(str, styleType) { - var style = inspect.styles[styleType]; - - if (style) { - return '\u001b[' + inspect.colors[style][0] + 'm' + str + - '\u001b[' + inspect.colors[style][1] + 'm'; - } else { - return str; - } -} + assert.notDeepStrictEqual = notDeepStrictEqual + function notDeepStrictEqual(actual, expected, message) { + if (_deepEqual(actual, expected, true)) { + fail( + actual, + expected, + message, + 'notDeepStrictEqual', + notDeepStrictEqual + ) + } + } + // 9. The strict equality assertion tests strict equality, as determined by ===. + // assert.strictEqual(actual, expected, message_opt); -function stylizeNoColor(str, styleType) { - return str; -} + assert.strictEqual = function strictEqual( + actual, + expected, + message + ) { + if (actual !== expected) { + fail(actual, expected, message, '===', assert.strictEqual) + } + } + // 10. The strict non-equality assertion tests for strict inequality, as + // determined by !==. assert.notStrictEqual(actual, expected, message_opt); -function arrayToHash(array) { - var hash = {}; + assert.notStrictEqual = function notStrictEqual( + actual, + expected, + message + ) { + if (actual === expected) { + fail(actual, expected, message, '!==', assert.notStrictEqual) + } + } - array.forEach(function(val, idx) { - hash[val] = true; - }); + function expectedException(actual, expected) { + if (!actual || !expected) { + return false + } - return hash; -} + if ( + Object.prototype.toString.call(expected) == '[object RegExp]' + ) { + return expected.test(actual) + } + try { + if (actual instanceof expected) { + return true + } + } catch (e) { + // Ignore. The instanceof check doesn't work for arrow functions. + } -function formatValue(ctx, value, recurseTimes) { - // Provide a hook for user-specified inspect functions. - // Check that value is an object with an inspect function on it - if (ctx.customInspect && - value && - isFunction(value.inspect) && - // Filter out the util module, it's inspect function is special - value.inspect !== exports.inspect && - // Also filter out any prototype objects using the circular check. - !(value.constructor && value.constructor.prototype === value)) { - var ret = value.inspect(recurseTimes, ctx); - if (!isString(ret)) { - ret = formatValue(ctx, ret, recurseTimes); - } - return ret; - } + if (Error.isPrototypeOf(expected)) { + return false + } - // Primitive types cannot have properties - var primitive = formatPrimitive(ctx, value); - if (primitive) { - return primitive; - } + return expected.call({}, actual) === true + } - // Look up the keys of the object. - var keys = Object.keys(value); - var visibleKeys = arrayToHash(keys); + function _tryBlock(block) { + var error + try { + block() + } catch (e) { + error = e + } + return error + } - if (ctx.showHidden) { - keys = Object.getOwnPropertyNames(value); - } + function _throws(shouldThrow, block, expected, message) { + var actual - // IE doesn't make error fields non-enumerable - // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx - if (isError(value) - && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { - return formatError(value); - } + if (typeof block !== 'function') { + throw new TypeError('"block" argument must be a function') + } - // Some type of object without properties can be shortcutted. - if (keys.length === 0) { - if (isFunction(value)) { - var name = value.name ? ': ' + value.name : ''; - return ctx.stylize('[Function' + name + ']', 'special'); - } - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } - if (isDate(value)) { - return ctx.stylize(Date.prototype.toString.call(value), 'date'); - } - if (isError(value)) { - return formatError(value); - } - } + if (typeof expected === 'string') { + message = expected + expected = null + } - var base = '', array = false, braces = ['{', '}']; + actual = _tryBlock(block) - // Make Array say that they are Array - if (isArray(value)) { - array = true; - braces = ['[', ']']; - } + message = + (expected && expected.name + ? ' (' + expected.name + ').' + : '.') + (message ? ' ' + message : '.') - // Make functions say that they are functions - if (isFunction(value)) { - var n = value.name ? ': ' + value.name : ''; - base = ' [Function' + n + ']'; - } + if (shouldThrow && !actual) { + fail(actual, expected, 'Missing expected exception' + message) + } - // Make RegExps say that they are RegExps - if (isRegExp(value)) { - base = ' ' + RegExp.prototype.toString.call(value); - } + var userProvidedMessage = typeof message === 'string' + var isUnwantedException = !shouldThrow && util.isError(actual) + var isUnexpectedException = !shouldThrow && actual && !expected + + if ( + (isUnwantedException && + userProvidedMessage && + expectedException(actual, expected)) || + isUnexpectedException + ) { + fail(actual, expected, 'Got unwanted exception' + message) + } - // Make dates with properties first say the date - if (isDate(value)) { - base = ' ' + Date.prototype.toUTCString.call(value); - } + if ( + (shouldThrow && + actual && + expected && + !expectedException(actual, expected)) || + (!shouldThrow && actual) + ) { + throw actual + } + } - // Make error with message first say the error - if (isError(value)) { - base = ' ' + formatError(value); - } + // 11. Expected to throw an error: + // assert.throws(block, Error_opt, message_opt); - if (keys.length === 0 && (!array || value.length == 0)) { - return braces[0] + base + braces[1]; - } + assert.throws = function ( + block, + /*optional*/ error, + /*optional*/ message + ) { + _throws(true, block, error, message) + } - if (recurseTimes < 0) { - if (isRegExp(value)) { - return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); - } else { - return ctx.stylize('[Object]', 'special'); - } - } + // EXTENSION! This is annoying to write outside this module. + assert.doesNotThrow = function ( + block, + /*optional*/ error, + /*optional*/ message + ) { + _throws(false, block, error, message) + } - ctx.seen.push(value); + assert.ifError = function (err) { + if (err) throw err + } - var output; - if (array) { - output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); - } else { - output = keys.map(function(key) { - return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); - }); - } + var objectKeys = + Object.keys || + function (obj) { + var keys = [] + for (var key in obj) { + if (hasOwn.call(obj, key)) keys.push(key) + } + return keys + } + }.call( + this, + typeof global !== 'undefined' + ? global + : typeof self !== 'undefined' + ? self + : typeof window !== 'undefined' + ? window + : {} + )) + }, + { 'util/': 11 }, + ], + 9: [ + function (require, module, exports) { + if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true, + }, + }) + } + } else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } + } + }, + {}, + ], + 10: [ + function (require, module, exports) { + module.exports = function isBuffer(arg) { + return ( + arg && + typeof arg === 'object' && + typeof arg.copy === 'function' && + typeof arg.fill === 'function' && + typeof arg.readUInt8 === 'function' + ) + } + }, + {}, + ], + 11: [ + function (require, module, exports) { + ;(function (process, global) { + // Copyright Joyent, Inc. and other Node contributors. + // + // Permission is hereby granted, free of charge, to any person obtaining a + // copy of this software and associated documentation files (the + // "Software"), to deal in the Software without restriction, including + // without limitation the rights to use, copy, modify, merge, publish, + // distribute, sublicense, and/or sell copies of the Software, and to permit + // persons to whom the Software is furnished to do so, subject to the + // following conditions: + // + // The above copyright notice and this permission notice shall be included + // in all copies or substantial portions of the Software. + // + // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN + // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + // USE OR OTHER DEALINGS IN THE SOFTWARE. + + var formatRegExp = /%[sdj%]/g + exports.format = function (f) { + if (!isString(f)) { + var objects = [] + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])) + } + return objects.join(' ') + } - ctx.seen.pop(); + var i = 1 + var args = arguments + var len = args.length + var str = String(f).replace(formatRegExp, function (x) { + if (x === '%%') return '%' + if (i >= len) return x + switch (x) { + case '%s': + return String(args[i++]) + case '%d': + return Number(args[i++]) + case '%j': + try { + return JSON.stringify(args[i++]) + } catch (_) { + return '[Circular]' + } + default: + return x + } + }) + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x + } else { + str += ' ' + inspect(x) + } + } + return str + } - return reduceToSingleString(output, base, braces); -} + // Mark that a method should not be used. + // Returns a modified function which warns once by default. + // If --no-deprecation is set, then it is a no-op. + exports.deprecate = function (fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function () { + return exports.deprecate(fn, msg).apply(this, arguments) + } + } + if (process.noDeprecation === true) { + return fn + } -function formatPrimitive(ctx, value) { - if (isUndefined(value)) - return ctx.stylize('undefined', 'undefined'); - if (isString(value)) { - var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') - .replace(/'/g, "\\'") - .replace(/\\"/g, '"') + '\''; - return ctx.stylize(simple, 'string'); - } - if (isNumber(value)) - return ctx.stylize('' + value, 'number'); - if (isBoolean(value)) - return ctx.stylize('' + value, 'boolean'); - // For some reason typeof null is "object", so special case here. - if (isNull(value)) - return ctx.stylize('null', 'null'); -} - - -function formatError(value) { - return '[' + Error.prototype.toString.call(value) + ']'; -} - - -function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { - var output = []; - for (var i = 0, l = value.length; i < l; ++i) { - if (hasOwnProperty(value, String(i))) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - String(i), true)); - } else { - output.push(''); - } - } - keys.forEach(function(key) { - if (!key.match(/^\d+$/)) { - output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, - key, true)); - } - }); - return output; -} + var warned = false + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg) + } else if (process.traceDeprecation) { + console.trace(msg) + } else { + console.error(msg) + } + warned = true + } + return fn.apply(this, arguments) + } + return deprecated + } -function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { - var name, str, desc; - desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; - if (desc.get) { - if (desc.set) { - str = ctx.stylize('[Getter/Setter]', 'special'); - } else { - str = ctx.stylize('[Getter]', 'special'); - } - } else { - if (desc.set) { - str = ctx.stylize('[Setter]', 'special'); - } - } - if (!hasOwnProperty(visibleKeys, key)) { - name = '[' + key + ']'; - } - if (!str) { - if (ctx.seen.indexOf(desc.value) < 0) { - if (isNull(recurseTimes)) { - str = formatValue(ctx, desc.value, null); - } else { - str = formatValue(ctx, desc.value, recurseTimes - 1); - } - if (str.indexOf('\n') > -1) { - if (array) { - str = str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n').substr(2); - } else { - str = '\n' + str.split('\n').map(function(line) { - return ' ' + line; - }).join('\n'); - } - } - } else { - str = ctx.stylize('[Circular]', 'special'); - } - } - if (isUndefined(name)) { - if (array && key.match(/^\d+$/)) { - return str; - } - name = JSON.stringify('' + key); - if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { - name = name.substr(1, name.length - 2); - name = ctx.stylize(name, 'name'); - } else { - name = name.replace(/'/g, "\\'") - .replace(/\\"/g, '"') - .replace(/(^"|"$)/g, "'"); - name = ctx.stylize(name, 'string'); - } - } + var debugs = {} + var debugEnviron + exports.debuglog = function (set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || '' + set = set.toUpperCase() + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid + debugs[set] = function () { + var msg = exports.format.apply(exports, arguments) + console.error('%s %d: %s', set, pid, msg) + } + } else { + debugs[set] = function () {} + } + } + return debugs[set] + } - return name + ': ' + str; -} - - -function reduceToSingleString(output, base, braces) { - var numLinesEst = 0; - var length = output.reduce(function(prev, cur) { - numLinesEst++; - if (cur.indexOf('\n') >= 0) numLinesEst++; - return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; - }, 0); - - if (length > 60) { - return braces[0] + - (base === '' ? '' : base + '\n ') + - ' ' + - output.join(',\n ') + - ' ' + - braces[1]; - } + /** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ + /* legacy: obj, showHidden, depth, colors*/ + function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor, + } + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2] + if (arguments.length >= 4) ctx.colors = arguments[3] + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts) + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false + if (isUndefined(ctx.depth)) ctx.depth = 2 + if (isUndefined(ctx.colors)) ctx.colors = false + if (isUndefined(ctx.customInspect)) ctx.customInspect = true + if (ctx.colors) ctx.stylize = stylizeWithColor + return formatValue(ctx, obj, ctx.depth) + } + exports.inspect = inspect + + // http://en.wikipedia.org/wiki/ANSI_escape_code#graphics + inspect.colors = { + bold: [1, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + white: [37, 39], + grey: [90, 39], + black: [30, 39], + blue: [34, 39], + cyan: [36, 39], + green: [32, 39], + magenta: [35, 39], + red: [31, 39], + yellow: [33, 39], + } - return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; -} - - -// NOTE: These type checking functions intentionally don't use `instanceof` -// because it is fragile and can be easily faked with `Object.create()`. -function isArray(ar) { - return Array.isArray(ar); -} -exports.isArray = isArray; - -function isBoolean(arg) { - return typeof arg === 'boolean'; -} -exports.isBoolean = isBoolean; - -function isNull(arg) { - return arg === null; -} -exports.isNull = isNull; - -function isNullOrUndefined(arg) { - return arg == null; -} -exports.isNullOrUndefined = isNullOrUndefined; - -function isNumber(arg) { - return typeof arg === 'number'; -} -exports.isNumber = isNumber; - -function isString(arg) { - return typeof arg === 'string'; -} -exports.isString = isString; - -function isSymbol(arg) { - return typeof arg === 'symbol'; -} -exports.isSymbol = isSymbol; - -function isUndefined(arg) { - return arg === void 0; -} -exports.isUndefined = isUndefined; - -function isRegExp(re) { - return isObject(re) && objectToString(re) === '[object RegExp]'; -} -exports.isRegExp = isRegExp; - -function isObject(arg) { - return typeof arg === 'object' && arg !== null; -} -exports.isObject = isObject; - -function isDate(d) { - return isObject(d) && objectToString(d) === '[object Date]'; -} -exports.isDate = isDate; - -function isError(e) { - return isObject(e) && - (objectToString(e) === '[object Error]' || e instanceof Error); -} -exports.isError = isError; - -function isFunction(arg) { - return typeof arg === 'function'; -} -exports.isFunction = isFunction; - -function isPrimitive(arg) { - return arg === null || - typeof arg === 'boolean' || - typeof arg === 'number' || - typeof arg === 'string' || - typeof arg === 'symbol' || // ES6 symbol - typeof arg === 'undefined'; -} -exports.isPrimitive = isPrimitive; - -exports.isBuffer = require('./support/isBuffer'); - -function objectToString(o) { - return Object.prototype.toString.call(o); -} - - -function pad(n) { - return n < 10 ? '0' + n.toString(10) : n.toString(10); -} - - -var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', - 'Oct', 'Nov', 'Dec']; - -// 26 Feb 16:19:34 -function timestamp() { - var d = new Date(); - var time = [pad(d.getHours()), - pad(d.getMinutes()), - pad(d.getSeconds())].join(':'); - return [d.getDate(), months[d.getMonth()], time].join(' '); -} - - -// log is just a thin wrapper to console.log that prepends a timestamp -exports.log = function() { - console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); -}; - - -/** - * Inherit the prototype methods from one constructor into another. - * - * The Function.prototype.inherits from lang.js rewritten as a standalone - * function (not on Function.prototype). NOTE: If this file is to be loaded - * during bootstrapping this function needs to be rewritten using some native - * functions as prototype setup using normal JavaScript does not work as - * expected during bootstrapping (see mirror.js in r114903). - * - * @param {function} ctor Constructor function which needs to inherit the - * prototype. - * @param {function} superCtor Constructor function to inherit prototype from. - */ -exports.inherits = require('inherits'); - -exports._extend = function(origin, add) { - // Don't do anything if add isn't an object - if (!add || !isObject(add)) return origin; - - var keys = Object.keys(add); - var i = keys.length; - while (i--) { - origin[keys[i]] = add[keys[i]]; - } - return origin; -}; - -function hasOwnProperty(obj, prop) { - return Object.prototype.hasOwnProperty.call(obj, prop); -} - -}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) -},{"./support/isBuffer":10,"_process":13,"inherits":9}],12:[function(require,module,exports){ -(function (process){ -// .dirname, .basename, and .extname methods are extracted from Node.js v8.11.1, -// backported and transplited with Babel, with backwards-compat fixes - -// Copyright Joyent, Inc. and other Node contributors. -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to permit -// persons to whom the Software is furnished to do so, subject to the -// following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN -// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE -// USE OR OTHER DEALINGS IN THE SOFTWARE. - -// resolves . and .. elements in a path array with directory names there -// must be no slashes, empty elements, or device names (c:\) in the array -// (so also no leading and trailing slashes - it does not distinguish -// relative and absolute paths) -function normalizeArray(parts, allowAboveRoot) { - // if the path tries to go above the root, `up` ends up > 0 - var up = 0; - for (var i = parts.length - 1; i >= 0; i--) { - var last = parts[i]; - if (last === '.') { - parts.splice(i, 1); - } else if (last === '..') { - parts.splice(i, 1); - up++; - } else if (up) { - parts.splice(i, 1); - up--; - } - } + // Don't use 'blue' not visible on cmd.exe + inspect.styles = { + special: 'cyan', + number: 'yellow', + boolean: 'yellow', + undefined: 'grey', + null: 'bold', + string: 'green', + date: 'magenta', + // "name": intentionally not styling + regexp: 'red', + } - // if the path is allowed to go above the root, restore leading ..s - if (allowAboveRoot) { - for (; up--; up) { - parts.unshift('..'); - } - } + function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType] + + if (style) { + return ( + '\u001b[' + + inspect.colors[style][0] + + 'm' + + str + + '\u001b[' + + inspect.colors[style][1] + + 'm' + ) + } else { + return str + } + } - return parts; -} + function stylizeNoColor(str, styleType) { + return str + } -// path.resolve([from ...], to) -// posix version -exports.resolve = function() { - var resolvedPath = '', - resolvedAbsolute = false; + function arrayToHash(array) { + var hash = {} - for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { - var path = (i >= 0) ? arguments[i] : process.cwd(); + array.forEach(function (val, idx) { + hash[val] = true + }) - // Skip empty and invalid entries - if (typeof path !== 'string') { - throw new TypeError('Arguments to path.resolve must be strings'); - } else if (!path) { - continue; - } + return hash + } - resolvedPath = path + '/' + resolvedPath; - resolvedAbsolute = path.charAt(0) === '/'; - } + function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if ( + ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value) + ) { + var ret = value.inspect(recurseTimes, ctx) + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes) + } + return ret + } - // At this point the path should be resolved to a full absolute path, but - // handle relative paths to be safe (might happen when process.cwd() fails) + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value) + if (primitive) { + return primitive + } - // Normalize the path - resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) { - return !!p; - }), !resolvedAbsolute).join('/'); + // Look up the keys of the object. + var keys = Object.keys(value) + var visibleKeys = arrayToHash(keys) - return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; -}; + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value) + } -// path.normalize(path) -// posix version -exports.normalize = function(path) { - var isAbsolute = exports.isAbsolute(path), - trailingSlash = substr(path, -1) === '/'; + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if ( + isError(value) && + (keys.indexOf('message') >= 0 || + keys.indexOf('description') >= 0) + ) { + return formatError(value) + } - // Normalize the path - path = normalizeArray(filter(path.split('/'), function(p) { - return !!p; - }), !isAbsolute).join('/'); + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : '' + return ctx.stylize('[Function' + name + ']', 'special') + } + if (isRegExp(value)) { + return ctx.stylize( + RegExp.prototype.toString.call(value), + 'regexp' + ) + } + if (isDate(value)) { + return ctx.stylize( + Date.prototype.toString.call(value), + 'date' + ) + } + if (isError(value)) { + return formatError(value) + } + } - if (!path && !isAbsolute) { - path = '.'; - } - if (path && trailingSlash) { - path += '/'; - } + var base = '', + array = false, + braces = ['{', '}'] - return (isAbsolute ? '/' : '') + path; -}; + // Make Array say that they are Array + if (isArray(value)) { + array = true + braces = ['[', ']'] + } -// posix version -exports.isAbsolute = function(path) { - return path.charAt(0) === '/'; -}; + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : '' + base = ' [Function' + n + ']' + } -// posix version -exports.join = function() { - var paths = Array.prototype.slice.call(arguments, 0); - return exports.normalize(filter(paths, function(p, index) { - if (typeof p !== 'string') { - throw new TypeError('Arguments to path.join must be strings'); - } - return p; - }).join('/')); -}; + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value) + } + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value) + } -// path.relative(from, to) -// posix version -exports.relative = function(from, to) { - from = exports.resolve(from).substr(1); - to = exports.resolve(to).substr(1); + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value) + } - function trim(arr) { - var start = 0; - for (; start < arr.length; start++) { - if (arr[start] !== '') break; - } + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1] + } - var end = arr.length - 1; - for (; end >= 0; end--) { - if (arr[end] !== '') break; - } - - if (start > end) return []; - return arr.slice(start, end - start + 1); - } - - var fromParts = trim(from.split('/')); - var toParts = trim(to.split('/')); - - var length = Math.min(fromParts.length, toParts.length); - var samePartsLength = length; - for (var i = 0; i < length; i++) { - if (fromParts[i] !== toParts[i]) { - samePartsLength = i; - break; - } - } - - var outputParts = []; - for (var i = samePartsLength; i < fromParts.length; i++) { - outputParts.push('..'); - } + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize( + RegExp.prototype.toString.call(value), + 'regexp' + ) + } else { + return ctx.stylize('[Object]', 'special') + } + } - outputParts = outputParts.concat(toParts.slice(samePartsLength)); - - return outputParts.join('/'); -}; - -exports.sep = '/'; -exports.delimiter = ':'; - -exports.dirname = function (path) { - if (typeof path !== 'string') path = path + ''; - if (path.length === 0) return '.'; - var code = path.charCodeAt(0); - var hasRoot = code === 47 /*/*/; - var end = -1; - var matchedSlash = true; - for (var i = path.length - 1; i >= 1; --i) { - code = path.charCodeAt(i); - if (code === 47 /*/*/) { - if (!matchedSlash) { - end = i; - break; - } - } else { - // We saw the first non-path separator - matchedSlash = false; - } - } + ctx.seen.push(value) + + var output + if (array) { + output = formatArray( + ctx, + value, + recurseTimes, + visibleKeys, + keys + ) + } else { + output = keys.map(function (key) { + return formatProperty( + ctx, + value, + recurseTimes, + visibleKeys, + key, + array + ) + }) + } - if (end === -1) return hasRoot ? '/' : '.'; - if (hasRoot && end === 1) { - // return '//'; - // Backwards-compat fix: - return '/'; - } - return path.slice(0, end); -}; - -function basename(path) { - if (typeof path !== 'string') path = path + ''; - - var start = 0; - var end = -1; - var matchedSlash = true; - var i; - - for (i = path.length - 1; i >= 0; --i) { - if (path.charCodeAt(i) === 47 /*/*/) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - start = i + 1; - break; - } - } else if (end === -1) { - // We saw the first non-path separator, mark this as the end of our - // path component - matchedSlash = false; - end = i + 1; - } - } + ctx.seen.pop() - if (end === -1) return ''; - return path.slice(start, end); -} + return reduceToSingleString(output, base, braces) + } -// Uses a mixed approach for backwards-compatibility, as ext behavior changed -// in new Node.js versions, so only basename() above is backported here -exports.basename = function (path, ext) { - var f = basename(path); - if (ext && f.substr(-1 * ext.length) === ext) { - f = f.substr(0, f.length - ext.length); - } - return f; -}; - -exports.extname = function (path) { - if (typeof path !== 'string') path = path + ''; - var startDot = -1; - var startPart = 0; - var end = -1; - var matchedSlash = true; - // Track the state of characters (if any) we see before our first dot and - // after any path separator we find - var preDotState = 0; - for (var i = path.length - 1; i >= 0; --i) { - var code = path.charCodeAt(i); - if (code === 47 /*/*/) { - // If we reached a path separator that was not part of a set of path - // separators at the end of the string, stop now - if (!matchedSlash) { - startPart = i + 1; - break; - } - continue; - } - if (end === -1) { - // We saw the first non-path separator, mark this as the end of our - // extension - matchedSlash = false; - end = i + 1; - } - if (code === 46 /*.*/) { - // If this is our first dot, mark it as the start of our extension - if (startDot === -1) - startDot = i; - else if (preDotState !== 1) - preDotState = 1; - } else if (startDot !== -1) { - // We saw a non-dot and non-path separator before our dot, so we should - // have a good chance at having a non-empty extension - preDotState = -1; - } - } + function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined') + if (isString(value)) { + var simple = + "'" + + JSON.stringify(value) + .replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + + "'" + return ctx.stylize(simple, 'string') + } + if (isNumber(value)) return ctx.stylize('' + value, 'number') + if (isBoolean(value)) return ctx.stylize('' + value, 'boolean') + // For some reason typeof null is "object", so special case here. + if (isNull(value)) return ctx.stylize('null', 'null') + } - if (startDot === -1 || end === -1 || - // We saw a non-dot character immediately before the dot - preDotState === 0 || - // The (right-most) trimmed path component is exactly '..' - preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) { - return ''; - } - return path.slice(startDot, end); -}; - -function filter (xs, f) { - if (xs.filter) return xs.filter(f); - var res = []; - for (var i = 0; i < xs.length; i++) { - if (f(xs[i], i, xs)) res.push(xs[i]); - } - return res; -} - -// String.prototype.substr - negative index don't work in IE8 -var substr = 'ab'.substr(-1) === 'b' - ? function (str, start, len) { return str.substr(start, len) } - : function (str, start, len) { - if (start < 0) start = str.length + start; - return str.substr(start, len); - } -; - -}).call(this,require('_process')) -},{"_process":13}],13:[function(require,module,exports){ -// shim for using process in browser -var process = module.exports = {}; - -// cached from whatever global is present so that test runners that stub it -// don't break things. But we need to wrap it in a try catch in case it is -// wrapped in strict mode code which doesn't define any globals. It's inside a -// function because try/catches deoptimize in certain engines. - -var cachedSetTimeout; -var cachedClearTimeout; - -function defaultSetTimout() { - throw new Error('setTimeout has not been defined'); -} -function defaultClearTimeout () { - throw new Error('clearTimeout has not been defined'); -} -(function () { - try { - if (typeof setTimeout === 'function') { - cachedSetTimeout = setTimeout; - } else { - cachedSetTimeout = defaultSetTimout; - } - } catch (e) { - cachedSetTimeout = defaultSetTimout; - } - try { - if (typeof clearTimeout === 'function') { - cachedClearTimeout = clearTimeout; - } else { - cachedClearTimeout = defaultClearTimeout; - } - } catch (e) { - cachedClearTimeout = defaultClearTimeout; - } -} ()) -function runTimeout(fun) { - if (cachedSetTimeout === setTimeout) { - //normal enviroments in sane situations - return setTimeout(fun, 0); - } - // if setTimeout wasn't available but was latter defined - if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { - cachedSetTimeout = setTimeout; - return setTimeout(fun, 0); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedSetTimeout(fun, 0); - } catch(e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedSetTimeout.call(null, fun, 0); - } catch(e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error - return cachedSetTimeout.call(this, fun, 0); - } - } + function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']' + } + function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = [] + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push( + formatProperty( + ctx, + value, + recurseTimes, + visibleKeys, + String(i), + true + ) + ) + } else { + output.push('') + } + } + keys.forEach(function (key) { + if (!key.match(/^\d+$/)) { + output.push( + formatProperty( + ctx, + value, + recurseTimes, + visibleKeys, + key, + true + ) + ) + } + }) + return output + } -} -function runClearTimeout(marker) { - if (cachedClearTimeout === clearTimeout) { - //normal enviroments in sane situations - return clearTimeout(marker); - } - // if clearTimeout wasn't available but was latter defined - if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { - cachedClearTimeout = clearTimeout; - return clearTimeout(marker); - } - try { - // when when somebody has screwed with setTimeout but no I.E. maddness - return cachedClearTimeout(marker); - } catch (e){ - try { - // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally - return cachedClearTimeout.call(null, marker); - } catch (e){ - // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. - // Some versions of I.E. have different rules for clearTimeout vs setTimeout - return cachedClearTimeout.call(this, marker); - } - } + function formatProperty( + ctx, + value, + recurseTimes, + visibleKeys, + key, + array + ) { + var name, str, desc + desc = Object.getOwnPropertyDescriptor(value, key) || { + value: value[key], + } + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special') + } else { + str = ctx.stylize('[Getter]', 'special') + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special') + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']' + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null) + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1) + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str + .split('\n') + .map(function (line) { + return ' ' + line + }) + .join('\n') + .substr(2) + } else { + str = + '\n' + + str + .split('\n') + .map(function (line) { + return ' ' + line + }) + .join('\n') + } + } + } else { + str = ctx.stylize('[Circular]', 'special') + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str + } + name = JSON.stringify('' + key) + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2) + name = ctx.stylize(name, 'name') + } else { + name = name + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'") + name = ctx.stylize(name, 'string') + } + } + return name + ': ' + str + } + function reduceToSingleString(output, base, braces) { + var numLinesEst = 0 + var length = output.reduce(function (prev, cur) { + numLinesEst++ + if (cur.indexOf('\n') >= 0) numLinesEst++ + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1 + }, 0) + + if (length > 60) { + return ( + braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1] + ) + } -} -var queue = []; -var draining = false; -var currentQueue; -var queueIndex = -1; + return ( + braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1] + ) + } -function cleanUpNextTick() { - if (!draining || !currentQueue) { - return; - } - draining = false; - if (currentQueue.length) { - queue = currentQueue.concat(queue); - } else { - queueIndex = -1; - } - if (queue.length) { - drainQueue(); - } -} + // NOTE: These type checking functions intentionally don't use `instanceof` + // because it is fragile and can be easily faked with `Object.create()`. + function isArray(ar) { + return Array.isArray(ar) + } + exports.isArray = isArray -function drainQueue() { - if (draining) { - return; - } - var timeout = runTimeout(cleanUpNextTick); - draining = true; + function isBoolean(arg) { + return typeof arg === 'boolean' + } + exports.isBoolean = isBoolean - var len = queue.length; - while(len) { - currentQueue = queue; - queue = []; - while (++queueIndex < len) { - if (currentQueue) { - currentQueue[queueIndex].run(); + function isNull(arg) { + return arg === null } - } - queueIndex = -1; - len = queue.length; - } - currentQueue = null; - draining = false; - runClearTimeout(timeout); -} - -process.nextTick = function (fun) { - var args = new Array(arguments.length - 1); - if (arguments.length > 1) { - for (var i = 1; i < arguments.length; i++) { - args[i - 1] = arguments[i]; - } - } - queue.push(new Item(fun, args)); - if (queue.length === 1 && !draining) { - runTimeout(drainQueue); - } -}; - -// v8 likes predictible objects -function Item(fun, array) { - this.fun = fun; - this.array = array; -} -Item.prototype.run = function () { - this.fun.apply(null, this.array); -}; -process.title = 'browser'; -process.browser = true; -process.env = {}; -process.argv = []; -process.version = ''; // empty string to avoid regexp issues -process.versions = {}; - -function noop() {} - -process.on = noop; -process.addListener = noop; -process.once = noop; -process.off = noop; -process.removeListener = noop; -process.removeAllListeners = noop; -process.emit = noop; -process.prependListener = noop; -process.prependOnceListener = noop; - -process.listeners = function (name) { return [] } - -process.binding = function (name) { - throw new Error('process.binding is not supported'); -}; - -process.cwd = function () { return '/' }; -process.chdir = function (dir) { - throw new Error('process.chdir is not supported'); -}; -process.umask = function() { return 0; }; - -},{}],14:[function(require,module,exports){ -(function webpackUniversalModuleDefinition(root, factory) { -/* istanbul ignore next */ - if(typeof exports === 'object' && typeof module === 'object') - module.exports = factory(); - else if(typeof define === 'function' && define.amd) - define([], factory); -/* istanbul ignore next */ - else if(typeof exports === 'object') - exports["esprima"] = factory(); - else - root["esprima"] = factory(); -})(this, function() { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; - -/******/ // The require function -/******/ function __webpack_require__(moduleId) { - -/******/ // Check if module is in cache -/* istanbul ignore if */ -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; - -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; - -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); - -/******/ // Flag the module as loaded -/******/ module.loaded = true; - -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } - - -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; - -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; - -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; - -/******/ // Load entry module and return exports -/******/ return __webpack_require__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - /* - Copyright JS Foundation and other contributors, https://js.foundation/ + exports.isNull = isNull - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + function isNullOrUndefined(arg) { + return arg == null + } + exports.isNullOrUndefined = isNullOrUndefined - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + function isNumber(arg) { + return typeof arg === 'number' + } + exports.isNumber = isNumber - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - Object.defineProperty(exports, "__esModule", { value: true }); - var comment_handler_1 = __webpack_require__(1); - var jsx_parser_1 = __webpack_require__(3); - var parser_1 = __webpack_require__(8); - var tokenizer_1 = __webpack_require__(15); - function parse(code, options, delegate) { - var commentHandler = null; - var proxyDelegate = function (node, metadata) { - if (delegate) { - delegate(node, metadata); - } - if (commentHandler) { - commentHandler.visit(node, metadata); - } - }; - var parserDelegate = (typeof delegate === 'function') ? proxyDelegate : null; - var collectComment = false; - if (options) { - collectComment = (typeof options.comment === 'boolean' && options.comment); - var attachComment = (typeof options.attachComment === 'boolean' && options.attachComment); - if (collectComment || attachComment) { - commentHandler = new comment_handler_1.CommentHandler(); - commentHandler.attach = attachComment; - options.comment = true; - parserDelegate = proxyDelegate; - } - } - var isModule = false; - if (options && typeof options.sourceType === 'string') { - isModule = (options.sourceType === 'module'); - } - var parser; - if (options && typeof options.jsx === 'boolean' && options.jsx) { - parser = new jsx_parser_1.JSXParser(code, options, parserDelegate); - } - else { - parser = new parser_1.Parser(code, options, parserDelegate); - } - var program = isModule ? parser.parseModule() : parser.parseScript(); - var ast = program; - if (collectComment && commentHandler) { - ast.comments = commentHandler.comments; - } - if (parser.config.tokens) { - ast.tokens = parser.tokens; - } - if (parser.config.tolerant) { - ast.errors = parser.errorHandler.errors; - } - return ast; - } - exports.parse = parse; - function parseModule(code, options, delegate) { - var parsingOptions = options || {}; - parsingOptions.sourceType = 'module'; - return parse(code, parsingOptions, delegate); - } - exports.parseModule = parseModule; - function parseScript(code, options, delegate) { - var parsingOptions = options || {}; - parsingOptions.sourceType = 'script'; - return parse(code, parsingOptions, delegate); - } - exports.parseScript = parseScript; - function tokenize(code, options, delegate) { - var tokenizer = new tokenizer_1.Tokenizer(code, options); - var tokens; - tokens = []; - try { - while (true) { - var token = tokenizer.getNextToken(); - if (!token) { - break; - } - if (delegate) { - token = delegate(token); - } - tokens.push(token); - } - } - catch (e) { - tokenizer.errorHandler.tolerate(e); - } - if (tokenizer.errorHandler.tolerant) { - tokens.errors = tokenizer.errors(); - } - return tokens; - } - exports.tokenize = tokenize; - var syntax_1 = __webpack_require__(2); - exports.Syntax = syntax_1.Syntax; - // Sync with *.json manifests. - exports.version = '4.0.1'; - - -/***/ }, -/* 1 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var syntax_1 = __webpack_require__(2); - var CommentHandler = (function () { - function CommentHandler() { - this.attach = false; - this.comments = []; - this.stack = []; - this.leading = []; - this.trailing = []; - } - CommentHandler.prototype.insertInnerComments = function (node, metadata) { - // innnerComments for properties empty block - // `function a() {/** comments **\/}` - if (node.type === syntax_1.Syntax.BlockStatement && node.body.length === 0) { - var innerComments = []; - for (var i = this.leading.length - 1; i >= 0; --i) { - var entry = this.leading[i]; - if (metadata.end.offset >= entry.start) { - innerComments.unshift(entry.comment); - this.leading.splice(i, 1); - this.trailing.splice(i, 1); - } - } - if (innerComments.length) { - node.innerComments = innerComments; - } - } - }; - CommentHandler.prototype.findTrailingComments = function (metadata) { - var trailingComments = []; - if (this.trailing.length > 0) { - for (var i = this.trailing.length - 1; i >= 0; --i) { - var entry_1 = this.trailing[i]; - if (entry_1.start >= metadata.end.offset) { - trailingComments.unshift(entry_1.comment); - } - } - this.trailing.length = 0; - return trailingComments; - } - var entry = this.stack[this.stack.length - 1]; - if (entry && entry.node.trailingComments) { - var firstComment = entry.node.trailingComments[0]; - if (firstComment && firstComment.range[0] >= metadata.end.offset) { - trailingComments = entry.node.trailingComments; - delete entry.node.trailingComments; - } - } - return trailingComments; - }; - CommentHandler.prototype.findLeadingComments = function (metadata) { - var leadingComments = []; - var target; - while (this.stack.length > 0) { - var entry = this.stack[this.stack.length - 1]; - if (entry && entry.start >= metadata.start.offset) { - target = entry.node; - this.stack.pop(); - } - else { - break; - } - } - if (target) { - var count = target.leadingComments ? target.leadingComments.length : 0; - for (var i = count - 1; i >= 0; --i) { - var comment = target.leadingComments[i]; - if (comment.range[1] <= metadata.start.offset) { - leadingComments.unshift(comment); - target.leadingComments.splice(i, 1); - } - } - if (target.leadingComments && target.leadingComments.length === 0) { - delete target.leadingComments; - } - return leadingComments; - } - for (var i = this.leading.length - 1; i >= 0; --i) { - var entry = this.leading[i]; - if (entry.start <= metadata.start.offset) { - leadingComments.unshift(entry.comment); - this.leading.splice(i, 1); - } - } - return leadingComments; - }; - CommentHandler.prototype.visitNode = function (node, metadata) { - if (node.type === syntax_1.Syntax.Program && node.body.length > 0) { - return; - } - this.insertInnerComments(node, metadata); - var trailingComments = this.findTrailingComments(metadata); - var leadingComments = this.findLeadingComments(metadata); - if (leadingComments.length > 0) { - node.leadingComments = leadingComments; - } - if (trailingComments.length > 0) { - node.trailingComments = trailingComments; - } - this.stack.push({ - node: node, - start: metadata.start.offset - }); - }; - CommentHandler.prototype.visitComment = function (node, metadata) { - var type = (node.type[0] === 'L') ? 'Line' : 'Block'; - var comment = { - type: type, - value: node.value - }; - if (node.range) { - comment.range = node.range; - } - if (node.loc) { - comment.loc = node.loc; - } - this.comments.push(comment); - if (this.attach) { - var entry = { - comment: { - type: type, - value: node.value, - range: [metadata.start.offset, metadata.end.offset] - }, - start: metadata.start.offset - }; - if (node.loc) { - entry.comment.loc = node.loc; - } - node.type = type; - this.leading.push(entry); - this.trailing.push(entry); - } - }; - CommentHandler.prototype.visit = function (node, metadata) { - if (node.type === 'LineComment') { - this.visitComment(node, metadata); - } - else if (node.type === 'BlockComment') { - this.visitComment(node, metadata); - } - else if (this.attach) { - this.visitNode(node, metadata); - } - }; - return CommentHandler; - }()); - exports.CommentHandler = CommentHandler; - - -/***/ }, -/* 2 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.Syntax = { - AssignmentExpression: 'AssignmentExpression', - AssignmentPattern: 'AssignmentPattern', - ArrayExpression: 'ArrayExpression', - ArrayPattern: 'ArrayPattern', - ArrowFunctionExpression: 'ArrowFunctionExpression', - AwaitExpression: 'AwaitExpression', - BlockStatement: 'BlockStatement', - BinaryExpression: 'BinaryExpression', - BreakStatement: 'BreakStatement', - CallExpression: 'CallExpression', - CatchClause: 'CatchClause', - ClassBody: 'ClassBody', - ClassDeclaration: 'ClassDeclaration', - ClassExpression: 'ClassExpression', - ConditionalExpression: 'ConditionalExpression', - ContinueStatement: 'ContinueStatement', - DoWhileStatement: 'DoWhileStatement', - DebuggerStatement: 'DebuggerStatement', - EmptyStatement: 'EmptyStatement', - ExportAllDeclaration: 'ExportAllDeclaration', - ExportDefaultDeclaration: 'ExportDefaultDeclaration', - ExportNamedDeclaration: 'ExportNamedDeclaration', - ExportSpecifier: 'ExportSpecifier', - ExpressionStatement: 'ExpressionStatement', - ForStatement: 'ForStatement', - ForOfStatement: 'ForOfStatement', - ForInStatement: 'ForInStatement', - FunctionDeclaration: 'FunctionDeclaration', - FunctionExpression: 'FunctionExpression', - Identifier: 'Identifier', - IfStatement: 'IfStatement', - ImportDeclaration: 'ImportDeclaration', - ImportDefaultSpecifier: 'ImportDefaultSpecifier', - ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', - ImportSpecifier: 'ImportSpecifier', - Literal: 'Literal', - LabeledStatement: 'LabeledStatement', - LogicalExpression: 'LogicalExpression', - MemberExpression: 'MemberExpression', - MetaProperty: 'MetaProperty', - MethodDefinition: 'MethodDefinition', - NewExpression: 'NewExpression', - ObjectExpression: 'ObjectExpression', - ObjectPattern: 'ObjectPattern', - Program: 'Program', - Property: 'Property', - RestElement: 'RestElement', - ReturnStatement: 'ReturnStatement', - SequenceExpression: 'SequenceExpression', - SpreadElement: 'SpreadElement', - Super: 'Super', - SwitchCase: 'SwitchCase', - SwitchStatement: 'SwitchStatement', - TaggedTemplateExpression: 'TaggedTemplateExpression', - TemplateElement: 'TemplateElement', - TemplateLiteral: 'TemplateLiteral', - ThisExpression: 'ThisExpression', - ThrowStatement: 'ThrowStatement', - TryStatement: 'TryStatement', - UnaryExpression: 'UnaryExpression', - UpdateExpression: 'UpdateExpression', - VariableDeclaration: 'VariableDeclaration', - VariableDeclarator: 'VariableDeclarator', - WhileStatement: 'WhileStatement', - WithStatement: 'WithStatement', - YieldExpression: 'YieldExpression' - }; - - -/***/ }, -/* 3 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; -/* istanbul ignore next */ - var __extends = (this && this.__extends) || (function () { - var extendStatics = Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || - function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; - return function (d, b) { - extendStatics(d, b); - function __() { this.constructor = d; } - d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); - }; - })(); - Object.defineProperty(exports, "__esModule", { value: true }); - var character_1 = __webpack_require__(4); - var JSXNode = __webpack_require__(5); - var jsx_syntax_1 = __webpack_require__(6); - var Node = __webpack_require__(7); - var parser_1 = __webpack_require__(8); - var token_1 = __webpack_require__(13); - var xhtml_entities_1 = __webpack_require__(14); - token_1.TokenName[100 /* Identifier */] = 'JSXIdentifier'; - token_1.TokenName[101 /* Text */] = 'JSXText'; - // Fully qualified element name, e.g. returns "svg:path" - function getQualifiedElementName(elementName) { - var qualifiedName; - switch (elementName.type) { - case jsx_syntax_1.JSXSyntax.JSXIdentifier: - var id = elementName; - qualifiedName = id.name; - break; - case jsx_syntax_1.JSXSyntax.JSXNamespacedName: - var ns = elementName; - qualifiedName = getQualifiedElementName(ns.namespace) + ':' + - getQualifiedElementName(ns.name); - break; - case jsx_syntax_1.JSXSyntax.JSXMemberExpression: - var expr = elementName; - qualifiedName = getQualifiedElementName(expr.object) + '.' + - getQualifiedElementName(expr.property); - break; - /* istanbul ignore next */ - default: - break; - } - return qualifiedName; - } - var JSXParser = (function (_super) { - __extends(JSXParser, _super); - function JSXParser(code, options, delegate) { - return _super.call(this, code, options, delegate) || this; - } - JSXParser.prototype.parsePrimaryExpression = function () { - return this.match('<') ? this.parseJSXRoot() : _super.prototype.parsePrimaryExpression.call(this); - }; - JSXParser.prototype.startJSX = function () { - // Unwind the scanner before the lookahead token. - this.scanner.index = this.startMarker.index; - this.scanner.lineNumber = this.startMarker.line; - this.scanner.lineStart = this.startMarker.index - this.startMarker.column; - }; - JSXParser.prototype.finishJSX = function () { - // Prime the next lookahead. - this.nextToken(); - }; - JSXParser.prototype.reenterJSX = function () { - this.startJSX(); - this.expectJSX('}'); - // Pop the closing '}' added from the lookahead. - if (this.config.tokens) { - this.tokens.pop(); - } - }; - JSXParser.prototype.createJSXNode = function () { - this.collectComments(); - return { - index: this.scanner.index, - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - }; - }; - JSXParser.prototype.createJSXChildNode = function () { - return { - index: this.scanner.index, - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - }; - }; - JSXParser.prototype.scanXHTMLEntity = function (quote) { - var result = '&'; - var valid = true; - var terminated = false; - var numeric = false; - var hex = false; - while (!this.scanner.eof() && valid && !terminated) { - var ch = this.scanner.source[this.scanner.index]; - if (ch === quote) { - break; - } - terminated = (ch === ';'); - result += ch; - ++this.scanner.index; - if (!terminated) { - switch (result.length) { - case 2: - // e.g. '{' - numeric = (ch === '#'); - break; - case 3: - if (numeric) { - // e.g. 'A' - hex = (ch === 'x'); - valid = hex || character_1.Character.isDecimalDigit(ch.charCodeAt(0)); - numeric = numeric && !hex; - } - break; - default: - valid = valid && !(numeric && !character_1.Character.isDecimalDigit(ch.charCodeAt(0))); - valid = valid && !(hex && !character_1.Character.isHexDigit(ch.charCodeAt(0))); - break; - } - } - } - if (valid && terminated && result.length > 2) { - // e.g. 'A' becomes just '#x41' - var str = result.substr(1, result.length - 2); - if (numeric && str.length > 1) { - result = String.fromCharCode(parseInt(str.substr(1), 10)); - } - else if (hex && str.length > 2) { - result = String.fromCharCode(parseInt('0' + str.substr(1), 16)); - } - else if (!numeric && !hex && xhtml_entities_1.XHTMLEntities[str]) { - result = xhtml_entities_1.XHTMLEntities[str]; - } - } - return result; - }; - // Scan the next JSX token. This replaces Scanner#lex when in JSX mode. - JSXParser.prototype.lexJSX = function () { - var cp = this.scanner.source.charCodeAt(this.scanner.index); - // < > / : = { } - if (cp === 60 || cp === 62 || cp === 47 || cp === 58 || cp === 61 || cp === 123 || cp === 125) { - var value = this.scanner.source[this.scanner.index++]; - return { - type: 7 /* Punctuator */, - value: value, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: this.scanner.index - 1, - end: this.scanner.index - }; - } - // " ' - if (cp === 34 || cp === 39) { - var start = this.scanner.index; - var quote = this.scanner.source[this.scanner.index++]; - var str = ''; - while (!this.scanner.eof()) { - var ch = this.scanner.source[this.scanner.index++]; - if (ch === quote) { - break; - } - else if (ch === '&') { - str += this.scanXHTMLEntity(quote); - } - else { - str += ch; - } - } - return { - type: 8 /* StringLiteral */, - value: str, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - } - // ... or . - if (cp === 46) { - var n1 = this.scanner.source.charCodeAt(this.scanner.index + 1); - var n2 = this.scanner.source.charCodeAt(this.scanner.index + 2); - var value = (n1 === 46 && n2 === 46) ? '...' : '.'; - var start = this.scanner.index; - this.scanner.index += value.length; - return { - type: 7 /* Punctuator */, - value: value, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - } - // ` - if (cp === 96) { - // Only placeholder, since it will be rescanned as a real assignment expression. - return { - type: 10 /* Template */, - value: '', - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: this.scanner.index, - end: this.scanner.index - }; - } - // Identifer can not contain backslash (char code 92). - if (character_1.Character.isIdentifierStart(cp) && (cp !== 92)) { - var start = this.scanner.index; - ++this.scanner.index; - while (!this.scanner.eof()) { - var ch = this.scanner.source.charCodeAt(this.scanner.index); - if (character_1.Character.isIdentifierPart(ch) && (ch !== 92)) { - ++this.scanner.index; - } - else if (ch === 45) { - // Hyphen (char code 45) can be part of an identifier. - ++this.scanner.index; - } - else { - break; - } - } - var id = this.scanner.source.slice(start, this.scanner.index); - return { - type: 100 /* Identifier */, - value: id, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - } - return this.scanner.lex(); - }; - JSXParser.prototype.nextJSXToken = function () { - this.collectComments(); - this.startMarker.index = this.scanner.index; - this.startMarker.line = this.scanner.lineNumber; - this.startMarker.column = this.scanner.index - this.scanner.lineStart; - var token = this.lexJSX(); - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - if (this.config.tokens) { - this.tokens.push(this.convertToken(token)); - } - return token; - }; - JSXParser.prototype.nextJSXText = function () { - this.startMarker.index = this.scanner.index; - this.startMarker.line = this.scanner.lineNumber; - this.startMarker.column = this.scanner.index - this.scanner.lineStart; - var start = this.scanner.index; - var text = ''; - while (!this.scanner.eof()) { - var ch = this.scanner.source[this.scanner.index]; - if (ch === '{' || ch === '<') { - break; - } - ++this.scanner.index; - text += ch; - if (character_1.Character.isLineTerminator(ch.charCodeAt(0))) { - ++this.scanner.lineNumber; - if (ch === '\r' && this.scanner.source[this.scanner.index] === '\n') { - ++this.scanner.index; - } - this.scanner.lineStart = this.scanner.index; - } - } - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - var token = { - type: 101 /* Text */, - value: text, - lineNumber: this.scanner.lineNumber, - lineStart: this.scanner.lineStart, - start: start, - end: this.scanner.index - }; - if ((text.length > 0) && this.config.tokens) { - this.tokens.push(this.convertToken(token)); - } - return token; - }; - JSXParser.prototype.peekJSXToken = function () { - var state = this.scanner.saveState(); - this.scanner.scanComments(); - var next = this.lexJSX(); - this.scanner.restoreState(state); - return next; - }; - // Expect the next JSX token to match the specified punctuator. - // If not, an exception will be thrown. - JSXParser.prototype.expectJSX = function (value) { - var token = this.nextJSXToken(); - if (token.type !== 7 /* Punctuator */ || token.value !== value) { - this.throwUnexpectedToken(token); - } - }; - // Return true if the next JSX token matches the specified punctuator. - JSXParser.prototype.matchJSX = function (value) { - var next = this.peekJSXToken(); - return next.type === 7 /* Punctuator */ && next.value === value; - }; - JSXParser.prototype.parseJSXIdentifier = function () { - var node = this.createJSXNode(); - var token = this.nextJSXToken(); - if (token.type !== 100 /* Identifier */) { - this.throwUnexpectedToken(token); - } - return this.finalize(node, new JSXNode.JSXIdentifier(token.value)); - }; - JSXParser.prototype.parseJSXElementName = function () { - var node = this.createJSXNode(); - var elementName = this.parseJSXIdentifier(); - if (this.matchJSX(':')) { - var namespace = elementName; - this.expectJSX(':'); - var name_1 = this.parseJSXIdentifier(); - elementName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_1)); - } - else if (this.matchJSX('.')) { - while (this.matchJSX('.')) { - var object = elementName; - this.expectJSX('.'); - var property = this.parseJSXIdentifier(); - elementName = this.finalize(node, new JSXNode.JSXMemberExpression(object, property)); - } - } - return elementName; - }; - JSXParser.prototype.parseJSXAttributeName = function () { - var node = this.createJSXNode(); - var attributeName; - var identifier = this.parseJSXIdentifier(); - if (this.matchJSX(':')) { - var namespace = identifier; - this.expectJSX(':'); - var name_2 = this.parseJSXIdentifier(); - attributeName = this.finalize(node, new JSXNode.JSXNamespacedName(namespace, name_2)); - } - else { - attributeName = identifier; - } - return attributeName; - }; - JSXParser.prototype.parseJSXStringLiteralAttribute = function () { - var node = this.createJSXNode(); - var token = this.nextJSXToken(); - if (token.type !== 8 /* StringLiteral */) { - this.throwUnexpectedToken(token); - } - var raw = this.getTokenRaw(token); - return this.finalize(node, new Node.Literal(token.value, raw)); - }; - JSXParser.prototype.parseJSXExpressionAttribute = function () { - var node = this.createJSXNode(); - this.expectJSX('{'); - this.finishJSX(); - if (this.match('}')) { - this.tolerateError('JSX attributes must only be assigned a non-empty expression'); - } - var expression = this.parseAssignmentExpression(); - this.reenterJSX(); - return this.finalize(node, new JSXNode.JSXExpressionContainer(expression)); - }; - JSXParser.prototype.parseJSXAttributeValue = function () { - return this.matchJSX('{') ? this.parseJSXExpressionAttribute() : - this.matchJSX('<') ? this.parseJSXElement() : this.parseJSXStringLiteralAttribute(); - }; - JSXParser.prototype.parseJSXNameValueAttribute = function () { - var node = this.createJSXNode(); - var name = this.parseJSXAttributeName(); - var value = null; - if (this.matchJSX('=')) { - this.expectJSX('='); - value = this.parseJSXAttributeValue(); - } - return this.finalize(node, new JSXNode.JSXAttribute(name, value)); - }; - JSXParser.prototype.parseJSXSpreadAttribute = function () { - var node = this.createJSXNode(); - this.expectJSX('{'); - this.expectJSX('...'); - this.finishJSX(); - var argument = this.parseAssignmentExpression(); - this.reenterJSX(); - return this.finalize(node, new JSXNode.JSXSpreadAttribute(argument)); - }; - JSXParser.prototype.parseJSXAttributes = function () { - var attributes = []; - while (!this.matchJSX('/') && !this.matchJSX('>')) { - var attribute = this.matchJSX('{') ? this.parseJSXSpreadAttribute() : - this.parseJSXNameValueAttribute(); - attributes.push(attribute); - } - return attributes; - }; - JSXParser.prototype.parseJSXOpeningElement = function () { - var node = this.createJSXNode(); - this.expectJSX('<'); - var name = this.parseJSXElementName(); - var attributes = this.parseJSXAttributes(); - var selfClosing = this.matchJSX('/'); - if (selfClosing) { - this.expectJSX('/'); - } - this.expectJSX('>'); - return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes)); - }; - JSXParser.prototype.parseJSXBoundaryElement = function () { - var node = this.createJSXNode(); - this.expectJSX('<'); - if (this.matchJSX('/')) { - this.expectJSX('/'); - var name_3 = this.parseJSXElementName(); - this.expectJSX('>'); - return this.finalize(node, new JSXNode.JSXClosingElement(name_3)); - } - var name = this.parseJSXElementName(); - var attributes = this.parseJSXAttributes(); - var selfClosing = this.matchJSX('/'); - if (selfClosing) { - this.expectJSX('/'); - } - this.expectJSX('>'); - return this.finalize(node, new JSXNode.JSXOpeningElement(name, selfClosing, attributes)); - }; - JSXParser.prototype.parseJSXEmptyExpression = function () { - var node = this.createJSXChildNode(); - this.collectComments(); - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - return this.finalize(node, new JSXNode.JSXEmptyExpression()); - }; - JSXParser.prototype.parseJSXExpressionContainer = function () { - var node = this.createJSXNode(); - this.expectJSX('{'); - var expression; - if (this.matchJSX('}')) { - expression = this.parseJSXEmptyExpression(); - this.expectJSX('}'); - } - else { - this.finishJSX(); - expression = this.parseAssignmentExpression(); - this.reenterJSX(); - } - return this.finalize(node, new JSXNode.JSXExpressionContainer(expression)); - }; - JSXParser.prototype.parseJSXChildren = function () { - var children = []; - while (!this.scanner.eof()) { - var node = this.createJSXChildNode(); - var token = this.nextJSXText(); - if (token.start < token.end) { - var raw = this.getTokenRaw(token); - var child = this.finalize(node, new JSXNode.JSXText(token.value, raw)); - children.push(child); - } - if (this.scanner.source[this.scanner.index] === '{') { - var container = this.parseJSXExpressionContainer(); - children.push(container); - } - else { - break; - } - } - return children; - }; - JSXParser.prototype.parseComplexJSXElement = function (el) { - var stack = []; - while (!this.scanner.eof()) { - el.children = el.children.concat(this.parseJSXChildren()); - var node = this.createJSXChildNode(); - var element = this.parseJSXBoundaryElement(); - if (element.type === jsx_syntax_1.JSXSyntax.JSXOpeningElement) { - var opening = element; - if (opening.selfClosing) { - var child = this.finalize(node, new JSXNode.JSXElement(opening, [], null)); - el.children.push(child); - } - else { - stack.push(el); - el = { node: node, opening: opening, closing: null, children: [] }; - } - } - if (element.type === jsx_syntax_1.JSXSyntax.JSXClosingElement) { - el.closing = element; - var open_1 = getQualifiedElementName(el.opening.name); - var close_1 = getQualifiedElementName(el.closing.name); - if (open_1 !== close_1) { - this.tolerateError('Expected corresponding JSX closing tag for %0', open_1); - } - if (stack.length > 0) { - var child = this.finalize(el.node, new JSXNode.JSXElement(el.opening, el.children, el.closing)); - el = stack[stack.length - 1]; - el.children.push(child); - stack.pop(); - } - else { - break; - } - } - } - return el; - }; - JSXParser.prototype.parseJSXElement = function () { - var node = this.createJSXNode(); - var opening = this.parseJSXOpeningElement(); - var children = []; - var closing = null; - if (!opening.selfClosing) { - var el = this.parseComplexJSXElement({ node: node, opening: opening, closing: closing, children: children }); - children = el.children; - closing = el.closing; - } - return this.finalize(node, new JSXNode.JSXElement(opening, children, closing)); - }; - JSXParser.prototype.parseJSXRoot = function () { - // Pop the opening '<' added from the lookahead. - if (this.config.tokens) { - this.tokens.pop(); - } - this.startJSX(); - var element = this.parseJSXElement(); - this.finishJSX(); - return element; - }; - JSXParser.prototype.isStartOfExpression = function () { - return _super.prototype.isStartOfExpression.call(this) || this.match('<'); - }; - return JSXParser; - }(parser_1.Parser)); - exports.JSXParser = JSXParser; - - -/***/ }, -/* 4 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - // See also tools/generate-unicode-regex.js. - var Regex = { - // Unicode v8.0.0 NonAsciiIdentifierStart: - NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B4\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0AF9\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58-\u0C5A\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D5F-\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA8FD\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE2B\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF50\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDDD8-\uDDDB\uDE00-\uDE2F\uDE44\uDE80-\uDEAA\uDF00-\uDF19]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]/, - // Unicode v8.0.0 NonAsciiIdentifierPart: - NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B4\u08E3-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC-\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0AF9\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58-\u0C5A\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D5F-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6\u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F5\u13F8-\u13FD\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FD5\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA7AD\uA7B0-\uA7B7\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA8FD\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB65\uAB70-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2F\uFE33\uFE34\uFE4D-\uFE4F\uFE70-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDCE0-\uDCF2\uDCF4\uDCF5\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48\uDC80-\uDCB2\uDCC0-\uDCF2]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDCA-\uDDCC\uDDD0-\uDDDA\uDDDC\uDE00-\uDE11\uDE13-\uDE37\uDE80-\uDE86\uDE88\uDE8A-\uDE8D\uDE8F-\uDE9D\uDE9F-\uDEA8\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF00-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF50\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDDD8-\uDDDD\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9\uDF00-\uDF19\uDF1D-\uDF2B\uDF30-\uDF39]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF99]|\uD809[\uDC00-\uDC6E\uDC80-\uDD43]|[\uD80C\uD840-\uD868\uD86A-\uD86C\uD86F-\uD872][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD811[\uDC00-\uDE46]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD836[\uDE00-\uDE36\uDE3B-\uDE6C\uDE75\uDE84\uDE9B-\uDE9F\uDEA1-\uDEAF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D\uDC20-\uDFFF]|\uD873[\uDC00-\uDEA1]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/ - }; - exports.Character = { - /* tslint:disable:no-bitwise */ - fromCodePoint: function (cp) { - return (cp < 0x10000) ? String.fromCharCode(cp) : - String.fromCharCode(0xD800 + ((cp - 0x10000) >> 10)) + - String.fromCharCode(0xDC00 + ((cp - 0x10000) & 1023)); - }, - // https://tc39.github.io/ecma262/#sec-white-space - isWhiteSpace: function (cp) { - return (cp === 0x20) || (cp === 0x09) || (cp === 0x0B) || (cp === 0x0C) || (cp === 0xA0) || - (cp >= 0x1680 && [0x1680, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(cp) >= 0); - }, - // https://tc39.github.io/ecma262/#sec-line-terminators - isLineTerminator: function (cp) { - return (cp === 0x0A) || (cp === 0x0D) || (cp === 0x2028) || (cp === 0x2029); - }, - // https://tc39.github.io/ecma262/#sec-names-and-keywords - isIdentifierStart: function (cp) { - return (cp === 0x24) || (cp === 0x5F) || - (cp >= 0x41 && cp <= 0x5A) || - (cp >= 0x61 && cp <= 0x7A) || - (cp === 0x5C) || - ((cp >= 0x80) && Regex.NonAsciiIdentifierStart.test(exports.Character.fromCodePoint(cp))); - }, - isIdentifierPart: function (cp) { - return (cp === 0x24) || (cp === 0x5F) || - (cp >= 0x41 && cp <= 0x5A) || - (cp >= 0x61 && cp <= 0x7A) || - (cp >= 0x30 && cp <= 0x39) || - (cp === 0x5C) || - ((cp >= 0x80) && Regex.NonAsciiIdentifierPart.test(exports.Character.fromCodePoint(cp))); - }, - // https://tc39.github.io/ecma262/#sec-literals-numeric-literals - isDecimalDigit: function (cp) { - return (cp >= 0x30 && cp <= 0x39); // 0..9 - }, - isHexDigit: function (cp) { - return (cp >= 0x30 && cp <= 0x39) || - (cp >= 0x41 && cp <= 0x46) || - (cp >= 0x61 && cp <= 0x66); // a..f - }, - isOctalDigit: function (cp) { - return (cp >= 0x30 && cp <= 0x37); // 0..7 - } - }; - - -/***/ }, -/* 5 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var jsx_syntax_1 = __webpack_require__(6); - /* tslint:disable:max-classes-per-file */ - var JSXClosingElement = (function () { - function JSXClosingElement(name) { - this.type = jsx_syntax_1.JSXSyntax.JSXClosingElement; - this.name = name; - } - return JSXClosingElement; - }()); - exports.JSXClosingElement = JSXClosingElement; - var JSXElement = (function () { - function JSXElement(openingElement, children, closingElement) { - this.type = jsx_syntax_1.JSXSyntax.JSXElement; - this.openingElement = openingElement; - this.children = children; - this.closingElement = closingElement; - } - return JSXElement; - }()); - exports.JSXElement = JSXElement; - var JSXEmptyExpression = (function () { - function JSXEmptyExpression() { - this.type = jsx_syntax_1.JSXSyntax.JSXEmptyExpression; - } - return JSXEmptyExpression; - }()); - exports.JSXEmptyExpression = JSXEmptyExpression; - var JSXExpressionContainer = (function () { - function JSXExpressionContainer(expression) { - this.type = jsx_syntax_1.JSXSyntax.JSXExpressionContainer; - this.expression = expression; - } - return JSXExpressionContainer; - }()); - exports.JSXExpressionContainer = JSXExpressionContainer; - var JSXIdentifier = (function () { - function JSXIdentifier(name) { - this.type = jsx_syntax_1.JSXSyntax.JSXIdentifier; - this.name = name; - } - return JSXIdentifier; - }()); - exports.JSXIdentifier = JSXIdentifier; - var JSXMemberExpression = (function () { - function JSXMemberExpression(object, property) { - this.type = jsx_syntax_1.JSXSyntax.JSXMemberExpression; - this.object = object; - this.property = property; - } - return JSXMemberExpression; - }()); - exports.JSXMemberExpression = JSXMemberExpression; - var JSXAttribute = (function () { - function JSXAttribute(name, value) { - this.type = jsx_syntax_1.JSXSyntax.JSXAttribute; - this.name = name; - this.value = value; - } - return JSXAttribute; - }()); - exports.JSXAttribute = JSXAttribute; - var JSXNamespacedName = (function () { - function JSXNamespacedName(namespace, name) { - this.type = jsx_syntax_1.JSXSyntax.JSXNamespacedName; - this.namespace = namespace; - this.name = name; - } - return JSXNamespacedName; - }()); - exports.JSXNamespacedName = JSXNamespacedName; - var JSXOpeningElement = (function () { - function JSXOpeningElement(name, selfClosing, attributes) { - this.type = jsx_syntax_1.JSXSyntax.JSXOpeningElement; - this.name = name; - this.selfClosing = selfClosing; - this.attributes = attributes; - } - return JSXOpeningElement; - }()); - exports.JSXOpeningElement = JSXOpeningElement; - var JSXSpreadAttribute = (function () { - function JSXSpreadAttribute(argument) { - this.type = jsx_syntax_1.JSXSyntax.JSXSpreadAttribute; - this.argument = argument; - } - return JSXSpreadAttribute; - }()); - exports.JSXSpreadAttribute = JSXSpreadAttribute; - var JSXText = (function () { - function JSXText(value, raw) { - this.type = jsx_syntax_1.JSXSyntax.JSXText; - this.value = value; - this.raw = raw; - } - return JSXText; - }()); - exports.JSXText = JSXText; - - -/***/ }, -/* 6 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - exports.JSXSyntax = { - JSXAttribute: 'JSXAttribute', - JSXClosingElement: 'JSXClosingElement', - JSXElement: 'JSXElement', - JSXEmptyExpression: 'JSXEmptyExpression', - JSXExpressionContainer: 'JSXExpressionContainer', - JSXIdentifier: 'JSXIdentifier', - JSXMemberExpression: 'JSXMemberExpression', - JSXNamespacedName: 'JSXNamespacedName', - JSXOpeningElement: 'JSXOpeningElement', - JSXSpreadAttribute: 'JSXSpreadAttribute', - JSXText: 'JSXText' - }; - - -/***/ }, -/* 7 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var syntax_1 = __webpack_require__(2); - /* tslint:disable:max-classes-per-file */ - var ArrayExpression = (function () { - function ArrayExpression(elements) { - this.type = syntax_1.Syntax.ArrayExpression; - this.elements = elements; - } - return ArrayExpression; - }()); - exports.ArrayExpression = ArrayExpression; - var ArrayPattern = (function () { - function ArrayPattern(elements) { - this.type = syntax_1.Syntax.ArrayPattern; - this.elements = elements; - } - return ArrayPattern; - }()); - exports.ArrayPattern = ArrayPattern; - var ArrowFunctionExpression = (function () { - function ArrowFunctionExpression(params, body, expression) { - this.type = syntax_1.Syntax.ArrowFunctionExpression; - this.id = null; - this.params = params; - this.body = body; - this.generator = false; - this.expression = expression; - this.async = false; - } - return ArrowFunctionExpression; - }()); - exports.ArrowFunctionExpression = ArrowFunctionExpression; - var AssignmentExpression = (function () { - function AssignmentExpression(operator, left, right) { - this.type = syntax_1.Syntax.AssignmentExpression; - this.operator = operator; - this.left = left; - this.right = right; - } - return AssignmentExpression; - }()); - exports.AssignmentExpression = AssignmentExpression; - var AssignmentPattern = (function () { - function AssignmentPattern(left, right) { - this.type = syntax_1.Syntax.AssignmentPattern; - this.left = left; - this.right = right; - } - return AssignmentPattern; - }()); - exports.AssignmentPattern = AssignmentPattern; - var AsyncArrowFunctionExpression = (function () { - function AsyncArrowFunctionExpression(params, body, expression) { - this.type = syntax_1.Syntax.ArrowFunctionExpression; - this.id = null; - this.params = params; - this.body = body; - this.generator = false; - this.expression = expression; - this.async = true; - } - return AsyncArrowFunctionExpression; - }()); - exports.AsyncArrowFunctionExpression = AsyncArrowFunctionExpression; - var AsyncFunctionDeclaration = (function () { - function AsyncFunctionDeclaration(id, params, body) { - this.type = syntax_1.Syntax.FunctionDeclaration; - this.id = id; - this.params = params; - this.body = body; - this.generator = false; - this.expression = false; - this.async = true; - } - return AsyncFunctionDeclaration; - }()); - exports.AsyncFunctionDeclaration = AsyncFunctionDeclaration; - var AsyncFunctionExpression = (function () { - function AsyncFunctionExpression(id, params, body) { - this.type = syntax_1.Syntax.FunctionExpression; - this.id = id; - this.params = params; - this.body = body; - this.generator = false; - this.expression = false; - this.async = true; - } - return AsyncFunctionExpression; - }()); - exports.AsyncFunctionExpression = AsyncFunctionExpression; - var AwaitExpression = (function () { - function AwaitExpression(argument) { - this.type = syntax_1.Syntax.AwaitExpression; - this.argument = argument; - } - return AwaitExpression; - }()); - exports.AwaitExpression = AwaitExpression; - var BinaryExpression = (function () { - function BinaryExpression(operator, left, right) { - var logical = (operator === '||' || operator === '&&'); - this.type = logical ? syntax_1.Syntax.LogicalExpression : syntax_1.Syntax.BinaryExpression; - this.operator = operator; - this.left = left; - this.right = right; - } - return BinaryExpression; - }()); - exports.BinaryExpression = BinaryExpression; - var BlockStatement = (function () { - function BlockStatement(body) { - this.type = syntax_1.Syntax.BlockStatement; - this.body = body; - } - return BlockStatement; - }()); - exports.BlockStatement = BlockStatement; - var BreakStatement = (function () { - function BreakStatement(label) { - this.type = syntax_1.Syntax.BreakStatement; - this.label = label; - } - return BreakStatement; - }()); - exports.BreakStatement = BreakStatement; - var CallExpression = (function () { - function CallExpression(callee, args) { - this.type = syntax_1.Syntax.CallExpression; - this.callee = callee; - this.arguments = args; - } - return CallExpression; - }()); - exports.CallExpression = CallExpression; - var CatchClause = (function () { - function CatchClause(param, body) { - this.type = syntax_1.Syntax.CatchClause; - this.param = param; - this.body = body; - } - return CatchClause; - }()); - exports.CatchClause = CatchClause; - var ClassBody = (function () { - function ClassBody(body) { - this.type = syntax_1.Syntax.ClassBody; - this.body = body; - } - return ClassBody; - }()); - exports.ClassBody = ClassBody; - var ClassDeclaration = (function () { - function ClassDeclaration(id, superClass, body) { - this.type = syntax_1.Syntax.ClassDeclaration; - this.id = id; - this.superClass = superClass; - this.body = body; - } - return ClassDeclaration; - }()); - exports.ClassDeclaration = ClassDeclaration; - var ClassExpression = (function () { - function ClassExpression(id, superClass, body) { - this.type = syntax_1.Syntax.ClassExpression; - this.id = id; - this.superClass = superClass; - this.body = body; - } - return ClassExpression; - }()); - exports.ClassExpression = ClassExpression; - var ComputedMemberExpression = (function () { - function ComputedMemberExpression(object, property) { - this.type = syntax_1.Syntax.MemberExpression; - this.computed = true; - this.object = object; - this.property = property; - } - return ComputedMemberExpression; - }()); - exports.ComputedMemberExpression = ComputedMemberExpression; - var ConditionalExpression = (function () { - function ConditionalExpression(test, consequent, alternate) { - this.type = syntax_1.Syntax.ConditionalExpression; - this.test = test; - this.consequent = consequent; - this.alternate = alternate; - } - return ConditionalExpression; - }()); - exports.ConditionalExpression = ConditionalExpression; - var ContinueStatement = (function () { - function ContinueStatement(label) { - this.type = syntax_1.Syntax.ContinueStatement; - this.label = label; - } - return ContinueStatement; - }()); - exports.ContinueStatement = ContinueStatement; - var DebuggerStatement = (function () { - function DebuggerStatement() { - this.type = syntax_1.Syntax.DebuggerStatement; - } - return DebuggerStatement; - }()); - exports.DebuggerStatement = DebuggerStatement; - var Directive = (function () { - function Directive(expression, directive) { - this.type = syntax_1.Syntax.ExpressionStatement; - this.expression = expression; - this.directive = directive; - } - return Directive; - }()); - exports.Directive = Directive; - var DoWhileStatement = (function () { - function DoWhileStatement(body, test) { - this.type = syntax_1.Syntax.DoWhileStatement; - this.body = body; - this.test = test; - } - return DoWhileStatement; - }()); - exports.DoWhileStatement = DoWhileStatement; - var EmptyStatement = (function () { - function EmptyStatement() { - this.type = syntax_1.Syntax.EmptyStatement; - } - return EmptyStatement; - }()); - exports.EmptyStatement = EmptyStatement; - var ExportAllDeclaration = (function () { - function ExportAllDeclaration(source) { - this.type = syntax_1.Syntax.ExportAllDeclaration; - this.source = source; - } - return ExportAllDeclaration; - }()); - exports.ExportAllDeclaration = ExportAllDeclaration; - var ExportDefaultDeclaration = (function () { - function ExportDefaultDeclaration(declaration) { - this.type = syntax_1.Syntax.ExportDefaultDeclaration; - this.declaration = declaration; - } - return ExportDefaultDeclaration; - }()); - exports.ExportDefaultDeclaration = ExportDefaultDeclaration; - var ExportNamedDeclaration = (function () { - function ExportNamedDeclaration(declaration, specifiers, source) { - this.type = syntax_1.Syntax.ExportNamedDeclaration; - this.declaration = declaration; - this.specifiers = specifiers; - this.source = source; - } - return ExportNamedDeclaration; - }()); - exports.ExportNamedDeclaration = ExportNamedDeclaration; - var ExportSpecifier = (function () { - function ExportSpecifier(local, exported) { - this.type = syntax_1.Syntax.ExportSpecifier; - this.exported = exported; - this.local = local; - } - return ExportSpecifier; - }()); - exports.ExportSpecifier = ExportSpecifier; - var ExpressionStatement = (function () { - function ExpressionStatement(expression) { - this.type = syntax_1.Syntax.ExpressionStatement; - this.expression = expression; - } - return ExpressionStatement; - }()); - exports.ExpressionStatement = ExpressionStatement; - var ForInStatement = (function () { - function ForInStatement(left, right, body) { - this.type = syntax_1.Syntax.ForInStatement; - this.left = left; - this.right = right; - this.body = body; - this.each = false; - } - return ForInStatement; - }()); - exports.ForInStatement = ForInStatement; - var ForOfStatement = (function () { - function ForOfStatement(left, right, body) { - this.type = syntax_1.Syntax.ForOfStatement; - this.left = left; - this.right = right; - this.body = body; - } - return ForOfStatement; - }()); - exports.ForOfStatement = ForOfStatement; - var ForStatement = (function () { - function ForStatement(init, test, update, body) { - this.type = syntax_1.Syntax.ForStatement; - this.init = init; - this.test = test; - this.update = update; - this.body = body; - } - return ForStatement; - }()); - exports.ForStatement = ForStatement; - var FunctionDeclaration = (function () { - function FunctionDeclaration(id, params, body, generator) { - this.type = syntax_1.Syntax.FunctionDeclaration; - this.id = id; - this.params = params; - this.body = body; - this.generator = generator; - this.expression = false; - this.async = false; - } - return FunctionDeclaration; - }()); - exports.FunctionDeclaration = FunctionDeclaration; - var FunctionExpression = (function () { - function FunctionExpression(id, params, body, generator) { - this.type = syntax_1.Syntax.FunctionExpression; - this.id = id; - this.params = params; - this.body = body; - this.generator = generator; - this.expression = false; - this.async = false; - } - return FunctionExpression; - }()); - exports.FunctionExpression = FunctionExpression; - var Identifier = (function () { - function Identifier(name) { - this.type = syntax_1.Syntax.Identifier; - this.name = name; - } - return Identifier; - }()); - exports.Identifier = Identifier; - var IfStatement = (function () { - function IfStatement(test, consequent, alternate) { - this.type = syntax_1.Syntax.IfStatement; - this.test = test; - this.consequent = consequent; - this.alternate = alternate; - } - return IfStatement; - }()); - exports.IfStatement = IfStatement; - var ImportDeclaration = (function () { - function ImportDeclaration(specifiers, source) { - this.type = syntax_1.Syntax.ImportDeclaration; - this.specifiers = specifiers; - this.source = source; - } - return ImportDeclaration; - }()); - exports.ImportDeclaration = ImportDeclaration; - var ImportDefaultSpecifier = (function () { - function ImportDefaultSpecifier(local) { - this.type = syntax_1.Syntax.ImportDefaultSpecifier; - this.local = local; - } - return ImportDefaultSpecifier; - }()); - exports.ImportDefaultSpecifier = ImportDefaultSpecifier; - var ImportNamespaceSpecifier = (function () { - function ImportNamespaceSpecifier(local) { - this.type = syntax_1.Syntax.ImportNamespaceSpecifier; - this.local = local; - } - return ImportNamespaceSpecifier; - }()); - exports.ImportNamespaceSpecifier = ImportNamespaceSpecifier; - var ImportSpecifier = (function () { - function ImportSpecifier(local, imported) { - this.type = syntax_1.Syntax.ImportSpecifier; - this.local = local; - this.imported = imported; - } - return ImportSpecifier; - }()); - exports.ImportSpecifier = ImportSpecifier; - var LabeledStatement = (function () { - function LabeledStatement(label, body) { - this.type = syntax_1.Syntax.LabeledStatement; - this.label = label; - this.body = body; - } - return LabeledStatement; - }()); - exports.LabeledStatement = LabeledStatement; - var Literal = (function () { - function Literal(value, raw) { - this.type = syntax_1.Syntax.Literal; - this.value = value; - this.raw = raw; - } - return Literal; - }()); - exports.Literal = Literal; - var MetaProperty = (function () { - function MetaProperty(meta, property) { - this.type = syntax_1.Syntax.MetaProperty; - this.meta = meta; - this.property = property; - } - return MetaProperty; - }()); - exports.MetaProperty = MetaProperty; - var MethodDefinition = (function () { - function MethodDefinition(key, computed, value, kind, isStatic) { - this.type = syntax_1.Syntax.MethodDefinition; - this.key = key; - this.computed = computed; - this.value = value; - this.kind = kind; - this.static = isStatic; - } - return MethodDefinition; - }()); - exports.MethodDefinition = MethodDefinition; - var Module = (function () { - function Module(body) { - this.type = syntax_1.Syntax.Program; - this.body = body; - this.sourceType = 'module'; - } - return Module; - }()); - exports.Module = Module; - var NewExpression = (function () { - function NewExpression(callee, args) { - this.type = syntax_1.Syntax.NewExpression; - this.callee = callee; - this.arguments = args; - } - return NewExpression; - }()); - exports.NewExpression = NewExpression; - var ObjectExpression = (function () { - function ObjectExpression(properties) { - this.type = syntax_1.Syntax.ObjectExpression; - this.properties = properties; - } - return ObjectExpression; - }()); - exports.ObjectExpression = ObjectExpression; - var ObjectPattern = (function () { - function ObjectPattern(properties) { - this.type = syntax_1.Syntax.ObjectPattern; - this.properties = properties; - } - return ObjectPattern; - }()); - exports.ObjectPattern = ObjectPattern; - var Property = (function () { - function Property(kind, key, computed, value, method, shorthand) { - this.type = syntax_1.Syntax.Property; - this.key = key; - this.computed = computed; - this.value = value; - this.kind = kind; - this.method = method; - this.shorthand = shorthand; - } - return Property; - }()); - exports.Property = Property; - var RegexLiteral = (function () { - function RegexLiteral(value, raw, pattern, flags) { - this.type = syntax_1.Syntax.Literal; - this.value = value; - this.raw = raw; - this.regex = { pattern: pattern, flags: flags }; - } - return RegexLiteral; - }()); - exports.RegexLiteral = RegexLiteral; - var RestElement = (function () { - function RestElement(argument) { - this.type = syntax_1.Syntax.RestElement; - this.argument = argument; - } - return RestElement; - }()); - exports.RestElement = RestElement; - var ReturnStatement = (function () { - function ReturnStatement(argument) { - this.type = syntax_1.Syntax.ReturnStatement; - this.argument = argument; - } - return ReturnStatement; - }()); - exports.ReturnStatement = ReturnStatement; - var Script = (function () { - function Script(body) { - this.type = syntax_1.Syntax.Program; - this.body = body; - this.sourceType = 'script'; - } - return Script; - }()); - exports.Script = Script; - var SequenceExpression = (function () { - function SequenceExpression(expressions) { - this.type = syntax_1.Syntax.SequenceExpression; - this.expressions = expressions; - } - return SequenceExpression; - }()); - exports.SequenceExpression = SequenceExpression; - var SpreadElement = (function () { - function SpreadElement(argument) { - this.type = syntax_1.Syntax.SpreadElement; - this.argument = argument; - } - return SpreadElement; - }()); - exports.SpreadElement = SpreadElement; - var StaticMemberExpression = (function () { - function StaticMemberExpression(object, property) { - this.type = syntax_1.Syntax.MemberExpression; - this.computed = false; - this.object = object; - this.property = property; - } - return StaticMemberExpression; - }()); - exports.StaticMemberExpression = StaticMemberExpression; - var Super = (function () { - function Super() { - this.type = syntax_1.Syntax.Super; - } - return Super; - }()); - exports.Super = Super; - var SwitchCase = (function () { - function SwitchCase(test, consequent) { - this.type = syntax_1.Syntax.SwitchCase; - this.test = test; - this.consequent = consequent; - } - return SwitchCase; - }()); - exports.SwitchCase = SwitchCase; - var SwitchStatement = (function () { - function SwitchStatement(discriminant, cases) { - this.type = syntax_1.Syntax.SwitchStatement; - this.discriminant = discriminant; - this.cases = cases; - } - return SwitchStatement; - }()); - exports.SwitchStatement = SwitchStatement; - var TaggedTemplateExpression = (function () { - function TaggedTemplateExpression(tag, quasi) { - this.type = syntax_1.Syntax.TaggedTemplateExpression; - this.tag = tag; - this.quasi = quasi; - } - return TaggedTemplateExpression; - }()); - exports.TaggedTemplateExpression = TaggedTemplateExpression; - var TemplateElement = (function () { - function TemplateElement(value, tail) { - this.type = syntax_1.Syntax.TemplateElement; - this.value = value; - this.tail = tail; - } - return TemplateElement; - }()); - exports.TemplateElement = TemplateElement; - var TemplateLiteral = (function () { - function TemplateLiteral(quasis, expressions) { - this.type = syntax_1.Syntax.TemplateLiteral; - this.quasis = quasis; - this.expressions = expressions; - } - return TemplateLiteral; - }()); - exports.TemplateLiteral = TemplateLiteral; - var ThisExpression = (function () { - function ThisExpression() { - this.type = syntax_1.Syntax.ThisExpression; - } - return ThisExpression; - }()); - exports.ThisExpression = ThisExpression; - var ThrowStatement = (function () { - function ThrowStatement(argument) { - this.type = syntax_1.Syntax.ThrowStatement; - this.argument = argument; - } - return ThrowStatement; - }()); - exports.ThrowStatement = ThrowStatement; - var TryStatement = (function () { - function TryStatement(block, handler, finalizer) { - this.type = syntax_1.Syntax.TryStatement; - this.block = block; - this.handler = handler; - this.finalizer = finalizer; - } - return TryStatement; - }()); - exports.TryStatement = TryStatement; - var UnaryExpression = (function () { - function UnaryExpression(operator, argument) { - this.type = syntax_1.Syntax.UnaryExpression; - this.operator = operator; - this.argument = argument; - this.prefix = true; - } - return UnaryExpression; - }()); - exports.UnaryExpression = UnaryExpression; - var UpdateExpression = (function () { - function UpdateExpression(operator, argument, prefix) { - this.type = syntax_1.Syntax.UpdateExpression; - this.operator = operator; - this.argument = argument; - this.prefix = prefix; - } - return UpdateExpression; - }()); - exports.UpdateExpression = UpdateExpression; - var VariableDeclaration = (function () { - function VariableDeclaration(declarations, kind) { - this.type = syntax_1.Syntax.VariableDeclaration; - this.declarations = declarations; - this.kind = kind; - } - return VariableDeclaration; - }()); - exports.VariableDeclaration = VariableDeclaration; - var VariableDeclarator = (function () { - function VariableDeclarator(id, init) { - this.type = syntax_1.Syntax.VariableDeclarator; - this.id = id; - this.init = init; - } - return VariableDeclarator; - }()); - exports.VariableDeclarator = VariableDeclarator; - var WhileStatement = (function () { - function WhileStatement(test, body) { - this.type = syntax_1.Syntax.WhileStatement; - this.test = test; - this.body = body; - } - return WhileStatement; - }()); - exports.WhileStatement = WhileStatement; - var WithStatement = (function () { - function WithStatement(object, body) { - this.type = syntax_1.Syntax.WithStatement; - this.object = object; - this.body = body; - } - return WithStatement; - }()); - exports.WithStatement = WithStatement; - var YieldExpression = (function () { - function YieldExpression(argument, delegate) { - this.type = syntax_1.Syntax.YieldExpression; - this.argument = argument; - this.delegate = delegate; - } - return YieldExpression; - }()); - exports.YieldExpression = YieldExpression; - - -/***/ }, -/* 8 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var assert_1 = __webpack_require__(9); - var error_handler_1 = __webpack_require__(10); - var messages_1 = __webpack_require__(11); - var Node = __webpack_require__(7); - var scanner_1 = __webpack_require__(12); - var syntax_1 = __webpack_require__(2); - var token_1 = __webpack_require__(13); - var ArrowParameterPlaceHolder = 'ArrowParameterPlaceHolder'; - var Parser = (function () { - function Parser(code, options, delegate) { - if (options === void 0) { options = {}; } - this.config = { - range: (typeof options.range === 'boolean') && options.range, - loc: (typeof options.loc === 'boolean') && options.loc, - source: null, - tokens: (typeof options.tokens === 'boolean') && options.tokens, - comment: (typeof options.comment === 'boolean') && options.comment, - tolerant: (typeof options.tolerant === 'boolean') && options.tolerant - }; - if (this.config.loc && options.source && options.source !== null) { - this.config.source = String(options.source); - } - this.delegate = delegate; - this.errorHandler = new error_handler_1.ErrorHandler(); - this.errorHandler.tolerant = this.config.tolerant; - this.scanner = new scanner_1.Scanner(code, this.errorHandler); - this.scanner.trackComment = this.config.comment; - this.operatorPrecedence = { - ')': 0, - ';': 0, - ',': 0, - '=': 0, - ']': 0, - '||': 1, - '&&': 2, - '|': 3, - '^': 4, - '&': 5, - '==': 6, - '!=': 6, - '===': 6, - '!==': 6, - '<': 7, - '>': 7, - '<=': 7, - '>=': 7, - '<<': 8, - '>>': 8, - '>>>': 8, - '+': 9, - '-': 9, - '*': 11, - '/': 11, - '%': 11 - }; - this.lookahead = { - type: 2 /* EOF */, - value: '', - lineNumber: this.scanner.lineNumber, - lineStart: 0, - start: 0, - end: 0 - }; - this.hasLineTerminator = false; - this.context = { - isModule: false, - await: false, - allowIn: true, - allowStrictDirective: true, - allowYield: true, - firstCoverInitializedNameError: null, - isAssignmentTarget: false, - isBindingElement: false, - inFunctionBody: false, - inIteration: false, - inSwitch: false, - labelSet: {}, - strict: false - }; - this.tokens = []; - this.startMarker = { - index: 0, - line: this.scanner.lineNumber, - column: 0 - }; - this.lastMarker = { - index: 0, - line: this.scanner.lineNumber, - column: 0 - }; - this.nextToken(); - this.lastMarker = { - index: this.scanner.index, - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - }; - } - Parser.prototype.throwError = function (messageFormat) { - var values = []; - for (var _i = 1; _i < arguments.length; _i++) { - values[_i - 1] = arguments[_i]; - } - var args = Array.prototype.slice.call(arguments, 1); - var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) { - assert_1.assert(idx < args.length, 'Message reference must be in range'); - return args[idx]; - }); - var index = this.lastMarker.index; - var line = this.lastMarker.line; - var column = this.lastMarker.column + 1; - throw this.errorHandler.createError(index, line, column, msg); - }; - Parser.prototype.tolerateError = function (messageFormat) { - var values = []; - for (var _i = 1; _i < arguments.length; _i++) { - values[_i - 1] = arguments[_i]; - } - var args = Array.prototype.slice.call(arguments, 1); - var msg = messageFormat.replace(/%(\d)/g, function (whole, idx) { - assert_1.assert(idx < args.length, 'Message reference must be in range'); - return args[idx]; - }); - var index = this.lastMarker.index; - var line = this.scanner.lineNumber; - var column = this.lastMarker.column + 1; - this.errorHandler.tolerateError(index, line, column, msg); - }; - // Throw an exception because of the token. - Parser.prototype.unexpectedTokenError = function (token, message) { - var msg = message || messages_1.Messages.UnexpectedToken; - var value; - if (token) { - if (!message) { - msg = (token.type === 2 /* EOF */) ? messages_1.Messages.UnexpectedEOS : - (token.type === 3 /* Identifier */) ? messages_1.Messages.UnexpectedIdentifier : - (token.type === 6 /* NumericLiteral */) ? messages_1.Messages.UnexpectedNumber : - (token.type === 8 /* StringLiteral */) ? messages_1.Messages.UnexpectedString : - (token.type === 10 /* Template */) ? messages_1.Messages.UnexpectedTemplate : - messages_1.Messages.UnexpectedToken; - if (token.type === 4 /* Keyword */) { - if (this.scanner.isFutureReservedWord(token.value)) { - msg = messages_1.Messages.UnexpectedReserved; - } - else if (this.context.strict && this.scanner.isStrictModeReservedWord(token.value)) { - msg = messages_1.Messages.StrictReservedWord; - } - } - } - value = token.value; - } - else { - value = 'ILLEGAL'; - } - msg = msg.replace('%0', value); - if (token && typeof token.lineNumber === 'number') { - var index = token.start; - var line = token.lineNumber; - var lastMarkerLineStart = this.lastMarker.index - this.lastMarker.column; - var column = token.start - lastMarkerLineStart + 1; - return this.errorHandler.createError(index, line, column, msg); - } - else { - var index = this.lastMarker.index; - var line = this.lastMarker.line; - var column = this.lastMarker.column + 1; - return this.errorHandler.createError(index, line, column, msg); - } - }; - Parser.prototype.throwUnexpectedToken = function (token, message) { - throw this.unexpectedTokenError(token, message); - }; - Parser.prototype.tolerateUnexpectedToken = function (token, message) { - this.errorHandler.tolerate(this.unexpectedTokenError(token, message)); - }; - Parser.prototype.collectComments = function () { - if (!this.config.comment) { - this.scanner.scanComments(); - } - else { - var comments = this.scanner.scanComments(); - if (comments.length > 0 && this.delegate) { - for (var i = 0; i < comments.length; ++i) { - var e = comments[i]; - var node = void 0; - node = { - type: e.multiLine ? 'BlockComment' : 'LineComment', - value: this.scanner.source.slice(e.slice[0], e.slice[1]) - }; - if (this.config.range) { - node.range = e.range; - } - if (this.config.loc) { - node.loc = e.loc; - } - var metadata = { - start: { - line: e.loc.start.line, - column: e.loc.start.column, - offset: e.range[0] - }, - end: { - line: e.loc.end.line, - column: e.loc.end.column, - offset: e.range[1] - } - }; - this.delegate(node, metadata); - } - } - } - }; - // From internal representation to an external structure - Parser.prototype.getTokenRaw = function (token) { - return this.scanner.source.slice(token.start, token.end); - }; - Parser.prototype.convertToken = function (token) { - var t = { - type: token_1.TokenName[token.type], - value: this.getTokenRaw(token) - }; - if (this.config.range) { - t.range = [token.start, token.end]; - } - if (this.config.loc) { - t.loc = { - start: { - line: this.startMarker.line, - column: this.startMarker.column - }, - end: { - line: this.scanner.lineNumber, - column: this.scanner.index - this.scanner.lineStart - } - }; - } - if (token.type === 9 /* RegularExpression */) { - var pattern = token.pattern; - var flags = token.flags; - t.regex = { pattern: pattern, flags: flags }; - } - return t; - }; - Parser.prototype.nextToken = function () { - var token = this.lookahead; - this.lastMarker.index = this.scanner.index; - this.lastMarker.line = this.scanner.lineNumber; - this.lastMarker.column = this.scanner.index - this.scanner.lineStart; - this.collectComments(); - if (this.scanner.index !== this.startMarker.index) { - this.startMarker.index = this.scanner.index; - this.startMarker.line = this.scanner.lineNumber; - this.startMarker.column = this.scanner.index - this.scanner.lineStart; - } - var next = this.scanner.lex(); - this.hasLineTerminator = (token.lineNumber !== next.lineNumber); - if (next && this.context.strict && next.type === 3 /* Identifier */) { - if (this.scanner.isStrictModeReservedWord(next.value)) { - next.type = 4 /* Keyword */; - } - } - this.lookahead = next; - if (this.config.tokens && next.type !== 2 /* EOF */) { - this.tokens.push(this.convertToken(next)); - } - return token; - }; - Parser.prototype.nextRegexToken = function () { - this.collectComments(); - var token = this.scanner.scanRegExp(); - if (this.config.tokens) { - // Pop the previous token, '/' or '/=' - // This is added from the lookahead token. - this.tokens.pop(); - this.tokens.push(this.convertToken(token)); - } - // Prime the next lookahead. - this.lookahead = token; - this.nextToken(); - return token; - }; - Parser.prototype.createNode = function () { - return { - index: this.startMarker.index, - line: this.startMarker.line, - column: this.startMarker.column - }; - }; - Parser.prototype.startNode = function (token, lastLineStart) { - if (lastLineStart === void 0) { lastLineStart = 0; } - var column = token.start - token.lineStart; - var line = token.lineNumber; - if (column < 0) { - column += lastLineStart; - line--; - } - return { - index: token.start, - line: line, - column: column - }; - }; - Parser.prototype.finalize = function (marker, node) { - if (this.config.range) { - node.range = [marker.index, this.lastMarker.index]; - } - if (this.config.loc) { - node.loc = { - start: { - line: marker.line, - column: marker.column, - }, - end: { - line: this.lastMarker.line, - column: this.lastMarker.column - } - }; - if (this.config.source) { - node.loc.source = this.config.source; - } - } - if (this.delegate) { - var metadata = { - start: { - line: marker.line, - column: marker.column, - offset: marker.index - }, - end: { - line: this.lastMarker.line, - column: this.lastMarker.column, - offset: this.lastMarker.index - } - }; - this.delegate(node, metadata); - } - return node; - }; - // Expect the next token to match the specified punctuator. - // If not, an exception will be thrown. - Parser.prototype.expect = function (value) { - var token = this.nextToken(); - if (token.type !== 7 /* Punctuator */ || token.value !== value) { - this.throwUnexpectedToken(token); - } - }; - // Quietly expect a comma when in tolerant mode, otherwise delegates to expect(). - Parser.prototype.expectCommaSeparator = function () { - if (this.config.tolerant) { - var token = this.lookahead; - if (token.type === 7 /* Punctuator */ && token.value === ',') { - this.nextToken(); - } - else if (token.type === 7 /* Punctuator */ && token.value === ';') { - this.nextToken(); - this.tolerateUnexpectedToken(token); - } - else { - this.tolerateUnexpectedToken(token, messages_1.Messages.UnexpectedToken); - } - } - else { - this.expect(','); - } - }; - // Expect the next token to match the specified keyword. - // If not, an exception will be thrown. - Parser.prototype.expectKeyword = function (keyword) { - var token = this.nextToken(); - if (token.type !== 4 /* Keyword */ || token.value !== keyword) { - this.throwUnexpectedToken(token); - } - }; - // Return true if the next token matches the specified punctuator. - Parser.prototype.match = function (value) { - return this.lookahead.type === 7 /* Punctuator */ && this.lookahead.value === value; - }; - // Return true if the next token matches the specified keyword - Parser.prototype.matchKeyword = function (keyword) { - return this.lookahead.type === 4 /* Keyword */ && this.lookahead.value === keyword; - }; - // Return true if the next token matches the specified contextual keyword - // (where an identifier is sometimes a keyword depending on the context) - Parser.prototype.matchContextualKeyword = function (keyword) { - return this.lookahead.type === 3 /* Identifier */ && this.lookahead.value === keyword; - }; - // Return true if the next token is an assignment operator - Parser.prototype.matchAssign = function () { - if (this.lookahead.type !== 7 /* Punctuator */) { - return false; - } - var op = this.lookahead.value; - return op === '=' || - op === '*=' || - op === '**=' || - op === '/=' || - op === '%=' || - op === '+=' || - op === '-=' || - op === '<<=' || - op === '>>=' || - op === '>>>=' || - op === '&=' || - op === '^=' || - op === '|='; - }; - // Cover grammar support. - // - // When an assignment expression position starts with an left parenthesis, the determination of the type - // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead) - // or the first comma. This situation also defers the determination of all the expressions nested in the pair. - // - // There are three productions that can be parsed in a parentheses pair that needs to be determined - // after the outermost pair is closed. They are: - // - // 1. AssignmentExpression - // 2. BindingElements - // 3. AssignmentTargets - // - // In order to avoid exponential backtracking, we use two flags to denote if the production can be - // binding element or assignment target. - // - // The three productions have the relationship: - // - // BindingElements ⊆ AssignmentTargets ⊆ AssignmentExpression - // - // with a single exception that CoverInitializedName when used directly in an Expression, generates - // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the - // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair. - // - // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not - // effect the current flags. This means the production the parser parses is only used as an expression. Therefore - // the CoverInitializedName check is conducted. - // - // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates - // the flags outside of the parser. This means the production the parser parses is used as a part of a potential - // pattern. The CoverInitializedName check is deferred. - Parser.prototype.isolateCoverGrammar = function (parseFunction) { - var previousIsBindingElement = this.context.isBindingElement; - var previousIsAssignmentTarget = this.context.isAssignmentTarget; - var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError; - this.context.isBindingElement = true; - this.context.isAssignmentTarget = true; - this.context.firstCoverInitializedNameError = null; - var result = parseFunction.call(this); - if (this.context.firstCoverInitializedNameError !== null) { - this.throwUnexpectedToken(this.context.firstCoverInitializedNameError); - } - this.context.isBindingElement = previousIsBindingElement; - this.context.isAssignmentTarget = previousIsAssignmentTarget; - this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError; - return result; - }; - Parser.prototype.inheritCoverGrammar = function (parseFunction) { - var previousIsBindingElement = this.context.isBindingElement; - var previousIsAssignmentTarget = this.context.isAssignmentTarget; - var previousFirstCoverInitializedNameError = this.context.firstCoverInitializedNameError; - this.context.isBindingElement = true; - this.context.isAssignmentTarget = true; - this.context.firstCoverInitializedNameError = null; - var result = parseFunction.call(this); - this.context.isBindingElement = this.context.isBindingElement && previousIsBindingElement; - this.context.isAssignmentTarget = this.context.isAssignmentTarget && previousIsAssignmentTarget; - this.context.firstCoverInitializedNameError = previousFirstCoverInitializedNameError || this.context.firstCoverInitializedNameError; - return result; - }; - Parser.prototype.consumeSemicolon = function () { - if (this.match(';')) { - this.nextToken(); - } - else if (!this.hasLineTerminator) { - if (this.lookahead.type !== 2 /* EOF */ && !this.match('}')) { - this.throwUnexpectedToken(this.lookahead); - } - this.lastMarker.index = this.startMarker.index; - this.lastMarker.line = this.startMarker.line; - this.lastMarker.column = this.startMarker.column; - } - }; - // https://tc39.github.io/ecma262/#sec-primary-expression - Parser.prototype.parsePrimaryExpression = function () { - var node = this.createNode(); - var expr; - var token, raw; - switch (this.lookahead.type) { - case 3 /* Identifier */: - if ((this.context.isModule || this.context.await) && this.lookahead.value === 'await') { - this.tolerateUnexpectedToken(this.lookahead); - } - expr = this.matchAsyncFunction() ? this.parseFunctionExpression() : this.finalize(node, new Node.Identifier(this.nextToken().value)); - break; - case 6 /* NumericLiteral */: - case 8 /* StringLiteral */: - if (this.context.strict && this.lookahead.octal) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.StrictOctalLiteral); - } - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - token = this.nextToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.Literal(token.value, raw)); - break; - case 1 /* BooleanLiteral */: - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - token = this.nextToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.Literal(token.value === 'true', raw)); - break; - case 5 /* NullLiteral */: - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - token = this.nextToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.Literal(null, raw)); - break; - case 10 /* Template */: - expr = this.parseTemplateLiteral(); - break; - case 7 /* Punctuator */: - switch (this.lookahead.value) { - case '(': - this.context.isBindingElement = false; - expr = this.inheritCoverGrammar(this.parseGroupExpression); - break; - case '[': - expr = this.inheritCoverGrammar(this.parseArrayInitializer); - break; - case '{': - expr = this.inheritCoverGrammar(this.parseObjectInitializer); - break; - case '/': - case '/=': - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - this.scanner.index = this.startMarker.index; - token = this.nextRegexToken(); - raw = this.getTokenRaw(token); - expr = this.finalize(node, new Node.RegexLiteral(token.regex, raw, token.pattern, token.flags)); - break; - default: - expr = this.throwUnexpectedToken(this.nextToken()); - } - break; - case 4 /* Keyword */: - if (!this.context.strict && this.context.allowYield && this.matchKeyword('yield')) { - expr = this.parseIdentifierName(); - } - else if (!this.context.strict && this.matchKeyword('let')) { - expr = this.finalize(node, new Node.Identifier(this.nextToken().value)); - } - else { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - if (this.matchKeyword('function')) { - expr = this.parseFunctionExpression(); - } - else if (this.matchKeyword('this')) { - this.nextToken(); - expr = this.finalize(node, new Node.ThisExpression()); - } - else if (this.matchKeyword('class')) { - expr = this.parseClassExpression(); - } - else { - expr = this.throwUnexpectedToken(this.nextToken()); - } - } - break; - default: - expr = this.throwUnexpectedToken(this.nextToken()); - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-array-initializer - Parser.prototype.parseSpreadElement = function () { - var node = this.createNode(); - this.expect('...'); - var arg = this.inheritCoverGrammar(this.parseAssignmentExpression); - return this.finalize(node, new Node.SpreadElement(arg)); - }; - Parser.prototype.parseArrayInitializer = function () { - var node = this.createNode(); - var elements = []; - this.expect('['); - while (!this.match(']')) { - if (this.match(',')) { - this.nextToken(); - elements.push(null); - } - else if (this.match('...')) { - var element = this.parseSpreadElement(); - if (!this.match(']')) { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - this.expect(','); - } - elements.push(element); - } - else { - elements.push(this.inheritCoverGrammar(this.parseAssignmentExpression)); - if (!this.match(']')) { - this.expect(','); - } - } - } - this.expect(']'); - return this.finalize(node, new Node.ArrayExpression(elements)); - }; - // https://tc39.github.io/ecma262/#sec-object-initializer - Parser.prototype.parsePropertyMethod = function (params) { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = params.simple; - var body = this.isolateCoverGrammar(this.parseFunctionSourceElements); - if (this.context.strict && params.firstRestricted) { - this.tolerateUnexpectedToken(params.firstRestricted, params.message); - } - if (this.context.strict && params.stricted) { - this.tolerateUnexpectedToken(params.stricted, params.message); - } - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - return body; - }; - Parser.prototype.parsePropertyMethodFunction = function () { - var isGenerator = false; - var node = this.createNode(); - var previousAllowYield = this.context.allowYield; - this.context.allowYield = true; - var params = this.parseFormalParameters(); - var method = this.parsePropertyMethod(params); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator)); - }; - Parser.prototype.parsePropertyMethodAsyncFunction = function () { - var node = this.createNode(); - var previousAllowYield = this.context.allowYield; - var previousAwait = this.context.await; - this.context.allowYield = false; - this.context.await = true; - var params = this.parseFormalParameters(); - var method = this.parsePropertyMethod(params); - this.context.allowYield = previousAllowYield; - this.context.await = previousAwait; - return this.finalize(node, new Node.AsyncFunctionExpression(null, params.params, method)); - }; - Parser.prototype.parseObjectPropertyKey = function () { - var node = this.createNode(); - var token = this.nextToken(); - var key; - switch (token.type) { - case 8 /* StringLiteral */: - case 6 /* NumericLiteral */: - if (this.context.strict && token.octal) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictOctalLiteral); - } - var raw = this.getTokenRaw(token); - key = this.finalize(node, new Node.Literal(token.value, raw)); - break; - case 3 /* Identifier */: - case 1 /* BooleanLiteral */: - case 5 /* NullLiteral */: - case 4 /* Keyword */: - key = this.finalize(node, new Node.Identifier(token.value)); - break; - case 7 /* Punctuator */: - if (token.value === '[') { - key = this.isolateCoverGrammar(this.parseAssignmentExpression); - this.expect(']'); - } - else { - key = this.throwUnexpectedToken(token); - } - break; - default: - key = this.throwUnexpectedToken(token); - } - return key; - }; - Parser.prototype.isPropertyKey = function (key, value) { - return (key.type === syntax_1.Syntax.Identifier && key.name === value) || - (key.type === syntax_1.Syntax.Literal && key.value === value); - }; - Parser.prototype.parseObjectProperty = function (hasProto) { - var node = this.createNode(); - var token = this.lookahead; - var kind; - var key = null; - var value = null; - var computed = false; - var method = false; - var shorthand = false; - var isAsync = false; - if (token.type === 3 /* Identifier */) { - var id = token.value; - this.nextToken(); - computed = this.match('['); - isAsync = !this.hasLineTerminator && (id === 'async') && - !this.match(':') && !this.match('(') && !this.match('*') && !this.match(','); - key = isAsync ? this.parseObjectPropertyKey() : this.finalize(node, new Node.Identifier(id)); - } - else if (this.match('*')) { - this.nextToken(); - } - else { - computed = this.match('['); - key = this.parseObjectPropertyKey(); - } - var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead); - if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'get' && lookaheadPropertyKey) { - kind = 'get'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - this.context.allowYield = false; - value = this.parseGetterMethod(); - } - else if (token.type === 3 /* Identifier */ && !isAsync && token.value === 'set' && lookaheadPropertyKey) { - kind = 'set'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseSetterMethod(); - } - else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) { - kind = 'init'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseGeneratorMethod(); - method = true; - } - else { - if (!key) { - this.throwUnexpectedToken(this.lookahead); - } - kind = 'init'; - if (this.match(':') && !isAsync) { - if (!computed && this.isPropertyKey(key, '__proto__')) { - if (hasProto.value) { - this.tolerateError(messages_1.Messages.DuplicateProtoProperty); - } - hasProto.value = true; - } - this.nextToken(); - value = this.inheritCoverGrammar(this.parseAssignmentExpression); - } - else if (this.match('(')) { - value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction(); - method = true; - } - else if (token.type === 3 /* Identifier */) { - var id = this.finalize(node, new Node.Identifier(token.value)); - if (this.match('=')) { - this.context.firstCoverInitializedNameError = this.lookahead; - this.nextToken(); - shorthand = true; - var init = this.isolateCoverGrammar(this.parseAssignmentExpression); - value = this.finalize(node, new Node.AssignmentPattern(id, init)); - } - else { - shorthand = true; - value = id; - } - } - else { - this.throwUnexpectedToken(this.nextToken()); - } - } - return this.finalize(node, new Node.Property(kind, key, computed, value, method, shorthand)); - }; - Parser.prototype.parseObjectInitializer = function () { - var node = this.createNode(); - this.expect('{'); - var properties = []; - var hasProto = { value: false }; - while (!this.match('}')) { - properties.push(this.parseObjectProperty(hasProto)); - if (!this.match('}')) { - this.expectCommaSeparator(); - } - } - this.expect('}'); - return this.finalize(node, new Node.ObjectExpression(properties)); - }; - // https://tc39.github.io/ecma262/#sec-template-literals - Parser.prototype.parseTemplateHead = function () { - assert_1.assert(this.lookahead.head, 'Template literal must start with a template head'); - var node = this.createNode(); - var token = this.nextToken(); - var raw = token.value; - var cooked = token.cooked; - return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail)); - }; - Parser.prototype.parseTemplateElement = function () { - if (this.lookahead.type !== 10 /* Template */) { - this.throwUnexpectedToken(); - } - var node = this.createNode(); - var token = this.nextToken(); - var raw = token.value; - var cooked = token.cooked; - return this.finalize(node, new Node.TemplateElement({ raw: raw, cooked: cooked }, token.tail)); - }; - Parser.prototype.parseTemplateLiteral = function () { - var node = this.createNode(); - var expressions = []; - var quasis = []; - var quasi = this.parseTemplateHead(); - quasis.push(quasi); - while (!quasi.tail) { - expressions.push(this.parseExpression()); - quasi = this.parseTemplateElement(); - quasis.push(quasi); - } - return this.finalize(node, new Node.TemplateLiteral(quasis, expressions)); - }; - // https://tc39.github.io/ecma262/#sec-grouping-operator - Parser.prototype.reinterpretExpressionAsPattern = function (expr) { - switch (expr.type) { - case syntax_1.Syntax.Identifier: - case syntax_1.Syntax.MemberExpression: - case syntax_1.Syntax.RestElement: - case syntax_1.Syntax.AssignmentPattern: - break; - case syntax_1.Syntax.SpreadElement: - expr.type = syntax_1.Syntax.RestElement; - this.reinterpretExpressionAsPattern(expr.argument); - break; - case syntax_1.Syntax.ArrayExpression: - expr.type = syntax_1.Syntax.ArrayPattern; - for (var i = 0; i < expr.elements.length; i++) { - if (expr.elements[i] !== null) { - this.reinterpretExpressionAsPattern(expr.elements[i]); - } - } - break; - case syntax_1.Syntax.ObjectExpression: - expr.type = syntax_1.Syntax.ObjectPattern; - for (var i = 0; i < expr.properties.length; i++) { - this.reinterpretExpressionAsPattern(expr.properties[i].value); - } - break; - case syntax_1.Syntax.AssignmentExpression: - expr.type = syntax_1.Syntax.AssignmentPattern; - delete expr.operator; - this.reinterpretExpressionAsPattern(expr.left); - break; - default: - // Allow other node type for tolerant parsing. - break; - } - }; - Parser.prototype.parseGroupExpression = function () { - var expr; - this.expect('('); - if (this.match(')')) { - this.nextToken(); - if (!this.match('=>')) { - this.expect('=>'); - } - expr = { - type: ArrowParameterPlaceHolder, - params: [], - async: false - }; - } - else { - var startToken = this.lookahead; - var params = []; - if (this.match('...')) { - expr = this.parseRestElement(params); - this.expect(')'); - if (!this.match('=>')) { - this.expect('=>'); - } - expr = { - type: ArrowParameterPlaceHolder, - params: [expr], - async: false - }; - } - else { - var arrow = false; - this.context.isBindingElement = true; - expr = this.inheritCoverGrammar(this.parseAssignmentExpression); - if (this.match(',')) { - var expressions = []; - this.context.isAssignmentTarget = false; - expressions.push(expr); - while (this.lookahead.type !== 2 /* EOF */) { - if (!this.match(',')) { - break; - } - this.nextToken(); - if (this.match(')')) { - this.nextToken(); - for (var i = 0; i < expressions.length; i++) { - this.reinterpretExpressionAsPattern(expressions[i]); - } - arrow = true; - expr = { - type: ArrowParameterPlaceHolder, - params: expressions, - async: false - }; - } - else if (this.match('...')) { - if (!this.context.isBindingElement) { - this.throwUnexpectedToken(this.lookahead); - } - expressions.push(this.parseRestElement(params)); - this.expect(')'); - if (!this.match('=>')) { - this.expect('=>'); - } - this.context.isBindingElement = false; - for (var i = 0; i < expressions.length; i++) { - this.reinterpretExpressionAsPattern(expressions[i]); - } - arrow = true; - expr = { - type: ArrowParameterPlaceHolder, - params: expressions, - async: false - }; - } - else { - expressions.push(this.inheritCoverGrammar(this.parseAssignmentExpression)); - } - if (arrow) { - break; - } - } - if (!arrow) { - expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions)); - } - } - if (!arrow) { - this.expect(')'); - if (this.match('=>')) { - if (expr.type === syntax_1.Syntax.Identifier && expr.name === 'yield') { - arrow = true; - expr = { - type: ArrowParameterPlaceHolder, - params: [expr], - async: false - }; - } - if (!arrow) { - if (!this.context.isBindingElement) { - this.throwUnexpectedToken(this.lookahead); - } - if (expr.type === syntax_1.Syntax.SequenceExpression) { - for (var i = 0; i < expr.expressions.length; i++) { - this.reinterpretExpressionAsPattern(expr.expressions[i]); - } - } - else { - this.reinterpretExpressionAsPattern(expr); - } - var parameters = (expr.type === syntax_1.Syntax.SequenceExpression ? expr.expressions : [expr]); - expr = { - type: ArrowParameterPlaceHolder, - params: parameters, - async: false - }; - } - } - this.context.isBindingElement = false; - } - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-left-hand-side-expressions - Parser.prototype.parseArguments = function () { - this.expect('('); - var args = []; - if (!this.match(')')) { - while (true) { - var expr = this.match('...') ? this.parseSpreadElement() : - this.isolateCoverGrammar(this.parseAssignmentExpression); - args.push(expr); - if (this.match(')')) { - break; - } - this.expectCommaSeparator(); - if (this.match(')')) { - break; - } - } - } - this.expect(')'); - return args; - }; - Parser.prototype.isIdentifierName = function (token) { - return token.type === 3 /* Identifier */ || - token.type === 4 /* Keyword */ || - token.type === 1 /* BooleanLiteral */ || - token.type === 5 /* NullLiteral */; - }; - Parser.prototype.parseIdentifierName = function () { - var node = this.createNode(); - var token = this.nextToken(); - if (!this.isIdentifierName(token)) { - this.throwUnexpectedToken(token); - } - return this.finalize(node, new Node.Identifier(token.value)); - }; - Parser.prototype.parseNewExpression = function () { - var node = this.createNode(); - var id = this.parseIdentifierName(); - assert_1.assert(id.name === 'new', 'New expression must start with `new`'); - var expr; - if (this.match('.')) { - this.nextToken(); - if (this.lookahead.type === 3 /* Identifier */ && this.context.inFunctionBody && this.lookahead.value === 'target') { - var property = this.parseIdentifierName(); - expr = new Node.MetaProperty(id, property); - } - else { - this.throwUnexpectedToken(this.lookahead); - } - } - else { - var callee = this.isolateCoverGrammar(this.parseLeftHandSideExpression); - var args = this.match('(') ? this.parseArguments() : []; - expr = new Node.NewExpression(callee, args); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - return this.finalize(node, expr); - }; - Parser.prototype.parseAsyncArgument = function () { - var arg = this.parseAssignmentExpression(); - this.context.firstCoverInitializedNameError = null; - return arg; - }; - Parser.prototype.parseAsyncArguments = function () { - this.expect('('); - var args = []; - if (!this.match(')')) { - while (true) { - var expr = this.match('...') ? this.parseSpreadElement() : - this.isolateCoverGrammar(this.parseAsyncArgument); - args.push(expr); - if (this.match(')')) { - break; - } - this.expectCommaSeparator(); - if (this.match(')')) { - break; - } - } - } - this.expect(')'); - return args; - }; - Parser.prototype.parseLeftHandSideExpressionAllowCall = function () { - var startToken = this.lookahead; - var maybeAsync = this.matchContextualKeyword('async'); - var previousAllowIn = this.context.allowIn; - this.context.allowIn = true; - var expr; - if (this.matchKeyword('super') && this.context.inFunctionBody) { - expr = this.createNode(); - this.nextToken(); - expr = this.finalize(expr, new Node.Super()); - if (!this.match('(') && !this.match('.') && !this.match('[')) { - this.throwUnexpectedToken(this.lookahead); - } - } - else { - expr = this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression); - } - while (true) { - if (this.match('.')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('.'); - var property = this.parseIdentifierName(); - expr = this.finalize(this.startNode(startToken), new Node.StaticMemberExpression(expr, property)); - } - else if (this.match('(')) { - var asyncArrow = maybeAsync && (startToken.lineNumber === this.lookahead.lineNumber); - this.context.isBindingElement = false; - this.context.isAssignmentTarget = false; - var args = asyncArrow ? this.parseAsyncArguments() : this.parseArguments(); - expr = this.finalize(this.startNode(startToken), new Node.CallExpression(expr, args)); - if (asyncArrow && this.match('=>')) { - for (var i = 0; i < args.length; ++i) { - this.reinterpretExpressionAsPattern(args[i]); - } - expr = { - type: ArrowParameterPlaceHolder, - params: args, - async: true - }; - } - } - else if (this.match('[')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('['); - var property = this.isolateCoverGrammar(this.parseExpression); - this.expect(']'); - expr = this.finalize(this.startNode(startToken), new Node.ComputedMemberExpression(expr, property)); - } - else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) { - var quasi = this.parseTemplateLiteral(); - expr = this.finalize(this.startNode(startToken), new Node.TaggedTemplateExpression(expr, quasi)); - } - else { - break; - } - } - this.context.allowIn = previousAllowIn; - return expr; - }; - Parser.prototype.parseSuper = function () { - var node = this.createNode(); - this.expectKeyword('super'); - if (!this.match('[') && !this.match('.')) { - this.throwUnexpectedToken(this.lookahead); - } - return this.finalize(node, new Node.Super()); - }; - Parser.prototype.parseLeftHandSideExpression = function () { - assert_1.assert(this.context.allowIn, 'callee of new expression always allow in keyword.'); - var node = this.startNode(this.lookahead); - var expr = (this.matchKeyword('super') && this.context.inFunctionBody) ? this.parseSuper() : - this.inheritCoverGrammar(this.matchKeyword('new') ? this.parseNewExpression : this.parsePrimaryExpression); - while (true) { - if (this.match('[')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('['); - var property = this.isolateCoverGrammar(this.parseExpression); - this.expect(']'); - expr = this.finalize(node, new Node.ComputedMemberExpression(expr, property)); - } - else if (this.match('.')) { - this.context.isBindingElement = false; - this.context.isAssignmentTarget = true; - this.expect('.'); - var property = this.parseIdentifierName(); - expr = this.finalize(node, new Node.StaticMemberExpression(expr, property)); - } - else if (this.lookahead.type === 10 /* Template */ && this.lookahead.head) { - var quasi = this.parseTemplateLiteral(); - expr = this.finalize(node, new Node.TaggedTemplateExpression(expr, quasi)); - } - else { - break; - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-update-expressions - Parser.prototype.parseUpdateExpression = function () { - var expr; - var startToken = this.lookahead; - if (this.match('++') || this.match('--')) { - var node = this.startNode(startToken); - var token = this.nextToken(); - expr = this.inheritCoverGrammar(this.parseUnaryExpression); - if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) { - this.tolerateError(messages_1.Messages.StrictLHSPrefix); - } - if (!this.context.isAssignmentTarget) { - this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); - } - var prefix = true; - expr = this.finalize(node, new Node.UpdateExpression(token.value, expr, prefix)); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - else { - expr = this.inheritCoverGrammar(this.parseLeftHandSideExpressionAllowCall); - if (!this.hasLineTerminator && this.lookahead.type === 7 /* Punctuator */) { - if (this.match('++') || this.match('--')) { - if (this.context.strict && expr.type === syntax_1.Syntax.Identifier && this.scanner.isRestrictedWord(expr.name)) { - this.tolerateError(messages_1.Messages.StrictLHSPostfix); - } - if (!this.context.isAssignmentTarget) { - this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); - } - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var operator = this.nextToken().value; - var prefix = false; - expr = this.finalize(this.startNode(startToken), new Node.UpdateExpression(operator, expr, prefix)); - } - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-unary-operators - Parser.prototype.parseAwaitExpression = function () { - var node = this.createNode(); - this.nextToken(); - var argument = this.parseUnaryExpression(); - return this.finalize(node, new Node.AwaitExpression(argument)); - }; - Parser.prototype.parseUnaryExpression = function () { - var expr; - if (this.match('+') || this.match('-') || this.match('~') || this.match('!') || - this.matchKeyword('delete') || this.matchKeyword('void') || this.matchKeyword('typeof')) { - var node = this.startNode(this.lookahead); - var token = this.nextToken(); - expr = this.inheritCoverGrammar(this.parseUnaryExpression); - expr = this.finalize(node, new Node.UnaryExpression(token.value, expr)); - if (this.context.strict && expr.operator === 'delete' && expr.argument.type === syntax_1.Syntax.Identifier) { - this.tolerateError(messages_1.Messages.StrictDelete); - } - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - else if (this.context.await && this.matchContextualKeyword('await')) { - expr = this.parseAwaitExpression(); - } - else { - expr = this.parseUpdateExpression(); - } - return expr; - }; - Parser.prototype.parseExponentiationExpression = function () { - var startToken = this.lookahead; - var expr = this.inheritCoverGrammar(this.parseUnaryExpression); - if (expr.type !== syntax_1.Syntax.UnaryExpression && this.match('**')) { - this.nextToken(); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var left = expr; - var right = this.isolateCoverGrammar(this.parseExponentiationExpression); - expr = this.finalize(this.startNode(startToken), new Node.BinaryExpression('**', left, right)); - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-exp-operator - // https://tc39.github.io/ecma262/#sec-multiplicative-operators - // https://tc39.github.io/ecma262/#sec-additive-operators - // https://tc39.github.io/ecma262/#sec-bitwise-shift-operators - // https://tc39.github.io/ecma262/#sec-relational-operators - // https://tc39.github.io/ecma262/#sec-equality-operators - // https://tc39.github.io/ecma262/#sec-binary-bitwise-operators - // https://tc39.github.io/ecma262/#sec-binary-logical-operators - Parser.prototype.binaryPrecedence = function (token) { - var op = token.value; - var precedence; - if (token.type === 7 /* Punctuator */) { - precedence = this.operatorPrecedence[op] || 0; - } - else if (token.type === 4 /* Keyword */) { - precedence = (op === 'instanceof' || (this.context.allowIn && op === 'in')) ? 7 : 0; - } - else { - precedence = 0; - } - return precedence; - }; - Parser.prototype.parseBinaryExpression = function () { - var startToken = this.lookahead; - var expr = this.inheritCoverGrammar(this.parseExponentiationExpression); - var token = this.lookahead; - var prec = this.binaryPrecedence(token); - if (prec > 0) { - this.nextToken(); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var markers = [startToken, this.lookahead]; - var left = expr; - var right = this.isolateCoverGrammar(this.parseExponentiationExpression); - var stack = [left, token.value, right]; - var precedences = [prec]; - while (true) { - prec = this.binaryPrecedence(this.lookahead); - if (prec <= 0) { - break; - } - // Reduce: make a binary expression from the three topmost entries. - while ((stack.length > 2) && (prec <= precedences[precedences.length - 1])) { - right = stack.pop(); - var operator = stack.pop(); - precedences.pop(); - left = stack.pop(); - markers.pop(); - var node = this.startNode(markers[markers.length - 1]); - stack.push(this.finalize(node, new Node.BinaryExpression(operator, left, right))); - } - // Shift. - stack.push(this.nextToken().value); - precedences.push(prec); - markers.push(this.lookahead); - stack.push(this.isolateCoverGrammar(this.parseExponentiationExpression)); - } - // Final reduce to clean-up the stack. - var i = stack.length - 1; - expr = stack[i]; - var lastMarker = markers.pop(); - while (i > 1) { - var marker = markers.pop(); - var lastLineStart = lastMarker && lastMarker.lineStart; - var node = this.startNode(marker, lastLineStart); - var operator = stack[i - 1]; - expr = this.finalize(node, new Node.BinaryExpression(operator, stack[i - 2], expr)); - i -= 2; - lastMarker = marker; - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-conditional-operator - Parser.prototype.parseConditionalExpression = function () { - var startToken = this.lookahead; - var expr = this.inheritCoverGrammar(this.parseBinaryExpression); - if (this.match('?')) { - this.nextToken(); - var previousAllowIn = this.context.allowIn; - this.context.allowIn = true; - var consequent = this.isolateCoverGrammar(this.parseAssignmentExpression); - this.context.allowIn = previousAllowIn; - this.expect(':'); - var alternate = this.isolateCoverGrammar(this.parseAssignmentExpression); - expr = this.finalize(this.startNode(startToken), new Node.ConditionalExpression(expr, consequent, alternate)); - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-assignment-operators - Parser.prototype.checkPatternParam = function (options, param) { - switch (param.type) { - case syntax_1.Syntax.Identifier: - this.validateParam(options, param, param.name); - break; - case syntax_1.Syntax.RestElement: - this.checkPatternParam(options, param.argument); - break; - case syntax_1.Syntax.AssignmentPattern: - this.checkPatternParam(options, param.left); - break; - case syntax_1.Syntax.ArrayPattern: - for (var i = 0; i < param.elements.length; i++) { - if (param.elements[i] !== null) { - this.checkPatternParam(options, param.elements[i]); - } - } - break; - case syntax_1.Syntax.ObjectPattern: - for (var i = 0; i < param.properties.length; i++) { - this.checkPatternParam(options, param.properties[i].value); - } - break; - default: - break; - } - options.simple = options.simple && (param instanceof Node.Identifier); - }; - Parser.prototype.reinterpretAsCoverFormalsList = function (expr) { - var params = [expr]; - var options; - var asyncArrow = false; - switch (expr.type) { - case syntax_1.Syntax.Identifier: - break; - case ArrowParameterPlaceHolder: - params = expr.params; - asyncArrow = expr.async; - break; - default: - return null; - } - options = { - simple: true, - paramSet: {} - }; - for (var i = 0; i < params.length; ++i) { - var param = params[i]; - if (param.type === syntax_1.Syntax.AssignmentPattern) { - if (param.right.type === syntax_1.Syntax.YieldExpression) { - if (param.right.argument) { - this.throwUnexpectedToken(this.lookahead); - } - param.right.type = syntax_1.Syntax.Identifier; - param.right.name = 'yield'; - delete param.right.argument; - delete param.right.delegate; - } - } - else if (asyncArrow && param.type === syntax_1.Syntax.Identifier && param.name === 'await') { - this.throwUnexpectedToken(this.lookahead); - } - this.checkPatternParam(options, param); - params[i] = param; - } - if (this.context.strict || !this.context.allowYield) { - for (var i = 0; i < params.length; ++i) { - var param = params[i]; - if (param.type === syntax_1.Syntax.YieldExpression) { - this.throwUnexpectedToken(this.lookahead); - } - } - } - if (options.message === messages_1.Messages.StrictParamDupe) { - var token = this.context.strict ? options.stricted : options.firstRestricted; - this.throwUnexpectedToken(token, options.message); - } - return { - simple: options.simple, - params: params, - stricted: options.stricted, - firstRestricted: options.firstRestricted, - message: options.message - }; - }; - Parser.prototype.parseAssignmentExpression = function () { - var expr; - if (!this.context.allowYield && this.matchKeyword('yield')) { - expr = this.parseYieldExpression(); - } - else { - var startToken = this.lookahead; - var token = startToken; - expr = this.parseConditionalExpression(); - if (token.type === 3 /* Identifier */ && (token.lineNumber === this.lookahead.lineNumber) && token.value === 'async') { - if (this.lookahead.type === 3 /* Identifier */ || this.matchKeyword('yield')) { - var arg = this.parsePrimaryExpression(); - this.reinterpretExpressionAsPattern(arg); - expr = { - type: ArrowParameterPlaceHolder, - params: [arg], - async: true - }; - } - } - if (expr.type === ArrowParameterPlaceHolder || this.match('=>')) { - // https://tc39.github.io/ecma262/#sec-arrow-function-definitions - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - var isAsync = expr.async; - var list = this.reinterpretAsCoverFormalsList(expr); - if (list) { - if (this.hasLineTerminator) { - this.tolerateUnexpectedToken(this.lookahead); - } - this.context.firstCoverInitializedNameError = null; - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = list.simple; - var previousAllowYield = this.context.allowYield; - var previousAwait = this.context.await; - this.context.allowYield = true; - this.context.await = isAsync; - var node = this.startNode(startToken); - this.expect('=>'); - var body = void 0; - if (this.match('{')) { - var previousAllowIn = this.context.allowIn; - this.context.allowIn = true; - body = this.parseFunctionSourceElements(); - this.context.allowIn = previousAllowIn; - } - else { - body = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - var expression = body.type !== syntax_1.Syntax.BlockStatement; - if (this.context.strict && list.firstRestricted) { - this.throwUnexpectedToken(list.firstRestricted, list.message); - } - if (this.context.strict && list.stricted) { - this.tolerateUnexpectedToken(list.stricted, list.message); - } - expr = isAsync ? this.finalize(node, new Node.AsyncArrowFunctionExpression(list.params, body, expression)) : - this.finalize(node, new Node.ArrowFunctionExpression(list.params, body, expression)); - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - this.context.allowYield = previousAllowYield; - this.context.await = previousAwait; - } - } - else { - if (this.matchAssign()) { - if (!this.context.isAssignmentTarget) { - this.tolerateError(messages_1.Messages.InvalidLHSInAssignment); - } - if (this.context.strict && expr.type === syntax_1.Syntax.Identifier) { - var id = expr; - if (this.scanner.isRestrictedWord(id.name)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictLHSAssignment); - } - if (this.scanner.isStrictModeReservedWord(id.name)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); - } - } - if (!this.match('=')) { - this.context.isAssignmentTarget = false; - this.context.isBindingElement = false; - } - else { - this.reinterpretExpressionAsPattern(expr); - } - token = this.nextToken(); - var operator = token.value; - var right = this.isolateCoverGrammar(this.parseAssignmentExpression); - expr = this.finalize(this.startNode(startToken), new Node.AssignmentExpression(operator, expr, right)); - this.context.firstCoverInitializedNameError = null; - } - } - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-comma-operator - Parser.prototype.parseExpression = function () { - var startToken = this.lookahead; - var expr = this.isolateCoverGrammar(this.parseAssignmentExpression); - if (this.match(',')) { - var expressions = []; - expressions.push(expr); - while (this.lookahead.type !== 2 /* EOF */) { - if (!this.match(',')) { - break; - } - this.nextToken(); - expressions.push(this.isolateCoverGrammar(this.parseAssignmentExpression)); - } - expr = this.finalize(this.startNode(startToken), new Node.SequenceExpression(expressions)); - } - return expr; - }; - // https://tc39.github.io/ecma262/#sec-block - Parser.prototype.parseStatementListItem = function () { - var statement; - this.context.isAssignmentTarget = true; - this.context.isBindingElement = true; - if (this.lookahead.type === 4 /* Keyword */) { - switch (this.lookahead.value) { - case 'export': - if (!this.context.isModule) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalExportDeclaration); - } - statement = this.parseExportDeclaration(); - break; - case 'import': - if (!this.context.isModule) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.IllegalImportDeclaration); - } - statement = this.parseImportDeclaration(); - break; - case 'const': - statement = this.parseLexicalDeclaration({ inFor: false }); - break; - case 'function': - statement = this.parseFunctionDeclaration(); - break; - case 'class': - statement = this.parseClassDeclaration(); - break; - case 'let': - statement = this.isLexicalDeclaration() ? this.parseLexicalDeclaration({ inFor: false }) : this.parseStatement(); - break; - default: - statement = this.parseStatement(); - break; - } - } - else { - statement = this.parseStatement(); - } - return statement; - }; - Parser.prototype.parseBlock = function () { - var node = this.createNode(); - this.expect('{'); - var block = []; - while (true) { - if (this.match('}')) { - break; - } - block.push(this.parseStatementListItem()); - } - this.expect('}'); - return this.finalize(node, new Node.BlockStatement(block)); - }; - // https://tc39.github.io/ecma262/#sec-let-and-const-declarations - Parser.prototype.parseLexicalBinding = function (kind, options) { - var node = this.createNode(); - var params = []; - var id = this.parsePattern(params, kind); - if (this.context.strict && id.type === syntax_1.Syntax.Identifier) { - if (this.scanner.isRestrictedWord(id.name)) { - this.tolerateError(messages_1.Messages.StrictVarName); - } - } - var init = null; - if (kind === 'const') { - if (!this.matchKeyword('in') && !this.matchContextualKeyword('of')) { - if (this.match('=')) { - this.nextToken(); - init = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - else { - this.throwError(messages_1.Messages.DeclarationMissingInitializer, 'const'); - } - } - } - else if ((!options.inFor && id.type !== syntax_1.Syntax.Identifier) || this.match('=')) { - this.expect('='); - init = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - return this.finalize(node, new Node.VariableDeclarator(id, init)); - }; - Parser.prototype.parseBindingList = function (kind, options) { - var list = [this.parseLexicalBinding(kind, options)]; - while (this.match(',')) { - this.nextToken(); - list.push(this.parseLexicalBinding(kind, options)); - } - return list; - }; - Parser.prototype.isLexicalDeclaration = function () { - var state = this.scanner.saveState(); - this.scanner.scanComments(); - var next = this.scanner.lex(); - this.scanner.restoreState(state); - return (next.type === 3 /* Identifier */) || - (next.type === 7 /* Punctuator */ && next.value === '[') || - (next.type === 7 /* Punctuator */ && next.value === '{') || - (next.type === 4 /* Keyword */ && next.value === 'let') || - (next.type === 4 /* Keyword */ && next.value === 'yield'); - }; - Parser.prototype.parseLexicalDeclaration = function (options) { - var node = this.createNode(); - var kind = this.nextToken().value; - assert_1.assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const'); - var declarations = this.parseBindingList(kind, options); - this.consumeSemicolon(); - return this.finalize(node, new Node.VariableDeclaration(declarations, kind)); - }; - // https://tc39.github.io/ecma262/#sec-destructuring-binding-patterns - Parser.prototype.parseBindingRestElement = function (params, kind) { - var node = this.createNode(); - this.expect('...'); - var arg = this.parsePattern(params, kind); - return this.finalize(node, new Node.RestElement(arg)); - }; - Parser.prototype.parseArrayPattern = function (params, kind) { - var node = this.createNode(); - this.expect('['); - var elements = []; - while (!this.match(']')) { - if (this.match(',')) { - this.nextToken(); - elements.push(null); - } - else { - if (this.match('...')) { - elements.push(this.parseBindingRestElement(params, kind)); - break; - } - else { - elements.push(this.parsePatternWithDefault(params, kind)); - } - if (!this.match(']')) { - this.expect(','); - } - } - } - this.expect(']'); - return this.finalize(node, new Node.ArrayPattern(elements)); - }; - Parser.prototype.parsePropertyPattern = function (params, kind) { - var node = this.createNode(); - var computed = false; - var shorthand = false; - var method = false; - var key; - var value; - if (this.lookahead.type === 3 /* Identifier */) { - var keyToken = this.lookahead; - key = this.parseVariableIdentifier(); - var init = this.finalize(node, new Node.Identifier(keyToken.value)); - if (this.match('=')) { - params.push(keyToken); - shorthand = true; - this.nextToken(); - var expr = this.parseAssignmentExpression(); - value = this.finalize(this.startNode(keyToken), new Node.AssignmentPattern(init, expr)); - } - else if (!this.match(':')) { - params.push(keyToken); - shorthand = true; - value = init; - } - else { - this.expect(':'); - value = this.parsePatternWithDefault(params, kind); - } - } - else { - computed = this.match('['); - key = this.parseObjectPropertyKey(); - this.expect(':'); - value = this.parsePatternWithDefault(params, kind); - } - return this.finalize(node, new Node.Property('init', key, computed, value, method, shorthand)); - }; - Parser.prototype.parseObjectPattern = function (params, kind) { - var node = this.createNode(); - var properties = []; - this.expect('{'); - while (!this.match('}')) { - properties.push(this.parsePropertyPattern(params, kind)); - if (!this.match('}')) { - this.expect(','); - } - } - this.expect('}'); - return this.finalize(node, new Node.ObjectPattern(properties)); - }; - Parser.prototype.parsePattern = function (params, kind) { - var pattern; - if (this.match('[')) { - pattern = this.parseArrayPattern(params, kind); - } - else if (this.match('{')) { - pattern = this.parseObjectPattern(params, kind); - } - else { - if (this.matchKeyword('let') && (kind === 'const' || kind === 'let')) { - this.tolerateUnexpectedToken(this.lookahead, messages_1.Messages.LetInLexicalBinding); - } - params.push(this.lookahead); - pattern = this.parseVariableIdentifier(kind); - } - return pattern; - }; - Parser.prototype.parsePatternWithDefault = function (params, kind) { - var startToken = this.lookahead; - var pattern = this.parsePattern(params, kind); - if (this.match('=')) { - this.nextToken(); - var previousAllowYield = this.context.allowYield; - this.context.allowYield = true; - var right = this.isolateCoverGrammar(this.parseAssignmentExpression); - this.context.allowYield = previousAllowYield; - pattern = this.finalize(this.startNode(startToken), new Node.AssignmentPattern(pattern, right)); - } - return pattern; - }; - // https://tc39.github.io/ecma262/#sec-variable-statement - Parser.prototype.parseVariableIdentifier = function (kind) { - var node = this.createNode(); - var token = this.nextToken(); - if (token.type === 4 /* Keyword */ && token.value === 'yield') { - if (this.context.strict) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); - } - else if (!this.context.allowYield) { - this.throwUnexpectedToken(token); - } - } - else if (token.type !== 3 /* Identifier */) { - if (this.context.strict && token.type === 4 /* Keyword */ && this.scanner.isStrictModeReservedWord(token.value)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictReservedWord); - } - else { - if (this.context.strict || token.value !== 'let' || kind !== 'var') { - this.throwUnexpectedToken(token); - } - } - } - else if ((this.context.isModule || this.context.await) && token.type === 3 /* Identifier */ && token.value === 'await') { - this.tolerateUnexpectedToken(token); - } - return this.finalize(node, new Node.Identifier(token.value)); - }; - Parser.prototype.parseVariableDeclaration = function (options) { - var node = this.createNode(); - var params = []; - var id = this.parsePattern(params, 'var'); - if (this.context.strict && id.type === syntax_1.Syntax.Identifier) { - if (this.scanner.isRestrictedWord(id.name)) { - this.tolerateError(messages_1.Messages.StrictVarName); - } - } - var init = null; - if (this.match('=')) { - this.nextToken(); - init = this.isolateCoverGrammar(this.parseAssignmentExpression); - } - else if (id.type !== syntax_1.Syntax.Identifier && !options.inFor) { - this.expect('='); - } - return this.finalize(node, new Node.VariableDeclarator(id, init)); - }; - Parser.prototype.parseVariableDeclarationList = function (options) { - var opt = { inFor: options.inFor }; - var list = []; - list.push(this.parseVariableDeclaration(opt)); - while (this.match(',')) { - this.nextToken(); - list.push(this.parseVariableDeclaration(opt)); - } - return list; - }; - Parser.prototype.parseVariableStatement = function () { - var node = this.createNode(); - this.expectKeyword('var'); - var declarations = this.parseVariableDeclarationList({ inFor: false }); - this.consumeSemicolon(); - return this.finalize(node, new Node.VariableDeclaration(declarations, 'var')); - }; - // https://tc39.github.io/ecma262/#sec-empty-statement - Parser.prototype.parseEmptyStatement = function () { - var node = this.createNode(); - this.expect(';'); - return this.finalize(node, new Node.EmptyStatement()); - }; - // https://tc39.github.io/ecma262/#sec-expression-statement - Parser.prototype.parseExpressionStatement = function () { - var node = this.createNode(); - var expr = this.parseExpression(); - this.consumeSemicolon(); - return this.finalize(node, new Node.ExpressionStatement(expr)); - }; - // https://tc39.github.io/ecma262/#sec-if-statement - Parser.prototype.parseIfClause = function () { - if (this.context.strict && this.matchKeyword('function')) { - this.tolerateError(messages_1.Messages.StrictFunction); - } - return this.parseStatement(); - }; - Parser.prototype.parseIfStatement = function () { - var node = this.createNode(); - var consequent; - var alternate = null; - this.expectKeyword('if'); - this.expect('('); - var test = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - consequent = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - consequent = this.parseIfClause(); - if (this.matchKeyword('else')) { - this.nextToken(); - alternate = this.parseIfClause(); - } - } - return this.finalize(node, new Node.IfStatement(test, consequent, alternate)); - }; - // https://tc39.github.io/ecma262/#sec-do-while-statement - Parser.prototype.parseDoWhileStatement = function () { - var node = this.createNode(); - this.expectKeyword('do'); - var previousInIteration = this.context.inIteration; - this.context.inIteration = true; - var body = this.parseStatement(); - this.context.inIteration = previousInIteration; - this.expectKeyword('while'); - this.expect('('); - var test = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - } - else { - this.expect(')'); - if (this.match(';')) { - this.nextToken(); - } - } - return this.finalize(node, new Node.DoWhileStatement(body, test)); - }; - // https://tc39.github.io/ecma262/#sec-while-statement - Parser.prototype.parseWhileStatement = function () { - var node = this.createNode(); - var body; - this.expectKeyword('while'); - this.expect('('); - var test = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - body = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - var previousInIteration = this.context.inIteration; - this.context.inIteration = true; - body = this.parseStatement(); - this.context.inIteration = previousInIteration; - } - return this.finalize(node, new Node.WhileStatement(test, body)); - }; - // https://tc39.github.io/ecma262/#sec-for-statement - // https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements - Parser.prototype.parseForStatement = function () { - var init = null; - var test = null; - var update = null; - var forIn = true; - var left, right; - var node = this.createNode(); - this.expectKeyword('for'); - this.expect('('); - if (this.match(';')) { - this.nextToken(); - } - else { - if (this.matchKeyword('var')) { - init = this.createNode(); - this.nextToken(); - var previousAllowIn = this.context.allowIn; - this.context.allowIn = false; - var declarations = this.parseVariableDeclarationList({ inFor: true }); - this.context.allowIn = previousAllowIn; - if (declarations.length === 1 && this.matchKeyword('in')) { - var decl = declarations[0]; - if (decl.init && (decl.id.type === syntax_1.Syntax.ArrayPattern || decl.id.type === syntax_1.Syntax.ObjectPattern || this.context.strict)) { - this.tolerateError(messages_1.Messages.ForInOfLoopInitializer, 'for-in'); - } - init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); - this.nextToken(); - left = init; - right = this.parseExpression(); - init = null; - } - else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) { - init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); - this.nextToken(); - left = init; - right = this.parseAssignmentExpression(); - init = null; - forIn = false; - } - else { - init = this.finalize(init, new Node.VariableDeclaration(declarations, 'var')); - this.expect(';'); - } - } - else if (this.matchKeyword('const') || this.matchKeyword('let')) { - init = this.createNode(); - var kind = this.nextToken().value; - if (!this.context.strict && this.lookahead.value === 'in') { - init = this.finalize(init, new Node.Identifier(kind)); - this.nextToken(); - left = init; - right = this.parseExpression(); - init = null; - } - else { - var previousAllowIn = this.context.allowIn; - this.context.allowIn = false; - var declarations = this.parseBindingList(kind, { inFor: true }); - this.context.allowIn = previousAllowIn; - if (declarations.length === 1 && declarations[0].init === null && this.matchKeyword('in')) { - init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); - this.nextToken(); - left = init; - right = this.parseExpression(); - init = null; - } - else if (declarations.length === 1 && declarations[0].init === null && this.matchContextualKeyword('of')) { - init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); - this.nextToken(); - left = init; - right = this.parseAssignmentExpression(); - init = null; - forIn = false; - } - else { - this.consumeSemicolon(); - init = this.finalize(init, new Node.VariableDeclaration(declarations, kind)); - } - } - } - else { - var initStartToken = this.lookahead; - var previousAllowIn = this.context.allowIn; - this.context.allowIn = false; - init = this.inheritCoverGrammar(this.parseAssignmentExpression); - this.context.allowIn = previousAllowIn; - if (this.matchKeyword('in')) { - if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) { - this.tolerateError(messages_1.Messages.InvalidLHSInForIn); - } - this.nextToken(); - this.reinterpretExpressionAsPattern(init); - left = init; - right = this.parseExpression(); - init = null; - } - else if (this.matchContextualKeyword('of')) { - if (!this.context.isAssignmentTarget || init.type === syntax_1.Syntax.AssignmentExpression) { - this.tolerateError(messages_1.Messages.InvalidLHSInForLoop); - } - this.nextToken(); - this.reinterpretExpressionAsPattern(init); - left = init; - right = this.parseAssignmentExpression(); - init = null; - forIn = false; - } - else { - if (this.match(',')) { - var initSeq = [init]; - while (this.match(',')) { - this.nextToken(); - initSeq.push(this.isolateCoverGrammar(this.parseAssignmentExpression)); - } - init = this.finalize(this.startNode(initStartToken), new Node.SequenceExpression(initSeq)); - } - this.expect(';'); - } - } - } - if (typeof left === 'undefined') { - if (!this.match(';')) { - test = this.parseExpression(); - } - this.expect(';'); - if (!this.match(')')) { - update = this.parseExpression(); - } - } - var body; - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - body = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - var previousInIteration = this.context.inIteration; - this.context.inIteration = true; - body = this.isolateCoverGrammar(this.parseStatement); - this.context.inIteration = previousInIteration; - } - return (typeof left === 'undefined') ? - this.finalize(node, new Node.ForStatement(init, test, update, body)) : - forIn ? this.finalize(node, new Node.ForInStatement(left, right, body)) : - this.finalize(node, new Node.ForOfStatement(left, right, body)); - }; - // https://tc39.github.io/ecma262/#sec-continue-statement - Parser.prototype.parseContinueStatement = function () { - var node = this.createNode(); - this.expectKeyword('continue'); - var label = null; - if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) { - var id = this.parseVariableIdentifier(); - label = id; - var key = '$' + id.name; - if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { - this.throwError(messages_1.Messages.UnknownLabel, id.name); - } - } - this.consumeSemicolon(); - if (label === null && !this.context.inIteration) { - this.throwError(messages_1.Messages.IllegalContinue); - } - return this.finalize(node, new Node.ContinueStatement(label)); - }; - // https://tc39.github.io/ecma262/#sec-break-statement - Parser.prototype.parseBreakStatement = function () { - var node = this.createNode(); - this.expectKeyword('break'); - var label = null; - if (this.lookahead.type === 3 /* Identifier */ && !this.hasLineTerminator) { - var id = this.parseVariableIdentifier(); - var key = '$' + id.name; - if (!Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { - this.throwError(messages_1.Messages.UnknownLabel, id.name); - } - label = id; - } - this.consumeSemicolon(); - if (label === null && !this.context.inIteration && !this.context.inSwitch) { - this.throwError(messages_1.Messages.IllegalBreak); - } - return this.finalize(node, new Node.BreakStatement(label)); - }; - // https://tc39.github.io/ecma262/#sec-return-statement - Parser.prototype.parseReturnStatement = function () { - if (!this.context.inFunctionBody) { - this.tolerateError(messages_1.Messages.IllegalReturn); - } - var node = this.createNode(); - this.expectKeyword('return'); - var hasArgument = (!this.match(';') && !this.match('}') && - !this.hasLineTerminator && this.lookahead.type !== 2 /* EOF */) || - this.lookahead.type === 8 /* StringLiteral */ || - this.lookahead.type === 10 /* Template */; - var argument = hasArgument ? this.parseExpression() : null; - this.consumeSemicolon(); - return this.finalize(node, new Node.ReturnStatement(argument)); - }; - // https://tc39.github.io/ecma262/#sec-with-statement - Parser.prototype.parseWithStatement = function () { - if (this.context.strict) { - this.tolerateError(messages_1.Messages.StrictModeWith); - } - var node = this.createNode(); - var body; - this.expectKeyword('with'); - this.expect('('); - var object = this.parseExpression(); - if (!this.match(')') && this.config.tolerant) { - this.tolerateUnexpectedToken(this.nextToken()); - body = this.finalize(this.createNode(), new Node.EmptyStatement()); - } - else { - this.expect(')'); - body = this.parseStatement(); - } - return this.finalize(node, new Node.WithStatement(object, body)); - }; - // https://tc39.github.io/ecma262/#sec-switch-statement - Parser.prototype.parseSwitchCase = function () { - var node = this.createNode(); - var test; - if (this.matchKeyword('default')) { - this.nextToken(); - test = null; - } - else { - this.expectKeyword('case'); - test = this.parseExpression(); - } - this.expect(':'); - var consequent = []; - while (true) { - if (this.match('}') || this.matchKeyword('default') || this.matchKeyword('case')) { - break; - } - consequent.push(this.parseStatementListItem()); - } - return this.finalize(node, new Node.SwitchCase(test, consequent)); - }; - Parser.prototype.parseSwitchStatement = function () { - var node = this.createNode(); - this.expectKeyword('switch'); - this.expect('('); - var discriminant = this.parseExpression(); - this.expect(')'); - var previousInSwitch = this.context.inSwitch; - this.context.inSwitch = true; - var cases = []; - var defaultFound = false; - this.expect('{'); - while (true) { - if (this.match('}')) { - break; - } - var clause = this.parseSwitchCase(); - if (clause.test === null) { - if (defaultFound) { - this.throwError(messages_1.Messages.MultipleDefaultsInSwitch); - } - defaultFound = true; - } - cases.push(clause); - } - this.expect('}'); - this.context.inSwitch = previousInSwitch; - return this.finalize(node, new Node.SwitchStatement(discriminant, cases)); - }; - // https://tc39.github.io/ecma262/#sec-labelled-statements - Parser.prototype.parseLabelledStatement = function () { - var node = this.createNode(); - var expr = this.parseExpression(); - var statement; - if ((expr.type === syntax_1.Syntax.Identifier) && this.match(':')) { - this.nextToken(); - var id = expr; - var key = '$' + id.name; - if (Object.prototype.hasOwnProperty.call(this.context.labelSet, key)) { - this.throwError(messages_1.Messages.Redeclaration, 'Label', id.name); - } - this.context.labelSet[key] = true; - var body = void 0; - if (this.matchKeyword('class')) { - this.tolerateUnexpectedToken(this.lookahead); - body = this.parseClassDeclaration(); - } - else if (this.matchKeyword('function')) { - var token = this.lookahead; - var declaration = this.parseFunctionDeclaration(); - if (this.context.strict) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunction); - } - else if (declaration.generator) { - this.tolerateUnexpectedToken(token, messages_1.Messages.GeneratorInLegacyContext); - } - body = declaration; - } - else { - body = this.parseStatement(); - } - delete this.context.labelSet[key]; - statement = new Node.LabeledStatement(id, body); - } - else { - this.consumeSemicolon(); - statement = new Node.ExpressionStatement(expr); - } - return this.finalize(node, statement); - }; - // https://tc39.github.io/ecma262/#sec-throw-statement - Parser.prototype.parseThrowStatement = function () { - var node = this.createNode(); - this.expectKeyword('throw'); - if (this.hasLineTerminator) { - this.throwError(messages_1.Messages.NewlineAfterThrow); - } - var argument = this.parseExpression(); - this.consumeSemicolon(); - return this.finalize(node, new Node.ThrowStatement(argument)); - }; - // https://tc39.github.io/ecma262/#sec-try-statement - Parser.prototype.parseCatchClause = function () { - var node = this.createNode(); - this.expectKeyword('catch'); - this.expect('('); - if (this.match(')')) { - this.throwUnexpectedToken(this.lookahead); - } - var params = []; - var param = this.parsePattern(params); - var paramMap = {}; - for (var i = 0; i < params.length; i++) { - var key = '$' + params[i].value; - if (Object.prototype.hasOwnProperty.call(paramMap, key)) { - this.tolerateError(messages_1.Messages.DuplicateBinding, params[i].value); - } - paramMap[key] = true; - } - if (this.context.strict && param.type === syntax_1.Syntax.Identifier) { - if (this.scanner.isRestrictedWord(param.name)) { - this.tolerateError(messages_1.Messages.StrictCatchVariable); - } - } - this.expect(')'); - var body = this.parseBlock(); - return this.finalize(node, new Node.CatchClause(param, body)); - }; - Parser.prototype.parseFinallyClause = function () { - this.expectKeyword('finally'); - return this.parseBlock(); - }; - Parser.prototype.parseTryStatement = function () { - var node = this.createNode(); - this.expectKeyword('try'); - var block = this.parseBlock(); - var handler = this.matchKeyword('catch') ? this.parseCatchClause() : null; - var finalizer = this.matchKeyword('finally') ? this.parseFinallyClause() : null; - if (!handler && !finalizer) { - this.throwError(messages_1.Messages.NoCatchOrFinally); - } - return this.finalize(node, new Node.TryStatement(block, handler, finalizer)); - }; - // https://tc39.github.io/ecma262/#sec-debugger-statement - Parser.prototype.parseDebuggerStatement = function () { - var node = this.createNode(); - this.expectKeyword('debugger'); - this.consumeSemicolon(); - return this.finalize(node, new Node.DebuggerStatement()); - }; - // https://tc39.github.io/ecma262/#sec-ecmascript-language-statements-and-declarations - Parser.prototype.parseStatement = function () { - var statement; - switch (this.lookahead.type) { - case 1 /* BooleanLiteral */: - case 5 /* NullLiteral */: - case 6 /* NumericLiteral */: - case 8 /* StringLiteral */: - case 10 /* Template */: - case 9 /* RegularExpression */: - statement = this.parseExpressionStatement(); - break; - case 7 /* Punctuator */: - var value = this.lookahead.value; - if (value === '{') { - statement = this.parseBlock(); - } - else if (value === '(') { - statement = this.parseExpressionStatement(); - } - else if (value === ';') { - statement = this.parseEmptyStatement(); - } - else { - statement = this.parseExpressionStatement(); - } - break; - case 3 /* Identifier */: - statement = this.matchAsyncFunction() ? this.parseFunctionDeclaration() : this.parseLabelledStatement(); - break; - case 4 /* Keyword */: - switch (this.lookahead.value) { - case 'break': - statement = this.parseBreakStatement(); - break; - case 'continue': - statement = this.parseContinueStatement(); - break; - case 'debugger': - statement = this.parseDebuggerStatement(); - break; - case 'do': - statement = this.parseDoWhileStatement(); - break; - case 'for': - statement = this.parseForStatement(); - break; - case 'function': - statement = this.parseFunctionDeclaration(); - break; - case 'if': - statement = this.parseIfStatement(); - break; - case 'return': - statement = this.parseReturnStatement(); - break; - case 'switch': - statement = this.parseSwitchStatement(); - break; - case 'throw': - statement = this.parseThrowStatement(); - break; - case 'try': - statement = this.parseTryStatement(); - break; - case 'var': - statement = this.parseVariableStatement(); - break; - case 'while': - statement = this.parseWhileStatement(); - break; - case 'with': - statement = this.parseWithStatement(); - break; - default: - statement = this.parseExpressionStatement(); - break; - } - break; - default: - statement = this.throwUnexpectedToken(this.lookahead); - } - return statement; - }; - // https://tc39.github.io/ecma262/#sec-function-definitions - Parser.prototype.parseFunctionSourceElements = function () { - var node = this.createNode(); - this.expect('{'); - var body = this.parseDirectivePrologues(); - var previousLabelSet = this.context.labelSet; - var previousInIteration = this.context.inIteration; - var previousInSwitch = this.context.inSwitch; - var previousInFunctionBody = this.context.inFunctionBody; - this.context.labelSet = {}; - this.context.inIteration = false; - this.context.inSwitch = false; - this.context.inFunctionBody = true; - while (this.lookahead.type !== 2 /* EOF */) { - if (this.match('}')) { - break; - } - body.push(this.parseStatementListItem()); - } - this.expect('}'); - this.context.labelSet = previousLabelSet; - this.context.inIteration = previousInIteration; - this.context.inSwitch = previousInSwitch; - this.context.inFunctionBody = previousInFunctionBody; - return this.finalize(node, new Node.BlockStatement(body)); - }; - Parser.prototype.validateParam = function (options, param, name) { - var key = '$' + name; - if (this.context.strict) { - if (this.scanner.isRestrictedWord(name)) { - options.stricted = param; - options.message = messages_1.Messages.StrictParamName; - } - if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { - options.stricted = param; - options.message = messages_1.Messages.StrictParamDupe; - } - } - else if (!options.firstRestricted) { - if (this.scanner.isRestrictedWord(name)) { - options.firstRestricted = param; - options.message = messages_1.Messages.StrictParamName; - } - else if (this.scanner.isStrictModeReservedWord(name)) { - options.firstRestricted = param; - options.message = messages_1.Messages.StrictReservedWord; - } - else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { - options.stricted = param; - options.message = messages_1.Messages.StrictParamDupe; - } - } - /* istanbul ignore next */ - if (typeof Object.defineProperty === 'function') { - Object.defineProperty(options.paramSet, key, { value: true, enumerable: true, writable: true, configurable: true }); - } - else { - options.paramSet[key] = true; - } - }; - Parser.prototype.parseRestElement = function (params) { - var node = this.createNode(); - this.expect('...'); - var arg = this.parsePattern(params); - if (this.match('=')) { - this.throwError(messages_1.Messages.DefaultRestParameter); - } - if (!this.match(')')) { - this.throwError(messages_1.Messages.ParameterAfterRestParameter); - } - return this.finalize(node, new Node.RestElement(arg)); - }; - Parser.prototype.parseFormalParameter = function (options) { - var params = []; - var param = this.match('...') ? this.parseRestElement(params) : this.parsePatternWithDefault(params); - for (var i = 0; i < params.length; i++) { - this.validateParam(options, params[i], params[i].value); - } - options.simple = options.simple && (param instanceof Node.Identifier); - options.params.push(param); - }; - Parser.prototype.parseFormalParameters = function (firstRestricted) { - var options; - options = { - simple: true, - params: [], - firstRestricted: firstRestricted - }; - this.expect('('); - if (!this.match(')')) { - options.paramSet = {}; - while (this.lookahead.type !== 2 /* EOF */) { - this.parseFormalParameter(options); - if (this.match(')')) { - break; - } - this.expect(','); - if (this.match(')')) { - break; - } - } - } - this.expect(')'); - return { - simple: options.simple, - params: options.params, - stricted: options.stricted, - firstRestricted: options.firstRestricted, - message: options.message - }; - }; - Parser.prototype.matchAsyncFunction = function () { - var match = this.matchContextualKeyword('async'); - if (match) { - var state = this.scanner.saveState(); - this.scanner.scanComments(); - var next = this.scanner.lex(); - this.scanner.restoreState(state); - match = (state.lineNumber === next.lineNumber) && (next.type === 4 /* Keyword */) && (next.value === 'function'); - } - return match; - }; - Parser.prototype.parseFunctionDeclaration = function (identifierIsOptional) { - var node = this.createNode(); - var isAsync = this.matchContextualKeyword('async'); - if (isAsync) { - this.nextToken(); - } - this.expectKeyword('function'); - var isGenerator = isAsync ? false : this.match('*'); - if (isGenerator) { - this.nextToken(); - } - var message; - var id = null; - var firstRestricted = null; - if (!identifierIsOptional || !this.match('(')) { - var token = this.lookahead; - id = this.parseVariableIdentifier(); - if (this.context.strict) { - if (this.scanner.isRestrictedWord(token.value)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName); - } - } - else { - if (this.scanner.isRestrictedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictFunctionName; - } - else if (this.scanner.isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictReservedWord; - } - } - } - var previousAllowAwait = this.context.await; - var previousAllowYield = this.context.allowYield; - this.context.await = isAsync; - this.context.allowYield = !isGenerator; - var formalParameters = this.parseFormalParameters(firstRestricted); - var params = formalParameters.params; - var stricted = formalParameters.stricted; - firstRestricted = formalParameters.firstRestricted; - if (formalParameters.message) { - message = formalParameters.message; - } - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = formalParameters.simple; - var body = this.parseFunctionSourceElements(); - if (this.context.strict && firstRestricted) { - this.throwUnexpectedToken(firstRestricted, message); - } - if (this.context.strict && stricted) { - this.tolerateUnexpectedToken(stricted, message); - } - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - this.context.await = previousAllowAwait; - this.context.allowYield = previousAllowYield; - return isAsync ? this.finalize(node, new Node.AsyncFunctionDeclaration(id, params, body)) : - this.finalize(node, new Node.FunctionDeclaration(id, params, body, isGenerator)); - }; - Parser.prototype.parseFunctionExpression = function () { - var node = this.createNode(); - var isAsync = this.matchContextualKeyword('async'); - if (isAsync) { - this.nextToken(); - } - this.expectKeyword('function'); - var isGenerator = isAsync ? false : this.match('*'); - if (isGenerator) { - this.nextToken(); - } - var message; - var id = null; - var firstRestricted; - var previousAllowAwait = this.context.await; - var previousAllowYield = this.context.allowYield; - this.context.await = isAsync; - this.context.allowYield = !isGenerator; - if (!this.match('(')) { - var token = this.lookahead; - id = (!this.context.strict && !isGenerator && this.matchKeyword('yield')) ? this.parseIdentifierName() : this.parseVariableIdentifier(); - if (this.context.strict) { - if (this.scanner.isRestrictedWord(token.value)) { - this.tolerateUnexpectedToken(token, messages_1.Messages.StrictFunctionName); - } - } - else { - if (this.scanner.isRestrictedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictFunctionName; - } - else if (this.scanner.isStrictModeReservedWord(token.value)) { - firstRestricted = token; - message = messages_1.Messages.StrictReservedWord; - } - } - } - var formalParameters = this.parseFormalParameters(firstRestricted); - var params = formalParameters.params; - var stricted = formalParameters.stricted; - firstRestricted = formalParameters.firstRestricted; - if (formalParameters.message) { - message = formalParameters.message; - } - var previousStrict = this.context.strict; - var previousAllowStrictDirective = this.context.allowStrictDirective; - this.context.allowStrictDirective = formalParameters.simple; - var body = this.parseFunctionSourceElements(); - if (this.context.strict && firstRestricted) { - this.throwUnexpectedToken(firstRestricted, message); - } - if (this.context.strict && stricted) { - this.tolerateUnexpectedToken(stricted, message); - } - this.context.strict = previousStrict; - this.context.allowStrictDirective = previousAllowStrictDirective; - this.context.await = previousAllowAwait; - this.context.allowYield = previousAllowYield; - return isAsync ? this.finalize(node, new Node.AsyncFunctionExpression(id, params, body)) : - this.finalize(node, new Node.FunctionExpression(id, params, body, isGenerator)); - }; - // https://tc39.github.io/ecma262/#sec-directive-prologues-and-the-use-strict-directive - Parser.prototype.parseDirective = function () { - var token = this.lookahead; - var node = this.createNode(); - var expr = this.parseExpression(); - var directive = (expr.type === syntax_1.Syntax.Literal) ? this.getTokenRaw(token).slice(1, -1) : null; - this.consumeSemicolon(); - return this.finalize(node, directive ? new Node.Directive(expr, directive) : new Node.ExpressionStatement(expr)); - }; - Parser.prototype.parseDirectivePrologues = function () { - var firstRestricted = null; - var body = []; - while (true) { - var token = this.lookahead; - if (token.type !== 8 /* StringLiteral */) { - break; - } - var statement = this.parseDirective(); - body.push(statement); - var directive = statement.directive; - if (typeof directive !== 'string') { - break; - } - if (directive === 'use strict') { - this.context.strict = true; - if (firstRestricted) { - this.tolerateUnexpectedToken(firstRestricted, messages_1.Messages.StrictOctalLiteral); - } - if (!this.context.allowStrictDirective) { - this.tolerateUnexpectedToken(token, messages_1.Messages.IllegalLanguageModeDirective); - } - } - else { - if (!firstRestricted && token.octal) { - firstRestricted = token; - } - } - } - return body; - }; - // https://tc39.github.io/ecma262/#sec-method-definitions - Parser.prototype.qualifiedPropertyName = function (token) { - switch (token.type) { - case 3 /* Identifier */: - case 8 /* StringLiteral */: - case 1 /* BooleanLiteral */: - case 5 /* NullLiteral */: - case 6 /* NumericLiteral */: - case 4 /* Keyword */: - return true; - case 7 /* Punctuator */: - return token.value === '['; - default: - break; - } - return false; - }; - Parser.prototype.parseGetterMethod = function () { - var node = this.createNode(); - var isGenerator = false; - var previousAllowYield = this.context.allowYield; - this.context.allowYield = !isGenerator; - var formalParameters = this.parseFormalParameters(); - if (formalParameters.params.length > 0) { - this.tolerateError(messages_1.Messages.BadGetterArity); - } - var method = this.parsePropertyMethod(formalParameters); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator)); - }; - Parser.prototype.parseSetterMethod = function () { - var node = this.createNode(); - var isGenerator = false; - var previousAllowYield = this.context.allowYield; - this.context.allowYield = !isGenerator; - var formalParameters = this.parseFormalParameters(); - if (formalParameters.params.length !== 1) { - this.tolerateError(messages_1.Messages.BadSetterArity); - } - else if (formalParameters.params[0] instanceof Node.RestElement) { - this.tolerateError(messages_1.Messages.BadSetterRestParameter); - } - var method = this.parsePropertyMethod(formalParameters); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, formalParameters.params, method, isGenerator)); - }; - Parser.prototype.parseGeneratorMethod = function () { - var node = this.createNode(); - var isGenerator = true; - var previousAllowYield = this.context.allowYield; - this.context.allowYield = true; - var params = this.parseFormalParameters(); - this.context.allowYield = false; - var method = this.parsePropertyMethod(params); - this.context.allowYield = previousAllowYield; - return this.finalize(node, new Node.FunctionExpression(null, params.params, method, isGenerator)); - }; - // https://tc39.github.io/ecma262/#sec-generator-function-definitions - Parser.prototype.isStartOfExpression = function () { - var start = true; - var value = this.lookahead.value; - switch (this.lookahead.type) { - case 7 /* Punctuator */: - start = (value === '[') || (value === '(') || (value === '{') || - (value === '+') || (value === '-') || - (value === '!') || (value === '~') || - (value === '++') || (value === '--') || - (value === '/') || (value === '/='); // regular expression literal - break; - case 4 /* Keyword */: - start = (value === 'class') || (value === 'delete') || - (value === 'function') || (value === 'let') || (value === 'new') || - (value === 'super') || (value === 'this') || (value === 'typeof') || - (value === 'void') || (value === 'yield'); - break; - default: - break; - } - return start; - }; - Parser.prototype.parseYieldExpression = function () { - var node = this.createNode(); - this.expectKeyword('yield'); - var argument = null; - var delegate = false; - if (!this.hasLineTerminator) { - var previousAllowYield = this.context.allowYield; - this.context.allowYield = false; - delegate = this.match('*'); - if (delegate) { - this.nextToken(); - argument = this.parseAssignmentExpression(); - } - else if (this.isStartOfExpression()) { - argument = this.parseAssignmentExpression(); - } - this.context.allowYield = previousAllowYield; - } - return this.finalize(node, new Node.YieldExpression(argument, delegate)); - }; - // https://tc39.github.io/ecma262/#sec-class-definitions - Parser.prototype.parseClassElement = function (hasConstructor) { - var token = this.lookahead; - var node = this.createNode(); - var kind = ''; - var key = null; - var value = null; - var computed = false; - var method = false; - var isStatic = false; - var isAsync = false; - if (this.match('*')) { - this.nextToken(); - } - else { - computed = this.match('['); - key = this.parseObjectPropertyKey(); - var id = key; - if (id.name === 'static' && (this.qualifiedPropertyName(this.lookahead) || this.match('*'))) { - token = this.lookahead; - isStatic = true; - computed = this.match('['); - if (this.match('*')) { - this.nextToken(); - } - else { - key = this.parseObjectPropertyKey(); - } - } - if ((token.type === 3 /* Identifier */) && !this.hasLineTerminator && (token.value === 'async')) { - var punctuator = this.lookahead.value; - if (punctuator !== ':' && punctuator !== '(' && punctuator !== '*') { - isAsync = true; - token = this.lookahead; - key = this.parseObjectPropertyKey(); - if (token.type === 3 /* Identifier */ && token.value === 'constructor') { - this.tolerateUnexpectedToken(token, messages_1.Messages.ConstructorIsAsync); - } - } - } - } - var lookaheadPropertyKey = this.qualifiedPropertyName(this.lookahead); - if (token.type === 3 /* Identifier */) { - if (token.value === 'get' && lookaheadPropertyKey) { - kind = 'get'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - this.context.allowYield = false; - value = this.parseGetterMethod(); - } - else if (token.value === 'set' && lookaheadPropertyKey) { - kind = 'set'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseSetterMethod(); - } - } - else if (token.type === 7 /* Punctuator */ && token.value === '*' && lookaheadPropertyKey) { - kind = 'init'; - computed = this.match('['); - key = this.parseObjectPropertyKey(); - value = this.parseGeneratorMethod(); - method = true; - } - if (!kind && key && this.match('(')) { - kind = 'init'; - value = isAsync ? this.parsePropertyMethodAsyncFunction() : this.parsePropertyMethodFunction(); - method = true; - } - if (!kind) { - this.throwUnexpectedToken(this.lookahead); - } - if (kind === 'init') { - kind = 'method'; - } - if (!computed) { - if (isStatic && this.isPropertyKey(key, 'prototype')) { - this.throwUnexpectedToken(token, messages_1.Messages.StaticPrototype); - } - if (!isStatic && this.isPropertyKey(key, 'constructor')) { - if (kind !== 'method' || !method || (value && value.generator)) { - this.throwUnexpectedToken(token, messages_1.Messages.ConstructorSpecialMethod); - } - if (hasConstructor.value) { - this.throwUnexpectedToken(token, messages_1.Messages.DuplicateConstructor); - } - else { - hasConstructor.value = true; - } - kind = 'constructor'; - } - } - return this.finalize(node, new Node.MethodDefinition(key, computed, value, kind, isStatic)); - }; - Parser.prototype.parseClassElementList = function () { - var body = []; - var hasConstructor = { value: false }; - this.expect('{'); - while (!this.match('}')) { - if (this.match(';')) { - this.nextToken(); - } - else { - body.push(this.parseClassElement(hasConstructor)); - } - } - this.expect('}'); - return body; - }; - Parser.prototype.parseClassBody = function () { - var node = this.createNode(); - var elementList = this.parseClassElementList(); - return this.finalize(node, new Node.ClassBody(elementList)); - }; - Parser.prototype.parseClassDeclaration = function (identifierIsOptional) { - var node = this.createNode(); - var previousStrict = this.context.strict; - this.context.strict = true; - this.expectKeyword('class'); - var id = (identifierIsOptional && (this.lookahead.type !== 3 /* Identifier */)) ? null : this.parseVariableIdentifier(); - var superClass = null; - if (this.matchKeyword('extends')) { - this.nextToken(); - superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall); - } - var classBody = this.parseClassBody(); - this.context.strict = previousStrict; - return this.finalize(node, new Node.ClassDeclaration(id, superClass, classBody)); - }; - Parser.prototype.parseClassExpression = function () { - var node = this.createNode(); - var previousStrict = this.context.strict; - this.context.strict = true; - this.expectKeyword('class'); - var id = (this.lookahead.type === 3 /* Identifier */) ? this.parseVariableIdentifier() : null; - var superClass = null; - if (this.matchKeyword('extends')) { - this.nextToken(); - superClass = this.isolateCoverGrammar(this.parseLeftHandSideExpressionAllowCall); - } - var classBody = this.parseClassBody(); - this.context.strict = previousStrict; - return this.finalize(node, new Node.ClassExpression(id, superClass, classBody)); - }; - // https://tc39.github.io/ecma262/#sec-scripts - // https://tc39.github.io/ecma262/#sec-modules - Parser.prototype.parseModule = function () { - this.context.strict = true; - this.context.isModule = true; - this.scanner.isModule = true; - var node = this.createNode(); - var body = this.parseDirectivePrologues(); - while (this.lookahead.type !== 2 /* EOF */) { - body.push(this.parseStatementListItem()); - } - return this.finalize(node, new Node.Module(body)); - }; - Parser.prototype.parseScript = function () { - var node = this.createNode(); - var body = this.parseDirectivePrologues(); - while (this.lookahead.type !== 2 /* EOF */) { - body.push(this.parseStatementListItem()); - } - return this.finalize(node, new Node.Script(body)); - }; - // https://tc39.github.io/ecma262/#sec-imports - Parser.prototype.parseModuleSpecifier = function () { - var node = this.createNode(); - if (this.lookahead.type !== 8 /* StringLiteral */) { - this.throwError(messages_1.Messages.InvalidModuleSpecifier); - } - var token = this.nextToken(); - var raw = this.getTokenRaw(token); - return this.finalize(node, new Node.Literal(token.value, raw)); - }; - // import {} ...; - Parser.prototype.parseImportSpecifier = function () { - var node = this.createNode(); - var imported; - var local; - if (this.lookahead.type === 3 /* Identifier */) { - imported = this.parseVariableIdentifier(); - local = imported; - if (this.matchContextualKeyword('as')) { - this.nextToken(); - local = this.parseVariableIdentifier(); - } - } - else { - imported = this.parseIdentifierName(); - local = imported; - if (this.matchContextualKeyword('as')) { - this.nextToken(); - local = this.parseVariableIdentifier(); - } - else { - this.throwUnexpectedToken(this.nextToken()); - } - } - return this.finalize(node, new Node.ImportSpecifier(local, imported)); - }; - // {foo, bar as bas} - Parser.prototype.parseNamedImports = function () { - this.expect('{'); - var specifiers = []; - while (!this.match('}')) { - specifiers.push(this.parseImportSpecifier()); - if (!this.match('}')) { - this.expect(','); - } - } - this.expect('}'); - return specifiers; - }; - // import ...; - Parser.prototype.parseImportDefaultSpecifier = function () { - var node = this.createNode(); - var local = this.parseIdentifierName(); - return this.finalize(node, new Node.ImportDefaultSpecifier(local)); - }; - // import <* as foo> ...; - Parser.prototype.parseImportNamespaceSpecifier = function () { - var node = this.createNode(); - this.expect('*'); - if (!this.matchContextualKeyword('as')) { - this.throwError(messages_1.Messages.NoAsAfterImportNamespace); - } - this.nextToken(); - var local = this.parseIdentifierName(); - return this.finalize(node, new Node.ImportNamespaceSpecifier(local)); - }; - Parser.prototype.parseImportDeclaration = function () { - if (this.context.inFunctionBody) { - this.throwError(messages_1.Messages.IllegalImportDeclaration); - } - var node = this.createNode(); - this.expectKeyword('import'); - var src; - var specifiers = []; - if (this.lookahead.type === 8 /* StringLiteral */) { - // import 'foo'; - src = this.parseModuleSpecifier(); - } - else { - if (this.match('{')) { - // import {bar} - specifiers = specifiers.concat(this.parseNamedImports()); - } - else if (this.match('*')) { - // import * as foo - specifiers.push(this.parseImportNamespaceSpecifier()); - } - else if (this.isIdentifierName(this.lookahead) && !this.matchKeyword('default')) { - // import foo - specifiers.push(this.parseImportDefaultSpecifier()); - if (this.match(',')) { - this.nextToken(); - if (this.match('*')) { - // import foo, * as foo - specifiers.push(this.parseImportNamespaceSpecifier()); - } - else if (this.match('{')) { - // import foo, {bar} - specifiers = specifiers.concat(this.parseNamedImports()); - } - else { - this.throwUnexpectedToken(this.lookahead); - } - } - } - else { - this.throwUnexpectedToken(this.nextToken()); - } - if (!this.matchContextualKeyword('from')) { - var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; - this.throwError(message, this.lookahead.value); - } - this.nextToken(); - src = this.parseModuleSpecifier(); - } - this.consumeSemicolon(); - return this.finalize(node, new Node.ImportDeclaration(specifiers, src)); - }; - // https://tc39.github.io/ecma262/#sec-exports - Parser.prototype.parseExportSpecifier = function () { - var node = this.createNode(); - var local = this.parseIdentifierName(); - var exported = local; - if (this.matchContextualKeyword('as')) { - this.nextToken(); - exported = this.parseIdentifierName(); - } - return this.finalize(node, new Node.ExportSpecifier(local, exported)); - }; - Parser.prototype.parseExportDeclaration = function () { - if (this.context.inFunctionBody) { - this.throwError(messages_1.Messages.IllegalExportDeclaration); - } - var node = this.createNode(); - this.expectKeyword('export'); - var exportDeclaration; - if (this.matchKeyword('default')) { - // export default ... - this.nextToken(); - if (this.matchKeyword('function')) { - // export default function foo () {} - // export default function () {} - var declaration = this.parseFunctionDeclaration(true); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - else if (this.matchKeyword('class')) { - // export default class foo {} - var declaration = this.parseClassDeclaration(true); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - else if (this.matchContextualKeyword('async')) { - // export default async function f () {} - // export default async function () {} - // export default async x => x - var declaration = this.matchAsyncFunction() ? this.parseFunctionDeclaration(true) : this.parseAssignmentExpression(); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - else { - if (this.matchContextualKeyword('from')) { - this.throwError(messages_1.Messages.UnexpectedToken, this.lookahead.value); - } - // export default {}; - // export default []; - // export default (1 + 2); - var declaration = this.match('{') ? this.parseObjectInitializer() : - this.match('[') ? this.parseArrayInitializer() : this.parseAssignmentExpression(); - this.consumeSemicolon(); - exportDeclaration = this.finalize(node, new Node.ExportDefaultDeclaration(declaration)); - } - } - else if (this.match('*')) { - // export * from 'foo'; - this.nextToken(); - if (!this.matchContextualKeyword('from')) { - var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; - this.throwError(message, this.lookahead.value); - } - this.nextToken(); - var src = this.parseModuleSpecifier(); - this.consumeSemicolon(); - exportDeclaration = this.finalize(node, new Node.ExportAllDeclaration(src)); - } - else if (this.lookahead.type === 4 /* Keyword */) { - // export var f = 1; - var declaration = void 0; - switch (this.lookahead.value) { - case 'let': - case 'const': - declaration = this.parseLexicalDeclaration({ inFor: false }); - break; - case 'var': - case 'class': - case 'function': - declaration = this.parseStatementListItem(); - break; - default: - this.throwUnexpectedToken(this.lookahead); - } - exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null)); - } - else if (this.matchAsyncFunction()) { - var declaration = this.parseFunctionDeclaration(); - exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(declaration, [], null)); - } - else { - var specifiers = []; - var source = null; - var isExportFromIdentifier = false; - this.expect('{'); - while (!this.match('}')) { - isExportFromIdentifier = isExportFromIdentifier || this.matchKeyword('default'); - specifiers.push(this.parseExportSpecifier()); - if (!this.match('}')) { - this.expect(','); - } - } - this.expect('}'); - if (this.matchContextualKeyword('from')) { - // export {default} from 'foo'; - // export {foo} from 'foo'; - this.nextToken(); - source = this.parseModuleSpecifier(); - this.consumeSemicolon(); - } - else if (isExportFromIdentifier) { - // export {default}; // missing fromClause - var message = this.lookahead.value ? messages_1.Messages.UnexpectedToken : messages_1.Messages.MissingFromClause; - this.throwError(message, this.lookahead.value); - } - else { - // export {foo}; - this.consumeSemicolon(); - } - exportDeclaration = this.finalize(node, new Node.ExportNamedDeclaration(null, specifiers, source)); - } - return exportDeclaration; - }; - return Parser; - }()); - exports.Parser = Parser; - - -/***/ }, -/* 9 */ -/***/ function(module, exports) { - - "use strict"; - // Ensure the condition is true, otherwise throw an error. - // This is only to have a better contract semantic, i.e. another safety net - // to catch a logic error. The condition shall be fulfilled in normal case. - // Do NOT use this to enforce a certain condition on any user input. - Object.defineProperty(exports, "__esModule", { value: true }); - function assert(condition, message) { - /* istanbul ignore if */ - if (!condition) { - throw new Error('ASSERT: ' + message); - } - } - exports.assert = assert; - - -/***/ }, -/* 10 */ -/***/ function(module, exports) { - - "use strict"; - /* tslint:disable:max-classes-per-file */ - Object.defineProperty(exports, "__esModule", { value: true }); - var ErrorHandler = (function () { - function ErrorHandler() { - this.errors = []; - this.tolerant = false; - } - ErrorHandler.prototype.recordError = function (error) { - this.errors.push(error); - }; - ErrorHandler.prototype.tolerate = function (error) { - if (this.tolerant) { - this.recordError(error); - } - else { - throw error; - } - }; - ErrorHandler.prototype.constructError = function (msg, column) { - var error = new Error(msg); - try { - throw error; - } - catch (base) { - /* istanbul ignore else */ - if (Object.create && Object.defineProperty) { - error = Object.create(base); - Object.defineProperty(error, 'column', { value: column }); - } - } - /* istanbul ignore next */ - return error; - }; - ErrorHandler.prototype.createError = function (index, line, col, description) { - var msg = 'Line ' + line + ': ' + description; - var error = this.constructError(msg, col); - error.index = index; - error.lineNumber = line; - error.description = description; - return error; - }; - ErrorHandler.prototype.throwError = function (index, line, col, description) { - throw this.createError(index, line, col, description); - }; - ErrorHandler.prototype.tolerateError = function (index, line, col, description) { - var error = this.createError(index, line, col, description); - if (this.tolerant) { - this.recordError(error); - } - else { - throw error; - } - }; - return ErrorHandler; - }()); - exports.ErrorHandler = ErrorHandler; - - -/***/ }, -/* 11 */ -/***/ function(module, exports) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - // Error messages should be identical to V8. - exports.Messages = { - BadGetterArity: 'Getter must not have any formal parameters', - BadSetterArity: 'Setter must have exactly one formal parameter', - BadSetterRestParameter: 'Setter function argument must not be a rest parameter', - ConstructorIsAsync: 'Class constructor may not be an async method', - ConstructorSpecialMethod: 'Class constructor may not be an accessor', - DeclarationMissingInitializer: 'Missing initializer in %0 declaration', - DefaultRestParameter: 'Unexpected token =', - DuplicateBinding: 'Duplicate binding %0', - DuplicateConstructor: 'A class may only have one constructor', - DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals', - ForInOfLoopInitializer: '%0 loop variable declaration may not have an initializer', - GeneratorInLegacyContext: 'Generator declarations are not allowed in legacy contexts', - IllegalBreak: 'Illegal break statement', - IllegalContinue: 'Illegal continue statement', - IllegalExportDeclaration: 'Unexpected token', - IllegalImportDeclaration: 'Unexpected token', - IllegalLanguageModeDirective: 'Illegal \'use strict\' directive in function with non-simple parameter list', - IllegalReturn: 'Illegal return statement', - InvalidEscapedReservedWord: 'Keyword must not contain escaped characters', - InvalidHexEscapeSequence: 'Invalid hexadecimal escape sequence', - InvalidLHSInAssignment: 'Invalid left-hand side in assignment', - InvalidLHSInForIn: 'Invalid left-hand side in for-in', - InvalidLHSInForLoop: 'Invalid left-hand side in for-loop', - InvalidModuleSpecifier: 'Unexpected token', - InvalidRegExp: 'Invalid regular expression', - LetInLexicalBinding: 'let is disallowed as a lexically bound name', - MissingFromClause: 'Unexpected token', - MultipleDefaultsInSwitch: 'More than one default clause in switch statement', - NewlineAfterThrow: 'Illegal newline after throw', - NoAsAfterImportNamespace: 'Unexpected token', - NoCatchOrFinally: 'Missing catch or finally after try', - ParameterAfterRestParameter: 'Rest parameter must be last formal parameter', - Redeclaration: '%0 \'%1\' has already been declared', - StaticPrototype: 'Classes may not have static property named prototype', - StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', - StrictDelete: 'Delete of an unqualified identifier in strict mode.', - StrictFunction: 'In strict mode code, functions can only be declared at top level or inside a block', - StrictFunctionName: 'Function name may not be eval or arguments in strict mode', - StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', - StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', - StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', - StrictModeWith: 'Strict mode code may not include a with statement', - StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', - StrictParamDupe: 'Strict mode function may not have duplicate parameter names', - StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', - StrictReservedWord: 'Use of future reserved word in strict mode', - StrictVarName: 'Variable name may not be eval or arguments in strict mode', - TemplateOctalLiteral: 'Octal literals are not allowed in template strings.', - UnexpectedEOS: 'Unexpected end of input', - UnexpectedIdentifier: 'Unexpected identifier', - UnexpectedNumber: 'Unexpected number', - UnexpectedReserved: 'Unexpected reserved word', - UnexpectedString: 'Unexpected string', - UnexpectedTemplate: 'Unexpected quasi %0', - UnexpectedToken: 'Unexpected token %0', - UnexpectedTokenIllegal: 'Unexpected token ILLEGAL', - UnknownLabel: 'Undefined label \'%0\'', - UnterminatedRegExp: 'Invalid regular expression: missing /' - }; - - -/***/ }, -/* 12 */ -/***/ function(module, exports, __webpack_require__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var assert_1 = __webpack_require__(9); - var character_1 = __webpack_require__(4); - var messages_1 = __webpack_require__(11); - function hexValue(ch) { - return '0123456789abcdef'.indexOf(ch.toLowerCase()); - } - function octalValue(ch) { - return '01234567'.indexOf(ch); - } - var Scanner = (function () { - function Scanner(code, handler) { - this.source = code; - this.errorHandler = handler; - this.trackComment = false; - this.isModule = false; - this.length = code.length; - this.index = 0; - this.lineNumber = (code.length > 0) ? 1 : 0; - this.lineStart = 0; - this.curlyStack = []; - } - Scanner.prototype.saveState = function () { - return { - index: this.index, - lineNumber: this.lineNumber, - lineStart: this.lineStart - }; - }; - Scanner.prototype.restoreState = function (state) { - this.index = state.index; - this.lineNumber = state.lineNumber; - this.lineStart = state.lineStart; - }; - Scanner.prototype.eof = function () { - return this.index >= this.length; - }; - Scanner.prototype.throwUnexpectedToken = function (message) { - if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; } - return this.errorHandler.throwError(this.index, this.lineNumber, this.index - this.lineStart + 1, message); - }; - Scanner.prototype.tolerateUnexpectedToken = function (message) { - if (message === void 0) { message = messages_1.Messages.UnexpectedTokenIllegal; } - this.errorHandler.tolerateError(this.index, this.lineNumber, this.index - this.lineStart + 1, message); - }; - // https://tc39.github.io/ecma262/#sec-comments - Scanner.prototype.skipSingleLineComment = function (offset) { - var comments = []; - var start, loc; - if (this.trackComment) { - comments = []; - start = this.index - offset; - loc = { - start: { - line: this.lineNumber, - column: this.index - this.lineStart - offset - }, - end: {} - }; - } - while (!this.eof()) { - var ch = this.source.charCodeAt(this.index); - ++this.index; - if (character_1.Character.isLineTerminator(ch)) { - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - 1 - }; - var entry = { - multiLine: false, - slice: [start + offset, this.index - 1], - range: [start, this.index - 1], - loc: loc - }; - comments.push(entry); - } - if (ch === 13 && this.source.charCodeAt(this.index) === 10) { - ++this.index; - } - ++this.lineNumber; - this.lineStart = this.index; - return comments; - } - } - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - }; - var entry = { - multiLine: false, - slice: [start + offset, this.index], - range: [start, this.index], - loc: loc - }; - comments.push(entry); - } - return comments; - }; - Scanner.prototype.skipMultiLineComment = function () { - var comments = []; - var start, loc; - if (this.trackComment) { - comments = []; - start = this.index - 2; - loc = { - start: { - line: this.lineNumber, - column: this.index - this.lineStart - 2 - }, - end: {} - }; - } - while (!this.eof()) { - var ch = this.source.charCodeAt(this.index); - if (character_1.Character.isLineTerminator(ch)) { - if (ch === 0x0D && this.source.charCodeAt(this.index + 1) === 0x0A) { - ++this.index; - } - ++this.lineNumber; - ++this.index; - this.lineStart = this.index; - } - else if (ch === 0x2A) { - // Block comment ends with '*/'. - if (this.source.charCodeAt(this.index + 1) === 0x2F) { - this.index += 2; - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - }; - var entry = { - multiLine: true, - slice: [start + 2, this.index - 2], - range: [start, this.index], - loc: loc - }; - comments.push(entry); - } - return comments; - } - ++this.index; - } - else { - ++this.index; - } - } - // Ran off the end of the file - the whole thing is a comment - if (this.trackComment) { - loc.end = { - line: this.lineNumber, - column: this.index - this.lineStart - }; - var entry = { - multiLine: true, - slice: [start + 2, this.index], - range: [start, this.index], - loc: loc - }; - comments.push(entry); - } - this.tolerateUnexpectedToken(); - return comments; - }; - Scanner.prototype.scanComments = function () { - var comments; - if (this.trackComment) { - comments = []; - } - var start = (this.index === 0); - while (!this.eof()) { - var ch = this.source.charCodeAt(this.index); - if (character_1.Character.isWhiteSpace(ch)) { - ++this.index; - } - else if (character_1.Character.isLineTerminator(ch)) { - ++this.index; - if (ch === 0x0D && this.source.charCodeAt(this.index) === 0x0A) { - ++this.index; - } - ++this.lineNumber; - this.lineStart = this.index; - start = true; - } - else if (ch === 0x2F) { - ch = this.source.charCodeAt(this.index + 1); - if (ch === 0x2F) { - this.index += 2; - var comment = this.skipSingleLineComment(2); - if (this.trackComment) { - comments = comments.concat(comment); - } - start = true; - } - else if (ch === 0x2A) { - this.index += 2; - var comment = this.skipMultiLineComment(); - if (this.trackComment) { - comments = comments.concat(comment); - } - } - else { - break; - } - } - else if (start && ch === 0x2D) { - // U+003E is '>' - if ((this.source.charCodeAt(this.index + 1) === 0x2D) && (this.source.charCodeAt(this.index + 2) === 0x3E)) { - // '-->' is a single-line comment - this.index += 3; - var comment = this.skipSingleLineComment(3); - if (this.trackComment) { - comments = comments.concat(comment); - } - } - else { - break; - } - } - else if (ch === 0x3C && !this.isModule) { - if (this.source.slice(this.index + 1, this.index + 4) === '!--') { - this.index += 4; // `' is a single-line comment + this.index += 3 + var comment = this.skipSingleLineComment(3) + if (this.trackComment) { + comments = comments.concat(comment) + } + } else { + break + } + } else if (ch === 0x3c && !this.isModule) { + if ( + this.source.slice( + this.index + 1, + this.index + 4 + ) === '!--' + ) { + this.index += 4 // `|EventPluginHub| | Event | - * | | . | | +-----------+ | Propagators| - * | ReactEvent | . | | |TapEvent | |------------| - * | Emitter | . | |<---+|Plugin | |other plugin| - * | | . | | +-----------+ | utilities | - * | +-----------.--->| | +------------+ - * | | | . +--------------+ - * +-----|------+ . ^ +-----------+ - * | . | |Enter/Leave| - * + . +-------+|Plugin | - * +-------------+ . +-----------+ - * | application | . - * |-------------| . - * | | . - * | | . - * +-------------+ . - * . - * React Core . General Purpose Event Plugin System - */ - -var alreadyListeningTo = {}; -var reactTopListenersCounter = 0; - -/** - * To ensure no conflicts with other potential React instances on the page - */ -var topListenersIDKey = '_reactListenersID' + ('' + Math.random()).slice(2); - -function getListeningForDocument(mountAt) { - // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty` - // directly. - if (!Object.prototype.hasOwnProperty.call(mountAt, topListenersIDKey)) { - mountAt[topListenersIDKey] = reactTopListenersCounter++; - alreadyListeningTo[mountAt[topListenersIDKey]] = {}; - } - return alreadyListeningTo[mountAt[topListenersIDKey]]; -} - -/** - * We listen for bubbled touch events on the document object. - * - * Firefox v8.01 (and possibly others) exhibited strange behavior when - * mounting `onmousemove` events at some node that was not the document - * element. The symptoms were that if your mouse is not moving over something - * contained within that mount point (for example on the background) the - * top-level listeners for `onmousemove` won't be called. However, if you - * register the `mousemove` on the document object, then it will of course - * catch all `mousemove`s. This along with iOS quirks, justifies restricting - * top-level listeners to the document object only, at least for these - * movement types of events and possibly all events. - * - * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html - * - * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but - * they bubble to document. - * - * @param {string} registrationName Name of listener (e.g. `onClick`). - * @param {object} contentDocumentHandle Document which owns the container - */ -function listenTo(registrationName, contentDocumentHandle) { - var mountAt = contentDocumentHandle; - var isListening = getListeningForDocument(mountAt); - var dependencies = registrationNameDependencies[registrationName]; - - for (var i = 0; i < dependencies.length; i++) { - var dependency = dependencies[i]; - if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) { - if (dependency === 'topScroll') { - trapCapturedEvent('topScroll', 'scroll', mountAt); - } else if (dependency === 'topFocus' || dependency === 'topBlur') { - trapCapturedEvent('topFocus', 'focus', mountAt); - trapCapturedEvent('topBlur', 'blur', mountAt); - - // to make sure blur and focus event listeners are only attached once - isListening.topBlur = true; - isListening.topFocus = true; - } else if (dependency === 'topCancel') { - if (isEventSupported('cancel', true)) { - trapCapturedEvent('topCancel', 'cancel', mountAt); - } - isListening.topCancel = true; - } else if (dependency === 'topClose') { - if (isEventSupported('close', true)) { - trapCapturedEvent('topClose', 'close', mountAt); - } - isListening.topClose = true; - } else if (topLevelTypes.hasOwnProperty(dependency)) { - trapBubbledEvent(dependency, topLevelTypes[dependency], mountAt); - } + function getEventModifierState(nativeEvent) { + return modifierStateGetter + } - isListening[dependency] = true; - } - } -} - -function isListeningToAllDependencies(registrationName, mountAt) { - var isListening = getListeningForDocument(mountAt); - var dependencies = registrationNameDependencies[registrationName]; - for (var i = 0; i < dependencies.length; i++) { - var dependency = dependencies[i]; - if (!(isListening.hasOwnProperty(dependency) && isListening[dependency])) { - return false; - } - } - return true; -} - -/** - * Given any node return the first leaf node without children. - * - * @param {DOMElement|DOMTextNode} node - * @return {DOMElement|DOMTextNode} - */ -function getLeafNode(node) { - while (node && node.firstChild) { - node = node.firstChild; - } - return node; -} - -/** - * Get the next sibling within a container. This will walk up the - * DOM if a node's siblings have been exhausted. - * - * @param {DOMElement|DOMTextNode} node - * @return {?DOMElement|DOMTextNode} - */ -function getSiblingNode(node) { - while (node) { - if (node.nextSibling) { - return node.nextSibling; - } - node = node.parentNode; - } -} - -/** - * Get object describing the nodes which contain characters at offset. - * - * @param {DOMElement|DOMTextNode} root - * @param {number} offset - * @return {?object} - */ -function getNodeForCharacterOffset(root, offset) { - var node = getLeafNode(root); - var nodeStart = 0; - var nodeEnd = 0; - - while (node) { - if (node.nodeType === TEXT_NODE) { - nodeEnd = nodeStart + node.textContent.length; - - if (nodeStart <= offset && nodeEnd >= offset) { - return { - node: node, - offset: offset - nodeStart - }; - } + /** + * @interface MouseEvent + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ + var SyntheticMouseEvent = SyntheticUIEvent.extend({ + screenX: null, + screenY: null, + clientX: null, + clientY: null, + pageX: null, + pageY: null, + ctrlKey: null, + shiftKey: null, + altKey: null, + metaKey: null, + getModifierState: getEventModifierState, + button: null, + buttons: null, + relatedTarget: function (event) { + return ( + event.relatedTarget || + (event.fromElement === event.srcElement + ? event.toElement + : event.fromElement) + ) + }, + }) + + var eventTypes$2 = { + mouseEnter: { + registrationName: 'onMouseEnter', + dependencies: ['topMouseOut', 'topMouseOver'], + }, + mouseLeave: { + registrationName: 'onMouseLeave', + dependencies: ['topMouseOut', 'topMouseOver'], + }, + } - nodeStart = nodeEnd; - } + var EnterLeaveEventPlugin = { + eventTypes: eventTypes$2, + + /** + * For almost every interaction we care about, there will be both a top-level + * `mouseover` and `mouseout` event that occurs. Only use `mouseout` so that + * we do not extract duplicate events. However, moving the mouse into the + * browser from outside will not fire a `mouseout` event. In this case, we use + * the `mouseover` top-level event. + */ + extractEvents: function ( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + if ( + topLevelType === 'topMouseOver' && + (nativeEvent.relatedTarget || nativeEvent.fromElement) + ) { + return null + } + if ( + topLevelType !== 'topMouseOut' && + topLevelType !== 'topMouseOver' + ) { + // Must not be a mouse in or mouse out - ignoring. + return null + } + + var win = void 0 + if (nativeEventTarget.window === nativeEventTarget) { + // `nativeEventTarget` is probably a window object. + win = nativeEventTarget + } else { + // TODO: Figure out why `ownerDocument` is sometimes undefined in IE8. + var doc = nativeEventTarget.ownerDocument + if (doc) { + win = doc.defaultView || doc.parentWindow + } else { + win = window + } + } + + var from = void 0 + var to = void 0 + if (topLevelType === 'topMouseOut') { + from = targetInst + var related = + nativeEvent.relatedTarget || nativeEvent.toElement + to = related ? getClosestInstanceFromNode(related) : null + } else { + // Moving to a node from outside the window. + from = null + to = targetInst + } + + if (from === to) { + // Nothing pertains to our managed components. + return null + } + + var fromNode = + from == null ? win : getNodeFromInstance$1(from) + var toNode = to == null ? win : getNodeFromInstance$1(to) + + var leave = SyntheticMouseEvent.getPooled( + eventTypes$2.mouseLeave, + from, + nativeEvent, + nativeEventTarget + ) + leave.type = 'mouseleave' + leave.target = fromNode + leave.relatedTarget = toNode + + var enter = SyntheticMouseEvent.getPooled( + eventTypes$2.mouseEnter, + to, + nativeEvent, + nativeEventTarget + ) + enter.type = 'mouseenter' + enter.target = toNode + enter.relatedTarget = fromNode + + accumulateEnterLeaveDispatches(leave, enter, from, to) + + return [leave, enter] + }, + } - node = getLeafNode(getSiblingNode(node)); - } -} + /** + * `ReactInstanceMap` maintains a mapping from a public facing stateful + * instance (key) and the internal representation (value). This allows public + * methods to accept the user facing instance as an argument and map them back + * to internal methods. + * + * Note that this module is currently shared and assumed to be stateless. + * If this becomes an actual Map, that will break. + */ + + /** + * This API should be called `delete` but we'd have to make sure to always + * transform these to strings for IE support. When this transform is fully + * supported we can rename it. + */ + + function get(key) { + return key._reactInternalFiber + } -/** - * @param {DOMElement} outerNode - * @return {?object} - */ -function getOffsets(outerNode) { - var selection = window.getSelection && window.getSelection(); + function has(key) { + return key._reactInternalFiber !== undefined + } - if (!selection || selection.rangeCount === 0) { - return null; - } + function set(key, value) { + key._reactInternalFiber = value + } - var anchorNode = selection.anchorNode, - anchorOffset = selection.anchorOffset, - focusNode = selection.focusNode, - focusOffset = selection.focusOffset; - - // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the - // up/down buttons on an . Anonymous divs do not seem to - // expose properties, triggering a "Permission denied error" if any of its - // properties are accessed. The only seemingly possible way to avoid erroring - // is to access a property that typically works for non-anonymous divs and - // catch any error that may otherwise arise. See - // https://bugzilla.mozilla.org/show_bug.cgi?id=208427 - - try { - /* eslint-disable no-unused-expressions */ - anchorNode.nodeType; - focusNode.nodeType; - /* eslint-enable no-unused-expressions */ - } catch (e) { - return null; - } + // Don't change these two values. They're used by React Dev Tools. + var NoEffect = /* */ 0 + var PerformedWork = /* */ 1 + + // You can change the rest (and add more). + var Placement = /* */ 2 + var Update = /* */ 4 + var PlacementAndUpdate = /* */ 6 + var Deletion = /* */ 8 + var ContentReset = /* */ 16 + var Callback = /* */ 32 + var DidCapture = /* */ 64 + var Ref = /* */ 128 + var ErrLog = /* */ 256 + var Snapshot = /* */ 2048 + + // Union of all host effects + var HostEffectMask = /* */ 2559 + + var Incomplete = /* */ 512 + var ShouldCapture = /* */ 1024 + + var MOUNTING = 1 + var MOUNTED = 2 + var UNMOUNTED = 3 + + function isFiberMountedImpl(fiber) { + var node = fiber + if (!fiber.alternate) { + // If there is no alternate, this might be a new tree that isn't inserted + // yet. If it is, then it will have a pending insertion effect on it. + if ((node.effectTag & Placement) !== NoEffect) { + return MOUNTING + } + while (node['return']) { + node = node['return'] + if ((node.effectTag & Placement) !== NoEffect) { + return MOUNTING + } + } + } else { + while (node['return']) { + node = node['return'] + } + } + if (node.tag === HostRoot) { + // TODO: Check if this was a nested HostRoot when used with + // renderContainerIntoSubtree. + return MOUNTED + } + // If we didn't hit the root, that means that we're in an disconnected tree + // that has been unmounted. + return UNMOUNTED + } - return getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset); -} - -/** - * Returns {start, end} where `start` is the character/codepoint index of - * (anchorNode, anchorOffset) within the textContent of `outerNode`, and - * `end` is the index of (focusNode, focusOffset). - * - * Returns null if you pass in garbage input but we should probably just crash. - * - * Exported only for testing. - */ -function getModernOffsetsFromPoints(outerNode, anchorNode, anchorOffset, focusNode, focusOffset) { - var length = 0; - var start = -1; - var end = -1; - var indexWithinAnchor = 0; - var indexWithinFocus = 0; - var node = outerNode; - var parentNode = null; - - outer: while (true) { - var next = null; - - while (true) { - if (node === anchorNode && (anchorOffset === 0 || node.nodeType === TEXT_NODE)) { - start = length + anchorOffset; - } - if (node === focusNode && (focusOffset === 0 || node.nodeType === TEXT_NODE)) { - end = length + focusOffset; - } + function isFiberMounted(fiber) { + return isFiberMountedImpl(fiber) === MOUNTED + } - if (node.nodeType === TEXT_NODE) { - length += node.nodeValue.length; - } + function isMounted(component) { + { + var owner = ReactCurrentOwner.current + if (owner !== null && owner.tag === ClassComponent) { + var ownerFiber = owner + var instance = ownerFiber.stateNode + !instance._warnedAboutRefsInRender + ? warning( + false, + '%s is accessing isMounted inside its render() function. ' + + 'render() should be a pure function of props and state. It should ' + + 'never access something that requires stale data from the previous ' + + 'render, such as refs. Move this logic to componentDidMount and ' + + 'componentDidUpdate instead.', + getComponentName(ownerFiber) || 'A component' + ) + : void 0 + instance._warnedAboutRefsInRender = true + } + } + + var fiber = get(component) + if (!fiber) { + return false + } + return isFiberMountedImpl(fiber) === MOUNTED + } - if ((next = node.firstChild) === null) { - break; - } - // Moving from `node` to its first child `next`. - parentNode = node; - node = next; - } + function assertIsMounted(fiber) { + !(isFiberMountedImpl(fiber) === MOUNTED) + ? invariant( + false, + 'Unable to find node on an unmounted component.' + ) + : void 0 + } - while (true) { - if (node === outerNode) { - // If `outerNode` has children, this is always the second time visiting - // it. If it has no children, this is still the first loop, and the only - // valid selection is anchorNode and focusNode both equal to this node - // and both offsets 0, in which case we will have handled above. - break outer; - } - if (parentNode === anchorNode && ++indexWithinAnchor === anchorOffset) { - start = length; - } - if (parentNode === focusNode && ++indexWithinFocus === focusOffset) { - end = length; - } - if ((next = node.nextSibling) !== null) { - break; - } - node = parentNode; - parentNode = node.parentNode; - } + function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate + if (!alternate) { + // If there is no alternate, then we only need to check if it is mounted. + var state = isFiberMountedImpl(fiber) + !(state !== UNMOUNTED) + ? invariant( + false, + 'Unable to find node on an unmounted component.' + ) + : void 0 + if (state === MOUNTING) { + return null + } + return fiber + } + // If we have two possible branches, we'll walk backwards up to the root + // to see what path the root points to. On the way we may hit one of the + // special cases and we'll deal with them. + var a = fiber + var b = alternate + while (true) { + var parentA = a['return'] + var parentB = parentA ? parentA.alternate : null + if (!parentA || !parentB) { + // We're at the root. + break + } + + // If both copies of the parent fiber point to the same child, we can + // assume that the child is current. This happens when we bailout on low + // priority: the bailed out fiber's child reuses the current child. + if (parentA.child === parentB.child) { + var child = parentA.child + while (child) { + if (child === a) { + // We've determined that A is the current branch. + assertIsMounted(parentA) + return fiber + } + if (child === b) { + // We've determined that B is the current branch. + assertIsMounted(parentA) + return alternate + } + child = child.sibling + } + // We should never have an alternate for any mounting node. So the only + // way this could possibly happen is if this was unmounted, if at all. + invariant( + false, + 'Unable to find node on an unmounted component.' + ) + } + + if (a['return'] !== b['return']) { + // The return pointer of A and the return pointer of B point to different + // fibers. We assume that return pointers never criss-cross, so A must + // belong to the child set of A.return, and B must belong to the child + // set of B.return. + a = parentA + b = parentB + } else { + // The return pointers point to the same fiber. We'll have to use the + // default, slow path: scan the child sets of each parent alternate to see + // which child belongs to which set. + // + // Search parent A's child set + var didFindChild = false + var _child = parentA.child + while (_child) { + if (_child === a) { + didFindChild = true + a = parentA + b = parentB + break + } + if (_child === b) { + didFindChild = true + b = parentA + a = parentB + break + } + _child = _child.sibling + } + if (!didFindChild) { + // Search parent B's child set + _child = parentB.child + while (_child) { + if (_child === a) { + didFindChild = true + a = parentB + b = parentA + break + } + if (_child === b) { + didFindChild = true + b = parentB + a = parentA + break + } + _child = _child.sibling + } + !didFindChild + ? invariant( + false, + 'Child was not found in either parent set. This indicates a bug in React related to the return pointer. Please file an issue.' + ) + : void 0 + } + } + + !(a.alternate === b) + ? invariant( + false, + "Return fibers should always be each others' alternates. This error is likely caused by a bug in React. Please file an issue." + ) + : void 0 + } + // If the root is not a host container, we're in a disconnected tree. I.e. + // unmounted. + !(a.tag === HostRoot) + ? invariant( + false, + 'Unable to find node on an unmounted component.' + ) + : void 0 + if (a.stateNode.current === a) { + // We've determined that A is the current branch. + return fiber + } + // Otherwise B has to be current branch. + return alternate + } - // Moving from `node` to its next sibling `next`. - node = next; - } + function findCurrentHostFiber(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent) + if (!currentParent) { + return null + } + + // Next we'll drill down this component to find the first HostComponent/Text. + var node = currentParent + while (true) { + if (node.tag === HostComponent || node.tag === HostText) { + return node + } else if (node.child) { + node.child['return'] = node + node = node.child + continue + } + if (node === currentParent) { + return null + } + while (!node.sibling) { + if (!node['return'] || node['return'] === currentParent) { + return null + } + node = node['return'] + } + node.sibling['return'] = node['return'] + node = node.sibling + } + // Flow needs the return null here, but ESLint complains about it. + // eslint-disable-next-line no-unreachable + return null + } - if (start === -1 || end === -1) { - // This should never happen. (Would happen if the anchor/focus nodes aren't - // actually inside the passed-in node.) - return null; - } + function findCurrentHostFiberWithNoPortals(parent) { + var currentParent = findCurrentFiberUsingSlowPath(parent) + if (!currentParent) { + return null + } + + // Next we'll drill down this component to find the first HostComponent/Text. + var node = currentParent + while (true) { + if (node.tag === HostComponent || node.tag === HostText) { + return node + } else if (node.child && node.tag !== HostPortal) { + node.child['return'] = node + node = node.child + continue + } + if (node === currentParent) { + return null + } + while (!node.sibling) { + if (!node['return'] || node['return'] === currentParent) { + return null + } + node = node['return'] + } + node.sibling['return'] = node['return'] + node = node.sibling + } + // Flow needs the return null here, but ESLint complains about it. + // eslint-disable-next-line no-unreachable + return null + } - return { - start: start, - end: end - }; -} - -/** - * In modern non-IE browsers, we can support both forward and backward - * selections. - * - * Note: IE10+ supports the Selection object, but it does not support - * the `extend` method, which means that even in modern IE, it's not possible - * to programmatically create a backward selection. Thus, for all IE - * versions, we use the old IE API to create our selections. - * - * @param {DOMElement|DOMTextNode} node - * @param {object} offsets - */ -function setOffsets(node, offsets) { - if (!window.getSelection) { - return; - } + function addEventBubbleListener(element, eventType, listener) { + element.addEventListener(eventType, listener, false) + } - var selection = window.getSelection(); - var length = node[getTextContentAccessor()].length; - var start = Math.min(offsets.start, length); - var end = offsets.end === undefined ? start : Math.min(offsets.end, length); - - // IE 11 uses modern selection, but doesn't support the extend method. - // Flip backward selections, so we can set with a single range. - if (!selection.extend && start > end) { - var temp = end; - end = start; - start = temp; - } + function addEventCaptureListener(element, eventType, listener) { + element.addEventListener(eventType, listener, true) + } - var startMarker = getNodeForCharacterOffset(node, start); - var endMarker = getNodeForCharacterOffset(node, end); + /** + * @interface Event + * @see http://www.w3.org/TR/css3-animations/#AnimationEvent-interface + * @see https://developer.mozilla.org/en-US/docs/Web/API/AnimationEvent + */ + var SyntheticAnimationEvent = SyntheticEvent$1.extend({ + animationName: null, + elapsedTime: null, + pseudoElement: null, + }) + + /** + * @interface Event + * @see http://www.w3.org/TR/clipboard-apis/ + */ + var SyntheticClipboardEvent = SyntheticEvent$1.extend({ + clipboardData: function (event) { + return 'clipboardData' in event + ? event.clipboardData + : window.clipboardData + }, + }) + + /** + * @interface FocusEvent + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ + var SyntheticFocusEvent = SyntheticUIEvent.extend({ + relatedTarget: null, + }) + + /** + * `charCode` represents the actual "character code" and is safe to use with + * `String.fromCharCode`. As such, only keys that correspond to printable + * characters produce a valid `charCode`, the only exception to this is Enter. + * The Tab-key is considered non-printable and does not have a `charCode`, + * presumably because it does not produce a tab-character in browsers. + * + * @param {object} nativeEvent Native browser event. + * @return {number} Normalized `charCode` property. + */ + function getEventCharCode(nativeEvent) { + var charCode = void 0 + var keyCode = nativeEvent.keyCode + + if ('charCode' in nativeEvent) { + charCode = nativeEvent.charCode + + // FF does not set `charCode` for the Enter-key, check against `keyCode`. + if (charCode === 0 && keyCode === 13) { + charCode = 13 + } + } else { + // IE8 does not implement `charCode`, but `keyCode` has the correct value. + charCode = keyCode + } + + // IE and Edge (on Windows) and Chrome / Safari (on Windows and Linux) + // report Enter as charCode 10 when ctrl is pressed. + if (charCode === 10) { + charCode = 13 + } + + // Some non-printable keys are reported in `charCode`/`keyCode`, discard them. + // Must not discard the (non-)printable Enter-key. + if (charCode >= 32 || charCode === 13) { + return charCode + } + + return 0 + } - if (startMarker && endMarker) { - if (selection.rangeCount === 1 && selection.anchorNode === startMarker.node && selection.anchorOffset === startMarker.offset && selection.focusNode === endMarker.node && selection.focusOffset === endMarker.offset) { - return; - } - var range = document.createRange(); - range.setStart(startMarker.node, startMarker.offset); - selection.removeAllRanges(); + /** + * Normalization of deprecated HTML5 `key` values + * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names + */ + var normalizeKey = { + Esc: 'Escape', + Spacebar: ' ', + Left: 'ArrowLeft', + Up: 'ArrowUp', + Right: 'ArrowRight', + Down: 'ArrowDown', + Del: 'Delete', + Win: 'OS', + Menu: 'ContextMenu', + Apps: 'ContextMenu', + Scroll: 'ScrollLock', + MozPrintableKey: 'Unidentified', + } - if (start > end) { - selection.addRange(range); - selection.extend(endMarker.node, endMarker.offset); - } else { - range.setEnd(endMarker.node, endMarker.offset); - selection.addRange(range); - } - } -} - -function isInDocument(node) { - return containsNode(document.documentElement, node); -} - -/** - * @ReactInputSelection: React input selection module. Based on Selection.js, - * but modified to be suitable for react and has a couple of bug fixes (doesn't - * assume buttons have range selections allowed). - * Input selection module for React. - */ - -function hasSelectionCapabilities(elem) { - var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); - return nodeName && (nodeName === 'input' && elem.type === 'text' || nodeName === 'textarea' || elem.contentEditable === 'true'); -} - -function getSelectionInformation() { - var focusedElem = getActiveElement(); - return { - focusedElem: focusedElem, - selectionRange: hasSelectionCapabilities(focusedElem) ? getSelection$1(focusedElem) : null - }; -} - -/** - * @restoreSelection: If any selection information was potentially lost, - * restore it. This is useful when performing operations that could remove dom - * nodes and place them back in, resulting in focus being lost. - */ -function restoreSelection(priorSelectionInformation) { - var curFocusedElem = getActiveElement(); - var priorFocusedElem = priorSelectionInformation.focusedElem; - var priorSelectionRange = priorSelectionInformation.selectionRange; - if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) { - if (hasSelectionCapabilities(priorFocusedElem)) { - setSelection(priorFocusedElem, priorSelectionRange); - } + /** + * Translation from legacy `keyCode` to HTML5 `key` + * Only special keys supported, all others depend on keyboard layout or browser + * @see https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent#Key_names + */ + var translateToKey = { + '8': 'Backspace', + '9': 'Tab', + '12': 'Clear', + '13': 'Enter', + '16': 'Shift', + '17': 'Control', + '18': 'Alt', + '19': 'Pause', + '20': 'CapsLock', + '27': 'Escape', + '32': ' ', + '33': 'PageUp', + '34': 'PageDown', + '35': 'End', + '36': 'Home', + '37': 'ArrowLeft', + '38': 'ArrowUp', + '39': 'ArrowRight', + '40': 'ArrowDown', + '45': 'Insert', + '46': 'Delete', + '112': 'F1', + '113': 'F2', + '114': 'F3', + '115': 'F4', + '116': 'F5', + '117': 'F6', + '118': 'F7', + '119': 'F8', + '120': 'F9', + '121': 'F10', + '122': 'F11', + '123': 'F12', + '144': 'NumLock', + '145': 'ScrollLock', + '224': 'Meta', + } - // Focusing a node can change the scroll position, which is undesirable - var ancestors = []; - var ancestor = priorFocusedElem; - while (ancestor = ancestor.parentNode) { - if (ancestor.nodeType === ELEMENT_NODE) { - ancestors.push({ - element: ancestor, - left: ancestor.scrollLeft, - top: ancestor.scrollTop - }); - } - } + /** + * @param {object} nativeEvent Native browser event. + * @return {string} Normalized `key` property. + */ + function getEventKey(nativeEvent) { + if (nativeEvent.key) { + // Normalize inconsistent values reported by browsers due to + // implementations of a working draft specification. + + // FireFox implements `key` but returns `MozPrintableKey` for all + // printable characters (normalized to `Unidentified`), ignore it. + var key = normalizeKey[nativeEvent.key] || nativeEvent.key + if (key !== 'Unidentified') { + return key + } + } + + // Browser does not implement `key`, polyfill as much of it as we can. + if (nativeEvent.type === 'keypress') { + var charCode = getEventCharCode(nativeEvent) + + // The enter-key is technically both printable and non-printable and can + // thus be captured by `keypress`, no other non-printable key should. + return charCode === 13 + ? 'Enter' + : String.fromCharCode(charCode) + } + if ( + nativeEvent.type === 'keydown' || + nativeEvent.type === 'keyup' + ) { + // While user keyboard layout determines the actual meaning of each + // `keyCode` value, almost all function keys have a universal value. + return translateToKey[nativeEvent.keyCode] || 'Unidentified' + } + return '' + } - priorFocusedElem.focus(); + /** + * @interface KeyboardEvent + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ + var SyntheticKeyboardEvent = SyntheticUIEvent.extend({ + key: getEventKey, + location: null, + ctrlKey: null, + shiftKey: null, + altKey: null, + metaKey: null, + repeat: null, + locale: null, + getModifierState: getEventModifierState, + // Legacy Interface + charCode: function (event) { + // `charCode` is the result of a KeyPress event and represents the value of + // the actual printable character. + + // KeyPress is deprecated, but its replacement is not yet final and not + // implemented in any major browser. Only KeyPress has charCode. + if (event.type === 'keypress') { + return getEventCharCode(event) + } + return 0 + }, + keyCode: function (event) { + // `keyCode` is the result of a KeyDown/Up event and represents the value of + // physical keyboard key. + + // The actual meaning of the value depends on the users' keyboard layout + // which cannot be detected. Assuming that it is a US keyboard layout + // provides a surprisingly accurate mapping for US and European users. + // Due to this, it is left to the user to implement at this time. + if (event.type === 'keydown' || event.type === 'keyup') { + return event.keyCode + } + return 0 + }, + which: function (event) { + // `which` is an alias for either `keyCode` or `charCode` depending on the + // type of the event. + if (event.type === 'keypress') { + return getEventCharCode(event) + } + if (event.type === 'keydown' || event.type === 'keyup') { + return event.keyCode + } + return 0 + }, + }) + + /** + * @interface DragEvent + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ + var SyntheticDragEvent = SyntheticMouseEvent.extend({ + dataTransfer: null, + }) + + /** + * @interface TouchEvent + * @see http://www.w3.org/TR/touch-events/ + */ + var SyntheticTouchEvent = SyntheticUIEvent.extend({ + touches: null, + targetTouches: null, + changedTouches: null, + altKey: null, + metaKey: null, + ctrlKey: null, + shiftKey: null, + getModifierState: getEventModifierState, + }) + + /** + * @interface Event + * @see http://www.w3.org/TR/2009/WD-css3-transitions-20090320/#transition-events- + * @see https://developer.mozilla.org/en-US/docs/Web/API/TransitionEvent + */ + var SyntheticTransitionEvent = SyntheticEvent$1.extend({ + propertyName: null, + elapsedTime: null, + pseudoElement: null, + }) + + /** + * @interface WheelEvent + * @see http://www.w3.org/TR/DOM-Level-3-Events/ + */ + var SyntheticWheelEvent = SyntheticMouseEvent.extend({ + deltaX: function (event) { + return 'deltaX' in event + ? event.deltaX // Fallback to `wheelDeltaX` for Webkit and normalize (right is positive). + : 'wheelDeltaX' in event + ? -event.wheelDeltaX + : 0 + }, + deltaY: function (event) { + return 'deltaY' in event + ? event.deltaY // Fallback to `wheelDeltaY` for Webkit and normalize (down is positive). + : 'wheelDeltaY' in event + ? -event.wheelDeltaY // Fallback to `wheelDelta` for IE<9 and normalize (down is positive). + : 'wheelDelta' in event + ? -event.wheelDelta + : 0 + }, + + deltaZ: null, + + // Browsers without "deltaMode" is reporting in raw wheel delta where one + // notch on the scroll is always +/- 120, roughly equivalent to pixels. + // A good approximation of DOM_DELTA_LINE (1) is 5% of viewport size or + // ~40 pixels, for DOM_DELTA_SCREEN (2) it is 87.5% of viewport size. + deltaMode: null, + }) + + /** + * Turns + * ['abort', ...] + * into + * eventTypes = { + * 'abort': { + * phasedRegistrationNames: { + * bubbled: 'onAbort', + * captured: 'onAbortCapture', + * }, + * dependencies: ['topAbort'], + * }, + * ... + * }; + * topLevelEventsToDispatchConfig = { + * 'topAbort': { sameConfig } + * }; + */ + var interactiveEventTypeNames = [ + 'blur', + 'cancel', + 'click', + 'close', + 'contextMenu', + 'copy', + 'cut', + 'doubleClick', + 'dragEnd', + 'dragStart', + 'drop', + 'focus', + 'input', + 'invalid', + 'keyDown', + 'keyPress', + 'keyUp', + 'mouseDown', + 'mouseUp', + 'paste', + 'pause', + 'play', + 'rateChange', + 'reset', + 'seeked', + 'submit', + 'touchCancel', + 'touchEnd', + 'touchStart', + 'volumeChange', + ] + var nonInteractiveEventTypeNames = [ + 'abort', + 'animationEnd', + 'animationIteration', + 'animationStart', + 'canPlay', + 'canPlayThrough', + 'drag', + 'dragEnter', + 'dragExit', + 'dragLeave', + 'dragOver', + 'durationChange', + 'emptied', + 'encrypted', + 'ended', + 'error', + 'load', + 'loadedData', + 'loadedMetadata', + 'loadStart', + 'mouseMove', + 'mouseOut', + 'mouseOver', + 'playing', + 'progress', + 'scroll', + 'seeking', + 'stalled', + 'suspend', + 'timeUpdate', + 'toggle', + 'touchMove', + 'transitionEnd', + 'waiting', + 'wheel', + ] + + var eventTypes$4 = {} + var topLevelEventsToDispatchConfig = {} + + function addEventTypeNameToConfig(event, isInteractive) { + var capitalizedEvent = event[0].toUpperCase() + event.slice(1) + var onEvent = 'on' + capitalizedEvent + var topEvent = 'top' + capitalizedEvent + + var type = { + phasedRegistrationNames: { + bubbled: onEvent, + captured: onEvent + 'Capture', + }, + dependencies: [topEvent], + isInteractive: isInteractive, + } + eventTypes$4[event] = type + topLevelEventsToDispatchConfig[topEvent] = type + } - for (var i = 0; i < ancestors.length; i++) { - var info = ancestors[i]; - info.element.scrollLeft = info.left; - info.element.scrollTop = info.top; - } - } -} - -/** - * @getSelection: Gets the selection bounds of a focused textarea, input or - * contentEditable node. - * -@input: Look up selection bounds of this input - * -@return {start: selectionStart, end: selectionEnd} - */ -function getSelection$1(input) { - var selection = void 0; - - if ('selectionStart' in input) { - // Modern browser with input or textarea. - selection = { - start: input.selectionStart, - end: input.selectionEnd - }; - } else { - // Content editable or old IE textarea. - selection = getOffsets(input); - } + interactiveEventTypeNames.forEach(function (eventTypeName) { + addEventTypeNameToConfig(eventTypeName, true) + }) + nonInteractiveEventTypeNames.forEach(function (eventTypeName) { + addEventTypeNameToConfig(eventTypeName, false) + }) + + // Only used in DEV for exhaustiveness validation. + var knownHTMLTopLevelTypes = [ + 'topAbort', + 'topCancel', + 'topCanPlay', + 'topCanPlayThrough', + 'topClose', + 'topDurationChange', + 'topEmptied', + 'topEncrypted', + 'topEnded', + 'topError', + 'topInput', + 'topInvalid', + 'topLoad', + 'topLoadedData', + 'topLoadedMetadata', + 'topLoadStart', + 'topPause', + 'topPlay', + 'topPlaying', + 'topProgress', + 'topRateChange', + 'topReset', + 'topSeeked', + 'topSeeking', + 'topStalled', + 'topSubmit', + 'topSuspend', + 'topTimeUpdate', + 'topToggle', + 'topVolumeChange', + 'topWaiting', + ] + + var SimpleEventPlugin = { + eventTypes: eventTypes$4, + + isInteractiveTopLevelEventType: function (topLevelType) { + var config = topLevelEventsToDispatchConfig[topLevelType] + return config !== undefined && config.isInteractive === true + }, + + extractEvents: function ( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + var dispatchConfig = + topLevelEventsToDispatchConfig[topLevelType] + if (!dispatchConfig) { + return null + } + var EventConstructor = void 0 + switch (topLevelType) { + case 'topKeyPress': + // Firefox creates a keypress event for function keys too. This removes + // the unwanted keypress events. Enter is however both printable and + // non-printable. One would expect Tab to be as well (but it isn't). + if (getEventCharCode(nativeEvent) === 0) { + return null + } + /* falls through */ + case 'topKeyDown': + case 'topKeyUp': + EventConstructor = SyntheticKeyboardEvent + break + case 'topBlur': + case 'topFocus': + EventConstructor = SyntheticFocusEvent + break + case 'topClick': + // Firefox creates a click event on right mouse clicks. This removes the + // unwanted click events. + if (nativeEvent.button === 2) { + return null + } + /* falls through */ + case 'topDoubleClick': + case 'topMouseDown': + case 'topMouseMove': + case 'topMouseUp': + // TODO: Disabled elements should not respond to mouse events + /* falls through */ + case 'topMouseOut': + case 'topMouseOver': + case 'topContextMenu': + EventConstructor = SyntheticMouseEvent + break + case 'topDrag': + case 'topDragEnd': + case 'topDragEnter': + case 'topDragExit': + case 'topDragLeave': + case 'topDragOver': + case 'topDragStart': + case 'topDrop': + EventConstructor = SyntheticDragEvent + break + case 'topTouchCancel': + case 'topTouchEnd': + case 'topTouchMove': + case 'topTouchStart': + EventConstructor = SyntheticTouchEvent + break + case 'topAnimationEnd': + case 'topAnimationIteration': + case 'topAnimationStart': + EventConstructor = SyntheticAnimationEvent + break + case 'topTransitionEnd': + EventConstructor = SyntheticTransitionEvent + break + case 'topScroll': + EventConstructor = SyntheticUIEvent + break + case 'topWheel': + EventConstructor = SyntheticWheelEvent + break + case 'topCopy': + case 'topCut': + case 'topPaste': + EventConstructor = SyntheticClipboardEvent + break + default: + { + if ( + knownHTMLTopLevelTypes.indexOf(topLevelType) === -1 + ) { + warning( + false, + 'SimpleEventPlugin: Unhandled event type, `%s`. This warning ' + + 'is likely caused by a bug in React. Please file an issue.', + topLevelType + ) + } + } + // HTML Events + // @see http://www.w3.org/TR/html5/index.html#events-0 + EventConstructor = SyntheticEvent$1 + break + } + var event = EventConstructor.getPooled( + dispatchConfig, + targetInst, + nativeEvent, + nativeEventTarget + ) + accumulateTwoPhaseDispatches(event) + return event + }, + } - return selection || { start: 0, end: 0 }; -} - -/** - * @setSelection: Sets the selection bounds of a textarea or input and focuses - * the input. - * -@input Set selection bounds of this input or textarea - * -@offsets Object of same form that is returned from get* - */ -function setSelection(input, offsets) { - var start = offsets.start, - end = offsets.end; - - if (end === undefined) { - end = start; - } + var isInteractiveTopLevelEventType = + SimpleEventPlugin.isInteractiveTopLevelEventType + + var CALLBACK_BOOKKEEPING_POOL_SIZE = 10 + var callbackBookkeepingPool = [] + + /** + * Find the deepest React component completely containing the root of the + * passed-in instance (for use when entire React trees are nested within each + * other). If React trees are not nested, returns null. + */ + function findRootContainerNode(inst) { + // TODO: It may be a good idea to cache this to prevent unnecessary DOM + // traversal, but caching is difficult to do correctly without using a + // mutation observer to listen for all DOM changes. + while (inst['return']) { + inst = inst['return'] + } + if (inst.tag !== HostRoot) { + // This can happen if we're in a detached tree. + return null + } + return inst.stateNode.containerInfo + } - if ('selectionStart' in input) { - input.selectionStart = start; - input.selectionEnd = Math.min(end, input.value.length); - } else { - setOffsets(input, offsets); - } -} + // Used to store ancestor hierarchy in top level callback + function getTopLevelCallbackBookKeeping( + topLevelType, + nativeEvent, + targetInst + ) { + if (callbackBookkeepingPool.length) { + var instance = callbackBookkeepingPool.pop() + instance.topLevelType = topLevelType + instance.nativeEvent = nativeEvent + instance.targetInst = targetInst + return instance + } + return { + topLevelType: topLevelType, + nativeEvent: nativeEvent, + targetInst: targetInst, + ancestors: [], + } + } -var skipSelectionChangeEvent = ExecutionEnvironment.canUseDOM && 'documentMode' in document && document.documentMode <= 11; + function releaseTopLevelCallbackBookKeeping(instance) { + instance.topLevelType = null + instance.nativeEvent = null + instance.targetInst = null + instance.ancestors.length = 0 + if ( + callbackBookkeepingPool.length < + CALLBACK_BOOKKEEPING_POOL_SIZE + ) { + callbackBookkeepingPool.push(instance) + } + } -var eventTypes$3 = { - select: { - phasedRegistrationNames: { - bubbled: 'onSelect', - captured: 'onSelectCapture' - }, - dependencies: ['topBlur', 'topContextMenu', 'topFocus', 'topKeyDown', 'topKeyUp', 'topMouseDown', 'topMouseUp', 'topSelectionChange'] - } -}; - -var activeElement$1 = null; -var activeElementInst$1 = null; -var lastSelection = null; -var mouseDown = false; - -/** - * Get an object which is a unique representation of the current selection. - * - * The return value will not be consistent across nodes or browsers, but - * two identical selections on the same node will return identical objects. - * - * @param {DOMElement} node - * @return {object} - */ -function getSelection(node) { - if ('selectionStart' in node && hasSelectionCapabilities(node)) { - return { - start: node.selectionStart, - end: node.selectionEnd - }; - } else if (window.getSelection) { - var selection = window.getSelection(); - return { - anchorNode: selection.anchorNode, - anchorOffset: selection.anchorOffset, - focusNode: selection.focusNode, - focusOffset: selection.focusOffset - }; - } -} - -/** - * Poll selection to see whether it's changed. - * - * @param {object} nativeEvent - * @return {?SyntheticEvent} - */ -function constructSelectEvent(nativeEvent, nativeEventTarget) { - // Ensure we have the right element, and that the user is not dragging a - // selection (this matches native `select` event behavior). In HTML5, select - // fires only on input and textarea thus if there's no focused element we - // won't dispatch. - if (mouseDown || activeElement$1 == null || activeElement$1 !== getActiveElement()) { - return null; - } + function handleTopLevel(bookKeeping) { + var targetInst = bookKeeping.targetInst + + // Loop through the hierarchy, in case there's any nested components. + // It's important that we build the array of ancestors before calling any + // event handlers, because event handlers can modify the DOM, leading to + // inconsistencies with ReactMount's node cache. See #1105. + var ancestor = targetInst + do { + if (!ancestor) { + bookKeeping.ancestors.push(ancestor) + break + } + var root = findRootContainerNode(ancestor) + if (!root) { + break + } + bookKeeping.ancestors.push(ancestor) + ancestor = getClosestInstanceFromNode(root) + } while (ancestor) + + for (var i = 0; i < bookKeeping.ancestors.length; i++) { + targetInst = bookKeeping.ancestors[i] + runExtractedEventsInBatch( + bookKeeping.topLevelType, + targetInst, + bookKeeping.nativeEvent, + getEventTarget(bookKeeping.nativeEvent) + ) + } + } - // Only fire when selection has actually changed. - var currentSelection = getSelection(activeElement$1); - if (!lastSelection || !shallowEqual(lastSelection, currentSelection)) { - lastSelection = currentSelection; + // TODO: can we stop exporting these? + var _enabled = true - var syntheticEvent = SyntheticEvent$1.getPooled(eventTypes$3.select, activeElementInst$1, nativeEvent, nativeEventTarget); + function setEnabled(enabled) { + _enabled = !!enabled + } - syntheticEvent.type = 'select'; - syntheticEvent.target = activeElement$1; + function isEnabled() { + return _enabled + } - accumulateTwoPhaseDispatches(syntheticEvent); + /** + * Traps top-level events by using event bubbling. + * + * @param {string} topLevelType Record from `BrowserEventConstants`. + * @param {string} handlerBaseName Event name (e.g. "click"). + * @param {object} element Element on which to attach listener. + * @return {?object} An object with a remove function which will forcefully + * remove the listener. + * @internal + */ + function trapBubbledEvent( + topLevelType, + handlerBaseName, + element + ) { + if (!element) { + return null + } + var dispatch = isInteractiveTopLevelEventType(topLevelType) + ? dispatchInteractiveEvent + : dispatchEvent + + addEventBubbleListener( + element, + handlerBaseName, + // Check if interactive and wrap in interactiveUpdates + dispatch.bind(null, topLevelType) + ) + } - return syntheticEvent; - } + /** + * Traps a top-level event by using event capturing. + * + * @param {string} topLevelType Record from `BrowserEventConstants`. + * @param {string} handlerBaseName Event name (e.g. "click"). + * @param {object} element Element on which to attach listener. + * @return {?object} An object with a remove function which will forcefully + * remove the listener. + * @internal + */ + function trapCapturedEvent( + topLevelType, + handlerBaseName, + element + ) { + if (!element) { + return null + } + var dispatch = isInteractiveTopLevelEventType(topLevelType) + ? dispatchInteractiveEvent + : dispatchEvent + + addEventCaptureListener( + element, + handlerBaseName, + // Check if interactive and wrap in interactiveUpdates + dispatch.bind(null, topLevelType) + ) + } - return null; -} - -/** - * This plugin creates an `onSelect` event that normalizes select events - * across form elements. - * - * Supported elements are: - * - input (see `isTextInputElement`) - * - textarea - * - contentEditable - * - * This differs from native browser implementations in the following ways: - * - Fires on contentEditable fields as well as inputs. - * - Fires for collapsed selection. - * - Fires after user input. - */ -var SelectEventPlugin = { - eventTypes: eventTypes$3, - - extractEvents: function (topLevelType, targetInst, nativeEvent, nativeEventTarget) { - var doc = nativeEventTarget.window === nativeEventTarget ? nativeEventTarget.document : nativeEventTarget.nodeType === DOCUMENT_NODE ? nativeEventTarget : nativeEventTarget.ownerDocument; - // Track whether all listeners exists for this plugin. If none exist, we do - // not extract events. See #3639. - if (!doc || !isListeningToAllDependencies('onSelect', doc)) { - return null; - } + function dispatchInteractiveEvent(topLevelType, nativeEvent) { + interactiveUpdates(dispatchEvent, topLevelType, nativeEvent) + } - var targetNode = targetInst ? getNodeFromInstance$1(targetInst) : window; + function dispatchEvent(topLevelType, nativeEvent) { + if (!_enabled) { + return + } + + var nativeEventTarget = getEventTarget(nativeEvent) + var targetInst = getClosestInstanceFromNode(nativeEventTarget) + if ( + targetInst !== null && + typeof targetInst.tag === 'number' && + !isFiberMounted(targetInst) + ) { + // If we get an event (ex: img onload) before committing that + // component's mount, ignore it for now (that is, treat it as if it was an + // event on a non-React tree). We might also consider queueing events and + // dispatching them after the mount. + targetInst = null + } + + var bookKeeping = getTopLevelCallbackBookKeeping( + topLevelType, + nativeEvent, + targetInst + ) + + try { + // Event queue being processed in the same cycle allows + // `preventDefault`. + batchedUpdates(handleTopLevel, bookKeeping) + } finally { + releaseTopLevelCallbackBookKeeping(bookKeeping) + } + } - switch (topLevelType) { - // Track the input node that has focus. - case 'topFocus': - if (isTextInputElement(targetNode) || targetNode.contentEditable === 'true') { - activeElement$1 = targetNode; - activeElementInst$1 = targetInst; - lastSelection = null; - } - break; - case 'topBlur': - activeElement$1 = null; - activeElementInst$1 = null; - lastSelection = null; - break; - // Don't fire the event while the user is dragging. This matches the - // semantics of the native select event. - case 'topMouseDown': - mouseDown = true; - break; - case 'topContextMenu': - case 'topMouseUp': - mouseDown = false; - return constructSelectEvent(nativeEvent, nativeEventTarget); - // Chrome and IE fire non-standard event when selection is changed (and - // sometimes when it hasn't). IE's event fires out of order with respect - // to key and input events on deletion, so we discard it. - // - // Firefox doesn't support selectionchange, so check selection status - // after each key entry. The selection changes after keydown and before - // keyup, but we check on keydown as well in the case of holding down a - // key, when multiple keydown events are fired but only one keyup is. - // This is also our approach for IE handling, for the reason above. - case 'topSelectionChange': - if (skipSelectionChangeEvent) { - break; - } - // falls through - case 'topKeyDown': - case 'topKeyUp': - return constructSelectEvent(nativeEvent, nativeEventTarget); - } + var ReactDOMEventListener = Object.freeze({ + get _enabled() { + return _enabled + }, + setEnabled: setEnabled, + isEnabled: isEnabled, + trapBubbledEvent: trapBubbledEvent, + trapCapturedEvent: trapCapturedEvent, + dispatchEvent: dispatchEvent, + }) + + /** + * Generate a mapping of standard vendor prefixes using the defined style property and event name. + * + * @param {string} styleProp + * @param {string} eventName + * @returns {object} + */ + function makePrefixMap(styleProp, eventName) { + var prefixes = {} + + prefixes[styleProp.toLowerCase()] = eventName.toLowerCase() + prefixes['Webkit' + styleProp] = 'webkit' + eventName + prefixes['Moz' + styleProp] = 'moz' + eventName + prefixes['ms' + styleProp] = 'MS' + eventName + prefixes['O' + styleProp] = 'o' + eventName.toLowerCase() + + return prefixes + } - return null; - } -}; - -/** - * Inject modules for resolving DOM hierarchy and plugin ordering. - */ -injection.injectEventPluginOrder(DOMEventPluginOrder); -injection$1.injectComponentTree(ReactDOMComponentTree); - -/** - * Some important event plugins included by default (without having to require - * them). - */ -injection.injectEventPluginsByName({ - SimpleEventPlugin: SimpleEventPlugin, - EnterLeaveEventPlugin: EnterLeaveEventPlugin, - ChangeEventPlugin: ChangeEventPlugin, - SelectEventPlugin: SelectEventPlugin, - BeforeInputEventPlugin: BeforeInputEventPlugin -}); - -// Max 31 bit integer. The max integer size in V8 for 32-bit systems. -// Math.pow(2, 30) - 1 -// 0b111111111111111111111111111111 -var MAX_SIGNED_31_BIT_INT = 1073741823; - -// TODO: Use an opaque type once ESLint et al support the syntax - - -var NoWork = 0; -var Sync = 1; -var Never = MAX_SIGNED_31_BIT_INT; - -var UNIT_SIZE = 10; -var MAGIC_NUMBER_OFFSET = 2; - -// 1 unit of expiration time represents 10ms. -function msToExpirationTime(ms) { - // Always add an offset so that we don't clash with the magic number for NoWork. - return (ms / UNIT_SIZE | 0) + MAGIC_NUMBER_OFFSET; -} - -function expirationTimeToMs(expirationTime) { - return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE; -} - -function ceiling(num, precision) { - return ((num / precision | 0) + 1) * precision; -} - -function computeExpirationBucket(currentTime, expirationInMs, bucketSizeMs) { - return ceiling(currentTime + expirationInMs / UNIT_SIZE, bucketSizeMs / UNIT_SIZE); -} - -var NoContext = 0; -var AsyncMode = 1; -var StrictMode = 2; - -var hasBadMapPolyfill = void 0; - -{ - hasBadMapPolyfill = false; - try { - var nonExtensibleObject = Object.preventExtensions({}); - var testMap = new Map([[nonExtensibleObject, null]]); - var testSet = new Set([nonExtensibleObject]); - // This is necessary for Rollup to not consider these unused. - // https://github.com/rollup/rollup/issues/1771 - // TODO: we can remove these if Rollup fixes the bug. - testMap.set(0, 0); - testSet.add(0); - } catch (e) { - // TODO: Consider warning about bad polyfills - hasBadMapPolyfill = true; - } -} + /** + * A list of event names to a configurable list of vendor prefixes. + */ + var vendorPrefixes = { + animationend: makePrefixMap('Animation', 'AnimationEnd'), + animationiteration: makePrefixMap( + 'Animation', + 'AnimationIteration' + ), + animationstart: makePrefixMap('Animation', 'AnimationStart'), + transitionend: makePrefixMap('Transition', 'TransitionEnd'), + } -// A Fiber is work on a Component that needs to be done or was done. There can -// be more than one per component. + /** + * Event names that have already been detected and prefixed (if applicable). + */ + var prefixedEventNames = {} + + /** + * Element to check for prefixes on. + */ + var style = {} + + /** + * Bootstrap if a DOM exists. + */ + if (ExecutionEnvironment.canUseDOM) { + style = document.createElement('div').style + + // On some platforms, in particular some releases of Android 4.x, + // the un-prefixed "animation" and "transition" properties are defined on the + // style object but the events that fire will still be prefixed, so we need + // to check if the un-prefixed events are usable, and if not remove them from the map. + if (!('AnimationEvent' in window)) { + delete vendorPrefixes.animationend.animation + delete vendorPrefixes.animationiteration.animation + delete vendorPrefixes.animationstart.animation + } + + // Same as above + if (!('TransitionEvent' in window)) { + delete vendorPrefixes.transitionend.transition + } + } + /** + * Attempts to determine the correct vendor prefixed event name. + * + * @param {string} eventName + * @returns {string} + */ + function getVendorPrefixedEventName(eventName) { + if (prefixedEventNames[eventName]) { + return prefixedEventNames[eventName] + } else if (!vendorPrefixes[eventName]) { + return eventName + } + + var prefixMap = vendorPrefixes[eventName] + + for (var styleProp in prefixMap) { + if ( + prefixMap.hasOwnProperty(styleProp) && + styleProp in style + ) { + return (prefixedEventNames[eventName] = + prefixMap[styleProp]) + } + } + + return eventName + } -var debugCounter = void 0; + /** + * Types of raw signals from the browser caught at the top level. + * + * For events like 'submit' or audio/video events which don't consistently + * bubble (which we trap at a lower node than `document`), binding + * at `document` would cause duplicate events so we don't include them here. + */ + var topLevelTypes = { + topAnimationEnd: getVendorPrefixedEventName('animationend'), + topAnimationIteration: getVendorPrefixedEventName( + 'animationiteration' + ), + topAnimationStart: getVendorPrefixedEventName( + 'animationstart' + ), + topBlur: 'blur', + topCancel: 'cancel', + topChange: 'change', + topClick: 'click', + topClose: 'close', + topCompositionEnd: 'compositionend', + topCompositionStart: 'compositionstart', + topCompositionUpdate: 'compositionupdate', + topContextMenu: 'contextmenu', + topCopy: 'copy', + topCut: 'cut', + topDoubleClick: 'dblclick', + topDrag: 'drag', + topDragEnd: 'dragend', + topDragEnter: 'dragenter', + topDragExit: 'dragexit', + topDragLeave: 'dragleave', + topDragOver: 'dragover', + topDragStart: 'dragstart', + topDrop: 'drop', + topFocus: 'focus', + topInput: 'input', + topKeyDown: 'keydown', + topKeyPress: 'keypress', + topKeyUp: 'keyup', + topLoad: 'load', + topLoadStart: 'loadstart', + topMouseDown: 'mousedown', + topMouseMove: 'mousemove', + topMouseOut: 'mouseout', + topMouseOver: 'mouseover', + topMouseUp: 'mouseup', + topPaste: 'paste', + topScroll: 'scroll', + topSelectionChange: 'selectionchange', + topTextInput: 'textInput', + topToggle: 'toggle', + topTouchCancel: 'touchcancel', + topTouchEnd: 'touchend', + topTouchMove: 'touchmove', + topTouchStart: 'touchstart', + topTransitionEnd: getVendorPrefixedEventName('transitionend'), + topWheel: 'wheel', + } -{ - debugCounter = 1; -} + // There are so many media events, it makes sense to just + // maintain a list of them. Note these aren't technically + // "top-level" since they don't bubble. We should come up + // with a better naming convention if we come to refactoring + // the event system. + var mediaEventTypes = { + topAbort: 'abort', + topCanPlay: 'canplay', + topCanPlayThrough: 'canplaythrough', + topDurationChange: 'durationchange', + topEmptied: 'emptied', + topEncrypted: 'encrypted', + topEnded: 'ended', + topError: 'error', + topLoadedData: 'loadeddata', + topLoadedMetadata: 'loadedmetadata', + topLoadStart: 'loadstart', + topPause: 'pause', + topPlay: 'play', + topPlaying: 'playing', + topProgress: 'progress', + topRateChange: 'ratechange', + topSeeked: 'seeked', + topSeeking: 'seeking', + topStalled: 'stalled', + topSuspend: 'suspend', + topTimeUpdate: 'timeupdate', + topVolumeChange: 'volumechange', + topWaiting: 'waiting', + } -function FiberNode(tag, pendingProps, key, mode) { - // Instance - this.tag = tag; - this.key = key; - this.type = null; - this.stateNode = null; + /** + * Summary of `ReactBrowserEventEmitter` event handling: + * + * - Top-level delegation is used to trap most native browser events. This + * may only occur in the main thread and is the responsibility of + * ReactDOMEventListener, which is injected and can therefore support + * pluggable event sources. This is the only work that occurs in the main + * thread. + * + * - We normalize and de-duplicate events to account for browser quirks. This + * may be done in the worker thread. + * + * - Forward these native events (with the associated top-level type used to + * trap it) to `EventPluginHub`, which in turn will ask plugins if they want + * to extract any synthetic events. + * + * - The `EventPluginHub` will then process each event by annotating them with + * "dispatches", a sequence of listeners and IDs that care about that event. + * + * - The `EventPluginHub` then dispatches the events. + * + * Overview of React and the event system: + * + * +------------+ . + * | DOM | . + * +------------+ . + * | . + * v . + * +------------+ . + * | ReactEvent | . + * | Listener | . + * +------------+ . +-----------+ + * | . +--------+|SimpleEvent| + * | . | |Plugin | + * +-----|------+ . v +-----------+ + * | | | . +--------------+ +------------+ + * | +-----------.--->|EventPluginHub| | Event | + * | | . | | +-----------+ | Propagators| + * | ReactEvent | . | | |TapEvent | |------------| + * | Emitter | . | |<---+|Plugin | |other plugin| + * | | . | | +-----------+ | utilities | + * | +-----------.--->| | +------------+ + * | | | . +--------------+ + * +-----|------+ . ^ +-----------+ + * | . | |Enter/Leave| + * + . +-------+|Plugin | + * +-------------+ . +-----------+ + * | application | . + * |-------------| . + * | | . + * | | . + * +-------------+ . + * . + * React Core . General Purpose Event Plugin System + */ + + var alreadyListeningTo = {} + var reactTopListenersCounter = 0 + + /** + * To ensure no conflicts with other potential React instances on the page + */ + var topListenersIDKey = + '_reactListenersID' + ('' + Math.random()).slice(2) + + function getListeningForDocument(mountAt) { + // In IE8, `mountAt` is a host object and doesn't have `hasOwnProperty` + // directly. + if ( + !Object.prototype.hasOwnProperty.call( + mountAt, + topListenersIDKey + ) + ) { + mountAt[topListenersIDKey] = reactTopListenersCounter++ + alreadyListeningTo[mountAt[topListenersIDKey]] = {} + } + return alreadyListeningTo[mountAt[topListenersIDKey]] + } - // Fiber - this['return'] = null; - this.child = null; - this.sibling = null; - this.index = 0; + /** + * We listen for bubbled touch events on the document object. + * + * Firefox v8.01 (and possibly others) exhibited strange behavior when + * mounting `onmousemove` events at some node that was not the document + * element. The symptoms were that if your mouse is not moving over something + * contained within that mount point (for example on the background) the + * top-level listeners for `onmousemove` won't be called. However, if you + * register the `mousemove` on the document object, then it will of course + * catch all `mousemove`s. This along with iOS quirks, justifies restricting + * top-level listeners to the document object only, at least for these + * movement types of events and possibly all events. + * + * @see http://www.quirksmode.org/blog/archives/2010/09/click_event_del.html + * + * Also, `keyup`/`keypress`/`keydown` do not bubble to the window on IE, but + * they bubble to document. + * + * @param {string} registrationName Name of listener (e.g. `onClick`). + * @param {object} contentDocumentHandle Document which owns the container + */ + function listenTo(registrationName, contentDocumentHandle) { + var mountAt = contentDocumentHandle + var isListening = getListeningForDocument(mountAt) + var dependencies = + registrationNameDependencies[registrationName] + + for (var i = 0; i < dependencies.length; i++) { + var dependency = dependencies[i] + if ( + !( + isListening.hasOwnProperty(dependency) && + isListening[dependency] + ) + ) { + if (dependency === 'topScroll') { + trapCapturedEvent('topScroll', 'scroll', mountAt) + } else if ( + dependency === 'topFocus' || + dependency === 'topBlur' + ) { + trapCapturedEvent('topFocus', 'focus', mountAt) + trapCapturedEvent('topBlur', 'blur', mountAt) + + // to make sure blur and focus event listeners are only attached once + isListening.topBlur = true + isListening.topFocus = true + } else if (dependency === 'topCancel') { + if (isEventSupported('cancel', true)) { + trapCapturedEvent('topCancel', 'cancel', mountAt) + } + isListening.topCancel = true + } else if (dependency === 'topClose') { + if (isEventSupported('close', true)) { + trapCapturedEvent('topClose', 'close', mountAt) + } + isListening.topClose = true + } else if (topLevelTypes.hasOwnProperty(dependency)) { + trapBubbledEvent( + dependency, + topLevelTypes[dependency], + mountAt + ) + } + + isListening[dependency] = true + } + } + } - this.ref = null; + function isListeningToAllDependencies( + registrationName, + mountAt + ) { + var isListening = getListeningForDocument(mountAt) + var dependencies = + registrationNameDependencies[registrationName] + for (var i = 0; i < dependencies.length; i++) { + var dependency = dependencies[i] + if ( + !( + isListening.hasOwnProperty(dependency) && + isListening[dependency] + ) + ) { + return false + } + } + return true + } - this.pendingProps = pendingProps; - this.memoizedProps = null; - this.updateQueue = null; - this.memoizedState = null; + /** + * Given any node return the first leaf node without children. + * + * @param {DOMElement|DOMTextNode} node + * @return {DOMElement|DOMTextNode} + */ + function getLeafNode(node) { + while (node && node.firstChild) { + node = node.firstChild + } + return node + } - this.mode = mode; + /** + * Get the next sibling within a container. This will walk up the + * DOM if a node's siblings have been exhausted. + * + * @param {DOMElement|DOMTextNode} node + * @return {?DOMElement|DOMTextNode} + */ + function getSiblingNode(node) { + while (node) { + if (node.nextSibling) { + return node.nextSibling + } + node = node.parentNode + } + } - // Effects - this.effectTag = NoEffect; - this.nextEffect = null; + /** + * Get object describing the nodes which contain characters at offset. + * + * @param {DOMElement|DOMTextNode} root + * @param {number} offset + * @return {?object} + */ + function getNodeForCharacterOffset(root, offset) { + var node = getLeafNode(root) + var nodeStart = 0 + var nodeEnd = 0 + + while (node) { + if (node.nodeType === TEXT_NODE) { + nodeEnd = nodeStart + node.textContent.length + + if (nodeStart <= offset && nodeEnd >= offset) { + return { + node: node, + offset: offset - nodeStart, + } + } + + nodeStart = nodeEnd + } + + node = getLeafNode(getSiblingNode(node)) + } + } - this.firstEffect = null; - this.lastEffect = null; + /** + * @param {DOMElement} outerNode + * @return {?object} + */ + function getOffsets(outerNode) { + var selection = window.getSelection && window.getSelection() + + if (!selection || selection.rangeCount === 0) { + return null + } + + var anchorNode = selection.anchorNode, + anchorOffset = selection.anchorOffset, + focusNode = selection.focusNode, + focusOffset = selection.focusOffset + + // In Firefox, anchorNode and focusNode can be "anonymous divs", e.g. the + // up/down buttons on an . Anonymous divs do not seem to + // expose properties, triggering a "Permission denied error" if any of its + // properties are accessed. The only seemingly possible way to avoid erroring + // is to access a property that typically works for non-anonymous divs and + // catch any error that may otherwise arise. See + // https://bugzilla.mozilla.org/show_bug.cgi?id=208427 + + try { + /* eslint-disable no-unused-expressions */ + anchorNode.nodeType + focusNode.nodeType + /* eslint-enable no-unused-expressions */ + } catch (e) { + return null + } + + return getModernOffsetsFromPoints( + outerNode, + anchorNode, + anchorOffset, + focusNode, + focusOffset + ) + } - this.expirationTime = NoWork; + /** + * Returns {start, end} where `start` is the character/codepoint index of + * (anchorNode, anchorOffset) within the textContent of `outerNode`, and + * `end` is the index of (focusNode, focusOffset). + * + * Returns null if you pass in garbage input but we should probably just crash. + * + * Exported only for testing. + */ + function getModernOffsetsFromPoints( + outerNode, + anchorNode, + anchorOffset, + focusNode, + focusOffset + ) { + var length = 0 + var start = -1 + var end = -1 + var indexWithinAnchor = 0 + var indexWithinFocus = 0 + var node = outerNode + var parentNode = null + + outer: while (true) { + var next = null + + while (true) { + if ( + node === anchorNode && + (anchorOffset === 0 || node.nodeType === TEXT_NODE) + ) { + start = length + anchorOffset + } + if ( + node === focusNode && + (focusOffset === 0 || node.nodeType === TEXT_NODE) + ) { + end = length + focusOffset + } + + if (node.nodeType === TEXT_NODE) { + length += node.nodeValue.length + } + + if ((next = node.firstChild) === null) { + break + } + // Moving from `node` to its first child `next`. + parentNode = node + node = next + } + + while (true) { + if (node === outerNode) { + // If `outerNode` has children, this is always the second time visiting + // it. If it has no children, this is still the first loop, and the only + // valid selection is anchorNode and focusNode both equal to this node + // and both offsets 0, in which case we will have handled above. + break outer + } + if ( + parentNode === anchorNode && + ++indexWithinAnchor === anchorOffset + ) { + start = length + } + if ( + parentNode === focusNode && + ++indexWithinFocus === focusOffset + ) { + end = length + } + if ((next = node.nextSibling) !== null) { + break + } + node = parentNode + parentNode = node.parentNode + } + + // Moving from `node` to its next sibling `next`. + node = next + } + + if (start === -1 || end === -1) { + // This should never happen. (Would happen if the anchor/focus nodes aren't + // actually inside the passed-in node.) + return null + } + + return { + start: start, + end: end, + } + } - this.alternate = null; + /** + * In modern non-IE browsers, we can support both forward and backward + * selections. + * + * Note: IE10+ supports the Selection object, but it does not support + * the `extend` method, which means that even in modern IE, it's not possible + * to programmatically create a backward selection. Thus, for all IE + * versions, we use the old IE API to create our selections. + * + * @param {DOMElement|DOMTextNode} node + * @param {object} offsets + */ + function setOffsets(node, offsets) { + if (!window.getSelection) { + return + } + + var selection = window.getSelection() + var length = node[getTextContentAccessor()].length + var start = Math.min(offsets.start, length) + var end = + offsets.end === undefined + ? start + : Math.min(offsets.end, length) + + // IE 11 uses modern selection, but doesn't support the extend method. + // Flip backward selections, so we can set with a single range. + if (!selection.extend && start > end) { + var temp = end + end = start + start = temp + } + + var startMarker = getNodeForCharacterOffset(node, start) + var endMarker = getNodeForCharacterOffset(node, end) + + if (startMarker && endMarker) { + if ( + selection.rangeCount === 1 && + selection.anchorNode === startMarker.node && + selection.anchorOffset === startMarker.offset && + selection.focusNode === endMarker.node && + selection.focusOffset === endMarker.offset + ) { + return + } + var range = document.createRange() + range.setStart(startMarker.node, startMarker.offset) + selection.removeAllRanges() + + if (start > end) { + selection.addRange(range) + selection.extend(endMarker.node, endMarker.offset) + } else { + range.setEnd(endMarker.node, endMarker.offset) + selection.addRange(range) + } + } + } - { - this._debugID = debugCounter++; - this._debugSource = null; - this._debugOwner = null; - this._debugIsCurrentlyTiming = false; - if (!hasBadMapPolyfill && typeof Object.preventExtensions === 'function') { - Object.preventExtensions(this); - } - } -} - -// This is a constructor function, rather than a POJO constructor, still -// please ensure we do the following: -// 1) Nobody should add any instance methods on this. Instance methods can be -// more difficult to predict when they get optimized and they are almost -// never inlined properly in static compilers. -// 2) Nobody should rely on `instanceof Fiber` for type testing. We should -// always know when it is a fiber. -// 3) We might want to experiment with using numeric keys since they are easier -// to optimize in a non-JIT environment. -// 4) We can easily go from a constructor to a createFiber object literal if that -// is faster. -// 5) It should be easy to port this to a C struct and keep a C implementation -// compatible. -var createFiber = function (tag, pendingProps, key, mode) { - // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors - return new FiberNode(tag, pendingProps, key, mode); -}; - -function shouldConstruct(Component) { - return !!(Component.prototype && Component.prototype.isReactComponent); -} - -// This is used to create an alternate fiber to do work on. -function createWorkInProgress(current, pendingProps, expirationTime) { - var workInProgress = current.alternate; - if (workInProgress === null) { - // We use a double buffering pooling technique because we know that we'll - // only ever need at most two versions of a tree. We pool the "other" unused - // node that we're free to reuse. This is lazily created to avoid allocating - // extra objects for things that are never updated. It also allow us to - // reclaim the extra memory if needed. - workInProgress = createFiber(current.tag, pendingProps, current.key, current.mode); - workInProgress.type = current.type; - workInProgress.stateNode = current.stateNode; + function isInDocument(node) { + return containsNode(document.documentElement, node) + } - { - // DEV-only fields - workInProgress._debugID = current._debugID; - workInProgress._debugSource = current._debugSource; - workInProgress._debugOwner = current._debugOwner; - } + /** + * @ReactInputSelection: React input selection module. Based on Selection.js, + * but modified to be suitable for react and has a couple of bug fixes (doesn't + * assume buttons have range selections allowed). + * Input selection module for React. + */ + + function hasSelectionCapabilities(elem) { + var nodeName = + elem && elem.nodeName && elem.nodeName.toLowerCase() + return ( + nodeName && + ((nodeName === 'input' && elem.type === 'text') || + nodeName === 'textarea' || + elem.contentEditable === 'true') + ) + } - workInProgress.alternate = current; - current.alternate = workInProgress; - } else { - workInProgress.pendingProps = pendingProps; + function getSelectionInformation() { + var focusedElem = getActiveElement() + return { + focusedElem: focusedElem, + selectionRange: hasSelectionCapabilities(focusedElem) + ? getSelection$1(focusedElem) + : null, + } + } - // We already have an alternate. - // Reset the effect tag. - workInProgress.effectTag = NoEffect; + /** + * @restoreSelection: If any selection information was potentially lost, + * restore it. This is useful when performing operations that could remove dom + * nodes and place them back in, resulting in focus being lost. + */ + function restoreSelection(priorSelectionInformation) { + var curFocusedElem = getActiveElement() + var priorFocusedElem = priorSelectionInformation.focusedElem + var priorSelectionRange = + priorSelectionInformation.selectionRange + if ( + curFocusedElem !== priorFocusedElem && + isInDocument(priorFocusedElem) + ) { + if (hasSelectionCapabilities(priorFocusedElem)) { + setSelection(priorFocusedElem, priorSelectionRange) + } + + // Focusing a node can change the scroll position, which is undesirable + var ancestors = [] + var ancestor = priorFocusedElem + while ((ancestor = ancestor.parentNode)) { + if (ancestor.nodeType === ELEMENT_NODE) { + ancestors.push({ + element: ancestor, + left: ancestor.scrollLeft, + top: ancestor.scrollTop, + }) + } + } + + priorFocusedElem.focus() + + for (var i = 0; i < ancestors.length; i++) { + var info = ancestors[i] + info.element.scrollLeft = info.left + info.element.scrollTop = info.top + } + } + } - // The effect list is no longer valid. - workInProgress.nextEffect = null; - workInProgress.firstEffect = null; - workInProgress.lastEffect = null; - } + /** + * @getSelection: Gets the selection bounds of a focused textarea, input or + * contentEditable node. + * -@input: Look up selection bounds of this input + * -@return {start: selectionStart, end: selectionEnd} + */ + function getSelection$1(input) { + var selection = void 0 + + if ('selectionStart' in input) { + // Modern browser with input or textarea. + selection = { + start: input.selectionStart, + end: input.selectionEnd, + } + } else { + // Content editable or old IE textarea. + selection = getOffsets(input) + } + + return selection || { start: 0, end: 0 } + } - workInProgress.expirationTime = expirationTime; + /** + * @setSelection: Sets the selection bounds of a textarea or input and focuses + * the input. + * -@input Set selection bounds of this input or textarea + * -@offsets Object of same form that is returned from get* + */ + function setSelection(input, offsets) { + var start = offsets.start, + end = offsets.end + + if (end === undefined) { + end = start + } + + if ('selectionStart' in input) { + input.selectionStart = start + input.selectionEnd = Math.min(end, input.value.length) + } else { + setOffsets(input, offsets) + } + } - workInProgress.child = current.child; - workInProgress.memoizedProps = current.memoizedProps; - workInProgress.memoizedState = current.memoizedState; - workInProgress.updateQueue = current.updateQueue; + var skipSelectionChangeEvent = + ExecutionEnvironment.canUseDOM && + 'documentMode' in document && + document.documentMode <= 11 + + var eventTypes$3 = { + select: { + phasedRegistrationNames: { + bubbled: 'onSelect', + captured: 'onSelectCapture', + }, + dependencies: [ + 'topBlur', + 'topContextMenu', + 'topFocus', + 'topKeyDown', + 'topKeyUp', + 'topMouseDown', + 'topMouseUp', + 'topSelectionChange', + ], + }, + } - // These will be overridden during the parent's reconciliation - workInProgress.sibling = current.sibling; - workInProgress.index = current.index; - workInProgress.ref = current.ref; + var activeElement$1 = null + var activeElementInst$1 = null + var lastSelection = null + var mouseDown = false + + /** + * Get an object which is a unique representation of the current selection. + * + * The return value will not be consistent across nodes or browsers, but + * two identical selections on the same node will return identical objects. + * + * @param {DOMElement} node + * @return {object} + */ + function getSelection(node) { + if ( + 'selectionStart' in node && + hasSelectionCapabilities(node) + ) { + return { + start: node.selectionStart, + end: node.selectionEnd, + } + } else if (window.getSelection) { + var selection = window.getSelection() + return { + anchorNode: selection.anchorNode, + anchorOffset: selection.anchorOffset, + focusNode: selection.focusNode, + focusOffset: selection.focusOffset, + } + } + } - return workInProgress; -} + /** + * Poll selection to see whether it's changed. + * + * @param {object} nativeEvent + * @return {?SyntheticEvent} + */ + function constructSelectEvent(nativeEvent, nativeEventTarget) { + // Ensure we have the right element, and that the user is not dragging a + // selection (this matches native `select` event behavior). In HTML5, select + // fires only on input and textarea thus if there's no focused element we + // won't dispatch. + if ( + mouseDown || + activeElement$1 == null || + activeElement$1 !== getActiveElement() + ) { + return null + } + + // Only fire when selection has actually changed. + var currentSelection = getSelection(activeElement$1) + if ( + !lastSelection || + !shallowEqual(lastSelection, currentSelection) + ) { + lastSelection = currentSelection + + var syntheticEvent = SyntheticEvent$1.getPooled( + eventTypes$3.select, + activeElementInst$1, + nativeEvent, + nativeEventTarget + ) + + syntheticEvent.type = 'select' + syntheticEvent.target = activeElement$1 + + accumulateTwoPhaseDispatches(syntheticEvent) + + return syntheticEvent + } + + return null + } -function createHostRootFiber(isAsync) { - var mode = isAsync ? AsyncMode | StrictMode : NoContext; - return createFiber(HostRoot, null, null, mode); -} + /** + * This plugin creates an `onSelect` event that normalizes select events + * across form elements. + * + * Supported elements are: + * - input (see `isTextInputElement`) + * - textarea + * - contentEditable + * + * This differs from native browser implementations in the following ways: + * - Fires on contentEditable fields as well as inputs. + * - Fires for collapsed selection. + * - Fires after user input. + */ + var SelectEventPlugin = { + eventTypes: eventTypes$3, + + extractEvents: function ( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ) { + var doc = + nativeEventTarget.window === nativeEventTarget + ? nativeEventTarget.document + : nativeEventTarget.nodeType === DOCUMENT_NODE + ? nativeEventTarget + : nativeEventTarget.ownerDocument + // Track whether all listeners exists for this plugin. If none exist, we do + // not extract events. See #3639. + if ( + !doc || + !isListeningToAllDependencies('onSelect', doc) + ) { + return null + } + + var targetNode = targetInst + ? getNodeFromInstance$1(targetInst) + : window + + switch (topLevelType) { + // Track the input node that has focus. + case 'topFocus': + if ( + isTextInputElement(targetNode) || + targetNode.contentEditable === 'true' + ) { + activeElement$1 = targetNode + activeElementInst$1 = targetInst + lastSelection = null + } + break + case 'topBlur': + activeElement$1 = null + activeElementInst$1 = null + lastSelection = null + break + // Don't fire the event while the user is dragging. This matches the + // semantics of the native select event. + case 'topMouseDown': + mouseDown = true + break + case 'topContextMenu': + case 'topMouseUp': + mouseDown = false + return constructSelectEvent( + nativeEvent, + nativeEventTarget + ) + // Chrome and IE fire non-standard event when selection is changed (and + // sometimes when it hasn't). IE's event fires out of order with respect + // to key and input events on deletion, so we discard it. + // + // Firefox doesn't support selectionchange, so check selection status + // after each key entry. The selection changes after keydown and before + // keyup, but we check on keydown as well in the case of holding down a + // key, when multiple keydown events are fired but only one keyup is. + // This is also our approach for IE handling, for the reason above. + case 'topSelectionChange': + if (skipSelectionChangeEvent) { + break + } + // falls through + case 'topKeyDown': + case 'topKeyUp': + return constructSelectEvent( + nativeEvent, + nativeEventTarget + ) + } + + return null + }, + } -function createFiberFromElement(element, mode, expirationTime) { - var owner = null; - { - owner = element._owner; - } + /** + * Inject modules for resolving DOM hierarchy and plugin ordering. + */ + injection.injectEventPluginOrder(DOMEventPluginOrder) + injection$1.injectComponentTree(ReactDOMComponentTree) + + /** + * Some important event plugins included by default (without having to require + * them). + */ + injection.injectEventPluginsByName({ + SimpleEventPlugin: SimpleEventPlugin, + EnterLeaveEventPlugin: EnterLeaveEventPlugin, + ChangeEventPlugin: ChangeEventPlugin, + SelectEventPlugin: SelectEventPlugin, + BeforeInputEventPlugin: BeforeInputEventPlugin, + }) + + // Max 31 bit integer. The max integer size in V8 for 32-bit systems. + // Math.pow(2, 30) - 1 + // 0b111111111111111111111111111111 + var MAX_SIGNED_31_BIT_INT = 1073741823 + + // TODO: Use an opaque type once ESLint et al support the syntax + + var NoWork = 0 + var Sync = 1 + var Never = MAX_SIGNED_31_BIT_INT + + var UNIT_SIZE = 10 + var MAGIC_NUMBER_OFFSET = 2 + + // 1 unit of expiration time represents 10ms. + function msToExpirationTime(ms) { + // Always add an offset so that we don't clash with the magic number for NoWork. + return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET + } - var fiber = void 0; - var type = element.type; - var key = element.key; - var pendingProps = element.props; + function expirationTimeToMs(expirationTime) { + return (expirationTime - MAGIC_NUMBER_OFFSET) * UNIT_SIZE + } - var fiberTag = void 0; - if (typeof type === 'function') { - fiberTag = shouldConstruct(type) ? ClassComponent : IndeterminateComponent; - } else if (typeof type === 'string') { - fiberTag = HostComponent; - } else { - switch (type) { - case REACT_FRAGMENT_TYPE: - return createFiberFromFragment(pendingProps.children, mode, expirationTime, key); - case REACT_ASYNC_MODE_TYPE: - fiberTag = Mode; - mode |= AsyncMode | StrictMode; - break; - case REACT_STRICT_MODE_TYPE: - fiberTag = Mode; - mode |= StrictMode; - break; - case REACT_CALL_TYPE: - fiberTag = CallComponent; - break; - case REACT_RETURN_TYPE: - fiberTag = ReturnComponent; - break; - default: - { - if (typeof type === 'object' && type !== null) { - switch (type.$$typeof) { - case REACT_PROVIDER_TYPE: - fiberTag = ContextProvider; - break; - case REACT_CONTEXT_TYPE: - // This is a consumer - fiberTag = ContextConsumer; - break; - case REACT_FORWARD_REF_TYPE: - fiberTag = ForwardRef; - break; - default: - if (typeof type.tag === 'number') { - // Currently assumed to be a continuation and therefore is a - // fiber already. - // TODO: The yield system is currently broken for updates in - // some cases. The reified yield stores a fiber, but we don't - // know which fiber that is; the current or a workInProgress? - // When the continuation gets rendered here we don't know if we - // can reuse that fiber or if we need to clone it. There is - // probably a clever way to restructure this. - fiber = type; - fiber.pendingProps = pendingProps; - fiber.expirationTime = expirationTime; - return fiber; - } else { - throwOnInvalidElementType(type, owner); + function ceiling(num, precision) { + return (((num / precision) | 0) + 1) * precision } - break; - } - } else { - throwOnInvalidElementType(type, owner); - } - } - } - } - fiber = createFiber(fiberTag, pendingProps, key, mode); - fiber.type = type; - fiber.expirationTime = expirationTime; + function computeExpirationBucket( + currentTime, + expirationInMs, + bucketSizeMs + ) { + return ceiling( + currentTime + expirationInMs / UNIT_SIZE, + bucketSizeMs / UNIT_SIZE + ) + } - { - fiber._debugSource = element._source; - fiber._debugOwner = element._owner; - } + var NoContext = 0 + var AsyncMode = 1 + var StrictMode = 2 + + var hasBadMapPolyfill = void 0 + + { + hasBadMapPolyfill = false + try { + var nonExtensibleObject = Object.preventExtensions({}) + var testMap = new Map([[nonExtensibleObject, null]]) + var testSet = new Set([nonExtensibleObject]) + // This is necessary for Rollup to not consider these unused. + // https://github.com/rollup/rollup/issues/1771 + // TODO: we can remove these if Rollup fixes the bug. + testMap.set(0, 0) + testSet.add(0) + } catch (e) { + // TODO: Consider warning about bad polyfills + hasBadMapPolyfill = true + } + } - return fiber; -} + // A Fiber is work on a Component that needs to be done or was done. There can + // be more than one per component. -function throwOnInvalidElementType(type, owner) { - var info = ''; - { - if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) { - info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and " + 'named imports.'; - } - var ownerName = owner ? getComponentName(owner) : null; - if (ownerName) { - info += '\n\nCheck the render method of `' + ownerName + '`.'; - } - } - invariant(false, 'Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s', type == null ? type : typeof type, info); -} - -function createFiberFromFragment(elements, mode, expirationTime, key) { - var fiber = createFiber(Fragment, elements, key, mode); - fiber.expirationTime = expirationTime; - return fiber; -} - -function createFiberFromText(content, mode, expirationTime) { - var fiber = createFiber(HostText, content, null, mode); - fiber.expirationTime = expirationTime; - return fiber; -} - -function createFiberFromHostInstanceForDeletion() { - var fiber = createFiber(HostComponent, null, null, NoContext); - fiber.type = 'DELETED'; - return fiber; -} - -function createFiberFromPortal(portal, mode, expirationTime) { - var pendingProps = portal.children !== null ? portal.children : []; - var fiber = createFiber(HostPortal, pendingProps, portal.key, mode); - fiber.expirationTime = expirationTime; - fiber.stateNode = { - containerInfo: portal.containerInfo, - pendingChildren: null, // Used by persistent updates - implementation: portal.implementation - }; - return fiber; -} - -// Used for stashing WIP properties to replay failed work in DEV. -function assignFiberPropertiesInDEV(target, source) { - if (target === null) { - // This Fiber's initial properties will always be overwritten. - // We only use a Fiber to ensure the same hidden class so DEV isn't slow. - target = createFiber(IndeterminateComponent, null, null, NoContext); - } + var debugCounter = void 0 - // This is intentionally written as a list of all properties. - // We tried to use Object.assign() instead but this is called in - // the hottest path, and Object.assign() was too slow: - // https://github.com/facebook/react/issues/12502 - // This code is DEV-only so size is not a concern. - - target.tag = source.tag; - target.key = source.key; - target.type = source.type; - target.stateNode = source.stateNode; - target['return'] = source['return']; - target.child = source.child; - target.sibling = source.sibling; - target.index = source.index; - target.ref = source.ref; - target.pendingProps = source.pendingProps; - target.memoizedProps = source.memoizedProps; - target.updateQueue = source.updateQueue; - target.memoizedState = source.memoizedState; - target.mode = source.mode; - target.effectTag = source.effectTag; - target.nextEffect = source.nextEffect; - target.firstEffect = source.firstEffect; - target.lastEffect = source.lastEffect; - target.expirationTime = source.expirationTime; - target.alternate = source.alternate; - target._debugID = source._debugID; - target._debugSource = source._debugSource; - target._debugOwner = source._debugOwner; - target._debugIsCurrentlyTiming = source._debugIsCurrentlyTiming; - return target; -} - -// TODO: This should be lifted into the renderer. - - -function createFiberRoot(containerInfo, isAsync, hydrate) { - // Cyclic construction. This cheats the type system right now because - // stateNode is any. - var uninitializedFiber = createHostRootFiber(isAsync); - var root = { - current: uninitializedFiber, - containerInfo: containerInfo, - pendingChildren: null, - pendingCommitExpirationTime: NoWork, - finishedWork: null, - context: null, - pendingContext: null, - hydrate: hydrate, - remainingExpirationTime: NoWork, - firstBatch: null, - nextScheduledRoot: null - }; - uninitializedFiber.stateNode = root; - return root; -} - -var onCommitFiberRoot = null; -var onCommitFiberUnmount = null; -var hasLoggedError = false; - -function catchErrors(fn) { - return function (arg) { - try { - return fn(arg); - } catch (err) { - if (true && !hasLoggedError) { - hasLoggedError = true; - warning(false, 'React DevTools encountered an error: %s', err); - } - } - }; -} + { + debugCounter = 1 + } -function injectInternals(internals) { - if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { - // No DevTools - return false; - } - var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; - 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. - // https://github.com/facebook/react/issues/3877 - return true; - } - if (!hook.supportsFiber) { - { - warning(false, 'The installed version of React DevTools is too old and will not work ' + 'with the current version of React. Please update React DevTools. ' + 'https://fb.me/react-devtools'); - } - // DevTools exists, even though it doesn't support Fiber. - return true; - } - try { - var rendererID = hook.inject(internals); - // We have successfully injected, so now it is safe to set up hooks. - onCommitFiberRoot = catchErrors(function (root) { - return hook.onCommitFiberRoot(rendererID, root); - }); - onCommitFiberUnmount = catchErrors(function (fiber) { - return hook.onCommitFiberUnmount(rendererID, fiber); - }); - } catch (err) { - // Catch all errors because it is unsafe to throw during initialization. - { - warning(false, 'React DevTools encountered an error: %s.', err); - } - } - // DevTools exists - return true; -} + function FiberNode(tag, pendingProps, key, mode) { + // Instance + this.tag = tag + this.key = key + this.type = null + this.stateNode = null + + // Fiber + this['return'] = null + this.child = null + this.sibling = null + this.index = 0 + + this.ref = null + + this.pendingProps = pendingProps + this.memoizedProps = null + this.updateQueue = null + this.memoizedState = null + + this.mode = mode + + // Effects + this.effectTag = NoEffect + this.nextEffect = null + + this.firstEffect = null + this.lastEffect = null + + this.expirationTime = NoWork + + this.alternate = null + + { + this._debugID = debugCounter++ + this._debugSource = null + this._debugOwner = null + this._debugIsCurrentlyTiming = false + if ( + !hasBadMapPolyfill && + typeof Object.preventExtensions === 'function' + ) { + Object.preventExtensions(this) + } + } + } -function onCommitRoot(root) { - if (typeof onCommitFiberRoot === 'function') { - onCommitFiberRoot(root); - } -} + // This is a constructor function, rather than a POJO constructor, still + // please ensure we do the following: + // 1) Nobody should add any instance methods on this. Instance methods can be + // more difficult to predict when they get optimized and they are almost + // never inlined properly in static compilers. + // 2) Nobody should rely on `instanceof Fiber` for type testing. We should + // always know when it is a fiber. + // 3) We might want to experiment with using numeric keys since they are easier + // to optimize in a non-JIT environment. + // 4) We can easily go from a constructor to a createFiber object literal if that + // is faster. + // 5) It should be easy to port this to a C struct and keep a C implementation + // compatible. + var createFiber = function (tag, pendingProps, key, mode) { + // $FlowFixMe: the shapes are exact here but Flow doesn't like constructors + return new FiberNode(tag, pendingProps, key, mode) + } -function onCommitUnmount(fiber) { - if (typeof onCommitFiberUnmount === 'function') { - onCommitFiberUnmount(fiber); - } -} - -/** - * Forked from fbjs/warning: - * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js - * - * Only change is we use console.warn instead of console.error, - * and do nothing when 'console' is not supported. - * This really simplifies the code. - * --- - * 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 lowPriorityWarning = function () {}; - -{ - var printWarning = function (format) { - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } + function shouldConstruct(Component) { + return !!( + Component.prototype && Component.prototype.isReactComponent + ) + } - var argIndex = 0; - var message = 'Warning: ' + format.replace(/%s/g, function () { - return args[argIndex++]; - }); - if (typeof console !== 'undefined') { - console.warn(message); - } - 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. - throw new Error(message); - } catch (x) {} - }; - - lowPriorityWarning = function (condition, format) { - if (format === undefined) { - throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument'); - } - if (!condition) { - for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { - args[_key2 - 2] = arguments[_key2]; - } + // This is used to create an alternate fiber to do work on. + function createWorkInProgress( + current, + pendingProps, + expirationTime + ) { + var workInProgress = current.alternate + if (workInProgress === null) { + // We use a double buffering pooling technique because we know that we'll + // only ever need at most two versions of a tree. We pool the "other" unused + // node that we're free to reuse. This is lazily created to avoid allocating + // extra objects for things that are never updated. It also allow us to + // reclaim the extra memory if needed. + workInProgress = createFiber( + current.tag, + pendingProps, + current.key, + current.mode + ) + workInProgress.type = current.type + workInProgress.stateNode = current.stateNode + + { + // DEV-only fields + workInProgress._debugID = current._debugID + workInProgress._debugSource = current._debugSource + workInProgress._debugOwner = current._debugOwner + } + + workInProgress.alternate = current + current.alternate = workInProgress + } else { + workInProgress.pendingProps = pendingProps + + // We already have an alternate. + // Reset the effect tag. + workInProgress.effectTag = NoEffect + + // The effect list is no longer valid. + workInProgress.nextEffect = null + workInProgress.firstEffect = null + workInProgress.lastEffect = null + } + + workInProgress.expirationTime = expirationTime + + workInProgress.child = current.child + workInProgress.memoizedProps = current.memoizedProps + workInProgress.memoizedState = current.memoizedState + workInProgress.updateQueue = current.updateQueue + + // These will be overridden during the parent's reconciliation + workInProgress.sibling = current.sibling + workInProgress.index = current.index + workInProgress.ref = current.ref + + return workInProgress + } - printWarning.apply(undefined, [format].concat(args)); - } - }; -} - -var lowPriorityWarning$1 = lowPriorityWarning; - -var ReactStrictModeWarnings = { - discardPendingWarnings: function () {}, - flushPendingDeprecationWarnings: function () {}, - flushPendingUnsafeLifecycleWarnings: function () {}, - recordDeprecationWarnings: function (fiber, instance) {}, - recordUnsafeLifecycleWarnings: function (fiber, instance) {} -}; - -{ - var LIFECYCLE_SUGGESTIONS = { - UNSAFE_componentWillMount: 'componentDidMount', - UNSAFE_componentWillReceiveProps: 'static getDerivedStateFromProps', - UNSAFE_componentWillUpdate: 'componentDidUpdate' - }; - - var pendingComponentWillMountWarnings = []; - var pendingComponentWillReceivePropsWarnings = []; - var pendingComponentWillUpdateWarnings = []; - var pendingUnsafeLifecycleWarnings = new Map(); - - // Tracks components we have already warned about. - var didWarnAboutDeprecatedLifecycles = new Set(); - var didWarnAboutUnsafeLifecycles = new Set(); - - var setToSortedString = function (set) { - var array = []; - set.forEach(function (value) { - array.push(value); - }); - return array.sort().join(', '); - }; - - ReactStrictModeWarnings.discardPendingWarnings = function () { - pendingComponentWillMountWarnings = []; - pendingComponentWillReceivePropsWarnings = []; - pendingComponentWillUpdateWarnings = []; - pendingUnsafeLifecycleWarnings = new Map(); - }; - - ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function () { - pendingUnsafeLifecycleWarnings.forEach(function (lifecycleWarningsMap, strictRoot) { - var lifecyclesWarningMesages = []; - - Object.keys(lifecycleWarningsMap).forEach(function (lifecycle) { - var lifecycleWarnings = lifecycleWarningsMap[lifecycle]; - if (lifecycleWarnings.length > 0) { - var componentNames = new Set(); - lifecycleWarnings.forEach(function (fiber) { - componentNames.add(getComponentName(fiber) || 'Component'); - didWarnAboutUnsafeLifecycles.add(fiber.type); - }); - - var formatted = lifecycle.replace('UNSAFE_', ''); - var suggestion = LIFECYCLE_SUGGESTIONS[lifecycle]; - var sortedComponentNames = setToSortedString(componentNames); - - lifecyclesWarningMesages.push(formatted + ': Please update the following components to use ' + (suggestion + ' instead: ' + sortedComponentNames)); - } - }); + function createHostRootFiber(isAsync) { + var mode = isAsync ? AsyncMode | StrictMode : NoContext + return createFiber(HostRoot, null, null, mode) + } - if (lifecyclesWarningMesages.length > 0) { - var strictRootComponentStack = getStackAddendumByWorkInProgressFiber(strictRoot); + function createFiberFromElement(element, mode, expirationTime) { + var owner = null + { + owner = element._owner + } + + var fiber = void 0 + var type = element.type + var key = element.key + var pendingProps = element.props + + var fiberTag = void 0 + if (typeof type === 'function') { + fiberTag = shouldConstruct(type) + ? ClassComponent + : IndeterminateComponent + } else if (typeof type === 'string') { + fiberTag = HostComponent + } else { + switch (type) { + case REACT_FRAGMENT_TYPE: + return createFiberFromFragment( + pendingProps.children, + mode, + expirationTime, + key + ) + case REACT_ASYNC_MODE_TYPE: + fiberTag = Mode + mode |= AsyncMode | StrictMode + break + case REACT_STRICT_MODE_TYPE: + fiberTag = Mode + mode |= StrictMode + break + case REACT_CALL_TYPE: + fiberTag = CallComponent + break + case REACT_RETURN_TYPE: + fiberTag = ReturnComponent + break + default: { + if (typeof type === 'object' && type !== null) { + switch (type.$$typeof) { + case REACT_PROVIDER_TYPE: + fiberTag = ContextProvider + break + case REACT_CONTEXT_TYPE: + // This is a consumer + fiberTag = ContextConsumer + break + case REACT_FORWARD_REF_TYPE: + fiberTag = ForwardRef + break + default: + if (typeof type.tag === 'number') { + // Currently assumed to be a continuation and therefore is a + // fiber already. + // TODO: The yield system is currently broken for updates in + // some cases. The reified yield stores a fiber, but we don't + // know which fiber that is; the current or a workInProgress? + // When the continuation gets rendered here we don't know if we + // can reuse that fiber or if we need to clone it. There is + // probably a clever way to restructure this. + fiber = type + fiber.pendingProps = pendingProps + fiber.expirationTime = expirationTime + return fiber + } else { + throwOnInvalidElementType(type, owner) + } + break + } + } else { + throwOnInvalidElementType(type, owner) + } + } + } + } + + fiber = createFiber(fiberTag, pendingProps, key, mode) + fiber.type = type + fiber.expirationTime = expirationTime + + { + fiber._debugSource = element._source + fiber._debugOwner = element._owner + } + + return fiber + } - warning(false, 'Unsafe lifecycle methods were found within a strict-mode tree:%s' + '\n\n%s' + '\n\nLearn more about this warning here:' + '\nhttps://fb.me/react-strict-mode-warnings', strictRootComponentStack, lifecyclesWarningMesages.join('\n\n')); - } - }); + function throwOnInvalidElementType(type, owner) { + var info = '' + { + if ( + type === undefined || + (typeof type === 'object' && + type !== null && + Object.keys(type).length === 0) + ) { + info += + ' You likely forgot to export your component from the file ' + + "it's defined in, or you might have mixed up default and " + + 'named imports.' + } + var ownerName = owner ? getComponentName(owner) : null + if (ownerName) { + info += + '\n\nCheck the render method of `' + ownerName + '`.' + } + } + invariant( + false, + 'Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s', + type == null ? type : typeof type, + info + ) + } - pendingUnsafeLifecycleWarnings = new Map(); - }; + function createFiberFromFragment( + elements, + mode, + expirationTime, + key + ) { + var fiber = createFiber(Fragment, elements, key, mode) + fiber.expirationTime = expirationTime + return fiber + } - var getStrictRoot = function (fiber) { - var maybeStrictRoot = null; + function createFiberFromText(content, mode, expirationTime) { + var fiber = createFiber(HostText, content, null, mode) + fiber.expirationTime = expirationTime + return fiber + } - while (fiber !== null) { - if (fiber.mode & StrictMode) { - maybeStrictRoot = fiber; - } + function createFiberFromHostInstanceForDeletion() { + var fiber = createFiber(HostComponent, null, null, NoContext) + fiber.type = 'DELETED' + return fiber + } - fiber = fiber['return']; - } + function createFiberFromPortal(portal, mode, expirationTime) { + var pendingProps = + portal.children !== null ? portal.children : [] + var fiber = createFiber( + HostPortal, + pendingProps, + portal.key, + mode + ) + fiber.expirationTime = expirationTime + fiber.stateNode = { + containerInfo: portal.containerInfo, + pendingChildren: null, // Used by persistent updates + implementation: portal.implementation, + } + return fiber + } - return maybeStrictRoot; - }; + // Used for stashing WIP properties to replay failed work in DEV. + function assignFiberPropertiesInDEV(target, source) { + if (target === null) { + // This Fiber's initial properties will always be overwritten. + // We only use a Fiber to ensure the same hidden class so DEV isn't slow. + target = createFiber( + IndeterminateComponent, + null, + null, + NoContext + ) + } + + // This is intentionally written as a list of all properties. + // We tried to use Object.assign() instead but this is called in + // the hottest path, and Object.assign() was too slow: + // https://github.com/facebook/react/issues/12502 + // This code is DEV-only so size is not a concern. + + target.tag = source.tag + target.key = source.key + target.type = source.type + target.stateNode = source.stateNode + target['return'] = source['return'] + target.child = source.child + target.sibling = source.sibling + target.index = source.index + target.ref = source.ref + target.pendingProps = source.pendingProps + target.memoizedProps = source.memoizedProps + target.updateQueue = source.updateQueue + target.memoizedState = source.memoizedState + target.mode = source.mode + target.effectTag = source.effectTag + target.nextEffect = source.nextEffect + target.firstEffect = source.firstEffect + target.lastEffect = source.lastEffect + target.expirationTime = source.expirationTime + target.alternate = source.alternate + target._debugID = source._debugID + target._debugSource = source._debugSource + target._debugOwner = source._debugOwner + target._debugIsCurrentlyTiming = + source._debugIsCurrentlyTiming + return target + } - ReactStrictModeWarnings.flushPendingDeprecationWarnings = function () { - if (pendingComponentWillMountWarnings.length > 0) { - var uniqueNames = new Set(); - pendingComponentWillMountWarnings.forEach(function (fiber) { - uniqueNames.add(getComponentName(fiber) || 'Component'); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); + // TODO: This should be lifted into the renderer. + + function createFiberRoot(containerInfo, isAsync, hydrate) { + // Cyclic construction. This cheats the type system right now because + // stateNode is any. + var uninitializedFiber = createHostRootFiber(isAsync) + var root = { + current: uninitializedFiber, + containerInfo: containerInfo, + pendingChildren: null, + pendingCommitExpirationTime: NoWork, + finishedWork: null, + context: null, + pendingContext: null, + hydrate: hydrate, + remainingExpirationTime: NoWork, + firstBatch: null, + nextScheduledRoot: null, + } + uninitializedFiber.stateNode = root + return root + } - var sortedNames = setToSortedString(uniqueNames); + var onCommitFiberRoot = null + var onCommitFiberUnmount = null + var hasLoggedError = false + + function catchErrors(fn) { + return function (arg) { + try { + return fn(arg) + } catch (err) { + if (true && !hasLoggedError) { + hasLoggedError = true + warning( + false, + 'React DevTools encountered an error: %s', + err + ) + } + } + } + } - lowPriorityWarning$1(false, 'componentWillMount is deprecated and will be removed in the next major version. ' + 'Use componentDidMount instead. As a temporary workaround, ' + 'you can rename to UNSAFE_componentWillMount.' + '\n\nPlease update the following components: %s' + '\n\nLearn more about this warning here:' + '\nhttps://fb.me/react-async-component-lifecycle-hooks', sortedNames); + function injectInternals(internals) { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined') { + // No DevTools + return false + } + var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__ + 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. + // https://github.com/facebook/react/issues/3877 + return true + } + if (!hook.supportsFiber) { + { + warning( + false, + 'The installed version of React DevTools is too old and will not work ' + + 'with the current version of React. Please update React DevTools. ' + + 'https://fb.me/react-devtools' + ) + } + // DevTools exists, even though it doesn't support Fiber. + return true + } + try { + var rendererID = hook.inject(internals) + // We have successfully injected, so now it is safe to set up hooks. + onCommitFiberRoot = catchErrors(function (root) { + return hook.onCommitFiberRoot(rendererID, root) + }) + onCommitFiberUnmount = catchErrors(function (fiber) { + return hook.onCommitFiberUnmount(rendererID, fiber) + }) + } catch (err) { + // Catch all errors because it is unsafe to throw during initialization. + { + warning( + false, + 'React DevTools encountered an error: %s.', + err + ) + } + } + // DevTools exists + return true + } - pendingComponentWillMountWarnings = []; - } + function onCommitRoot(root) { + if (typeof onCommitFiberRoot === 'function') { + onCommitFiberRoot(root) + } + } - if (pendingComponentWillReceivePropsWarnings.length > 0) { - var _uniqueNames = new Set(); - pendingComponentWillReceivePropsWarnings.forEach(function (fiber) { - _uniqueNames.add(getComponentName(fiber) || 'Component'); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); + function onCommitUnmount(fiber) { + if (typeof onCommitFiberUnmount === 'function') { + onCommitFiberUnmount(fiber) + } + } - var _sortedNames = setToSortedString(_uniqueNames); + /** + * Forked from fbjs/warning: + * https://github.com/facebook/fbjs/blob/e66ba20ad5be433eb54423f2b097d829324d9de6/packages/fbjs/src/__forks__/warning.js + * + * Only change is we use console.warn instead of console.error, + * and do nothing when 'console' is not supported. + * This really simplifies the code. + * --- + * 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 lowPriorityWarning = function () {} + + { + var printWarning = function (format) { + for ( + var _len = arguments.length, + args = Array(_len > 1 ? _len - 1 : 0), + _key = 1; + _key < _len; + _key++ + ) { + args[_key - 1] = arguments[_key] + } + + var argIndex = 0 + var message = + 'Warning: ' + + format.replace(/%s/g, function () { + return args[argIndex++] + }) + if (typeof console !== 'undefined') { + console.warn(message) + } + 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. + throw new Error(message) + } catch (x) {} + } + + lowPriorityWarning = function (condition, format) { + if (format === undefined) { + throw new Error( + '`warning(condition, format, ...args)` requires a warning ' + + 'message argument' + ) + } + if (!condition) { + for ( + var _len2 = arguments.length, + args = Array(_len2 > 2 ? _len2 - 2 : 0), + _key2 = 2; + _key2 < _len2; + _key2++ + ) { + args[_key2 - 2] = arguments[_key2] + } + + printWarning.apply(undefined, [format].concat(args)) + } + } + } - lowPriorityWarning$1(false, 'componentWillReceiveProps is deprecated and will be removed in the next major version. ' + 'Use static getDerivedStateFromProps instead.' + '\n\nPlease update the following components: %s' + '\n\nLearn more about this warning here:' + '\nhttps://fb.me/react-async-component-lifecycle-hooks', _sortedNames); + var lowPriorityWarning$1 = lowPriorityWarning - pendingComponentWillReceivePropsWarnings = []; - } + var ReactStrictModeWarnings = { + discardPendingWarnings: function () {}, + flushPendingDeprecationWarnings: function () {}, + flushPendingUnsafeLifecycleWarnings: function () {}, + recordDeprecationWarnings: function (fiber, instance) {}, + recordUnsafeLifecycleWarnings: function (fiber, instance) {}, + } - if (pendingComponentWillUpdateWarnings.length > 0) { - var _uniqueNames2 = new Set(); - pendingComponentWillUpdateWarnings.forEach(function (fiber) { - _uniqueNames2.add(getComponentName(fiber) || 'Component'); - didWarnAboutDeprecatedLifecycles.add(fiber.type); - }); + { + var LIFECYCLE_SUGGESTIONS = { + UNSAFE_componentWillMount: 'componentDidMount', + UNSAFE_componentWillReceiveProps: + 'static getDerivedStateFromProps', + UNSAFE_componentWillUpdate: 'componentDidUpdate', + } + + var pendingComponentWillMountWarnings = [] + var pendingComponentWillReceivePropsWarnings = [] + var pendingComponentWillUpdateWarnings = [] + var pendingUnsafeLifecycleWarnings = new Map() + + // Tracks components we have already warned about. + var didWarnAboutDeprecatedLifecycles = new Set() + var didWarnAboutUnsafeLifecycles = new Set() + + var setToSortedString = function (set) { + var array = [] + set.forEach(function (value) { + array.push(value) + }) + return array.sort().join(', ') + } + + ReactStrictModeWarnings.discardPendingWarnings = function () { + pendingComponentWillMountWarnings = [] + pendingComponentWillReceivePropsWarnings = [] + pendingComponentWillUpdateWarnings = [] + pendingUnsafeLifecycleWarnings = new Map() + } + + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings = function () { + pendingUnsafeLifecycleWarnings.forEach(function ( + lifecycleWarningsMap, + strictRoot + ) { + var lifecyclesWarningMesages = [] + + Object.keys(lifecycleWarningsMap).forEach(function ( + lifecycle + ) { + var lifecycleWarnings = lifecycleWarningsMap[lifecycle] + if (lifecycleWarnings.length > 0) { + var componentNames = new Set() + lifecycleWarnings.forEach(function (fiber) { + componentNames.add( + getComponentName(fiber) || 'Component' + ) + didWarnAboutUnsafeLifecycles.add(fiber.type) + }) + + var formatted = lifecycle.replace('UNSAFE_', '') + var suggestion = LIFECYCLE_SUGGESTIONS[lifecycle] + var sortedComponentNames = setToSortedString( + componentNames + ) + + lifecyclesWarningMesages.push( + formatted + + ': Please update the following components to use ' + + (suggestion + ' instead: ' + sortedComponentNames) + ) + } + }) + + if (lifecyclesWarningMesages.length > 0) { + var strictRootComponentStack = getStackAddendumByWorkInProgressFiber( + strictRoot + ) + + warning( + false, + 'Unsafe lifecycle methods were found within a strict-mode tree:%s' + + '\n\n%s' + + '\n\nLearn more about this warning here:' + + '\nhttps://fb.me/react-strict-mode-warnings', + strictRootComponentStack, + lifecyclesWarningMesages.join('\n\n') + ) + } + }) + + pendingUnsafeLifecycleWarnings = new Map() + } + + var getStrictRoot = function (fiber) { + var maybeStrictRoot = null + + while (fiber !== null) { + if (fiber.mode & StrictMode) { + maybeStrictRoot = fiber + } + + fiber = fiber['return'] + } + + return maybeStrictRoot + } + + ReactStrictModeWarnings.flushPendingDeprecationWarnings = function () { + if (pendingComponentWillMountWarnings.length > 0) { + var uniqueNames = new Set() + pendingComponentWillMountWarnings.forEach(function ( + fiber + ) { + uniqueNames.add(getComponentName(fiber) || 'Component') + didWarnAboutDeprecatedLifecycles.add(fiber.type) + }) + + var sortedNames = setToSortedString(uniqueNames) + + lowPriorityWarning$1( + false, + 'componentWillMount is deprecated and will be removed in the next major version. ' + + 'Use componentDidMount instead. As a temporary workaround, ' + + 'you can rename to UNSAFE_componentWillMount.' + + '\n\nPlease update the following components: %s' + + '\n\nLearn more about this warning here:' + + '\nhttps://fb.me/react-async-component-lifecycle-hooks', + sortedNames + ) + + pendingComponentWillMountWarnings = [] + } + + if (pendingComponentWillReceivePropsWarnings.length > 0) { + var _uniqueNames = new Set() + pendingComponentWillReceivePropsWarnings.forEach( + function (fiber) { + _uniqueNames.add( + getComponentName(fiber) || 'Component' + ) + didWarnAboutDeprecatedLifecycles.add(fiber.type) + } + ) + + var _sortedNames = setToSortedString(_uniqueNames) + + lowPriorityWarning$1( + false, + 'componentWillReceiveProps is deprecated and will be removed in the next major version. ' + + 'Use static getDerivedStateFromProps instead.' + + '\n\nPlease update the following components: %s' + + '\n\nLearn more about this warning here:' + + '\nhttps://fb.me/react-async-component-lifecycle-hooks', + _sortedNames + ) + + pendingComponentWillReceivePropsWarnings = [] + } + + if (pendingComponentWillUpdateWarnings.length > 0) { + var _uniqueNames2 = new Set() + pendingComponentWillUpdateWarnings.forEach(function ( + fiber + ) { + _uniqueNames2.add( + getComponentName(fiber) || 'Component' + ) + didWarnAboutDeprecatedLifecycles.add(fiber.type) + }) + + var _sortedNames2 = setToSortedString(_uniqueNames2) + + lowPriorityWarning$1( + false, + 'componentWillUpdate is deprecated and will be removed in the next major version. ' + + 'Use componentDidUpdate instead. As a temporary workaround, ' + + 'you can rename to UNSAFE_componentWillUpdate.' + + '\n\nPlease update the following components: %s' + + '\n\nLearn more about this warning here:' + + '\nhttps://fb.me/react-async-component-lifecycle-hooks', + _sortedNames2 + ) + + pendingComponentWillUpdateWarnings = [] + } + } + + ReactStrictModeWarnings.recordDeprecationWarnings = function ( + fiber, + instance + ) { + // Dedup strategy: Warn once per component. + if (didWarnAboutDeprecatedLifecycles.has(fiber.type)) { + return + } + + // Don't warn about react-lifecycles-compat polyfilled components. + if ( + typeof instance.componentWillMount === 'function' && + instance.componentWillMount + .__suppressDeprecationWarning !== true + ) { + pendingComponentWillMountWarnings.push(fiber) + } + if ( + typeof instance.componentWillReceiveProps === + 'function' && + instance.componentWillReceiveProps + .__suppressDeprecationWarning !== true + ) { + pendingComponentWillReceivePropsWarnings.push(fiber) + } + if ( + typeof instance.componentWillUpdate === 'function' && + instance.componentWillUpdate + .__suppressDeprecationWarning !== true + ) { + pendingComponentWillUpdateWarnings.push(fiber) + } + } + + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function ( + fiber, + instance + ) { + var strictRoot = getStrictRoot(fiber) + + // Dedup strategy: Warn once per component. + // This is difficult to track any other way since component names + // are often vague and are likely to collide between 3rd party libraries. + // An expand property is probably okay to use here since it's DEV-only, + // and will only be set in the event of serious warnings. + if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { + return + } + + // Don't warn about react-lifecycles-compat polyfilled components. + // Note that it is sufficient to check for the presence of a + // single lifecycle, componentWillMount, with the polyfill flag. + if ( + typeof instance.componentWillMount === 'function' && + instance.componentWillMount + .__suppressDeprecationWarning === true + ) { + return + } + + var warningsForRoot = void 0 + if (!pendingUnsafeLifecycleWarnings.has(strictRoot)) { + warningsForRoot = { + UNSAFE_componentWillMount: [], + UNSAFE_componentWillReceiveProps: [], + UNSAFE_componentWillUpdate: [], + } + + pendingUnsafeLifecycleWarnings.set( + strictRoot, + warningsForRoot + ) + } else { + warningsForRoot = pendingUnsafeLifecycleWarnings.get( + strictRoot + ) + } + + var unsafeLifecycles = [] + if ( + typeof instance.componentWillMount === 'function' || + typeof instance.UNSAFE_componentWillMount === 'function' + ) { + unsafeLifecycles.push('UNSAFE_componentWillMount') + } + if ( + typeof instance.componentWillReceiveProps === + 'function' || + typeof instance.UNSAFE_componentWillReceiveProps === + 'function' + ) { + unsafeLifecycles.push('UNSAFE_componentWillReceiveProps') + } + if ( + typeof instance.componentWillUpdate === 'function' || + typeof instance.UNSAFE_componentWillUpdate === 'function' + ) { + unsafeLifecycles.push('UNSAFE_componentWillUpdate') + } + + if (unsafeLifecycles.length > 0) { + unsafeLifecycles.forEach(function (lifecycle) { + warningsForRoot[lifecycle].push(fiber) + }) + } + } + } - var _sortedNames2 = setToSortedString(_uniqueNames2); + // Exports ReactDOM.createRoot + var enableUserTimingAPI = true + + // Mutating mode (React DOM, React ART, React Native): + var enableMutatingReconciler = true + // Experimental noop mode (currently unused): + var enableNoopReconciler = false + // Experimental persistent mode (Fabric): + var enablePersistentReconciler = false + // Experimental error-boundary API that can recover from errors within a single + // render phase + var enableGetDerivedStateFromCatch = false + // Helps identify side effects in begin-phase lifecycle hooks and setState reducers: + var debugRenderPhaseSideEffects = false + + // In some cases, StrictMode should also double-render lifecycles. + // This can be confusing for tests though, + // And it can be bad for performance in production. + // This feature flag can be used to control the behavior: + var debugRenderPhaseSideEffectsForStrictMode = true + + // To preserve the "Pause on caught exceptions" behavior of the debugger, we + // replay the begin phase of a failed component inside invokeGuardedCallback. + var replayFailedUnitOfWorkWithInvokeGuardedCallback = true + + // Warn about deprecated, async-unsafe lifecycles; relates to RFC #6: + var warnAboutDeprecatedLifecycles = false + + var alwaysUseRequestIdleCallbackPolyfill = false + + // Only used in www builds. + + // Prefix measurements so that it's possible to filter them. + // Longer prefixes are hard to read in DevTools. + var reactEmoji = '\u269B' + var warningEmoji = '\u26D4' + var supportsUserTiming = + typeof performance !== 'undefined' && + typeof performance.mark === 'function' && + typeof performance.clearMarks === 'function' && + typeof performance.measure === 'function' && + typeof performance.clearMeasures === 'function' + + // Keep track of current fiber so that we know the path to unwind on pause. + // TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them? + var currentFiber = null + // If we're in the middle of user code, which fiber and method is it? + // Reusing `currentFiber` would be confusing for this because user code fiber + // can change during commit phase too, but we don't need to unwind it (since + // lifecycles in the commit phase don't resemble a tree). + var currentPhase = null + var currentPhaseFiber = null + // Did lifecycle hook schedule an update? This is often a performance problem, + // so we will keep track of it, and include it in the report. + // Track commits caused by cascading updates. + var isCommitting = false + var hasScheduledUpdateInCurrentCommit = false + var hasScheduledUpdateInCurrentPhase = false + var commitCountInCurrentWorkLoop = 0 + var effectCountInCurrentCommit = 0 + var isWaitingForCallback = false + // During commits, we only show a measurement once per method name + // to avoid stretch the commit phase with measurement overhead. + var labelsInCurrentCommit = new Set() + + var formatMarkName = function (markName) { + return reactEmoji + ' ' + markName + } - lowPriorityWarning$1(false, 'componentWillUpdate is deprecated and will be removed in the next major version. ' + 'Use componentDidUpdate instead. As a temporary workaround, ' + 'you can rename to UNSAFE_componentWillUpdate.' + '\n\nPlease update the following components: %s' + '\n\nLearn more about this warning here:' + '\nhttps://fb.me/react-async-component-lifecycle-hooks', _sortedNames2); + var formatLabel = function (label, warning$$1) { + var prefix = warning$$1 + ? warningEmoji + ' ' + : reactEmoji + ' ' + var suffix = warning$$1 ? ' Warning: ' + warning$$1 : '' + return '' + prefix + label + suffix + } - pendingComponentWillUpdateWarnings = []; - } - }; + var beginMark = function (markName) { + performance.mark(formatMarkName(markName)) + } - ReactStrictModeWarnings.recordDeprecationWarnings = function (fiber, instance) { - // Dedup strategy: Warn once per component. - if (didWarnAboutDeprecatedLifecycles.has(fiber.type)) { - return; - } + var clearMark = function (markName) { + performance.clearMarks(formatMarkName(markName)) + } - // Don't warn about react-lifecycles-compat polyfilled components. - if (typeof instance.componentWillMount === 'function' && instance.componentWillMount.__suppressDeprecationWarning !== true) { - pendingComponentWillMountWarnings.push(fiber); - } - if (typeof instance.componentWillReceiveProps === 'function' && instance.componentWillReceiveProps.__suppressDeprecationWarning !== true) { - pendingComponentWillReceivePropsWarnings.push(fiber); - } - if (typeof instance.componentWillUpdate === 'function' && instance.componentWillUpdate.__suppressDeprecationWarning !== true) { - pendingComponentWillUpdateWarnings.push(fiber); - } - }; - - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings = function (fiber, instance) { - var strictRoot = getStrictRoot(fiber); - - // Dedup strategy: Warn once per component. - // This is difficult to track any other way since component names - // are often vague and are likely to collide between 3rd party libraries. - // An expand property is probably okay to use here since it's DEV-only, - // and will only be set in the event of serious warnings. - if (didWarnAboutUnsafeLifecycles.has(fiber.type)) { - return; - } + var endMark = function (label, markName, warning$$1) { + var formattedMarkName = formatMarkName(markName) + var formattedLabel = formatLabel(label, warning$$1) + try { + performance.measure(formattedLabel, formattedMarkName) + } catch (err) {} + // If previous mark was missing for some reason, this will throw. + // This could only happen if React crashed in an unexpected place earlier. + // Don't pile on with more errors. + + // Clear marks immediately to avoid growing buffer. + performance.clearMarks(formattedMarkName) + performance.clearMeasures(formattedLabel) + } - // Don't warn about react-lifecycles-compat polyfilled components. - // Note that it is sufficient to check for the presence of a - // single lifecycle, componentWillMount, with the polyfill flag. - if (typeof instance.componentWillMount === 'function' && instance.componentWillMount.__suppressDeprecationWarning === true) { - return; - } + var getFiberMarkName = function (label, debugID) { + return label + ' (#' + debugID + ')' + } - var warningsForRoot = void 0; - if (!pendingUnsafeLifecycleWarnings.has(strictRoot)) { - warningsForRoot = { - UNSAFE_componentWillMount: [], - UNSAFE_componentWillReceiveProps: [], - UNSAFE_componentWillUpdate: [] - }; + var getFiberLabel = function (componentName, isMounted, phase) { + if (phase === null) { + // These are composite component total time measurements. + return ( + componentName + + ' [' + + (isMounted ? 'update' : 'mount') + + ']' + ) + } else { + // Composite component methods. + return componentName + '.' + phase + } + } - pendingUnsafeLifecycleWarnings.set(strictRoot, warningsForRoot); - } else { - warningsForRoot = pendingUnsafeLifecycleWarnings.get(strictRoot); - } + var beginFiberMark = function (fiber, phase) { + var componentName = getComponentName(fiber) || 'Unknown' + var debugID = fiber._debugID + var isMounted = fiber.alternate !== null + var label = getFiberLabel(componentName, isMounted, phase) + + if (isCommitting && labelsInCurrentCommit.has(label)) { + // During the commit phase, we don't show duplicate labels because + // there is a fixed overhead for every measurement, and we don't + // want to stretch the commit phase beyond necessary. + return false + } + labelsInCurrentCommit.add(label) + + var markName = getFiberMarkName(label, debugID) + beginMark(markName) + return true + } - var unsafeLifecycles = []; - if (typeof instance.componentWillMount === 'function' || typeof instance.UNSAFE_componentWillMount === 'function') { - unsafeLifecycles.push('UNSAFE_componentWillMount'); - } - if (typeof instance.componentWillReceiveProps === 'function' || typeof instance.UNSAFE_componentWillReceiveProps === 'function') { - unsafeLifecycles.push('UNSAFE_componentWillReceiveProps'); - } - if (typeof instance.componentWillUpdate === 'function' || typeof instance.UNSAFE_componentWillUpdate === 'function') { - unsafeLifecycles.push('UNSAFE_componentWillUpdate'); - } + var clearFiberMark = function (fiber, phase) { + var componentName = getComponentName(fiber) || 'Unknown' + var debugID = fiber._debugID + var isMounted = fiber.alternate !== null + var label = getFiberLabel(componentName, isMounted, phase) + var markName = getFiberMarkName(label, debugID) + clearMark(markName) + } - if (unsafeLifecycles.length > 0) { - unsafeLifecycles.forEach(function (lifecycle) { - warningsForRoot[lifecycle].push(fiber); - }); - } - }; -} - -// Exports ReactDOM.createRoot -var enableUserTimingAPI = true; - -// Mutating mode (React DOM, React ART, React Native): -var enableMutatingReconciler = true; -// Experimental noop mode (currently unused): -var enableNoopReconciler = false; -// Experimental persistent mode (Fabric): -var enablePersistentReconciler = false; -// Experimental error-boundary API that can recover from errors within a single -// render phase -var enableGetDerivedStateFromCatch = false; -// Helps identify side effects in begin-phase lifecycle hooks and setState reducers: -var debugRenderPhaseSideEffects = false; - -// In some cases, StrictMode should also double-render lifecycles. -// This can be confusing for tests though, -// And it can be bad for performance in production. -// This feature flag can be used to control the behavior: -var debugRenderPhaseSideEffectsForStrictMode = true; - -// To preserve the "Pause on caught exceptions" behavior of the debugger, we -// replay the begin phase of a failed component inside invokeGuardedCallback. -var replayFailedUnitOfWorkWithInvokeGuardedCallback = true; - -// Warn about deprecated, async-unsafe lifecycles; relates to RFC #6: -var warnAboutDeprecatedLifecycles = false; - -var alwaysUseRequestIdleCallbackPolyfill = false; - -// Only used in www builds. - -// Prefix measurements so that it's possible to filter them. -// Longer prefixes are hard to read in DevTools. -var reactEmoji = '\u269B'; -var warningEmoji = '\u26D4'; -var supportsUserTiming = typeof performance !== 'undefined' && typeof performance.mark === 'function' && typeof performance.clearMarks === 'function' && typeof performance.measure === 'function' && typeof performance.clearMeasures === 'function'; - -// Keep track of current fiber so that we know the path to unwind on pause. -// TODO: this looks the same as nextUnitOfWork in scheduler. Can we unify them? -var currentFiber = null; -// If we're in the middle of user code, which fiber and method is it? -// Reusing `currentFiber` would be confusing for this because user code fiber -// can change during commit phase too, but we don't need to unwind it (since -// lifecycles in the commit phase don't resemble a tree). -var currentPhase = null; -var currentPhaseFiber = null; -// Did lifecycle hook schedule an update? This is often a performance problem, -// so we will keep track of it, and include it in the report. -// Track commits caused by cascading updates. -var isCommitting = false; -var hasScheduledUpdateInCurrentCommit = false; -var hasScheduledUpdateInCurrentPhase = false; -var commitCountInCurrentWorkLoop = 0; -var effectCountInCurrentCommit = 0; -var isWaitingForCallback = false; -// During commits, we only show a measurement once per method name -// to avoid stretch the commit phase with measurement overhead. -var labelsInCurrentCommit = new Set(); - -var formatMarkName = function (markName) { - return reactEmoji + ' ' + markName; -}; - -var formatLabel = function (label, warning$$1) { - var prefix = warning$$1 ? warningEmoji + ' ' : reactEmoji + ' '; - var suffix = warning$$1 ? ' Warning: ' + warning$$1 : ''; - return '' + prefix + label + suffix; -}; - -var beginMark = function (markName) { - performance.mark(formatMarkName(markName)); -}; - -var clearMark = function (markName) { - performance.clearMarks(formatMarkName(markName)); -}; - -var endMark = function (label, markName, warning$$1) { - var formattedMarkName = formatMarkName(markName); - var formattedLabel = formatLabel(label, warning$$1); - try { - performance.measure(formattedLabel, formattedMarkName); - } catch (err) {} - // If previous mark was missing for some reason, this will throw. - // This could only happen if React crashed in an unexpected place earlier. - // Don't pile on with more errors. - - // Clear marks immediately to avoid growing buffer. - performance.clearMarks(formattedMarkName); - performance.clearMeasures(formattedLabel); -}; - -var getFiberMarkName = function (label, debugID) { - return label + ' (#' + debugID + ')'; -}; - -var getFiberLabel = function (componentName, isMounted, phase) { - if (phase === null) { - // These are composite component total time measurements. - return componentName + ' [' + (isMounted ? 'update' : 'mount') + ']'; - } else { - // Composite component methods. - return componentName + '.' + phase; - } -}; - -var beginFiberMark = function (fiber, phase) { - var componentName = getComponentName(fiber) || 'Unknown'; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - - if (isCommitting && labelsInCurrentCommit.has(label)) { - // During the commit phase, we don't show duplicate labels because - // there is a fixed overhead for every measurement, and we don't - // want to stretch the commit phase beyond necessary. - return false; - } - labelsInCurrentCommit.add(label); - - var markName = getFiberMarkName(label, debugID); - beginMark(markName); - return true; -}; - -var clearFiberMark = function (fiber, phase) { - var componentName = getComponentName(fiber) || 'Unknown'; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - var markName = getFiberMarkName(label, debugID); - clearMark(markName); -}; - -var endFiberMark = function (fiber, phase, warning$$1) { - var componentName = getComponentName(fiber) || 'Unknown'; - var debugID = fiber._debugID; - var isMounted = fiber.alternate !== null; - var label = getFiberLabel(componentName, isMounted, phase); - var markName = getFiberMarkName(label, debugID); - endMark(label, markName, warning$$1); -}; - -var shouldIgnoreFiber = function (fiber) { - // Host components should be skipped in the timeline. - // We could check typeof fiber.type, but does this work with RN? - switch (fiber.tag) { - case HostRoot: - case HostComponent: - case HostText: - case HostPortal: - case CallComponent: - case ReturnComponent: - case Fragment: - case ContextProvider: - case ContextConsumer: - case Mode: - return true; - default: - return false; - } -}; + var endFiberMark = function (fiber, phase, warning$$1) { + var componentName = getComponentName(fiber) || 'Unknown' + var debugID = fiber._debugID + var isMounted = fiber.alternate !== null + var label = getFiberLabel(componentName, isMounted, phase) + var markName = getFiberMarkName(label, debugID) + endMark(label, markName, warning$$1) + } -var clearPendingPhaseMeasurement = function () { - if (currentPhase !== null && currentPhaseFiber !== null) { - clearFiberMark(currentPhaseFiber, currentPhase); - } - currentPhaseFiber = null; - currentPhase = null; - hasScheduledUpdateInCurrentPhase = false; -}; - -var pauseTimers = function () { - // Stops all currently active measurements so that they can be resumed - // if we continue in a later deferred loop from the same unit of work. - var fiber = currentFiber; - while (fiber) { - if (fiber._debugIsCurrentlyTiming) { - endFiberMark(fiber, null, null); - } - fiber = fiber['return']; - } -}; + var shouldIgnoreFiber = function (fiber) { + // Host components should be skipped in the timeline. + // We could check typeof fiber.type, but does this work with RN? + switch (fiber.tag) { + case HostRoot: + case HostComponent: + case HostText: + case HostPortal: + case CallComponent: + case ReturnComponent: + case Fragment: + case ContextProvider: + case ContextConsumer: + case Mode: + return true + default: + return false + } + } -var resumeTimersRecursively = function (fiber) { - if (fiber['return'] !== null) { - resumeTimersRecursively(fiber['return']); - } - if (fiber._debugIsCurrentlyTiming) { - beginFiberMark(fiber, null); - } -}; + var clearPendingPhaseMeasurement = function () { + if (currentPhase !== null && currentPhaseFiber !== null) { + clearFiberMark(currentPhaseFiber, currentPhase) + } + currentPhaseFiber = null + currentPhase = null + hasScheduledUpdateInCurrentPhase = false + } -var resumeTimers = function () { - // Resumes all measurements that were active during the last deferred loop. - if (currentFiber !== null) { - resumeTimersRecursively(currentFiber); - } -}; + var pauseTimers = function () { + // Stops all currently active measurements so that they can be resumed + // if we continue in a later deferred loop from the same unit of work. + var fiber = currentFiber + while (fiber) { + if (fiber._debugIsCurrentlyTiming) { + endFiberMark(fiber, null, null) + } + fiber = fiber['return'] + } + } -function recordEffect() { - if (enableUserTimingAPI) { - effectCountInCurrentCommit++; - } -} + var resumeTimersRecursively = function (fiber) { + if (fiber['return'] !== null) { + resumeTimersRecursively(fiber['return']) + } + if (fiber._debugIsCurrentlyTiming) { + beginFiberMark(fiber, null) + } + } -function recordScheduleUpdate() { - if (enableUserTimingAPI) { - if (isCommitting) { - hasScheduledUpdateInCurrentCommit = true; - } - if (currentPhase !== null && currentPhase !== 'componentWillMount' && currentPhase !== 'componentWillReceiveProps') { - hasScheduledUpdateInCurrentPhase = true; - } - } -} - -function startRequestCallbackTimer() { - if (enableUserTimingAPI) { - if (supportsUserTiming && !isWaitingForCallback) { - isWaitingForCallback = true; - beginMark('(Waiting for async callback...)'); - } - } -} - -function stopRequestCallbackTimer(didExpire, expirationTime) { - if (enableUserTimingAPI) { - if (supportsUserTiming) { - isWaitingForCallback = false; - var warning$$1 = didExpire ? 'React was blocked by main thread' : null; - endMark('(Waiting for async callback... will force flush in ' + expirationTime + ' ms)', '(Waiting for async callback...)', warning$$1); - } - } -} - -function startWorkTimer(fiber) { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // If we pause, this is the fiber to unwind from. - currentFiber = fiber; - if (!beginFiberMark(fiber, null)) { - return; - } - fiber._debugIsCurrentlyTiming = true; - } -} - -function cancelWorkTimer(fiber) { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // Remember we shouldn't complete measurement for this fiber. - // Otherwise flamechart will be deep even for small updates. - fiber._debugIsCurrentlyTiming = false; - clearFiberMark(fiber, null); - } -} + var resumeTimers = function () { + // Resumes all measurements that were active during the last deferred loop. + if (currentFiber !== null) { + resumeTimersRecursively(currentFiber) + } + } -function stopWorkTimer(fiber) { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // If we pause, its parent is the fiber to unwind from. - currentFiber = fiber['return']; - if (!fiber._debugIsCurrentlyTiming) { - return; - } - fiber._debugIsCurrentlyTiming = false; - endFiberMark(fiber, null, null); - } -} + function recordEffect() { + if (enableUserTimingAPI) { + effectCountInCurrentCommit++ + } + } -function stopFailedWorkTimer(fiber) { - if (enableUserTimingAPI) { - if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { - return; - } - // If we pause, its parent is the fiber to unwind from. - currentFiber = fiber['return']; - if (!fiber._debugIsCurrentlyTiming) { - return; - } - fiber._debugIsCurrentlyTiming = false; - var warning$$1 = 'An error was thrown inside this error boundary'; - endFiberMark(fiber, null, warning$$1); - } -} + function recordScheduleUpdate() { + if (enableUserTimingAPI) { + if (isCommitting) { + hasScheduledUpdateInCurrentCommit = true + } + if ( + currentPhase !== null && + currentPhase !== 'componentWillMount' && + currentPhase !== 'componentWillReceiveProps' + ) { + hasScheduledUpdateInCurrentPhase = true + } + } + } -function startPhaseTimer(fiber, phase) { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - clearPendingPhaseMeasurement(); - if (!beginFiberMark(fiber, phase)) { - return; - } - currentPhaseFiber = fiber; - currentPhase = phase; - } -} + function startRequestCallbackTimer() { + if (enableUserTimingAPI) { + if (supportsUserTiming && !isWaitingForCallback) { + isWaitingForCallback = true + beginMark('(Waiting for async callback...)') + } + } + } -function stopPhaseTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - if (currentPhase !== null && currentPhaseFiber !== null) { - var warning$$1 = hasScheduledUpdateInCurrentPhase ? 'Scheduled a cascading update' : null; - endFiberMark(currentPhaseFiber, currentPhase, warning$$1); - } - currentPhase = null; - currentPhaseFiber = null; - } -} + function stopRequestCallbackTimer(didExpire, expirationTime) { + if (enableUserTimingAPI) { + if (supportsUserTiming) { + isWaitingForCallback = false + var warning$$1 = didExpire + ? 'React was blocked by main thread' + : null + endMark( + '(Waiting for async callback... will force flush in ' + + expirationTime + + ' ms)', + '(Waiting for async callback...)', + warning$$1 + ) + } + } + } -function startWorkLoopTimer(nextUnitOfWork) { - if (enableUserTimingAPI) { - currentFiber = nextUnitOfWork; - if (!supportsUserTiming) { - return; - } - commitCountInCurrentWorkLoop = 0; - // This is top level call. - // Any other measurements are performed within. - beginMark('(React Tree Reconciliation)'); - // Resume any measurements that were in progress during the last loop. - resumeTimers(); - } -} + function startWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return + } + // If we pause, this is the fiber to unwind from. + currentFiber = fiber + if (!beginFiberMark(fiber, null)) { + return + } + fiber._debugIsCurrentlyTiming = true + } + } -function stopWorkLoopTimer(interruptedBy, didCompleteRoot) { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - var warning$$1 = null; - if (interruptedBy !== null) { - if (interruptedBy.tag === HostRoot) { - warning$$1 = 'A top-level update interrupted the previous render'; - } else { - var componentName = getComponentName(interruptedBy) || 'Unknown'; - warning$$1 = 'An update to ' + componentName + ' interrupted the previous render'; - } - } else if (commitCountInCurrentWorkLoop > 1) { - warning$$1 = 'There were cascading updates'; - } - commitCountInCurrentWorkLoop = 0; - var label = didCompleteRoot ? '(React Tree Reconciliation: Completed Root)' : '(React Tree Reconciliation: Yielded)'; - // Pause any measurements until the next loop. - pauseTimers(); - endMark(label, '(React Tree Reconciliation)', warning$$1); - } -} + function cancelWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return + } + // Remember we shouldn't complete measurement for this fiber. + // Otherwise flamechart will be deep even for small updates. + fiber._debugIsCurrentlyTiming = false + clearFiberMark(fiber, null) + } + } -function startCommitTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - isCommitting = true; - hasScheduledUpdateInCurrentCommit = false; - labelsInCurrentCommit.clear(); - beginMark('(Committing Changes)'); - } -} + function stopWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return + } + // If we pause, its parent is the fiber to unwind from. + currentFiber = fiber['return'] + if (!fiber._debugIsCurrentlyTiming) { + return + } + fiber._debugIsCurrentlyTiming = false + endFiberMark(fiber, null, null) + } + } -function stopCommitTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } + function stopFailedWorkTimer(fiber) { + if (enableUserTimingAPI) { + if (!supportsUserTiming || shouldIgnoreFiber(fiber)) { + return + } + // If we pause, its parent is the fiber to unwind from. + currentFiber = fiber['return'] + if (!fiber._debugIsCurrentlyTiming) { + return + } + fiber._debugIsCurrentlyTiming = false + var warning$$1 = + 'An error was thrown inside this error boundary' + endFiberMark(fiber, null, warning$$1) + } + } - var warning$$1 = null; - if (hasScheduledUpdateInCurrentCommit) { - warning$$1 = 'Lifecycle hook scheduled a cascading update'; - } else if (commitCountInCurrentWorkLoop > 0) { - warning$$1 = 'Caused by a cascading update in earlier commit'; - } - hasScheduledUpdateInCurrentCommit = false; - commitCountInCurrentWorkLoop++; - isCommitting = false; - labelsInCurrentCommit.clear(); + function startPhaseTimer(fiber, phase) { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return + } + clearPendingPhaseMeasurement() + if (!beginFiberMark(fiber, phase)) { + return + } + currentPhaseFiber = fiber + currentPhase = phase + } + } - endMark('(Committing Changes)', '(Committing Changes)', warning$$1); - } -} + function stopPhaseTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return + } + if (currentPhase !== null && currentPhaseFiber !== null) { + var warning$$1 = hasScheduledUpdateInCurrentPhase + ? 'Scheduled a cascading update' + : null + endFiberMark(currentPhaseFiber, currentPhase, warning$$1) + } + currentPhase = null + currentPhaseFiber = null + } + } -function startCommitSnapshotEffectsTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - effectCountInCurrentCommit = 0; - beginMark('(Committing Snapshot Effects)'); - } -} + function startWorkLoopTimer(nextUnitOfWork) { + if (enableUserTimingAPI) { + currentFiber = nextUnitOfWork + if (!supportsUserTiming) { + return + } + commitCountInCurrentWorkLoop = 0 + // This is top level call. + // Any other measurements are performed within. + beginMark('(React Tree Reconciliation)') + // Resume any measurements that were in progress during the last loop. + resumeTimers() + } + } -function stopCommitSnapshotEffectsTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark('(Committing Snapshot Effects: ' + count + ' Total)', '(Committing Snapshot Effects)', null); - } -} + function stopWorkLoopTimer(interruptedBy, didCompleteRoot) { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return + } + var warning$$1 = null + if (interruptedBy !== null) { + if (interruptedBy.tag === HostRoot) { + warning$$1 = + 'A top-level update interrupted the previous render' + } else { + var componentName = + getComponentName(interruptedBy) || 'Unknown' + warning$$1 = + 'An update to ' + + componentName + + ' interrupted the previous render' + } + } else if (commitCountInCurrentWorkLoop > 1) { + warning$$1 = 'There were cascading updates' + } + commitCountInCurrentWorkLoop = 0 + var label = didCompleteRoot + ? '(React Tree Reconciliation: Completed Root)' + : '(React Tree Reconciliation: Yielded)' + // Pause any measurements until the next loop. + pauseTimers() + endMark(label, '(React Tree Reconciliation)', warning$$1) + } + } -function startCommitHostEffectsTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - effectCountInCurrentCommit = 0; - beginMark('(Committing Host Effects)'); - } -} + function startCommitTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return + } + isCommitting = true + hasScheduledUpdateInCurrentCommit = false + labelsInCurrentCommit.clear() + beginMark('(Committing Changes)') + } + } -function stopCommitHostEffectsTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark('(Committing Host Effects: ' + count + ' Total)', '(Committing Host Effects)', null); - } -} + function stopCommitTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return + } + + var warning$$1 = null + if (hasScheduledUpdateInCurrentCommit) { + warning$$1 = 'Lifecycle hook scheduled a cascading update' + } else if (commitCountInCurrentWorkLoop > 0) { + warning$$1 = + 'Caused by a cascading update in earlier commit' + } + hasScheduledUpdateInCurrentCommit = false + commitCountInCurrentWorkLoop++ + isCommitting = false + labelsInCurrentCommit.clear() + + endMark( + '(Committing Changes)', + '(Committing Changes)', + warning$$1 + ) + } + } -function startCommitLifeCyclesTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - effectCountInCurrentCommit = 0; - beginMark('(Calling Lifecycle Methods)'); - } -} + function startCommitSnapshotEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return + } + effectCountInCurrentCommit = 0 + beginMark('(Committing Snapshot Effects)') + } + } -function stopCommitLifeCyclesTimer() { - if (enableUserTimingAPI) { - if (!supportsUserTiming) { - return; - } - var count = effectCountInCurrentCommit; - effectCountInCurrentCommit = 0; - endMark('(Calling Lifecycle Methods: ' + count + ' Total)', '(Calling Lifecycle Methods)', null); - } -} - -var didWarnUpdateInsideUpdate = void 0; - -{ - didWarnUpdateInsideUpdate = false; -} - -// Callbacks are not validated until invocation - - -// Singly linked-list of updates. When an update is scheduled, it is added to -// the queue of the current fiber and the work-in-progress fiber. The two queues -// are separate but they share a persistent structure. -// -// During reconciliation, updates are removed from the work-in-progress fiber, -// but they remain on the current fiber. That ensures that if a work-in-progress -// is aborted, the aborted updates are recovered by cloning from current. -// -// The work-in-progress queue is always a subset of the current queue. -// -// When the tree is committed, the work-in-progress becomes the current. - - -function createUpdateQueue(baseState) { - var queue = { - baseState: baseState, - expirationTime: NoWork, - first: null, - last: null, - callbackList: null, - hasForceUpdate: false, - isInitialized: false, - capturedValues: null - }; - { - queue.isProcessing = false; - } - return queue; -} - -function insertUpdateIntoQueue(queue, update) { - // Append the update to the end of the list. - if (queue.last === null) { - // Queue is empty - queue.first = queue.last = update; - } else { - queue.last.next = update; - queue.last = update; - } - if (queue.expirationTime === NoWork || queue.expirationTime > update.expirationTime) { - queue.expirationTime = update.expirationTime; - } -} - -var q1 = void 0; -var q2 = void 0; -function ensureUpdateQueues(fiber) { - q1 = q2 = null; - // We'll have at least one and at most two distinct update queues. - var alternateFiber = fiber.alternate; - var queue1 = fiber.updateQueue; - if (queue1 === null) { - // TODO: We don't know what the base state will be until we begin work. - // It depends on which fiber is the next current. Initialize with an empty - // base state, then set to the memoizedState when rendering. Not super - // happy with this approach. - queue1 = fiber.updateQueue = createUpdateQueue(null); - } + function stopCommitSnapshotEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return + } + var count = effectCountInCurrentCommit + effectCountInCurrentCommit = 0 + endMark( + '(Committing Snapshot Effects: ' + count + ' Total)', + '(Committing Snapshot Effects)', + null + ) + } + } - var queue2 = void 0; - if (alternateFiber !== null) { - queue2 = alternateFiber.updateQueue; - if (queue2 === null) { - queue2 = alternateFiber.updateQueue = createUpdateQueue(null); - } - } else { - queue2 = null; - } - queue2 = queue2 !== queue1 ? queue2 : null; - - // Use module variables instead of returning a tuple - q1 = queue1; - q2 = queue2; -} - -function insertUpdateIntoFiber(fiber, update) { - ensureUpdateQueues(fiber); - var queue1 = q1; - var queue2 = q2; - - // Warn if an update is scheduled from inside an updater function. - { - if ((queue1.isProcessing || queue2 !== null && queue2.isProcessing) && !didWarnUpdateInsideUpdate) { - warning(false, 'An update (setState, replaceState, or forceUpdate) was scheduled ' + 'from inside an update function. Update functions should be pure, ' + 'with zero side-effects. Consider using componentDidUpdate or a ' + 'callback.'); - didWarnUpdateInsideUpdate = true; - } - } + function startCommitHostEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return + } + effectCountInCurrentCommit = 0 + beginMark('(Committing Host Effects)') + } + } - // If there's only one queue, add the update to that queue and exit. - if (queue2 === null) { - insertUpdateIntoQueue(queue1, update); - return; - } + function stopCommitHostEffectsTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return + } + var count = effectCountInCurrentCommit + effectCountInCurrentCommit = 0 + endMark( + '(Committing Host Effects: ' + count + ' Total)', + '(Committing Host Effects)', + null + ) + } + } - // If either queue is empty, we need to add to both queues. - if (queue1.last === null || queue2.last === null) { - insertUpdateIntoQueue(queue1, update); - insertUpdateIntoQueue(queue2, update); - return; - } + function startCommitLifeCyclesTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return + } + effectCountInCurrentCommit = 0 + beginMark('(Calling Lifecycle Methods)') + } + } - // If both lists are not empty, the last update is the same for both lists - // because of structural sharing. So, we should only append to one of - // the lists. - insertUpdateIntoQueue(queue1, update); - // But we still need to update the `last` pointer of queue2. - queue2.last = update; -} - -function getUpdateExpirationTime(fiber) { - switch (fiber.tag) { - case HostRoot: - case ClassComponent: - var updateQueue = fiber.updateQueue; - if (updateQueue === null) { - return NoWork; - } - return updateQueue.expirationTime; - default: - return NoWork; - } -} + function stopCommitLifeCyclesTimer() { + if (enableUserTimingAPI) { + if (!supportsUserTiming) { + return + } + var count = effectCountInCurrentCommit + effectCountInCurrentCommit = 0 + endMark( + '(Calling Lifecycle Methods: ' + count + ' Total)', + '(Calling Lifecycle Methods)', + null + ) + } + } -function getStateFromUpdate(update, instance, prevState, props) { - var partialState = update.partialState; - if (typeof partialState === 'function') { - return partialState.call(instance, prevState, props); - } else { - return partialState; - } -} - -function processUpdateQueue(current, workInProgress, queue, instance, props, renderExpirationTime) { - if (current !== null && current.updateQueue === queue) { - // We need to create a work-in-progress queue, by cloning the current queue. - var currentQueue = queue; - queue = workInProgress.updateQueue = { - baseState: currentQueue.baseState, - expirationTime: currentQueue.expirationTime, - first: currentQueue.first, - last: currentQueue.last, - isInitialized: currentQueue.isInitialized, - capturedValues: currentQueue.capturedValues, - // These fields are no longer valid because they were already committed. - // Reset them. - callbackList: null, - hasForceUpdate: false - }; - } + var didWarnUpdateInsideUpdate = void 0 - { - // Set this flag so we can warn if setState is called inside the update - // function of another setState. - queue.isProcessing = true; - } + { + didWarnUpdateInsideUpdate = false + } - // Reset the remaining expiration time. If we skip over any updates, we'll - // increase this accordingly. - queue.expirationTime = NoWork; - - // TODO: We don't know what the base state will be until we begin work. - // It depends on which fiber is the next current. Initialize with an empty - // base state, then set to the memoizedState when rendering. Not super - // happy with this approach. - var state = void 0; - if (queue.isInitialized) { - state = queue.baseState; - } else { - state = queue.baseState = workInProgress.memoizedState; - queue.isInitialized = true; - } - var dontMutatePrevState = true; - var update = queue.first; - var didSkip = false; - while (update !== null) { - var updateExpirationTime = update.expirationTime; - if (updateExpirationTime > renderExpirationTime) { - // This update does not have sufficient priority. Skip it. - var remainingExpirationTime = queue.expirationTime; - if (remainingExpirationTime === NoWork || remainingExpirationTime > updateExpirationTime) { - // Update the remaining expiration time. - queue.expirationTime = updateExpirationTime; - } - if (!didSkip) { - didSkip = true; - queue.baseState = state; - } - // Continue to the next update. - update = update.next; - continue; - } + // Callbacks are not validated until invocation + + // Singly linked-list of updates. When an update is scheduled, it is added to + // the queue of the current fiber and the work-in-progress fiber. The two queues + // are separate but they share a persistent structure. + // + // During reconciliation, updates are removed from the work-in-progress fiber, + // but they remain on the current fiber. That ensures that if a work-in-progress + // is aborted, the aborted updates are recovered by cloning from current. + // + // The work-in-progress queue is always a subset of the current queue. + // + // When the tree is committed, the work-in-progress becomes the current. + + function createUpdateQueue(baseState) { + var queue = { + baseState: baseState, + expirationTime: NoWork, + first: null, + last: null, + callbackList: null, + hasForceUpdate: false, + isInitialized: false, + capturedValues: null, + } + { + queue.isProcessing = false + } + return queue + } - // This update does have sufficient priority. + function insertUpdateIntoQueue(queue, update) { + // Append the update to the end of the list. + if (queue.last === null) { + // Queue is empty + queue.first = queue.last = update + } else { + queue.last.next = update + queue.last = update + } + if ( + queue.expirationTime === NoWork || + queue.expirationTime > update.expirationTime + ) { + queue.expirationTime = update.expirationTime + } + } - // If no previous updates were skipped, drop this update from the queue by - // advancing the head of the list. - if (!didSkip) { - queue.first = update.next; - if (queue.first === null) { - queue.last = null; - } - } + var q1 = void 0 + var q2 = void 0 + function ensureUpdateQueues(fiber) { + q1 = q2 = null + // We'll have at least one and at most two distinct update queues. + var alternateFiber = fiber.alternate + var queue1 = fiber.updateQueue + if (queue1 === null) { + // TODO: We don't know what the base state will be until we begin work. + // It depends on which fiber is the next current. Initialize with an empty + // base state, then set to the memoizedState when rendering. Not super + // happy with this approach. + queue1 = fiber.updateQueue = createUpdateQueue(null) + } + + var queue2 = void 0 + if (alternateFiber !== null) { + queue2 = alternateFiber.updateQueue + if (queue2 === null) { + queue2 = alternateFiber.updateQueue = createUpdateQueue( + null + ) + } + } else { + queue2 = null + } + queue2 = queue2 !== queue1 ? queue2 : null + + // Use module variables instead of returning a tuple + q1 = queue1 + q2 = queue2 + } - // Invoke setState callback an extra time to help detect side-effects. - // Ignore the return value in this case. - if (debugRenderPhaseSideEffects || debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictMode) { - getStateFromUpdate(update, instance, state, props); - } + function insertUpdateIntoFiber(fiber, update) { + ensureUpdateQueues(fiber) + var queue1 = q1 + var queue2 = q2 + + // Warn if an update is scheduled from inside an updater function. + { + if ( + (queue1.isProcessing || + (queue2 !== null && queue2.isProcessing)) && + !didWarnUpdateInsideUpdate + ) { + warning( + false, + 'An update (setState, replaceState, or forceUpdate) was scheduled ' + + 'from inside an update function. Update functions should be pure, ' + + 'with zero side-effects. Consider using componentDidUpdate or a ' + + 'callback.' + ) + didWarnUpdateInsideUpdate = true + } + } + + // If there's only one queue, add the update to that queue and exit. + if (queue2 === null) { + insertUpdateIntoQueue(queue1, update) + return + } + + // If either queue is empty, we need to add to both queues. + if (queue1.last === null || queue2.last === null) { + insertUpdateIntoQueue(queue1, update) + insertUpdateIntoQueue(queue2, update) + return + } + + // If both lists are not empty, the last update is the same for both lists + // because of structural sharing. So, we should only append to one of + // the lists. + insertUpdateIntoQueue(queue1, update) + // But we still need to update the `last` pointer of queue2. + queue2.last = update + } - // Process the update - var _partialState = void 0; - if (update.isReplace) { - state = getStateFromUpdate(update, instance, state, props); - dontMutatePrevState = true; - } else { - _partialState = getStateFromUpdate(update, instance, state, props); - if (_partialState) { - if (dontMutatePrevState) { - // $FlowFixMe: Idk how to type this properly. - state = _assign({}, state, _partialState); - } else { - state = _assign(state, _partialState); - } - dontMutatePrevState = false; - } - } - if (update.isForced) { - queue.hasForceUpdate = true; - } - if (update.callback !== null) { - // Append to list of callbacks. - var _callbackList = queue.callbackList; - if (_callbackList === null) { - _callbackList = queue.callbackList = []; - } - _callbackList.push(update); - } - if (update.capturedValue !== null) { - var _capturedValues = queue.capturedValues; - if (_capturedValues === null) { - queue.capturedValues = [update.capturedValue]; - } else { - _capturedValues.push(update.capturedValue); - } - } - update = update.next; - } + function getUpdateExpirationTime(fiber) { + switch (fiber.tag) { + case HostRoot: + case ClassComponent: + var updateQueue = fiber.updateQueue + if (updateQueue === null) { + return NoWork + } + return updateQueue.expirationTime + default: + return NoWork + } + } - if (queue.callbackList !== null) { - workInProgress.effectTag |= Callback; - } else if (queue.first === null && !queue.hasForceUpdate && queue.capturedValues === null) { - // The queue is empty. We can reset it. - workInProgress.updateQueue = null; - } + function getStateFromUpdate( + update, + instance, + prevState, + props + ) { + var partialState = update.partialState + if (typeof partialState === 'function') { + return partialState.call(instance, prevState, props) + } else { + return partialState + } + } - if (!didSkip) { - didSkip = true; - queue.baseState = state; - } + function processUpdateQueue( + current, + workInProgress, + queue, + instance, + props, + renderExpirationTime + ) { + if (current !== null && current.updateQueue === queue) { + // We need to create a work-in-progress queue, by cloning the current queue. + var currentQueue = queue + queue = workInProgress.updateQueue = { + baseState: currentQueue.baseState, + expirationTime: currentQueue.expirationTime, + first: currentQueue.first, + last: currentQueue.last, + isInitialized: currentQueue.isInitialized, + capturedValues: currentQueue.capturedValues, + // These fields are no longer valid because they were already committed. + // Reset them. + callbackList: null, + hasForceUpdate: false, + } + } + + { + // Set this flag so we can warn if setState is called inside the update + // function of another setState. + queue.isProcessing = true + } + + // Reset the remaining expiration time. If we skip over any updates, we'll + // increase this accordingly. + queue.expirationTime = NoWork + + // TODO: We don't know what the base state will be until we begin work. + // It depends on which fiber is the next current. Initialize with an empty + // base state, then set to the memoizedState when rendering. Not super + // happy with this approach. + var state = void 0 + if (queue.isInitialized) { + state = queue.baseState + } else { + state = queue.baseState = workInProgress.memoizedState + queue.isInitialized = true + } + var dontMutatePrevState = true + var update = queue.first + var didSkip = false + while (update !== null) { + var updateExpirationTime = update.expirationTime + if (updateExpirationTime > renderExpirationTime) { + // This update does not have sufficient priority. Skip it. + var remainingExpirationTime = queue.expirationTime + if ( + remainingExpirationTime === NoWork || + remainingExpirationTime > updateExpirationTime + ) { + // Update the remaining expiration time. + queue.expirationTime = updateExpirationTime + } + if (!didSkip) { + didSkip = true + queue.baseState = state + } + // Continue to the next update. + update = update.next + continue + } + + // This update does have sufficient priority. + + // If no previous updates were skipped, drop this update from the queue by + // advancing the head of the list. + if (!didSkip) { + queue.first = update.next + if (queue.first === null) { + queue.last = null + } + } + + // Invoke setState callback an extra time to help detect side-effects. + // Ignore the return value in this case. + if ( + debugRenderPhaseSideEffects || + (debugRenderPhaseSideEffectsForStrictMode && + workInProgress.mode & StrictMode) + ) { + getStateFromUpdate(update, instance, state, props) + } + + // Process the update + var _partialState = void 0 + if (update.isReplace) { + state = getStateFromUpdate(update, instance, state, props) + dontMutatePrevState = true + } else { + _partialState = getStateFromUpdate( + update, + instance, + state, + props + ) + if (_partialState) { + if (dontMutatePrevState) { + // $FlowFixMe: Idk how to type this properly. + state = _assign({}, state, _partialState) + } else { + state = _assign(state, _partialState) + } + dontMutatePrevState = false + } + } + if (update.isForced) { + queue.hasForceUpdate = true + } + if (update.callback !== null) { + // Append to list of callbacks. + var _callbackList = queue.callbackList + if (_callbackList === null) { + _callbackList = queue.callbackList = [] + } + _callbackList.push(update) + } + if (update.capturedValue !== null) { + var _capturedValues = queue.capturedValues + if (_capturedValues === null) { + queue.capturedValues = [update.capturedValue] + } else { + _capturedValues.push(update.capturedValue) + } + } + update = update.next + } + + if (queue.callbackList !== null) { + workInProgress.effectTag |= Callback + } else if ( + queue.first === null && + !queue.hasForceUpdate && + queue.capturedValues === null + ) { + // The queue is empty. We can reset it. + workInProgress.updateQueue = null + } + + if (!didSkip) { + didSkip = true + queue.baseState = state + } + + { + // No longer processing. + queue.isProcessing = false + } + + return state + } - { - // No longer processing. - queue.isProcessing = false; - } + function commitCallbacks(queue, context) { + var callbackList = queue.callbackList + if (callbackList === null) { + return + } + // Set the list to null to make sure they don't get called more than once. + queue.callbackList = null + for (var i = 0; i < callbackList.length; i++) { + var update = callbackList[i] + var _callback = update.callback + // This update might be processed again. Clear the callback so it's only + // called once. + update.callback = null + !(typeof _callback === 'function') + ? invariant( + false, + 'Invalid argument passed as callback. Expected a function. Instead received: %s', + _callback + ) + : void 0 + _callback.call(context) + } + } - return state; -} + var fakeInternalInstance = {} + var isArray = Array.isArray + + var didWarnAboutStateAssignmentForComponent = void 0 + var didWarnAboutUndefinedDerivedState = void 0 + var didWarnAboutUninitializedState = void 0 + var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = void 0 + var didWarnAboutLegacyLifecyclesAndDerivedState = void 0 + var warnOnInvalidCallback$1 = void 0 + + { + didWarnAboutStateAssignmentForComponent = new Set() + didWarnAboutUndefinedDerivedState = new Set() + didWarnAboutUninitializedState = new Set() + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set() + didWarnAboutLegacyLifecyclesAndDerivedState = new Set() + + var didWarnOnInvalidCallback = new Set() + + warnOnInvalidCallback$1 = function (callback, callerName) { + if (callback === null || typeof callback === 'function') { + return + } + var key = callerName + '_' + callback + if (!didWarnOnInvalidCallback.has(key)) { + didWarnOnInvalidCallback.add(key) + warning( + false, + '%s(...): Expected the last optional `callback` argument to be a ' + + 'function. Instead received: %s.', + callerName, + callback + ) + } + } + + // This is so gross but it's at least non-critical and can be removed if + // it causes problems. This is meant to give a nicer error message for + // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, + // ...)) which otherwise throws a "_processChildContext is not a function" + // exception. + Object.defineProperty( + fakeInternalInstance, + '_processChildContext', + { + enumerable: false, + value: function () { + invariant( + false, + "_processChildContext is not available in React 16+. This likely means you have multiple copies of React and are attempting to nest a React 15 tree inside a React 16 tree using unstable_renderSubtreeIntoContainer, which isn't supported. Try to make sure you have only one copy of React (and ideally, switch to ReactDOM.createPortal)." + ) + }, + } + ) + Object.freeze(fakeInternalInstance) + } + function callGetDerivedStateFromCatch(ctor, capturedValues) { + var resultState = {} + for (var i = 0; i < capturedValues.length; i++) { + var capturedValue = capturedValues[i] + var error = capturedValue.value + var partialState = ctor.getDerivedStateFromCatch.call( + null, + error + ) + if (partialState !== null && partialState !== undefined) { + _assign(resultState, partialState) + } + } + return resultState + } -function commitCallbacks(queue, context) { - var callbackList = queue.callbackList; - if (callbackList === null) { - return; - } - // Set the list to null to make sure they don't get called more than once. - queue.callbackList = null; - for (var i = 0; i < callbackList.length; i++) { - var update = callbackList[i]; - var _callback = update.callback; - // This update might be processed again. Clear the callback so it's only - // called once. - update.callback = null; - !(typeof _callback === 'function') ? invariant(false, 'Invalid argument passed as callback. Expected a function. Instead received: %s', _callback) : void 0; - _callback.call(context); - } -} - -var fakeInternalInstance = {}; -var isArray = Array.isArray; - -var didWarnAboutStateAssignmentForComponent = void 0; -var didWarnAboutUndefinedDerivedState = void 0; -var didWarnAboutUninitializedState = void 0; -var didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = void 0; -var didWarnAboutLegacyLifecyclesAndDerivedState = void 0; -var warnOnInvalidCallback$1 = void 0; - -{ - didWarnAboutStateAssignmentForComponent = new Set(); - didWarnAboutUndefinedDerivedState = new Set(); - didWarnAboutUninitializedState = new Set(); - didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate = new Set(); - didWarnAboutLegacyLifecyclesAndDerivedState = new Set(); - - var didWarnOnInvalidCallback = new Set(); - - warnOnInvalidCallback$1 = function (callback, callerName) { - if (callback === null || typeof callback === 'function') { - return; - } - var key = callerName + '_' + callback; - if (!didWarnOnInvalidCallback.has(key)) { - didWarnOnInvalidCallback.add(key); - warning(false, '%s(...): Expected the last optional `callback` argument to be a ' + 'function. Instead received: %s.', callerName, callback); - } - }; - - // This is so gross but it's at least non-critical and can be removed if - // it causes problems. This is meant to give a nicer error message for - // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component, - // ...)) which otherwise throws a "_processChildContext is not a function" - // exception. - Object.defineProperty(fakeInternalInstance, '_processChildContext', { - enumerable: false, - value: function () { - invariant(false, '_processChildContext is not available in React 16+. This likely means you have multiple copies of React and are attempting to nest a React 15 tree inside a React 16 tree using unstable_renderSubtreeIntoContainer, which isn\'t supported. Try to make sure you have only one copy of React (and ideally, switch to ReactDOM.createPortal).'); - } - }); - Object.freeze(fakeInternalInstance); -} -function callGetDerivedStateFromCatch(ctor, capturedValues) { - var resultState = {}; - for (var i = 0; i < capturedValues.length; i++) { - var capturedValue = capturedValues[i]; - var error = capturedValue.value; - var partialState = ctor.getDerivedStateFromCatch.call(null, error); - if (partialState !== null && partialState !== undefined) { - _assign(resultState, partialState); - } - } - return resultState; -} - -var ReactFiberClassComponent = function (legacyContext, scheduleWork, computeExpirationForFiber, memoizeProps, memoizeState) { - var cacheContext = legacyContext.cacheContext, - getMaskedContext = legacyContext.getMaskedContext, - getUnmaskedContext = legacyContext.getUnmaskedContext, - isContextConsumer = legacyContext.isContextConsumer, - hasContextChanged = legacyContext.hasContextChanged; - - // Class component state updater - - var updater = { - isMounted: isMounted, - enqueueSetState: function (instance, partialState, callback) { - var fiber = get(instance); - callback = callback === undefined ? null : callback; - { - warnOnInvalidCallback$1(callback, 'setState'); - } - var expirationTime = computeExpirationForFiber(fiber); - var update = { - expirationTime: expirationTime, - partialState: partialState, - callback: callback, - isReplace: false, - isForced: false, - capturedValue: null, - next: null - }; - insertUpdateIntoFiber(fiber, update); - scheduleWork(fiber, expirationTime); - }, - enqueueReplaceState: function (instance, state, callback) { - var fiber = get(instance); - callback = callback === undefined ? null : callback; - { - warnOnInvalidCallback$1(callback, 'replaceState'); - } - var expirationTime = computeExpirationForFiber(fiber); - var update = { - expirationTime: expirationTime, - partialState: state, - callback: callback, - isReplace: true, - isForced: false, - capturedValue: null, - next: null - }; - insertUpdateIntoFiber(fiber, update); - scheduleWork(fiber, expirationTime); - }, - enqueueForceUpdate: function (instance, callback) { - var fiber = get(instance); - callback = callback === undefined ? null : callback; - { - warnOnInvalidCallback$1(callback, 'forceUpdate'); - } - var expirationTime = computeExpirationForFiber(fiber); - var update = { - expirationTime: expirationTime, - partialState: null, - callback: callback, - isReplace: false, - isForced: true, - capturedValue: null, - next: null - }; - insertUpdateIntoFiber(fiber, update); - scheduleWork(fiber, expirationTime); - } - }; + var ReactFiberClassComponent = function ( + legacyContext, + scheduleWork, + computeExpirationForFiber, + memoizeProps, + memoizeState + ) { + var cacheContext = legacyContext.cacheContext, + getMaskedContext = legacyContext.getMaskedContext, + getUnmaskedContext = legacyContext.getUnmaskedContext, + isContextConsumer = legacyContext.isContextConsumer, + hasContextChanged = legacyContext.hasContextChanged + + // Class component state updater + + var updater = { + isMounted: isMounted, + enqueueSetState: function ( + instance, + partialState, + callback + ) { + var fiber = get(instance) + callback = callback === undefined ? null : callback + { + warnOnInvalidCallback$1(callback, 'setState') + } + var expirationTime = computeExpirationForFiber(fiber) + var update = { + expirationTime: expirationTime, + partialState: partialState, + callback: callback, + isReplace: false, + isForced: false, + capturedValue: null, + next: null, + } + insertUpdateIntoFiber(fiber, update) + scheduleWork(fiber, expirationTime) + }, + enqueueReplaceState: function (instance, state, callback) { + var fiber = get(instance) + callback = callback === undefined ? null : callback + { + warnOnInvalidCallback$1(callback, 'replaceState') + } + var expirationTime = computeExpirationForFiber(fiber) + var update = { + expirationTime: expirationTime, + partialState: state, + callback: callback, + isReplace: true, + isForced: false, + capturedValue: null, + next: null, + } + insertUpdateIntoFiber(fiber, update) + scheduleWork(fiber, expirationTime) + }, + enqueueForceUpdate: function (instance, callback) { + var fiber = get(instance) + callback = callback === undefined ? null : callback + { + warnOnInvalidCallback$1(callback, 'forceUpdate') + } + var expirationTime = computeExpirationForFiber(fiber) + var update = { + expirationTime: expirationTime, + partialState: null, + callback: callback, + isReplace: false, + isForced: true, + capturedValue: null, + next: null, + } + insertUpdateIntoFiber(fiber, update) + scheduleWork(fiber, expirationTime) + }, + } + + function checkShouldComponentUpdate( + workInProgress, + oldProps, + newProps, + oldState, + newState, + newContext + ) { + if ( + oldProps === null || + (workInProgress.updateQueue !== null && + workInProgress.updateQueue.hasForceUpdate) + ) { + // If the workInProgress already has an Update effect, return true + return true + } + + var instance = workInProgress.stateNode + var ctor = workInProgress.type + if (typeof instance.shouldComponentUpdate === 'function') { + startPhaseTimer(workInProgress, 'shouldComponentUpdate') + var shouldUpdate = instance.shouldComponentUpdate( + newProps, + newState, + newContext + ) + stopPhaseTimer() + + { + !(shouldUpdate !== undefined) + ? warning( + false, + '%s.shouldComponentUpdate(): Returned undefined instead of a ' + + 'boolean value. Make sure to return true or false.', + getComponentName(workInProgress) || 'Component' + ) + : void 0 + } + + return shouldUpdate + } + + if (ctor.prototype && ctor.prototype.isPureReactComponent) { + return ( + !shallowEqual(oldProps, newProps) || + !shallowEqual(oldState, newState) + ) + } + + return true + } + + function checkClassInstance(workInProgress) { + var instance = workInProgress.stateNode + var type = workInProgress.type + { + var name = getComponentName(workInProgress) || 'Component' + var renderPresent = instance.render + + if (!renderPresent) { + if ( + type.prototype && + typeof type.prototype.render === 'function' + ) { + warning( + false, + '%s(...): No `render` method found on the returned component ' + + 'instance: did you accidentally return an object from the constructor?', + name + ) + } else { + warning( + false, + '%s(...): No `render` method found on the returned component ' + + 'instance: you may have forgotten to define `render`.', + name + ) + } + } + + var noGetInitialStateOnES6 = + !instance.getInitialState || + instance.getInitialState.isReactClassApproved || + instance.state + !noGetInitialStateOnES6 + ? warning( + false, + 'getInitialState was defined on %s, a plain JavaScript class. ' + + 'This is only supported for classes created using React.createClass. ' + + 'Did you mean to define a state property instead?', + name + ) + : void 0 + var noGetDefaultPropsOnES6 = + !instance.getDefaultProps || + instance.getDefaultProps.isReactClassApproved + !noGetDefaultPropsOnES6 + ? warning( + false, + 'getDefaultProps was defined on %s, a plain JavaScript class. ' + + 'This is only supported for classes created using React.createClass. ' + + 'Use a static property to define defaultProps instead.', + name + ) + : void 0 + var noInstancePropTypes = !instance.propTypes + !noInstancePropTypes + ? warning( + false, + 'propTypes was defined as an instance property on %s. Use a static ' + + 'property to define propTypes instead.', + name + ) + : void 0 + var noInstanceContextTypes = !instance.contextTypes + !noInstanceContextTypes + ? warning( + false, + 'contextTypes was defined as an instance property on %s. Use a static ' + + 'property to define contextTypes instead.', + name + ) + : void 0 + var noComponentShouldUpdate = + typeof instance.componentShouldUpdate !== 'function' + !noComponentShouldUpdate + ? warning( + false, + '%s has a method called ' + + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + + 'The name is phrased as a question because the function is ' + + 'expected to return a value.', + name + ) + : void 0 + if ( + type.prototype && + type.prototype.isPureReactComponent && + typeof instance.shouldComponentUpdate !== 'undefined' + ) { + warning( + false, + '%s has a method called shouldComponentUpdate(). ' + + 'shouldComponentUpdate should not be used when extending React.PureComponent. ' + + 'Please extend React.Component if shouldComponentUpdate is used.', + getComponentName(workInProgress) || 'A pure component' + ) + } + var noComponentDidUnmount = + typeof instance.componentDidUnmount !== 'function' + !noComponentDidUnmount + ? warning( + false, + '%s has a method called ' + + 'componentDidUnmount(). But there is no such lifecycle method. ' + + 'Did you mean componentWillUnmount()?', + name + ) + : void 0 + var noComponentDidReceiveProps = + typeof instance.componentDidReceiveProps !== 'function' + !noComponentDidReceiveProps + ? warning( + false, + '%s has a method called ' + + 'componentDidReceiveProps(). But there is no such lifecycle method. ' + + 'If you meant to update the state in response to changing props, ' + + 'use componentWillReceiveProps(). If you meant to fetch data or ' + + 'run side-effects or mutations after React has updated the UI, use componentDidUpdate().', + name + ) + : void 0 + var noComponentWillRecieveProps = + typeof instance.componentWillRecieveProps !== 'function' + !noComponentWillRecieveProps + ? warning( + false, + '%s has a method called ' + + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', + name + ) + : void 0 + var noUnsafeComponentWillRecieveProps = + typeof instance.UNSAFE_componentWillRecieveProps !== + 'function' + !noUnsafeComponentWillRecieveProps + ? warning( + false, + '%s has a method called ' + + 'UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?', + name + ) + : void 0 + var hasMutatedProps = + instance.props !== workInProgress.pendingProps + !(instance.props === undefined || !hasMutatedProps) + ? warning( + false, + '%s(...): When calling super() in `%s`, make sure to pass ' + + "up the same props that your component's constructor was passed.", + name, + name + ) + : void 0 + var noInstanceDefaultProps = !instance.defaultProps + !noInstanceDefaultProps + ? warning( + false, + 'Setting defaultProps as an instance property on %s is not supported and will be ignored.' + + ' Instead, define defaultProps as a static property on %s.', + name, + name + ) + : void 0 + + if ( + typeof instance.getSnapshotBeforeUpdate === + 'function' && + typeof instance.componentDidUpdate !== 'function' && + !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has( + type + ) + ) { + didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add( + type + ) + warning( + false, + '%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). ' + + 'This component defines getSnapshotBeforeUpdate() only.', + getComponentName(workInProgress) + ) + } + + var noInstanceGetDerivedStateFromProps = + typeof instance.getDerivedStateFromProps !== 'function' + !noInstanceGetDerivedStateFromProps + ? warning( + false, + '%s: getDerivedStateFromProps() is defined as an instance method ' + + 'and will be ignored. Instead, declare it as a static method.', + name + ) + : void 0 + var noInstanceGetDerivedStateFromCatch = + typeof instance.getDerivedStateFromCatch !== 'function' + !noInstanceGetDerivedStateFromCatch + ? warning( + false, + '%s: getDerivedStateFromCatch() is defined as an instance method ' + + 'and will be ignored. Instead, declare it as a static method.', + name + ) + : void 0 + var noStaticGetSnapshotBeforeUpdate = + typeof type.getSnapshotBeforeUpdate !== 'function' + !noStaticGetSnapshotBeforeUpdate + ? warning( + false, + '%s: getSnapshotBeforeUpdate() is defined as a static method ' + + 'and will be ignored. Instead, declare it as an instance method.', + name + ) + : void 0 + var _state = instance.state + if ( + _state && + (typeof _state !== 'object' || isArray(_state)) + ) { + warning( + false, + '%s.state: must be set to an object or null', + name + ) + } + if (typeof instance.getChildContext === 'function') { + !(typeof type.childContextTypes === 'object') + ? warning( + false, + '%s.getChildContext(): childContextTypes must be defined in order to ' + + 'use getChildContext().', + name + ) + : void 0 + } + } + } + + function resetInputPointers(workInProgress, instance) { + instance.props = workInProgress.memoizedProps + instance.state = workInProgress.memoizedState + } + + function adoptClassInstance(workInProgress, instance) { + instance.updater = updater + workInProgress.stateNode = instance + // The instance needs access to the fiber so that it can schedule updates + set(instance, workInProgress) + { + instance._reactInternalInstance = fakeInternalInstance + } + } + + function constructClassInstance(workInProgress, props) { + var ctor = workInProgress.type + var unmaskedContext = getUnmaskedContext(workInProgress) + var needsContext = isContextConsumer(workInProgress) + var context = needsContext + ? getMaskedContext(workInProgress, unmaskedContext) + : emptyObject + + // Instantiate twice to help detect side-effects. + if ( + debugRenderPhaseSideEffects || + (debugRenderPhaseSideEffectsForStrictMode && + workInProgress.mode & StrictMode) + ) { + new ctor(props, context) // eslint-disable-line no-new + } + + var instance = new ctor(props, context) + var state = + instance.state !== null && instance.state !== undefined + ? instance.state + : null + adoptClassInstance(workInProgress, instance) + + { + if ( + typeof ctor.getDerivedStateFromProps === 'function' && + state === null + ) { + var componentName = + getComponentName(workInProgress) || 'Component' + if ( + !didWarnAboutUninitializedState.has(componentName) + ) { + didWarnAboutUninitializedState.add(componentName) + warning( + false, + '%s: Did not properly initialize state during construction. ' + + 'Expected state to be an object, but it was %s.', + componentName, + instance.state === null ? 'null' : 'undefined' + ) + } + } + + // If new component APIs are defined, "unsafe" lifecycles won't be called. + // Warn about these lifecycles if they are present. + // Don't warn about react-lifecycles-compat polyfilled methods though. + if ( + typeof ctor.getDerivedStateFromProps === 'function' || + typeof instance.getSnapshotBeforeUpdate === 'function' + ) { + var foundWillMountName = null + var foundWillReceivePropsName = null + var foundWillUpdateName = null + if ( + typeof instance.componentWillMount === 'function' && + instance.componentWillMount + .__suppressDeprecationWarning !== true + ) { + foundWillMountName = 'componentWillMount' + } else if ( + typeof instance.UNSAFE_componentWillMount === + 'function' + ) { + foundWillMountName = 'UNSAFE_componentWillMount' + } + if ( + typeof instance.componentWillReceiveProps === + 'function' && + instance.componentWillReceiveProps + .__suppressDeprecationWarning !== true + ) { + foundWillReceivePropsName = + 'componentWillReceiveProps' + } else if ( + typeof instance.UNSAFE_componentWillReceiveProps === + 'function' + ) { + foundWillReceivePropsName = + 'UNSAFE_componentWillReceiveProps' + } + if ( + typeof instance.componentWillUpdate === 'function' && + instance.componentWillUpdate + .__suppressDeprecationWarning !== true + ) { + foundWillUpdateName = 'componentWillUpdate' + } else if ( + typeof instance.UNSAFE_componentWillUpdate === + 'function' + ) { + foundWillUpdateName = 'UNSAFE_componentWillUpdate' + } + if ( + foundWillMountName !== null || + foundWillReceivePropsName !== null || + foundWillUpdateName !== null + ) { + var _componentName = + getComponentName(workInProgress) || 'Component' + var newApiName = + typeof ctor.getDerivedStateFromProps === 'function' + ? 'getDerivedStateFromProps()' + : 'getSnapshotBeforeUpdate()' + if ( + !didWarnAboutLegacyLifecyclesAndDerivedState.has( + _componentName + ) + ) { + didWarnAboutLegacyLifecyclesAndDerivedState.add( + _componentName + ) + warning( + false, + 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' + + '%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n' + + 'The above lifecycles should be removed. Learn more about this warning here:\n' + + 'https://fb.me/react-async-component-lifecycle-hooks', + _componentName, + newApiName, + foundWillMountName !== null + ? '\n ' + foundWillMountName + : '', + foundWillReceivePropsName !== null + ? '\n ' + foundWillReceivePropsName + : '', + foundWillUpdateName !== null + ? '\n ' + foundWillUpdateName + : '' + ) + } + } + } + } + + workInProgress.memoizedState = state + + var partialState = callGetDerivedStateFromProps( + workInProgress, + instance, + props, + state + ) + + if (partialState !== null && partialState !== undefined) { + // Render-phase updates (like this) should not be added to the update queue, + // So that multiple render passes do not enqueue multiple updates. + // Instead, just synchronously merge the returned state into the instance. + workInProgress.memoizedState = _assign( + {}, + workInProgress.memoizedState, + partialState + ) + } + + // Cache unmasked context so we can avoid recreating masked context unless necessary. + // ReactFiberContext usually updates this cache but can't for newly-created instances. + if (needsContext) { + cacheContext(workInProgress, unmaskedContext, context) + } + + return instance + } + + function callComponentWillMount(workInProgress, instance) { + startPhaseTimer(workInProgress, 'componentWillMount') + var oldState = instance.state + + if (typeof instance.componentWillMount === 'function') { + instance.componentWillMount() + } + if ( + typeof instance.UNSAFE_componentWillMount === 'function' + ) { + instance.UNSAFE_componentWillMount() + } + + stopPhaseTimer() + + if (oldState !== instance.state) { + { + warning( + false, + '%s.componentWillMount(): Assigning directly to this.state is ' + + "deprecated (except inside a component's " + + 'constructor). Use setState instead.', + getComponentName(workInProgress) || 'Component' + ) + } + updater.enqueueReplaceState( + instance, + instance.state, + null + ) + } + } + + function callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + newContext + ) { + var oldState = instance.state + startPhaseTimer(workInProgress, 'componentWillReceiveProps') + if ( + typeof instance.componentWillReceiveProps === 'function' + ) { + instance.componentWillReceiveProps(newProps, newContext) + } + if ( + typeof instance.UNSAFE_componentWillReceiveProps === + 'function' + ) { + instance.UNSAFE_componentWillReceiveProps( + newProps, + newContext + ) + } + stopPhaseTimer() + + if (instance.state !== oldState) { + { + var componentName = + getComponentName(workInProgress) || 'Component' + if ( + !didWarnAboutStateAssignmentForComponent.has( + componentName + ) + ) { + didWarnAboutStateAssignmentForComponent.add( + componentName + ) + warning( + false, + '%s.componentWillReceiveProps(): Assigning directly to ' + + "this.state is deprecated (except inside a component's " + + 'constructor). Use setState instead.', + componentName + ) + } + } + updater.enqueueReplaceState( + instance, + instance.state, + null + ) + } + } + + function callGetDerivedStateFromProps( + workInProgress, + instance, + nextProps, + prevState + ) { + var type = workInProgress.type + + if (typeof type.getDerivedStateFromProps === 'function') { + if ( + debugRenderPhaseSideEffects || + (debugRenderPhaseSideEffectsForStrictMode && + workInProgress.mode & StrictMode) + ) { + // Invoke method an extra time to help detect side-effects. + type.getDerivedStateFromProps.call( + null, + nextProps, + prevState + ) + } + + var partialState = type.getDerivedStateFromProps.call( + null, + nextProps, + prevState + ) + + { + if (partialState === undefined) { + var componentName = + getComponentName(workInProgress) || 'Component' + if ( + !didWarnAboutUndefinedDerivedState.has( + componentName + ) + ) { + didWarnAboutUndefinedDerivedState.add(componentName) + warning( + false, + '%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' + + 'You have returned undefined.', + componentName + ) + } + } + } + + return partialState + } + } + + // Invokes the mount life-cycles on a previously never rendered instance. + function mountClassInstance( + workInProgress, + renderExpirationTime + ) { + var ctor = workInProgress.type + var current = workInProgress.alternate + + { + checkClassInstance(workInProgress) + } + + var instance = workInProgress.stateNode + var props = workInProgress.pendingProps + var unmaskedContext = getUnmaskedContext(workInProgress) + + instance.props = props + instance.state = workInProgress.memoizedState + instance.refs = emptyObject + instance.context = getMaskedContext( + workInProgress, + unmaskedContext + ) + + { + if (workInProgress.mode & StrictMode) { + ReactStrictModeWarnings.recordUnsafeLifecycleWarnings( + workInProgress, + instance + ) + } + + if (warnAboutDeprecatedLifecycles) { + ReactStrictModeWarnings.recordDeprecationWarnings( + workInProgress, + instance + ) + } + } + + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. + if ( + typeof ctor.getDerivedStateFromProps !== 'function' && + typeof instance.getSnapshotBeforeUpdate !== 'function' && + (typeof instance.UNSAFE_componentWillMount === + 'function' || + typeof instance.componentWillMount === 'function') + ) { + callComponentWillMount(workInProgress, instance) + // If we had additional state updates during this life-cycle, let's + // process them now. + var updateQueue = workInProgress.updateQueue + if (updateQueue !== null) { + instance.state = processUpdateQueue( + current, + workInProgress, + updateQueue, + instance, + props, + renderExpirationTime + ) + } + } + if (typeof instance.componentDidMount === 'function') { + workInProgress.effectTag |= Update + } + } + + function resumeMountClassInstance( + workInProgress, + renderExpirationTime + ) { + var ctor = workInProgress.type + var instance = workInProgress.stateNode + resetInputPointers(workInProgress, instance) + + var oldProps = workInProgress.memoizedProps + var newProps = workInProgress.pendingProps + var oldContext = instance.context + var newUnmaskedContext = getUnmaskedContext(workInProgress) + var newContext = getMaskedContext( + workInProgress, + newUnmaskedContext + ) + + var hasNewLifecycles = + typeof ctor.getDerivedStateFromProps === 'function' || + typeof instance.getSnapshotBeforeUpdate === 'function' + + // Note: During these life-cycles, instance.props/instance.state are what + // ever the previously attempted to render - not the "current". However, + // during componentDidUpdate we pass the "current" props. + + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillReceiveProps === + 'function' || + typeof instance.componentWillReceiveProps === + 'function') + ) { + if (oldProps !== newProps || oldContext !== newContext) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + newContext + ) + } + } + + // Compute the next state using the memoized state and the update queue. + var oldState = workInProgress.memoizedState + // TODO: Previous state can be null. + var newState = void 0 + var derivedStateFromCatch = void 0 + if (workInProgress.updateQueue !== null) { + newState = processUpdateQueue( + null, + workInProgress, + workInProgress.updateQueue, + instance, + newProps, + renderExpirationTime + ) + + var updateQueue = workInProgress.updateQueue + if ( + updateQueue !== null && + updateQueue.capturedValues !== null && + enableGetDerivedStateFromCatch && + typeof ctor.getDerivedStateFromCatch === 'function' + ) { + var capturedValues = updateQueue.capturedValues + // Don't remove these from the update queue yet. We need them in + // finishClassComponent. Do the reset there. + // TODO: This is awkward. Refactor class components. + // updateQueue.capturedValues = null; + derivedStateFromCatch = callGetDerivedStateFromCatch( + ctor, + capturedValues + ) + } + } else { + newState = oldState + } + + var derivedStateFromProps = void 0 + if (oldProps !== newProps) { + // The prevState parameter should be the partially updated state. + // Otherwise, spreading state in return values could override updates. + derivedStateFromProps = callGetDerivedStateFromProps( + workInProgress, + instance, + newProps, + newState + ) + } + + if ( + derivedStateFromProps !== null && + derivedStateFromProps !== undefined + ) { + // Render-phase updates (like this) should not be added to the update queue, + // So that multiple render passes do not enqueue multiple updates. + // Instead, just synchronously merge the returned state into the instance. + newState = + newState === null || newState === undefined + ? derivedStateFromProps + : _assign({}, newState, derivedStateFromProps) + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue = workInProgress.updateQueue + if (_updateQueue !== null) { + _updateQueue.baseState = _assign( + {}, + _updateQueue.baseState, + derivedStateFromProps + ) + } + } + if ( + derivedStateFromCatch !== null && + derivedStateFromCatch !== undefined + ) { + // Render-phase updates (like this) should not be added to the update queue, + // So that multiple render passes do not enqueue multiple updates. + // Instead, just synchronously merge the returned state into the instance. + newState = + newState === null || newState === undefined + ? derivedStateFromCatch + : _assign({}, newState, derivedStateFromCatch) + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue2 = workInProgress.updateQueue + if (_updateQueue2 !== null) { + _updateQueue2.baseState = _assign( + {}, + _updateQueue2.baseState, + derivedStateFromCatch + ) + } + } + + if ( + oldProps === newProps && + oldState === newState && + !hasContextChanged() && + !( + workInProgress.updateQueue !== null && + workInProgress.updateQueue.hasForceUpdate + ) + ) { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidMount === 'function') { + workInProgress.effectTag |= Update + } + return false + } + + var shouldUpdate = checkShouldComponentUpdate( + workInProgress, + oldProps, + newProps, + oldState, + newState, + newContext + ) + + if (shouldUpdate) { + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillMount === + 'function' || + typeof instance.componentWillMount === 'function') + ) { + startPhaseTimer(workInProgress, 'componentWillMount') + if (typeof instance.componentWillMount === 'function') { + instance.componentWillMount() + } + if ( + typeof instance.UNSAFE_componentWillMount === + 'function' + ) { + instance.UNSAFE_componentWillMount() + } + stopPhaseTimer() + } + if (typeof instance.componentDidMount === 'function') { + workInProgress.effectTag |= Update + } + } else { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidMount === 'function') { + workInProgress.effectTag |= Update + } + + // If shouldComponentUpdate returned false, we should still update the + // memoized props/state to indicate that this work can be reused. + memoizeProps(workInProgress, newProps) + memoizeState(workInProgress, newState) + } + + // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. + instance.props = newProps + instance.state = newState + instance.context = newContext + + return shouldUpdate + } + + // Invokes the update life-cycles and returns false if it shouldn't rerender. + function updateClassInstance( + current, + workInProgress, + renderExpirationTime + ) { + var ctor = workInProgress.type + var instance = workInProgress.stateNode + resetInputPointers(workInProgress, instance) + + var oldProps = workInProgress.memoizedProps + var newProps = workInProgress.pendingProps + var oldContext = instance.context + var newUnmaskedContext = getUnmaskedContext(workInProgress) + var newContext = getMaskedContext( + workInProgress, + newUnmaskedContext + ) + + var hasNewLifecycles = + typeof ctor.getDerivedStateFromProps === 'function' || + typeof instance.getSnapshotBeforeUpdate === 'function' + + // Note: During these life-cycles, instance.props/instance.state are what + // ever the previously attempted to render - not the "current". However, + // during componentDidUpdate we pass the "current" props. + + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillReceiveProps === + 'function' || + typeof instance.componentWillReceiveProps === + 'function') + ) { + if (oldProps !== newProps || oldContext !== newContext) { + callComponentWillReceiveProps( + workInProgress, + instance, + newProps, + newContext + ) + } + } + + // Compute the next state using the memoized state and the update queue. + var oldState = workInProgress.memoizedState + // TODO: Previous state can be null. + var newState = void 0 + var derivedStateFromCatch = void 0 + + if (workInProgress.updateQueue !== null) { + newState = processUpdateQueue( + current, + workInProgress, + workInProgress.updateQueue, + instance, + newProps, + renderExpirationTime + ) + + var updateQueue = workInProgress.updateQueue + if ( + updateQueue !== null && + updateQueue.capturedValues !== null && + enableGetDerivedStateFromCatch && + typeof ctor.getDerivedStateFromCatch === 'function' + ) { + var capturedValues = updateQueue.capturedValues + // Don't remove these from the update queue yet. We need them in + // finishClassComponent. Do the reset there. + // TODO: This is awkward. Refactor class components. + // updateQueue.capturedValues = null; + derivedStateFromCatch = callGetDerivedStateFromCatch( + ctor, + capturedValues + ) + } + } else { + newState = oldState + } + + var derivedStateFromProps = void 0 + if (oldProps !== newProps) { + // The prevState parameter should be the partially updated state. + // Otherwise, spreading state in return values could override updates. + derivedStateFromProps = callGetDerivedStateFromProps( + workInProgress, + instance, + newProps, + newState + ) + } + + if ( + derivedStateFromProps !== null && + derivedStateFromProps !== undefined + ) { + // Render-phase updates (like this) should not be added to the update queue, + // So that multiple render passes do not enqueue multiple updates. + // Instead, just synchronously merge the returned state into the instance. + newState = + newState === null || newState === undefined + ? derivedStateFromProps + : _assign({}, newState, derivedStateFromProps) + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue3 = workInProgress.updateQueue + if (_updateQueue3 !== null) { + _updateQueue3.baseState = _assign( + {}, + _updateQueue3.baseState, + derivedStateFromProps + ) + } + } + if ( + derivedStateFromCatch !== null && + derivedStateFromCatch !== undefined + ) { + // Render-phase updates (like this) should not be added to the update queue, + // So that multiple render passes do not enqueue multiple updates. + // Instead, just synchronously merge the returned state into the instance. + newState = + newState === null || newState === undefined + ? derivedStateFromCatch + : _assign({}, newState, derivedStateFromCatch) + + // Update the base state of the update queue. + // FIXME: This is getting ridiculous. Refactor plz! + var _updateQueue4 = workInProgress.updateQueue + if (_updateQueue4 !== null) { + _updateQueue4.baseState = _assign( + {}, + _updateQueue4.baseState, + derivedStateFromCatch + ) + } + } + + if ( + oldProps === newProps && + oldState === newState && + !hasContextChanged() && + !( + workInProgress.updateQueue !== null && + workInProgress.updateQueue.hasForceUpdate + ) + ) { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidUpdate === 'function') { + if ( + oldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.effectTag |= Update + } + } + if ( + typeof instance.getSnapshotBeforeUpdate === 'function' + ) { + if ( + oldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.effectTag |= Snapshot + } + } + return false + } + + var shouldUpdate = checkShouldComponentUpdate( + workInProgress, + oldProps, + newProps, + oldState, + newState, + newContext + ) + + if (shouldUpdate) { + // In order to support react-lifecycles-compat polyfilled components, + // Unsafe lifecycles should not be invoked for components using the new APIs. + if ( + !hasNewLifecycles && + (typeof instance.UNSAFE_componentWillUpdate === + 'function' || + typeof instance.componentWillUpdate === 'function') + ) { + startPhaseTimer(workInProgress, 'componentWillUpdate') + if ( + typeof instance.componentWillUpdate === 'function' + ) { + instance.componentWillUpdate( + newProps, + newState, + newContext + ) + } + if ( + typeof instance.UNSAFE_componentWillUpdate === + 'function' + ) { + instance.UNSAFE_componentWillUpdate( + newProps, + newState, + newContext + ) + } + stopPhaseTimer() + } + if (typeof instance.componentDidUpdate === 'function') { + workInProgress.effectTag |= Update + } + if ( + typeof instance.getSnapshotBeforeUpdate === 'function' + ) { + workInProgress.effectTag |= Snapshot + } + } else { + // If an update was already in progress, we should schedule an Update + // effect even though we're bailing out, so that cWU/cDU are called. + if (typeof instance.componentDidUpdate === 'function') { + if ( + oldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.effectTag |= Update + } + } + if ( + typeof instance.getSnapshotBeforeUpdate === 'function' + ) { + if ( + oldProps !== current.memoizedProps || + oldState !== current.memoizedState + ) { + workInProgress.effectTag |= Snapshot + } + } + + // If shouldComponentUpdate returned false, we should still update the + // memoized props/state to indicate that this work can be reused. + memoizeProps(workInProgress, newProps) + memoizeState(workInProgress, newState) + } + + // Update the existing instance's state, props, and context pointers even + // if shouldComponentUpdate returns false. + instance.props = newProps + instance.state = newState + instance.context = newContext + + return shouldUpdate + } + + return { + adoptClassInstance: adoptClassInstance, + callGetDerivedStateFromProps: callGetDerivedStateFromProps, + constructClassInstance: constructClassInstance, + mountClassInstance: mountClassInstance, + resumeMountClassInstance: resumeMountClassInstance, + updateClassInstance: updateClassInstance, + } + } - function checkShouldComponentUpdate(workInProgress, oldProps, newProps, oldState, newState, newContext) { - if (oldProps === null || workInProgress.updateQueue !== null && workInProgress.updateQueue.hasForceUpdate) { - // If the workInProgress already has an Update effect, return true - return true; - } + var getCurrentFiberStackAddendum$2 = + ReactDebugCurrentFiber.getCurrentFiberStackAddendum + + var didWarnAboutMaps = void 0 + var didWarnAboutStringRefInStrictMode = void 0 + var ownerHasKeyUseWarning = void 0 + var ownerHasFunctionTypeWarning = void 0 + var warnForMissingKey = function (child) {} + + { + didWarnAboutMaps = false + didWarnAboutStringRefInStrictMode = {} + + /** + * Warn if there's no key explicitly set on dynamic arrays of children or + * object keys are not valid. This allows us to keep track of children between + * updates. + */ + ownerHasKeyUseWarning = {} + ownerHasFunctionTypeWarning = {} + + warnForMissingKey = function (child) { + if (child === null || typeof child !== 'object') { + return + } + if ( + !child._store || + child._store.validated || + child.key != null + ) { + return + } + !(typeof child._store === 'object') + ? invariant( + false, + 'React Component in warnForMissingKey should have a _store. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + child._store.validated = true + + var currentComponentErrorInfo = + 'Each child in an array or iterator should have a unique ' + + '"key" prop. See https://fb.me/react-warning-keys for ' + + 'more information.' + + (getCurrentFiberStackAddendum$2() || '') + if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { + return + } + ownerHasKeyUseWarning[currentComponentErrorInfo] = true + + warning( + false, + 'Each child in an array or iterator should have a unique ' + + '"key" prop. See https://fb.me/react-warning-keys for ' + + 'more information.%s', + getCurrentFiberStackAddendum$2() + ) + } + } - var instance = workInProgress.stateNode; - var ctor = workInProgress.type; - if (typeof instance.shouldComponentUpdate === 'function') { - startPhaseTimer(workInProgress, 'shouldComponentUpdate'); - var shouldUpdate = instance.shouldComponentUpdate(newProps, newState, newContext); - stopPhaseTimer(); + var isArray$1 = Array.isArray + + function coerceRef(returnFiber, current, element) { + var mixedRef = element.ref + if ( + mixedRef !== null && + typeof mixedRef !== 'function' && + typeof mixedRef !== 'object' + ) { + { + if (returnFiber.mode & StrictMode) { + var componentName = + getComponentName(returnFiber) || 'Component' + if (!didWarnAboutStringRefInStrictMode[componentName]) { + warning( + false, + 'A string ref, "%s", has been found within a strict mode tree. ' + + 'String refs are a source of potential bugs and should be avoided. ' + + 'We recommend using createRef() instead.' + + '\n%s' + + '\n\nLearn more about using refs safely here:' + + '\nhttps://fb.me/react-strict-mode-string-ref', + mixedRef, + getStackAddendumByWorkInProgressFiber(returnFiber) + ) + didWarnAboutStringRefInStrictMode[ + componentName + ] = true + } + } + } + + if (element._owner) { + var owner = element._owner + var inst = void 0 + if (owner) { + var ownerFiber = owner + !(ownerFiber.tag === ClassComponent) + ? invariant( + false, + 'Stateless function components cannot have refs.' + ) + : void 0 + inst = ownerFiber.stateNode + } + !inst + ? invariant( + false, + 'Missing owner for string ref %s. This error is likely caused by a bug in React. Please file an issue.', + mixedRef + ) + : void 0 + var stringRef = '' + mixedRef + // Check if previous string ref matches new string ref + if ( + current !== null && + current.ref !== null && + current.ref._stringRef === stringRef + ) { + return current.ref + } + var ref = function (value) { + var refs = + inst.refs === emptyObject + ? (inst.refs = {}) + : inst.refs + if (value === null) { + delete refs[stringRef] + } else { + refs[stringRef] = value + } + } + ref._stringRef = stringRef + return ref + } else { + !(typeof mixedRef === 'string') + ? invariant( + false, + 'Expected ref to be a function or a string.' + ) + : void 0 + !element._owner + ? invariant( + false, + "Element ref was specified as a string (%s) but no owner was set. This could happen for one of the following reasons:\n1. You may be adding a ref to a functional component\n2. You may be adding a ref to a component that was not created inside a component's render method\n3. You have multiple copies of React loaded\nSee https://fb.me/react-refs-must-have-owner for more information.", + mixedRef + ) + : void 0 + } + } + return mixedRef + } - { - !(shouldUpdate !== undefined) ? warning(false, '%s.shouldComponentUpdate(): Returned undefined instead of a ' + 'boolean value. Make sure to return true or false.', getComponentName(workInProgress) || 'Component') : void 0; - } + function throwOnInvalidObjectType(returnFiber, newChild) { + if (returnFiber.type !== 'textarea') { + var addendum = '' + { + addendum = + ' If you meant to render a collection of children, use an array ' + + 'instead.' + + (getCurrentFiberStackAddendum$2() || '') + } + invariant( + false, + 'Objects are not valid as a React child (found: %s).%s', + Object.prototype.toString.call(newChild) === + '[object Object]' + ? 'object with keys {' + + Object.keys(newChild).join(', ') + + '}' + : newChild, + addendum + ) + } + } - return shouldUpdate; - } + function warnOnFunctionType() { + var currentComponentErrorInfo = + 'Functions are not valid as a React child. This may happen if ' + + 'you return a Component instead of from render. ' + + 'Or maybe you meant to call this function rather than return it.' + + (getCurrentFiberStackAddendum$2() || '') + + if (ownerHasFunctionTypeWarning[currentComponentErrorInfo]) { + return + } + ownerHasFunctionTypeWarning[currentComponentErrorInfo] = true + + warning( + false, + 'Functions are not valid as a React child. This may happen if ' + + 'you return a Component instead of from render. ' + + 'Or maybe you meant to call this function rather than return it.%s', + getCurrentFiberStackAddendum$2() || '' + ) + } - if (ctor.prototype && ctor.prototype.isPureReactComponent) { - return !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState); - } + // This wrapper function exists because I expect to clone the code in each path + // to be able to optimize each path individually by branching early. This needs + // a compiler or we can do it manually. Helpers that don't need this branching + // live outside of this function. + function ChildReconciler(shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (!shouldTrackSideEffects) { + // Noop. + return + } + // Deletions are added in reversed order so we add it to the front. + // At this point, the return fiber's effect list is empty except for + // deletions, so we can just append the deletion to the list. The remaining + // effects aren't added until the complete phase. Once we implement + // resuming, this may not be true. + var last = returnFiber.lastEffect + if (last !== null) { + last.nextEffect = childToDelete + returnFiber.lastEffect = childToDelete + } else { + returnFiber.firstEffect = returnFiber.lastEffect = childToDelete + } + childToDelete.nextEffect = null + childToDelete.effectTag = Deletion + } + + function deleteRemainingChildren( + returnFiber, + currentFirstChild + ) { + if (!shouldTrackSideEffects) { + // Noop. + return null + } + + // TODO: For the shouldClone case, this could be micro-optimized a bit by + // assuming that after the first child we've already added everything. + var childToDelete = currentFirstChild + while (childToDelete !== null) { + deleteChild(returnFiber, childToDelete) + childToDelete = childToDelete.sibling + } + return null + } + + function mapRemainingChildren( + returnFiber, + currentFirstChild + ) { + // Add the remaining children to a temporary map so that we can find them by + // keys quickly. Implicit (null) keys get added to this set with their index + var existingChildren = new Map() + + var existingChild = currentFirstChild + while (existingChild !== null) { + if (existingChild.key !== null) { + existingChildren.set(existingChild.key, existingChild) + } else { + existingChildren.set(existingChild.index, existingChild) + } + existingChild = existingChild.sibling + } + return existingChildren + } + + function useFiber(fiber, pendingProps, expirationTime) { + // We currently set sibling to null and index to 0 here because it is easy + // to forget to do before returning it. E.g. for the single child case. + var clone = createWorkInProgress( + fiber, + pendingProps, + expirationTime + ) + clone.index = 0 + clone.sibling = null + return clone + } + + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex + if (!shouldTrackSideEffects) { + // Noop. + return lastPlacedIndex + } + var current = newFiber.alternate + if (current !== null) { + var oldIndex = current.index + if (oldIndex < lastPlacedIndex) { + // This is a move. + newFiber.effectTag = Placement + return lastPlacedIndex + } else { + // This item can stay in place. + return oldIndex + } + } else { + // This is an insertion. + newFiber.effectTag = Placement + return lastPlacedIndex + } + } + + function placeSingleChild(newFiber) { + // This is simpler for the single child case. We only need to do a + // placement for inserting new children. + if (shouldTrackSideEffects && newFiber.alternate === null) { + newFiber.effectTag = Placement + } + return newFiber + } + + function updateTextNode( + returnFiber, + current, + textContent, + expirationTime + ) { + if (current === null || current.tag !== HostText) { + // Insert + var created = createFiberFromText( + textContent, + returnFiber.mode, + expirationTime + ) + created['return'] = returnFiber + return created + } else { + // Update + var existing = useFiber( + current, + textContent, + expirationTime + ) + existing['return'] = returnFiber + return existing + } + } + + function updateElement( + returnFiber, + current, + element, + expirationTime + ) { + if (current !== null && current.type === element.type) { + // Move based on index + var existing = useFiber( + current, + element.props, + expirationTime + ) + existing.ref = coerceRef(returnFiber, current, element) + existing['return'] = returnFiber + { + existing._debugSource = element._source + existing._debugOwner = element._owner + } + return existing + } else { + // Insert + var created = createFiberFromElement( + element, + returnFiber.mode, + expirationTime + ) + created.ref = coerceRef(returnFiber, current, element) + created['return'] = returnFiber + return created + } + } + + function updatePortal( + returnFiber, + current, + portal, + expirationTime + ) { + if ( + current === null || + current.tag !== HostPortal || + current.stateNode.containerInfo !== + portal.containerInfo || + current.stateNode.implementation !== portal.implementation + ) { + // Insert + var created = createFiberFromPortal( + portal, + returnFiber.mode, + expirationTime + ) + created['return'] = returnFiber + return created + } else { + // Update + var existing = useFiber( + current, + portal.children || [], + expirationTime + ) + existing['return'] = returnFiber + return existing + } + } + + function updateFragment( + returnFiber, + current, + fragment, + expirationTime, + key + ) { + if (current === null || current.tag !== Fragment) { + // Insert + var created = createFiberFromFragment( + fragment, + returnFiber.mode, + expirationTime, + key + ) + created['return'] = returnFiber + return created + } else { + // Update + var existing = useFiber(current, fragment, expirationTime) + existing['return'] = returnFiber + return existing + } + } + + function createChild(returnFiber, newChild, expirationTime) { + if ( + typeof newChild === 'string' || + typeof newChild === 'number' + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + var created = createFiberFromText( + '' + newChild, + returnFiber.mode, + expirationTime + ) + created['return'] = returnFiber + return created + } + + if (typeof newChild === 'object' && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _created = createFiberFromElement( + newChild, + returnFiber.mode, + expirationTime + ) + _created.ref = coerceRef(returnFiber, null, newChild) + _created['return'] = returnFiber + return _created + } + case REACT_PORTAL_TYPE: { + var _created2 = createFiberFromPortal( + newChild, + returnFiber.mode, + expirationTime + ) + _created2['return'] = returnFiber + return _created2 + } + } + + if (isArray$1(newChild) || getIteratorFn(newChild)) { + var _created3 = createFiberFromFragment( + newChild, + returnFiber.mode, + expirationTime, + null + ) + _created3['return'] = returnFiber + return _created3 + } + + throwOnInvalidObjectType(returnFiber, newChild) + } + + { + if (typeof newChild === 'function') { + warnOnFunctionType() + } + } + + return null + } + + function updateSlot( + returnFiber, + oldFiber, + newChild, + expirationTime + ) { + // Update the fiber if the keys match, otherwise return null. + + var key = oldFiber !== null ? oldFiber.key : null + + if ( + typeof newChild === 'string' || + typeof newChild === 'number' + ) { + // Text nodes don't have keys. If the previous node is implicitly keyed + // we can continue to replace it without aborting even if it is not a text + // node. + if (key !== null) { + return null + } + return updateTextNode( + returnFiber, + oldFiber, + '' + newChild, + expirationTime + ) + } + + if (typeof newChild === 'object' && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + if (newChild.key === key) { + if (newChild.type === REACT_FRAGMENT_TYPE) { + return updateFragment( + returnFiber, + oldFiber, + newChild.props.children, + expirationTime, + key + ) + } + return updateElement( + returnFiber, + oldFiber, + newChild, + expirationTime + ) + } else { + return null + } + } + case REACT_PORTAL_TYPE: { + if (newChild.key === key) { + return updatePortal( + returnFiber, + oldFiber, + newChild, + expirationTime + ) + } else { + return null + } + } + } + + if (isArray$1(newChild) || getIteratorFn(newChild)) { + if (key !== null) { + return null + } + + return updateFragment( + returnFiber, + oldFiber, + newChild, + expirationTime, + null + ) + } + + throwOnInvalidObjectType(returnFiber, newChild) + } + + { + if (typeof newChild === 'function') { + warnOnFunctionType() + } + } + + return null + } + + function updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChild, + expirationTime + ) { + if ( + typeof newChild === 'string' || + typeof newChild === 'number' + ) { + // Text nodes don't have keys, so we neither have to check the old nor + // new node for the key. If both are text nodes, they match. + var matchedFiber = existingChildren.get(newIdx) || null + return updateTextNode( + returnFiber, + matchedFiber, + '' + newChild, + expirationTime + ) + } + + if (typeof newChild === 'object' && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: { + var _matchedFiber = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null + if (newChild.type === REACT_FRAGMENT_TYPE) { + return updateFragment( + returnFiber, + _matchedFiber, + newChild.props.children, + expirationTime, + newChild.key + ) + } + return updateElement( + returnFiber, + _matchedFiber, + newChild, + expirationTime + ) + } + case REACT_PORTAL_TYPE: { + var _matchedFiber2 = + existingChildren.get( + newChild.key === null ? newIdx : newChild.key + ) || null + return updatePortal( + returnFiber, + _matchedFiber2, + newChild, + expirationTime + ) + } + } + + if (isArray$1(newChild) || getIteratorFn(newChild)) { + var _matchedFiber3 = + existingChildren.get(newIdx) || null + return updateFragment( + returnFiber, + _matchedFiber3, + newChild, + expirationTime, + null + ) + } + + throwOnInvalidObjectType(returnFiber, newChild) + } + + { + if (typeof newChild === 'function') { + warnOnFunctionType() + } + } + + return null + } + + /** + * Warns if there is a duplicate or missing key + */ + function warnOnInvalidKey(child, knownKeys) { + { + if (typeof child !== 'object' || child === null) { + return knownKeys + } + switch (child.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + warnForMissingKey(child) + var key = child.key + if (typeof key !== 'string') { + break + } + if (knownKeys === null) { + knownKeys = new Set() + knownKeys.add(key) + break + } + if (!knownKeys.has(key)) { + knownKeys.add(key) + break + } + warning( + false, + 'Encountered two children with the same key, `%s`. ' + + 'Keys should be unique so that components maintain their identity ' + + 'across updates. Non-unique keys may cause children to be ' + + 'duplicated and/or omitted — the behavior is unsupported and ' + + 'could change in a future version.%s', + key, + getCurrentFiberStackAddendum$2() + ) + break + default: + break + } + } + return knownKeys + } + + function reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChildren, + expirationTime + ) { + // This algorithm can't optimize by searching from boths ends since we + // don't have backpointers on fibers. I'm trying to see how far we can get + // with that model. If it ends up not being worth the tradeoffs, we can + // add it later. + + // Even with a two ended optimization, we'd want to optimize for the case + // where there are few changes and brute force the comparison instead of + // going for the Map. It'd like to explore hitting that path first in + // forward-only mode and only go for the Map once we notice that we need + // lots of look ahead. This doesn't handle reversal as well as two ended + // search but that's unusual. Besides, for the two ended optimization to + // work on Iterables, we'd need to copy the whole set. + + // In this first iteration, we'll just live with hitting the bad case + // (adding everything to a Map) in for every insert/move. + + // If you change this code, also update reconcileChildrenIterator() which + // uses the same algorithm. + + { + // First, validate keys. + var knownKeys = null + for (var i = 0; i < newChildren.length; i++) { + var child = newChildren[i] + knownKeys = warnOnInvalidKey(child, knownKeys) + } + } + + var resultingFirstChild = null + var previousNewFiber = null + + var oldFiber = currentFirstChild + var lastPlacedIndex = 0 + var newIdx = 0 + var nextOldFiber = null + for ( + ; + oldFiber !== null && newIdx < newChildren.length; + newIdx++ + ) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber + oldFiber = null + } else { + nextOldFiber = oldFiber.sibling + } + var newFiber = updateSlot( + returnFiber, + oldFiber, + newChildren[newIdx], + expirationTime + ) + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (oldFiber === null) { + oldFiber = nextOldFiber + } + break + } + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber) + } + } + lastPlacedIndex = placeChild( + newFiber, + lastPlacedIndex, + newIdx + ) + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber + } + previousNewFiber = newFiber + oldFiber = nextOldFiber + } + + if (newIdx === newChildren.length) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber) + return resultingFirstChild + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber = createChild( + returnFiber, + newChildren[newIdx], + expirationTime + ) + if (!_newFiber) { + continue + } + lastPlacedIndex = placeChild( + _newFiber, + lastPlacedIndex, + newIdx + ) + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber + } else { + previousNewFiber.sibling = _newFiber + } + previousNewFiber = _newFiber + } + return resultingFirstChild + } + + // Add all children to a key map for quick lookups. + var existingChildren = mapRemainingChildren( + returnFiber, + oldFiber + ) + + // Keep scanning and use the map to restore deleted items as moves. + for (; newIdx < newChildren.length; newIdx++) { + var _newFiber2 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + newChildren[newIdx], + expirationTime + ) + if (_newFiber2) { + if (shouldTrackSideEffects) { + if (_newFiber2.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren['delete']( + _newFiber2.key === null ? newIdx : _newFiber2.key + ) + } + } + lastPlacedIndex = placeChild( + _newFiber2, + lastPlacedIndex, + newIdx + ) + if (previousNewFiber === null) { + resultingFirstChild = _newFiber2 + } else { + previousNewFiber.sibling = _newFiber2 + } + previousNewFiber = _newFiber2 + } + } + + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child) + }) + } + + return resultingFirstChild + } + + function reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChildrenIterable, + expirationTime + ) { + // This is the same implementation as reconcileChildrenArray(), + // but using the iterator instead. + + var iteratorFn = getIteratorFn(newChildrenIterable) + !(typeof iteratorFn === 'function') + ? invariant( + false, + 'An object is not an iterable. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + + { + // Warn about using Maps as children + if (typeof newChildrenIterable.entries === 'function') { + var possibleMap = newChildrenIterable + if (possibleMap.entries === iteratorFn) { + !didWarnAboutMaps + ? warning( + false, + 'Using Maps as children is unsupported and will likely yield ' + + 'unexpected results. Convert it to a sequence/iterable of keyed ' + + 'ReactElements instead.%s', + getCurrentFiberStackAddendum$2() + ) + : void 0 + didWarnAboutMaps = true + } + } + + // First, validate keys. + // We'll get a different iterator later for the main pass. + var _newChildren = iteratorFn.call(newChildrenIterable) + if (_newChildren) { + var knownKeys = null + var _step = _newChildren.next() + for (; !_step.done; _step = _newChildren.next()) { + var child = _step.value + knownKeys = warnOnInvalidKey(child, knownKeys) + } + } + } + + var newChildren = iteratorFn.call(newChildrenIterable) + !(newChildren != null) + ? invariant( + false, + 'An iterable object provided no iterator.' + ) + : void 0 + + var resultingFirstChild = null + var previousNewFiber = null + + var oldFiber = currentFirstChild + var lastPlacedIndex = 0 + var newIdx = 0 + var nextOldFiber = null + + var step = newChildren.next() + for ( + ; + oldFiber !== null && !step.done; + newIdx++, step = newChildren.next() + ) { + if (oldFiber.index > newIdx) { + nextOldFiber = oldFiber + oldFiber = null + } else { + nextOldFiber = oldFiber.sibling + } + var newFiber = updateSlot( + returnFiber, + oldFiber, + step.value, + expirationTime + ) + if (newFiber === null) { + // TODO: This breaks on empty slots like null children. That's + // unfortunate because it triggers the slow path all the time. We need + // a better way to communicate whether this was a miss or null, + // boolean, undefined, etc. + if (!oldFiber) { + oldFiber = nextOldFiber + } + break + } + if (shouldTrackSideEffects) { + if (oldFiber && newFiber.alternate === null) { + // We matched the slot, but we didn't reuse the existing fiber, so we + // need to delete the existing child. + deleteChild(returnFiber, oldFiber) + } + } + lastPlacedIndex = placeChild( + newFiber, + lastPlacedIndex, + newIdx + ) + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = newFiber + } else { + // TODO: Defer siblings if we're not at the right index for this slot. + // I.e. if we had null values before, then we want to defer this + // for each null value. However, we also don't want to call updateSlot + // with the previous one. + previousNewFiber.sibling = newFiber + } + previousNewFiber = newFiber + oldFiber = nextOldFiber + } + + if (step.done) { + // We've reached the end of the new children. We can delete the rest. + deleteRemainingChildren(returnFiber, oldFiber) + return resultingFirstChild + } + + if (oldFiber === null) { + // If we don't have any more existing children we can choose a fast path + // since the rest will all be insertions. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber3 = createChild( + returnFiber, + step.value, + expirationTime + ) + if (_newFiber3 === null) { + continue + } + lastPlacedIndex = placeChild( + _newFiber3, + lastPlacedIndex, + newIdx + ) + if (previousNewFiber === null) { + // TODO: Move out of the loop. This only happens for the first run. + resultingFirstChild = _newFiber3 + } else { + previousNewFiber.sibling = _newFiber3 + } + previousNewFiber = _newFiber3 + } + return resultingFirstChild + } + + // Add all children to a key map for quick lookups. + var existingChildren = mapRemainingChildren( + returnFiber, + oldFiber + ) + + // Keep scanning and use the map to restore deleted items as moves. + for (; !step.done; newIdx++, step = newChildren.next()) { + var _newFiber4 = updateFromMap( + existingChildren, + returnFiber, + newIdx, + step.value, + expirationTime + ) + if (_newFiber4 !== null) { + if (shouldTrackSideEffects) { + if (_newFiber4.alternate !== null) { + // The new fiber is a work in progress, but if there exists a + // current, that means that we reused the fiber. We need to delete + // it from the child list so that we don't add it to the deletion + // list. + existingChildren['delete']( + _newFiber4.key === null ? newIdx : _newFiber4.key + ) + } + } + lastPlacedIndex = placeChild( + _newFiber4, + lastPlacedIndex, + newIdx + ) + if (previousNewFiber === null) { + resultingFirstChild = _newFiber4 + } else { + previousNewFiber.sibling = _newFiber4 + } + previousNewFiber = _newFiber4 + } + } + + if (shouldTrackSideEffects) { + // Any existing children that weren't consumed above were deleted. We need + // to add them to the deletion list. + existingChildren.forEach(function (child) { + return deleteChild(returnFiber, child) + }) + } + + return resultingFirstChild + } + + function reconcileSingleTextNode( + returnFiber, + currentFirstChild, + textContent, + expirationTime + ) { + // There's no need to check for keys on text nodes since we don't have a + // way to define them. + if ( + currentFirstChild !== null && + currentFirstChild.tag === HostText + ) { + // We already have an existing node so let's just update it and delete + // the rest. + deleteRemainingChildren( + returnFiber, + currentFirstChild.sibling + ) + var existing = useFiber( + currentFirstChild, + textContent, + expirationTime + ) + existing['return'] = returnFiber + return existing + } + // The existing first child is not a text node so we need to create one + // and delete the existing ones. + deleteRemainingChildren(returnFiber, currentFirstChild) + var created = createFiberFromText( + textContent, + returnFiber.mode, + expirationTime + ) + created['return'] = returnFiber + return created + } + + function reconcileSingleElement( + returnFiber, + currentFirstChild, + element, + expirationTime + ) { + var key = element.key + var child = currentFirstChild + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if ( + child.tag === Fragment + ? element.type === REACT_FRAGMENT_TYPE + : child.type === element.type + ) { + deleteRemainingChildren(returnFiber, child.sibling) + var existing = useFiber( + child, + element.type === REACT_FRAGMENT_TYPE + ? element.props.children + : element.props, + expirationTime + ) + existing.ref = coerceRef(returnFiber, child, element) + existing['return'] = returnFiber + { + existing._debugSource = element._source + existing._debugOwner = element._owner + } + return existing + } else { + deleteRemainingChildren(returnFiber, child) + break + } + } else { + deleteChild(returnFiber, child) + } + child = child.sibling + } + + if (element.type === REACT_FRAGMENT_TYPE) { + var created = createFiberFromFragment( + element.props.children, + returnFiber.mode, + expirationTime, + element.key + ) + created['return'] = returnFiber + return created + } else { + var _created4 = createFiberFromElement( + element, + returnFiber.mode, + expirationTime + ) + _created4.ref = coerceRef( + returnFiber, + currentFirstChild, + element + ) + _created4['return'] = returnFiber + return _created4 + } + } + + function reconcileSinglePortal( + returnFiber, + currentFirstChild, + portal, + expirationTime + ) { + var key = portal.key + var child = currentFirstChild + while (child !== null) { + // TODO: If key === null and child.key === null, then this only applies to + // the first item in the list. + if (child.key === key) { + if ( + child.tag === HostPortal && + child.stateNode.containerInfo === + portal.containerInfo && + child.stateNode.implementation === + portal.implementation + ) { + deleteRemainingChildren(returnFiber, child.sibling) + var existing = useFiber( + child, + portal.children || [], + expirationTime + ) + existing['return'] = returnFiber + return existing + } else { + deleteRemainingChildren(returnFiber, child) + break + } + } else { + deleteChild(returnFiber, child) + } + child = child.sibling + } + + var created = createFiberFromPortal( + portal, + returnFiber.mode, + expirationTime + ) + created['return'] = returnFiber + return created + } + + // This API will tag the children with the side-effect of the reconciliation + // itself. They will be added to the side-effect list as we pass through the + // children and the parent. + function reconcileChildFibers( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ) { + // This function is not recursive. + // If the top level item is an array, we treat it as a set of children, + // not as a fragment. Nested arrays on the other hand will be treated as + // fragment nodes. Recursion happens at the normal flow. + + // Handle top level unkeyed fragments as if they were arrays. + // This leads to an ambiguity between <>{[...]} and <>.... + // We treat the ambiguous cases above the same. + if ( + typeof newChild === 'object' && + newChild !== null && + newChild.type === REACT_FRAGMENT_TYPE && + newChild.key === null + ) { + newChild = newChild.props.children + } + + // Handle object types + var isObject = + typeof newChild === 'object' && newChild !== null + + if (isObject) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE: + return placeSingleChild( + reconcileSingleElement( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ) + ) + case REACT_PORTAL_TYPE: + return placeSingleChild( + reconcileSinglePortal( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ) + ) + } + } + + if ( + typeof newChild === 'string' || + typeof newChild === 'number' + ) { + return placeSingleChild( + reconcileSingleTextNode( + returnFiber, + currentFirstChild, + '' + newChild, + expirationTime + ) + ) + } + + if (isArray$1(newChild)) { + return reconcileChildrenArray( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ) + } + + if (getIteratorFn(newChild)) { + return reconcileChildrenIterator( + returnFiber, + currentFirstChild, + newChild, + expirationTime + ) + } + + if (isObject) { + throwOnInvalidObjectType(returnFiber, newChild) + } + + { + if (typeof newChild === 'function') { + warnOnFunctionType() + } + } + if (typeof newChild === 'undefined') { + // If the new child is undefined, and the return fiber is a composite + // component, throw an error. If Fiber return types are disabled, + // we already threw above. + switch (returnFiber.tag) { + case ClassComponent: { + { + var instance = returnFiber.stateNode + if (instance.render._isMockFunction) { + // We allow auto-mocks to proceed as if they're returning null. + break + } + } + } + // Intentionally fall through to the next case, which handles both + // functions and classes + // eslint-disable-next-lined no-fallthrough + case FunctionalComponent: { + var Component = returnFiber.type + invariant( + false, + '%s(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.', + Component.displayName || + Component.name || + 'Component' + ) + } + } + } + + // Remaining cases are all treated as empty. + return deleteRemainingChildren( + returnFiber, + currentFirstChild + ) + } + + return reconcileChildFibers + } - return true; - } + var reconcileChildFibers = ChildReconciler(true) + var mountChildFibers = ChildReconciler(false) + + function cloneChildFibers(current, workInProgress) { + !(current === null || workInProgress.child === current.child) + ? invariant(false, 'Resuming work not yet implemented.') + : void 0 + + if (workInProgress.child === null) { + return + } + + var currentChild = workInProgress.child + var newChild = createWorkInProgress( + currentChild, + currentChild.pendingProps, + currentChild.expirationTime + ) + workInProgress.child = newChild + + newChild['return'] = workInProgress + while (currentChild.sibling !== null) { + currentChild = currentChild.sibling + newChild = newChild.sibling = createWorkInProgress( + currentChild, + currentChild.pendingProps, + currentChild.expirationTime + ) + newChild['return'] = workInProgress + } + newChild.sibling = null + } - function checkClassInstance(workInProgress) { - var instance = workInProgress.stateNode; - var type = workInProgress.type; - { - var name = getComponentName(workInProgress) || 'Component'; - var renderPresent = instance.render; - - if (!renderPresent) { - if (type.prototype && typeof type.prototype.render === 'function') { - warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: did you accidentally return an object from the constructor?', name); - } else { - warning(false, '%s(...): No `render` method found on the returned component ' + 'instance: you may have forgotten to define `render`.', name); - } - } + var didWarnAboutBadClass = void 0 + var didWarnAboutGetDerivedStateOnFunctionalComponent = void 0 + var didWarnAboutStatelessRefs = void 0 - var noGetInitialStateOnES6 = !instance.getInitialState || instance.getInitialState.isReactClassApproved || instance.state; - !noGetInitialStateOnES6 ? warning(false, 'getInitialState was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Did you mean to define a state property instead?', name) : void 0; - var noGetDefaultPropsOnES6 = !instance.getDefaultProps || instance.getDefaultProps.isReactClassApproved; - !noGetDefaultPropsOnES6 ? warning(false, 'getDefaultProps was defined on %s, a plain JavaScript class. ' + 'This is only supported for classes created using React.createClass. ' + 'Use a static property to define defaultProps instead.', name) : void 0; - var noInstancePropTypes = !instance.propTypes; - !noInstancePropTypes ? warning(false, 'propTypes was defined as an instance property on %s. Use a static ' + 'property to define propTypes instead.', name) : void 0; - var noInstanceContextTypes = !instance.contextTypes; - !noInstanceContextTypes ? warning(false, 'contextTypes was defined as an instance property on %s. Use a static ' + 'property to define contextTypes instead.', name) : void 0; - var noComponentShouldUpdate = typeof instance.componentShouldUpdate !== 'function'; - !noComponentShouldUpdate ? warning(false, '%s has a method called ' + 'componentShouldUpdate(). Did you mean shouldComponentUpdate()? ' + 'The name is phrased as a question because the function is ' + 'expected to return a value.', name) : void 0; - if (type.prototype && type.prototype.isPureReactComponent && typeof instance.shouldComponentUpdate !== 'undefined') { - warning(false, '%s has a method called shouldComponentUpdate(). ' + 'shouldComponentUpdate should not be used when extending React.PureComponent. ' + 'Please extend React.Component if shouldComponentUpdate is used.', getComponentName(workInProgress) || 'A pure component'); - } - var noComponentDidUnmount = typeof instance.componentDidUnmount !== 'function'; - !noComponentDidUnmount ? warning(false, '%s has a method called ' + 'componentDidUnmount(). But there is no such lifecycle method. ' + 'Did you mean componentWillUnmount()?', name) : void 0; - var noComponentDidReceiveProps = typeof instance.componentDidReceiveProps !== 'function'; - !noComponentDidReceiveProps ? warning(false, '%s has a method called ' + 'componentDidReceiveProps(). But there is no such lifecycle method. ' + 'If you meant to update the state in response to changing props, ' + 'use componentWillReceiveProps(). If you meant to fetch data or ' + 'run side-effects or mutations after React has updated the UI, use componentDidUpdate().', name) : void 0; - var noComponentWillRecieveProps = typeof instance.componentWillRecieveProps !== 'function'; - !noComponentWillRecieveProps ? warning(false, '%s has a method called ' + 'componentWillRecieveProps(). Did you mean componentWillReceiveProps()?', name) : void 0; - var noUnsafeComponentWillRecieveProps = typeof instance.UNSAFE_componentWillRecieveProps !== 'function'; - !noUnsafeComponentWillRecieveProps ? warning(false, '%s has a method called ' + 'UNSAFE_componentWillRecieveProps(). Did you mean UNSAFE_componentWillReceiveProps()?', name) : void 0; - var hasMutatedProps = instance.props !== workInProgress.pendingProps; - !(instance.props === undefined || !hasMutatedProps) ? warning(false, '%s(...): When calling super() in `%s`, make sure to pass ' + "up the same props that your component's constructor was passed.", name, name) : void 0; - var noInstanceDefaultProps = !instance.defaultProps; - !noInstanceDefaultProps ? warning(false, 'Setting defaultProps as an instance property on %s is not supported and will be ignored.' + ' Instead, define defaultProps as a static property on %s.', name, name) : void 0; - - if (typeof instance.getSnapshotBeforeUpdate === 'function' && typeof instance.componentDidUpdate !== 'function' && !didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.has(type)) { - didWarnAboutGetSnapshotBeforeUpdateWithoutDidUpdate.add(type); - warning(false, '%s: getSnapshotBeforeUpdate() should be used with componentDidUpdate(). ' + 'This component defines getSnapshotBeforeUpdate() only.', getComponentName(workInProgress)); - } + { + didWarnAboutBadClass = {} + didWarnAboutGetDerivedStateOnFunctionalComponent = {} + didWarnAboutStatelessRefs = {} + } - var noInstanceGetDerivedStateFromProps = typeof instance.getDerivedStateFromProps !== 'function'; - !noInstanceGetDerivedStateFromProps ? warning(false, '%s: getDerivedStateFromProps() is defined as an instance method ' + 'and will be ignored. Instead, declare it as a static method.', name) : void 0; - var noInstanceGetDerivedStateFromCatch = typeof instance.getDerivedStateFromCatch !== 'function'; - !noInstanceGetDerivedStateFromCatch ? warning(false, '%s: getDerivedStateFromCatch() is defined as an instance method ' + 'and will be ignored. Instead, declare it as a static method.', name) : void 0; - var noStaticGetSnapshotBeforeUpdate = typeof type.getSnapshotBeforeUpdate !== 'function'; - !noStaticGetSnapshotBeforeUpdate ? warning(false, '%s: getSnapshotBeforeUpdate() is defined as a static method ' + 'and will be ignored. Instead, declare it as an instance method.', name) : void 0; - var _state = instance.state; - if (_state && (typeof _state !== 'object' || isArray(_state))) { - warning(false, '%s.state: must be set to an object or null', name); + var ReactFiberBeginWork = function ( + config, + hostContext, + legacyContext, + newContext, + hydrationContext, + scheduleWork, + computeExpirationForFiber + ) { + var shouldSetTextContent = config.shouldSetTextContent, + shouldDeprioritizeSubtree = config.shouldDeprioritizeSubtree + var pushHostContext = hostContext.pushHostContext, + pushHostContainer = hostContext.pushHostContainer + var pushProvider = newContext.pushProvider + var getMaskedContext = legacyContext.getMaskedContext, + getUnmaskedContext = legacyContext.getUnmaskedContext, + hasLegacyContextChanged = legacyContext.hasContextChanged, + pushLegacyContextProvider = + legacyContext.pushContextProvider, + pushTopLevelContextObject = + legacyContext.pushTopLevelContextObject, + invalidateContextProvider = + legacyContext.invalidateContextProvider + var enterHydrationState = + hydrationContext.enterHydrationState, + resetHydrationState = hydrationContext.resetHydrationState, + tryToClaimNextHydratableInstance = + hydrationContext.tryToClaimNextHydratableInstance + + var _ReactFiberClassCompo = ReactFiberClassComponent( + legacyContext, + scheduleWork, + computeExpirationForFiber, + memoizeProps, + memoizeState + ), + adoptClassInstance = + _ReactFiberClassCompo.adoptClassInstance, + callGetDerivedStateFromProps = + _ReactFiberClassCompo.callGetDerivedStateFromProps, + constructClassInstance = + _ReactFiberClassCompo.constructClassInstance, + mountClassInstance = + _ReactFiberClassCompo.mountClassInstance, + resumeMountClassInstance = + _ReactFiberClassCompo.resumeMountClassInstance, + updateClassInstance = + _ReactFiberClassCompo.updateClassInstance + + // TODO: Remove this and use reconcileChildrenAtExpirationTime directly. + + function reconcileChildren( + current, + workInProgress, + nextChildren + ) { + reconcileChildrenAtExpirationTime( + current, + workInProgress, + nextChildren, + workInProgress.expirationTime + ) + } + + function reconcileChildrenAtExpirationTime( + current, + workInProgress, + nextChildren, + renderExpirationTime + ) { + if (current === null) { + // If this is a fresh new component that hasn't been rendered yet, we + // won't update its child set by applying minimal side-effects. Instead, + // we will add them all to the child before it gets rendered. That means + // we can optimize this reconciliation pass by not tracking side-effects. + workInProgress.child = mountChildFibers( + workInProgress, + null, + nextChildren, + renderExpirationTime + ) + } else { + // If the current child is the same as the work in progress, it means that + // we haven't yet started any work on these children. Therefore, we use + // the clone algorithm to create a copy of all the current children. + + // If we had any progressed work already, that is invalid at this point so + // let's throw it out. + workInProgress.child = reconcileChildFibers( + workInProgress, + current.child, + nextChildren, + renderExpirationTime + ) + } + } + + function updateForwardRef(current, workInProgress) { + var render = workInProgress.type.render + var nextChildren = render( + workInProgress.pendingProps, + workInProgress.ref + ) + reconcileChildren(current, workInProgress, nextChildren) + memoizeProps(workInProgress, nextChildren) + return workInProgress.child + } + + function updateFragment(current, workInProgress) { + var nextChildren = workInProgress.pendingProps + if (hasLegacyContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + } else if (workInProgress.memoizedProps === nextChildren) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + reconcileChildren(current, workInProgress, nextChildren) + memoizeProps(workInProgress, nextChildren) + return workInProgress.child + } + + function updateMode(current, workInProgress) { + var nextChildren = workInProgress.pendingProps.children + if (hasLegacyContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + } else if ( + nextChildren === null || + workInProgress.memoizedProps === nextChildren + ) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + reconcileChildren(current, workInProgress, nextChildren) + memoizeProps(workInProgress, nextChildren) + return workInProgress.child + } + + function markRef(current, workInProgress) { + var ref = workInProgress.ref + if ( + (current === null && ref !== null) || + (current !== null && current.ref !== ref) + ) { + // Schedule a Ref effect + workInProgress.effectTag |= Ref + } + } + + function updateFunctionalComponent(current, workInProgress) { + var fn = workInProgress.type + var nextProps = workInProgress.pendingProps + + if (hasLegacyContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + } else { + if (workInProgress.memoizedProps === nextProps) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + // TODO: consider bringing fn.shouldComponentUpdate() back. + // It used to be here. + } + + var unmaskedContext = getUnmaskedContext(workInProgress) + var context = getMaskedContext( + workInProgress, + unmaskedContext + ) + + var nextChildren = void 0 + + { + ReactCurrentOwner.current = workInProgress + ReactDebugCurrentFiber.setCurrentPhase('render') + nextChildren = fn(nextProps, context) + ReactDebugCurrentFiber.setCurrentPhase(null) + } + // React DevTools reads this flag. + workInProgress.effectTag |= PerformedWork + reconcileChildren(current, workInProgress, nextChildren) + memoizeProps(workInProgress, nextProps) + return workInProgress.child + } + + function updateClassComponent( + current, + workInProgress, + renderExpirationTime + ) { + // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. + var hasContext = pushLegacyContextProvider(workInProgress) + var shouldUpdate = void 0 + if (current === null) { + if (workInProgress.stateNode === null) { + // In the initial pass we might need to construct the instance. + constructClassInstance( + workInProgress, + workInProgress.pendingProps + ) + mountClassInstance(workInProgress, renderExpirationTime) + + shouldUpdate = true + } else { + // In a resume, we'll already have an instance we can reuse. + shouldUpdate = resumeMountClassInstance( + workInProgress, + renderExpirationTime + ) + } + } else { + shouldUpdate = updateClassInstance( + current, + workInProgress, + renderExpirationTime + ) + } + + // We processed the update queue inside updateClassInstance. It may have + // included some errors that were dispatched during the commit phase. + // TODO: Refactor class components so this is less awkward. + var didCaptureError = false + var updateQueue = workInProgress.updateQueue + if ( + updateQueue !== null && + updateQueue.capturedValues !== null + ) { + shouldUpdate = true + didCaptureError = true + } + return finishClassComponent( + current, + workInProgress, + shouldUpdate, + hasContext, + didCaptureError, + renderExpirationTime + ) + } + + function finishClassComponent( + current, + workInProgress, + shouldUpdate, + hasContext, + didCaptureError, + renderExpirationTime + ) { + // Refs should update even if shouldComponentUpdate returns false + markRef(current, workInProgress) + + if (!shouldUpdate && !didCaptureError) { + // Context providers should defer to sCU for rendering + if (hasContext) { + invalidateContextProvider(workInProgress, false) + } + + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + + var ctor = workInProgress.type + var instance = workInProgress.stateNode + + // Rerender + ReactCurrentOwner.current = workInProgress + var nextChildren = void 0 + if ( + didCaptureError && + (!enableGetDerivedStateFromCatch || + typeof ctor.getDerivedStateFromCatch !== 'function') + ) { + // If we captured an error, but getDerivedStateFrom catch is not defined, + // unmount all the children. componentDidCatch will schedule an update to + // re-render a fallback. This is temporary until we migrate everyone to + // the new API. + // TODO: Warn in a future release. + nextChildren = null + } else { + { + ReactDebugCurrentFiber.setCurrentPhase('render') + nextChildren = instance.render() + if ( + debugRenderPhaseSideEffects || + (debugRenderPhaseSideEffectsForStrictMode && + workInProgress.mode & StrictMode) + ) { + instance.render() + } + ReactDebugCurrentFiber.setCurrentPhase(null) + } + } + + // React DevTools reads this flag. + workInProgress.effectTag |= PerformedWork + if (didCaptureError) { + // If we're recovering from an error, reconcile twice: first to delete + // all the existing children. + reconcileChildrenAtExpirationTime( + current, + workInProgress, + null, + renderExpirationTime + ) + workInProgress.child = null + // Now we can continue reconciling like normal. This has the effect of + // remounting all children regardless of whether their their + // identity matches. + } + reconcileChildrenAtExpirationTime( + current, + workInProgress, + nextChildren, + renderExpirationTime + ) + // Memoize props and state using the values we just used to render. + // TODO: Restructure so we never read values from the instance. + memoizeState(workInProgress, instance.state) + memoizeProps(workInProgress, instance.props) + + // The context might have changed so we need to recalculate it. + if (hasContext) { + invalidateContextProvider(workInProgress, true) + } + + return workInProgress.child + } + + function pushHostRootContext(workInProgress) { + var root = workInProgress.stateNode + if (root.pendingContext) { + pushTopLevelContextObject( + workInProgress, + root.pendingContext, + root.pendingContext !== root.context + ) + } else if (root.context) { + // Should always be set + pushTopLevelContextObject( + workInProgress, + root.context, + false + ) + } + pushHostContainer(workInProgress, root.containerInfo) + } + + function updateHostRoot( + current, + workInProgress, + renderExpirationTime + ) { + pushHostRootContext(workInProgress) + var updateQueue = workInProgress.updateQueue + if (updateQueue !== null) { + var prevState = workInProgress.memoizedState + var state = processUpdateQueue( + current, + workInProgress, + updateQueue, + null, + null, + renderExpirationTime + ) + memoizeState(workInProgress, state) + updateQueue = workInProgress.updateQueue + + var element = void 0 + if ( + updateQueue !== null && + updateQueue.capturedValues !== null + ) { + // There's an uncaught error. Unmount the whole root. + element = null + } else if (prevState === state) { + // If the state is the same as before, that's a bailout because we had + // no work that expires at this time. + resetHydrationState() + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } else { + element = state.element + } + var root = workInProgress.stateNode + if ( + (current === null || current.child === null) && + root.hydrate && + enterHydrationState(workInProgress) + ) { + // If we don't have any current children this might be the first pass. + // We always try to hydrate. If this isn't a hydration pass there won't + // be any children to hydrate which is effectively the same thing as + // not hydrating. + + // This is a bit of a hack. We track the host root as a placement to + // know that we're currently in a mounting state. That way isMounted + // works as expected. We must reset this before committing. + // TODO: Delete this when we delete isMounted and findDOMNode. + workInProgress.effectTag |= Placement + + // Ensure that children mount into this root without tracking + // side-effects. This ensures that we don't store Placement effects on + // nodes that will be hydrated. + workInProgress.child = mountChildFibers( + workInProgress, + null, + element, + renderExpirationTime + ) + } else { + // Otherwise reset hydration state in case we aborted and resumed another + // root. + resetHydrationState() + reconcileChildren(current, workInProgress, element) + } + memoizeState(workInProgress, state) + return workInProgress.child + } + resetHydrationState() + // If there is no update queue, that's a bailout because the root has no props. + return bailoutOnAlreadyFinishedWork(current, workInProgress) + } + + function updateHostComponent( + current, + workInProgress, + renderExpirationTime + ) { + pushHostContext(workInProgress) + + if (current === null) { + tryToClaimNextHydratableInstance(workInProgress) + } + + var type = workInProgress.type + var memoizedProps = workInProgress.memoizedProps + var nextProps = workInProgress.pendingProps + var prevProps = + current !== null ? current.memoizedProps : null + + if (hasLegacyContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + } else if (memoizedProps === nextProps) { + var isHidden = + workInProgress.mode & AsyncMode && + shouldDeprioritizeSubtree(type, nextProps) + if (isHidden) { + // Before bailing out, make sure we've deprioritized a hidden component. + workInProgress.expirationTime = Never + } + if (!isHidden || renderExpirationTime !== Never) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + // If we're rendering a hidden node at hidden priority, don't bailout. The + // parent is complete, but the children may not be. + } + + var nextChildren = nextProps.children + var isDirectTextChild = shouldSetTextContent( + type, + nextProps + ) + + if (isDirectTextChild) { + // We special case a direct text child of a host node. This is a common + // case. We won't handle it as a reified child. We will instead handle + // this in the host environment that also have access to this prop. That + // avoids allocating another HostText fiber and traversing it. + nextChildren = null + } else if ( + prevProps && + shouldSetTextContent(type, prevProps) + ) { + // If we're switching from a direct text child to a normal child, or to + // empty, we need to schedule the text content to be reset. + workInProgress.effectTag |= ContentReset + } + + markRef(current, workInProgress) + + // Check the host config to see if the children are offscreen/hidden. + if ( + renderExpirationTime !== Never && + workInProgress.mode & AsyncMode && + shouldDeprioritizeSubtree(type, nextProps) + ) { + // Down-prioritize the children. + workInProgress.expirationTime = Never + // Bailout and come back to this fiber later. + workInProgress.memoizedProps = nextProps + return null + } + + reconcileChildren(current, workInProgress, nextChildren) + memoizeProps(workInProgress, nextProps) + return workInProgress.child + } + + function updateHostText(current, workInProgress) { + if (current === null) { + tryToClaimNextHydratableInstance(workInProgress) + } + var nextProps = workInProgress.pendingProps + memoizeProps(workInProgress, nextProps) + // Nothing to do here. This is terminal. We'll do the completion step + // immediately after. + return null + } + + function mountIndeterminateComponent( + current, + workInProgress, + renderExpirationTime + ) { + !(current === null) + ? invariant( + false, + 'An indeterminate component should never have mounted. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + var fn = workInProgress.type + var props = workInProgress.pendingProps + var unmaskedContext = getUnmaskedContext(workInProgress) + var context = getMaskedContext( + workInProgress, + unmaskedContext + ) + + var value = void 0 + + { + if ( + fn.prototype && + typeof fn.prototype.render === 'function' + ) { + var componentName = + getComponentName(workInProgress) || 'Unknown' + + if (!didWarnAboutBadClass[componentName]) { + warning( + false, + "The <%s /> component appears to have a render method, but doesn't extend React.Component. " + + 'This is likely to cause errors. Change %s to extend React.Component instead.', + componentName, + componentName + ) + didWarnAboutBadClass[componentName] = true + } + } + ReactCurrentOwner.current = workInProgress + value = fn(props, context) + } + // React DevTools reads this flag. + workInProgress.effectTag |= PerformedWork + + if ( + typeof value === 'object' && + value !== null && + typeof value.render === 'function' && + value.$$typeof === undefined + ) { + var Component = workInProgress.type + + // Proceed under the assumption that this is a class instance + workInProgress.tag = ClassComponent + + workInProgress.memoizedState = + value.state !== null && value.state !== undefined + ? value.state + : null + + if ( + typeof Component.getDerivedStateFromProps === 'function' + ) { + var partialState = callGetDerivedStateFromProps( + workInProgress, + value, + props, + workInProgress.memoizedState + ) + + if ( + partialState !== null && + partialState !== undefined + ) { + workInProgress.memoizedState = _assign( + {}, + workInProgress.memoizedState, + partialState + ) + } + } + + // Push context providers early to prevent context stack mismatches. + // During mounting we don't know the child context yet as the instance doesn't exist. + // We will invalidate the child context in finishClassComponent() right after rendering. + var hasContext = pushLegacyContextProvider(workInProgress) + adoptClassInstance(workInProgress, value) + mountClassInstance(workInProgress, renderExpirationTime) + return finishClassComponent( + current, + workInProgress, + true, + hasContext, + false, + renderExpirationTime + ) + } else { + // Proceed under the assumption that this is a functional component + workInProgress.tag = FunctionalComponent + { + var _Component = workInProgress.type + + if (_Component) { + !!_Component.childContextTypes + ? warning( + false, + '%s(...): childContextTypes cannot be defined on a functional component.', + _Component.displayName || + _Component.name || + 'Component' + ) + : void 0 + } + if (workInProgress.ref !== null) { + var info = '' + var ownerName = ReactDebugCurrentFiber.getCurrentFiberOwnerName() + if (ownerName) { + info += + '\n\nCheck the render method of `' + + ownerName + + '`.' + } + + var warningKey = + ownerName || workInProgress._debugID || '' + var debugSource = workInProgress._debugSource + if (debugSource) { + warningKey = + debugSource.fileName + + ':' + + debugSource.lineNumber + } + if (!didWarnAboutStatelessRefs[warningKey]) { + didWarnAboutStatelessRefs[warningKey] = true + warning( + false, + 'Stateless function components cannot be given refs. ' + + 'Attempts to access this ref will fail.%s%s', + info, + ReactDebugCurrentFiber.getCurrentFiberStackAddendum() + ) + } + } + + if (typeof fn.getDerivedStateFromProps === 'function') { + var _componentName = + getComponentName(workInProgress) || 'Unknown' + + if ( + !didWarnAboutGetDerivedStateOnFunctionalComponent[ + _componentName + ] + ) { + warning( + false, + '%s: Stateless functional components do not support getDerivedStateFromProps.', + _componentName + ) + didWarnAboutGetDerivedStateOnFunctionalComponent[ + _componentName + ] = true + } + } + } + reconcileChildren(current, workInProgress, value) + memoizeProps(workInProgress, props) + return workInProgress.child + } + } + + function updateCallComponent( + current, + workInProgress, + renderExpirationTime + ) { + var nextProps = workInProgress.pendingProps + if (hasLegacyContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + } else if (workInProgress.memoizedProps === nextProps) { + nextProps = workInProgress.memoizedProps + // TODO: When bailing out, we might need to return the stateNode instead + // of the child. To check it for work. + // return bailoutOnAlreadyFinishedWork(current, workInProgress); + } + + var nextChildren = nextProps.children + + // The following is a fork of reconcileChildrenAtExpirationTime but using + // stateNode to store the child. + if (current === null) { + workInProgress.stateNode = mountChildFibers( + workInProgress, + workInProgress.stateNode, + nextChildren, + renderExpirationTime + ) + } else { + workInProgress.stateNode = reconcileChildFibers( + workInProgress, + current.stateNode, + nextChildren, + renderExpirationTime + ) + } + + memoizeProps(workInProgress, nextProps) + // This doesn't take arbitrary time so we could synchronously just begin + // eagerly do the work of workInProgress.child as an optimization. + return workInProgress.stateNode + } + + function updatePortalComponent( + current, + workInProgress, + renderExpirationTime + ) { + pushHostContainer( + workInProgress, + workInProgress.stateNode.containerInfo + ) + var nextChildren = workInProgress.pendingProps + if (hasLegacyContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + } else if (workInProgress.memoizedProps === nextChildren) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + + if (current === null) { + // Portals are special because we don't append the children during mount + // but at commit. Therefore we need to track insertions which the normal + // flow doesn't do during mount. This doesn't happen at the root because + // the root always starts with a "current" with a null child. + // TODO: Consider unifying this with how the root works. + workInProgress.child = reconcileChildFibers( + workInProgress, + null, + nextChildren, + renderExpirationTime + ) + memoizeProps(workInProgress, nextChildren) + } else { + reconcileChildren(current, workInProgress, nextChildren) + memoizeProps(workInProgress, nextChildren) + } + return workInProgress.child + } + + function propagateContextChange( + workInProgress, + context, + changedBits, + renderExpirationTime + ) { + var fiber = workInProgress.child + if (fiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + fiber['return'] = workInProgress + } + while (fiber !== null) { + var nextFiber = void 0 + // Visit this fiber. + switch (fiber.tag) { + case ContextConsumer: + // Check if the context matches. + var observedBits = fiber.stateNode | 0 + if ( + fiber.type === context && + (observedBits & changedBits) !== 0 + ) { + // Update the expiration time of all the ancestors, including + // the alternates. + var node = fiber + while (node !== null) { + var alternate = node.alternate + if ( + node.expirationTime === NoWork || + node.expirationTime > renderExpirationTime + ) { + node.expirationTime = renderExpirationTime + if ( + alternate !== null && + (alternate.expirationTime === NoWork || + alternate.expirationTime > + renderExpirationTime) + ) { + alternate.expirationTime = renderExpirationTime + } + } else if ( + alternate !== null && + (alternate.expirationTime === NoWork || + alternate.expirationTime > + renderExpirationTime) + ) { + alternate.expirationTime = renderExpirationTime + } else { + // Neither alternate was updated, which means the rest of the + // ancestor path already has sufficient priority. + break + } + node = node['return'] + } + // Don't scan deeper than a matching consumer. When we render the + // consumer, we'll continue scanning from that point. This way the + // scanning work is time-sliced. + nextFiber = null + } else { + // Traverse down. + nextFiber = fiber.child + } + break + case ContextProvider: + // Don't scan deeper if this is a matching provider + nextFiber = + fiber.type === workInProgress.type + ? null + : fiber.child + break + default: + // Traverse down. + nextFiber = fiber.child + break + } + if (nextFiber !== null) { + // Set the return pointer of the child to the work-in-progress fiber. + nextFiber['return'] = fiber + } else { + // No child. Traverse to next sibling. + nextFiber = fiber + while (nextFiber !== null) { + if (nextFiber === workInProgress) { + // We're back to the root of this subtree. Exit. + nextFiber = null + break + } + var sibling = nextFiber.sibling + if (sibling !== null) { + nextFiber = sibling + break + } + // No more siblings. Traverse up. + nextFiber = nextFiber['return'] + } + } + fiber = nextFiber + } + } + + function updateContextProvider( + current, + workInProgress, + renderExpirationTime + ) { + var providerType = workInProgress.type + var context = providerType._context + + var newProps = workInProgress.pendingProps + var oldProps = workInProgress.memoizedProps + + if (hasLegacyContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + } else if (oldProps === newProps) { + workInProgress.stateNode = 0 + pushProvider(workInProgress) + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + + var newValue = newProps.value + workInProgress.memoizedProps = newProps + + var changedBits = void 0 + if (oldProps === null) { + // Initial render + changedBits = MAX_SIGNED_31_BIT_INT + } else { + if (oldProps.value === newProps.value) { + // No change. Bailout early if children are the same. + if (oldProps.children === newProps.children) { + workInProgress.stateNode = 0 + pushProvider(workInProgress) + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + changedBits = 0 + } else { + var oldValue = oldProps.value + // Use Object.is to compare the new context value to the old value. + // Inlined Object.is polyfill. + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is + if ( + (oldValue === newValue && + (oldValue !== 0 || + 1 / oldValue === 1 / newValue)) || + (oldValue !== oldValue && newValue !== newValue) // eslint-disable-line no-self-compare + ) { + // No change. Bailout early if children are the same. + if (oldProps.children === newProps.children) { + workInProgress.stateNode = 0 + pushProvider(workInProgress) + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + changedBits = 0 + } else { + changedBits = + typeof context._calculateChangedBits === 'function' + ? context._calculateChangedBits( + oldValue, + newValue + ) + : MAX_SIGNED_31_BIT_INT + { + !( + (changedBits & MAX_SIGNED_31_BIT_INT) === + changedBits + ) + ? warning( + false, + 'calculateChangedBits: Expected the return value to be a ' + + '31-bit integer. Instead received: %s', + changedBits + ) + : void 0 + } + changedBits |= 0 + + if (changedBits === 0) { + // No change. Bailout early if children are the same. + if (oldProps.children === newProps.children) { + workInProgress.stateNode = 0 + pushProvider(workInProgress) + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + } else { + propagateContextChange( + workInProgress, + context, + changedBits, + renderExpirationTime + ) + } + } + } + } + + workInProgress.stateNode = changedBits + pushProvider(workInProgress) + + var newChildren = newProps.children + reconcileChildren(current, workInProgress, newChildren) + return workInProgress.child + } + + function updateContextConsumer( + current, + workInProgress, + renderExpirationTime + ) { + var context = workInProgress.type + var newProps = workInProgress.pendingProps + var oldProps = workInProgress.memoizedProps + + var newValue = context._currentValue + var changedBits = context._changedBits + + if (hasLegacyContextChanged()) { + // Normally we can bail out on props equality but if context has changed + // we don't do the bailout and we have to reuse existing props instead. + } else if (changedBits === 0 && oldProps === newProps) { + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + workInProgress.memoizedProps = newProps + + var observedBits = newProps.unstable_observedBits + if (observedBits === undefined || observedBits === null) { + // Subscribe to all changes by default + observedBits = MAX_SIGNED_31_BIT_INT + } + // Store the observedBits on the fiber's stateNode for quick access. + workInProgress.stateNode = observedBits + + if ((changedBits & observedBits) !== 0) { + // Context change propagation stops at matching consumers, for time- + // slicing. Continue the propagation here. + propagateContextChange( + workInProgress, + context, + changedBits, + renderExpirationTime + ) + } else if (oldProps === newProps) { + // Skip over a memoized parent with a bitmask bailout even + // if we began working on it because of a deeper matching child. + return bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) + } + // There is no bailout on `children` equality because we expect people + // to often pass a bound method as a child, but it may reference + // `this.state` or `this.props` (and thus needs to re-render on `setState`). + + var render = newProps.children + + { + !(typeof render === 'function') + ? warning( + false, + 'A context consumer was rendered with multiple children, or a child ' + + "that isn't a function. A context consumer expects a single child " + + 'that is a function. If you did pass a function, make sure there ' + + 'is no trailing or leading whitespace around it.' + ) + : void 0 + } + + var newChildren = render(newValue) + reconcileChildren(current, workInProgress, newChildren) + return workInProgress.child + } + + /* + function reuseChildrenEffects(returnFiber : Fiber, firstChild : Fiber) { + let child = firstChild; + do { + // Ensure that the first and last effect of the parent corresponds + // to the children's first and last effect. + if (!returnFiber.firstEffect) { + returnFiber.firstEffect = child.firstEffect; } - if (typeof instance.getChildContext === 'function') { - !(typeof type.childContextTypes === 'object') ? warning(false, '%s.getChildContext(): childContextTypes must be defined in order to ' + 'use getChildContext().', name) : void 0; + if (child.lastEffect) { + if (returnFiber.lastEffect) { + returnFiber.lastEffect.nextEffect = child.firstEffect; + } + returnFiber.lastEffect = child.lastEffect; } - } + } while (child = child.sibling); } + */ - function resetInputPointers(workInProgress, instance) { - instance.props = workInProgress.memoizedProps; - instance.state = workInProgress.memoizedState; - } + function bailoutOnAlreadyFinishedWork( + current, + workInProgress + ) { + cancelWorkTimer(workInProgress) + + // TODO: We should ideally be able to bail out early if the children have no + // more work to do. However, since we don't have a separation of this + // Fiber's priority and its children yet - we don't know without doing lots + // of the same work we do anyway. Once we have that separation we can just + // bail out here if the children has no more work at this priority level. + // if (workInProgress.priorityOfChildren <= priorityLevel) { + // // If there are side-effects in these children that have not yet been + // // committed we need to ensure that they get properly transferred up. + // if (current && current.child !== workInProgress.child) { + // reuseChildrenEffects(workInProgress, child); + // } + // return null; + // } + + cloneChildFibers(current, workInProgress) + return workInProgress.child + } + + function bailoutOnLowPriority(current, workInProgress) { + cancelWorkTimer(workInProgress) + + // TODO: Handle HostComponent tags here as well and call pushHostContext()? + // See PR 8590 discussion for context + switch (workInProgress.tag) { + case HostRoot: + pushHostRootContext(workInProgress) + break + case ClassComponent: + pushLegacyContextProvider(workInProgress) + break + case HostPortal: + pushHostContainer( + workInProgress, + workInProgress.stateNode.containerInfo + ) + break + case ContextProvider: + pushProvider(workInProgress) + break + } + // TODO: What if this is currently in progress? + // How can that happen? How is this not being cloned? + return null + } + + // TODO: Delete memoizeProps/State and move to reconcile/bailout instead + function memoizeProps(workInProgress, nextProps) { + workInProgress.memoizedProps = nextProps + } + + function memoizeState(workInProgress, nextState) { + workInProgress.memoizedState = nextState + // Don't reset the updateQueue, in case there are pending updates. Resetting + // is handled by processUpdateQueue. + } + + function beginWork( + current, + workInProgress, + renderExpirationTime + ) { + if ( + workInProgress.expirationTime === NoWork || + workInProgress.expirationTime > renderExpirationTime + ) { + return bailoutOnLowPriority(current, workInProgress) + } + + switch (workInProgress.tag) { + case IndeterminateComponent: + return mountIndeterminateComponent( + current, + workInProgress, + renderExpirationTime + ) + case FunctionalComponent: + return updateFunctionalComponent( + current, + workInProgress + ) + case ClassComponent: + return updateClassComponent( + current, + workInProgress, + renderExpirationTime + ) + case HostRoot: + return updateHostRoot( + current, + workInProgress, + renderExpirationTime + ) + case HostComponent: + return updateHostComponent( + current, + workInProgress, + renderExpirationTime + ) + case HostText: + return updateHostText(current, workInProgress) + case CallHandlerPhase: + // This is a restart. Reset the tag to the initial phase. + workInProgress.tag = CallComponent + // Intentionally fall through since this is now the same. + case CallComponent: + return updateCallComponent( + current, + workInProgress, + renderExpirationTime + ) + case ReturnComponent: + // A return component is just a placeholder, we can just run through the + // next one immediately. + return null + case HostPortal: + return updatePortalComponent( + current, + workInProgress, + renderExpirationTime + ) + case ForwardRef: + return updateForwardRef(current, workInProgress) + case Fragment: + return updateFragment(current, workInProgress) + case Mode: + return updateMode(current, workInProgress) + case ContextProvider: + return updateContextProvider( + current, + workInProgress, + renderExpirationTime + ) + case ContextConsumer: + return updateContextConsumer( + current, + workInProgress, + renderExpirationTime + ) + default: + invariant( + false, + 'Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.' + ) + } + } + + return { + beginWork: beginWork, + } + } - function adoptClassInstance(workInProgress, instance) { - instance.updater = updater; - workInProgress.stateNode = instance; - // The instance needs access to the fiber so that it can schedule updates - set(instance, workInProgress); - { - instance._reactInternalInstance = fakeInternalInstance; - } - } + var ReactFiberCompleteWork = function ( + config, + hostContext, + legacyContext, + newContext, + hydrationContext + ) { + var createInstance = config.createInstance, + createTextInstance = config.createTextInstance, + appendInitialChild = config.appendInitialChild, + finalizeInitialChildren = config.finalizeInitialChildren, + prepareUpdate = config.prepareUpdate, + mutation = config.mutation, + persistence = config.persistence + var getRootHostContainer = hostContext.getRootHostContainer, + popHostContext = hostContext.popHostContext, + getHostContext = hostContext.getHostContext, + popHostContainer = hostContext.popHostContainer + var popLegacyContextProvider = + legacyContext.popContextProvider, + popTopLevelLegacyContextObject = + legacyContext.popTopLevelContextObject + var popProvider = newContext.popProvider + var prepareToHydrateHostInstance = + hydrationContext.prepareToHydrateHostInstance, + prepareToHydrateHostTextInstance = + hydrationContext.prepareToHydrateHostTextInstance, + popHydrationState = hydrationContext.popHydrationState + + function markUpdate(workInProgress) { + // Tag the fiber with an update effect. This turns a Placement into + // a PlacementAndUpdate. + workInProgress.effectTag |= Update + } + + function markRef(workInProgress) { + workInProgress.effectTag |= Ref + } + + function appendAllReturns(returns, workInProgress) { + var node = workInProgress.stateNode + if (node) { + node['return'] = workInProgress + } + while (node !== null) { + if ( + node.tag === HostComponent || + node.tag === HostText || + node.tag === HostPortal + ) { + invariant( + false, + 'A call cannot have host component children.' + ) + } else if (node.tag === ReturnComponent) { + returns.push(node.pendingProps.value) + } else if (node.child !== null) { + node.child['return'] = node + node = node.child + continue + } + while (node.sibling === null) { + if ( + node['return'] === null || + node['return'] === workInProgress + ) { + return + } + node = node['return'] + } + node.sibling['return'] = node['return'] + node = node.sibling + } + } + + function moveCallToHandlerPhase( + current, + workInProgress, + renderExpirationTime + ) { + var props = workInProgress.memoizedProps + !props + ? invariant( + false, + 'Should be resolved by now. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + + // First step of the call has completed. Now we need to do the second. + // TODO: It would be nice to have a multi stage call represented by a + // single component, or at least tail call optimize nested ones. Currently + // that requires additional fields that we don't want to add to the fiber. + // So this requires nested handlers. + // Note: This doesn't mutate the alternate node. I don't think it needs to + // since this stage is reset for every pass. + workInProgress.tag = CallHandlerPhase + + // Build up the returns. + // TODO: Compare this to a generator or opaque helpers like Children. + var returns = [] + appendAllReturns(returns, workInProgress) + var fn = props.handler + var childProps = props.props + var nextChildren = fn(childProps, returns) + + var currentFirstChild = + current !== null ? current.child : null + workInProgress.child = reconcileChildFibers( + workInProgress, + currentFirstChild, + nextChildren, + renderExpirationTime + ) + return workInProgress.child + } + + function appendAllChildren(parent, workInProgress) { + // We only have the top Fiber that was created but we need recurse down its + // children to find all the terminal nodes. + var node = workInProgress.child + while (node !== null) { + if (node.tag === HostComponent || node.tag === HostText) { + appendInitialChild(parent, node.stateNode) + } else if (node.tag === HostPortal) { + // If we have a portal child, then we don't want to traverse + // down its children. Instead, we'll get insertions from each child in + // the portal directly. + } else if (node.child !== null) { + node.child['return'] = node + node = node.child + continue + } + if (node === workInProgress) { + return + } + while (node.sibling === null) { + if ( + node['return'] === null || + node['return'] === workInProgress + ) { + return + } + node = node['return'] + } + node.sibling['return'] = node['return'] + node = node.sibling + } + } + + var updateHostContainer = void 0 + var updateHostComponent = void 0 + var updateHostText = void 0 + if (mutation) { + if (enableMutatingReconciler) { + // Mutation mode + updateHostContainer = function (workInProgress) { + // Noop + } + updateHostComponent = function ( + current, + workInProgress, + updatePayload, + type, + oldProps, + newProps, + rootContainerInstance, + currentHostContext + ) { + // TODO: Type this specific to this type of component. + workInProgress.updateQueue = updatePayload + // If the update payload indicates that there is a change or if there + // is a new ref we mark this as an update. All the work is done in commitWork. + if (updatePayload) { + markUpdate(workInProgress) + } + } + updateHostText = function ( + current, + workInProgress, + oldText, + newText + ) { + // If the text differs, mark it as an update. All the work in done in commitWork. + if (oldText !== newText) { + markUpdate(workInProgress) + } + } + } else { + invariant(false, 'Mutating reconciler is disabled.') + } + } else if (persistence) { + if (enablePersistentReconciler) { + // Persistent host tree mode + var cloneInstance = persistence.cloneInstance, + createContainerChildSet = + persistence.createContainerChildSet, + appendChildToContainerChildSet = + persistence.appendChildToContainerChildSet, + finalizeContainerChildren = + persistence.finalizeContainerChildren + + // An unfortunate fork of appendAllChildren because we have two different parent types. + + var appendAllChildrenToContainer = function ( + containerChildSet, + workInProgress + ) { + // We only have the top Fiber that was created but we need recurse down its + // children to find all the terminal nodes. + var node = workInProgress.child + while (node !== null) { + if ( + node.tag === HostComponent || + node.tag === HostText + ) { + appendChildToContainerChildSet( + containerChildSet, + node.stateNode + ) + } else if (node.tag === HostPortal) { + // If we have a portal child, then we don't want to traverse + // down its children. Instead, we'll get insertions from each child in + // the portal directly. + } else if (node.child !== null) { + node.child['return'] = node + node = node.child + continue + } + if (node === workInProgress) { + return + } + while (node.sibling === null) { + if ( + node['return'] === null || + node['return'] === workInProgress + ) { + return + } + node = node['return'] + } + node.sibling['return'] = node['return'] + node = node.sibling + } + } + updateHostContainer = function (workInProgress) { + var portalOrRoot = workInProgress.stateNode + var childrenUnchanged = + workInProgress.firstEffect === null + if (childrenUnchanged) { + // No changes, just reuse the existing instance. + } else { + var container = portalOrRoot.containerInfo + var newChildSet = createContainerChildSet(container) + // If children might have changed, we have to add them all to the set. + appendAllChildrenToContainer( + newChildSet, + workInProgress + ) + portalOrRoot.pendingChildren = newChildSet + // Schedule an update on the container to swap out the container. + markUpdate(workInProgress) + finalizeContainerChildren(container, newChildSet) + } + } + updateHostComponent = function ( + current, + workInProgress, + updatePayload, + type, + oldProps, + newProps, + rootContainerInstance, + currentHostContext + ) { + // If there are no effects associated with this node, then none of our children had any updates. + // This guarantees that we can reuse all of them. + var childrenUnchanged = + workInProgress.firstEffect === null + var currentInstance = current.stateNode + if (childrenUnchanged && updatePayload === null) { + // No changes, just reuse the existing instance. + // Note that this might release a previous clone. + workInProgress.stateNode = currentInstance + } else { + var recyclableInstance = workInProgress.stateNode + var newInstance = cloneInstance( + currentInstance, + updatePayload, + type, + oldProps, + newProps, + workInProgress, + childrenUnchanged, + recyclableInstance + ) + if ( + finalizeInitialChildren( + newInstance, + type, + newProps, + rootContainerInstance, + currentHostContext + ) + ) { + markUpdate(workInProgress) + } + workInProgress.stateNode = newInstance + if (childrenUnchanged) { + // If there are no other effects in this tree, we need to flag this node as having one. + // Even though we're not going to use it for anything. + // Otherwise parents won't know that there are new children to propagate upwards. + markUpdate(workInProgress) + } else { + // If children might have changed, we have to add them all to the set. + appendAllChildren(newInstance, workInProgress) + } + } + } + updateHostText = function ( + current, + workInProgress, + oldText, + newText + ) { + if (oldText !== newText) { + // If the text content differs, we'll create a new text instance for it. + var rootContainerInstance = getRootHostContainer() + var currentHostContext = getHostContext() + workInProgress.stateNode = createTextInstance( + newText, + rootContainerInstance, + currentHostContext, + workInProgress + ) + // We'll have to mark it as having an effect, even though we won't use the effect for anything. + // This lets the parents know that at least one of their children has changed. + markUpdate(workInProgress) + } + } + } else { + invariant(false, 'Persistent reconciler is disabled.') + } + } else { + if (enableNoopReconciler) { + // No host operations + updateHostContainer = function (workInProgress) { + // Noop + } + updateHostComponent = function ( + current, + workInProgress, + updatePayload, + type, + oldProps, + newProps, + rootContainerInstance, + currentHostContext + ) { + // Noop + } + updateHostText = function ( + current, + workInProgress, + oldText, + newText + ) { + // Noop + } + } else { + invariant(false, 'Noop reconciler is disabled.') + } + } + + function completeWork( + current, + workInProgress, + renderExpirationTime + ) { + var newProps = workInProgress.pendingProps + switch (workInProgress.tag) { + case FunctionalComponent: + return null + case ClassComponent: { + // We are leaving this subtree, so pop context if any. + popLegacyContextProvider(workInProgress) + + // If this component caught an error, schedule an error log effect. + var instance = workInProgress.stateNode + var updateQueue = workInProgress.updateQueue + if ( + updateQueue !== null && + updateQueue.capturedValues !== null + ) { + workInProgress.effectTag &= ~DidCapture + if ( + typeof instance.componentDidCatch === 'function' + ) { + workInProgress.effectTag |= ErrLog + } else { + // Normally we clear this in the commit phase, but since we did not + // schedule an effect, we need to reset it here. + updateQueue.capturedValues = null + } + } + return null + } + case HostRoot: { + popHostContainer(workInProgress) + popTopLevelLegacyContextObject(workInProgress) + var fiberRoot = workInProgress.stateNode + if (fiberRoot.pendingContext) { + fiberRoot.context = fiberRoot.pendingContext + fiberRoot.pendingContext = null + } + if (current === null || current.child === null) { + // If we hydrated, pop so that we can delete any remaining children + // that weren't hydrated. + popHydrationState(workInProgress) + // This resets the hacky state to fix isMounted before committing. + // TODO: Delete this when we delete isMounted and findDOMNode. + workInProgress.effectTag &= ~Placement + } + updateHostContainer(workInProgress) + + var _updateQueue = workInProgress.updateQueue + if ( + _updateQueue !== null && + _updateQueue.capturedValues !== null + ) { + workInProgress.effectTag |= ErrLog + } + return null + } + case HostComponent: { + popHostContext(workInProgress) + var rootContainerInstance = getRootHostContainer() + var type = workInProgress.type + if ( + current !== null && + workInProgress.stateNode != null + ) { + // If we have an alternate, that means this is an update and we need to + // schedule a side-effect to do the updates. + var oldProps = current.memoizedProps + // If we get updated because one of our children updated, we don't + // have newProps so we'll have to reuse them. + // TODO: Split the update API as separate for the props vs. children. + // Even better would be if children weren't special cased at all tho. + var _instance = workInProgress.stateNode + var currentHostContext = getHostContext() + // TODO: Experiencing an error where oldProps is null. Suggests a host + // component is hitting the resume path. Figure out why. Possibly + // related to `hidden`. + var updatePayload = prepareUpdate( + _instance, + type, + oldProps, + newProps, + rootContainerInstance, + currentHostContext + ) + + updateHostComponent( + current, + workInProgress, + updatePayload, + type, + oldProps, + newProps, + rootContainerInstance, + currentHostContext + ) + + if (current.ref !== workInProgress.ref) { + markRef(workInProgress) + } + } else { + if (!newProps) { + !(workInProgress.stateNode !== null) + ? invariant( + false, + 'We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + // This can happen when we abort work. + return null + } + + var _currentHostContext = getHostContext() + // TODO: Move createInstance to beginWork and keep it on a context + // "stack" as the parent. Then append children as we go in beginWork + // or completeWork depending on we want to add then top->down or + // bottom->up. Top->down is faster in IE11. + var wasHydrated = popHydrationState(workInProgress) + if (wasHydrated) { + // TODO: Move this and createInstance step into the beginPhase + // to consolidate. + if ( + prepareToHydrateHostInstance( + workInProgress, + rootContainerInstance, + _currentHostContext + ) + ) { + // If changes to the hydrated node needs to be applied at the + // commit-phase we mark this as such. + markUpdate(workInProgress) + } + } else { + var _instance2 = createInstance( + type, + newProps, + rootContainerInstance, + _currentHostContext, + workInProgress + ) + + appendAllChildren(_instance2, workInProgress) + + // Certain renderers require commit-time effects for initial mount. + // (eg DOM renderer supports auto-focus for certain elements). + // Make sure such renderers get scheduled for later work. + if ( + finalizeInitialChildren( + _instance2, + type, + newProps, + rootContainerInstance, + _currentHostContext + ) + ) { + markUpdate(workInProgress) + } + workInProgress.stateNode = _instance2 + } + + if (workInProgress.ref !== null) { + // If there is a ref on a host node we need to schedule a callback + markRef(workInProgress) + } + } + return null + } + case HostText: { + var newText = newProps + if (current && workInProgress.stateNode != null) { + var oldText = current.memoizedProps + // If we have an alternate, that means this is an update and we need + // to schedule a side-effect to do the updates. + updateHostText( + current, + workInProgress, + oldText, + newText + ) + } else { + if (typeof newText !== 'string') { + !(workInProgress.stateNode !== null) + ? invariant( + false, + 'We must have new props for new mounts. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + // This can happen when we abort work. + return null + } + var _rootContainerInstance = getRootHostContainer() + var _currentHostContext2 = getHostContext() + var _wasHydrated = popHydrationState(workInProgress) + if (_wasHydrated) { + if ( + prepareToHydrateHostTextInstance(workInProgress) + ) { + markUpdate(workInProgress) + } + } else { + workInProgress.stateNode = createTextInstance( + newText, + _rootContainerInstance, + _currentHostContext2, + workInProgress + ) + } + } + return null + } + case CallComponent: + return moveCallToHandlerPhase( + current, + workInProgress, + renderExpirationTime + ) + case CallHandlerPhase: + // Reset the tag to now be a first phase call. + workInProgress.tag = CallComponent + return null + case ReturnComponent: + // Does nothing. + return null + case ForwardRef: + return null + case Fragment: + return null + case Mode: + return null + case HostPortal: + popHostContainer(workInProgress) + updateHostContainer(workInProgress) + return null + case ContextProvider: + // Pop provider fiber + popProvider(workInProgress) + return null + case ContextConsumer: + return null + // Error cases + case IndeterminateComponent: + invariant( + false, + 'An indeterminate component should have become determinate before completing. This error is likely caused by a bug in React. Please file an issue.' + ) + // eslint-disable-next-line no-fallthrough + default: + invariant( + false, + 'Unknown unit of work tag. This error is likely caused by a bug in React. Please file an issue.' + ) + } + } + + return { + completeWork: completeWork, + } + } - function constructClassInstance(workInProgress, props) { - var ctor = workInProgress.type; - var unmaskedContext = getUnmaskedContext(workInProgress); - var needsContext = isContextConsumer(workInProgress); - var context = needsContext ? getMaskedContext(workInProgress, unmaskedContext) : emptyObject; + function createCapturedValue(value, source) { + // If the value is an error, call this function immediately after it is thrown + // so the stack is accurate. + return { + value: value, + source: source, + stack: getStackAddendumByWorkInProgressFiber(source), + } + } - // Instantiate twice to help detect side-effects. - if (debugRenderPhaseSideEffects || debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictMode) { - new ctor(props, context); // eslint-disable-line no-new - } + var ReactFiberUnwindWork = function ( + hostContext, + legacyContext, + newContext, + scheduleWork, + isAlreadyFailedLegacyErrorBoundary + ) { + var popHostContainer = hostContext.popHostContainer, + popHostContext = hostContext.popHostContext + var popLegacyContextProvider = + legacyContext.popContextProvider, + popTopLevelLegacyContextObject = + legacyContext.popTopLevelContextObject + var popProvider = newContext.popProvider + + function throwException(returnFiber, sourceFiber, rawValue) { + // The source fiber did not complete. + sourceFiber.effectTag |= Incomplete + // Its effect list is no longer valid. + sourceFiber.firstEffect = sourceFiber.lastEffect = null + + var value = createCapturedValue(rawValue, sourceFiber) + + var workInProgress = returnFiber + do { + switch (workInProgress.tag) { + case HostRoot: { + // Uncaught error + var errorInfo = value + ensureUpdateQueues(workInProgress) + var updateQueue = workInProgress.updateQueue + updateQueue.capturedValues = [errorInfo] + workInProgress.effectTag |= ShouldCapture + return + } + case ClassComponent: + // Capture and retry + var ctor = workInProgress.type + var _instance = workInProgress.stateNode + if ( + (workInProgress.effectTag & DidCapture) === + NoEffect && + ((typeof ctor.getDerivedStateFromCatch === + 'function' && + enableGetDerivedStateFromCatch) || + (_instance !== null && + typeof _instance.componentDidCatch === + 'function' && + !isAlreadyFailedLegacyErrorBoundary(_instance))) + ) { + ensureUpdateQueues(workInProgress) + var _updateQueue = workInProgress.updateQueue + var capturedValues = _updateQueue.capturedValues + if (capturedValues === null) { + _updateQueue.capturedValues = [value] + } else { + capturedValues.push(value) + } + workInProgress.effectTag |= ShouldCapture + return + } + break + default: + break + } + workInProgress = workInProgress['return'] + } while (workInProgress !== null) + } + + function unwindWork(workInProgress) { + switch (workInProgress.tag) { + case ClassComponent: { + popLegacyContextProvider(workInProgress) + var effectTag = workInProgress.effectTag + if (effectTag & ShouldCapture) { + workInProgress.effectTag = + (effectTag & ~ShouldCapture) | DidCapture + return workInProgress + } + return null + } + case HostRoot: { + popHostContainer(workInProgress) + popTopLevelLegacyContextObject(workInProgress) + var _effectTag = workInProgress.effectTag + if (_effectTag & ShouldCapture) { + workInProgress.effectTag = + (_effectTag & ~ShouldCapture) | DidCapture + return workInProgress + } + return null + } + case HostComponent: { + popHostContext(workInProgress) + return null + } + case HostPortal: + popHostContainer(workInProgress) + return null + case ContextProvider: + popProvider(workInProgress) + return null + default: + return null + } + } + + function unwindInterruptedWork(interruptedWork) { + switch (interruptedWork.tag) { + case ClassComponent: { + popLegacyContextProvider(interruptedWork) + break + } + case HostRoot: { + popHostContainer(interruptedWork) + popTopLevelLegacyContextObject(interruptedWork) + break + } + case HostComponent: { + popHostContext(interruptedWork) + break + } + case HostPortal: + popHostContainer(interruptedWork) + break + case ContextProvider: + popProvider(interruptedWork) + break + default: + break + } + } + + return { + throwException: throwException, + unwindWork: unwindWork, + unwindInterruptedWork: unwindInterruptedWork, + } + } - var instance = new ctor(props, context); - var state = instance.state !== null && instance.state !== undefined ? instance.state : null; - adoptClassInstance(workInProgress, instance); + // This module is forked in different environments. + // By default, return `true` to log errors to the console. + // Forks can return `false` if this isn't desirable. + function showErrorDialog(capturedError) { + return true + } - { - if (typeof ctor.getDerivedStateFromProps === 'function' && state === null) { - var componentName = getComponentName(workInProgress) || 'Component'; - if (!didWarnAboutUninitializedState.has(componentName)) { - didWarnAboutUninitializedState.add(componentName); - warning(false, '%s: Did not properly initialize state during construction. ' + 'Expected state to be an object, but it was %s.', componentName, instance.state === null ? 'null' : 'undefined'); - } - } + function logCapturedError(capturedError) { + var logError = showErrorDialog(capturedError) + + // Allow injected showErrorDialog() to prevent default console.error logging. + // This enables renderers like ReactNative to better manage redbox behavior. + if (logError === false) { + return + } + + var error = capturedError.error + var suppressLogging = error && error.suppressReactErrorLogging + if (suppressLogging) { + return + } + + { + var componentName = capturedError.componentName, + componentStack = capturedError.componentStack, + errorBoundaryName = capturedError.errorBoundaryName, + errorBoundaryFound = capturedError.errorBoundaryFound, + willRetry = capturedError.willRetry + + var componentNameMessage = componentName + ? 'The above error occurred in the <' + + componentName + + '> component:' + : 'The above error occurred in one of your React components:' + + var errorBoundaryMessage = void 0 + // errorBoundaryFound check is sufficient; errorBoundaryName check is to satisfy Flow. + if (errorBoundaryFound && errorBoundaryName) { + if (willRetry) { + errorBoundaryMessage = + 'React will try to recreate this component tree from scratch ' + + ('using the error boundary you provided, ' + + errorBoundaryName + + '.') + } else { + errorBoundaryMessage = + 'This error was initially handled by the error boundary ' + + errorBoundaryName + + '.\n' + + 'Recreating the tree from scratch failed so React will unmount the tree.' + } + } else { + errorBoundaryMessage = + 'Consider adding an error boundary to your tree to customize error handling behavior.\n' + + 'Visit https://fb.me/react-error-boundaries to learn more about error boundaries.' + } + var combinedMessage = + '' + + componentNameMessage + + componentStack + + '\n\n' + + ('' + errorBoundaryMessage) + + // In development, we provide our own message with just the component stack. + // We don't include the original error message and JS stack because the browser + // has already printed it. Even if the application swallows the error, it is still + // displayed by the browser thanks to the DEV-only fake event trick in ReactErrorUtils. + console.error(combinedMessage) + } + } - // If new component APIs are defined, "unsafe" lifecycles won't be called. - // Warn about these lifecycles if they are present. - // Don't warn about react-lifecycles-compat polyfilled methods though. - if (typeof ctor.getDerivedStateFromProps === 'function' || typeof instance.getSnapshotBeforeUpdate === 'function') { - var foundWillMountName = null; - var foundWillReceivePropsName = null; - var foundWillUpdateName = null; - if (typeof instance.componentWillMount === 'function' && instance.componentWillMount.__suppressDeprecationWarning !== true) { - foundWillMountName = 'componentWillMount'; - } else if (typeof instance.UNSAFE_componentWillMount === 'function') { - foundWillMountName = 'UNSAFE_componentWillMount'; - } - if (typeof instance.componentWillReceiveProps === 'function' && instance.componentWillReceiveProps.__suppressDeprecationWarning !== true) { - foundWillReceivePropsName = 'componentWillReceiveProps'; - } else if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') { - foundWillReceivePropsName = 'UNSAFE_componentWillReceiveProps'; - } - if (typeof instance.componentWillUpdate === 'function' && instance.componentWillUpdate.__suppressDeprecationWarning !== true) { - foundWillUpdateName = 'componentWillUpdate'; - } else if (typeof instance.UNSAFE_componentWillUpdate === 'function') { - foundWillUpdateName = 'UNSAFE_componentWillUpdate'; - } - if (foundWillMountName !== null || foundWillReceivePropsName !== null || foundWillUpdateName !== null) { - var _componentName = getComponentName(workInProgress) || 'Component'; - var newApiName = typeof ctor.getDerivedStateFromProps === 'function' ? 'getDerivedStateFromProps()' : 'getSnapshotBeforeUpdate()'; - if (!didWarnAboutLegacyLifecyclesAndDerivedState.has(_componentName)) { - didWarnAboutLegacyLifecyclesAndDerivedState.add(_componentName); - warning(false, 'Unsafe legacy lifecycles will not be called for components using new component APIs.\n\n' + '%s uses %s but also contains the following legacy lifecycles:%s%s%s\n\n' + 'The above lifecycles should be removed. Learn more about this warning here:\n' + 'https://fb.me/react-async-component-lifecycle-hooks', _componentName, newApiName, foundWillMountName !== null ? '\n ' + foundWillMountName : '', foundWillReceivePropsName !== null ? '\n ' + foundWillReceivePropsName : '', foundWillUpdateName !== null ? '\n ' + foundWillUpdateName : ''); - } - } - } - } + var invokeGuardedCallback$3 = + ReactErrorUtils.invokeGuardedCallback + var hasCaughtError$1 = ReactErrorUtils.hasCaughtError + var clearCaughtError$1 = ReactErrorUtils.clearCaughtError - workInProgress.memoizedState = state; + var didWarnAboutUndefinedSnapshotBeforeUpdate = null + { + didWarnAboutUndefinedSnapshotBeforeUpdate = new Set() + } - var partialState = callGetDerivedStateFromProps(workInProgress, instance, props, state); + function logError(boundary, errorInfo) { + var source = errorInfo.source + var stack = errorInfo.stack + if (stack === null) { + stack = getStackAddendumByWorkInProgressFiber(source) + } + + var capturedError = { + componentName: + source !== null ? getComponentName(source) : null, + componentStack: stack !== null ? stack : '', + error: errorInfo.value, + errorBoundary: null, + errorBoundaryName: null, + errorBoundaryFound: false, + willRetry: false, + } + + if (boundary !== null && boundary.tag === ClassComponent) { + capturedError.errorBoundary = boundary.stateNode + capturedError.errorBoundaryName = getComponentName(boundary) + capturedError.errorBoundaryFound = true + capturedError.willRetry = true + } + + try { + logCapturedError(capturedError) + } catch (e) { + // Prevent cycle if logCapturedError() throws. + // A cycle may still occur if logCapturedError renders a component that throws. + var suppressLogging = e && e.suppressReactErrorLogging + if (!suppressLogging) { + console.error(e) + } + } + } - if (partialState !== null && partialState !== undefined) { - // Render-phase updates (like this) should not be added to the update queue, - // So that multiple render passes do not enqueue multiple updates. - // Instead, just synchronously merge the returned state into the instance. - workInProgress.memoizedState = _assign({}, workInProgress.memoizedState, partialState); - } + var ReactFiberCommitWork = function ( + config, + captureError, + scheduleWork, + computeExpirationForFiber, + markLegacyErrorBoundaryAsFailed, + recalculateCurrentTime + ) { + var getPublicInstance = config.getPublicInstance, + mutation = config.mutation, + persistence = config.persistence + + var callComponentWillUnmountWithTimer = function ( + current, + instance + ) { + startPhaseTimer(current, 'componentWillUnmount') + instance.props = current.memoizedProps + instance.state = current.memoizedState + instance.componentWillUnmount() + stopPhaseTimer() + } + + // Capture errors so they don't interrupt unmounting. + function safelyCallComponentWillUnmount(current, instance) { + { + invokeGuardedCallback$3( + null, + callComponentWillUnmountWithTimer, + null, + current, + instance + ) + if (hasCaughtError$1()) { + var unmountError = clearCaughtError$1() + captureError(current, unmountError) + } + } + } + + function safelyDetachRef(current) { + var ref = current.ref + if (ref !== null) { + if (typeof ref === 'function') { + { + invokeGuardedCallback$3(null, ref, null, null) + if (hasCaughtError$1()) { + var refError = clearCaughtError$1() + captureError(current, refError) + } + } + } else { + ref.current = null + } + } + } + + function commitBeforeMutationLifeCycles( + current, + finishedWork + ) { + switch (finishedWork.tag) { + case ClassComponent: { + if (finishedWork.effectTag & Snapshot) { + if (current !== null) { + var prevProps = current.memoizedProps + var prevState = current.memoizedState + startPhaseTimer( + finishedWork, + 'getSnapshotBeforeUpdate' + ) + var _instance = finishedWork.stateNode + _instance.props = finishedWork.memoizedProps + _instance.state = finishedWork.memoizedState + var snapshot = _instance.getSnapshotBeforeUpdate( + prevProps, + prevState + ) + { + var didWarnSet = didWarnAboutUndefinedSnapshotBeforeUpdate + if ( + snapshot === undefined && + !didWarnSet.has(finishedWork.type) + ) { + didWarnSet.add(finishedWork.type) + warning( + false, + '%s.getSnapshotBeforeUpdate(): A snapshot value (or null) ' + + 'must be returned. You have returned undefined.', + getComponentName(finishedWork) + ) + } + } + _instance.__reactInternalSnapshotBeforeUpdate = snapshot + stopPhaseTimer() + } + } + return + } + case HostRoot: + case HostComponent: + case HostText: + case HostPortal: + // Nothing to do for these component types + return + default: { + invariant( + false, + 'This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue.' + ) + } + } + } + + function commitLifeCycles( + finishedRoot, + current, + finishedWork, + currentTime, + committedExpirationTime + ) { + switch (finishedWork.tag) { + case ClassComponent: { + var _instance2 = finishedWork.stateNode + if (finishedWork.effectTag & Update) { + if (current === null) { + startPhaseTimer(finishedWork, 'componentDidMount') + _instance2.props = finishedWork.memoizedProps + _instance2.state = finishedWork.memoizedState + _instance2.componentDidMount() + stopPhaseTimer() + } else { + var prevProps = current.memoizedProps + var prevState = current.memoizedState + startPhaseTimer(finishedWork, 'componentDidUpdate') + _instance2.props = finishedWork.memoizedProps + _instance2.state = finishedWork.memoizedState + _instance2.componentDidUpdate( + prevProps, + prevState, + _instance2.__reactInternalSnapshotBeforeUpdate + ) + stopPhaseTimer() + } + } + var updateQueue = finishedWork.updateQueue + if (updateQueue !== null) { + commitCallbacks(updateQueue, _instance2) + } + return + } + case HostRoot: { + var _updateQueue = finishedWork.updateQueue + if (_updateQueue !== null) { + var _instance3 = null + if (finishedWork.child !== null) { + switch (finishedWork.child.tag) { + case HostComponent: + _instance3 = getPublicInstance( + finishedWork.child.stateNode + ) + break + case ClassComponent: + _instance3 = finishedWork.child.stateNode + break + } + } + commitCallbacks(_updateQueue, _instance3) + } + return + } + case HostComponent: { + var _instance4 = finishedWork.stateNode + + // Renderers may schedule work to be done after host components are mounted + // (eg DOM renderer may schedule auto-focus for inputs and form controls). + // These effects should only be committed when components are first mounted, + // aka when there is no current/alternate. + if ( + current === null && + finishedWork.effectTag & Update + ) { + var type = finishedWork.type + var props = finishedWork.memoizedProps + commitMount(_instance4, type, props, finishedWork) + } + + return + } + case HostText: { + // We have no life-cycles associated with text. + return + } + case HostPortal: { + // We have no life-cycles associated with portals. + return + } + default: { + invariant( + false, + 'This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue.' + ) + } + } + } + + function commitErrorLogging(finishedWork, onUncaughtError) { + switch (finishedWork.tag) { + case ClassComponent: + { + var ctor = finishedWork.type + var _instance5 = finishedWork.stateNode + var updateQueue = finishedWork.updateQueue + !( + updateQueue !== null && + updateQueue.capturedValues !== null + ) + ? invariant( + false, + 'An error logging effect should not have been scheduled if no errors were captured. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + var capturedErrors = updateQueue.capturedValues + updateQueue.capturedValues = null + + if ( + typeof ctor.getDerivedStateFromCatch !== 'function' + ) { + // To preserve the preexisting retry behavior of error boundaries, + // we keep track of which ones already failed during this batch. + // This gets reset before we yield back to the browser. + // TODO: Warn in strict mode if getDerivedStateFromCatch is + // not defined. + markLegacyErrorBoundaryAsFailed(_instance5) + } + + _instance5.props = finishedWork.memoizedProps + _instance5.state = finishedWork.memoizedState + for (var i = 0; i < capturedErrors.length; i++) { + var errorInfo = capturedErrors[i] + var _error = errorInfo.value + var stack = errorInfo.stack + logError(finishedWork, errorInfo) + _instance5.componentDidCatch(_error, { + componentStack: stack !== null ? stack : '', + }) + } + } + break + case HostRoot: { + var _updateQueue2 = finishedWork.updateQueue + !( + _updateQueue2 !== null && + _updateQueue2.capturedValues !== null + ) + ? invariant( + false, + 'An error logging effect should not have been scheduled if no errors were captured. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + var _capturedErrors = _updateQueue2.capturedValues + _updateQueue2.capturedValues = null + for (var _i = 0; _i < _capturedErrors.length; _i++) { + var _errorInfo = _capturedErrors[_i] + logError(finishedWork, _errorInfo) + onUncaughtError(_errorInfo.value) + } + break + } + default: + invariant( + false, + 'This unit of work tag cannot capture errors. This error is likely caused by a bug in React. Please file an issue.' + ) + } + } + + function commitAttachRef(finishedWork) { + var ref = finishedWork.ref + if (ref !== null) { + var _instance6 = finishedWork.stateNode + var instanceToUse = void 0 + switch (finishedWork.tag) { + case HostComponent: + instanceToUse = getPublicInstance(_instance6) + break + default: + instanceToUse = _instance6 + } + if (typeof ref === 'function') { + ref(instanceToUse) + } else { + { + if (!ref.hasOwnProperty('current')) { + warning( + false, + 'Unexpected ref object provided for %s. ' + + 'Use either a ref-setter function or React.createRef().%s', + getComponentName(finishedWork), + getStackAddendumByWorkInProgressFiber( + finishedWork + ) + ) + } + } + + ref.current = instanceToUse + } + } + } + + function commitDetachRef(current) { + var currentRef = current.ref + if (currentRef !== null) { + if (typeof currentRef === 'function') { + currentRef(null) + } else { + currentRef.current = null + } + } + } + + // User-originating errors (lifecycles and refs) should not interrupt + // deletion, so don't let them throw. Host-originating errors should + // interrupt deletion, so it's okay + function commitUnmount(current) { + if (typeof onCommitUnmount === 'function') { + onCommitUnmount(current) + } + + switch (current.tag) { + case ClassComponent: { + safelyDetachRef(current) + var _instance7 = current.stateNode + if ( + typeof _instance7.componentWillUnmount === 'function' + ) { + safelyCallComponentWillUnmount(current, _instance7) + } + return + } + case HostComponent: { + safelyDetachRef(current) + return + } + case CallComponent: { + commitNestedUnmounts(current.stateNode) + return + } + case HostPortal: { + // TODO: this is recursive. + // We are also not using this parent because + // the portal will get pushed immediately. + if (enableMutatingReconciler && mutation) { + unmountHostComponents(current) + } else if (enablePersistentReconciler && persistence) { + emptyPortalContainer(current) + } + return + } + } + } + + function commitNestedUnmounts(root) { + // While we're inside a removed host node we don't want to call + // removeChild on the inner nodes because they're removed by the top + // call anyway. We also want to call componentWillUnmount on all + // composites before this host node is removed from the tree. Therefore + var node = root + while (true) { + commitUnmount(node) + // Visit children because they may contain more composite or host nodes. + // Skip portals because commitUnmount() currently visits them recursively. + if ( + node.child !== null && + // If we use mutation we drill down into portals using commitUnmount above. + // If we don't use mutation we drill down into portals here instead. + (!mutation || node.tag !== HostPortal) + ) { + node.child['return'] = node + node = node.child + continue + } + if (node === root) { + return + } + while (node.sibling === null) { + if ( + node['return'] === null || + node['return'] === root + ) { + return + } + node = node['return'] + } + node.sibling['return'] = node['return'] + node = node.sibling + } + } + + function detachFiber(current) { + // Cut off the return pointers to disconnect it from the tree. Ideally, we + // should clear the child pointer of the parent alternate to let this + // get GC:ed but we don't know which for sure which parent is the current + // one so we'll settle for GC:ing the subtree of this child. This child + // itself will be GC:ed when the parent updates the next time. + current['return'] = null + current.child = null + if (current.alternate) { + current.alternate.child = null + current.alternate['return'] = null + } + } + + var emptyPortalContainer = void 0 + + if (!mutation) { + var commitContainer = void 0 + if (persistence) { + var replaceContainerChildren = + persistence.replaceContainerChildren, + createContainerChildSet = + persistence.createContainerChildSet + + emptyPortalContainer = function (current) { + var portal = current.stateNode + var containerInfo = portal.containerInfo + + var emptyChildSet = createContainerChildSet( + containerInfo + ) + replaceContainerChildren(containerInfo, emptyChildSet) + } + commitContainer = function (finishedWork) { + switch (finishedWork.tag) { + case ClassComponent: { + return + } + case HostComponent: { + return + } + case HostText: { + return + } + case HostRoot: + case HostPortal: { + var portalOrRoot = finishedWork.stateNode + var containerInfo = portalOrRoot.containerInfo, + _pendingChildren = portalOrRoot.pendingChildren + + replaceContainerChildren( + containerInfo, + _pendingChildren + ) + return + } + default: { + invariant( + false, + 'This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue.' + ) + } + } + } + } else { + commitContainer = function (finishedWork) { + // Noop + } + } + if (enablePersistentReconciler || enableNoopReconciler) { + return { + commitResetTextContent: function (finishedWork) {}, + commitPlacement: function (finishedWork) {}, + commitDeletion: function (current) { + // Detach refs and call componentWillUnmount() on the whole subtree. + commitNestedUnmounts(current) + detachFiber(current) + }, + commitWork: function (current, finishedWork) { + commitContainer(finishedWork) + }, + + commitLifeCycles: commitLifeCycles, + commitBeforeMutationLifeCycles: commitBeforeMutationLifeCycles, + commitErrorLogging: commitErrorLogging, + commitAttachRef: commitAttachRef, + commitDetachRef: commitDetachRef, + } + } else if (persistence) { + invariant(false, 'Persistent reconciler is disabled.') + } else { + invariant(false, 'Noop reconciler is disabled.') + } + } + var commitMount = mutation.commitMount, + commitUpdate = mutation.commitUpdate, + resetTextContent = mutation.resetTextContent, + commitTextUpdate = mutation.commitTextUpdate, + appendChild = mutation.appendChild, + appendChildToContainer = mutation.appendChildToContainer, + insertBefore = mutation.insertBefore, + insertInContainerBefore = mutation.insertInContainerBefore, + removeChild = mutation.removeChild, + removeChildFromContainer = mutation.removeChildFromContainer + + function getHostParentFiber(fiber) { + var parent = fiber['return'] + while (parent !== null) { + if (isHostParent(parent)) { + return parent + } + parent = parent['return'] + } + invariant( + false, + 'Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue.' + ) + } + + function isHostParent(fiber) { + return ( + fiber.tag === HostComponent || + fiber.tag === HostRoot || + fiber.tag === HostPortal + ) + } + + function getHostSibling(fiber) { + // We're going to search forward into the tree until we find a sibling host + // node. Unfortunately, if multiple insertions are done in a row we have to + // search past them. This leads to exponential search for the next sibling. + var node = fiber + siblings: while (true) { + // If we didn't find anything, let's try the next sibling. + while (node.sibling === null) { + if ( + node['return'] === null || + isHostParent(node['return']) + ) { + // If we pop out of the root or hit the parent the fiber we are the + // last sibling. + return null + } + node = node['return'] + } + node.sibling['return'] = node['return'] + node = node.sibling + while ( + node.tag !== HostComponent && + node.tag !== HostText + ) { + // If it is not host node and, we might have a host node inside it. + // Try to search down until we find one. + if (node.effectTag & Placement) { + // If we don't have a child, try the siblings instead. + continue siblings + } + // If we don't have a child, try the siblings instead. + // We also skip portals because they are not part of this host tree. + if (node.child === null || node.tag === HostPortal) { + continue siblings + } else { + node.child['return'] = node + node = node.child + } + } + // Check if this host node is stable or about to be placed. + if (!(node.effectTag & Placement)) { + // Found it! + return node.stateNode + } + } + } + + function commitPlacement(finishedWork) { + // Recursively insert all host nodes into the parent. + var parentFiber = getHostParentFiber(finishedWork) + var parent = void 0 + var isContainer = void 0 + switch (parentFiber.tag) { + case HostComponent: + parent = parentFiber.stateNode + isContainer = false + break + case HostRoot: + parent = parentFiber.stateNode.containerInfo + isContainer = true + break + case HostPortal: + parent = parentFiber.stateNode.containerInfo + isContainer = true + break + default: + invariant( + false, + 'Invalid host parent fiber. This error is likely caused by a bug in React. Please file an issue.' + ) + } + if (parentFiber.effectTag & ContentReset) { + // Reset the text content of the parent before doing any insertions + resetTextContent(parent) + // Clear ContentReset from the effect tag + parentFiber.effectTag &= ~ContentReset + } + + var before = getHostSibling(finishedWork) + // We only have the top Fiber that was inserted but we need recurse down its + // children to find all the terminal nodes. + var node = finishedWork + while (true) { + if (node.tag === HostComponent || node.tag === HostText) { + if (before) { + if (isContainer) { + insertInContainerBefore( + parent, + node.stateNode, + before + ) + } else { + insertBefore(parent, node.stateNode, before) + } + } else { + if (isContainer) { + appendChildToContainer(parent, node.stateNode) + } else { + appendChild(parent, node.stateNode) + } + } + } else if (node.tag === HostPortal) { + // If the insertion itself is a portal, then we don't want to traverse + // down its children. Instead, we'll get insertions from each child in + // the portal directly. + } else if (node.child !== null) { + node.child['return'] = node + node = node.child + continue + } + if (node === finishedWork) { + return + } + while (node.sibling === null) { + if ( + node['return'] === null || + node['return'] === finishedWork + ) { + return + } + node = node['return'] + } + node.sibling['return'] = node['return'] + node = node.sibling + } + } + + function unmountHostComponents(current) { + // We only have the top Fiber that was inserted but we need recurse down its + var node = current + + // Each iteration, currentParent is populated with node's host parent if not + // currentParentIsValid. + var currentParentIsValid = false + var currentParent = void 0 + var currentParentIsContainer = void 0 + + while (true) { + if (!currentParentIsValid) { + var parent = node['return'] + findParent: while (true) { + !(parent !== null) + ? invariant( + false, + 'Expected to find a host parent. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + switch (parent.tag) { + case HostComponent: + currentParent = parent.stateNode + currentParentIsContainer = false + break findParent + case HostRoot: + currentParent = parent.stateNode.containerInfo + currentParentIsContainer = true + break findParent + case HostPortal: + currentParent = parent.stateNode.containerInfo + currentParentIsContainer = true + break findParent + } + parent = parent['return'] + } + currentParentIsValid = true + } + + if (node.tag === HostComponent || node.tag === HostText) { + commitNestedUnmounts(node) + // After all the children have unmounted, it is now safe to remove the + // node from the tree. + if (currentParentIsContainer) { + removeChildFromContainer( + currentParent, + node.stateNode + ) + } else { + removeChild(currentParent, node.stateNode) + } + // Don't visit children because we already visited them. + } else if (node.tag === HostPortal) { + // When we go into a portal, it becomes the parent to remove from. + // We will reassign it back when we pop the portal on the way up. + currentParent = node.stateNode.containerInfo + // Visit children because portals might contain host components. + if (node.child !== null) { + node.child['return'] = node + node = node.child + continue + } + } else { + commitUnmount(node) + // Visit children because we may find more host components below. + if (node.child !== null) { + node.child['return'] = node + node = node.child + continue + } + } + if (node === current) { + return + } + while (node.sibling === null) { + if ( + node['return'] === null || + node['return'] === current + ) { + return + } + node = node['return'] + if (node.tag === HostPortal) { + // When we go out of the portal, we need to restore the parent. + // Since we don't keep a stack of them, we will search for it. + currentParentIsValid = false + } + } + node.sibling['return'] = node['return'] + node = node.sibling + } + } + + function commitDeletion(current) { + // Recursively delete all host nodes from the parent. + // Detach refs and call componentWillUnmount() on the whole subtree. + unmountHostComponents(current) + detachFiber(current) + } + + function commitWork(current, finishedWork) { + switch (finishedWork.tag) { + case ClassComponent: { + return + } + case HostComponent: { + var _instance8 = finishedWork.stateNode + if (_instance8 != null) { + // Commit the work prepared earlier. + var newProps = finishedWork.memoizedProps + // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. + var oldProps = + current !== null ? current.memoizedProps : newProps + var type = finishedWork.type + // TODO: Type the updateQueue to be specific to host components. + var updatePayload = finishedWork.updateQueue + finishedWork.updateQueue = null + if (updatePayload !== null) { + commitUpdate( + _instance8, + updatePayload, + type, + oldProps, + newProps, + finishedWork + ) + } + } + return + } + case HostText: { + !(finishedWork.stateNode !== null) + ? invariant( + false, + 'This should have a text node initialized. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + var textInstance = finishedWork.stateNode + var newText = finishedWork.memoizedProps + // For hydration we reuse the update path but we treat the oldProps + // as the newProps. The updatePayload will contain the real change in + // this case. + var oldText = + current !== null ? current.memoizedProps : newText + commitTextUpdate(textInstance, oldText, newText) + return + } + case HostRoot: { + return + } + default: { + invariant( + false, + 'This unit of work tag should not have side-effects. This error is likely caused by a bug in React. Please file an issue.' + ) + } + } + } + + function commitResetTextContent(current) { + resetTextContent(current.stateNode) + } + + if (enableMutatingReconciler) { + return { + commitBeforeMutationLifeCycles: commitBeforeMutationLifeCycles, + commitResetTextContent: commitResetTextContent, + commitPlacement: commitPlacement, + commitDeletion: commitDeletion, + commitWork: commitWork, + commitLifeCycles: commitLifeCycles, + commitErrorLogging: commitErrorLogging, + commitAttachRef: commitAttachRef, + commitDetachRef: commitDetachRef, + } + } else { + invariant(false, 'Mutating reconciler is disabled.') + } + } - // Cache unmasked context so we can avoid recreating masked context unless necessary. - // ReactFiberContext usually updates this cache but can't for newly-created instances. - if (needsContext) { - cacheContext(workInProgress, unmaskedContext, context); - } + var NO_CONTEXT = {} + + var ReactFiberHostContext = function (config, stack) { + var getChildHostContext = config.getChildHostContext, + getRootHostContext = config.getRootHostContext + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop + + var contextStackCursor = createCursor(NO_CONTEXT) + var contextFiberStackCursor = createCursor(NO_CONTEXT) + var rootInstanceStackCursor = createCursor(NO_CONTEXT) + + function requiredContext(c) { + !(c !== NO_CONTEXT) + ? invariant( + false, + 'Expected host context to exist. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + return c + } + + function getRootHostContainer() { + var rootInstance = requiredContext( + rootInstanceStackCursor.current + ) + return rootInstance + } + + function pushHostContainer(fiber, nextRootInstance) { + // Push current root instance onto the stack; + // This allows us to reset root when portals are popped. + push(rootInstanceStackCursor, nextRootInstance, fiber) + // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. + push(contextFiberStackCursor, fiber, fiber) + + // Finally, we need to push the host context to the stack. + // However, we can't just call getRootHostContext() and push it because + // we'd have a different number of entries on the stack depending on + // whether getRootHostContext() throws somewhere in renderer code or not. + // So we push an empty value first. This lets us safely unwind on errors. + push(contextStackCursor, NO_CONTEXT, fiber) + var nextRootContext = getRootHostContext(nextRootInstance) + // Now that we know this function doesn't throw, replace it. + pop(contextStackCursor, fiber) + push(contextStackCursor, nextRootContext, fiber) + } + + function popHostContainer(fiber) { + pop(contextStackCursor, fiber) + pop(contextFiberStackCursor, fiber) + pop(rootInstanceStackCursor, fiber) + } + + function getHostContext() { + var context = requiredContext(contextStackCursor.current) + return context + } + + function pushHostContext(fiber) { + var rootInstance = requiredContext( + rootInstanceStackCursor.current + ) + var context = requiredContext(contextStackCursor.current) + var nextContext = getChildHostContext( + context, + fiber.type, + rootInstance + ) + + // Don't push this Fiber's context unless it's unique. + if (context === nextContext) { + return + } + + // Track the context and the Fiber that provided it. + // This enables us to pop only Fibers that provide unique contexts. + push(contextFiberStackCursor, fiber, fiber) + push(contextStackCursor, nextContext, fiber) + } + + function popHostContext(fiber) { + // Do not pop unless this Fiber provided the current context. + // pushHostContext() only pushes Fibers that provide unique contexts. + if (contextFiberStackCursor.current !== fiber) { + return + } + + pop(contextStackCursor, fiber) + pop(contextFiberStackCursor, fiber) + } + + return { + getHostContext: getHostContext, + getRootHostContainer: getRootHostContainer, + popHostContainer: popHostContainer, + popHostContext: popHostContext, + pushHostContainer: pushHostContainer, + pushHostContext: pushHostContext, + } + } - return instance; - } + var ReactFiberHydrationContext = function (config) { + var shouldSetTextContent = config.shouldSetTextContent, + hydration = config.hydration + + // If this doesn't have hydration mode. + + if (!hydration) { + return { + enterHydrationState: function () { + return false + }, + resetHydrationState: function () {}, + tryToClaimNextHydratableInstance: function () {}, + prepareToHydrateHostInstance: function () { + invariant( + false, + 'Expected prepareToHydrateHostInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.' + ) + }, + prepareToHydrateHostTextInstance: function () { + invariant( + false, + 'Expected prepareToHydrateHostTextInstance() to never be called. This error is likely caused by a bug in React. Please file an issue.' + ) + }, + popHydrationState: function (fiber) { + return false + }, + } + } + + var canHydrateInstance = hydration.canHydrateInstance, + canHydrateTextInstance = hydration.canHydrateTextInstance, + getNextHydratableSibling = + hydration.getNextHydratableSibling, + getFirstHydratableChild = hydration.getFirstHydratableChild, + hydrateInstance = hydration.hydrateInstance, + hydrateTextInstance = hydration.hydrateTextInstance, + didNotMatchHydratedContainerTextInstance = + hydration.didNotMatchHydratedContainerTextInstance, + didNotMatchHydratedTextInstance = + hydration.didNotMatchHydratedTextInstance, + didNotHydrateContainerInstance = + hydration.didNotHydrateContainerInstance, + didNotHydrateInstance = hydration.didNotHydrateInstance, + didNotFindHydratableContainerInstance = + hydration.didNotFindHydratableContainerInstance, + didNotFindHydratableContainerTextInstance = + hydration.didNotFindHydratableContainerTextInstance, + didNotFindHydratableInstance = + hydration.didNotFindHydratableInstance, + didNotFindHydratableTextInstance = + hydration.didNotFindHydratableTextInstance + + // The deepest Fiber on the stack involved in a hydration context. + // This may have been an insertion or a hydration. + + var hydrationParentFiber = null + var nextHydratableInstance = null + var isHydrating = false + + function enterHydrationState(fiber) { + var parentInstance = fiber.stateNode.containerInfo + nextHydratableInstance = getFirstHydratableChild( + parentInstance + ) + hydrationParentFiber = fiber + isHydrating = true + return true + } + + function deleteHydratableInstance(returnFiber, instance) { + { + switch (returnFiber.tag) { + case HostRoot: + didNotHydrateContainerInstance( + returnFiber.stateNode.containerInfo, + instance + ) + break + case HostComponent: + didNotHydrateInstance( + returnFiber.type, + returnFiber.memoizedProps, + returnFiber.stateNode, + instance + ) + break + } + } + + var childToDelete = createFiberFromHostInstanceForDeletion() + childToDelete.stateNode = instance + childToDelete['return'] = returnFiber + childToDelete.effectTag = Deletion + + // This might seem like it belongs on progressedFirstDeletion. However, + // these children are not part of the reconciliation list of children. + // Even if we abort and rereconcile the children, that will try to hydrate + // again and the nodes are still in the host tree so these will be + // recreated. + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = childToDelete + returnFiber.lastEffect = childToDelete + } else { + returnFiber.firstEffect = returnFiber.lastEffect = childToDelete + } + } + + function insertNonHydratedInstance(returnFiber, fiber) { + fiber.effectTag |= Placement + { + switch (returnFiber.tag) { + case HostRoot: { + var parentContainer = + returnFiber.stateNode.containerInfo + switch (fiber.tag) { + case HostComponent: + var type = fiber.type + var props = fiber.pendingProps + didNotFindHydratableContainerInstance( + parentContainer, + type, + props + ) + break + case HostText: + var text = fiber.pendingProps + didNotFindHydratableContainerTextInstance( + parentContainer, + text + ) + break + } + break + } + case HostComponent: { + var parentType = returnFiber.type + var parentProps = returnFiber.memoizedProps + var parentInstance = returnFiber.stateNode + switch (fiber.tag) { + case HostComponent: + var _type = fiber.type + var _props = fiber.pendingProps + didNotFindHydratableInstance( + parentType, + parentProps, + parentInstance, + _type, + _props + ) + break + case HostText: + var _text = fiber.pendingProps + didNotFindHydratableTextInstance( + parentType, + parentProps, + parentInstance, + _text + ) + break + } + break + } + default: + return + } + } + } + + function tryHydrate(fiber, nextInstance) { + switch (fiber.tag) { + case HostComponent: { + var type = fiber.type + var props = fiber.pendingProps + var instance = canHydrateInstance( + nextInstance, + type, + props + ) + if (instance !== null) { + fiber.stateNode = instance + return true + } + return false + } + case HostText: { + var text = fiber.pendingProps + var textInstance = canHydrateTextInstance( + nextInstance, + text + ) + if (textInstance !== null) { + fiber.stateNode = textInstance + return true + } + return false + } + default: + return false + } + } + + function tryToClaimNextHydratableInstance(fiber) { + if (!isHydrating) { + return + } + var nextInstance = nextHydratableInstance + if (!nextInstance) { + // Nothing to hydrate. Make it an insertion. + insertNonHydratedInstance(hydrationParentFiber, fiber) + isHydrating = false + hydrationParentFiber = fiber + return + } + if (!tryHydrate(fiber, nextInstance)) { + // If we can't hydrate this instance let's try the next one. + // We use this as a heuristic. It's based on intuition and not data so it + // might be flawed or unnecessary. + nextInstance = getNextHydratableSibling(nextInstance) + if (!nextInstance || !tryHydrate(fiber, nextInstance)) { + // Nothing to hydrate. Make it an insertion. + insertNonHydratedInstance(hydrationParentFiber, fiber) + isHydrating = false + hydrationParentFiber = fiber + return + } + // We matched the next one, we'll now assume that the first one was + // superfluous and we'll delete it. Since we can't eagerly delete it + // we'll have to schedule a deletion. To do that, this node needs a dummy + // fiber associated with it. + deleteHydratableInstance( + hydrationParentFiber, + nextHydratableInstance + ) + } + hydrationParentFiber = fiber + nextHydratableInstance = getFirstHydratableChild( + nextInstance + ) + } + + function prepareToHydrateHostInstance( + fiber, + rootContainerInstance, + hostContext + ) { + var instance = fiber.stateNode + var updatePayload = hydrateInstance( + instance, + fiber.type, + fiber.memoizedProps, + rootContainerInstance, + hostContext, + fiber + ) + // TODO: Type this specific to this type of component. + fiber.updateQueue = updatePayload + // If the update payload indicates that there is a change or if there + // is a new ref we mark this as an update. + if (updatePayload !== null) { + return true + } + return false + } + + function prepareToHydrateHostTextInstance(fiber) { + var textInstance = fiber.stateNode + var textContent = fiber.memoizedProps + var shouldUpdate = hydrateTextInstance( + textInstance, + textContent, + fiber + ) + { + if (shouldUpdate) { + // We assume that prepareToHydrateHostTextInstance is called in a context where the + // hydration parent is the parent host component of this host text. + var returnFiber = hydrationParentFiber + if (returnFiber !== null) { + switch (returnFiber.tag) { + case HostRoot: { + var parentContainer = + returnFiber.stateNode.containerInfo + didNotMatchHydratedContainerTextInstance( + parentContainer, + textInstance, + textContent + ) + break + } + case HostComponent: { + var parentType = returnFiber.type + var parentProps = returnFiber.memoizedProps + var parentInstance = returnFiber.stateNode + didNotMatchHydratedTextInstance( + parentType, + parentProps, + parentInstance, + textInstance, + textContent + ) + break + } + } + } + } + } + return shouldUpdate + } + + function popToNextHostParent(fiber) { + var parent = fiber['return'] + while ( + parent !== null && + parent.tag !== HostComponent && + parent.tag !== HostRoot + ) { + parent = parent['return'] + } + hydrationParentFiber = parent + } + + function popHydrationState(fiber) { + if (fiber !== hydrationParentFiber) { + // We're deeper than the current hydration context, inside an inserted + // tree. + return false + } + if (!isHydrating) { + // If we're not currently hydrating but we're in a hydration context, then + // we were an insertion and now need to pop up reenter hydration of our + // siblings. + popToNextHostParent(fiber) + isHydrating = true + return false + } + + var type = fiber.type + + // If we have any remaining hydratable nodes, we need to delete them now. + // We only do this deeper than head and body since they tend to have random + // other nodes in them. We also ignore components with pure text content in + // side of them. + // TODO: Better heuristic. + if ( + fiber.tag !== HostComponent || + (type !== 'head' && + type !== 'body' && + !shouldSetTextContent(type, fiber.memoizedProps)) + ) { + var nextInstance = nextHydratableInstance + while (nextInstance) { + deleteHydratableInstance(fiber, nextInstance) + nextInstance = getNextHydratableSibling(nextInstance) + } + } + + popToNextHostParent(fiber) + nextHydratableInstance = hydrationParentFiber + ? getNextHydratableSibling(fiber.stateNode) + : null + return true + } + + function resetHydrationState() { + hydrationParentFiber = null + nextHydratableInstance = null + isHydrating = false + } + + return { + enterHydrationState: enterHydrationState, + resetHydrationState: resetHydrationState, + tryToClaimNextHydratableInstance: tryToClaimNextHydratableInstance, + prepareToHydrateHostInstance: prepareToHydrateHostInstance, + prepareToHydrateHostTextInstance: prepareToHydrateHostTextInstance, + popHydrationState: popHydrationState, + } + } - function callComponentWillMount(workInProgress, instance) { - startPhaseTimer(workInProgress, 'componentWillMount'); - var oldState = instance.state; + // This lets us hook into Fiber to debug what it's doing. + // See https://github.com/facebook/react/pull/8033. + // This is not part of the public API, not even for React DevTools. + // You may only inject a debugTool if you work on React Fiber itself. + var ReactFiberInstrumentation = { + debugTool: null, + } - if (typeof instance.componentWillMount === 'function') { - instance.componentWillMount(); - } - if (typeof instance.UNSAFE_componentWillMount === 'function') { - instance.UNSAFE_componentWillMount(); - } + var ReactFiberInstrumentation_1 = ReactFiberInstrumentation - stopPhaseTimer(); + var warnedAboutMissingGetChildContext = void 0 - if (oldState !== instance.state) { - { - warning(false, '%s.componentWillMount(): Assigning directly to this.state is ' + "deprecated (except inside a component's " + 'constructor). Use setState instead.', getComponentName(workInProgress) || 'Component'); - } - updater.enqueueReplaceState(instance, instance.state, null); - } - } + { + warnedAboutMissingGetChildContext = {} + } - function callComponentWillReceiveProps(workInProgress, instance, newProps, newContext) { - var oldState = instance.state; - startPhaseTimer(workInProgress, 'componentWillReceiveProps'); - if (typeof instance.componentWillReceiveProps === 'function') { - instance.componentWillReceiveProps(newProps, newContext); - } - if (typeof instance.UNSAFE_componentWillReceiveProps === 'function') { - instance.UNSAFE_componentWillReceiveProps(newProps, newContext); - } - stopPhaseTimer(); - - if (instance.state !== oldState) { - { - var componentName = getComponentName(workInProgress) || 'Component'; - if (!didWarnAboutStateAssignmentForComponent.has(componentName)) { - didWarnAboutStateAssignmentForComponent.add(componentName); - warning(false, '%s.componentWillReceiveProps(): Assigning directly to ' + "this.state is deprecated (except inside a component's " + 'constructor). Use setState instead.', componentName); - } - } - updater.enqueueReplaceState(instance, instance.state, null); - } - } + var ReactFiberLegacyContext = function (stack) { + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop + + // A cursor to the current merged context object on the stack. + + var contextStackCursor = createCursor(emptyObject) + // A cursor to a boolean indicating whether the context has changed. + var didPerformWorkStackCursor = createCursor(false) + // Keep track of the previous context object that was on the stack. + // We use this to get access to the parent context after we have already + // pushed the next context provider, and now need to merge their contexts. + var previousContext = emptyObject + + function getUnmaskedContext(workInProgress) { + var hasOwnContext = isContextProvider(workInProgress) + if (hasOwnContext) { + // If the fiber is a context provider itself, when we read its context + // we have already pushed its own child context on the stack. A context + // provider should not "see" its own child context. Therefore we read the + // previous (parent) context instead for a context provider. + return previousContext + } + return contextStackCursor.current + } + + function cacheContext( + workInProgress, + unmaskedContext, + maskedContext + ) { + var instance = workInProgress.stateNode + instance.__reactInternalMemoizedUnmaskedChildContext = unmaskedContext + instance.__reactInternalMemoizedMaskedChildContext = maskedContext + } + + function getMaskedContext(workInProgress, unmaskedContext) { + var type = workInProgress.type + var contextTypes = type.contextTypes + if (!contextTypes) { + return emptyObject + } + + // Avoid recreating masked context unless unmasked context has changed. + // Failing to do this will result in unnecessary calls to componentWillReceiveProps. + // This may trigger infinite loops if componentWillReceiveProps calls setState. + var instance = workInProgress.stateNode + if ( + instance && + instance.__reactInternalMemoizedUnmaskedChildContext === + unmaskedContext + ) { + return instance.__reactInternalMemoizedMaskedChildContext + } + + var context = {} + for (var key in contextTypes) { + context[key] = unmaskedContext[key] + } + + { + var name = getComponentName(workInProgress) || 'Unknown' + checkPropTypes( + contextTypes, + context, + 'context', + name, + ReactDebugCurrentFiber.getCurrentFiberStackAddendum + ) + } + + // Cache unmasked context so we can avoid recreating masked context unless necessary. + // Context is created before the class component is instantiated so check for instance. + if (instance) { + cacheContext(workInProgress, unmaskedContext, context) + } + + return context + } + + function hasContextChanged() { + return didPerformWorkStackCursor.current + } + + function isContextConsumer(fiber) { + return ( + fiber.tag === ClassComponent && + fiber.type.contextTypes != null + ) + } + + function isContextProvider(fiber) { + return ( + fiber.tag === ClassComponent && + fiber.type.childContextTypes != null + ) + } + + function popContextProvider(fiber) { + if (!isContextProvider(fiber)) { + return + } + + pop(didPerformWorkStackCursor, fiber) + pop(contextStackCursor, fiber) + } + + function popTopLevelContextObject(fiber) { + pop(didPerformWorkStackCursor, fiber) + pop(contextStackCursor, fiber) + } + + function pushTopLevelContextObject( + fiber, + context, + didChange + ) { + !(contextStackCursor.cursor == null) + ? invariant( + false, + 'Unexpected context found on stack. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + + push(contextStackCursor, context, fiber) + push(didPerformWorkStackCursor, didChange, fiber) + } + + function processChildContext(fiber, parentContext) { + var instance = fiber.stateNode + var childContextTypes = fiber.type.childContextTypes + + // TODO (bvaughn) Replace this behavior with an invariant() in the future. + // It has only been added in Fiber to match the (unintentional) behavior in Stack. + if (typeof instance.getChildContext !== 'function') { + { + var componentName = getComponentName(fiber) || 'Unknown' + + if (!warnedAboutMissingGetChildContext[componentName]) { + warnedAboutMissingGetChildContext[ + componentName + ] = true + warning( + false, + '%s.childContextTypes is specified but there is no getChildContext() method ' + + 'on the instance. You can either define getChildContext() on %s or remove ' + + 'childContextTypes from it.', + componentName, + componentName + ) + } + } + return parentContext + } + + var childContext = void 0 + { + ReactDebugCurrentFiber.setCurrentPhase('getChildContext') + } + startPhaseTimer(fiber, 'getChildContext') + childContext = instance.getChildContext() + stopPhaseTimer() + { + ReactDebugCurrentFiber.setCurrentPhase(null) + } + for (var contextKey in childContext) { + !(contextKey in childContextTypes) + ? invariant( + false, + '%s.getChildContext(): key "%s" is not defined in childContextTypes.', + getComponentName(fiber) || 'Unknown', + contextKey + ) + : void 0 + } + { + var name = getComponentName(fiber) || 'Unknown' + checkPropTypes( + childContextTypes, + childContext, + 'child context', + name, + // In practice, there is one case in which we won't get a stack. It's when + // somebody calls unstable_renderSubtreeIntoContainer() and we process + // context from the parent component instance. The stack will be missing + // because it's outside of the reconciliation, and so the pointer has not + // been set. This is rare and doesn't matter. We'll also remove that API. + ReactDebugCurrentFiber.getCurrentFiberStackAddendum + ) + } + + return _assign({}, parentContext, childContext) + } + + function pushContextProvider(workInProgress) { + if (!isContextProvider(workInProgress)) { + return false + } + + var instance = workInProgress.stateNode + // We push the context as early as possible to ensure stack integrity. + // If the instance does not exist yet, we will push null at first, + // and replace it on the stack later when invalidating the context. + var memoizedMergedChildContext = + (instance && + instance.__reactInternalMemoizedMergedChildContext) || + emptyObject + + // Remember the parent context so we can merge with it later. + // Inherit the parent's did-perform-work value to avoid inadvertently blocking updates. + previousContext = contextStackCursor.current + push( + contextStackCursor, + memoizedMergedChildContext, + workInProgress + ) + push( + didPerformWorkStackCursor, + didPerformWorkStackCursor.current, + workInProgress + ) + + return true + } + + function invalidateContextProvider( + workInProgress, + didChange + ) { + var instance = workInProgress.stateNode + !instance + ? invariant( + false, + 'Expected to have an instance by this point. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + + if (didChange) { + // Merge parent and own context. + // Skip this if we're not updating due to sCU. + // This avoids unnecessarily recomputing memoized values. + var mergedContext = processChildContext( + workInProgress, + previousContext + ) + instance.__reactInternalMemoizedMergedChildContext = mergedContext + + // Replace the old (or empty) context with the new one. + // It is important to unwind the context in the reverse order. + pop(didPerformWorkStackCursor, workInProgress) + pop(contextStackCursor, workInProgress) + // Now push the new context and mark that it has changed. + push(contextStackCursor, mergedContext, workInProgress) + push(didPerformWorkStackCursor, didChange, workInProgress) + } else { + pop(didPerformWorkStackCursor, workInProgress) + push(didPerformWorkStackCursor, didChange, workInProgress) + } + } + + function findCurrentUnmaskedContext(fiber) { + // Currently this is only used with renderSubtreeIntoContainer; not sure if it + // makes sense elsewhere + !(isFiberMounted(fiber) && fiber.tag === ClassComponent) + ? invariant( + false, + 'Expected subtree parent to be a mounted class component. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + + var node = fiber + while (node.tag !== HostRoot) { + if (isContextProvider(node)) { + return node.stateNode + .__reactInternalMemoizedMergedChildContext + } + var parent = node['return'] + !parent + ? invariant( + false, + 'Found unexpected detached subtree parent. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + node = parent + } + return node.stateNode.context + } + + return { + getUnmaskedContext: getUnmaskedContext, + cacheContext: cacheContext, + getMaskedContext: getMaskedContext, + hasContextChanged: hasContextChanged, + isContextConsumer: isContextConsumer, + isContextProvider: isContextProvider, + popContextProvider: popContextProvider, + popTopLevelContextObject: popTopLevelContextObject, + pushTopLevelContextObject: pushTopLevelContextObject, + processChildContext: processChildContext, + pushContextProvider: pushContextProvider, + invalidateContextProvider: invalidateContextProvider, + findCurrentUnmaskedContext: findCurrentUnmaskedContext, + } + } - function callGetDerivedStateFromProps(workInProgress, instance, nextProps, prevState) { - var type = workInProgress.type; + var ReactFiberNewContext = function (stack) { + var createCursor = stack.createCursor, + push = stack.push, + pop = stack.pop + + var providerCursor = createCursor(null) + var valueCursor = createCursor(null) + var changedBitsCursor = createCursor(0) + + var rendererSigil = void 0 + { + // Use this to detect multiple renderers using the same context + rendererSigil = {} + } + + function pushProvider(providerFiber) { + var context = providerFiber.type._context + + push(changedBitsCursor, context._changedBits, providerFiber) + push(valueCursor, context._currentValue, providerFiber) + push(providerCursor, providerFiber, providerFiber) + + context._currentValue = providerFiber.pendingProps.value + context._changedBits = providerFiber.stateNode + + { + !( + context._currentRenderer === null || + context._currentRenderer === rendererSigil + ) + ? warning( + false, + 'Detected multiple renderers concurrently rendering the ' + + 'same context provider. This is currently unsupported.' + ) + : void 0 + context._currentRenderer = rendererSigil + } + } + + function popProvider(providerFiber) { + var changedBits = changedBitsCursor.current + var currentValue = valueCursor.current + + pop(providerCursor, providerFiber) + pop(valueCursor, providerFiber) + pop(changedBitsCursor, providerFiber) + + var context = providerFiber.type._context + context._currentValue = currentValue + context._changedBits = changedBits + } + + return { + pushProvider: pushProvider, + popProvider: popProvider, + } + } + var ReactFiberStack = function () { + var valueStack = [] + + var fiberStack = void 0 + + { + fiberStack = [] + } + + var index = -1 + + function createCursor(defaultValue) { + return { + current: defaultValue, + } + } + + function isEmpty() { + return index === -1 + } + + function pop(cursor, fiber) { + if (index < 0) { + { + warning(false, 'Unexpected pop.') + } + return + } + + { + if (fiber !== fiberStack[index]) { + warning(false, 'Unexpected Fiber popped.') + } + } + + cursor.current = valueStack[index] + + valueStack[index] = null + + { + fiberStack[index] = null + } + + index-- + } + + function push(cursor, value, fiber) { + index++ + + valueStack[index] = cursor.current + + { + fiberStack[index] = fiber + } + + cursor.current = value + } + + function checkThatStackIsEmpty() { + { + if (index !== -1) { + warning( + false, + 'Expected an empty stack. Something was not reset properly.' + ) + } + } + } + + function resetStackAfterFatalErrorInDev() { + { + index = -1 + valueStack.length = 0 + fiberStack.length = 0 + } + } + + return { + createCursor: createCursor, + isEmpty: isEmpty, + pop: pop, + push: push, + checkThatStackIsEmpty: checkThatStackIsEmpty, + resetStackAfterFatalErrorInDev: resetStackAfterFatalErrorInDev, + } + } - if (typeof type.getDerivedStateFromProps === 'function') { - if (debugRenderPhaseSideEffects || debugRenderPhaseSideEffectsForStrictMode && workInProgress.mode & StrictMode) { - // Invoke method an extra time to help detect side-effects. - type.getDerivedStateFromProps.call(null, nextProps, prevState); - } + var invokeGuardedCallback$2 = + ReactErrorUtils.invokeGuardedCallback + var hasCaughtError = ReactErrorUtils.hasCaughtError + var clearCaughtError = ReactErrorUtils.clearCaughtError + + var didWarnAboutStateTransition = void 0 + var didWarnSetStateChildContext = void 0 + var warnAboutUpdateOnUnmounted = void 0 + var warnAboutInvalidUpdates = void 0 + + { + didWarnAboutStateTransition = false + didWarnSetStateChildContext = false + var didWarnStateUpdateForUnmountedComponent = {} + + warnAboutUpdateOnUnmounted = function (fiber) { + // We show the whole stack but dedupe on the top component's name because + // the problematic code almost always lies inside that component. + var componentName = getComponentName(fiber) || 'ReactClass' + if ( + didWarnStateUpdateForUnmountedComponent[componentName] + ) { + return + } + warning( + false, + "Can't call setState (or forceUpdate) on an unmounted component. This " + + 'is a no-op, but it indicates a memory leak in your application. To ' + + 'fix, cancel all subscriptions and asynchronous tasks in the ' + + 'componentWillUnmount method.%s', + getStackAddendumByWorkInProgressFiber(fiber) + ) + didWarnStateUpdateForUnmountedComponent[ + componentName + ] = true + } + + warnAboutInvalidUpdates = function (instance) { + switch (ReactDebugCurrentFiber.phase) { + case 'getChildContext': + if (didWarnSetStateChildContext) { + return + } + warning( + false, + 'setState(...): Cannot call setState() inside getChildContext()' + ) + didWarnSetStateChildContext = true + break + case 'render': + if (didWarnAboutStateTransition) { + return + } + warning( + false, + 'Cannot update during an existing state transition (such as within ' + + "`render` or another component's constructor). Render methods should " + + 'be a pure function of props and state; constructor side-effects are ' + + 'an anti-pattern, but can be moved to `componentWillMount`.' + ) + didWarnAboutStateTransition = true + break + } + } + } - var partialState = type.getDerivedStateFromProps.call(null, nextProps, prevState); + var ReactFiberScheduler = function (config) { + var stack = ReactFiberStack() + var hostContext = ReactFiberHostContext(config, stack) + var legacyContext = ReactFiberLegacyContext(stack) + var newContext = ReactFiberNewContext(stack) + var popHostContext = hostContext.popHostContext, + popHostContainer = hostContext.popHostContainer + var popTopLevelLegacyContextObject = + legacyContext.popTopLevelContextObject, + popLegacyContextProvider = legacyContext.popContextProvider + var popProvider = newContext.popProvider + + var hydrationContext = ReactFiberHydrationContext(config) + + var _ReactFiberBeginWork = ReactFiberBeginWork( + config, + hostContext, + legacyContext, + newContext, + hydrationContext, + scheduleWork, + computeExpirationForFiber + ), + beginWork = _ReactFiberBeginWork.beginWork + + var _ReactFiberCompleteWo = ReactFiberCompleteWork( + config, + hostContext, + legacyContext, + newContext, + hydrationContext + ), + completeWork = _ReactFiberCompleteWo.completeWork + + var _ReactFiberUnwindWork = ReactFiberUnwindWork( + hostContext, + legacyContext, + newContext, + scheduleWork, + isAlreadyFailedLegacyErrorBoundary + ), + throwException = _ReactFiberUnwindWork.throwException, + unwindWork = _ReactFiberUnwindWork.unwindWork, + unwindInterruptedWork = + _ReactFiberUnwindWork.unwindInterruptedWork + + var _ReactFiberCommitWork = ReactFiberCommitWork( + config, + onCommitPhaseError, + scheduleWork, + computeExpirationForFiber, + markLegacyErrorBoundaryAsFailed, + recalculateCurrentTime + ), + commitBeforeMutationLifeCycles = + _ReactFiberCommitWork.commitBeforeMutationLifeCycles, + commitResetTextContent = + _ReactFiberCommitWork.commitResetTextContent, + commitPlacement = _ReactFiberCommitWork.commitPlacement, + commitDeletion = _ReactFiberCommitWork.commitDeletion, + commitWork = _ReactFiberCommitWork.commitWork, + commitLifeCycles = _ReactFiberCommitWork.commitLifeCycles, + commitErrorLogging = + _ReactFiberCommitWork.commitErrorLogging, + commitAttachRef = _ReactFiberCommitWork.commitAttachRef, + commitDetachRef = _ReactFiberCommitWork.commitDetachRef + + var now = config.now, + scheduleDeferredCallback = config.scheduleDeferredCallback, + cancelDeferredCallback = config.cancelDeferredCallback, + prepareForCommit = config.prepareForCommit, + resetAfterCommit = config.resetAfterCommit + + // Represents the current time in ms. + + var originalStartTimeMs = now() + var mostRecentCurrentTime = msToExpirationTime(0) + var mostRecentCurrentTimeMs = originalStartTimeMs + + // Used to ensure computeUniqueAsyncExpiration is monotonically increases. + var lastUniqueAsyncExpiration = 0 + + // Represents the expiration time that incoming updates should use. (If this + // is NoWork, use the default strategy: async updates in async mode, sync + // updates in sync mode.) + var expirationContext = NoWork + + var isWorking = false + + // The next work in progress fiber that we're currently working on. + var nextUnitOfWork = null + var nextRoot = null + // The time at which we're currently rendering work. + var nextRenderExpirationTime = NoWork + + // The next fiber with an effect that we're currently committing. + var nextEffect = null + + var isCommitting = false + + var isRootReadyForCommit = false + + var legacyErrorBoundariesThatAlreadyFailed = null + + // Used for performance tracking. + var interruptedBy = null + + var stashedWorkInProgressProperties = void 0 + var replayUnitOfWork = void 0 + var isReplayingFailedUnitOfWork = void 0 + var originalReplayError = void 0 + var rethrowOriginalError = void 0 + if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) { + stashedWorkInProgressProperties = null + isReplayingFailedUnitOfWork = false + originalReplayError = null + replayUnitOfWork = function ( + failedUnitOfWork, + error, + isAsync + ) { + // Restore the original state of the work-in-progress + assignFiberPropertiesInDEV( + failedUnitOfWork, + stashedWorkInProgressProperties + ) + switch (failedUnitOfWork.tag) { + case HostRoot: + popHostContainer(failedUnitOfWork) + popTopLevelLegacyContextObject(failedUnitOfWork) + break + case HostComponent: + popHostContext(failedUnitOfWork) + break + case ClassComponent: + popLegacyContextProvider(failedUnitOfWork) + break + case HostPortal: + popHostContainer(failedUnitOfWork) + break + case ContextProvider: + popProvider(failedUnitOfWork) + break + } + // Replay the begin phase. + isReplayingFailedUnitOfWork = true + originalReplayError = error + invokeGuardedCallback$2(null, workLoop, null, isAsync) + isReplayingFailedUnitOfWork = false + originalReplayError = null + if (hasCaughtError()) { + clearCaughtError() + } else { + // If the begin phase did not fail the second time, set this pointer + // back to the original value. + nextUnitOfWork = failedUnitOfWork + } + } + rethrowOriginalError = function () { + throw originalReplayError + } + } + + function resetStack() { + if (nextUnitOfWork !== null) { + var interruptedWork = nextUnitOfWork['return'] + while (interruptedWork !== null) { + unwindInterruptedWork(interruptedWork) + interruptedWork = interruptedWork['return'] + } + } + + { + ReactStrictModeWarnings.discardPendingWarnings() + stack.checkThatStackIsEmpty() + } + + nextRoot = null + nextRenderExpirationTime = NoWork + nextUnitOfWork = null + + isRootReadyForCommit = false + } + + function commitAllHostEffects() { + while (nextEffect !== null) { + { + ReactDebugCurrentFiber.setCurrentFiber(nextEffect) + } + recordEffect() + + var effectTag = nextEffect.effectTag + + if (effectTag & ContentReset) { + commitResetTextContent(nextEffect) + } + + if (effectTag & Ref) { + var current = nextEffect.alternate + if (current !== null) { + commitDetachRef(current) + } + } + + // The following switch statement is only concerned about placement, + // updates, and deletions. To avoid needing to add a case for every + // possible bitmap value, we remove the secondary effects from the + // effect tag and switch on that value. + var primaryEffectTag = + effectTag & (Placement | Update | Deletion) + switch (primaryEffectTag) { + case Placement: { + commitPlacement(nextEffect) + // Clear the "placement" from effect tag so that we know that this is inserted, before + // any life-cycles like componentDidMount gets called. + // TODO: findDOMNode doesn't rely on this any more but isMounted + // does and isMounted is deprecated anyway so we should be able + // to kill this. + nextEffect.effectTag &= ~Placement + break + } + case PlacementAndUpdate: { + // Placement + commitPlacement(nextEffect) + // Clear the "placement" from effect tag so that we know that this is inserted, before + // any life-cycles like componentDidMount gets called. + nextEffect.effectTag &= ~Placement + + // Update + var _current = nextEffect.alternate + commitWork(_current, nextEffect) + break + } + case Update: { + var _current2 = nextEffect.alternate + commitWork(_current2, nextEffect) + break + } + case Deletion: { + commitDeletion(nextEffect) + break + } + } + nextEffect = nextEffect.nextEffect + } + + { + ReactDebugCurrentFiber.resetCurrentFiber() + } + } + + function commitBeforeMutationLifecycles() { + while (nextEffect !== null) { + var effectTag = nextEffect.effectTag + + if (effectTag & Snapshot) { + recordEffect() + var current = nextEffect.alternate + commitBeforeMutationLifeCycles(current, nextEffect) + } + + // Don't cleanup effects yet; + // This will be done by commitAllLifeCycles() + nextEffect = nextEffect.nextEffect + } + } + + function commitAllLifeCycles( + finishedRoot, + currentTime, + committedExpirationTime + ) { + { + ReactStrictModeWarnings.flushPendingUnsafeLifecycleWarnings() + + if (warnAboutDeprecatedLifecycles) { + ReactStrictModeWarnings.flushPendingDeprecationWarnings() + } + } + while (nextEffect !== null) { + var effectTag = nextEffect.effectTag + + if (effectTag & (Update | Callback)) { + recordEffect() + var current = nextEffect.alternate + commitLifeCycles( + finishedRoot, + current, + nextEffect, + currentTime, + committedExpirationTime + ) + } + + if (effectTag & ErrLog) { + commitErrorLogging(nextEffect, onUncaughtError) + } + + if (effectTag & Ref) { + recordEffect() + commitAttachRef(nextEffect) + } + + var next = nextEffect.nextEffect + // Ensure that we clean these up so that we don't accidentally keep them. + // I'm not actually sure this matters because we can't reset firstEffect + // and lastEffect since they're on every node, not just the effectful + // ones. So we have to clean everything as we reuse nodes anyway. + nextEffect.nextEffect = null + // Ensure that we reset the effectTag here so that we can rely on effect + // tags to reason about the current life-cycle. + nextEffect = next + } + } + + function isAlreadyFailedLegacyErrorBoundary(instance) { + return ( + legacyErrorBoundariesThatAlreadyFailed !== null && + legacyErrorBoundariesThatAlreadyFailed.has(instance) + ) + } + + function markLegacyErrorBoundaryAsFailed(instance) { + if (legacyErrorBoundariesThatAlreadyFailed === null) { + legacyErrorBoundariesThatAlreadyFailed = new Set([ + instance, + ]) + } else { + legacyErrorBoundariesThatAlreadyFailed.add(instance) + } + } + + function commitRoot(finishedWork) { + isWorking = true + isCommitting = true + startCommitTimer() + + var root = finishedWork.stateNode + !(root.current !== finishedWork) + ? invariant( + false, + 'Cannot commit the same tree as before. This is probably a bug related to the return field. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + var committedExpirationTime = + root.pendingCommitExpirationTime + !(committedExpirationTime !== NoWork) + ? invariant( + false, + 'Cannot commit an incomplete root. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + root.pendingCommitExpirationTime = NoWork + + var currentTime = recalculateCurrentTime() + + // Reset this to null before calling lifecycles + ReactCurrentOwner.current = null + + var firstEffect = void 0 + if (finishedWork.effectTag > PerformedWork) { + // A fiber's effect list consists only of its children, not itself. So if + // the root has an effect, we need to add it to the end of the list. The + // resulting list is the set that would belong to the root's parent, if + // it had one; that is, all the effects in the tree including the root. + if (finishedWork.lastEffect !== null) { + finishedWork.lastEffect.nextEffect = finishedWork + firstEffect = finishedWork.firstEffect + } else { + firstEffect = finishedWork + } + } else { + // There is no effect on the root. + firstEffect = finishedWork.firstEffect + } + + prepareForCommit(root.containerInfo) + + // Invoke instances of getSnapshotBeforeUpdate before mutation. + nextEffect = firstEffect + startCommitSnapshotEffectsTimer() + while (nextEffect !== null) { + var didError = false + var error = void 0 + { + invokeGuardedCallback$2( + null, + commitBeforeMutationLifecycles, + null + ) + if (hasCaughtError()) { + didError = true + error = clearCaughtError() + } + } + if (didError) { + !(nextEffect !== null) + ? invariant( + false, + 'Should have next effect. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + onCommitPhaseError(nextEffect, error) + // Clean-up + if (nextEffect !== null) { + nextEffect = nextEffect.nextEffect + } + } + } + stopCommitSnapshotEffectsTimer() + + // Commit all the side-effects within a tree. We'll do this in two passes. + // The first pass performs all the host insertions, updates, deletions and + // ref unmounts. + nextEffect = firstEffect + startCommitHostEffectsTimer() + while (nextEffect !== null) { + var _didError = false + var _error = void 0 + { + invokeGuardedCallback$2( + null, + commitAllHostEffects, + null + ) + if (hasCaughtError()) { + _didError = true + _error = clearCaughtError() + } + } + if (_didError) { + !(nextEffect !== null) + ? invariant( + false, + 'Should have next effect. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + onCommitPhaseError(nextEffect, _error) + // Clean-up + if (nextEffect !== null) { + nextEffect = nextEffect.nextEffect + } + } + } + stopCommitHostEffectsTimer() + + resetAfterCommit(root.containerInfo) + + // The work-in-progress tree is now the current tree. This must come after + // the first pass of the commit phase, so that the previous tree is still + // current during componentWillUnmount, but before the second pass, so that + // the finished work is current during componentDidMount/Update. + root.current = finishedWork + + // In the second pass we'll perform all life-cycles and ref callbacks. + // Life-cycles happen as a separate pass so that all placements, updates, + // and deletions in the entire tree have already been invoked. + // This pass also triggers any renderer-specific initial effects. + nextEffect = firstEffect + startCommitLifeCyclesTimer() + while (nextEffect !== null) { + var _didError2 = false + var _error2 = void 0 + { + invokeGuardedCallback$2( + null, + commitAllLifeCycles, + null, + root, + currentTime, + committedExpirationTime + ) + if (hasCaughtError()) { + _didError2 = true + _error2 = clearCaughtError() + } + } + if (_didError2) { + !(nextEffect !== null) + ? invariant( + false, + 'Should have next effect. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + onCommitPhaseError(nextEffect, _error2) + if (nextEffect !== null) { + nextEffect = nextEffect.nextEffect + } + } + } + + isCommitting = false + isWorking = false + stopCommitLifeCyclesTimer() + stopCommitTimer() + if (typeof onCommitRoot === 'function') { + onCommitRoot(finishedWork.stateNode) + } + if (true && ReactFiberInstrumentation_1.debugTool) { + ReactFiberInstrumentation_1.debugTool.onCommitWork( + finishedWork + ) + } + + var remainingTime = root.current.expirationTime + if (remainingTime === NoWork) { + // If there's no remaining work, we can clear the set of already failed + // error boundaries. + legacyErrorBoundariesThatAlreadyFailed = null + } + return remainingTime + } + + function resetExpirationTime(workInProgress, renderTime) { + if ( + renderTime !== Never && + workInProgress.expirationTime === Never + ) { + // The children of this component are hidden. Don't bubble their + // expiration times. + return + } + + // Check for pending updates. + var newExpirationTime = getUpdateExpirationTime( + workInProgress + ) + + // TODO: Calls need to visit stateNode + + // Bubble up the earliest expiration time. + var child = workInProgress.child + while (child !== null) { + if ( + child.expirationTime !== NoWork && + (newExpirationTime === NoWork || + newExpirationTime > child.expirationTime) + ) { + newExpirationTime = child.expirationTime + } + child = child.sibling + } + workInProgress.expirationTime = newExpirationTime + } + + function completeUnitOfWork(workInProgress) { + // Attempt to complete the current unit of work, then move to the + // next sibling. If there are no more siblings, return to the + // parent fiber. + while (true) { + // The current, flushed, state of this fiber is the alternate. + // Ideally nothing should rely on this, but relying on it here + // means that we don't need an additional field on the work in + // progress. + var current = workInProgress.alternate + { + ReactDebugCurrentFiber.setCurrentFiber(workInProgress) + } + + var returnFiber = workInProgress['return'] + var siblingFiber = workInProgress.sibling + + if ( + (workInProgress.effectTag & Incomplete) === + NoEffect + ) { + // This fiber completed. + var next = completeWork( + current, + workInProgress, + nextRenderExpirationTime + ) + stopWorkTimer(workInProgress) + resetExpirationTime( + workInProgress, + nextRenderExpirationTime + ) + { + ReactDebugCurrentFiber.resetCurrentFiber() + } + + if (next !== null) { + stopWorkTimer(workInProgress) + if (true && ReactFiberInstrumentation_1.debugTool) { + ReactFiberInstrumentation_1.debugTool.onCompleteWork( + workInProgress + ) + } + // If completing this work spawned new work, do that next. We'll come + // back here again. + return next + } + + if ( + returnFiber !== null && + // Do not append effects to parents if a sibling failed to complete + (returnFiber.effectTag & Incomplete) === NoEffect + ) { + // Append all the effects of the subtree and this fiber onto the effect + // list of the parent. The completion order of the children affects the + // side-effect order. + if (returnFiber.firstEffect === null) { + returnFiber.firstEffect = workInProgress.firstEffect + } + if (workInProgress.lastEffect !== null) { + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = + workInProgress.firstEffect + } + returnFiber.lastEffect = workInProgress.lastEffect + } + + // If this fiber had side-effects, we append it AFTER the children's + // side-effects. We can perform certain side-effects earlier if + // needed, by doing multiple passes over the effect list. We don't want + // to schedule our own side-effect on our own list because if end up + // reusing children we'll schedule this effect onto itself since we're + // at the end. + var effectTag = workInProgress.effectTag + // Skip both NoWork and PerformedWork tags when creating the effect list. + // PerformedWork effect is read by React DevTools but shouldn't be committed. + if (effectTag > PerformedWork) { + if (returnFiber.lastEffect !== null) { + returnFiber.lastEffect.nextEffect = workInProgress + } else { + returnFiber.firstEffect = workInProgress + } + returnFiber.lastEffect = workInProgress + } + } + + if (true && ReactFiberInstrumentation_1.debugTool) { + ReactFiberInstrumentation_1.debugTool.onCompleteWork( + workInProgress + ) + } + + if (siblingFiber !== null) { + // If there is more work to do in this returnFiber, do that next. + return siblingFiber + } else if (returnFiber !== null) { + // If there's no more work in this returnFiber. Complete the returnFiber. + workInProgress = returnFiber + continue + } else { + // We've reached the root. + isRootReadyForCommit = true + return null + } + } else { + // This fiber did not complete because something threw. Pop values off + // the stack without entering the complete phase. If this is a boundary, + // capture values if possible. + var _next = unwindWork(workInProgress) + // Because this fiber did not complete, don't reset its expiration time. + if (workInProgress.effectTag & DidCapture) { + // Restarting an error boundary + stopFailedWorkTimer(workInProgress) + } else { + stopWorkTimer(workInProgress) + } + + { + ReactDebugCurrentFiber.resetCurrentFiber() + } + + if (_next !== null) { + stopWorkTimer(workInProgress) + if (true && ReactFiberInstrumentation_1.debugTool) { + ReactFiberInstrumentation_1.debugTool.onCompleteWork( + workInProgress + ) + } + // If completing this work spawned new work, do that next. We'll come + // back here again. + // Since we're restarting, remove anything that is not a host effect + // from the effect tag. + _next.effectTag &= HostEffectMask + return _next + } + + if (returnFiber !== null) { + // Mark the parent fiber as incomplete and clear its effect list. + returnFiber.firstEffect = returnFiber.lastEffect = null + returnFiber.effectTag |= Incomplete + } + + if (true && ReactFiberInstrumentation_1.debugTool) { + ReactFiberInstrumentation_1.debugTool.onCompleteWork( + workInProgress + ) + } + + if (siblingFiber !== null) { + // If there is more work to do in this returnFiber, do that next. + return siblingFiber + } else if (returnFiber !== null) { + // If there's no more work in this returnFiber. Complete the returnFiber. + workInProgress = returnFiber + continue + } else { + return null + } + } + } + + // Without this explicit null return Flow complains of invalid return type + // TODO Remove the above while(true) loop + // eslint-disable-next-line no-unreachable + return null + } + + function performUnitOfWork(workInProgress) { + // The current, flushed, state of this fiber is the alternate. + // Ideally nothing should rely on this, but relying on it here + // means that we don't need an additional field on the work in + // progress. + var current = workInProgress.alternate + + // See if beginning this work spawns more work. + startWorkTimer(workInProgress) + { + ReactDebugCurrentFiber.setCurrentFiber(workInProgress) + } + + if ( + true && + replayFailedUnitOfWorkWithInvokeGuardedCallback + ) { + stashedWorkInProgressProperties = assignFiberPropertiesInDEV( + stashedWorkInProgressProperties, + workInProgress + ) + } + var next = beginWork( + current, + workInProgress, + nextRenderExpirationTime + ) + { + ReactDebugCurrentFiber.resetCurrentFiber() + if (isReplayingFailedUnitOfWork) { + // Currently replaying a failed unit of work. This should be unreachable, + // because the render phase is meant to be idempotent, and it should + // have thrown again. Since it didn't, rethrow the original error, so + // React's internal stack is not misaligned. + rethrowOriginalError() + } + } + if (true && ReactFiberInstrumentation_1.debugTool) { + ReactFiberInstrumentation_1.debugTool.onBeginWork( + workInProgress + ) + } + + if (next === null) { + // If this doesn't spawn new work, complete the current work. + next = completeUnitOfWork(workInProgress) + } + + ReactCurrentOwner.current = null + + return next + } + + function workLoop(isAsync) { + if (!isAsync) { + // Flush all expired work. + while (nextUnitOfWork !== null) { + nextUnitOfWork = performUnitOfWork(nextUnitOfWork) + } + } else { + // Flush asynchronous work until the deadline runs out of time. + while (nextUnitOfWork !== null && !shouldYield()) { + nextUnitOfWork = performUnitOfWork(nextUnitOfWork) + } + } + } + + function renderRoot(root, expirationTime, isAsync) { + !!isWorking + ? invariant( + false, + 'renderRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + isWorking = true + + // Check if we're starting from a fresh stack, or if we're resuming from + // previously yielded work. + if ( + expirationTime !== nextRenderExpirationTime || + root !== nextRoot || + nextUnitOfWork === null + ) { + // Reset the stack and start working from the root. + resetStack() + nextRoot = root + nextRenderExpirationTime = expirationTime + nextUnitOfWork = createWorkInProgress( + nextRoot.current, + null, + nextRenderExpirationTime + ) + root.pendingCommitExpirationTime = NoWork + } + + var didFatal = false + + startWorkLoopTimer(nextUnitOfWork) + + do { + try { + workLoop(isAsync) + } catch (thrownValue) { + if (nextUnitOfWork === null) { + // This is a fatal error. + didFatal = true + onUncaughtError(thrownValue) + break + } + + if ( + true && + replayFailedUnitOfWorkWithInvokeGuardedCallback + ) { + var failedUnitOfWork = nextUnitOfWork + replayUnitOfWork( + failedUnitOfWork, + thrownValue, + isAsync + ) + } + + var sourceFiber = nextUnitOfWork + var returnFiber = sourceFiber['return'] + if (returnFiber === null) { + // This is the root. The root could capture its own errors. However, + // we don't know if it errors before or after we pushed the host + // context. This information is needed to avoid a stack mismatch. + // Because we're not sure, treat this as a fatal error. We could track + // which phase it fails in, but doesn't seem worth it. At least + // for now. + didFatal = true + onUncaughtError(thrownValue) + break + } + throwException(returnFiber, sourceFiber, thrownValue) + nextUnitOfWork = completeUnitOfWork(sourceFiber) + } + break + } while (true) + + // We're done performing work. Time to clean up. + var didCompleteRoot = false + isWorking = false + + // Yield back to main thread. + if (didFatal) { + stopWorkLoopTimer(interruptedBy, didCompleteRoot) + interruptedBy = null + // There was a fatal error. + { + stack.resetStackAfterFatalErrorInDev() + } + return null + } else if (nextUnitOfWork === null) { + // We reached the root. + if (isRootReadyForCommit) { + didCompleteRoot = true + stopWorkLoopTimer(interruptedBy, didCompleteRoot) + interruptedBy = null + // The root successfully completed. It's ready for commit. + root.pendingCommitExpirationTime = expirationTime + var finishedWork = root.current.alternate + return finishedWork + } else { + // The root did not complete. + stopWorkLoopTimer(interruptedBy, didCompleteRoot) + interruptedBy = null + invariant( + false, + 'Expired work should have completed. This error is likely caused by a bug in React. Please file an issue.' + ) + } + } else { + stopWorkLoopTimer(interruptedBy, didCompleteRoot) + interruptedBy = null + // There's more work to do, but we ran out of time. Yield back to + // the renderer. + return null + } + } + + function scheduleCapture( + sourceFiber, + boundaryFiber, + value, + expirationTime + ) { + // TODO: We only support dispatching errors. + var capturedValue = createCapturedValue(value, sourceFiber) + var update = { + expirationTime: expirationTime, + partialState: null, + callback: null, + isReplace: false, + isForced: false, + capturedValue: capturedValue, + next: null, + } + insertUpdateIntoFiber(boundaryFiber, update) + scheduleWork(boundaryFiber, expirationTime) + } + + function dispatch(sourceFiber, value, expirationTime) { + !(!isWorking || isCommitting) + ? invariant( + false, + 'dispatch: Cannot dispatch during the render phase.' + ) + : void 0 + + // TODO: Handle arrays + + var fiber = sourceFiber['return'] + while (fiber !== null) { + switch (fiber.tag) { + case ClassComponent: + var ctor = fiber.type + var instance = fiber.stateNode + if ( + typeof ctor.getDerivedStateFromCatch === + 'function' || + (typeof instance.componentDidCatch === 'function' && + !isAlreadyFailedLegacyErrorBoundary(instance)) + ) { + scheduleCapture( + sourceFiber, + fiber, + value, + expirationTime + ) + return + } + break + // TODO: Handle async boundaries + case HostRoot: + scheduleCapture( + sourceFiber, + fiber, + value, + expirationTime + ) + return + } + fiber = fiber['return'] + } + + if (sourceFiber.tag === HostRoot) { + // Error was thrown at the root. There is no parent, so the root + // itself should capture it. + scheduleCapture( + sourceFiber, + sourceFiber, + value, + expirationTime + ) + } + } + + function onCommitPhaseError(fiber, error) { + return dispatch(fiber, error, Sync) + } + + function computeAsyncExpiration(currentTime) { + // Given the current clock time, returns an expiration time. We use rounding + // to batch like updates together. + // Should complete within ~1000ms. 1200ms max. + var expirationMs = 5000 + var bucketSizeMs = 250 + return computeExpirationBucket( + currentTime, + expirationMs, + bucketSizeMs + ) + } + + function computeInteractiveExpiration(currentTime) { + var expirationMs = void 0 + // We intentionally set a higher expiration time for interactive updates in + // dev than in production. + // If the main thread is being blocked so long that you hit the expiration, + // it's a problem that could be solved with better scheduling. + // People will be more likely to notice this and fix it with the long + // expiration time in development. + // In production we opt for better UX at the risk of masking scheduling + // problems, by expiring fast. + { + // Should complete within ~500ms. 600ms max. + expirationMs = 500 + } + var bucketSizeMs = 100 + return computeExpirationBucket( + currentTime, + expirationMs, + bucketSizeMs + ) + } + + // Creates a unique async expiration time. + function computeUniqueAsyncExpiration() { + var currentTime = recalculateCurrentTime() + var result = computeAsyncExpiration(currentTime) + if (result <= lastUniqueAsyncExpiration) { + // Since we assume the current time monotonically increases, we only hit + // this branch when computeUniqueAsyncExpiration is fired multiple times + // within a 200ms window (or whatever the async bucket size is). + result = lastUniqueAsyncExpiration + 1 + } + lastUniqueAsyncExpiration = result + return lastUniqueAsyncExpiration + } + + function computeExpirationForFiber(fiber) { + var expirationTime = void 0 + if (expirationContext !== NoWork) { + // An explicit expiration context was set; + expirationTime = expirationContext + } else if (isWorking) { + if (isCommitting) { + // Updates that occur during the commit phase should have sync priority + // by default. + expirationTime = Sync + } else { + // Updates during the render phase should expire at the same time as + // the work that is being rendered. + expirationTime = nextRenderExpirationTime + } + } else { + // No explicit expiration context was set, and we're not currently + // performing work. Calculate a new expiration time. + if (fiber.mode & AsyncMode) { + if (isBatchingInteractiveUpdates) { + // This is an interactive update + var currentTime = recalculateCurrentTime() + expirationTime = computeInteractiveExpiration( + currentTime + ) + } else { + // This is an async update + var _currentTime = recalculateCurrentTime() + expirationTime = computeAsyncExpiration(_currentTime) + } + } else { + // This is a sync update + expirationTime = Sync + } + } + if (isBatchingInteractiveUpdates) { + // This is an interactive update. Keep track of the lowest pending + // interactive expiration time. This allows us to synchronously flush + // all interactive updates when needed. + if ( + lowestPendingInteractiveExpirationTime === NoWork || + expirationTime > lowestPendingInteractiveExpirationTime + ) { + lowestPendingInteractiveExpirationTime = expirationTime + } + } + return expirationTime + } + + function scheduleWork(fiber, expirationTime) { + return scheduleWorkImpl(fiber, expirationTime, false) + } + + function scheduleWorkImpl( + fiber, + expirationTime, + isErrorRecovery + ) { + recordScheduleUpdate() + + { + if (!isErrorRecovery && fiber.tag === ClassComponent) { + var instance = fiber.stateNode + warnAboutInvalidUpdates(instance) + } + } + + var node = fiber + while (node !== null) { + // Walk the parent path to the root and update each node's + // expiration time. + if ( + node.expirationTime === NoWork || + node.expirationTime > expirationTime + ) { + node.expirationTime = expirationTime + } + if (node.alternate !== null) { + if ( + node.alternate.expirationTime === NoWork || + node.alternate.expirationTime > expirationTime + ) { + node.alternate.expirationTime = expirationTime + } + } + if (node['return'] === null) { + if (node.tag === HostRoot) { + var root = node.stateNode + if ( + !isWorking && + nextRenderExpirationTime !== NoWork && + expirationTime < nextRenderExpirationTime + ) { + // This is an interruption. (Used for performance tracking.) + interruptedBy = fiber + resetStack() + } + if ( + // If we're in the render phase, we don't need to schedule this root + // for an update, because we'll do it before we exit... + !isWorking || + isCommitting || + // ...unless this is a different root than the one we're rendering. + nextRoot !== root + ) { + // Add this root to the root schedule. + requestWork(root, expirationTime) + } + if (nestedUpdateCount > NESTED_UPDATE_LIMIT) { + invariant( + false, + 'Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.' + ) + } + } else { + { + if ( + !isErrorRecovery && + fiber.tag === ClassComponent + ) { + warnAboutUpdateOnUnmounted(fiber) + } + } + return + } + } + node = node['return'] + } + } + + function recalculateCurrentTime() { + // Subtract initial time so it fits inside 32bits + mostRecentCurrentTimeMs = now() - originalStartTimeMs + mostRecentCurrentTime = msToExpirationTime( + mostRecentCurrentTimeMs + ) + return mostRecentCurrentTime + } + + function deferredUpdates(fn) { + var previousExpirationContext = expirationContext + var currentTime = recalculateCurrentTime() + expirationContext = computeAsyncExpiration(currentTime) + try { + return fn() + } finally { + expirationContext = previousExpirationContext + } + } + function syncUpdates(fn, a, b, c, d) { + var previousExpirationContext = expirationContext + expirationContext = Sync + try { + return fn(a, b, c, d) + } finally { + expirationContext = previousExpirationContext + } + } + + // TODO: Everything below this is written as if it has been lifted to the + // renderers. I'll do this in a follow-up. + + // Linked-list of roots + var firstScheduledRoot = null + var lastScheduledRoot = null + + var callbackExpirationTime = NoWork + var callbackID = -1 + var isRendering = false + var nextFlushedRoot = null + var nextFlushedExpirationTime = NoWork + var lowestPendingInteractiveExpirationTime = NoWork + var deadlineDidExpire = false + var hasUnhandledError = false + var unhandledError = null + var deadline = null + + var isBatchingUpdates = false + var isUnbatchingUpdates = false + var isBatchingInteractiveUpdates = false + + var completedBatches = null + + // Use these to prevent an infinite loop of nested updates + var NESTED_UPDATE_LIMIT = 1000 + var nestedUpdateCount = 0 + + var timeHeuristicForUnitOfWork = 1 + + function scheduleCallbackWithExpiration(expirationTime) { + if (callbackExpirationTime !== NoWork) { + // A callback is already scheduled. Check its expiration time (timeout). + if (expirationTime > callbackExpirationTime) { + // Existing callback has sufficient timeout. Exit. + return + } else { + // Existing callback has insufficient timeout. Cancel and schedule a + // new one. + cancelDeferredCallback(callbackID) + } + // The request callback timer is already running. Don't start a new one. + } else { + startRequestCallbackTimer() + } + + // Compute a timeout for the given expiration time. + var currentMs = now() - originalStartTimeMs + var expirationMs = expirationTimeToMs(expirationTime) + var timeout = expirationMs - currentMs + + callbackExpirationTime = expirationTime + callbackID = scheduleDeferredCallback(performAsyncWork, { + timeout: timeout, + }) + } + + // requestWork is called by the scheduler whenever a root receives an update. + // It's up to the renderer to call renderRoot at some point in the future. + function requestWork(root, expirationTime) { + addRootToSchedule(root, expirationTime) + + if (isRendering) { + // Prevent reentrancy. Remaining work will be scheduled at the end of + // the currently rendering batch. + return + } + + if (isBatchingUpdates) { + // Flush work at the end of the batch. + if (isUnbatchingUpdates) { + // ...unless we're inside unbatchedUpdates, in which case we should + // flush it now. + nextFlushedRoot = root + nextFlushedExpirationTime = Sync + performWorkOnRoot(root, Sync, false) + } + return + } + + // TODO: Get rid of Sync and use current time? + if (expirationTime === Sync) { + performSyncWork() + } else { + scheduleCallbackWithExpiration(expirationTime) + } + } + + function addRootToSchedule(root, expirationTime) { + // Add the root to the schedule. + // Check if this root is already part of the schedule. + if (root.nextScheduledRoot === null) { + // This root is not already scheduled. Add it. + root.remainingExpirationTime = expirationTime + if (lastScheduledRoot === null) { + firstScheduledRoot = lastScheduledRoot = root + root.nextScheduledRoot = root + } else { + lastScheduledRoot.nextScheduledRoot = root + lastScheduledRoot = root + lastScheduledRoot.nextScheduledRoot = firstScheduledRoot + } + } else { + // This root is already scheduled, but its priority may have increased. + var remainingExpirationTime = root.remainingExpirationTime + if ( + remainingExpirationTime === NoWork || + expirationTime < remainingExpirationTime + ) { + // Update the priority. + root.remainingExpirationTime = expirationTime + } + } + } + + function findHighestPriorityRoot() { + var highestPriorityWork = NoWork + var highestPriorityRoot = null + if (lastScheduledRoot !== null) { + var previousScheduledRoot = lastScheduledRoot + var root = firstScheduledRoot + while (root !== null) { + var remainingExpirationTime = + root.remainingExpirationTime + if (remainingExpirationTime === NoWork) { + // This root no longer has work. Remove it from the scheduler. + + // TODO: This check is redudant, but Flow is confused by the branch + // below where we set lastScheduledRoot to null, even though we break + // from the loop right after. + !( + previousScheduledRoot !== null && + lastScheduledRoot !== null + ) + ? invariant( + false, + 'Should have a previous and last root. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + if (root === root.nextScheduledRoot) { + // This is the only root in the list. + root.nextScheduledRoot = null + firstScheduledRoot = lastScheduledRoot = null + break + } else if (root === firstScheduledRoot) { + // This is the first root in the list. + var next = root.nextScheduledRoot + firstScheduledRoot = next + lastScheduledRoot.nextScheduledRoot = next + root.nextScheduledRoot = null + } else if (root === lastScheduledRoot) { + // This is the last root in the list. + lastScheduledRoot = previousScheduledRoot + lastScheduledRoot.nextScheduledRoot = firstScheduledRoot + root.nextScheduledRoot = null + break + } else { + previousScheduledRoot.nextScheduledRoot = + root.nextScheduledRoot + root.nextScheduledRoot = null + } + root = previousScheduledRoot.nextScheduledRoot + } else { + if ( + highestPriorityWork === NoWork || + remainingExpirationTime < highestPriorityWork + ) { + // Update the priority, if it's higher + highestPriorityWork = remainingExpirationTime + highestPriorityRoot = root + } + if (root === lastScheduledRoot) { + break + } + previousScheduledRoot = root + root = root.nextScheduledRoot + } + } + } + + // If the next root is the same as the previous root, this is a nested + // update. To prevent an infinite loop, increment the nested update count. + var previousFlushedRoot = nextFlushedRoot + if ( + previousFlushedRoot !== null && + previousFlushedRoot === highestPriorityRoot && + highestPriorityWork === Sync + ) { + nestedUpdateCount++ + } else { + // Reset whenever we switch roots. + nestedUpdateCount = 0 + } + nextFlushedRoot = highestPriorityRoot + nextFlushedExpirationTime = highestPriorityWork + } + + function performAsyncWork(dl) { + performWork(NoWork, true, dl) + } + + function performSyncWork() { + performWork(Sync, false, null) + } + + function performWork(minExpirationTime, isAsync, dl) { + deadline = dl + + // Keep working on roots until there's no more work, or until the we reach + // the deadline. + findHighestPriorityRoot() + + if (enableUserTimingAPI && deadline !== null) { + var didExpire = + nextFlushedExpirationTime < recalculateCurrentTime() + var timeout = expirationTimeToMs( + nextFlushedExpirationTime + ) + stopRequestCallbackTimer(didExpire, timeout) + } + + if (isAsync) { + while ( + nextFlushedRoot !== null && + nextFlushedExpirationTime !== NoWork && + (minExpirationTime === NoWork || + minExpirationTime >= nextFlushedExpirationTime) && + (!deadlineDidExpire || + recalculateCurrentTime() >= nextFlushedExpirationTime) + ) { + performWorkOnRoot( + nextFlushedRoot, + nextFlushedExpirationTime, + !deadlineDidExpire + ) + findHighestPriorityRoot() + } + } else { + while ( + nextFlushedRoot !== null && + nextFlushedExpirationTime !== NoWork && + (minExpirationTime === NoWork || + minExpirationTime >= nextFlushedExpirationTime) + ) { + performWorkOnRoot( + nextFlushedRoot, + nextFlushedExpirationTime, + false + ) + findHighestPriorityRoot() + } + } + + // We're done flushing work. Either we ran out of time in this callback, + // or there's no more work left with sufficient priority. + + // If we're inside a callback, set this to false since we just completed it. + if (deadline !== null) { + callbackExpirationTime = NoWork + callbackID = -1 + } + // If there's work left over, schedule a new callback. + if (nextFlushedExpirationTime !== NoWork) { + scheduleCallbackWithExpiration(nextFlushedExpirationTime) + } + + // Clean-up. + deadline = null + deadlineDidExpire = false + + finishRendering() + } + + function flushRoot(root, expirationTime) { + !!isRendering + ? invariant( + false, + 'work.commit(): Cannot commit while already rendering. This likely means you attempted to commit from inside a lifecycle method.' + ) + : void 0 + // Perform work on root as if the given expiration time is the current time. + // This has the effect of synchronously flushing all work up to and + // including the given time. + nextFlushedRoot = root + nextFlushedExpirationTime = expirationTime + performWorkOnRoot(root, expirationTime, false) + // Flush any sync work that was scheduled by lifecycles + performSyncWork() + finishRendering() + } + + function finishRendering() { + nestedUpdateCount = 0 + + if (completedBatches !== null) { + var batches = completedBatches + completedBatches = null + for (var i = 0; i < batches.length; i++) { + var batch = batches[i] + try { + batch._onComplete() + } catch (error) { + if (!hasUnhandledError) { + hasUnhandledError = true + unhandledError = error + } + } + } + } + + if (hasUnhandledError) { + var error = unhandledError + unhandledError = null + hasUnhandledError = false + throw error + } + } + + function performWorkOnRoot(root, expirationTime, isAsync) { + !!isRendering + ? invariant( + false, + 'performWorkOnRoot was called recursively. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + + isRendering = true + + // Check if this is async work or sync/expired work. + if (!isAsync) { + // Flush sync work. + var finishedWork = root.finishedWork + if (finishedWork !== null) { + // This root is already complete. We can commit it. + completeRoot(root, finishedWork, expirationTime) + } else { + root.finishedWork = null + finishedWork = renderRoot(root, expirationTime, false) + if (finishedWork !== null) { + // We've completed the root. Commit it. + completeRoot(root, finishedWork, expirationTime) + } + } + } else { + // Flush async work. + var _finishedWork = root.finishedWork + if (_finishedWork !== null) { + // This root is already complete. We can commit it. + completeRoot(root, _finishedWork, expirationTime) + } else { + root.finishedWork = null + _finishedWork = renderRoot(root, expirationTime, true) + if (_finishedWork !== null) { + // We've completed the root. Check the deadline one more time + // before committing. + if (!shouldYield()) { + // Still time left. Commit the root. + completeRoot(root, _finishedWork, expirationTime) + } else { + // There's no time left. Mark this root as complete. We'll come + // back and commit it later. + root.finishedWork = _finishedWork + } + } + } + } + + isRendering = false + } + + function completeRoot(root, finishedWork, expirationTime) { + // Check if there's a batch that matches this expiration time. + var firstBatch = root.firstBatch + if ( + firstBatch !== null && + firstBatch._expirationTime <= expirationTime + ) { + if (completedBatches === null) { + completedBatches = [firstBatch] + } else { + completedBatches.push(firstBatch) + } + if (firstBatch._defer) { + // This root is blocked from committing by a batch. Unschedule it until + // we receive another update. + root.finishedWork = finishedWork + root.remainingExpirationTime = NoWork + return + } + } + + // Commit the root. + root.finishedWork = null + root.remainingExpirationTime = commitRoot(finishedWork) + } + + // When working on async work, the reconciler asks the renderer if it should + // yield execution. For DOM, we implement this with requestIdleCallback. + function shouldYield() { + if (deadline === null) { + return false + } + if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) { + // Disregard deadline.didTimeout. Only expired work should be flushed + // during a timeout. This path is only hit for non-expired work. + return false + } + deadlineDidExpire = true + return true + } + + function onUncaughtError(error) { + !(nextFlushedRoot !== null) + ? invariant( + false, + 'Should be working on a root. This error is likely caused by a bug in React. Please file an issue.' + ) + : void 0 + // Unschedule this root so we don't work on it again until there's + // another update. + nextFlushedRoot.remainingExpirationTime = NoWork + if (!hasUnhandledError) { + hasUnhandledError = true + unhandledError = error + } + } + + // TODO: Batching should be implemented at the renderer level, not inside + // the reconciler. + function batchedUpdates(fn, a) { + var previousIsBatchingUpdates = isBatchingUpdates + isBatchingUpdates = true + try { + return fn(a) + } finally { + isBatchingUpdates = previousIsBatchingUpdates + if (!isBatchingUpdates && !isRendering) { + performSyncWork() + } + } + } + + // TODO: Batching should be implemented at the renderer level, not inside + // the reconciler. + function unbatchedUpdates(fn, a) { + if (isBatchingUpdates && !isUnbatchingUpdates) { + isUnbatchingUpdates = true + try { + return fn(a) + } finally { + isUnbatchingUpdates = false + } + } + return fn(a) + } + + // TODO: Batching should be implemented at the renderer level, not within + // the reconciler. + function flushSync(fn, a) { + !!isRendering + ? invariant( + false, + 'flushSync was called from inside a lifecycle method. It cannot be called when React is already rendering.' + ) + : void 0 + var previousIsBatchingUpdates = isBatchingUpdates + isBatchingUpdates = true + try { + return syncUpdates(fn, a) + } finally { + isBatchingUpdates = previousIsBatchingUpdates + performSyncWork() + } + } + + function interactiveUpdates(fn, a, b) { + if (isBatchingInteractiveUpdates) { + return fn(a, b) + } + // If there are any pending interactive updates, synchronously flush them. + // This needs to happen before we read any handlers, because the effect of + // the previous event may influence which handlers are called during + // this event. + if ( + !isBatchingUpdates && + !isRendering && + lowestPendingInteractiveExpirationTime !== NoWork + ) { + // Synchronously flush pending interactive updates. + performWork( + lowestPendingInteractiveExpirationTime, + false, + null + ) + lowestPendingInteractiveExpirationTime = NoWork + } + var previousIsBatchingInteractiveUpdates = isBatchingInteractiveUpdates + var previousIsBatchingUpdates = isBatchingUpdates + isBatchingInteractiveUpdates = true + isBatchingUpdates = true + try { + return fn(a, b) + } finally { + isBatchingInteractiveUpdates = previousIsBatchingInteractiveUpdates + isBatchingUpdates = previousIsBatchingUpdates + if (!isBatchingUpdates && !isRendering) { + performSyncWork() + } + } + } + + function flushInteractiveUpdates() { + if ( + !isRendering && + lowestPendingInteractiveExpirationTime !== NoWork + ) { + // Synchronously flush pending interactive updates. + performWork( + lowestPendingInteractiveExpirationTime, + false, + null + ) + lowestPendingInteractiveExpirationTime = NoWork + } + } + + function flushControlled(fn) { + var previousIsBatchingUpdates = isBatchingUpdates + isBatchingUpdates = true + try { + syncUpdates(fn) + } finally { + isBatchingUpdates = previousIsBatchingUpdates + if (!isBatchingUpdates && !isRendering) { + performWork(Sync, false, null) + } + } + } + + return { + recalculateCurrentTime: recalculateCurrentTime, + computeExpirationForFiber: computeExpirationForFiber, + scheduleWork: scheduleWork, + requestWork: requestWork, + flushRoot: flushRoot, + batchedUpdates: batchedUpdates, + unbatchedUpdates: unbatchedUpdates, + flushSync: flushSync, + flushControlled: flushControlled, + deferredUpdates: deferredUpdates, + syncUpdates: syncUpdates, + interactiveUpdates: interactiveUpdates, + flushInteractiveUpdates: flushInteractiveUpdates, + computeUniqueAsyncExpiration: computeUniqueAsyncExpiration, + legacyContext: legacyContext, + } + } - { - if (partialState === undefined) { - var componentName = getComponentName(workInProgress) || 'Component'; - if (!didWarnAboutUndefinedDerivedState.has(componentName)) { - didWarnAboutUndefinedDerivedState.add(componentName); - warning(false, '%s.getDerivedStateFromProps(): A valid state object (or null) must be returned. ' + 'You have returned undefined.', componentName); - } - } - } + var didWarnAboutNestedUpdates = void 0 - return partialState; - } - } + { + didWarnAboutNestedUpdates = false + } - // Invokes the mount life-cycles on a previously never rendered instance. - function mountClassInstance(workInProgress, renderExpirationTime) { - var ctor = workInProgress.type; - var current = workInProgress.alternate; + // 0 is PROD, 1 is DEV. + // Might add PROFILE later. + + var ReactFiberReconciler$1 = function (config) { + var getPublicInstance = config.getPublicInstance + + var _ReactFiberScheduler = ReactFiberScheduler(config), + computeUniqueAsyncExpiration = + _ReactFiberScheduler.computeUniqueAsyncExpiration, + recalculateCurrentTime = + _ReactFiberScheduler.recalculateCurrentTime, + computeExpirationForFiber = + _ReactFiberScheduler.computeExpirationForFiber, + scheduleWork = _ReactFiberScheduler.scheduleWork, + requestWork = _ReactFiberScheduler.requestWork, + flushRoot = _ReactFiberScheduler.flushRoot, + batchedUpdates = _ReactFiberScheduler.batchedUpdates, + unbatchedUpdates = _ReactFiberScheduler.unbatchedUpdates, + flushSync = _ReactFiberScheduler.flushSync, + flushControlled = _ReactFiberScheduler.flushControlled, + deferredUpdates = _ReactFiberScheduler.deferredUpdates, + syncUpdates = _ReactFiberScheduler.syncUpdates, + interactiveUpdates = + _ReactFiberScheduler.interactiveUpdates, + flushInteractiveUpdates = + _ReactFiberScheduler.flushInteractiveUpdates, + legacyContext = _ReactFiberScheduler.legacyContext + + var findCurrentUnmaskedContext = + legacyContext.findCurrentUnmaskedContext, + isContextProvider = legacyContext.isContextProvider, + processChildContext = legacyContext.processChildContext + + function getContextForSubtree(parentComponent) { + if (!parentComponent) { + return emptyObject + } + + var fiber = get(parentComponent) + var parentContext = findCurrentUnmaskedContext(fiber) + return isContextProvider(fiber) + ? processChildContext(fiber, parentContext) + : parentContext + } + + function scheduleRootUpdate( + current, + element, + currentTime, + expirationTime, + callback + ) { + { + if ( + ReactDebugCurrentFiber.phase === 'render' && + ReactDebugCurrentFiber.current !== null && + !didWarnAboutNestedUpdates + ) { + didWarnAboutNestedUpdates = true + warning( + false, + 'Render methods should be a pure function of props and state; ' + + 'triggering nested component updates from render is not allowed. ' + + 'If necessary, trigger nested updates in componentDidUpdate.\n\n' + + 'Check the render method of %s.', + getComponentName(ReactDebugCurrentFiber.current) || + 'Unknown' + ) + } + } + + callback = callback === undefined ? null : callback + { + !(callback === null || typeof callback === 'function') + ? warning( + false, + 'render(...): Expected the last optional `callback` argument to be a ' + + 'function. Instead received: %s.', + callback + ) + : void 0 + } + + var update = { + expirationTime: expirationTime, + partialState: { element: element }, + callback: callback, + isReplace: false, + isForced: false, + capturedValue: null, + next: null, + } + insertUpdateIntoFiber(current, update) + scheduleWork(current, expirationTime) + + return expirationTime + } + + function updateContainerAtExpirationTime( + element, + container, + parentComponent, + currentTime, + expirationTime, + callback + ) { + // TODO: If this is a nested container, this won't be the root. + var current = container.current + + { + if (ReactFiberInstrumentation_1.debugTool) { + if (current.alternate === null) { + ReactFiberInstrumentation_1.debugTool.onMountContainer( + container + ) + } else if (element === null) { + ReactFiberInstrumentation_1.debugTool.onUnmountContainer( + container + ) + } else { + ReactFiberInstrumentation_1.debugTool.onUpdateContainer( + container + ) + } + } + } + + var context = getContextForSubtree(parentComponent) + if (container.context === null) { + container.context = context + } else { + container.pendingContext = context + } + + return scheduleRootUpdate( + current, + element, + currentTime, + expirationTime, + callback + ) + } + + function findHostInstance(component) { + var fiber = get(component) + if (fiber === undefined) { + if (typeof component.render === 'function') { + invariant( + false, + 'Unable to find node on an unmounted component.' + ) + } else { + invariant( + false, + 'Argument appears to not be a ReactComponent. Keys: %s', + Object.keys(component) + ) + } + } + var hostFiber = findCurrentHostFiber(fiber) + if (hostFiber === null) { + return null + } + return hostFiber.stateNode + } + + return { + createContainer: function ( + containerInfo, + isAsync, + hydrate + ) { + return createFiberRoot(containerInfo, isAsync, hydrate) + }, + updateContainer: function ( + element, + container, + parentComponent, + callback + ) { + var current = container.current + var currentTime = recalculateCurrentTime() + var expirationTime = computeExpirationForFiber(current) + return updateContainerAtExpirationTime( + element, + container, + parentComponent, + currentTime, + expirationTime, + callback + ) + }, + updateContainerAtExpirationTime: function ( + element, + container, + parentComponent, + expirationTime, + callback + ) { + var currentTime = recalculateCurrentTime() + return updateContainerAtExpirationTime( + element, + container, + parentComponent, + currentTime, + expirationTime, + callback + ) + }, + + flushRoot: flushRoot, + + requestWork: requestWork, + + computeUniqueAsyncExpiration: computeUniqueAsyncExpiration, + + batchedUpdates: batchedUpdates, + + unbatchedUpdates: unbatchedUpdates, + + deferredUpdates: deferredUpdates, + + syncUpdates: syncUpdates, + + interactiveUpdates: interactiveUpdates, + + flushInteractiveUpdates: flushInteractiveUpdates, + + flushControlled: flushControlled, + + flushSync: flushSync, + + getPublicRootInstance: function (container) { + var containerFiber = container.current + if (!containerFiber.child) { + return null + } + switch (containerFiber.child.tag) { + case HostComponent: + return getPublicInstance( + containerFiber.child.stateNode + ) + default: + return containerFiber.child.stateNode + } + }, + + findHostInstance: findHostInstance, + + findHostInstanceWithNoPortals: function (fiber) { + var hostFiber = findCurrentHostFiberWithNoPortals(fiber) + if (hostFiber === null) { + return null + } + return hostFiber.stateNode + }, + injectIntoDevTools: function (devToolsConfig) { + var findFiberByHostInstance = + devToolsConfig.findFiberByHostInstance + + return injectInternals( + _assign({}, devToolsConfig, { + findHostInstanceByFiber: function (fiber) { + var hostFiber = findCurrentHostFiber(fiber) + if (hostFiber === null) { + return null + } + return hostFiber.stateNode + }, + findFiberByHostInstance: function (instance) { + if (!findFiberByHostInstance) { + // Might not be implemented by the renderer. + return null + } + return findFiberByHostInstance(instance) + }, + }) + ) + }, + } + } - { - checkClassInstance(workInProgress); - } + var ReactFiberReconciler$2 = Object.freeze({ + default: ReactFiberReconciler$1, + }) + + var ReactFiberReconciler$3 = + (ReactFiberReconciler$2 && ReactFiberReconciler$1) || + ReactFiberReconciler$2 + + // TODO: bundle Flow types with the package. + + // TODO: decide on the top-level export form. + // This is hacky but makes it work with both Rollup and Jest. + var reactReconciler = ReactFiberReconciler$3['default'] + ? ReactFiberReconciler$3['default'] + : ReactFiberReconciler$3 + + function createPortal$1( + children, + containerInfo, + // TODO: figure out the API for cross-renderer implementation. + implementation + ) { + var key = + arguments.length > 3 && arguments[3] !== undefined + ? arguments[3] + : null + + return { + // This tag allow us to uniquely identify this as a React Portal + $$typeof: REACT_PORTAL_TYPE, + key: key == null ? null : '' + key, + children: children, + containerInfo: containerInfo, + implementation: implementation, + } + } - var instance = workInProgress.stateNode; - var props = workInProgress.pendingProps; - var unmaskedContext = getUnmaskedContext(workInProgress); + // TODO: this is special because it gets imported during build. + + var ReactVersion = '16.3.3' + + // a requestAnimationFrame, storing the time for the start of the frame, then + // scheduling a postMessage which gets scheduled after paint. Within the + // postMessage handler do as much work as possible until time + frame rate. + // By separating the idle call into a separate event tick we ensure that + // layout, paint and other browser work is counted against the available time. + // The frame rate is dynamically adjusted. + + { + if ( + ExecutionEnvironment.canUseDOM && + typeof requestAnimationFrame !== 'function' + ) { + warning( + false, + 'React depends on requestAnimationFrame. Make sure that you load a ' + + 'polyfill in older browsers. https://fb.me/react-polyfills' + ) + } + } - instance.props = props; - instance.state = workInProgress.memoizedState; - instance.refs = emptyObject; - instance.context = getMaskedContext(workInProgress, unmaskedContext); + var hasNativePerformanceNow = + typeof performance === 'object' && + typeof performance.now === 'function' - { - if (workInProgress.mode & StrictMode) { - ReactStrictModeWarnings.recordUnsafeLifecycleWarnings(workInProgress, instance); - } + var now = void 0 + if (hasNativePerformanceNow) { + now = function () { + return performance.now() + } + } else { + now = function () { + return Date.now() + } + } - if (warnAboutDeprecatedLifecycles) { - ReactStrictModeWarnings.recordDeprecationWarnings(workInProgress, instance); - } - } + // TODO: There's no way to cancel, because Fiber doesn't atm. + var rIC = void 0 + var cIC = void 0 + + if (!ExecutionEnvironment.canUseDOM) { + rIC = function (frameCallback) { + return setTimeout(function () { + frameCallback({ + timeRemaining: function () { + return Infinity + }, + + didTimeout: false, + }) + }) + } + cIC = function (timeoutID) { + clearTimeout(timeoutID) + } + } else if ( + alwaysUseRequestIdleCallbackPolyfill || + typeof requestIdleCallback !== 'function' || + typeof cancelIdleCallback !== 'function' + ) { + // Polyfill requestIdleCallback and cancelIdleCallback + + var scheduledRICCallback = null + var isIdleScheduled = false + var timeoutTime = -1 + + var isAnimationFrameScheduled = false + + var frameDeadline = 0 + // We start out assuming that we run at 30fps but then the heuristic tracking + // will adjust this value to a faster fps if we get more frequent animation + // frames. + var previousFrameTime = 33 + var activeFrameTime = 33 + + var frameDeadlineObject = void 0 + if (hasNativePerformanceNow) { + frameDeadlineObject = { + didTimeout: false, + timeRemaining: function () { + // We assume that if we have a performance timer that the rAF callback + // gets a performance timer value. Not sure if this is always true. + var remaining = frameDeadline - performance.now() + return remaining > 0 ? remaining : 0 + }, + } + } else { + frameDeadlineObject = { + didTimeout: false, + timeRemaining: function () { + // Fallback to Date.now() + var remaining = frameDeadline - Date.now() + return remaining > 0 ? remaining : 0 + }, + } + } + + // We use the postMessage trick to defer idle work until after the repaint. + var messageKey = + '__reactIdleCallback$' + Math.random().toString(36).slice(2) + var idleTick = function (event) { + if (event.source !== window || event.data !== messageKey) { + return + } + + isIdleScheduled = false + + var currentTime = now() + if (frameDeadline - currentTime <= 0) { + // There's no time left in this idle period. Check if the callback has + // a timeout and whether it's been exceeded. + if (timeoutTime !== -1 && timeoutTime <= currentTime) { + // Exceeded the timeout. Invoke the callback even though there's no + // time left. + frameDeadlineObject.didTimeout = true + } else { + // No timeout. + if (!isAnimationFrameScheduled) { + // Schedule another animation callback so we retry later. + isAnimationFrameScheduled = true + requestAnimationFrame(animationTick) + } + // Exit without invoking the callback. + return + } + } else { + // There's still time left in this idle period. + frameDeadlineObject.didTimeout = false + } + + timeoutTime = -1 + var callback = scheduledRICCallback + scheduledRICCallback = null + if (callback !== null) { + callback(frameDeadlineObject) + } + } + // Assumes that we have addEventListener in this environment. Might need + // something better for old IE. + window.addEventListener('message', idleTick, false) + + var animationTick = function (rafTime) { + isAnimationFrameScheduled = false + var nextFrameTime = + rafTime - frameDeadline + activeFrameTime + if ( + nextFrameTime < activeFrameTime && + previousFrameTime < activeFrameTime + ) { + if (nextFrameTime < 8) { + // Defensive coding. We don't support higher frame rates than 120hz. + // If we get lower than that, it is probably a bug. + nextFrameTime = 8 + } + // If one frame goes long, then the next one can be short to catch up. + // If two frames are short in a row, then that's an indication that we + // actually have a higher frame rate than what we're currently optimizing. + // We adjust our heuristic dynamically accordingly. For example, if we're + // running on 120hz display or 90hz VR display. + // Take the max of the two in case one of them was an anomaly due to + // missed frame deadlines. + activeFrameTime = + nextFrameTime < previousFrameTime + ? previousFrameTime + : nextFrameTime + } else { + previousFrameTime = nextFrameTime + } + frameDeadline = rafTime + activeFrameTime + if (!isIdleScheduled) { + isIdleScheduled = true + window.postMessage(messageKey, '*') + } + } + + rIC = function (callback, options) { + // This assumes that we only schedule one callback at a time because that's + // how Fiber uses it. + scheduledRICCallback = callback + if ( + options != null && + typeof options.timeout === 'number' + ) { + timeoutTime = now() + options.timeout + } + if (!isAnimationFrameScheduled) { + // If rAF didn't already schedule one, we need to schedule a frame. + // TODO: If this rAF doesn't materialize because the browser throttles, we + // might want to still have setTimeout trigger rIC as a backup to ensure + // that we keep performing work. + isAnimationFrameScheduled = true + requestAnimationFrame(animationTick) + } + return 0 + } + + cIC = function () { + scheduledRICCallback = null + isIdleScheduled = false + timeoutTime = -1 + } + } else { + rIC = window.requestIdleCallback + cIC = window.cancelIdleCallback + } - // In order to support react-lifecycles-compat polyfilled components, - // Unsafe lifecycles should not be invoked for components using the new APIs. - if (typeof ctor.getDerivedStateFromProps !== 'function' && typeof instance.getSnapshotBeforeUpdate !== 'function' && (typeof instance.UNSAFE_componentWillMount === 'function' || typeof instance.componentWillMount === 'function')) { - callComponentWillMount(workInProgress, instance); - // If we had additional state updates during this life-cycle, let's - // process them now. - var updateQueue = workInProgress.updateQueue; - if (updateQueue !== null) { - instance.state = processUpdateQueue(current, workInProgress, updateQueue, instance, props, renderExpirationTime); - } - } - if (typeof instance.componentDidMount === 'function') { - workInProgress.effectTag |= Update; - } - } + var didWarnSelectedSetOnOption = false + + function flattenChildren(children) { + var content = '' + + // Flatten children and warn if they aren't strings or numbers; + // invalid types are ignored. + // We can silently skip them because invalid DOM nesting warning + // catches these cases in Fiber. + React.Children.forEach(children, function (child) { + if (child == null) { + return + } + if ( + typeof child === 'string' || + typeof child === 'number' + ) { + content += child + } + }) + + return content + } - function resumeMountClassInstance(workInProgress, renderExpirationTime) { - var ctor = workInProgress.type; - var instance = workInProgress.stateNode; - resetInputPointers(workInProgress, instance); + /** + * Implements an