Comparing version
515
index.js
@@ -1,514 +0,1 @@ | ||
// Except a small part of the code, all of the code here is taken from | ||
// https://github.com/evanw/node-source-map-support | ||
var SourceMapConsumer = require('source-map').SourceMapConsumer; | ||
var path = require('path'); | ||
var fs = require('fs'); | ||
var tsc = require('typescript'); | ||
var {getTSConfig} = require('./utils'); | ||
// Only install once if called multiple times | ||
var errorFormatterInstalled = false; | ||
var uncaughtShimInstalled = false; | ||
// If true, the caches are reset before a stack trace formatting operation | ||
var emptyCacheBetweenOperations = false; | ||
// Supports {browser, node, auto} | ||
var environment = "auto"; | ||
// Maps a file path to a string containing the file contents | ||
var fileContentsCache = {}; | ||
// Maps a file path to a source map for that file | ||
var sourceMapCache = {}; | ||
// Regex for detecting source maps | ||
var reSourceMap = /^data:application\/json[^,]+base64,/; | ||
// Priority list of retrieve handlers | ||
var retrieveFileHandlers = []; | ||
var retrieveMapHandlers = []; | ||
function isInBrowser() { | ||
if (environment === "browser") | ||
return true; | ||
if (environment === "node") | ||
return false; | ||
return ((typeof window !== 'undefined') && (typeof XMLHttpRequest === 'function') && !(window.require && window.module && window.process && window.process.type === "renderer")); | ||
} | ||
function hasGlobalProcessEventEmitter() { | ||
return ((typeof process === 'object') && (process !== null) && (typeof process.on === 'function')); | ||
} | ||
function handlerExec(list) { | ||
return function (arg) { | ||
for (var i = 0; i < list.length; i++) { | ||
var ret = list[i](arg); | ||
if (ret) { | ||
return ret; | ||
} | ||
} | ||
return null; | ||
}; | ||
} | ||
var retrieveFile = handlerExec(retrieveFileHandlers); | ||
retrieveFileHandlers.push(function (path) { | ||
// Trim the path to make sure there is no extra whitespace. | ||
path = path.trim(); | ||
if (path in fileContentsCache) { | ||
return fileContentsCache[path]; | ||
} | ||
try { | ||
// Use SJAX if we are in the browser | ||
if (isInBrowser()) { | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open('GET', path, false); | ||
xhr.send(null); | ||
var contents = null | ||
if (xhr.readyState === 4 && xhr.status === 200) { | ||
contents = xhr.responseText | ||
contents = transpileIfTypescript(path, contents); | ||
} | ||
} | ||
// Otherwise, use the filesystem | ||
else { | ||
var contents = fs.readFileSync(path, 'utf8'); | ||
contents = transpileIfTypescript(path, contents); | ||
} | ||
} catch (e) { | ||
var contents = null; | ||
} | ||
return fileContentsCache[path] = contents; | ||
}); | ||
function transpileIfTypescript(path, contents) { | ||
if (path && (path.endsWith('.tsx') || path.endsWith('.ts'))) { | ||
transpiled = tsc.transpileModule(contents, { | ||
compilerOptions: addSourceMapToTSConfig(), | ||
fileName: path | ||
}); | ||
return transpiled.outputText; | ||
} | ||
return contents; | ||
} | ||
// Support URLs relative to a directory, but be careful about a protocol prefix | ||
// in case we are in the browser (i.e. directories may start with "http://") | ||
function supportRelativeURL(file, url) { | ||
if (!file) return url; | ||
var dir = path.dirname(file); | ||
var match = /^\w+:\/\/[^\/]*/.exec(dir); | ||
var protocol = match ? match[0] : ''; | ||
return protocol + path.resolve(dir.slice(protocol.length), url); | ||
} | ||
function retrieveSourceMapURL(source) { | ||
var fileData; | ||
if (isInBrowser()) { | ||
var xhr = new XMLHttpRequest(); | ||
xhr.open('GET', source, false); | ||
xhr.send(null); | ||
fileData = xhr.readyState === 4 ? xhr.responseText : null; | ||
// Support providing a sourceMappingURL via the SourceMap header | ||
var sourceMapHeader = xhr.getResponseHeader("SourceMap") || | ||
xhr.getResponseHeader("X-SourceMap"); | ||
if (sourceMapHeader) { | ||
return sourceMapHeader; | ||
} | ||
} | ||
// Get the URL of the source map | ||
fileData = retrieveFile(source); | ||
// //# sourceMappingURL=foo.js.map /*# sourceMappingURL=foo.js.map */ | ||
var re = /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^\*]+?)[ \t]*(?:\*\/)[ \t]*$)/mg; | ||
// Keep executing the search to find the *last* sourceMappingURL to avoid | ||
// picking up sourceMappingURLs from comments, strings, etc. | ||
var lastMatch, match; | ||
while (match = re.exec(fileData)) lastMatch = match; | ||
if (!lastMatch) return null; | ||
return lastMatch[1]; | ||
}; | ||
// Can be overridden by the retrieveSourceMap option to install. Takes a | ||
// generated source filename; returns a {map, optional url} object, or null if | ||
// there is no source map. The map field may be either a string or the parsed | ||
// JSON object (ie, it must be a valid argument to the SourceMapConsumer | ||
// constructor). | ||
var retrieveSourceMap = handlerExec(retrieveMapHandlers); | ||
retrieveMapHandlers.push(function (source) { | ||
var sourceMappingURL = retrieveSourceMapURL(source); | ||
if (!sourceMappingURL) return null; | ||
// Read the contents of the source map | ||
var sourceMapData; | ||
if (reSourceMap.test(sourceMappingURL)) { | ||
// Support source map URL as a data url | ||
var rawData = sourceMappingURL.slice(sourceMappingURL.indexOf(',') + 1); | ||
sourceMapData = new Buffer(rawData, "base64").toString(); | ||
sourceMappingURL = null; | ||
} else { | ||
// Support source map URLs relative to the source URL | ||
sourceMappingURL = supportRelativeURL(source, sourceMappingURL); | ||
sourceMapData = retrieveFile(sourceMappingURL); | ||
} | ||
if (!sourceMapData) { | ||
return null; | ||
} | ||
return { | ||
url: sourceMappingURL, | ||
map: sourceMapData | ||
}; | ||
}); | ||
function mapSourcePosition(position) { | ||
var sourceMap = sourceMapCache[position.source]; | ||
if (!sourceMap) { | ||
// Call the (overrideable) retrieveSourceMap function to get the source map. | ||
var urlAndMap = retrieveSourceMap(position.source); | ||
if (urlAndMap) { | ||
sourceMap = sourceMapCache[position.source] = { | ||
url: urlAndMap.url, | ||
map: new SourceMapConsumer(urlAndMap.map) | ||
}; | ||
// Load all sources stored inline with the source map into the file cache | ||
// to pretend like they are already loaded. They may not exist on disk. | ||
if (sourceMap.map.sourcesContent) { | ||
sourceMap.map.sources.forEach(function (source, i) { | ||
var contents = sourceMap.map.sourcesContent[i]; | ||
if (contents) { | ||
var url = supportRelativeURL(sourceMap.url, source); | ||
fileContentsCache[url] = contents; | ||
} | ||
}); | ||
} | ||
} else { | ||
sourceMap = sourceMapCache[position.source] = { | ||
url: null, | ||
map: null | ||
}; | ||
} | ||
} | ||
// Resolve the source URL relative to the URL of the source map | ||
if (sourceMap && sourceMap.map) { | ||
var originalPosition = sourceMap.map.originalPositionFor(position); | ||
// Only return the original position if a matching line was found. If no | ||
// matching line is found then we return position instead, which will cause | ||
// the stack trace to print the path and line for the compiled file. It is | ||
// better to give a precise location in the compiled file than a vague | ||
// location in the original file. | ||
if (originalPosition.source !== null) { | ||
originalPosition.source = supportRelativeURL( | ||
sourceMap.url, originalPosition.source); | ||
return originalPosition; | ||
} | ||
} | ||
return position; | ||
} | ||
// Parses code generated by FormatEvalOrigin(), a function inside V8: | ||
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js | ||
function mapEvalOrigin(origin) { | ||
// Most eval() calls are in this format | ||
var match = /^eval at ([^(]+) \((.+):(\d+):(\d+)\)$/.exec(origin); | ||
if (match) { | ||
var position = mapSourcePosition({ | ||
source: match[2], | ||
line: match[3], | ||
column: match[4] - 1 | ||
}); | ||
return 'eval at ' + match[1] + ' (' + position.source + ':' + | ||
position.line + ':' + (position.column + 1) + ')'; | ||
} | ||
// Parse nested eval() calls using recursion | ||
match = /^eval at ([^(]+) \((.+)\)$/.exec(origin); | ||
if (match) { | ||
return 'eval at ' + match[1] + ' (' + mapEvalOrigin(match[2]) + ')'; | ||
} | ||
// Make sure we still return useful information if we didn't find anything | ||
return origin; | ||
} | ||
// This is copied almost verbatim from the V8 source code at | ||
// https://code.google.com/p/v8/source/browse/trunk/src/messages.js. The | ||
// implementation of wrapCallSite() used to just forward to the actual source | ||
// code of CallSite.prototype.toString but unfortunately a new release of V8 | ||
// did something to the prototype chain and broke the shim. The only fix I | ||
// could find was copy/paste. | ||
function CallSiteToString() { | ||
var fileName; | ||
var fileLocation = ""; | ||
if (this.isNative()) { | ||
fileLocation = "native"; | ||
} else { | ||
fileName = this.getScriptNameOrSourceURL(); | ||
if (!fileName && this.isEval()) { | ||
fileLocation = this.getEvalOrigin(); | ||
fileLocation += ", "; // Expecting source position to follow. | ||
} | ||
if (fileName) { | ||
fileLocation += fileName; | ||
} else { | ||
// Source code does not originate from a file and is not native, but we | ||
// can still get the source position inside the source string, e.g. in | ||
// an eval string. | ||
fileLocation += "<anonymous>"; | ||
} | ||
var lineNumber = this.getLineNumber(); | ||
if (lineNumber != null) { | ||
fileLocation += ":" + lineNumber; | ||
var columnNumber = this.getColumnNumber(); | ||
if (columnNumber) { | ||
fileLocation += ":" + columnNumber; | ||
} | ||
} | ||
} | ||
var line = ""; | ||
var functionName = this.getFunctionName(); | ||
var addSuffix = true; | ||
var isConstructor = this.isConstructor(); | ||
var isMethodCall = !(this.isToplevel() || isConstructor); | ||
if (isMethodCall) { | ||
var typeName = this.getTypeName(); | ||
var methodName = this.getMethodName(); | ||
if (functionName) { | ||
if (typeName && functionName.indexOf(typeName) != 0) { | ||
line += typeName + "."; | ||
} | ||
line += functionName; | ||
if (methodName && functionName.indexOf("." + methodName) != functionName.length - methodName.length - 1) { | ||
line += " [as " + methodName + "]"; | ||
} | ||
} else { | ||
line += typeName + "." + (methodName || "<anonymous>"); | ||
} | ||
} else if (isConstructor) { | ||
line += "new " + (functionName || "<anonymous>"); | ||
} else if (functionName) { | ||
line += functionName; | ||
} else { | ||
line += fileLocation; | ||
addSuffix = false; | ||
} | ||
if (addSuffix) { | ||
line += " (" + fileLocation + ")"; | ||
} | ||
return line; | ||
} | ||
function cloneCallSite(frame) { | ||
var object = {}; | ||
Object.getOwnPropertyNames(Object.getPrototypeOf(frame)).forEach(function (name) { | ||
object[name] = /^(?:is|get)/.test(name) ? function () { return frame[name].call(frame); } : frame[name]; | ||
}); | ||
object.toString = CallSiteToString; | ||
return object; | ||
} | ||
function wrapCallSite(frame) { | ||
if (frame.isNative()) { | ||
return frame; | ||
} | ||
// Most call sites will return the source file from getFileName(), but code | ||
// passed to eval() ending in "//# sourceURL=..." will return the source file | ||
// from getScriptNameOrSourceURL() instead | ||
var source = frame.getFileName() || frame.getScriptNameOrSourceURL(); | ||
if (source) { | ||
var line = frame.getLineNumber(); | ||
var column = frame.getColumnNumber() - 1; | ||
// Fix position in Node where some (internal) code is prepended. | ||
// See https://github.com/evanw/node-source-map-support/issues/36 | ||
if (line === 1 && !isInBrowser() && !frame.isEval()) { | ||
column -= 62; | ||
} | ||
var position = mapSourcePosition({ | ||
source: source, | ||
line: line, | ||
column: column | ||
}); | ||
frame = cloneCallSite(frame); | ||
frame.getFileName = function () { return position.source; }; | ||
frame.getLineNumber = function () { return position.line; }; | ||
frame.getColumnNumber = function () { return position.column + 1; }; | ||
frame.getScriptNameOrSourceURL = function () { return position.source; }; | ||
return frame; | ||
} | ||
// Code called using eval() needs special handling | ||
var origin = frame.isEval() && frame.getEvalOrigin(); | ||
if (origin) { | ||
origin = mapEvalOrigin(origin); | ||
frame = cloneCallSite(frame); | ||
frame.getEvalOrigin = function () { return origin; }; | ||
return frame; | ||
} | ||
// If we get here then we were unable to change the source position | ||
return frame; | ||
} | ||
// This function is part of the V8 stack trace API, for more info see: | ||
// http://code.google.com/p/v8/wiki/JavaScriptStackTraceApi | ||
function prepareStackTrace(error, stack) { | ||
if (emptyCacheBetweenOperations) { | ||
fileContentsCache = {}; | ||
sourceMapCache = {}; | ||
} | ||
return error + stack.map(function (frame) { | ||
return '\n at ' + wrapCallSite(frame); | ||
}).join(''); | ||
} | ||
// Generate position and snippet of original source with pointer | ||
function getErrorSource(error) { | ||
var match = /\n at [^(]+ \((.*):(\d+):(\d+)\)/.exec(error.stack); | ||
if (match) { | ||
var source = match[1]; | ||
var line = +match[2]; | ||
var column = +match[3]; | ||
// Support the inline sourceContents inside the source map | ||
var contents = fileContentsCache[source]; | ||
// Support files on disk | ||
if (!contents && fs.existsSync(source)) { | ||
contents = fs.readFileSync(source, 'utf8'); | ||
} | ||
// Format the line from the original source code like node does | ||
if (contents) { | ||
var code = contents.split(/(?:\r\n|\r|\n)/)[line - 1]; | ||
if (code) { | ||
return source + ':' + line + '\n' + code + '\n' + | ||
new Array(column).join(' ') + '^'; | ||
} | ||
} | ||
} | ||
return null; | ||
} | ||
function printErrorAndExit(error) { | ||
var source = getErrorSource(error); | ||
if (source) { | ||
console.error(); | ||
console.error(source); | ||
} | ||
console.error(error.stack); | ||
process.exit(1); | ||
} | ||
function shimEmitUncaughtException() { | ||
var origEmit = process.emit; | ||
process.emit = function (type) { | ||
if (type === 'uncaughtException') { | ||
var hasStack = (arguments[1] && arguments[1].stack); | ||
var hasListeners = (this.listeners(type).length > 0); | ||
if (hasStack && !hasListeners) { | ||
return printErrorAndExit(arguments[1]); | ||
} | ||
} | ||
return origEmit.apply(this, arguments); | ||
}; | ||
} | ||
exports.wrapCallSite = wrapCallSite; | ||
exports.getErrorSource = getErrorSource; | ||
exports.mapSourcePosition = mapSourcePosition; | ||
exports.retrieveSourceMap = retrieveSourceMap; | ||
exports.install = function (options) { | ||
options = options || {}; | ||
if (options.environment) { | ||
environment = options.environment; | ||
if (["node", "browser", "auto"].indexOf(environment) === -1) { | ||
throw new Error("environment " + environment + " was unknown. Available options are {auto, browser, node}") | ||
} | ||
} | ||
// Allow sources to be found by methods other than reading the files | ||
// directly from disk. | ||
if (options.retrieveFile) { | ||
if (options.overrideRetrieveFile) { | ||
retrieveFileHandlers.length = 0; | ||
} | ||
retrieveFileHandlers.unshift(options.retrieveFile); | ||
} | ||
// Allow source maps to be found by methods other than reading the files | ||
// directly from disk. | ||
if (options.retrieveSourceMap) { | ||
if (options.overrideRetrieveSourceMap) { | ||
retrieveMapHandlers.length = 0; | ||
} | ||
retrieveMapHandlers.unshift(options.retrieveSourceMap); | ||
} | ||
// Configure options | ||
if (!emptyCacheBetweenOperations) { | ||
emptyCacheBetweenOperations = 'emptyCacheBetweenOperations' in options ? | ||
options.emptyCacheBetweenOperations : false; | ||
} | ||
// Install the error reformatter | ||
if (!errorFormatterInstalled) { | ||
errorFormatterInstalled = true; | ||
Error.prepareStackTrace = prepareStackTrace; | ||
} | ||
if (!uncaughtShimInstalled) { | ||
var installHandler = 'handleUncaughtExceptions' in options ? | ||
options.handleUncaughtExceptions : true; | ||
// Provide the option to not install the uncaught exception handler. This is | ||
// to support other uncaught exception handlers (in test frameworks, for | ||
// example). If this handler is not installed and there are no other uncaught | ||
// exception handlers, uncaught exceptions will be caught by node's built-in | ||
// exception handler and the process will still be terminated. However, the | ||
// generated JavaScript code will be shown above the stack trace instead of | ||
// the original source code. | ||
if (installHandler && hasGlobalProcessEventEmitter()) { | ||
uncaughtShimInstalled = true; | ||
shimEmitUncaughtException(); | ||
} | ||
} | ||
}; | ||
function addSourceMapToTSConfig() { | ||
// if a global __TS_CONFIG__ is set, update the compiler setting to include inline SourceMap | ||
var config = getTSConfig({ __TS_CONFIG__: __TS_CONFIG__ }); | ||
config.inlineSourceMap = true; | ||
return config; | ||
} | ||
module.exports = require('./dist/index'); |
{ | ||
"name": "ts-jest", | ||
"version": "0.1.7", | ||
"main": "index.ts", | ||
"version": "0.1.8", | ||
"main": "index.js", | ||
"types": "./dist/index.d.ts", | ||
"description": "A preprocessor with sourcemap support to help use Typescript with Jest", | ||
"scripts": { | ||
"build": "tsc -p .", | ||
"build:watch": "tsc -p . -w", | ||
"clean": "rimraf dist/**/*", | ||
"clean-build": "npm run clean && npm run build", | ||
"pretest": "npm run clean-build", | ||
"test": "node scripts/tests.js", | ||
"doc": "doctoc ." | ||
"doc": "doctoc .", | ||
"prepublish": "npm run clean-build" | ||
}, | ||
@@ -28,4 +38,7 @@ "repository": { | ||
"jest": { | ||
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(js)$", | ||
"scriptPreprocessor": "<rootDir>/node_modules/ts-jest/preprocessor.js", | ||
"mocksPattern": "__ts-jest-mocks__", | ||
"testRegex": "/__tests__/.*\\.(spec)\\.(ts|js)$", | ||
"moduleFileExtensions": [ | ||
"ts", | ||
"js" | ||
@@ -39,8 +52,18 @@ ] | ||
"devDependencies": { | ||
"react": "^15.3.2", | ||
"react-test-renderer": "^15.3.2", | ||
"jest": "16.0.1", | ||
"cross-spawn": "4.0.2", | ||
"doctoc": "^1.2.0" | ||
"@types/jest": "latest", | ||
"@types/react": "latest", | ||
"@types/source-map": "latest", | ||
"@types/node": "latest", | ||
"typescript": "latest", | ||
"tslint": "latest", | ||
"react": "latest", | ||
"react-test-renderer": "latest", | ||
"jest": "latest", | ||
"ts-jest": "latest", | ||
"cross-spawn": "latest", | ||
"rimraf": "latest", | ||
"doctoc": "latest" | ||
} | ||
} |
@@ -1,21 +0,1 @@ | ||
const tsc = require('typescript'); | ||
const {getTSConfig} = require('./utils'); | ||
module.exports = { | ||
process(src, path, config) { | ||
if (path.endsWith('.ts') || path.endsWith('.tsx')) { | ||
const transpiled = tsc.transpileModule( | ||
src, | ||
{ | ||
compilerOptions: getTSConfig(config.globals), | ||
fileName: path | ||
}); | ||
const modified = `require('ts-jest').install({environment: 'node', emptyCacheBetweenOperations: true});${transpiled.outputText}`; | ||
return modified; | ||
} | ||
return src; | ||
} | ||
}; | ||
module.exports = require('./dist/preprocessor'); |
@@ -82,3 +82,2 @@ # ts-jest | ||
``` | ||
> **Note:** On Windows machines you have to run `test` command with administrator privileges, because we have to create symlink for `ts-jest` in `node_modules` in order to correctly run integration tests. | ||
@@ -85,0 +84,0 @@ ## License |
{ | ||
"compilerOptions": { | ||
"target": "es5", | ||
"jsx": "react" | ||
"sourceMap": false, | ||
"declaration": true, | ||
"target": "ES5", | ||
"module": "commonjs", | ||
"moduleResolution": "node", | ||
"noEmitOnError": true, | ||
"noFallthroughCasesInSwitch": true, | ||
"noImplicitAny": false, | ||
"noImplicitReturns": true, | ||
"removeComments": true, | ||
"strictNullChecks": false, | ||
"jsx": "react", | ||
"emitDecoratorMetadata": true, | ||
"experimentalDecorators": true, | ||
"allowSyntheticDefaultImports": false, | ||
"outDir": "dist", | ||
"rootDir": "src" | ||
}, | ||
"include": [ | ||
"typings/index.d.ts" | ||
"src/**/*.ts", | ||
"src/**/*.tsx" | ||
], | ||
@@ -9,0 +25,0 @@ "exclude": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 3 instances in 1 package
2
-71.43%22509
-82.96%13
160%14
-6.67%499
-82.2%86
-1.15%2
Infinity%