Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

get-source

Package Overview
Dependencies
Maintainers
2
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

get-source - npm Package Compare versions

Comparing version 1.0.42 to 2.0.0

impl/SyncPromise.js

238

get-source.js

@@ -5,7 +5,7 @@ "use strict";

const O = Object,
const { assign } = Object,
isBrowser = (typeof window !== 'undefined') && (window.window === window) && window.navigator,
SourceMapConsumer = require ('source-map').SourceMapConsumer,
SyncPromise = require ('./impl/SyncPromise'),
path = require ('./impl/path'),
isURL = path.isURL,
dataURIToBuffer = require ('data-uri-to-buffer')

@@ -24,145 +24,135 @@

/* ------------------------------------------------------------------------ */
function impl (fetchFile, sync) {
const PromiseImpl = sync ? SyncPromise : Promise
const SourceFileMemoized = memoize (path => SourceFile (path, fetchFile (path)))
const newSourceFileMemoized = memoize (file => new SourceFile (file))
function SourceFile (srcPath, text) {
if (text === undefined) return SourceFileMemoized (path.resolve (srcPath))
const getSource = module.exports = file => { return newSourceFileMemoized (path.resolve (file)) }
return PromiseImpl.resolve (text).then (text => {
getSource.resetCache = () => newSourceFileMemoized.forgetEverything ()
getSource.getCache = () => newSourceFileMemoized.cache
let file
let lines
let resolver
let _resolve = loc => (resolver = resolver || SourceMapResolverFromFetchedFile (file)) (loc)
/* ------------------------------------------------------------------------ */
return (file = {
path: srcPath,
text,
get lines () { return lines = (lines || text.split ('\n')) },
resolve (loc) {
const result = _resolve (loc)
if (sync) {
try { return SyncPromise.valueFrom (result) }
catch (e) { return assign ({}, loc, { error: e }) }
}
return result
},
_resolve,
})
})
}
class SourceMap {
function SourceMapResolverFromFetchedFile (file) {
constructor (originalFilePath, sourceMapPath) {
/* Extract the last sourceMap occurence (TODO: support multiple sourcemaps) */
this.file = sourceMapPath.startsWith ('data:')
? new SourceFile (originalFilePath, dataURIToBuffer (sourceMapPath).toString ())
: getSource (path.relativeToFile (originalFilePath, sourceMapPath))
const re = /\u0023 sourceMappingURL=(.+)\n?/g
let lastMatch = undefined
this.parsed = (this.file.text && SourceMapConsumer (JSON.parse (this.file.text))) || null
this.sourceFor = memoize (this.sourceFor.bind (this))
}
while (true) {
const match = re.exec (file.text)
if (match) lastMatch = match
else break
}
sourceFor (file) {
const content = this.parsed.sourceContentFor (file, true /* return null on missing */)
const fullPath = path.relativeToFile (this.file.path, file)
return content ? new SourceFile (fullPath, content) : getSource (fullPath)
}
const url = lastMatch && lastMatch[1]
resolve (loc) {
const defaultResolver = loc => assign ({}, loc, {
sourceFile: file,
sourceLine: (file.lines[loc.line - 1] || '')
})
const originalLoc = this.parsed.originalPositionFor (loc)
return originalLoc.source ? this.sourceFor (originalLoc.source)
.resolve (O.assign ({}, loc, {
line: originalLoc.line,
column: originalLoc.column + 1,
name: originalLoc.name
}))
: loc
return url ? SourceMapResolver (file.path, url, defaultResolver)
: defaultResolver
}
}
/* ------------------------------------------------------------------------ */
function SourceMapResolver (originalFilePath, sourceMapPath, fallbackResolve) {
const srcFile = sourceMapPath.startsWith ('data:')
? SourceFile (originalFilePath, dataURIToBuffer (sourceMapPath).toString ())
: SourceFile (path.relativeToFile (originalFilePath, sourceMapPath))
class SourceFile {
constructor (path, text /* optional */) {
this.path = path
if (text) {
this.text = text
} else {
try {
if (isBrowser) {
let xhr = new XMLHttpRequest ()
xhr.open ('GET', path, false /* SYNCHRONOUS XHR FTW :) */)
xhr.send (null)
this.text = xhr.responseText
} else {
this.text = module.require ('fs').readFileSync (path, { encoding: 'utf8' })
// this.text = isURL (path)
// ? module.require ('child_process').execSync (`curl ${path}`).toString ('UTF8')
// : module.require ('fs').readFileSync (path, { encoding: 'utf8' })
}
} catch (e) {
this.error = e
this.text = ''
}
}
const parsedMap = srcFile.then (f => SourceMapConsumer (JSON.parse (f.text)))
const sourceFor = memoize (function sourceFor (filePath) {
return srcFile.then (f => {
const fullPath = path.relativeToFile (f.path, filePath)
return parsedMap.then (x => SourceFile (
fullPath,
x.sourceContentFor (filePath, true /* return null on missing */) || undefined))
})
})
return loc => parsedMap.then (x => {
const originalLoc = x.originalPositionFor (loc)
return originalLoc.source ? sourceFor (originalLoc.source).then (x =>
x._resolve (assign ({}, loc, {
line: originalLoc.line,
column: originalLoc.column + 1,
name: originalLoc.name
}))
)
: fallbackResolve (loc)
}).catch (e =>
assign (fallbackResolve (loc), { sourceMapError: e }))
}
get lines () {
return (this.lines_ = this.lines_ || this.text.split ('\n'))
}
return assign (function getSource (path) {
const file = SourceFile (path)
if (sync) {
try { return SyncPromise.valueFrom (file) }
catch (e) { return {
path, text: '', error: e,
resolve (loc) { return assign ({}, loc, { error: e, sourceLine: '', sourceFile: '' }) }
} }
}
return file
}, {
resetCache: () => SourceFileMemoized.forgetEverything (),
getCache: () => SourceFileMemoized.cache
})
}
get sourceMap () {
/* ------------------------------------------------------------------------ */
try {
module.exports = impl (function fetchFileSync (path) {
return new SyncPromise (resolve => {
if (isBrowser) {
let xhr = new XMLHttpRequest ()
xhr.open ('GET', path, false /* SYNCHRONOUS XHR FTW :) */)
xhr.send (null)
resolve (xhr.responseText)
} else {
resolve (module.require ('fs').readFileSync (path, { encoding: 'utf8' }))
}
})
}, true)
if (this.sourceMap_ === undefined) {
/* ------------------------------------------------------------------------ */
/* Extract the last sourceMap occurence (TODO: support multiple sourcemaps) */
module.exports.async = impl (function fetchFileAsync (path) {
if (isBrowser) {
return fetch (path).then (x => x.text ())
} else {
return new Promise ((resolve, reject) => {
module.require ('fs').readFile (path, { encoding: 'utf8' }, (e, x) => {
e ? reject (e) : resolve (x)
})
})
}
})
const re = /\u0023 sourceMappingURL=(.+)\n?/g
let lastMatch = undefined
while (true) {
const match = re.exec (this.text)
if (match) lastMatch = match
else break
}
const url = lastMatch && lastMatch[1]
if (url) {
const sourceMap = new SourceMap (this.path, url)
if (sourceMap.parsed) {
this.sourceMap_ = sourceMap
}
} else {
this.sourceMap_ = null
}
}
}
catch (e) {
this.sourceMap_ = null
this.sourceMapError = e
}
return this.sourceMap_
}
resolve (loc /* { line[, column] } */) /* → { line, column, sourceFile, sourceLine } */ {
if (this.sourceMap) {
const newLoc = this.sourceMap.resolve (loc)
if (newLoc.sourceFile) return newLoc
}
return O.assign ({}, loc, {
sourceFile: this,
sourceLine: (this.lines[loc.line - 1] || ''),
error: this.error
})
}
}
/* ------------------------------------------------------------------------ */
{
"name": "get-source",
"version": "1.0.42",
"version": "2.0.0",
"description": "Platform-agnostic source code inspection, with sourcemaps support",

@@ -31,10 +31,8 @@ "main": "get-source",

"chai": "^3.5.0",
"chromedriver": "^2.46.0",
"coveralls": "^3.0.3",
"istanbul": "^0.4.5",
"memory-fs": "^0.3.0",
"mocha": "^6.0.2",
"nyc": "^13.3.0",
"selenium-webdriver": "^3.6.0",
"webpack": "^3.12.0"
"mocha": "^8.0.1",
"nyc": "^15.1.0",
"webpack": "^4.43.0"
},

@@ -41,0 +39,0 @@ "dependencies": {

@@ -15,3 +15,4 @@ # get-source

- [x] Full sourcemap support (path resolving, external/embedded/inline linking, and long chains)
- [x] **Synchronous** API — which is good when you implement a debugging tool (e.g. [logging](https://github.com/xpl/ololog))
- [x] **Synchronous** API — good for CLI tools (e.g. [logging](https://github.com/xpl/ololog)). Works in browsers!
- [x] **Asynchronous** API — good for everything web!
- [x] Built-in cache

@@ -30,2 +31,5 @@

```
### Synchronous
```javascript

@@ -62,4 +66,13 @@ file = getSource ('./scripts/index.min.js')

### Asynchronous
```javascript
file = await getSource.async ('./scripts/index.min.js')
location = await file.resolve ({ line: 1, column: 8 })
```
## Error handling
In synchronous mode, it never throws (due to backward compatibility reasons with existing code):
```javascript

@@ -77,1 +90,28 @@ nonsense = getSource ('/some/nonexistent/file')

```
In asychronous mode, it throws an error:
```javascript
try {
file = await getSource.async ('/some/file')
location = await file.resolve ({ line: 5, column: 0 })
} catch (e) {
...
}
```
## Resetting Cache
E.g. when you need to force-reload files:
```javascript
getSource.resetCache () // sync cache
getSource.async.resetCache () // async cache
```
Also, viewing cached files:
```javascript
getSource.getCache () // sync cache
getSource.async.getCache () // async cache
```

@@ -19,4 +19,4 @@ "use strict";

getSource ('./test.js').should.equal (getSource ('./test.js'))
getSource ('./test.js').should.not.equal (getSource ('./package.json'))
getSource ('./get-source.js').should.equal (getSource ('./get-source.js'))
getSource ('./get-source.js').should.not.equal (getSource ('./package.json'))
})

@@ -56,4 +56,4 @@

uglified.sourceMap.should.not.equal (undefined)
uglified.sourceMap.should.equal (uglified.sourceMap) // memoization should work
// uglified.sourceMap.should.not.equal (undefined)
// uglified.sourceMap.should.equal (uglified.sourceMap) // memoization should work

@@ -68,2 +68,30 @@ const resolved = uglified.resolve ({ line: 1, column: 18 }) // should be tolerant to column omission

it ('reads sources (sourcemapped, with external links) — ASYNC', () => {
const uglified = getSource.async ('./test/files/original.uglified.js')
return uglified.then (uglified => {
uglified.path.should.equal (path.resolve ('./test/files/original.uglified.js'))
uglified.lines.should.deep.equal ([
'function hello(){return"hello world"}',
'//# sourceMappingURL=original.uglified.js.map',
''
])
// uglified.sourceMap.should.not.equal (undefined)
// uglified.sourceMap.should.equal (uglified.sourceMap) // memoization should work
return uglified.resolve ({ line: 1, column: 18 }).then (resolved => {
return getSource.async ('./test/files/original.js').then (originalFile => {
resolved.line.should.equal (4)
resolved.column.should.equal (2)
resolved.sourceFile.should.equal (originalFile)
resolved.sourceLine.should.equal ('\treturn \'hello world\' }')
})
})
})
})
it ('reads sources (sourcemapped, with embedded sources)', () => {

@@ -80,3 +108,3 @@

uglified.sourceMap.should.not.equal (undefined)
// uglified.sourceMap.should.not.equal (undefined)

@@ -95,4 +123,4 @@ const resolved = uglified.resolve ({ line: 1, column: 18 })

babeled.sourceMap.should.not.equal (undefined)
babeled.sourceMap.file.path.should.equal (babeled.path)
// babeled.sourceMap.should.not.equal (undefined)
// babeled.sourceMap.file.path.should.equal (babeled.path)

@@ -115,3 +143,3 @@ const resolved = babeled.resolve ({ line: 6, column: 1 })

beautified.sourceMap.should.not.equal (undefined)
// beautified.sourceMap.should.not.equal (undefined)

@@ -126,2 +154,21 @@ const resolved = beautified.resolve ({ line: 2, column: 4 })

it ('supports even CHAINED sourcemaps! — ASYNC', () => {
/* original.js → original.uglified.js → original.uglified.beautified.js */
return getSource.async ('./test/files/original.uglified.beautified.js').then (beautified => {
beautified.text.should.equal (fs.readFileSync ('./test/files/original.uglified.beautified.js', { encoding: 'utf-8' }))
beautified.path.should.equal (path.resolve ('./test/files/original.uglified.beautified.js'))
return beautified.resolve ({ line: 2, column: 4 }).then (resolved => {
resolved.line.should.equal (4)
resolved.column.should.equal (2)
resolved.sourceFile.path.should.equal (path.resolve ('./test/files/original.js'))
resolved.sourceLine.should.equal ('\treturn \'hello world\' }')
})
})
})
it ('does some error handling', () => {

@@ -140,5 +187,12 @@

it ('does some error handling - ASYNC', () => {
return getSource.async ('abyrvalg').then (x => { console.log (x) }).catch (error => {
error.should.be.an.instanceof (Error)
})
})
it ('allows absolute paths', () => {
getSource (require ('path').resolve ('./test.js')).should.equal (getSource ('./test.js'))
getSource (require ('path').resolve ('./get-source.js')).should.equal (getSource ('./get-source.js'))
})

@@ -149,3 +203,3 @@

const files =
[ './test.js',
[ './get-source.js',
'./package.json',

@@ -152,0 +206,0 @@ './test/files/original.js',

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc