Skip to content
This repository was archived by the owner on Nov 4, 2023. It is now read-only.

Rewrite async API to use promises #16

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .jshintrc
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"camelcase": true,
"curly": false,
"eqeqeq": true,
"es3": true,
"es3": false,
"esversion": 2016,
"forin": true,
"immed": false,
"indent": false,
Expand All @@ -30,6 +31,8 @@
"smarttabs": true,
"sub": true,

"loopfunc" : true,

"node": true,
"globals": {
"describe": false,
Expand Down
134 changes: 48 additions & 86 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ function customDecodeUriComponent(string) {
return decodeUriComponentLib(string.replace(/\+/g, "%2B"))
}

function callbackAsync(callback, error, result) {
setImmediate(function() { callback(error, result) })
}

function parseMapToJSON(string, data) {
try {
return JSON.parse(string.replace(/^\)\]\}'/, ""))
Expand Down Expand Up @@ -67,30 +63,22 @@ function getSourceMappingUrl(code) {



function resolveSourceMap(code, codeUrl, read, callback) {
var mapData
try {
mapData = resolveSourceMapHelper(code, codeUrl)
} catch (error) {
return callbackAsync(callback, error)
}
async function resolveSourceMap(code, codeUrl, read) {
var mapData = resolveSourceMapHelper(code, codeUrl)

if (!mapData || mapData.map) {
return callbackAsync(callback, null, mapData)
return mapData
}
var readUrl = customDecodeUriComponent(mapData.url)
read(readUrl, function(error, result) {
if (error) {
error.sourceMapData = mapData
return callback(error)
}
try {
const result = await read(readUrl)
mapData.map = String(result)
try {
mapData.map = parseMapToJSON(mapData.map, mapData)
} catch (error) {
return callback(error)
}
callback(null, mapData)
})
mapData.map = parseMapToJSON(mapData.map, mapData)
return mapData
} catch (error) {
error.sourceMapData = mapData
throw error
}
}

function resolveSourceMapSync(code, codeUrl, read) {
Expand Down Expand Up @@ -190,42 +178,32 @@ function resolveSourceMapHelper(code, codeUrl) {



function resolveSources(map, mapUrl, read, options, callback) {
if (typeof options === "function") {
callback = options
options = {}
}
var pending = map.sources ? map.sources.length : 0
async function resolveSources(map, mapUrl, read, options) {
var result = {
sourcesResolved: [],
sourcesContent: []
}

if (pending === 0) {
callbackAsync(callback, null, result)
return
}

var done = function() {
pending--
if (pending === 0) {
callback(null, result)
}
if (!map.sources || map.sources.length === 0) {
return result
}

resolveSourcesHelper(map, mapUrl, options, function(fullUrl, sourceContent, index) {
for (let {fullUrl, sourceContent, index} of resolveSourcesHelper(map, mapUrl, options)) {
result.sourcesResolved[index] = fullUrl
if (typeof sourceContent === "string") {
result.sourcesContent[index] = sourceContent
callbackAsync(done, null)
} else {
var readUrl = customDecodeUriComponent(fullUrl)
read(readUrl, function(error, source) {
result.sourcesContent[index] = error ? error : String(source)
done()
})
try {
const source = await read(readUrl)
result.sourcesContent[index] = String(source)
} catch (error) {
result.sourcesContent[index] = error
}
}
})
}

return result
}

function resolveSourcesSync(map, mapUrl, read, options) {
Expand All @@ -238,7 +216,7 @@ function resolveSourcesSync(map, mapUrl, read, options) {
return result
}

resolveSourcesHelper(map, mapUrl, options, function(fullUrl, sourceContent, index) {
for (let {fullUrl, sourceContent, index} of resolveSourcesHelper(map, mapUrl, options)) {
result.sourcesResolved[index] = fullUrl
if (read !== null) {
if (typeof sourceContent === "string") {
Expand All @@ -252,14 +230,14 @@ function resolveSourcesSync(map, mapUrl, read, options) {
}
}
}
})
}

return result
}

var endingSlash = /\/?$/

function resolveSourcesHelper(map, mapUrl, options, fn) {
function* resolveSourcesHelper(map, mapUrl, options) {
options = options || {}
mapUrl = convertWindowsPath(mapUrl)
var fullUrl
Expand All @@ -283,17 +261,13 @@ function resolveSourcesHelper(map, mapUrl, options, fn) {
fullUrl = resolveUrl(mapUrl, sourceRoot.replace(endingSlash, "/"), map.sources[index])
}
sourceContent = (map.sourcesContent || [])[index]
fn(fullUrl, sourceContent, index)
yield {fullUrl, sourceContent, index}
}
}



function resolve(code, codeUrl, read, options, callback) {
if (typeof options === "function") {
callback = options
options = {}
}
async function resolve(code, codeUrl, read, options) {
if (code === null) {
var mapUrl = codeUrl
var data = {
Expand All @@ -303,40 +277,28 @@ function resolve(code, codeUrl, read, options, callback) {
map: null
}
var readUrl = customDecodeUriComponent(mapUrl)
read(readUrl, function(error, result) {
if (error) {
error.sourceMapData = data
return callback(error)
}
try {
const result = await read(readUrl)
data.map = String(result)
try {
data.map = parseMapToJSON(data.map, data)
} catch (error) {
return callback(error)
}
_resolveSources(data)
})
data.map = parseMapToJSON(data.map, data)
return await _resolveSources(data)
} catch (error) {
error.sourceMapData = data
throw error
}
} else {
resolveSourceMap(code, codeUrl, read, function(error, mapData) {
if (error) {
return callback(error)
}
if (!mapData) {
return callback(null, null)
}
_resolveSources(mapData)
})
const mapData = await resolveSourceMap(code, codeUrl, read)
if (!mapData) {
return null
}
return await _resolveSources(mapData)
}

function _resolveSources(mapData) {
resolveSources(mapData.map, mapData.sourcesRelativeTo, read, options, function(error, result) {
if (error) {
return callback(error)
}
mapData.sourcesResolved = result.sourcesResolved
mapData.sourcesContent = result.sourcesContent
callback(null, mapData)
})
async function _resolveSources(mapData) {
const result = await resolveSources(mapData.map, mapData.sourcesRelativeTo, read, options)
mapData.sourcesResolved = result.sourcesResolved
mapData.sourcesContent = result.sourcesContent
return mapData
}
}

Expand Down
33 changes: 30 additions & 3 deletions test/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,39 @@ function asyncify(syncFn) {
setImmediate(function() {
try {
result = syncFn.apply(this, args)
callback(null, result)
} catch (error) {
return callback(error)
callback(error)
}
callback(null, result)
})
}
}

function enqueue() {
return new Promise(function (resolve) {
setImmediate(function() { resolve() })
})
}

function asyncifyPromise(asyncFn) {
return async function(...args) {
var callback = args.pop()
await enqueue()
try {
let result = await asyncFn(...args)
callback(null, result)
} catch (error) {
callback(error)
}
}
}

function makePromise(syncFn) {
return async function(...args) {
return await syncFn(...args)
}
}

module.exports = {
u1: u1,
u2: u2,
Expand All @@ -52,5 +77,7 @@ module.exports = {
read: read,
Throws: Throws,
identity: identity,
asyncify: asyncify
asyncify: asyncify,
makePromise: makePromise,
asyncifyPromise: asyncifyPromise
}
14 changes: 11 additions & 3 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ var read = common.read
var Throws = common.Throws
var identity = common.identity
var asyncify = common.asyncify
var makePromise = common.makePromise
var asyncifyPromise = common.asyncifyPromise

var sourceMapResolve = require("../")

Expand Down Expand Up @@ -97,7 +99,7 @@ var code = {

function testResolveSourceMap(method, sync) {
return function(t) {
var wrap = (sync ? identity : asyncify)
var wrap = (sync ? identity : makePromise)

var codeUrl = "http://example.com/a/b/c/foo.js"

Expand All @@ -107,6 +109,8 @@ function testResolveSourceMap(method, sync) {

if (sync) {
method = asyncify(method)
} else {
method = asyncifyPromise(method)
}

var next = false
Expand Down Expand Up @@ -358,7 +362,7 @@ test(".resolveSourceMapSync", testResolveSourceMap(sourceMapResolve.resolveSourc

function testResolveSources(method, sync) {
return function(t) {
var wrap = (sync ? identity : asyncify)
var wrap = (sync ? identity : makePromise)

var mapUrl = "http://example.com/a/b/c/foo.js.map"

Expand All @@ -368,6 +372,8 @@ function testResolveSources(method, sync) {

if (sync) {
method = asyncify(method)
} else {
method = asyncifyPromise(method)
}

var next = false
Expand Down Expand Up @@ -615,7 +621,7 @@ test(".resolveSourcesSync no read", function(t) {

function testResolve(method, sync) {
return function(t) {
var wrap = (sync ? identity : asyncify)
var wrap = (sync ? identity : makePromise)
var wrapMap = function(mapFn, fn) {
return wrap(function(url) {
if (/\.map$/.test(url)) {
Expand All @@ -633,6 +639,8 @@ function testResolve(method, sync) {

if (sync) {
method = asyncify(method)
} else {
method = asyncifyPromise(method)
}

var next = false
Expand Down
Loading