@ -4,8 +4,10 @@
import * as acorn from 'acorn' ;
import * as acorn from 'acorn' ;
import { walk } from 'zimmerframe' ;
import { walk } from 'zimmerframe' ;
import { tsPlugin } from '@sveltejs/acorn-typescript' ;
import { tsPlugin } from '@sveltejs/acorn-typescript' ;
import * as e from '../../errors.js' ;
const ParserWithTS = acorn . Parser . extend ( tsPlugin ( ) ) ;
const JSParser = acorn . Parser ;
const TSParser = JSParser . extend ( tsPlugin ( ) ) ;
/ * *
/ * *
* @ typedef { Comment & {
* @ typedef { Comment & {
@ -21,15 +23,15 @@ const ParserWithTS = acorn.Parser.extend(tsPlugin());
* @ param { boolean } [ is _script ]
* @ param { boolean } [ is _script ]
* /
* /
export function parse ( source , comments , typescript , is _script ) {
export function parse ( source , comments , typescript , is _script ) {
const parser = typescript ? ParserWithTS : acorn . Parser;
const acorn = typescript ? TSParser : JS Parser;
const { onComment , add _comments } = get _comment _handlers (
const { onComment , add _comments } = get _comment _handlers (
source ,
source ,
/** @type {CommentWithLocation[]} */ ( comments )
/** @type {CommentWithLocation[]} */ ( comments )
) ;
) ;
// @ts- ignore
// @ts- expect-error
const parse _statement = parser . prototype . parseStatement ;
const parse _statement = acorn . prototype . parseStatement ;
// If we're dealing with a <script> then it might contain an export
// If we're dealing with a <script> then it might contain an export
// for something that doesn't exist directly inside but is inside the
// for something that doesn't exist directly inside but is inside the
@ -37,7 +39,7 @@ export function parse(source, comments, typescript, is_script) {
// an error in these cases
// an error in these cases
if ( is _script ) {
if ( is _script ) {
// @ts-ignore
// @ts-ignore
parser . prototype . parseStatement = function ( ... args ) {
acorn . prototype . parseStatement = function ( ... args ) {
const v = parse _statement . call ( this , ... args ) ;
const v = parse _statement . call ( this , ... args ) ;
// @ts-ignore
// @ts-ignore
this . undefinedExports = { } ;
this . undefinedExports = { } ;
@ -45,25 +47,27 @@ export function parse(source, comments, typescript, is_script) {
} ;
} ;
}
}
let ast ;
try {
try {
ast = parser . parse ( source , {
const ast = acorn . parse ( source , {
onComment ,
onComment ,
sourceType : 'module' ,
sourceType : 'module' ,
ecmaVersion : 16 ,
ecmaVersion : 16 ,
locations : true
locations : true
} ) ;
} ) ;
} finally {
if ( is _script ) {
// @ts-ignore
parser . prototype . parseStatement = parse _statement ;
}
}
add _comments ( ast ) ;
add _comments ( ast ) ;
return /** @type {Program} */ ( ast ) ;
return /** @type {Program} */ ( ast ) ;
} catch ( err ) {
// TODO the `return` in necessary for TS<7 due to a bug; otherwise
// the `finally` block is regarded as unreachable
return handle _parse _error ( err ) ;
} finally {
if ( is _script ) {
// @ts-expect-error
acorn . prototype . parseStatement = parse _statement ;
}
}
}
}
/ * *
/ * *
@ -73,11 +77,12 @@ export function parse(source, comments, typescript, is_script) {
* @ returns { acorn . Expression & { leadingComments ? : CommentWithLocation [ ] ; trailingComments ? : CommentWithLocation [ ] ; } }
* @ returns { acorn . Expression & { leadingComments ? : CommentWithLocation [ ] ; trailingComments ? : CommentWithLocation [ ] ; } }
* /
* /
export function parse _expression _at ( parser , source , index ) {
export function parse _expression _at ( parser , source , index ) {
const _ = parser . ts ? ParserWithTS : acorn . Parser;
const acorn = parser . ts ? TSParser : JS Parser;
const { onComment , add _comments } = get _comment _handlers ( source , parser . root . comments , index ) ;
const { onComment , add _comments } = get _comment _handlers ( source , parser . root . comments , index ) ;
const ast = _ . parseExpressionAt ( source , index , {
try {
const ast = acorn . parseExpressionAt ( source , index , {
onComment ,
onComment ,
sourceType : 'module' ,
sourceType : 'module' ,
ecmaVersion : 16 ,
ecmaVersion : 16 ,
@ -88,6 +93,19 @@ export function parse_expression_at(parser, source, index) {
add _comments ( ast ) ;
add _comments ( ast ) ;
return ast ;
return ast ;
} catch ( e ) {
handle _parse _error ( e ) ;
}
}
const regex _position _indicator = / \(\d+:\d+\)$/ ;
/ * *
* @ param { any } err
* @ returns { never }
* /
function handle _parse _error ( err ) {
e . js _parse _error ( err . pos , err . message . replace ( regex _position _indicator , '' ) ) ;
}
}
/ * *
/ * *