From 5c13478bac684581e6d7a502c5539a1a3044c6d9 Mon Sep 17 00:00:00 2001 From: janssen <118828444+janssen-tiobe@users.noreply.github.com> Date: Thu, 31 Aug 2023 14:36:09 +0200 Subject: [PATCH 1/8] #32831: Changed fetcher to retrieve project information Rather than seperately collecting quality gates and analyzed files they are now collected in a single function and put in a single object. Also changed the summary function to now report the violations and gates per project. --- dist/index.js | 129 +++++++++++++++++++++---------------- src/helper/interfaces.d.ts | 16 ++++- src/helper/summary.ts | 51 ++++++++------- src/main.ts | 17 +++-- src/tics/analyzer.ts | 10 +-- src/tics/fetcher.ts | 53 +++++++++++++-- 6 files changed, 181 insertions(+), 95 deletions(-) diff --git a/dist/index.js b/dist/index.js index e64cb68e..5e67b2f2 100644 --- a/dist/index.js +++ b/dist/index.js @@ -787,30 +787,34 @@ const configuration_1 = __nccwpck_require__(5527); const enums_1 = __nccwpck_require__(1655); const underscore_1 = __nccwpck_require__(5067); const logger_1 = __nccwpck_require__(6440); -function createSummaryBody(analysis, filesAnalyzed, qualityGate, reviewComments) { - const failedConditions = extractFailedConditions(qualityGate.gates); +function createSummaryBody(analysis, analysisResults, reviewComments) { logger_1.logger.header('Creating summary.'); core_1.summary.addHeading('TICS Quality Gate'); - core_1.summary.addHeading(`${(0, markdown_1.generateStatusMarkdown)(qualityGate.passed ? enums_1.Status.PASSED : enums_1.Status.FAILED, true)}`, 3); - core_1.summary.addHeading(`${failedConditions.length} Condition(s) failed`, 2); - failedConditions.forEach(condition => { - if (condition.details && condition.details.items.length > 0) { - core_1.summary.addRaw(`\n
:x: ${condition.message}\n`); - core_1.summary.addBreak(); - core_1.summary.addTable(createConditionTable(condition)); - core_1.summary.addRaw('
', true); - } - else { - core_1.summary.addRaw(`\n   :x: ${condition.message}`, true); + core_1.summary.addHeading(`${(0, markdown_1.generateStatusMarkdown)(analysisResults.passed ? enums_1.Status.PASSED : enums_1.Status.FAILED, true)}`, 3); + analysisResults.projectResults.forEach(projectResult => { + if (projectResult.qualityGate) { + const failedConditions = extractFailedConditions(projectResult.qualityGate.gates); + core_1.summary.addHeading(projectResult.project, 3); + core_1.summary.addHeading(`${failedConditions.length} Condition(s) failed`, 4); + failedConditions.forEach(condition => { + if (condition.details && condition.details.items.length > 0) { + core_1.summary.addRaw(`\n
:x: ${condition.message}\n`); + core_1.summary.addBreak(); + core_1.summary.addTable(createConditionTable(condition)); + core_1.summary.addRaw('
', true); + } + else { + core_1.summary.addRaw(`\n   :x: ${condition.message}`, true); + } + }); + core_1.summary.addEOL(); + core_1.summary.addLink('See the results in the TICS Viewer', projectResult.explorerUrl); + if (reviewComments && reviewComments.unpostable.length > 0) { + core_1.summary.addRaw(createUnpostableAnnotationsDetails(reviewComments.unpostable)); + } + core_1.summary.addRaw(createFilesSummary(projectResult.analyzedFiles)); } }); - core_1.summary.addEOL(); - if (analysis.explorerUrl) - core_1.summary.addLink('See the results in the TICS Viewer', analysis.explorerUrl); - if (reviewComments && reviewComments.unpostable.length > 0) { - core_1.summary.addRaw(createUnpostableAnnotationsDetails(reviewComments.unpostable)); - } - core_1.summary.addRaw(createFilesSummary(filesAnalyzed)); logger_1.logger.info('Created summary.'); return core_1.summary.stringify(); } @@ -1079,7 +1083,7 @@ async function runTicsAnalyzer(fileListPath) { return { completed: completed, statusCode: statusCode, - explorerUrl: explorerUrl, + explorerUrls: explorerUrl, errorList: errorList, warningList: warningList }; @@ -1133,10 +1137,11 @@ function findInStdOutOrErr(data) { if (warning && !warningList.find(w => w === warning?.toString())) warningList.push(warning.toString()); const findExplorerUrl = data.match(/\/Explorer.*/g); - if (!explorerUrl && findExplorerUrl) { + if (findExplorerUrl) { const urlPath = findExplorerUrl.slice(-1).pop(); - if (urlPath) - explorerUrl = configuration_1.viewerUrl + urlPath; + if (urlPath) { + explorerUrl.push(configuration_1.viewerUrl + urlPath); + } } } /** @@ -1333,10 +1338,38 @@ exports.getProjectName = getProjectName; "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getViewerVersion = exports.getAnnotations = exports.getQualityGate = exports.getAnalyzedFiles = void 0; +exports.getViewerVersion = exports.getAnnotations = exports.getAnalysisResults = void 0; const configuration_1 = __nccwpck_require__(5527); const logger_1 = __nccwpck_require__(6440); const api_helper_1 = __nccwpck_require__(3823); +async function getAnalysisResults(explorerUrls) { + let analysisResults = { + passed: true, + message: '', + missesQualityGate: false, + projectResults: [] + }; + explorerUrls.forEach(async (url) => { + let analysisResult = { + project: (0, api_helper_1.getProjectName)(url), + explorerUrl: url, + analyzedFiles: await getAnalyzedFiles(url) + }; + const qualityGate = await getQualityGate(url); + if (!qualityGate) { + analysisResults.passed = false; + analysisResults.missesQualityGate = true; + } + if (qualityGate && !qualityGate.passed) { + analysisResults.passed = false; + analysisResults.message += qualityGate.message + ' '; + } + analysisResult.qualityGate = qualityGate; + analysisResults.projectResults.push(analysisResult); + }); + return analysisResults; +} +exports.getAnalysisResults = getAnalysisResults; /** * Retrieves the files TICS analyzed from the TICS viewer. * @param url The TICS explorer url. @@ -1365,7 +1398,6 @@ async function getAnalyzedFiles(url) { } return analyzedFiles; } -exports.getAnalyzedFiles = getAnalyzedFiles; /** * Returns the url to get the analyzed files with from the TICS. * @param url The TICS explorer url. @@ -1392,7 +1424,6 @@ async function getQualityGate(url) { response = await (0, api_helper_1.httpRequest)(qualityGateUrl); logger_1.logger.info('Retrieved the quality gates.'); logger_1.logger.debug(JSON.stringify(response)); - return response; } catch (error) { let message = 'reason unknown'; @@ -1402,7 +1433,6 @@ async function getQualityGate(url) { } return response; } -exports.getQualityGate = getQualityGate; /** * Builds the quality gate url from the explorer url. * @param url The TICS Explorer url. @@ -1426,9 +1456,15 @@ function getQualityGateUrl(url) { * @param apiLinks annotationsApiLinks url. * @returns TICS annotations. */ -async function getAnnotations(apiLinks) { +async function getAnnotations(analysisResults) { let annotations = []; logger_1.logger.header('Retrieving annotations.'); + let apiLinks = []; + analysisResults.projectResults.forEach((analysis) => { + if (analysis.qualityGate) { + apiLinks.push(...analysis.qualityGate.annotationsApiV1Links); + } + }); try { await Promise.all(apiLinks.map(async (link, index) => { const annotationsUrl = new URL(`${configuration_1.baseUrl}/${link.url}`); @@ -19959,27 +19995,11 @@ module.exports.canonical = canonical; * ``` */ const validate = (version) => typeof version === 'string' && /^[v\d]/.test(version) && semver.test(version); - /** - * Validate [semver](https://semver.org/) version strings strictly. Will not accept wildcards and version ranges. - * - * @param version Version number to validate - * @returns `true` if the version number is a valid semver version number `false` otherwise - * - * @example - * ``` - * validate('1.0.0-rc.1'); // return true - * validate('1.0-rc.1'); // return false - * validate('foo'); // return false - * ``` - */ - const validateStrict = (version) => typeof version === 'string' && - /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(version); exports.compare = compare; exports.compareVersions = compareVersions; exports.satisfies = satisfies; exports.validate = validate; - exports.validateStrict = validateStrict; })); //# sourceMappingURL=index.js.map @@ -58110,7 +58130,7 @@ async function run() { if (!changedFilesFilePath) return logger_1.logger.error('No filepath for changedfiles list.'); analysis = await (0, analyzer_1.runTicsAnalyzer)(changedFilesFilePath); - if (!analysis.explorerUrl) { + if (analysis.explorerUrls.length === 0) { (0, comments_1.deletePreviousComments)(await (0, comments_1.getPostedComments)()); if (!analysis.completed) { await (0, comments_1.postErrorComment)(analysis); @@ -58127,10 +58147,9 @@ async function run() { (0, api_helper_1.cliSummary)(analysis); return; } - const analyzedFiles = await (0, fetcher_1.getAnalyzedFiles)(analysis.explorerUrl); - const qualityGate = await (0, fetcher_1.getQualityGate)(analysis.explorerUrl); - if (!qualityGate) - return logger_1.logger.exit('Quality gate could not be retrieved'); + const analysisResults = await (0, fetcher_1.getAnalysisResults)(analysis.explorerUrls); + if (analysisResults.missesQualityGate) + return logger_1.logger.exit('Some quality gates could not be retrieved'); // If not run on a pull request no review comments have to be deleted if (configuration_1.githubConfig.eventName === 'pull_request') { const previousReviewComments = await (0, annotations_1.getPostedReviewComments)(); @@ -58140,21 +58159,21 @@ async function run() { } let reviewComments; if (configuration_1.ticsConfig.postAnnotations) { - const annotations = await (0, fetcher_1.getAnnotations)(qualityGate.annotationsApiV1Links); + const annotations = await (0, fetcher_1.getAnnotations)(analysisResults); if (annotations && annotations.length > 0) { reviewComments = (0, summary_1.createReviewComments)(annotations, changedFiles); (0, annotations_1.postAnnotations)(reviewComments); } } - let reviewBody = (0, summary_1.createSummaryBody)(analysis, analyzedFiles, qualityGate, reviewComments); + let reviewBody = (0, summary_1.createSummaryBody)(analysis, analysisResults, reviewComments); // If not run on a pull request no comments have to be deleted // and there is no conversation to post to. if (configuration_1.githubConfig.eventName === 'pull_request') { (0, comments_1.deletePreviousComments)(await (0, comments_1.getPostedComments)()); - await postToConversation(true, reviewBody, qualityGate.passed ? enums_1.Events.APPROVE : enums_1.Events.REQUEST_CHANGES); + await postToConversation(true, reviewBody, analysisResults.passed ? enums_1.Events.APPROVE : enums_1.Events.REQUEST_CHANGES); } - if (!qualityGate.passed) - logger_1.logger.setFailed(qualityGate.message); + if (!analysisResults.passed) + logger_1.logger.setFailed(analysisResults.message); } if (configuration_1.ticsConfig.tmpDir || configuration_1.githubConfig.debugger) { await (0, artifacts_1.uploadArtifact)(); diff --git a/src/helper/interfaces.d.ts b/src/helper/interfaces.d.ts index 66895d91..61c08c8e 100644 --- a/src/helper/interfaces.d.ts +++ b/src/helper/interfaces.d.ts @@ -3,7 +3,21 @@ export interface Analysis { statusCode: number; errorList: string[]; warningList: string[]; - explorerUrl?: string; + explorerUrls: string[]; +} + +export interface AnalysisResults { + passed: boolean; + message: string; + missesQualityGate: boolean; + projectResults: ProjectResult[]; +} + +export interface ProjectResult { + project: string; + explorerUrl: string; + qualityGate?: QualityGate; + analyzedFiles: string[]; } export interface QualityGate { diff --git a/src/helper/summary.ts b/src/helper/summary.ts index 8ef54f45..5a8238b9 100644 --- a/src/helper/summary.ts +++ b/src/helper/summary.ts @@ -1,39 +1,46 @@ import { summary } from '@actions/core'; import { SummaryTableRow } from '@actions/core/lib/summary'; import { generateExpandableAreaMarkdown, generateStatusMarkdown } from './markdown'; -import { Analysis, Annotation, Condition, ExtendedAnnotation, Gate, QualityGate, ReviewComment, ReviewComments } from './interfaces'; +import { Analysis, AnalysisResults, Annotation, Condition, ExtendedAnnotation, Gate, QualityGate, ReviewComment, ReviewComments } from './interfaces'; import { ChangedFile } from '../github/interfaces'; import { githubConfig, viewerUrl } from '../configuration'; import { Status } from './enums'; import { range } from 'underscore'; import { logger } from './logger'; -export function createSummaryBody(analysis: Analysis, filesAnalyzed: string[], qualityGate: QualityGate, reviewComments?: ReviewComments): string { - const failedConditions = extractFailedConditions(qualityGate.gates); - +export function createSummaryBody(analysis: Analysis, analysisResults: AnalysisResults, reviewComments?: ReviewComments): string { logger.header('Creating summary.'); summary.addHeading('TICS Quality Gate'); - summary.addHeading(`${generateStatusMarkdown(qualityGate.passed ? Status.PASSED : Status.FAILED, true)}`, 3); - summary.addHeading(`${failedConditions.length} Condition(s) failed`, 2); - failedConditions.forEach(condition => { - if (condition.details && condition.details.items.length > 0) { - summary.addRaw(`\n
:x: ${condition.message}\n`); - summary.addBreak(); - summary.addTable(createConditionTable(condition)); - summary.addRaw('
', true); - } else { - summary.addRaw(`\n   :x: ${condition.message}`, true); - } - }); - summary.addEOL(); + summary.addHeading(`${generateStatusMarkdown(analysisResults.passed ? Status.PASSED : Status.FAILED, true)}`, 3); - if (analysis.explorerUrl) summary.addLink('See the results in the TICS Viewer', analysis.explorerUrl); + analysisResults.projectResults.forEach(projectResult => { + if (projectResult.qualityGate) { + const failedConditions = extractFailedConditions(projectResult.qualityGate.gates); - if (reviewComments && reviewComments.unpostable.length > 0) { - summary.addRaw(createUnpostableAnnotationsDetails(reviewComments.unpostable)); - } + summary.addHeading(projectResult.project, 3); + summary.addHeading(`${failedConditions.length} Condition(s) failed`, 4); + failedConditions.forEach(condition => { + if (condition.details && condition.details.items.length > 0) { + summary.addRaw(`\n
:x: ${condition.message}\n`); + summary.addBreak(); + summary.addTable(createConditionTable(condition)); + summary.addRaw('
', true); + } else { + summary.addRaw(`\n   :x: ${condition.message}`, true); + } + }); + summary.addEOL(); + + summary.addLink('See the results in the TICS Viewer', projectResult.explorerUrl); + + if (reviewComments && reviewComments.unpostable.length > 0) { + summary.addRaw(createUnpostableAnnotationsDetails(reviewComments.unpostable)); + } + + summary.addRaw(createFilesSummary(projectResult.analyzedFiles)); + } + }); - summary.addRaw(createFilesSummary(filesAnalyzed)); logger.info('Created summary.'); return summary.stringify(); diff --git a/src/main.ts b/src/main.ts index 0d05e1d1..e78a8791 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,7 +5,7 @@ import { changedFilesToFile, getChangedFilesOfPullRequest } from './github/pulls import { logger } from './helper/logger'; import { runTicsAnalyzer } from './tics/analyzer'; import { cliSummary } from './tics/api_helper'; -import { getAnalyzedFiles, getAnnotations, getQualityGate, getViewerVersion } from './tics/fetcher'; +import { getAnalysisResults, getAnnotations, getViewerVersion } from './tics/fetcher'; import { postNothingAnalyzedReview, postReview } from './github/review'; import { createSummaryBody, createReviewComments } from './helper/summary'; import { getPostedReviewComments, postAnnotations, deletePreviousReviewComments } from './github/annotations'; @@ -67,7 +67,7 @@ async function run() { if (!changedFilesFilePath) return logger.error('No filepath for changedfiles list.'); analysis = await runTicsAnalyzer(changedFilesFilePath); - if (!analysis.explorerUrl) { + if (analysis.explorerUrls.length === 0) { deletePreviousComments(await getPostedComments()); if (!analysis.completed) { await postErrorComment(analysis); @@ -83,10 +83,9 @@ async function run() { return; } - const analyzedFiles = await getAnalyzedFiles(analysis.explorerUrl); - const qualityGate = await getQualityGate(analysis.explorerUrl); + const analysisResults = await getAnalysisResults(analysis.explorerUrls); - if (!qualityGate) return logger.exit('Quality gate could not be retrieved'); + if (analysisResults.missesQualityGate) return logger.exit('Some quality gates could not be retrieved'); // If not run on a pull request no review comments have to be deleted if (githubConfig.eventName === 'pull_request') { @@ -98,24 +97,24 @@ async function run() { let reviewComments: ReviewComments | undefined; if (ticsConfig.postAnnotations) { - const annotations = await getAnnotations(qualityGate.annotationsApiV1Links); + const annotations = await getAnnotations(analysisResults); if (annotations && annotations.length > 0) { reviewComments = createReviewComments(annotations, changedFiles); postAnnotations(reviewComments); } } - let reviewBody = createSummaryBody(analysis, analyzedFiles, qualityGate, reviewComments); + let reviewBody = createSummaryBody(analysis, analysisResults, reviewComments); // If not run on a pull request no comments have to be deleted // and there is no conversation to post to. if (githubConfig.eventName === 'pull_request') { deletePreviousComments(await getPostedComments()); - await postToConversation(true, reviewBody, qualityGate.passed ? Events.APPROVE : Events.REQUEST_CHANGES); + await postToConversation(true, reviewBody, analysisResults.passed ? Events.APPROVE : Events.REQUEST_CHANGES); } - if (!qualityGate.passed) logger.setFailed(qualityGate.message); + if (!analysisResults.passed) logger.setFailed(analysisResults.message); } if (ticsConfig.tmpDir || githubConfig.debugger) { diff --git a/src/tics/analyzer.ts b/src/tics/analyzer.ts index c07ec801..c6bee434 100644 --- a/src/tics/analyzer.ts +++ b/src/tics/analyzer.ts @@ -7,7 +7,7 @@ import { getTmpDir } from '../github/artifacts'; let errorList: string[] = []; let warningList: string[] = []; -let explorerUrl: string | undefined; +let explorerUrl: string[]; let statusCode: number; let completed: boolean; @@ -50,7 +50,7 @@ export async function runTicsAnalyzer(fileListPath: string): Promise { return { completed: completed, statusCode: statusCode, - explorerUrl: explorerUrl, + explorerUrls: explorerUrl, errorList: errorList, warningList: warningList }; @@ -106,9 +106,11 @@ function findInStdOutOrErr(data: string): void { if (warning && !warningList.find(w => w === warning?.toString())) warningList.push(warning.toString()); const findExplorerUrl = data.match(/\/Explorer.*/g); - if (!explorerUrl && findExplorerUrl) { + if (findExplorerUrl) { const urlPath = findExplorerUrl.slice(-1).pop(); - if (urlPath) explorerUrl = viewerUrl + urlPath; + if (urlPath) { + explorerUrl.push(viewerUrl + urlPath); + } } } diff --git a/src/tics/fetcher.ts b/src/tics/fetcher.ts index 56516d4e..15d704b9 100644 --- a/src/tics/fetcher.ts +++ b/src/tics/fetcher.ts @@ -1,5 +1,7 @@ import { baseUrl, ticsConfig } from '../configuration'; import { + ProjectResult, + AnalysisResults, AnalyzedFile, AnalyzedFiles, Annotation, @@ -12,12 +14,47 @@ import { import { logger } from '../helper/logger'; import { getItemFromUrl, getProjectName, httpRequest } from './api_helper'; +export async function getAnalysisResults(explorerUrls: string[]): Promise { + let analysisResults: AnalysisResults = { + passed: true, + message: '', + missesQualityGate: false, + projectResults: [] + }; + + explorerUrls.forEach(async (url: string) => { + let analysisResult: ProjectResult = { + project: getProjectName(url), + explorerUrl: url, + analyzedFiles: await getAnalyzedFiles(url) + }; + + const qualityGate = await getQualityGate(url); + + if (!qualityGate) { + analysisResults.passed = false; + analysisResults.missesQualityGate = true; + } + + if (qualityGate && !qualityGate.passed) { + analysisResults.passed = false; + analysisResults.message += qualityGate.message + ' '; + } + + analysisResult.qualityGate = qualityGate; + + analysisResults.projectResults.push(analysisResult); + }); + + return analysisResults; +} + /** * Retrieves the files TICS analyzed from the TICS viewer. * @param url The TICS explorer url. * @returns the analyzed files. */ -export async function getAnalyzedFiles(url: string): Promise { +async function getAnalyzedFiles(url: string): Promise { logger.header('Retrieving analyzed files.'); const analyzedFilesUrl = getAnalyzedFilesUrl(url); let analyzedFiles: string[] = []; @@ -60,7 +97,7 @@ function getAnalyzedFilesUrl(url: string) { * @param url The TICS explorer url. * @returns the quality gates */ -export async function getQualityGate(url: string): Promise { +async function getQualityGate(url: string): Promise { logger.header('Retrieving the quality gates.'); const qualityGateUrl = getQualityGateUrl(url); logger.debug(`From: ${qualityGateUrl}`); @@ -71,12 +108,12 @@ export async function getQualityGate(url: string): Promise(qualityGateUrl); logger.info('Retrieved the quality gates.'); logger.debug(JSON.stringify(response)); - return response; } catch (error: unknown) { let message = 'reason unknown'; if (error instanceof Error) message = error.message; logger.exit(`There was an error retrieving the quality gates: ${message}`); } + return response; } @@ -109,9 +146,17 @@ function getQualityGateUrl(url: string) { * @param apiLinks annotationsApiLinks url. * @returns TICS annotations. */ -export async function getAnnotations(apiLinks: AnnotationApiLink[]): Promise { +export async function getAnnotations(analysisResults: AnalysisResults): Promise { let annotations: ExtendedAnnotation[] = []; logger.header('Retrieving annotations.'); + + let apiLinks: AnnotationApiLink[] = []; + analysisResults.projectResults.forEach((analysis: ProjectResult) => { + if (analysis.qualityGate) { + apiLinks.push(...analysis.qualityGate.annotationsApiV1Links); + } + }); + try { await Promise.all( apiLinks.map(async (link, index) => { From e5511f36f71adf81ffaf3ca3fe057ec18c84a0a6 Mon Sep 17 00:00:00 2001 From: janssen <118828444+janssen-tiobe@users.noreply.github.com> Date: Thu, 31 Aug 2023 14:49:36 +0200 Subject: [PATCH 2/8] #32831: Forgot to initialize array of explorerUrls --- dist/index.js | 6 +++--- src/tics/analyzer.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dist/index.js b/dist/index.js index 5e67b2f2..939f2f84 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1042,7 +1042,7 @@ const api_helper_1 = __nccwpck_require__(3823); const artifacts_1 = __nccwpck_require__(5734); let errorList = []; let warningList = []; -let explorerUrl; +let explorerUrls = []; let statusCode; let completed; /** @@ -1083,7 +1083,7 @@ async function runTicsAnalyzer(fileListPath) { return { completed: completed, statusCode: statusCode, - explorerUrls: explorerUrl, + explorerUrls: explorerUrls, errorList: errorList, warningList: warningList }; @@ -1140,7 +1140,7 @@ function findInStdOutOrErr(data) { if (findExplorerUrl) { const urlPath = findExplorerUrl.slice(-1).pop(); if (urlPath) { - explorerUrl.push(configuration_1.viewerUrl + urlPath); + explorerUrls.push(configuration_1.viewerUrl + urlPath); } } } diff --git a/src/tics/analyzer.ts b/src/tics/analyzer.ts index c6bee434..f1699a0c 100644 --- a/src/tics/analyzer.ts +++ b/src/tics/analyzer.ts @@ -7,7 +7,7 @@ import { getTmpDir } from '../github/artifacts'; let errorList: string[] = []; let warningList: string[] = []; -let explorerUrl: string[]; +let explorerUrls: string[] = []; let statusCode: number; let completed: boolean; @@ -50,7 +50,7 @@ export async function runTicsAnalyzer(fileListPath: string): Promise { return { completed: completed, statusCode: statusCode, - explorerUrls: explorerUrl, + explorerUrls: explorerUrls, errorList: errorList, warningList: warningList }; @@ -109,7 +109,7 @@ function findInStdOutOrErr(data: string): void { if (findExplorerUrl) { const urlPath = findExplorerUrl.slice(-1).pop(); if (urlPath) { - explorerUrl.push(viewerUrl + urlPath); + explorerUrls.push(viewerUrl + urlPath); } } } From a355b20bd28c88c994c780c418b474d80da69834 Mon Sep 17 00:00:00 2001 From: janssen <118828444+janssen-tiobe@users.noreply.github.com> Date: Thu, 31 Aug 2023 14:54:09 +0200 Subject: [PATCH 3/8] #32831: Small changes in summary output --- dist/index.js | 6 +++--- src/helper/summary.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dist/index.js b/dist/index.js index 939f2f84..e1c73f5e 100644 --- a/dist/index.js +++ b/dist/index.js @@ -794,8 +794,8 @@ function createSummaryBody(analysis, analysisResults, reviewComments) { analysisResults.projectResults.forEach(projectResult => { if (projectResult.qualityGate) { const failedConditions = extractFailedConditions(projectResult.qualityGate.gates); - core_1.summary.addHeading(projectResult.project, 3); - core_1.summary.addHeading(`${failedConditions.length} Condition(s) failed`, 4); + core_1.summary.addHeading(projectResult.project, 2); + core_1.summary.addHeading(`${failedConditions.length} Condition(s) failed`, 3); failedConditions.forEach(condition => { if (condition.details && condition.details.items.length > 0) { core_1.summary.addRaw(`\n
:x: ${condition.message}\n`); @@ -851,7 +851,7 @@ exports.createErrorSummary = createErrorSummary; * @returns Dropdown with all the files analyzed. */ function createFilesSummary(fileList) { - let header = 'The following files have been checked:'; + let header = 'The following files have been checked for this project:'; let body = '
    '; fileList.sort(); fileList.forEach(file => { diff --git a/src/helper/summary.ts b/src/helper/summary.ts index 5a8238b9..6ae86b7f 100644 --- a/src/helper/summary.ts +++ b/src/helper/summary.ts @@ -17,8 +17,8 @@ export function createSummaryBody(analysis: Analysis, analysisResults: AnalysisR if (projectResult.qualityGate) { const failedConditions = extractFailedConditions(projectResult.qualityGate.gates); - summary.addHeading(projectResult.project, 3); - summary.addHeading(`${failedConditions.length} Condition(s) failed`, 4); + summary.addHeading(projectResult.project, 2); + summary.addHeading(`${failedConditions.length} Condition(s) failed`, 3); failedConditions.forEach(condition => { if (condition.details && condition.details.items.length > 0) { summary.addRaw(`\n
    :x: ${condition.message}\n`); @@ -83,7 +83,7 @@ export function createErrorSummary(errorList: string[], warningList: string[]): * @returns Dropdown with all the files analyzed. */ export function createFilesSummary(fileList: string[]): string { - let header = 'The following files have been checked:'; + let header = 'The following files have been checked for this project:'; let body = '
      '; fileList.sort(); fileList.forEach(file => { From 3c6bf1b1b717b76177c48c451edebfc076d0a268 Mon Sep 17 00:00:00 2001 From: janssen <118828444+janssen-tiobe@users.noreply.github.com> Date: Thu, 31 Aug 2023 15:14:12 +0200 Subject: [PATCH 4/8] #32831: More small changes in summary output --- dist/index.js | 4 ++-- src/helper/summary.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dist/index.js b/dist/index.js index e1c73f5e..cbad1850 100644 --- a/dist/index.js +++ b/dist/index.js @@ -851,7 +851,7 @@ exports.createErrorSummary = createErrorSummary; * @returns Dropdown with all the files analyzed. */ function createFilesSummary(fileList) { - let header = 'The following files have been checked for this project:'; + let header = 'The following files have been checked for this project'; let body = '
        '; fileList.sort(); fileList.forEach(file => { @@ -1005,7 +1005,7 @@ function findAnnotationInList(list, annotation) { * @returns Summary of all the review comments that could not be posted. */ function createUnpostableAnnotationsDetails(unpostableReviewComments) { - let label = 'Quality gate failures that cannot be annotated in Files Changed:'; + let label = 'Quality gate failures that cannot be annotated in Files Changed'; let body = ''; let previousPath = ''; unpostableReviewComments.forEach(reviewComment => { diff --git a/src/helper/summary.ts b/src/helper/summary.ts index 6ae86b7f..f56583c5 100644 --- a/src/helper/summary.ts +++ b/src/helper/summary.ts @@ -83,7 +83,7 @@ export function createErrorSummary(errorList: string[], warningList: string[]): * @returns Dropdown with all the files analyzed. */ export function createFilesSummary(fileList: string[]): string { - let header = 'The following files have been checked for this project:'; + let header = 'The following files have been checked for this project'; let body = '
          '; fileList.sort(); fileList.forEach(file => { @@ -249,7 +249,7 @@ function findAnnotationInList(list: ExtendedAnnotation[], annotation: ExtendedAn * @returns Summary of all the review comments that could not be posted. */ export function createUnpostableAnnotationsDetails(unpostableReviewComments: ExtendedAnnotation[]): string { - let label = 'Quality gate failures that cannot be annotated in Files Changed:'; + let label = 'Quality gate failures that cannot be annotated in Files Changed'; let body = ''; let previousPath = ''; From 3291f170015810363df280b7b965017ad1bdd33d Mon Sep 17 00:00:00 2001 From: janssen <118828444+janssen-tiobe@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:05:56 +0200 Subject: [PATCH 5/8] #32831: Fixed tests failing --- dist/index.js | 4 +- src/tics/fetcher.ts | 4 +- test/github/comments.test.ts | 9 ++- test/github/review.test.ts | 124 +++++++++++++++++++++++++---------- test/helper/summary.test.ts | 11 ++-- test/main.test.ts | 35 ++++------ test/main_helper.ts | 69 +++++++++++++++---- test/tics/analyzer.test.ts | 2 +- test/tics/api_helper.test.ts | 6 +- test/tics/fetcher.test.ts | 45 ++++++++++++- 10 files changed, 225 insertions(+), 84 deletions(-) diff --git a/dist/index.js b/dist/index.js index cbad1850..f3c6da28 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1338,7 +1338,7 @@ exports.getProjectName = getProjectName; "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getViewerVersion = exports.getAnnotations = exports.getAnalysisResults = void 0; +exports.getViewerVersion = exports.getAnnotations = exports.getQualityGate = exports.getAnalyzedFiles = exports.getAnalysisResults = void 0; const configuration_1 = __nccwpck_require__(5527); const logger_1 = __nccwpck_require__(6440); const api_helper_1 = __nccwpck_require__(3823); @@ -1398,6 +1398,7 @@ async function getAnalyzedFiles(url) { } return analyzedFiles; } +exports.getAnalyzedFiles = getAnalyzedFiles; /** * Returns the url to get the analyzed files with from the TICS. * @param url The TICS explorer url. @@ -1433,6 +1434,7 @@ async function getQualityGate(url) { } return response; } +exports.getQualityGate = getQualityGate; /** * Builds the quality gate url from the explorer url. * @param url The TICS Explorer url. diff --git a/src/tics/fetcher.ts b/src/tics/fetcher.ts index 15d704b9..d76e3a4e 100644 --- a/src/tics/fetcher.ts +++ b/src/tics/fetcher.ts @@ -54,7 +54,7 @@ export async function getAnalysisResults(explorerUrls: string[]): Promise { +export async function getAnalyzedFiles(url: string): Promise { logger.header('Retrieving analyzed files.'); const analyzedFilesUrl = getAnalyzedFilesUrl(url); let analyzedFiles: string[] = []; @@ -97,7 +97,7 @@ function getAnalyzedFilesUrl(url: string) { * @param url The TICS explorer url. * @returns the quality gates */ -async function getQualityGate(url: string): Promise { +export async function getQualityGate(url: string): Promise { logger.header('Retrieving the quality gates.'); const qualityGateUrl = getQualityGateUrl(url); logger.debug(`From: ${qualityGateUrl}`); diff --git a/test/github/comments.test.ts b/test/github/comments.test.ts index cf0167ef..0251d360 100644 --- a/test/github/comments.test.ts +++ b/test/github/comments.test.ts @@ -51,7 +51,8 @@ describe('postErrorComment', () => { completed: true, errorList: ['error1'], warningList: [], - statusCode: 0 + statusCode: 0, + explorerUrls: [] }; await postErrorComment(analysis); expect(spy).toBeCalledTimes(1); @@ -64,7 +65,8 @@ describe('postErrorComment', () => { completed: true, errorList: ['error1'], warningList: [], - statusCode: 0 + statusCode: 0, + explorerUrls: [] }; await postErrorComment(analysis); const calledWith = { @@ -87,7 +89,8 @@ describe('postErrorComment', () => { completed: false, errorList: ['error1'], warningList: [], - statusCode: 0 + statusCode: 0, + explorerUrls: [] }; await postErrorComment(analysis); diff --git a/test/github/review.test.ts b/test/github/review.test.ts index ce6e0fc3..55a684e4 100644 --- a/test/github/review.test.ts +++ b/test/github/review.test.ts @@ -3,6 +3,7 @@ import { postNothingAnalyzedReview, postReview } from '../../src/github/review'; import { createSummaryBody } from '../../src/helper/summary'; import { Events } from '../../src/helper/enums'; import { logger } from '../../src/helper/logger'; +import { AnalysisResults } from '../../src/helper/interfaces'; jest.mock('../../src/helper/summary', () => { return { @@ -21,17 +22,31 @@ describe('postReview', () => { errorList: ['error1'], warningList: [], statusCode: 0, - explorerUrl: 'url' + explorerUrls: ['url'] }; - const qualityGate = { + + const analysisResults: AnalysisResults = { passed: true, - message: 'message', - url: 'url', - gates: [], - annotationsApiV1Links: [] + message: '', + missesQualityGate: false, + projectResults: [ + { + project: '', + explorerUrl: 'url', + analyzedFiles: [], + qualityGate: { + passed: true, + message: 'message', + url: 'url', + gates: [], + annotationsApiV1Links: [] + } + } + ] }; - let body = await createSummaryBody(analysis, [''], qualityGate, undefined); - let event = qualityGate.passed ? Events.APPROVE : Events.REQUEST_CHANGES; + + let body = createSummaryBody(analysis, analysisResults, undefined); + let event = analysisResults.passed ? Events.APPROVE : Events.REQUEST_CHANGES; await postReview(body, event); expect(spy).toBeCalledTimes(1); }); @@ -46,17 +61,31 @@ describe('postReview', () => { errorList: ['error1'], warningList: [], statusCode: 0, - explorerUrl: 'url' + explorerUrls: ['url'] }; - const qualityGate = { + + const analysisResults: AnalysisResults = { passed: true, - message: 'message', - url: 'url', - gates: [], - annotationsApiV1Links: [] + message: '', + missesQualityGate: false, + projectResults: [ + { + project: '', + explorerUrl: 'url', + analyzedFiles: [], + qualityGate: { + passed: true, + message: 'message', + url: 'url', + gates: [], + annotationsApiV1Links: [] + } + } + ] }; - let body = await createSummaryBody(analysis, [''], qualityGate, undefined); - let event = qualityGate.passed ? Events.APPROVE : Events.REQUEST_CHANGES; + + let body = createSummaryBody(analysis, analysisResults, undefined); + let event = analysisResults.passed ? Events.APPROVE : Events.REQUEST_CHANGES; await postReview(body, event); const calledWith = { @@ -80,21 +109,36 @@ describe('postReview', () => { errorList: ['error1'], warningList: [], statusCode: 0, - explorerUrl: 'url' + explorerUrls: ['url'] }; - const qualityGate = { + + const analysisResults: AnalysisResults = { passed: false, - message: 'message', - url: 'url', - gates: [], - annotationsApiV1Links: [] + message: '', + missesQualityGate: false, + projectResults: [ + { + project: '', + explorerUrl: 'url', + analyzedFiles: [], + qualityGate: { + passed: false, + message: 'message', + url: 'url', + gates: [], + annotationsApiV1Links: [] + } + } + ] }; + const reviewComments = { postable: [], unpostable: [] }; - let body = await createSummaryBody(analysis, [''], qualityGate, reviewComments); - let event = qualityGate.passed ? Events.APPROVE : Events.REQUEST_CHANGES; + + let body = createSummaryBody(analysis, analysisResults, reviewComments); + let event = analysisResults.passed ? Events.APPROVE : Events.REQUEST_CHANGES; await postReview(body, event); const calledWith = { @@ -120,17 +164,31 @@ describe('postReview', () => { errorList: ['error1'], warningList: [], statusCode: 0, - explorerUrl: undefined + explorerUrls: [] }; - const qualityGate = { - passed: true, - message: 'message', - url: 'url', - gates: [], - annotationsApiV1Links: [] + + const analysisResults: AnalysisResults = { + passed: false, + message: '', + missesQualityGate: false, + projectResults: [ + { + project: '', + explorerUrl: 'url', + analyzedFiles: [], + qualityGate: { + passed: false, + message: 'message', + url: 'url', + gates: [], + annotationsApiV1Links: [] + } + } + ] }; - let body = await createSummaryBody(analysis, [''], qualityGate, undefined); - let event = qualityGate.passed ? Events.APPROVE : Events.REQUEST_CHANGES; + + let body = createSummaryBody(analysis, analysisResults, undefined); + let event = analysisResults.passed ? Events.APPROVE : Events.REQUEST_CHANGES; await postReview(body, event); expect(spy).toBeCalledTimes(1); diff --git a/test/helper/summary.test.ts b/test/helper/summary.test.ts index 55fc75cf..fd305048 100644 --- a/test/helper/summary.test.ts +++ b/test/helper/summary.test.ts @@ -42,12 +42,9 @@ describe('createFilesSummary', () => { test('Should return summary list of a single file', () => { const response = createFilesSummary(['test.js']); - expect(response).toEqual('
          The following files have been checked:\n
          • test.js
          \n\n'); - }); - - test('Should return summary list of a single file', () => { - const response = createFilesSummary(['test.js']); - + expect(response).toEqual( + '
          The following files have been checked for this project\n
          • test.js
          \n\n' + ); expect(response).toContainTimes('
        • test.js
        • ', 1); }); @@ -268,7 +265,7 @@ describe('createUnpostableReviewCommentsSummary', () => { test('Should return summary of zero unpostable review comments on empty input', () => { const response = createUnpostableAnnotationsDetails([]); expect(response).toEqual( - '
          Quality gate failures that cannot be annotated in Files Changed:\n
          \n\n' + '
          Quality gate failures that cannot be annotated in Files Changed\n
          \n\n' ); }); diff --git a/test/main.test.ts b/test/main.test.ts index 025d3ea0..f121fa9a 100644 --- a/test/main.test.ts +++ b/test/main.test.ts @@ -16,14 +16,13 @@ import { analysisPassed, analysisPassedNoUrl, analysisPassedNoUrlWarning5057, - doubleAnalyzedFiles, + analysisResultsDoubleFilePassed, + analysisResultsPassedNoUrl, + analysisResultsSingleFileFailed, + analysisResultsSingleFilePassed, doubleChangedFiles, - doubleFileQualityGatePassed, - singleAnalyzedFiles, singleAnnotations, singleChangedFiles, - singleFileQualityGateFailed, - singleFileQualityGatePassed as singleFileQualityGatePassed, singlePreviousReviewComments } from './main_helper'; @@ -108,15 +107,14 @@ describe('SetFailed checks', () => { jest.spyOn(pulls, 'getChangedFilesOfPullRequest').mockResolvedValueOnce(singleChangedFiles); jest.spyOn(pulls, 'changedFilesToFile').mockReturnValueOnce('location/changedFiles.txt'); jest.spyOn(analyzer, 'runTicsAnalyzer').mockResolvedValueOnce(analysisPassed); - jest.spyOn(fetcher, 'getAnalyzedFiles').mockResolvedValueOnce([]); - jest.spyOn(fetcher, 'getQualityGate').mockResolvedValueOnce(undefined); + jest.spyOn(fetcher, 'getAnalysisResults').mockResolvedValueOnce(analysisResultsPassedNoUrl); jest.spyOn(review, 'postReview').mockImplementationOnce(() => Promise.resolve()); const spySetFailed = jest.spyOn(logger, 'exit'); await main.main(); - expect(spySetFailed).toHaveBeenCalledWith('Quality gate could not be retrieved'); + expect(spySetFailed).toHaveBeenCalledWith('Some quality gates could not be retrieved'); }); test('Should call setFailed if analysis passed and quality gate failed', async () => { @@ -124,8 +122,7 @@ describe('SetFailed checks', () => { jest.spyOn(pulls, 'getChangedFilesOfPullRequest').mockResolvedValueOnce(singleChangedFiles); jest.spyOn(pulls, 'changedFilesToFile').mockReturnValueOnce('location/changedFiles.txt'); jest.spyOn(analyzer, 'runTicsAnalyzer').mockResolvedValueOnce(analysisPassed); - jest.spyOn(fetcher, 'getAnalyzedFiles').mockResolvedValueOnce(singleAnalyzedFiles); - jest.spyOn(fetcher, 'getQualityGate').mockResolvedValueOnce(singleFileQualityGateFailed); + jest.spyOn(fetcher, 'getAnalysisResults').mockResolvedValueOnce(analysisResultsSingleFileFailed); jest.spyOn(review, 'postReview').mockImplementationOnce(() => Promise.resolve()); jest.spyOn(comments, 'getPostedComments').mockResolvedValue([]); @@ -141,8 +138,7 @@ describe('SetFailed checks', () => { jest.spyOn(pulls, 'getChangedFilesOfPullRequest').mockResolvedValueOnce(singleChangedFiles); jest.spyOn(pulls, 'changedFilesToFile').mockReturnValueOnce('location/changedFiles.txt'); jest.spyOn(analyzer, 'runTicsAnalyzer').mockResolvedValueOnce(analysisPassed); - jest.spyOn(fetcher, 'getAnalyzedFiles').mockResolvedValueOnce(singleAnalyzedFiles); - jest.spyOn(fetcher, 'getQualityGate').mockResolvedValueOnce(singleFileQualityGatePassed); + jest.spyOn(fetcher, 'getAnalysisResults').mockResolvedValueOnce(analysisResultsSingleFilePassed); jest.spyOn(review, 'postReview').mockImplementationOnce(() => Promise.resolve()); jest.spyOn(comments, 'getPostedComments').mockResolvedValue([]); @@ -191,8 +187,7 @@ describe('PostReview checks', () => { jest.spyOn(pulls, 'getChangedFilesOfPullRequest').mockResolvedValueOnce(singleChangedFiles); jest.spyOn(pulls, 'changedFilesToFile').mockReturnValueOnce('location/changedFiles.txt'); jest.spyOn(analyzer, 'runTicsAnalyzer').mockResolvedValueOnce(analysisPassed); - jest.spyOn(fetcher, 'getAnalyzedFiles').mockResolvedValueOnce(singleAnalyzedFiles); - jest.spyOn(fetcher, 'getQualityGate').mockResolvedValueOnce(singleFileQualityGateFailed); + jest.spyOn(fetcher, 'getAnalysisResults').mockResolvedValueOnce(analysisResultsSingleFileFailed); jest.spyOn(comments, 'getPostedComments').mockResolvedValue([]); const spyReview = jest.spyOn(review, 'postReview').mockImplementationOnce(() => Promise.resolve()); @@ -207,8 +202,7 @@ describe('PostReview checks', () => { jest.spyOn(pulls, 'getChangedFilesOfPullRequest').mockResolvedValueOnce(singleChangedFiles); jest.spyOn(pulls, 'changedFilesToFile').mockReturnValueOnce('location/changedFiles.txt'); jest.spyOn(analyzer, 'runTicsAnalyzer').mockResolvedValueOnce(analysisPassed); - jest.spyOn(fetcher, 'getAnalyzedFiles').mockResolvedValueOnce(singleAnalyzedFiles); - jest.spyOn(fetcher, 'getQualityGate').mockResolvedValueOnce(singleFileQualityGatePassed); + jest.spyOn(fetcher, 'getAnalysisResults').mockResolvedValueOnce(analysisResultsSingleFilePassed); jest.spyOn(comments, 'getPostedComments').mockImplementationOnce(() => Promise.resolve([])); const spyReview = jest.spyOn(review, 'postReview').mockImplementationOnce(() => Promise.resolve()); @@ -223,8 +217,7 @@ describe('PostReview checks', () => { jest.spyOn(pulls, 'getChangedFilesOfPullRequest').mockResolvedValueOnce(doubleChangedFiles); jest.spyOn(pulls, 'changedFilesToFile').mockReturnValueOnce('location/changedFiles.txt'); jest.spyOn(analyzer, 'runTicsAnalyzer').mockResolvedValueOnce(analysisPassed); - jest.spyOn(fetcher, 'getAnalyzedFiles').mockResolvedValueOnce(doubleAnalyzedFiles); - jest.spyOn(fetcher, 'getQualityGate').mockResolvedValueOnce(doubleFileQualityGatePassed); + jest.spyOn(fetcher, 'getAnalysisResults').mockResolvedValueOnce(analysisResultsSingleFilePassed); jest.spyOn(fetcher, 'getAnnotations').mockResolvedValueOnce([]); jest.spyOn(annotations, 'getPostedReviewComments').mockResolvedValueOnce([]); jest.spyOn(comments, 'getPostedComments').mockImplementationOnce(() => Promise.resolve([])); @@ -242,8 +235,7 @@ describe('PostReview checks', () => { jest.spyOn(pulls, 'getChangedFilesOfPullRequest').mockResolvedValueOnce(doubleChangedFiles); jest.spyOn(pulls, 'changedFilesToFile').mockReturnValueOnce('location/changedFiles.txt'); jest.spyOn(analyzer, 'runTicsAnalyzer').mockResolvedValueOnce(analysisPassed); - jest.spyOn(fetcher, 'getAnalyzedFiles').mockResolvedValueOnce(doubleAnalyzedFiles); - jest.spyOn(fetcher, 'getQualityGate').mockResolvedValueOnce(doubleFileQualityGatePassed); + jest.spyOn(fetcher, 'getAnalysisResults').mockResolvedValueOnce(analysisResultsDoubleFilePassed); jest.spyOn(fetcher, 'getAnnotations').mockResolvedValueOnce(singleAnnotations); jest.spyOn(annotations, 'getPostedReviewComments').mockResolvedValueOnce([]); jest.spyOn(comments, 'getPostedComments').mockImplementationOnce(() => Promise.resolve([])); @@ -263,8 +255,7 @@ describe('DeletePreviousReviewComments check', () => { jest.spyOn(pulls, 'getChangedFilesOfPullRequest').mockResolvedValueOnce(doubleChangedFiles); jest.spyOn(pulls, 'changedFilesToFile').mockReturnValueOnce('location/changedFiles.txt'); jest.spyOn(analyzer, 'runTicsAnalyzer').mockResolvedValueOnce(analysisPassed); - jest.spyOn(fetcher, 'getAnalyzedFiles').mockResolvedValueOnce(doubleAnalyzedFiles); - jest.spyOn(fetcher, 'getQualityGate').mockResolvedValueOnce(doubleFileQualityGatePassed); + jest.spyOn(fetcher, 'getAnalysisResults').mockResolvedValueOnce(analysisResultsDoubleFilePassed); jest.spyOn(fetcher, 'getAnnotations').mockResolvedValueOnce(singleAnnotations); jest.spyOn(annotations, 'getPostedReviewComments').mockImplementationOnce((): any => singlePreviousReviewComments); jest.spyOn(comments, 'getPostedComments').mockImplementationOnce(() => Promise.resolve([])); diff --git a/test/main_helper.ts b/test/main_helper.ts index a00fde78..24a06ea4 100644 --- a/test/main_helper.ts +++ b/test/main_helper.ts @@ -1,4 +1,4 @@ -import { ExtendedAnnotation, QualityGate } from '../src/helper/interfaces'; +import { AnalysisResults, ExtendedAnnotation, QualityGate } from '../src/helper/interfaces'; interface changedFile { sha: string; @@ -14,7 +14,6 @@ interface changedFile { previous_filename?: string | undefined; } -export const singleAnalyzedFiles: string[] = ['test.js']; export const singleChangedFiles: changedFile[] = [ { sha: 'test', @@ -31,7 +30,6 @@ export const singleChangedFiles: changedFile[] = [ } ]; -export const doubleAnalyzedFiles: string[] = ['test.js', 'jest.js']; export const doubleChangedFiles: changedFile[] = [ { sha: 'test', @@ -64,7 +62,7 @@ export const doubleChangedFiles: changedFile[] = [ export const analysisFailedNoUrl = { completed: false, statusCode: 1, - explorerUrl: undefined, + explorerUrls: [], errorList: ['Error'], warningList: [] }; @@ -72,7 +70,7 @@ export const analysisFailedNoUrl = { export const analysisPassedNoUrl = { completed: true, statusCode: 0, - explorerUrl: undefined, + explorerUrls: [], errorList: ['Error'], warningList: [] }; @@ -80,7 +78,7 @@ export const analysisPassedNoUrl = { export const analysisPassedNoUrlWarning5057 = { completed: true, statusCode: 0, - explorerUrl: undefined, + explorerUrls: [], errorList: ['Error'], warningList: ['[WARNING 5057] No url ...'] }; @@ -88,7 +86,7 @@ export const analysisPassedNoUrlWarning5057 = { export const analysisPassed = { completed: true, statusCode: 0, - explorerUrl: 'explorerUrl', + explorerUrls: ['explorerUrl'], errorList: ['Error'], warningList: [] }; @@ -96,12 +94,12 @@ export const analysisPassed = { export const analysisPassedNoUrlWarning = { completed: true, statusCode: 0, - explorerUrl: undefined, + explorerUrls: [], errorList: ['Error'], warningList: ['[WARNING 5057] No files have been analyzed.'] }; -export const singleFileQualityGateFailed: QualityGate = { +const singleFileQualityGateFailed: QualityGate = { passed: false, message: 'Project failed 2 out of 2 quality gates', url: 'api', @@ -156,7 +154,7 @@ export const singleFileQualityGateFailed: QualityGate = { ] }; -export const singleFileQualityGatePassed: QualityGate = { +const singleFileQualityGatePassed: QualityGate = { passed: true, message: 'Project passed 2 out of 2 quality gates', url: 'api', @@ -211,7 +209,7 @@ export const singleFileQualityGatePassed: QualityGate = { ] }; -export const doubleFileQualityGatePassed: QualityGate = { +const doubleFileQualityGatePassed: QualityGate = { passed: true, message: 'Project passed 2 out of 2 quality gates', url: 'api', @@ -309,3 +307,52 @@ export const singleExpectedPostable = { ], unpostable: [] }; + +export const analysisResultsPassedNoUrl: AnalysisResults = { + passed: false, + message: '', + missesQualityGate: true, + projectResults: [] +}; + +export const analysisResultsSingleFileFailed: AnalysisResults = { + passed: false, + message: 'Project failed 2 out of 2 quality gates', + missesQualityGate: false, + projectResults: [ + { + analyzedFiles: ['test.js'], + explorerUrl: 'url', + project: 'project', + qualityGate: singleFileQualityGateFailed + } + ] +}; + +export const analysisResultsSingleFilePassed: AnalysisResults = { + passed: true, + message: 'Project failed 2 out of 2 quality gates', + missesQualityGate: false, + projectResults: [ + { + analyzedFiles: ['test.js'], + explorerUrl: 'url', + project: 'project', + qualityGate: singleFileQualityGatePassed + } + ] +}; + +export const analysisResultsDoubleFilePassed: AnalysisResults = { + passed: true, + message: 'Project failed 2 out of 2 quality gates', + missesQualityGate: false, + projectResults: [ + { + analyzedFiles: ['test.js', 'jest.js'], + explorerUrl: 'url', + project: 'project', + qualityGate: doubleFileQualityGatePassed + } + ] +}; diff --git a/test/tics/analyzer.test.ts b/test/tics/analyzer.test.ts index 2437fdf7..4a9298e3 100644 --- a/test/tics/analyzer.test.ts +++ b/test/tics/analyzer.test.ts @@ -268,7 +268,7 @@ describe('test callback functions', () => { (exec.exec as any).mockResolvedValueOnce(0); const response = await runTicsAnalyzer('/path/to'); - expect(response.explorerUrl).toEqual('/Explorer.html#axes=ClientData'); + expect(response.explorerUrls[0]).toEqual('/Explorer.html#axes=ClientData'); }); }); diff --git a/test/tics/api_helper.test.ts b/test/tics/api_helper.test.ts index db083f94..5a91ab33 100644 --- a/test/tics/api_helper.test.ts +++ b/test/tics/api_helper.test.ts @@ -124,7 +124,8 @@ describe('cliSummary', () => { completed: false, statusCode: -1, errorList: ['error', 'error', 'warning'], - warningList: ['warning', 'warning'] + warningList: ['warning', 'warning'], + explorerUrls: [] }; cliSummary(analysis); @@ -142,7 +143,8 @@ describe('cliSummary', () => { completed: false, statusCode: -1, errorList: ['error', 'error', 'warning'], - warningList: ['warning', 'warning'] + warningList: ['warning', 'warning'], + explorerUrls: [] }; cliSummary(analysis); diff --git a/test/tics/fetcher.test.ts b/test/tics/fetcher.test.ts index 437ee1d7..be2f212c 100644 --- a/test/tics/fetcher.test.ts +++ b/test/tics/fetcher.test.ts @@ -1,4 +1,5 @@ import { ticsConfig } from '../../src/configuration'; +import { AnalysisResults, ProjectResult, QualityGate } from '../../src/helper/interfaces'; import { logger } from '../../src/helper/logger'; import * as api_helper from '../../src/tics/api_helper'; import { getAnalyzedFiles, getAnnotations, getQualityGate, getViewerVersion } from '../../src/tics/fetcher'; @@ -78,7 +79,27 @@ describe('getAnnotations', () => { jest.spyOn(api_helper, 'httpRequest').mockImplementationOnce((): Promise => Promise.resolve({ data: [{ annotation: 'anno_1' }] })); jest.spyOn(api_helper, 'httpRequest').mockImplementationOnce((): Promise => Promise.resolve({ data: [{ annotation: 'anno_2' }] })); - const response = await getAnnotations([{ url: 'url' }, { url: 'url' }]); + const analysisResults: AnalysisResults = { + passed: false, + message: '', + missesQualityGate: false, + projectResults: [ + { + project: '', + explorerUrl: 'url', + analyzedFiles: [], + qualityGate: { + passed: false, + message: '', + url: '', + gates: [], + annotationsApiV1Links: [{ url: 'url' }, { url: 'url' }] + } + } + ] + }; + + const response = await getAnnotations(analysisResults); console.log(response); expect(response).toEqual([ @@ -92,7 +113,27 @@ describe('getAnnotations', () => { const spy = jest.spyOn(logger, 'exit'); - await getAnnotations([{ url: 'url' }]); + const analysisResults: AnalysisResults = { + passed: false, + message: '', + missesQualityGate: false, + projectResults: [ + { + project: '', + explorerUrl: 'url', + analyzedFiles: [], + qualityGate: { + passed: false, + message: '', + url: '', + gates: [], + annotationsApiV1Links: [{ url: 'url' }] + } + } + ] + }; + + await getAnnotations(analysisResults); expect(spy).toHaveBeenCalledTimes(1); }); From bce9370ecbdfff7bb597197553acb2a24876c5af Mon Sep 17 00:00:00 2001 From: janssen <118828444+janssen-tiobe@users.noreply.github.com> Date: Fri, 1 Sep 2023 12:28:16 +0200 Subject: [PATCH 6/8] #32831: Annotations are now reported per project --- .githooks/pre-commit/run | 2 + dist/index.js | 46 ++++++++++---------- src/github/annotations.ts | 15 +++++-- src/github/commits.ts | 2 +- src/helper/interfaces.d.ts | 7 +-- src/helper/summary.ts | 12 +++--- src/main.ts | 17 +++----- src/tics/fetcher.ts | 21 +++++---- test/.setup/mock.ts | 3 ++ test/github/commits.test.ts | 85 +++++++++++++++++++++++++++++++++++++ test/github/review.test.ts | 49 ++++----------------- test/tics/fetcher.test.ts | 45 +------------------- 12 files changed, 165 insertions(+), 139 deletions(-) create mode 100644 .githooks/pre-commit/run create mode 100644 test/github/commits.test.ts diff --git a/.githooks/pre-commit/run b/.githooks/pre-commit/run new file mode 100644 index 00000000..5be1c2bb --- /dev/null +++ b/.githooks/pre-commit/run @@ -0,0 +1,2 @@ +#!/bin/sh +npm run test \ No newline at end of file diff --git a/dist/index.js b/dist/index.js index f3c6da28..32a838cd 100644 --- a/dist/index.js +++ b/dist/index.js @@ -141,9 +141,15 @@ exports.getPostedReviewComments = getPostedReviewComments; * Deletes the review comments of previous runs. * @param postedReviewComments Previously posted review comments. */ -function postAnnotations(reviewComments) { +function postAnnotations(analysisResult) { logger_1.logger.header('Posting annotations.'); - reviewComments.postable.forEach(reviewComment => { + let postableReviewComments = []; + analysisResult.projectResults.forEach(projectResult => { + if (projectResult.reviewComments) { + postableReviewComments.push(...projectResult.reviewComments.postable); + } + }); + postableReviewComments.forEach(reviewComment => { logger_1.logger.warning(reviewComment.body, { file: reviewComment.path, startLine: reviewComment.line, @@ -393,6 +399,7 @@ async function getChangedFilesOfCommit() { if (response.data.files) { return response.data.files .filter(item => { + // If a file is moved or renamed the status is 'renamed'. if (item.status === 'renamed') { // If a files has been moved without changes or if moved files are excluded, exclude them. if (configuration_1.ticsConfig.excludeMovedFiles || item.changes === 0) { @@ -402,7 +409,6 @@ async function getChangedFilesOfCommit() { return true; }) .map(item => { - // If a file is moved or renamed the status is 'renamed'. item.filename = (0, canonical_path_1.normalize)(item.filename); logger_1.logger.debug(item.filename); return item; @@ -787,7 +793,7 @@ const configuration_1 = __nccwpck_require__(5527); const enums_1 = __nccwpck_require__(1655); const underscore_1 = __nccwpck_require__(5067); const logger_1 = __nccwpck_require__(6440); -function createSummaryBody(analysis, analysisResults, reviewComments) { +function createSummaryBody(analysisResults) { logger_1.logger.header('Creating summary.'); core_1.summary.addHeading('TICS Quality Gate'); core_1.summary.addHeading(`${(0, markdown_1.generateStatusMarkdown)(analysisResults.passed ? enums_1.Status.PASSED : enums_1.Status.FAILED, true)}`, 3); @@ -809,8 +815,8 @@ function createSummaryBody(analysis, analysisResults, reviewComments) { }); core_1.summary.addEOL(); core_1.summary.addLink('See the results in the TICS Viewer', projectResult.explorerUrl); - if (reviewComments && reviewComments.unpostable.length > 0) { - core_1.summary.addRaw(createUnpostableAnnotationsDetails(reviewComments.unpostable)); + if (projectResult.reviewComments) { + core_1.summary.addRaw(createUnpostableAnnotationsDetails(projectResult.reviewComments.unpostable)); } core_1.summary.addRaw(createFilesSummary(projectResult.analyzedFiles)); } @@ -1341,8 +1347,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getViewerVersion = exports.getAnnotations = exports.getQualityGate = exports.getAnalyzedFiles = exports.getAnalysisResults = void 0; const configuration_1 = __nccwpck_require__(5527); const logger_1 = __nccwpck_require__(6440); +const summary_1 = __nccwpck_require__(1502); const api_helper_1 = __nccwpck_require__(3823); -async function getAnalysisResults(explorerUrls) { +async function getAnalysisResults(explorerUrls, changedFiles) { let analysisResults = { passed: true, message: '', @@ -1364,6 +1371,12 @@ async function getAnalysisResults(explorerUrls) { analysisResults.passed = false; analysisResults.message += qualityGate.message + ' '; } + if (qualityGate && configuration_1.ticsConfig.postAnnotations) { + const annotations = await getAnnotations(qualityGate.annotationsApiV1Links); + if (annotations && annotations.length > 0) { + analysisResult.reviewComments = (0, summary_1.createReviewComments)(annotations, changedFiles); + } + } analysisResult.qualityGate = qualityGate; analysisResults.projectResults.push(analysisResult); }); @@ -1458,15 +1471,9 @@ function getQualityGateUrl(url) { * @param apiLinks annotationsApiLinks url. * @returns TICS annotations. */ -async function getAnnotations(analysisResults) { +async function getAnnotations(apiLinks) { let annotations = []; logger_1.logger.header('Retrieving annotations.'); - let apiLinks = []; - analysisResults.projectResults.forEach((analysis) => { - if (analysis.qualityGate) { - apiLinks.push(...analysis.qualityGate.annotationsApiV1Links); - } - }); try { await Promise.all(apiLinks.map(async (link, index) => { const annotationsUrl = new URL(`${configuration_1.baseUrl}/${link.url}`); @@ -58149,7 +58156,7 @@ async function run() { (0, api_helper_1.cliSummary)(analysis); return; } - const analysisResults = await (0, fetcher_1.getAnalysisResults)(analysis.explorerUrls); + const analysisResults = await (0, fetcher_1.getAnalysisResults)(analysis.explorerUrls, changedFiles); if (analysisResults.missesQualityGate) return logger_1.logger.exit('Some quality gates could not be retrieved'); // If not run on a pull request no review comments have to be deleted @@ -58159,15 +58166,10 @@ async function run() { (0, annotations_1.deletePreviousReviewComments)(previousReviewComments); } } - let reviewComments; if (configuration_1.ticsConfig.postAnnotations) { - const annotations = await (0, fetcher_1.getAnnotations)(analysisResults); - if (annotations && annotations.length > 0) { - reviewComments = (0, summary_1.createReviewComments)(annotations, changedFiles); - (0, annotations_1.postAnnotations)(reviewComments); - } + (0, annotations_1.postAnnotations)(analysisResults); } - let reviewBody = (0, summary_1.createSummaryBody)(analysis, analysisResults, reviewComments); + let reviewBody = (0, summary_1.createSummaryBody)(analysisResults); // If not run on a pull request no comments have to be deleted // and there is no conversation to post to. if (configuration_1.githubConfig.eventName === 'pull_request') { diff --git a/src/github/annotations.ts b/src/github/annotations.ts index 9048fe92..f2501c1a 100644 --- a/src/github/annotations.ts +++ b/src/github/annotations.ts @@ -1,7 +1,7 @@ import { logger } from '../helper/logger'; import { githubConfig, octokit } from '../configuration'; import { ReviewComment } from './interfaces'; -import { ReviewComments } from '../helper/interfaces'; +import { AnalysisResults, TicsReviewComment } from '../helper/interfaces'; /** * Gets a list of all reviews posted on the pull request. @@ -29,9 +29,18 @@ export async function getPostedReviewComments(): Promise { * Deletes the review comments of previous runs. * @param postedReviewComments Previously posted review comments. */ -export function postAnnotations(reviewComments: ReviewComments): void { +export function postAnnotations(analysisResult: AnalysisResults): void { logger.header('Posting annotations.'); - reviewComments.postable.forEach(reviewComment => { + + let postableReviewComments: TicsReviewComment[] = []; + + analysisResult.projectResults.forEach(projectResult => { + if (projectResult.reviewComments) { + postableReviewComments.push(...projectResult.reviewComments.postable); + } + }); + + postableReviewComments.forEach(reviewComment => { logger.warning(reviewComment.body, { file: reviewComment.path, startLine: reviewComment.line, diff --git a/src/github/commits.ts b/src/github/commits.ts index 2e77571d..640f05a7 100644 --- a/src/github/commits.ts +++ b/src/github/commits.ts @@ -20,6 +20,7 @@ export async function getChangedFilesOfCommit(): Promise { if (response.data.files) { return response.data.files .filter(item => { + // If a file is moved or renamed the status is 'renamed'. if (item.status === 'renamed') { // If a files has been moved without changes or if moved files are excluded, exclude them. if (ticsConfig.excludeMovedFiles || item.changes === 0) { @@ -29,7 +30,6 @@ export async function getChangedFilesOfCommit(): Promise { return true; }) .map(item => { - // If a file is moved or renamed the status is 'renamed'. item.filename = normalize(item.filename); logger.debug(item.filename); return item; diff --git a/src/helper/interfaces.d.ts b/src/helper/interfaces.d.ts index 61c08c8e..66c25738 100644 --- a/src/helper/interfaces.d.ts +++ b/src/helper/interfaces.d.ts @@ -18,6 +18,7 @@ export interface ProjectResult { explorerUrl: string; qualityGate?: QualityGate; analyzedFiles: string[]; + reviewComments?: TicsReviewComments; } export interface QualityGate { @@ -74,15 +75,15 @@ export interface AnnotationApiLink { url: string; } -export interface ReviewComment { +export interface TicsReviewComment { title: string; body: string; path?: string; line: number; } -export interface ReviewComments { - postable: ReviewComment[]; +export interface TicsReviewComments { + postable: TicsReviewComment[]; unpostable: ExtendedAnnotation[]; } diff --git a/src/helper/summary.ts b/src/helper/summary.ts index f56583c5..d1e59c90 100644 --- a/src/helper/summary.ts +++ b/src/helper/summary.ts @@ -1,14 +1,14 @@ import { summary } from '@actions/core'; import { SummaryTableRow } from '@actions/core/lib/summary'; import { generateExpandableAreaMarkdown, generateStatusMarkdown } from './markdown'; -import { Analysis, AnalysisResults, Annotation, Condition, ExtendedAnnotation, Gate, QualityGate, ReviewComment, ReviewComments } from './interfaces'; +import { AnalysisResults, Annotation, Condition, ExtendedAnnotation, Gate, TicsReviewComment, TicsReviewComments } from './interfaces'; import { ChangedFile } from '../github/interfaces'; import { githubConfig, viewerUrl } from '../configuration'; import { Status } from './enums'; import { range } from 'underscore'; import { logger } from './logger'; -export function createSummaryBody(analysis: Analysis, analysisResults: AnalysisResults, reviewComments?: ReviewComments): string { +export function createSummaryBody(analysisResults: AnalysisResults): string { logger.header('Creating summary.'); summary.addHeading('TICS Quality Gate'); summary.addHeading(`${generateStatusMarkdown(analysisResults.passed ? Status.PASSED : Status.FAILED, true)}`, 3); @@ -33,8 +33,8 @@ export function createSummaryBody(analysis: Analysis, analysisResults: AnalysisR summary.addLink('See the results in the TICS Viewer', projectResult.explorerUrl); - if (reviewComments && reviewComments.unpostable.length > 0) { - summary.addRaw(createUnpostableAnnotationsDetails(reviewComments.unpostable)); + if (projectResult.reviewComments) { + summary.addRaw(createUnpostableAnnotationsDetails(projectResult.reviewComments.unpostable)); } summary.addRaw(createFilesSummary(projectResult.analyzedFiles)); @@ -128,14 +128,14 @@ function createConditionTable(condition: Condition): SummaryTableRow[] { * @param changedFiles List of files changed in the pull request. * @returns List of the review comments. */ -export function createReviewComments(annotations: ExtendedAnnotation[], changedFiles: ChangedFile[]): ReviewComments { +export function createReviewComments(annotations: ExtendedAnnotation[], changedFiles: ChangedFile[]): TicsReviewComments { logger.info('Creating review comments from annotations.'); const sortedAnnotations = sortAnnotations(annotations); const groupedAnnotations = groupAnnotations(sortedAnnotations, changedFiles); let unpostable: ExtendedAnnotation[] = []; - let postable: ReviewComment[] = []; + let postable: TicsReviewComment[] = []; groupedAnnotations.forEach(annotation => { const displayCount = annotation.count === 1 ? '' : `(${annotation.count}x) `; diff --git a/src/main.ts b/src/main.ts index e78a8791..f508621b 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,14 +5,14 @@ import { changedFilesToFile, getChangedFilesOfPullRequest } from './github/pulls import { logger } from './helper/logger'; import { runTicsAnalyzer } from './tics/analyzer'; import { cliSummary } from './tics/api_helper'; -import { getAnalysisResults, getAnnotations, getViewerVersion } from './tics/fetcher'; +import { getAnalysisResults, getViewerVersion } from './tics/fetcher'; import { postNothingAnalyzedReview, postReview } from './github/review'; -import { createSummaryBody, createReviewComments } from './helper/summary'; +import { createSummaryBody } from './helper/summary'; import { getPostedReviewComments, postAnnotations, deletePreviousReviewComments } from './github/annotations'; import { Events } from './helper/enums'; import { satisfies } from 'compare-versions'; import { exportVariable, summary } from '@actions/core'; -import { Analysis, ReviewComments } from './helper/interfaces'; +import { Analysis } from './helper/interfaces'; import { uploadArtifact } from './github/artifacts'; import { getChangedFilesOfCommit } from './github/commits'; @@ -83,7 +83,7 @@ async function run() { return; } - const analysisResults = await getAnalysisResults(analysis.explorerUrls); + const analysisResults = await getAnalysisResults(analysis.explorerUrls, changedFiles); if (analysisResults.missesQualityGate) return logger.exit('Some quality gates could not be retrieved'); @@ -95,16 +95,11 @@ async function run() { } } - let reviewComments: ReviewComments | undefined; if (ticsConfig.postAnnotations) { - const annotations = await getAnnotations(analysisResults); - if (annotations && annotations.length > 0) { - reviewComments = createReviewComments(annotations, changedFiles); - postAnnotations(reviewComments); - } + postAnnotations(analysisResults); } - let reviewBody = createSummaryBody(analysis, analysisResults, reviewComments); + let reviewBody = createSummaryBody(analysisResults); // If not run on a pull request no comments have to be deleted // and there is no conversation to post to. diff --git a/src/tics/fetcher.ts b/src/tics/fetcher.ts index d76e3a4e..75e8377e 100644 --- a/src/tics/fetcher.ts +++ b/src/tics/fetcher.ts @@ -1,4 +1,5 @@ import { baseUrl, ticsConfig } from '../configuration'; +import { ChangedFile } from '../github/interfaces'; import { ProjectResult, AnalysisResults, @@ -12,9 +13,10 @@ import { VersionResponse } from '../helper/interfaces'; import { logger } from '../helper/logger'; +import { createReviewComments } from '../helper/summary'; import { getItemFromUrl, getProjectName, httpRequest } from './api_helper'; -export async function getAnalysisResults(explorerUrls: string[]): Promise { +export async function getAnalysisResults(explorerUrls: string[], changedFiles: ChangedFile[]): Promise { let analysisResults: AnalysisResults = { passed: true, message: '', @@ -41,6 +43,13 @@ export async function getAnalysisResults(explorerUrls: string[]): Promise 0) { + analysisResult.reviewComments = createReviewComments(annotations, changedFiles); + } + } + analysisResult.qualityGate = qualityGate; analysisResults.projectResults.push(analysisResult); @@ -146,17 +155,10 @@ function getQualityGateUrl(url: string) { * @param apiLinks annotationsApiLinks url. * @returns TICS annotations. */ -export async function getAnnotations(analysisResults: AnalysisResults): Promise { +export async function getAnnotations(apiLinks: AnnotationApiLink[]): Promise { let annotations: ExtendedAnnotation[] = []; logger.header('Retrieving annotations.'); - let apiLinks: AnnotationApiLink[] = []; - analysisResults.projectResults.forEach((analysis: ProjectResult) => { - if (analysis.qualityGate) { - apiLinks.push(...analysis.qualityGate.annotationsApiV1Links); - } - }); - try { await Promise.all( apiLinks.map(async (link, index) => { @@ -183,6 +185,7 @@ export async function getAnnotations(analysisResults: AnalysisResults): Promise< if (error instanceof Error) message = error.message; logger.exit(`An error occured when trying to retrieve annotations: ${message}`); } + return annotations; } diff --git a/test/.setup/mock.ts b/test/.setup/mock.ts index 508a0109..831c24bc 100644 --- a/test/.setup/mock.ts +++ b/test/.setup/mock.ts @@ -36,6 +36,9 @@ jest.mock('../../src/configuration', () => { listComments: jest.fn(), createComment: jest.fn(), deleteComment: jest.fn() + }, + repos: { + getCommit: jest.fn() } } }, diff --git a/test/github/commits.test.ts b/test/github/commits.test.ts new file mode 100644 index 00000000..bf7d2881 --- /dev/null +++ b/test/github/commits.test.ts @@ -0,0 +1,85 @@ +import { getChangedFilesOfCommit } from '../../src/github/commits'; +import { octokit, ticsConfig } from '../../src/configuration'; +import { changedFile } from './objects/pulls'; +import { logger } from '../../src/helper/logger'; + +describe('getChangedFilesOfCommit', () => { + test('Should return single file on getChangedFilesOfCommit', async () => { + const changedFiles = [changedFile]; + + (octokit.paginate as any).mockResolvedValueOnce(changedFiles); + + const response = await getChangedFilesOfCommit(); + expect(response).toEqual(changedFiles); + }); + + test('Should include changed moved file', async () => { + const spy = jest.spyOn(logger, 'debug'); + await getChangedFilesOfCommit(); + + (octokit.paginate as any).mock.calls[0][2]({ + data: { files: [{ filename: 'test.js', status: 'renamed', changes: 1 }, { filename: 'test.js' }] } + }); + + expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledWith('test.js'); + }); + + test('Should exclude unchanged moved file', async () => { + const spy = jest.spyOn(logger, 'debug'); + await getChangedFilesOfCommit(); + + (octokit.paginate as any).mock.calls[0][2]({ + data: { files: [{ filename: 'test.js', status: 'renamed', changes: 0 }, { filename: 'test.js' }] } + }); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith('test.js'); + }); + + test('Should include changed moved file on excludeMovedFiles', async () => { + ticsConfig.excludeMovedFiles = true; + + const spy = jest.spyOn(logger, 'debug'); + await getChangedFilesOfCommit(); + + (octokit.paginate as any).mock.calls[0][2]({ + data: { files: [{ filename: 'test.js', status: 'renamed', changes: 1 }, { filename: 'test.js' }] } + }); + expect(spy).toHaveBeenCalledTimes(1); + expect(spy).toHaveBeenCalledWith('test.js'); + }); + + test('Should call debug on callback of paginate', async () => { + const spy = jest.spyOn(logger, 'debug'); + await getChangedFilesOfCommit(); + + (octokit.paginate as any).mock.calls[0][2]({ data: { files: [{ filename: 'test.js' }, { filename: 'test.js' }] } }); + expect(spy).toHaveBeenCalledTimes(2); + expect(spy).toHaveBeenCalledWith('test.js'); + }); + + test('Should be called with specific parameters on getChangedFilesOfCommit', async () => { + (octokit.paginate as any).mockReturnValueOnce(); + const spy = jest.spyOn(octokit, 'paginate'); + + await getChangedFilesOfCommit(); + expect(spy).toHaveBeenCalledWith(octokit.rest.repos.getCommit, { repo: 'test', owner: 'tester', ref: 'asdfghjk' }, expect.any(Function)); + }); + + test('Should return three files on getChangedFilesOfCommit', async () => { + (octokit.paginate as any).mockReturnValueOnce([{}, {}, {}]); + + const response = await getChangedFilesOfCommit(); + expect((response as any[]).length).toEqual(3); + }); + + test('Should call exit on thrown error on paginate', async () => { + (octokit.paginate as any).mockImplementationOnce(() => { + throw new Error(); + }); + const spy = jest.spyOn(logger, 'exit'); + await getChangedFilesOfCommit(); + + expect(spy).toHaveBeenCalledTimes(1); + }); +}); diff --git a/test/github/review.test.ts b/test/github/review.test.ts index 55a684e4..4816a088 100644 --- a/test/github/review.test.ts +++ b/test/github/review.test.ts @@ -17,14 +17,6 @@ describe('postReview', () => { const spy = jest.spyOn(octokit.rest.pulls, 'createReview'); - const analysis = { - completed: true, - errorList: ['error1'], - warningList: [], - statusCode: 0, - explorerUrls: ['url'] - }; - const analysisResults: AnalysisResults = { passed: true, message: '', @@ -45,7 +37,7 @@ describe('postReview', () => { ] }; - let body = createSummaryBody(analysis, analysisResults, undefined); + let body = createSummaryBody(analysisResults); let event = analysisResults.passed ? Events.APPROVE : Events.REQUEST_CHANGES; await postReview(body, event); expect(spy).toBeCalledTimes(1); @@ -56,14 +48,6 @@ describe('postReview', () => { const spy = jest.spyOn(octokit.rest.pulls, 'createReview'); - const analysis = { - completed: true, - errorList: ['error1'], - warningList: [], - statusCode: 0, - explorerUrls: ['url'] - }; - const analysisResults: AnalysisResults = { passed: true, message: '', @@ -84,7 +68,7 @@ describe('postReview', () => { ] }; - let body = createSummaryBody(analysis, analysisResults, undefined); + let body = createSummaryBody(analysisResults); let event = analysisResults.passed ? Events.APPROVE : Events.REQUEST_CHANGES; await postReview(body, event); @@ -104,14 +88,6 @@ describe('postReview', () => { const spy = jest.spyOn(octokit.rest.pulls, 'createReview'); - const analysis = { - completed: true, - errorList: ['error1'], - warningList: [], - statusCode: 0, - explorerUrls: ['url'] - }; - const analysisResults: AnalysisResults = { passed: false, message: '', @@ -127,17 +103,16 @@ describe('postReview', () => { url: 'url', gates: [], annotationsApiV1Links: [] + }, + reviewComments: { + postable: [], + unpostable: [] } } ] }; - const reviewComments = { - postable: [], - unpostable: [] - }; - - let body = createSummaryBody(analysis, analysisResults, reviewComments); + let body = createSummaryBody(analysisResults); let event = analysisResults.passed ? Events.APPROVE : Events.REQUEST_CHANGES; await postReview(body, event); @@ -159,14 +134,6 @@ describe('postReview', () => { }); const spy = jest.spyOn(logger, 'error'); - const analysis = { - completed: false, - errorList: ['error1'], - warningList: [], - statusCode: 0, - explorerUrls: [] - }; - const analysisResults: AnalysisResults = { passed: false, message: '', @@ -187,7 +154,7 @@ describe('postReview', () => { ] }; - let body = createSummaryBody(analysis, analysisResults, undefined); + let body = createSummaryBody(analysisResults); let event = analysisResults.passed ? Events.APPROVE : Events.REQUEST_CHANGES; await postReview(body, event); diff --git a/test/tics/fetcher.test.ts b/test/tics/fetcher.test.ts index be2f212c..437ee1d7 100644 --- a/test/tics/fetcher.test.ts +++ b/test/tics/fetcher.test.ts @@ -1,5 +1,4 @@ import { ticsConfig } from '../../src/configuration'; -import { AnalysisResults, ProjectResult, QualityGate } from '../../src/helper/interfaces'; import { logger } from '../../src/helper/logger'; import * as api_helper from '../../src/tics/api_helper'; import { getAnalyzedFiles, getAnnotations, getQualityGate, getViewerVersion } from '../../src/tics/fetcher'; @@ -79,27 +78,7 @@ describe('getAnnotations', () => { jest.spyOn(api_helper, 'httpRequest').mockImplementationOnce((): Promise => Promise.resolve({ data: [{ annotation: 'anno_1' }] })); jest.spyOn(api_helper, 'httpRequest').mockImplementationOnce((): Promise => Promise.resolve({ data: [{ annotation: 'anno_2' }] })); - const analysisResults: AnalysisResults = { - passed: false, - message: '', - missesQualityGate: false, - projectResults: [ - { - project: '', - explorerUrl: 'url', - analyzedFiles: [], - qualityGate: { - passed: false, - message: '', - url: '', - gates: [], - annotationsApiV1Links: [{ url: 'url' }, { url: 'url' }] - } - } - ] - }; - - const response = await getAnnotations(analysisResults); + const response = await getAnnotations([{ url: 'url' }, { url: 'url' }]); console.log(response); expect(response).toEqual([ @@ -113,27 +92,7 @@ describe('getAnnotations', () => { const spy = jest.spyOn(logger, 'exit'); - const analysisResults: AnalysisResults = { - passed: false, - message: '', - missesQualityGate: false, - projectResults: [ - { - project: '', - explorerUrl: 'url', - analyzedFiles: [], - qualityGate: { - passed: false, - message: '', - url: '', - gates: [], - annotationsApiV1Links: [{ url: 'url' }] - } - } - ] - }; - - await getAnnotations(analysisResults); + await getAnnotations([{ url: 'url' }]); expect(spy).toHaveBeenCalledTimes(1); }); From 22056437c69b7d60bd1a3f8691f8d55aabad2ff9 Mon Sep 17 00:00:00 2001 From: janssen <118828444+janssen-tiobe@users.noreply.github.com> Date: Mon, 4 Sep 2023 17:13:33 +0200 Subject: [PATCH 7/8] #32831: Added tests for getAnalysisResults + fixed async issue in function --- dist/index.js | 37 +++++++++++++--- src/tics/fetcher.ts | 22 +++++++--- test/tics/fetcher.test.ts | 91 ++++++++++++++++++++++++++++++++++----- 3 files changed, 129 insertions(+), 21 deletions(-) diff --git a/dist/index.js b/dist/index.js index 32a838cd..603239f8 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1349,6 +1349,12 @@ const configuration_1 = __nccwpck_require__(5527); const logger_1 = __nccwpck_require__(6440); const summary_1 = __nccwpck_require__(1502); const api_helper_1 = __nccwpck_require__(3823); +/** + * Retrieve all analysis results from the viewer in one convenient object. + * @param explorerUrls All the explorer urls gotten from the TICS analysis. + * @param changedFiles The changed files gotten from GitHub. + * @returns Object containing the results of the analysis. + */ async function getAnalysisResults(explorerUrls, changedFiles) { let analysisResults = { passed: true, @@ -1356,13 +1362,18 @@ async function getAnalysisResults(explorerUrls, changedFiles) { missesQualityGate: false, projectResults: [] }; - explorerUrls.forEach(async (url) => { + if (explorerUrls.length === 0) { + analysisResults.passed = false; + analysisResults.message = 'No Explorer url found'; + analysisResults.missesQualityGate = true; + } + for (const url of explorerUrls) { let analysisResult = { project: (0, api_helper_1.getProjectName)(url), explorerUrl: url, - analyzedFiles: await getAnalyzedFiles(url) + analyzedFiles: await exports.getAnalyzedFiles(url) // export is used for testing }; - const qualityGate = await getQualityGate(url); + const qualityGate = await exports.getQualityGate(url); // export is used for testing if (!qualityGate) { analysisResults.passed = false; analysisResults.missesQualityGate = true; @@ -1372,14 +1383,14 @@ async function getAnalysisResults(explorerUrls, changedFiles) { analysisResults.message += qualityGate.message + ' '; } if (qualityGate && configuration_1.ticsConfig.postAnnotations) { - const annotations = await getAnnotations(qualityGate.annotationsApiV1Links); + const annotations = await exports.getAnnotations(qualityGate.annotationsApiV1Links); // export is used for testing if (annotations && annotations.length > 0) { analysisResult.reviewComments = (0, summary_1.createReviewComments)(annotations, changedFiles); } } analysisResult.qualityGate = qualityGate; analysisResults.projectResults.push(analysisResult); - }); + } return analysisResults; } exports.getAnalysisResults = getAnalysisResults; @@ -20004,11 +20015,27 @@ module.exports.canonical = canonical; * ``` */ const validate = (version) => typeof version === 'string' && /^[v\d]/.test(version) && semver.test(version); + /** + * Validate [semver](https://semver.org/) version strings strictly. Will not accept wildcards and version ranges. + * + * @param version Version number to validate + * @returns `true` if the version number is a valid semver version number `false` otherwise + * + * @example + * ``` + * validate('1.0.0-rc.1'); // return true + * validate('1.0-rc.1'); // return false + * validate('foo'); // return false + * ``` + */ + const validateStrict = (version) => typeof version === 'string' && + /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(version); exports.compare = compare; exports.compareVersions = compareVersions; exports.satisfies = satisfies; exports.validate = validate; + exports.validateStrict = validateStrict; })); //# sourceMappingURL=index.js.map diff --git a/src/tics/fetcher.ts b/src/tics/fetcher.ts index 75e8377e..8dfab9c8 100644 --- a/src/tics/fetcher.ts +++ b/src/tics/fetcher.ts @@ -16,6 +16,12 @@ import { logger } from '../helper/logger'; import { createReviewComments } from '../helper/summary'; import { getItemFromUrl, getProjectName, httpRequest } from './api_helper'; +/** + * Retrieve all analysis results from the viewer in one convenient object. + * @param explorerUrls All the explorer urls gotten from the TICS analysis. + * @param changedFiles The changed files gotten from GitHub. + * @returns Object containing the results of the analysis. + */ export async function getAnalysisResults(explorerUrls: string[], changedFiles: ChangedFile[]): Promise { let analysisResults: AnalysisResults = { passed: true, @@ -24,14 +30,20 @@ export async function getAnalysisResults(explorerUrls: string[], changedFiles: C projectResults: [] }; - explorerUrls.forEach(async (url: string) => { + if (explorerUrls.length === 0) { + analysisResults.passed = false; + analysisResults.message = 'No Explorer url found'; + analysisResults.missesQualityGate = true; + } + + for (const url of explorerUrls) { let analysisResult: ProjectResult = { project: getProjectName(url), explorerUrl: url, - analyzedFiles: await getAnalyzedFiles(url) + analyzedFiles: await exports.getAnalyzedFiles(url) // export is used for testing }; - const qualityGate = await getQualityGate(url); + const qualityGate = await exports.getQualityGate(url); // export is used for testing if (!qualityGate) { analysisResults.passed = false; @@ -44,7 +56,7 @@ export async function getAnalysisResults(explorerUrls: string[], changedFiles: C } if (qualityGate && ticsConfig.postAnnotations) { - const annotations = await getAnnotations(qualityGate.annotationsApiV1Links); + const annotations = await exports.getAnnotations(qualityGate.annotationsApiV1Links); // export is used for testing if (annotations && annotations.length > 0) { analysisResult.reviewComments = createReviewComments(annotations, changedFiles); } @@ -53,7 +65,7 @@ export async function getAnalysisResults(explorerUrls: string[], changedFiles: C analysisResult.qualityGate = qualityGate; analysisResults.projectResults.push(analysisResult); - }); + } return analysisResults; } diff --git a/test/tics/fetcher.test.ts b/test/tics/fetcher.test.ts index 437ee1d7..cdde1c01 100644 --- a/test/tics/fetcher.test.ts +++ b/test/tics/fetcher.test.ts @@ -1,7 +1,7 @@ import { ticsConfig } from '../../src/configuration'; import { logger } from '../../src/helper/logger'; import * as api_helper from '../../src/tics/api_helper'; -import { getAnalyzedFiles, getAnnotations, getQualityGate, getViewerVersion } from '../../src/tics/fetcher'; +import * as fetcher from '../../src/tics/fetcher'; describe('getAnalyzedFiles', () => { test('Should return one analyzed file from viewer', async () => { @@ -11,7 +11,7 @@ describe('getAnalyzedFiles', () => { const spy = jest.spyOn(logger, 'debug'); - const response = await getAnalyzedFiles('url'); + const response = await fetcher.getAnalyzedFiles('url'); expect(response).toEqual(['file.js']); expect(spy).toHaveBeenCalledTimes(2); @@ -26,7 +26,7 @@ describe('getAnalyzedFiles', () => { const spy = jest.spyOn(logger, 'debug'); - const response = await getAnalyzedFiles('url'); + const response = await fetcher.getAnalyzedFiles('url'); expect(spy).toHaveBeenCalledTimes(3); expect(response).toEqual(['file.js', 'files.js']); @@ -39,7 +39,7 @@ describe('getAnalyzedFiles', () => { const spy = jest.spyOn(logger, 'exit'); - await getAnalyzedFiles('url'); + await fetcher.getAnalyzedFiles('url'); expect(spy).toHaveBeenCalledTimes(1); }); @@ -53,7 +53,7 @@ describe('getQualityGate', () => { ticsConfig.branchName = 'main'; - const response = await getQualityGate('url'); + const response = await fetcher.getQualityGate('url'); expect(response).toEqual({ data: 'data' }); }); @@ -65,7 +65,7 @@ describe('getQualityGate', () => { const spy = jest.spyOn(logger, 'exit'); - await getQualityGate('url'); + await fetcher.getQualityGate('url'); expect(spy).toHaveBeenCalledTimes(1); }); @@ -78,9 +78,8 @@ describe('getAnnotations', () => { jest.spyOn(api_helper, 'httpRequest').mockImplementationOnce((): Promise => Promise.resolve({ data: [{ annotation: 'anno_1' }] })); jest.spyOn(api_helper, 'httpRequest').mockImplementationOnce((): Promise => Promise.resolve({ data: [{ annotation: 'anno_2' }] })); - const response = await getAnnotations([{ url: 'url' }, { url: 'url' }]); + const response = await fetcher.getAnnotations([{ url: 'url' }, { url: 'url' }]); - console.log(response); expect(response).toEqual([ { annotation: 'anno_1', gateId: 0, instanceName: undefined }, { annotation: 'anno_2', gateId: 1, instanceName: undefined } @@ -92,7 +91,7 @@ describe('getAnnotations', () => { const spy = jest.spyOn(logger, 'exit'); - await getAnnotations([{ url: 'url' }]); + await fetcher.getAnnotations([{ url: 'url' }]); expect(spy).toHaveBeenCalledTimes(1); }); @@ -102,7 +101,7 @@ describe('getViewerVersion', () => { test('Should version of the viewer', async () => { jest.spyOn(api_helper, 'httpRequest').mockImplementationOnce((): Promise => Promise.resolve({ version: '2022.0.0' })); - const response = await getViewerVersion(); + const response = await fetcher.getViewerVersion(); expect(response?.version).toEqual('2022.0.0'); }); @@ -112,8 +111,78 @@ describe('getViewerVersion', () => { const spy = jest.spyOn(logger, 'exit'); - await getViewerVersion(); + await fetcher.getViewerVersion(); expect(spy).toHaveBeenCalledTimes(1); }); }); + +// Should be executed last due to spying rules +describe('getAnalysisResults', () => { + test('Should return nothing on no ExplorerUrl given (should not happen, sanity check)', async () => { + const result = await fetcher.getAnalysisResults([], []); + + expect(result).toEqual({ + passed: false, + message: 'No Explorer url found', + missesQualityGate: true, + projectResults: [] + }); + }); + + test('Should return single analyzed file and no quality gate', async () => { + jest.spyOn(api_helper, 'getProjectName').mockReturnValueOnce('projectName'); + jest.spyOn(fetcher, 'getAnalyzedFiles').mockResolvedValueOnce(['file']); + jest.spyOn(fetcher, 'getQualityGate').mockResolvedValueOnce(undefined); + + const result = await fetcher.getAnalysisResults(['https://url.com/Project(project)'], []); + + expect(result).toEqual({ + passed: false, + message: '', + missesQualityGate: true, + projectResults: [ + { + project: 'projectName', + explorerUrl: 'https://url.com/Project(project)', + analyzedFiles: ['file'], + qualityGate: undefined + } + ] + }); + }); + + test('Should return single analyzed file and failed quality gate', async () => { + jest.spyOn(api_helper, 'getProjectName').mockReturnValueOnce('projectName'); + jest.spyOn(fetcher, 'getAnalyzedFiles').mockResolvedValueOnce(['file']); + jest.spyOn(fetcher, 'getQualityGate').mockResolvedValueOnce({ + passed: false, + message: 'failed', + url: 'url', + gates: [], + annotationsApiV1Links: [] + }); + + const result = await fetcher.getAnalysisResults(['https://url.com/Project(project)'], []); + + expect(result).toEqual({ + passed: false, + message: 'failed ', + missesQualityGate: false, + projectResults: [ + { + project: 'projectName', + explorerUrl: 'https://url.com/Project(project)', + analyzedFiles: ['file'], + qualityGate: { + passed: false, + message: 'failed', + url: 'url', + gates: [], + annotationsApiV1Links: [] + } + } + ] + }); + }); +}); From 166e3d28f2463e560a3989acd5e5f9d9b6ddf753 Mon Sep 17 00:00:00 2001 From: janssen <118828444+janssen-tiobe@users.noreply.github.com> Date: Tue, 5 Sep 2023 11:28:50 +0200 Subject: [PATCH 8/8] #32831: Added more tests and small design change --- dist/index.js | 14631 ++++++++++++++++----------------- src/tics/fetcher.ts | 5 +- test/github/commits.test.ts | 12 + test/tics/fetcher.test.ts | 111 +- test/tics/objects/fetcher.ts | 72 + 5 files changed, 7463 insertions(+), 7368 deletions(-) create mode 100644 test/tics/objects/fetcher.ts diff --git a/dist/index.js b/dist/index.js index 8e0b831e..62eff9ae 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1380,7 +1380,7 @@ async function getAnalysisResults(explorerUrls, changedFiles) { } if (qualityGate && !qualityGate.passed) { analysisResults.passed = false; - analysisResults.message += qualityGate.message + ' '; + analysisResults.message += qualityGate.message + '; '; } if (qualityGate && configuration_1.ticsConfig.postAnnotations) { const annotations = await exports.getAnnotations(qualityGate.annotationsApiV1Links); // export is used for testing @@ -1391,6 +1391,8 @@ async function getAnalysisResults(explorerUrls, changedFiles) { analysisResult.qualityGate = qualityGate; analysisResults.projectResults.push(analysisResult); } + // Remove trailing space from the message + analysisResults.message = analysisResults.message.trimEnd(); return analysisResults; } exports.getAnalysisResults = getAnalysisResults; @@ -21318,7 +21320,6 @@ exports.Deprecation = Deprecation; Copyright (C) 2012 Joost-Wim Boekesteijn Copyright (C) 2012 Kris Kowal Copyright (C) 2012 Arpad Borsos - Copyright (C) 2020 Apple Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: @@ -21372,7 +21373,7 @@ exports.Deprecation = Deprecation; FORMAT_MINIFY, FORMAT_DEFAULTS; - estraverse = __nccwpck_require__(3479); + estraverse = __nccwpck_require__(9606); esutils = __nccwpck_require__(4038); Syntax = estraverse.Syntax; @@ -21393,31 +21394,28 @@ exports.Deprecation = Deprecation; Assignment: 1, Conditional: 2, ArrowFunction: 2, - Coalesce: 3, - LogicalOR: 4, - LogicalAND: 5, - BitwiseOR: 6, - BitwiseXOR: 7, - BitwiseAND: 8, - Equality: 9, - Relational: 10, - BitwiseSHIFT: 11, - Additive: 12, - Multiplicative: 13, - Exponentiation: 14, - Await: 15, - Unary: 15, - Postfix: 16, - OptionalChaining: 17, - Call: 18, - New: 19, - TaggedTemplate: 20, - Member: 21, - Primary: 22 + LogicalOR: 3, + LogicalAND: 4, + BitwiseOR: 5, + BitwiseXOR: 6, + BitwiseAND: 7, + Equality: 8, + Relational: 9, + BitwiseSHIFT: 10, + Additive: 11, + Multiplicative: 12, + Exponentiation: 13, + Await: 14, + Unary: 14, + Postfix: 15, + Call: 16, + New: 17, + TaggedTemplate: 18, + Member: 19, + Primary: 20 }; BinaryPrecedence = { - '??': Precedence.Coalesce, '||': Precedence.LogicalOR, '&&': Precedence.LogicalAND, '|': Precedence.BitwiseOR, @@ -21452,8 +21450,7 @@ exports.Deprecation = Deprecation; F_ALLOW_UNPARATH_NEW = 1 << 2, F_FUNC_BODY = 1 << 3, F_DIRECTIVE_CTX = 1 << 4, - F_SEMICOLON_OPT = 1 << 5, - F_FOUND_COALESCE = 1 << 6; + F_SEMICOLON_OPT = 1 << 5; //Expression flag sets //NOTE: Flag order: @@ -23129,7 +23126,7 @@ exports.Deprecation = Deprecation; } return parenthesize( [ - this.generateExpression(expr.test, Precedence.Coalesce, flags), + this.generateExpression(expr.test, Precedence.LogicalOR, flags), space + '?' + space, this.generateExpression(expr.consequent, Precedence.Assignment, flags), space + ':' + space, @@ -23141,9 +23138,6 @@ exports.Deprecation = Deprecation; }, LogicalExpression: function (expr, precedence, flags) { - if (expr.operator === '??') { - flags |= F_FOUND_COALESCE; - } return this.BinaryExpression(expr, precedence, flags); }, @@ -23181,22 +23175,13 @@ exports.Deprecation = Deprecation; if (expr.operator === 'in' && !(flags & F_ALLOW_IN)) { return ['(', result, ')']; } - if ((expr.operator === '||' || expr.operator === '&&') && (flags & F_FOUND_COALESCE)) { - return ['(', result, ')']; - } return parenthesize(result, currentPrecedence, precedence); }, CallExpression: function (expr, precedence, flags) { var result, i, iz; - // F_ALLOW_UNPARATH_NEW becomes false. result = [this.generateExpression(expr.callee, Precedence.Call, E_TTF)]; - - if (expr.optional) { - result.push('?.'); - } - result.push('('); for (i = 0, iz = expr['arguments'].length; i < iz; ++i) { result.push(this.generateExpression(expr['arguments'][i], Precedence.Assignment, E_TTT)); @@ -23209,20 +23194,9 @@ exports.Deprecation = Deprecation; if (!(flags & F_ALLOW_CALL)) { return ['(', result, ')']; } - return parenthesize(result, Precedence.Call, precedence); }, - ChainExpression: function (expr, precedence, flags) { - if (Precedence.OptionalChaining < precedence) { - flags |= F_ALLOW_CALL; - } - - var result = this.generateExpression(expr.expression, Precedence.OptionalChaining, flags); - - return parenthesize(result, Precedence.OptionalChaining, precedence); - }, - NewExpression: function (expr, precedence, flags) { var result, length, i, iz, itemFlags; length = expr['arguments'].length; @@ -23257,15 +23231,11 @@ exports.Deprecation = Deprecation; result = [this.generateExpression(expr.object, Precedence.Call, (flags & F_ALLOW_CALL) ? E_TTF : E_TFF)]; if (expr.computed) { - if (expr.optional) { - result.push('?.'); - } - result.push('['); result.push(this.generateExpression(expr.property, Precedence.Sequence, flags & F_ALLOW_CALL ? E_TTT : E_TFT)); result.push(']'); } else { - if (!expr.optional && expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') { + if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') { fragment = toSourceNodeWhenNeeded(result).toString(); // When the following conditions are all true, // 1. No floating point @@ -23282,7 +23252,7 @@ exports.Deprecation = Deprecation; result.push(' '); } } - result.push(expr.optional ? '?.' : '.'); + result.push('.'); result.push(generateIdentifier(expr.property)); } @@ -23665,16 +23635,6 @@ exports.Deprecation = Deprecation; return '/' + expr.regex.pattern + '/' + expr.regex.flags; } - if (typeof expr.value === 'bigint') { - return expr.value.toString() + 'n'; - } - - // `expr.value` can be null if `expr.bigint` exists. We need to check - // `expr.bigint` first. - if (expr.bigint) { - return expr.bigint + 'n'; - } - if (expr.value === null) { return 'null'; } @@ -23806,7 +23766,8 @@ exports.Deprecation = Deprecation; this.generateExpression(expr.source, Precedence.Assignment, E_TTT), ')' ], Precedence.Call, precedence); - } + }, + }; merge(CodeGenerator.prototype, CodeGenerator.Expression); @@ -23976,7083 +23937,368 @@ exports.Deprecation = Deprecation; /***/ }), -/***/ 8823: -/***/ (function(module) { +/***/ 9606: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { -(function webpackUniversalModuleDefinition(root, factory) { -/* istanbul ignore next */ - if(true) - module.exports = factory(); - else {} -})(this, function() { -return /******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; +/* + Copyright (C) 2012-2013 Yusuke Suzuki + Copyright (C) 2012 Ariya Hidayat -/******/ // The require function -/******/ function __nested_webpack_require_583__(moduleId) { + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: -/******/ // Check if module is in cache -/* istanbul ignore if */ -/******/ if(installedModules[moduleId]) -/******/ return installedModules[moduleId].exports; + * 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. -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ exports: {}, -/******/ id: moduleId, -/******/ loaded: false -/******/ }; + 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. +*/ +/*jslint vars:false, bitwise:true*/ +/*jshint indent:4*/ +/*global exports:true*/ +(function clone(exports) { + 'use strict'; -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __nested_webpack_require_583__); + var Syntax, + VisitorOption, + VisitorKeys, + BREAK, + SKIP, + REMOVE; -/******/ // Flag the module as loaded -/******/ module.loaded = true; + function deepCopy(obj) { + var ret = {}, key, val; + for (key in obj) { + if (obj.hasOwnProperty(key)) { + val = obj[key]; + if (typeof val === 'object' && val !== null) { + ret[key] = deepCopy(val); + } else { + ret[key] = val; + } + } + } + return ret; + } -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } + // based on LLVM libc++ upper_bound / lower_bound + // MIT License + function upperBound(array, func) { + var diff, len, i, current; -/******/ // expose the modules object (__webpack_modules__) -/******/ __nested_webpack_require_583__.m = modules; + len = array.length; + i = 0; -/******/ // expose the module cache -/******/ __nested_webpack_require_583__.c = installedModules; + while (len) { + diff = len >>> 1; + current = i + diff; + if (func(array[current])) { + len = diff; + } else { + i = current + 1; + len -= diff + 1; + } + } + return i; + } -/******/ // __webpack_public_path__ -/******/ __nested_webpack_require_583__.p = ""; + Syntax = { + AssignmentExpression: 'AssignmentExpression', + AssignmentPattern: 'AssignmentPattern', + ArrayExpression: 'ArrayExpression', + ArrayPattern: 'ArrayPattern', + ArrowFunctionExpression: 'ArrowFunctionExpression', + AwaitExpression: 'AwaitExpression', // CAUTION: It's deferred to ES7. + BlockStatement: 'BlockStatement', + BinaryExpression: 'BinaryExpression', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ClassBody: 'ClassBody', + ClassDeclaration: 'ClassDeclaration', + ClassExpression: 'ClassExpression', + ComprehensionBlock: 'ComprehensionBlock', // CAUTION: It's deferred to ES7. + ComprehensionExpression: 'ComprehensionExpression', // CAUTION: It's deferred to ES7. + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DebuggerStatement: 'DebuggerStatement', + DirectiveStatement: 'DirectiveStatement', + DoWhileStatement: 'DoWhileStatement', + EmptyStatement: 'EmptyStatement', + ExportAllDeclaration: 'ExportAllDeclaration', + ExportDefaultDeclaration: 'ExportDefaultDeclaration', + ExportNamedDeclaration: 'ExportNamedDeclaration', + ExportSpecifier: 'ExportSpecifier', + ExpressionStatement: 'ExpressionStatement', + ForStatement: 'ForStatement', + ForInStatement: 'ForInStatement', + ForOfStatement: 'ForOfStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + GeneratorExpression: 'GeneratorExpression', // CAUTION: It's deferred to ES7. + Identifier: 'Identifier', + IfStatement: 'IfStatement', + ImportExpression: 'ImportExpression', + ImportDeclaration: 'ImportDeclaration', + ImportDefaultSpecifier: 'ImportDefaultSpecifier', + ImportNamespaceSpecifier: 'ImportNamespaceSpecifier', + ImportSpecifier: 'ImportSpecifier', + Literal: 'Literal', + LabeledStatement: 'LabeledStatement', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + MetaProperty: 'MetaProperty', + MethodDefinition: 'MethodDefinition', + ModuleSpecifier: 'ModuleSpecifier', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + ObjectPattern: 'ObjectPattern', + Program: 'Program', + Property: 'Property', + RestElement: 'RestElement', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SpreadElement: 'SpreadElement', + Super: 'Super', + SwitchStatement: 'SwitchStatement', + SwitchCase: 'SwitchCase', + 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' + }; -/******/ // Load entry module and return exports -/******/ return __nested_webpack_require_583__(0); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ function(module, exports, __nested_webpack_require_1808__) { + VisitorKeys = { + AssignmentExpression: ['left', 'right'], + AssignmentPattern: ['left', 'right'], + ArrayExpression: ['elements'], + ArrayPattern: ['elements'], + ArrowFunctionExpression: ['params', 'body'], + AwaitExpression: ['argument'], // CAUTION: It's deferred to ES7. + BlockStatement: ['body'], + BinaryExpression: ['left', 'right'], + BreakStatement: ['label'], + CallExpression: ['callee', 'arguments'], + CatchClause: ['param', 'body'], + ClassBody: ['body'], + ClassDeclaration: ['id', 'superClass', 'body'], + ClassExpression: ['id', 'superClass', 'body'], + ComprehensionBlock: ['left', 'right'], // CAUTION: It's deferred to ES7. + ComprehensionExpression: ['blocks', 'filter', 'body'], // CAUTION: It's deferred to ES7. + ConditionalExpression: ['test', 'consequent', 'alternate'], + ContinueStatement: ['label'], + DebuggerStatement: [], + DirectiveStatement: [], + DoWhileStatement: ['body', 'test'], + EmptyStatement: [], + ExportAllDeclaration: ['source'], + ExportDefaultDeclaration: ['declaration'], + ExportNamedDeclaration: ['declaration', 'specifiers', 'source'], + ExportSpecifier: ['exported', 'local'], + ExpressionStatement: ['expression'], + ForStatement: ['init', 'test', 'update', 'body'], + ForInStatement: ['left', 'right', 'body'], + ForOfStatement: ['left', 'right', 'body'], + FunctionDeclaration: ['id', 'params', 'body'], + FunctionExpression: ['id', 'params', 'body'], + GeneratorExpression: ['blocks', 'filter', 'body'], // CAUTION: It's deferred to ES7. + Identifier: [], + IfStatement: ['test', 'consequent', 'alternate'], + ImportExpression: ['source'], + ImportDeclaration: ['specifiers', 'source'], + ImportDefaultSpecifier: ['local'], + ImportNamespaceSpecifier: ['local'], + ImportSpecifier: ['imported', 'local'], + Literal: [], + LabeledStatement: ['label', 'body'], + LogicalExpression: ['left', 'right'], + MemberExpression: ['object', 'property'], + MetaProperty: ['meta', 'property'], + MethodDefinition: ['key', 'value'], + ModuleSpecifier: [], + NewExpression: ['callee', 'arguments'], + ObjectExpression: ['properties'], + ObjectPattern: ['properties'], + Program: ['body'], + Property: ['key', 'value'], + RestElement: [ 'argument' ], + ReturnStatement: ['argument'], + SequenceExpression: ['expressions'], + SpreadElement: ['argument'], + Super: [], + SwitchStatement: ['discriminant', 'cases'], + SwitchCase: ['test', 'consequent'], + TaggedTemplateExpression: ['tag', 'quasi'], + TemplateElement: [], + TemplateLiteral: ['quasis', 'expressions'], + ThisExpression: [], + ThrowStatement: ['argument'], + TryStatement: ['block', 'handler', 'finalizer'], + UnaryExpression: ['argument'], + UpdateExpression: ['argument'], + VariableDeclaration: ['declarations'], + VariableDeclarator: ['id', 'init'], + WhileStatement: ['test', 'body'], + WithStatement: ['object', 'body'], + YieldExpression: ['argument'] + }; - "use strict"; - /* - Copyright JS Foundation and other contributors, https://js.foundation/ + // unique id + BREAK = {}; + SKIP = {}; + REMOVE = {}; - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: + VisitorOption = { + Break: BREAK, + Skip: SKIP, + Remove: REMOVE + }; - * 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 Reference(parent, key) { + this.parent = parent; + this.key = key; + } - 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 = __nested_webpack_require_1808__(1); - var jsx_parser_1 = __nested_webpack_require_1808__(3); - var parser_1 = __nested_webpack_require_1808__(8); - var tokenizer_1 = __nested_webpack_require_1808__(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 = __nested_webpack_require_1808__(2); - exports.Syntax = syntax_1.Syntax; - // Sync with *.json manifests. - exports.version = '4.0.1'; + Reference.prototype.replace = function replace(node) { + this.parent[this.key] = node; + }; + Reference.prototype.remove = function remove() { + if (Array.isArray(this.parent)) { + this.parent.splice(this.key, 1); + return true; + } else { + this.replace(null); + return false; + } + }; -/***/ }, -/* 1 */ -/***/ function(module, exports, __nested_webpack_require_6456__) { + function Element(node, path, wrap, ref) { + this.node = node; + this.path = path; + this.wrap = wrap; + this.ref = ref; + } - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var syntax_1 = __nested_webpack_require_6456__(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; + function Controller() { } + // API: + // return property path array from root to current node + Controller.prototype.path = function path() { + var i, iz, j, jz, result, element; -/***/ }, -/* 2 */ -/***/ function(module, exports) { + function addToPath(result, path) { + if (Array.isArray(path)) { + for (j = 0, jz = path.length; j < jz; ++j) { + result.push(path[j]); + } + } else { + result.push(path); + } + } - "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' - }; + // root node + if (!this.__current.path) { + return null; + } + // first node is sentinel, second node is root element + result = []; + for (i = 2, iz = this.__leavelist.length; i < iz; ++i) { + element = this.__leavelist[i]; + addToPath(result, element.path); + } + addToPath(result, this.__current.path); + return result; + }; -/***/ }, -/* 3 */ -/***/ function(module, exports, __nested_webpack_require_15019__) { + // API: + // return type of current node + Controller.prototype.type = function () { + var node = this.current(); + return node.type || this.__current.wrap; + }; - "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 = __nested_webpack_require_15019__(4); - var JSXNode = __nested_webpack_require_15019__(5); - var jsx_syntax_1 = __nested_webpack_require_15019__(6); - var Node = __nested_webpack_require_15019__(7); - var parser_1 = __nested_webpack_require_15019__(8); - var token_1 = __nested_webpack_require_15019__(13); - var xhtml_entities_1 = __nested_webpack_require_15019__(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; + // API: + // return array of parent elements + Controller.prototype.parents = function parents() { + var i, iz, result; + // first node is sentinel + result = []; + for (i = 1, iz = this.__leavelist.length; i < iz; ++i) { + result.push(this.__leavelist[i].node); + } -/***/ }, -/* 4 */ -/***/ function(module, exports) { + return result; + }; - "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 - } - }; + // API: + // return current node + Controller.prototype.current = function current() { + return this.__current.node; + }; + Controller.prototype.__execute = function __execute(callback, element) { + var previous, result; -/***/ }, -/* 5 */ -/***/ function(module, exports, __nested_webpack_require_54354__) { + result = undefined; - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var jsx_syntax_1 = __nested_webpack_require_54354__(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; + previous = this.__current; + this.__current = element; + this.__state = null; + if (callback) { + result = callback.call(this, element.node, this.__leavelist[this.__leavelist.length - 1].node); + } + this.__current = previous; + return result; + }; -/***/ }, -/* 6 */ -/***/ function(module, exports) { + // API: + // notify control skip / break + Controller.prototype.notify = function notify(flag) { + this.__state = flag; + }; - "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' - }; + // API: + // skip child nodes of current node + Controller.prototype.skip = function () { + this.notify(SKIP); + }; + // API: + // break traversals + Controller.prototype['break'] = function () { + this.notify(BREAK); + }; -/***/ }, -/* 7 */ -/***/ function(module, exports, __nested_webpack_require_58416__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var syntax_1 = __nested_webpack_require_58416__(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, __nested_webpack_require_80491__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var assert_1 = __nested_webpack_require_80491__(9); - var error_handler_1 = __nested_webpack_require_80491__(10); - var messages_1 = __nested_webpack_require_80491__(11); - var Node = __nested_webpack_require_80491__(7); - var scanner_1 = __nested_webpack_require_80491__(12); - var syntax_1 = __nested_webpack_require_80491__(2); - var token_1 = __nested_webpack_require_80491__(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, __nested_webpack_require_226595__) { - - "use strict"; - Object.defineProperty(exports, "__esModule", { value: true }); - var assert_1 = __nested_webpack_require_226595__(9); - var character_1 = __nested_webpack_require_226595__(4); - var messages_1 = __nested_webpack_require_226595__(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; // `