Skip to content
Merged
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
9 changes: 5 additions & 4 deletions src/Bundle.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ExclusionRange } from './MagicString.ts'
import type { DecodedSourceMap, SourceMapOptions } from './SourceMap.ts'
import MagicString from './MagicString.ts'
import MagicStringError from './MagicStringError.ts'
import SourceMap from './SourceMap.ts'
import getLocator from './utils/getLocator.ts'
import getRelativePath from './utils/getRelativePath.ts'
Expand Down Expand Up @@ -72,9 +73,7 @@ export default class Bundle {
}

if (!isObject(source) || !source.content) {
throw new Error(
'bundle.addSource() takes an object with a `content` property, which should be an instance of MagicString, and an optional `filename`',
)
throw new MagicStringError('addSource() requires a `content` property that is a MagicString')
}

['filename', 'ignoreList', 'indentExclusionRanges', 'separator'].forEach((option) => {
Expand All @@ -95,7 +94,9 @@ export default class Bundle {
else {
const uniqueSource = this.uniqueSources[this.uniqueSourceIndexByFilename[source.filename]]
if (source.content.original !== uniqueSource.content) {
throw new Error(`Illegal source: same filename (${source.filename}), different contents`)
throw new MagicStringError(
`duplicate filename "${source.filename}" with different content, use unique filenames`,
)
}
}
}
Expand Down
104 changes: 59 additions & 45 deletions src/MagicString.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { DecodedSourceMap, SourceMapOptions } from './SourceMap.ts'
import BitSet from './BitSet.ts'
import Chunk from './Chunk.ts'
import MagicStringError from './MagicStringError.ts'
import SourceMap from './SourceMap.ts'
import getLocator from './utils/getLocator.ts'
import getRelativePath from './utils/getRelativePath.ts'
Expand Down Expand Up @@ -115,8 +116,9 @@ export default class MagicString {
* Appends the specified content to the end of the string.
*/
append(content: string): this {
if (typeof content !== 'string')
throw new TypeError('outro content must be a string')
if (typeof content !== 'string') {
throw new MagicStringError(`content must be a string, got ${typeof content}`)
}

this.outro += content
return this
Expand All @@ -130,8 +132,9 @@ export default class MagicString {
appendLeft(index: number, content: string): this {
index = index + this.offset

if (typeof content !== 'string')
throw new TypeError('inserted content must be a string')
if (typeof content !== 'string') {
throw new MagicStringError(`content must be a string, got ${typeof content}`)
}

if (DEBUG)
this.stats.time('appendLeft')
Expand Down Expand Up @@ -160,8 +163,9 @@ export default class MagicString {
appendRight(index: number, content: string): this {
index = index + this.offset

if (typeof content !== 'string')
throw new TypeError('inserted content must be a string')
if (typeof content !== 'string') {
throw new MagicStringError(`content must be a string, got ${typeof content}`)
}

if (DEBUG)
this.stats.time('appendRight')
Expand Down Expand Up @@ -444,9 +448,7 @@ export default class MagicString {

/** @internal */
insert(): never {
throw new Error(
'magicString.insert(...) is deprecated. Use prependRight(...) or appendLeft(...)',
)
throw new MagicStringError('insert() is deprecated, use appendLeft() or prependRight()')
}

/** @internal */
Expand Down Expand Up @@ -484,8 +486,9 @@ export default class MagicString {
if (start === end)
return this

if (index >= start && index <= end)
throw new Error('Cannot move a selection inside itself')
if (index >= start && index <= end) {
throw new MagicStringError('cannot move a selection inside itself')
}

if (DEBUG)
this.stats.time('move')
Expand Down Expand Up @@ -569,25 +572,29 @@ export default class MagicString {
start = start + this.offset
end = end + this.offset

if (typeof content !== 'string')
throw new TypeError('replacement content must be a string')
if (typeof content !== 'string') {
throw new MagicStringError(`content must be a string, got ${typeof content}`)
}

if (this.original.length !== 0) {
while (start < 0) start += this.original.length
while (end < 0) end += this.original.length
}

if (start < 0)
throw new Error('Character is out of bounds')
if (end > this.original.length)
throw new Error('end is out of bounds')
if (start < 0) {
throw new MagicStringError(`start ${start} is out of bounds`)
}
if (end > this.original.length) {
throw new MagicStringError(`end ${end} is out of bounds`)
}
if (start === end) {
throw new Error(
'Cannot overwrite a zero-length range use appendLeft or prependRight instead',
throw new MagicStringError(
`cannot overwrite a zero-length range at ${start}, use appendLeft() or prependRight()`,
)
}
if (start > end)
throw new Error(`end must be greater than start (start: ${start}, end: ${end})`)
if (start > end) {
throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`)
}

if (DEBUG)
this.stats.time('overwrite')
Expand Down Expand Up @@ -625,7 +632,7 @@ export default class MagicString {
let chunk = first
while (chunk !== last) {
if (chunk.next !== this.byStart.get(chunk.end)) {
throw new Error('Cannot overwrite across a split point')
throw new MagicStringError('cannot overwrite across a split point')
}
chunk = chunk.next
chunk.edit('', false)
Expand All @@ -651,8 +658,9 @@ export default class MagicString {
* Prepends the string with the specified content.
*/
prepend(content: string): this {
if (typeof content !== 'string')
throw new TypeError('outro content must be a string')
if (typeof content !== 'string') {
throw new MagicStringError(`content must be a string, got ${typeof content}`)
}

this.intro = content + this.intro
return this
Expand All @@ -664,8 +672,9 @@ export default class MagicString {
prependLeft(index: number, content: string): this {
index = index + this.offset

if (typeof content !== 'string')
throw new TypeError('inserted content must be a string')
if (typeof content !== 'string') {
throw new MagicStringError(`content must be a string, got ${typeof content}`)
}

if (DEBUG)
this.stats.time('insertRight')
Expand All @@ -692,8 +701,9 @@ export default class MagicString {
prependRight(index: number, content: string): this {
index = index + this.offset

if (typeof content !== 'string')
throw new TypeError('inserted content must be a string')
if (typeof content !== 'string') {
throw new MagicStringError(`content must be a string, got ${typeof content}`)
}

if (DEBUG)
this.stats.time('insertRight')
Expand Down Expand Up @@ -730,10 +740,12 @@ export default class MagicString {
if (start === end)
return this

if (start < 0 || end > this.original.length)
throw new Error('Character is out of bounds')
if (start > end)
throw new Error(`end must be greater than start (start: ${start}, end: ${end})`)
if (start < 0 || end > this.original.length) {
throw new MagicStringError(`range ${start}–${end} is out of bounds`)
}
if (start > end) {
throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`)
}

if (DEBUG)
this.stats.time('remove')
Expand Down Expand Up @@ -771,10 +783,12 @@ export default class MagicString {
if (start === end)
return this

if (start < 0 || end > this.original.length)
throw new Error('Character is out of bounds')
if (start > end)
throw new Error(`end must be greater than start (start: ${start}, end: ${end})`)
if (start < 0 || end > this.original.length) {
throw new MagicStringError(`range ${start}–${end} is out of bounds`)
}
if (start > end) {
throw new MagicStringError(`end must be greater than start (start: ${start}, end: ${end})`)
}

if (DEBUG)
this.stats.time('reset')
Expand Down Expand Up @@ -874,8 +888,9 @@ export default class MagicString {
chunk = chunk.next
}

if (chunk && chunk.edited && chunk.start !== start)
throw new Error(`Cannot use replaced character ${start} as slice start anchor.`)
if (chunk && chunk.edited && chunk.start !== start) {
throw new MagicStringError(`cannot use edited character ${start} as slice start anchor`)
}

const startChunk = chunk
while (chunk) {
Expand All @@ -884,8 +899,9 @@ export default class MagicString {
}

const containsEnd = chunk.start < end && chunk.end >= end
if (containsEnd && chunk.edited && chunk.end !== end)
throw new Error(`Cannot use replaced character ${end} as slice end anchor.`)
if (containsEnd && chunk.edited && chunk.end !== end) {
throw new MagicStringError(`cannot use edited character ${end} as slice end anchor`)
}

const sliceStart = startChunk === chunk ? start - chunk.start : 0
const sliceEnd = containsEnd ? chunk.content.length + end - chunk.end : chunk.content.length
Expand Down Expand Up @@ -949,8 +965,8 @@ export default class MagicString {
if (chunk.edited && chunk.content.length) {
// zero-length edited chunks are a special case (overlapping replacements)
const loc = getLocator(this.original)(index)
throw new Error(
`Cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`,
throw new MagicStringError(
`cannot split a chunk that has already been edited (${loc.line}:${loc.column} – "${chunk.original}")`,
)
}

Expand Down Expand Up @@ -1224,9 +1240,7 @@ export default class MagicString {
}

if (!searchValue.global) {
throw new TypeError(
'MagicString.prototype.replaceAll called with a non-global RegExp argument',
)
throw new MagicStringError('replaceAll() requires a global RegExp')
}

return this._replaceRegexp(searchValue, replacement)
Expand Down
13 changes: 13 additions & 0 deletions src/MagicStringError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/**
* The single error type thrown by MagicString.
*
* Every message is prefixed with `[MagicString]` so its source is obvious at a
* glance, and is kept short and consistent in tone.
*/
export default class MagicStringError extends Error {
override name = 'MagicStringError'

constructor(message: string, options?: ErrorOptions) {
super(`[MagicString] ${message}`, options)
}
}
3 changes: 2 additions & 1 deletion src/SourceMap.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { encode } from '@jridgewell/sourcemap-codec'
import MagicStringError from './MagicStringError.ts'

type Btoa = (str: string) => string

Expand Down Expand Up @@ -61,7 +62,7 @@ function getBtoa(): Btoa {
}

return () => {
throw new Error('Unsupported environment: `window.btoa` or `Buffer` should be supported.')
throw new MagicStringError('unsupported environment: `btoa` or `Buffer` is required')
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import Bundle from './Bundle.ts'
import MagicString from './MagicString.ts'
import MagicStringError from './MagicStringError.ts'
import SourceMap from './SourceMap.ts'

export { Bundle, MagicString as default, MagicString, SourceMap }
export { Bundle, MagicString as default, MagicString, MagicStringError, SourceMap }
export type { BundleOptions } from './Bundle.ts'
export type {
ExclusionRange,
Expand Down
Loading
Loading