From 5eb090f288cf56f3ab9bce8bd133faa0637368c7 Mon Sep 17 00:00:00 2001 From: Tim van der Meij Date: Sat, 4 Mar 2017 21:43:25 +0100 Subject: [PATCH] ES6 modules: remove UMD header validation This patch is another step towards enabling Babel. Since we're moving towards ES6 modules, we will not be using UMD headers anymore, so we can remove the validation. --- external/builder/preprocessor2.js | 2 +- external/umdutils/verifier.js | 515 ------------------------------ gulpfile.js | 13 - src/pdf.js | 1 - src/pdf.worker.js | 1 - web/pdf_viewer.component.js | 1 - web/pdfjs.js | 1 - 7 files changed, 1 insertion(+), 533 deletions(-) delete mode 100644 external/umdutils/verifier.js diff --git a/external/builder/preprocessor2.js b/external/builder/preprocessor2.js index bf22ac64d..f7e3ee9fd 100644 --- a/external/builder/preprocessor2.js +++ b/external/builder/preprocessor2.js @@ -294,7 +294,7 @@ function fixComments(ctx, node) { // Removes ESLint and other service comments. if (node.leadingComments) { var CopyrightRegExp = /\bcopyright\b/i; - var BlockCommentRegExp = /^\s*(globals|eslint|falls through|umdutils)\b/; + var BlockCommentRegExp = /^\s*(globals|eslint|falls through)\b/; var LineCommentRegExp = /^\s*eslint\b/; var i = 0; diff --git a/external/umdutils/verifier.js b/external/umdutils/verifier.js deleted file mode 100644 index d76350855..000000000 --- a/external/umdutils/verifier.js +++ /dev/null @@ -1,515 +0,0 @@ -/* Copyright 2015 Mozilla Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -'use strict'; - -/* Utilities for parsing PDF.js UMD file format. A UMD header of the file - * shall conform the following rules: - * 1. Names of AMD modules and JavaScript object placed to the global object - * shall be alike: symbols'/' and '_' removed, and character case is - * ignored. - * 2. CommonJS require shall use relative path to the required module, e.g. - * './display.js' or '../shared/util.js', and they shall construct the - * similar name to AMD one. - * 3. Factory function shall contain names for modules, not less than listed - * in AMD, CommonJS or global object properties list, and also their - * names must be alike to name of the root object properties. - * - * Example: - * - * (function (root, factory) { - * if (typeof define === 'function' && define.amd) { - * define('pdfjs/display/pattern_helper', ['exports', 'pdfjs/shared/util', - * 'pdfjs/display/webgl'], factory); - * } else if (typeof exports !== 'undefined') { - * factory(exports, require('../shared/util.js'), require('./webgl.js')); - * } else { - * factory((root.pdfjsDisplayPatternHelper = {}), root.pdfjsSharedUtil, - * root.pdfjsDisplayWebGL); - * } - * }(this, function (exports, sharedUtil, displayWebGL) { - * - */ - -var fs = require('fs'); -var path = require('path'); - -/** - * Parses PDF.js UMD header. - * @param {string} filePath PDF.js JavaScript file path. - * @returns {{amdId: *, amdImports: Array, cjsRequires: Array, jsRootName: *, - * jsImports: Array, imports: Array, importedNames: Array, - * exportedNames: Array, body: *}} - */ -function parseUmd(filePath) { - var jscode = fs.readFileSync(filePath).toString(); - if (/\/\*\s*umdutils\s+ignore\s*\*\//.test(jscode)) { - throw new Error('UMD processing ignored'); - } - // Extracts header and body. - var umdStart = '\\(function\\s\\(root,\\sfactory\\)\\s\\{'; - var umdImports = '\\}\\(this,\\sfunction\\s\\(exports\\b'; - var umdBody = '\\)\\s\\{'; - var umdEnd = '\\}\\)\\);\\s*(//#endif\\s*)?$'; - var m, re; - m = new RegExp(umdStart + '([\\s\\S]*?)' + umdImports + '([\\s\\S]*?)' + - umdBody + '([\\s\\S]*?)' + umdEnd).exec(jscode); - if (!m) { - throw new Error('UMD was not found'); - } - var header = m[1]; - var imports = m[2].replace(/\s+/g, '').split(','); - imports.shift(); // avoiding only-export case - var body = m[3]; - - // Extracts AMD definitions. - var amdMatch = /\bdefine\('([^']*)',\s\[([^\]]*)\],\s+factory\);/. - exec(header); - if (!amdMatch) { - throw new Error('AMD call was not found'); - } - var amdId = amdMatch[1]; - var amdImports = amdMatch[2].replace(/[\s']+/g, '').split(','); - if (amdImports[0] !== 'exports') { - throw new Error('exports expected first at AMD call'); - } - amdImports.shift(); - - // Extracts CommonJS definitions. - var cjsMatch = /\bfactory\(exports((?:,\s+require\([^\)]+\))*)\);/. - exec(header); - if (!cjsMatch) { - throw new Error('CommonJS call was not found'); - } - var cjsRequires = cjsMatch[1].replace(/\s+/g, ' ').trim(). - replace(/\s*require\('([^']*)'\)/g, '$1').split(','); - cjsRequires.shift(); - var jsMatch = /\bfactory\(\(root\.(\S+)\s=\s\{\}\)((?:,\s+root\.\S+)*)\);/. - exec(header); - if (!jsMatch) { - throw new Error('Regular JS call was not found'); - } - - // Extracts global object properties definitions. - var jsRootName = jsMatch[1]; - var jsImports = jsMatch[2].replace(/\s+/g, '').split(','); - jsImports.shift(); - - // Scans for imports usages in the body. - var importedNames = []; - if (imports.length > 0) { - re = new RegExp('\\b(' + imports.join('|') + ')\\.(\\w+)', 'g'); - while ((m = re.exec(body))) { - importedNames.push(m[0]); - } - } - importedNames.sort(); - for (var i = importedNames.length - 1; i > 0; i--) { - if (importedNames[i - 1] === importedNames[i]) { - importedNames.splice(i, 1); - } - } - // Scans for exports definitions in the body. - var exportedNames = []; - re = /\bexports.(\w+)\s*=\s/g; - while ((m = re.exec(body))) { - exportedNames.push(m[1]); - } - - return { - amdId: amdId, - amdImports: amdImports, - cjsRequires: cjsRequires, - jsRootName: jsRootName, - jsImports: jsImports, - imports: imports, - importedNames: importedNames, - exportedNames: exportedNames, - body: body - }; -} - -/** - * Reads and parses all JavaScript root files dependencies and calculates - * evaluation/load order. - * @param {Array} rootPaths Array of the paths for JavaScript files. - * @returns {{modules: null, loadOrder: Array}} - */ -function readDependencies(rootPaths) { - // Reading of dependencies. - var modules = Object.create(null); - var processed = Object.create(null); - var queue = []; - rootPaths.forEach(function (i) { - if (processed[i]) { - return; - } - queue.push(i); - processed[i] = true; - }); - while (queue.length > 0) { - var p = queue.shift(); - var umd; - try { - umd = parseUmd(p); - } catch (_) { - // Ignoring bad UMD modules. - continue; - } - modules[umd.amdId] = { - dependencies: umd.amdImports - }; - umd.cjsRequires.forEach(function (r) { - if (r[0] !== '.' || !/\.js$/.test(r)) { - return; // not pdfjs module - } - var dependencyPath = path.join(path.dirname(p), r); - if (processed[dependencyPath]) { - return; - } - queue.push(dependencyPath); - processed[dependencyPath] = true; - }); - } - - // Topological sorting, somewhat Kahn's algorithm but sorts found nodes at - // each iteration. - processed = Object.create(null); - var left = [], result = []; - for (var i in modules) { - var hasDependencies = modules[i].dependencies.length > 0; - if (hasDependencies) { - left.push(i); - } else { - processed[i] = true; - result.push(i); - } - } - result.sort(); - while (left.length > 0) { - var discovered = []; - left.forEach(function (i) { - // Finding if we did not process all dependencies for current module yet. - var hasDependecies = modules[i].dependencies.some(function (j) { - return !processed[j] && !!modules[j]; - }); - if (!hasDependecies) { - discovered.push(i); - } - }); - if (discovered.length === 0) { - throw new Error('Some circular references exist: somewhere at ' + - left.join(',')); - } - discovered.sort(); - discovered.forEach(function (i) { - result.push(i); - left.splice(left.indexOf(i), 1); - processed[i] = true; - }); - } - - return {modules: modules, loadOrder: result}; -} - -/** - * Validates individual file. See rules above. - */ -function validateFile(path, name, context) { - function info(msg) { - context.infoCallback(path + ': ' + msg); - } - function warn(msg) { - context.warnCallback(path + ': ' + msg); - } - function error(msg) { - context.errorCallback(path + ': ' + msg); - } - - try { - var umd = parseUmd(path); - info('found ' + umd.amdId); - - if (name !== umd.amdId) { - error('AMD name does not match module name'); - } - if (name.replace(/[_\-\/]/g, '').toLowerCase() !== - umd.jsRootName.toLowerCase()) { - error('root name does not look like module name'); - } - - if (umd.amdImports.length > umd.imports.length) { - error('AMD imports has more entries than body imports'); - } - if (umd.cjsRequires.length > umd.imports.length) { - error('CommonJS imports has more entries than body imports'); - } - if (umd.jsImports.length > umd.imports.length) { - error('JS imports has more entries than body imports'); - } - var optionalArgs = umd.imports.length - Math.min(umd.amdImports.length, - umd.cjsRequires.length, umd.jsImports.length); - if (optionalArgs > 0) { - warn('' + optionalArgs + ' optional args found: ' + - umd.imports.slice(-optionalArgs)); - } - umd.jsImports.forEach(function (i, index) { - if (i.indexOf('root.') !== 0) { - if (index >= umd.jsImports.length - optionalArgs) { - warn('Non-optional non-root based JS import: ' + i); - } - return; - } - i = i.substring('root.'.length); - var j = umd.imports[index].replace(/(_|Lib)$/, ''); - var offset = i.toLowerCase().lastIndexOf(j.toLowerCase()); - if (offset + j.length !== i.length) { - error('JS import name does not look like corresponding body import ' + - 'name: ' + i + ' vs ' + j); - } - - j = umd.amdImports[index]; - if (j) { - if (j.replace(/[_\-\/]/g, '').toLowerCase() !== i.toLowerCase()) { - error('JS import name does not look like corresponding AMD import ' + - 'name: ' + i + ' vs ' + j); - } - } - }); - umd.cjsRequires.forEach(function (i, index) { - var j = umd.amdImports[index]; - if (!j) { - return; // optional - } - var noExtension = i.replace(/\.js$/, ''); - if (noExtension === i || i[0] !== '.') { - error('CommonJS shall have relative path and extension: ' + i); - return; - } - var base = name.split('/'); - base.pop(); - var parts = noExtension.split('/'); - if (parts[0] === '.') { - parts.shift(); - } - while (parts[0] === '..') { - if (base.length === 0) { - error('Invalid relative CommonJS path'); - } - parts.shift(); - base.pop(); - } - if (base.length === 0) { - // Reached the project root -- finding prefix matching subpath. - for (var prefix in context.paths) { - if (!context.paths.hasOwnProperty(prefix)) { - continue; - } - var prefixPath = context.paths[prefix]; - if (!('./' + parts.join('/') + '/').startsWith(prefixPath + '/')) { - continue; - } - parts.splice(0, prefixPath.split('/').length - 1); - base.push(prefix); - break; - } - if (base.length === 0) { - error('Invalid relative CommonJS path prefix'); - } - } - if (j !== base.concat(parts).join('/')) { - error('CommonJS path does not point to right AMD module: ' + - i + ' vs ' + j); - } - }); - - umd.imports.forEach(function (i) { - var prefix = i + '.'; - if (umd.importedNames.every(function (j) { - return j.indexOf(prefix) !== 0; - })) { - warn('import is not used to import names: ' + i); - } - }); - - // Recording the module exports and imports for further validation. - // See validateImports and validateDependencies below. - context.exports[name] = Object.create(null); - umd.exportedNames.forEach(function (i) { - context.exports[name][i] = true; - }); - context.dependencies[name] = umd.amdImports; - umd.importedNames.forEach(function (i) { - var parts = i.split('.'); - var index = umd.imports.indexOf(parts[0]); - if (index < 0 || !umd.amdImports[index]) { - return; // some optional arg and not in AMD list? - } - var refModuleName = umd.amdImports[index]; - var fromModule = context.imports[refModuleName]; - if (!fromModule) { - context.imports[refModuleName] = (fromModule = Object.create(null)); - } - var symbolRefs = fromModule[parts[1]]; - if (!symbolRefs) { - fromModule[parts[1]] = (symbolRefs = []); - } - symbolRefs.push(name); - }); - } catch (e) { - warn(e.message); - } -} - -function findFilesInDirectory(dirPath, name, foundFiles) { - fs.readdirSync(dirPath).forEach(function (file) { - var filePath = dirPath + '/' + file; - var stats = fs.statSync(filePath); - if (stats.isFile() && /\.js$/i.test(file)) { - var fileName = file.substring(0, file.lastIndexOf('.')); - foundFiles.push({path: filePath, name: name + '/' + fileName}); - } else if (stats.isDirectory() && /^\w+$/.test(file)) { - findFilesInDirectory(filePath, name + '/' + file, foundFiles); - } - }); -} - -function validateImports(context) { - // Checks if some non-exported symbol was imported. - for (var i in context.imports) { - var exportedSymbols = context.exports[i]; - if (!exportedSymbols) { - context.warnCallback('Exported symbols don\'t exist for: ' + i); - continue; - } - var importedSymbols = context.imports[i]; - for (var j in importedSymbols) { - if (!(j in exportedSymbols)) { - context.errorCallback('The non-exported symbol is referred: ' + j + - ' from ' + i + ' used in ' + importedSymbols[j]); - } - } - } -} - -function validateDependencies(context) { - // Checks for circular dependency (non-efficient algorithm but does the work). - var nonRoots = Object.create(null); - var i, j, item; - for (i in context.dependencies) { - var checked = Object.create(null); - var queue = [[i]]; - while (queue.length > 0) { - item = queue.shift(); - j = item[0]; - - var dependencies = context.dependencies[j]; - dependencies.forEach(function (q) { - if (!(q in context.dependencies)) { - context.warnCallback('Unknown dependency: ' + q); - return; - } - - var index = item.indexOf(q); - if (index >= 0) { - context.errorCallback('Circular dependency was found: ' + - item.slice(0, index + 1).join('<-')); - return; - } - if (q in checked) { - return; - } - queue.push([q].concat(item)); - checked[q] = i; - nonRoots[q] = true; - }); - } - } - - // Some root modules info. - for (i in context.dependencies) { - if (!(i in nonRoots)) { - context.infoCallback('Root module: ' + i); - } - } -} - -/** - * Validates all modules/files in the specified path. The modules must be - * defined using PDF.js UMD format. Results printed to console. - * @param {Object} paths The map of the module path prefixes to file/directory - * location. - * @param {Object} options (optional) options for validation. - * @returns {boolean} true if no error was found. - */ -function validateFiles(paths, options) { - options = options || {}; - var verbosity = options.verbosity === undefined ? 0 : options.verbosity; - var wasErrorFound = false; - var errorCallback = function (msg) { - if (verbosity >= 0) { - console.error('ERROR:' + msg); - } - wasErrorFound = true; - }; - var warnCallback = function (msg) { - if (verbosity >= 1) { - console.warn('WARNING: ' + msg); - } - }; - var infoCallback = function (msg) { - if (verbosity >= 5) { - console.info('INFO: ' + msg); - } - }; - - // Finds all files. - var foundFiles = []; - for (var name in paths) { - if (!paths.hasOwnProperty(name)) { - continue; - } - var path = paths[name]; - var stats = fs.statSync(path); - if (stats.isFile()) { - foundFiles.push({path: path, name: name}); - } else if (stats.isDirectory()) { - findFilesInDirectory(path, name, foundFiles); - } - } - - var context = { - exports: Object.create(null), - imports: Object.create(null), - dependencies: Object.create(null), - paths: paths, - errorCallback: errorCallback, - warnCallback: warnCallback, - infoCallback: infoCallback - }; - - foundFiles.forEach(function (pair) { - validateFile(pair.path, pair.name, context); - }); - - validateImports(context); - validateDependencies(context); - - return !wasErrorFound; -} - -exports.parseUmd = parseUmd; -exports.readDependencies = readDependencies; -exports.validateFiles = validateFiles; diff --git a/gulpfile.js b/gulpfile.js index c40378052..d6d64defb 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1087,19 +1087,6 @@ gulp.task('lint', function (done) { return; } - console.log(); - console.log('### Checking UMD dependencies'); - var umd = require('./external/umdutils/verifier.js'); - var paths = { - 'pdfjs': './src', - 'pdfjs-web': './web', - 'pdfjs-test': './test' - }; - if (!umd.validateFiles(paths)) { - done(new Error('UMD check failed.')); - return; - } - console.log(); console.log('### Checking supplemental files'); diff --git a/src/pdf.js b/src/pdf.js index 1dc23daa0..7ada95823 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -13,7 +13,6 @@ * limitations under the License. */ /* eslint-disable no-unused-vars */ -/* umdutils ignore */ 'use strict'; diff --git a/src/pdf.worker.js b/src/pdf.worker.js index 2a9724e9e..93cfa6c9f 100644 --- a/src/pdf.worker.js +++ b/src/pdf.worker.js @@ -13,7 +13,6 @@ * limitations under the License. */ /* eslint-disable no-unused-vars */ -/* umdutils ignore */ 'use strict'; diff --git a/web/pdf_viewer.component.js b/web/pdf_viewer.component.js index da0926230..4fed1f884 100644 --- a/web/pdf_viewer.component.js +++ b/web/pdf_viewer.component.js @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* umdutils ignore */ 'use strict'; diff --git a/web/pdfjs.js b/web/pdfjs.js index 8e5d642da..551f94f88 100644 --- a/web/pdfjs.js +++ b/web/pdfjs.js @@ -13,7 +13,6 @@ * limitations under the License. */ /* globals module, __pdfjsdev_webpack__ */ -/* umdutils ignore */ 'use strict';