mirror of https://github.com/sveltejs/svelte
parent
870b75b141
commit
a4e38d5305
@ -0,0 +1,571 @@
|
||||
// Type definitions for ESTree AST specification
|
||||
// Project: https://github.com/estree/estree
|
||||
// Definitions by: RReverser <https://github.com/RReverser>
|
||||
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
|
||||
|
||||
// This definition file follows a somewhat unusual format. ESTree allows
|
||||
// runtime type checks based on the `type` parameter. In order to explain this
|
||||
// to typescript we want to use discriminated union types:
|
||||
// https://github.com/Microsoft/TypeScript/pull/9163
|
||||
//
|
||||
// For ESTree this is a bit tricky because the high level interfaces like
|
||||
// Node or Function are pulling double duty. We want to pass common fields down
|
||||
// to the interfaces that extend them (like Identifier or
|
||||
// ArrowFunctionExpression), but you can't extend a type union or enforce
|
||||
// common fields on them. So we've split the high level interfaces into two
|
||||
// types, a base type which passes down inhereted fields, and a type union of
|
||||
// all types which extend the base type. Only the type union is exported, and
|
||||
// the union is how other types refer to the collection of inheriting types.
|
||||
//
|
||||
// This makes the definitions file here somewhat more difficult to maintain,
|
||||
// but it has the notable advantage of making ESTree much easier to use as
|
||||
// an end user.
|
||||
|
||||
interface BaseNodeWithoutComments {
|
||||
// Every leaf interface that extends BaseNode must specify a type property.
|
||||
// The type property should be a string literal. For example, Identifier
|
||||
// has: `type: "Identifier"`
|
||||
type: string;
|
||||
loc?: SourceLocation | null;
|
||||
range?: [number, number];
|
||||
}
|
||||
|
||||
interface BaseNode extends BaseNodeWithoutComments {
|
||||
leadingComments?: Array<Comment>;
|
||||
trailingComments?: Array<Comment>;
|
||||
}
|
||||
|
||||
export type Node =
|
||||
Identifier | Literal | Program | Function | SwitchCase | CatchClause |
|
||||
VariableDeclarator | Statement | Expression | Property |
|
||||
AssignmentProperty | Super | TemplateElement | SpreadElement | Pattern |
|
||||
ClassBody | Class | MethodDefinition | ModuleDeclaration | ModuleSpecifier;
|
||||
|
||||
export interface Comment extends BaseNodeWithoutComments {
|
||||
type: "Line" | "Block";
|
||||
value: string;
|
||||
}
|
||||
|
||||
interface SourceLocation {
|
||||
source?: string | null;
|
||||
start: Position;
|
||||
end: Position;
|
||||
}
|
||||
|
||||
export interface Position {
|
||||
/** >= 1 */
|
||||
line: number;
|
||||
/** >= 0 */
|
||||
column: number;
|
||||
}
|
||||
|
||||
export interface Program extends BaseNode {
|
||||
type: "Program";
|
||||
sourceType: "script" | "module";
|
||||
body: Array<Directive | Statement | ModuleDeclaration>;
|
||||
comments?: Array<Comment>;
|
||||
}
|
||||
|
||||
export interface Directive extends BaseNode {
|
||||
type: "ExpressionStatement";
|
||||
expression: Literal;
|
||||
directive: string;
|
||||
}
|
||||
|
||||
interface BaseFunction extends BaseNode {
|
||||
params: Array<Pattern>;
|
||||
generator?: boolean;
|
||||
async?: boolean;
|
||||
// The body is either BlockStatement or Expression because arrow functions
|
||||
// can have a body that's either. FunctionDeclarations and
|
||||
// FunctionExpressions have only BlockStatement bodies.
|
||||
body: BlockStatement | Expression;
|
||||
}
|
||||
|
||||
export type Function =
|
||||
FunctionDeclaration | FunctionExpression | ArrowFunctionExpression;
|
||||
|
||||
export type Statement =
|
||||
ExpressionStatement | BlockStatement | EmptyStatement |
|
||||
DebuggerStatement | WithStatement | ReturnStatement | LabeledStatement |
|
||||
BreakStatement | ContinueStatement | IfStatement | SwitchStatement |
|
||||
ThrowStatement | TryStatement | WhileStatement | DoWhileStatement |
|
||||
ForStatement | ForInStatement | ForOfStatement | Declaration;
|
||||
|
||||
interface BaseStatement extends BaseNode { }
|
||||
|
||||
export interface EmptyStatement extends BaseStatement {
|
||||
type: "EmptyStatement";
|
||||
}
|
||||
|
||||
export interface BlockStatement extends BaseStatement {
|
||||
type: "BlockStatement";
|
||||
body: Array<Statement>;
|
||||
innerComments?: Array<Comment>;
|
||||
}
|
||||
|
||||
export interface ExpressionStatement extends BaseStatement {
|
||||
type: "ExpressionStatement";
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export interface IfStatement extends BaseStatement {
|
||||
type: "IfStatement";
|
||||
test: Expression;
|
||||
consequent: Statement;
|
||||
alternate?: Statement | null;
|
||||
}
|
||||
|
||||
export interface LabeledStatement extends BaseStatement {
|
||||
type: "LabeledStatement";
|
||||
label: Identifier;
|
||||
body: Statement;
|
||||
}
|
||||
|
||||
export interface BreakStatement extends BaseStatement {
|
||||
type: "BreakStatement";
|
||||
label?: Identifier | null;
|
||||
}
|
||||
|
||||
export interface ContinueStatement extends BaseStatement {
|
||||
type: "ContinueStatement";
|
||||
label?: Identifier | null;
|
||||
}
|
||||
|
||||
export interface WithStatement extends BaseStatement {
|
||||
type: "WithStatement";
|
||||
object: Expression;
|
||||
body: Statement;
|
||||
}
|
||||
|
||||
export interface SwitchStatement extends BaseStatement {
|
||||
type: "SwitchStatement";
|
||||
discriminant: Expression;
|
||||
cases: Array<SwitchCase>;
|
||||
}
|
||||
|
||||
export interface ReturnStatement extends BaseStatement {
|
||||
type: "ReturnStatement";
|
||||
argument?: Expression | null;
|
||||
}
|
||||
|
||||
export interface ThrowStatement extends BaseStatement {
|
||||
type: "ThrowStatement";
|
||||
argument: Expression;
|
||||
}
|
||||
|
||||
export interface TryStatement extends BaseStatement {
|
||||
type: "TryStatement";
|
||||
block: BlockStatement;
|
||||
handler?: CatchClause | null;
|
||||
finalizer?: BlockStatement | null;
|
||||
}
|
||||
|
||||
export interface WhileStatement extends BaseStatement {
|
||||
type: "WhileStatement";
|
||||
test: Expression;
|
||||
body: Statement;
|
||||
}
|
||||
|
||||
export interface DoWhileStatement extends BaseStatement {
|
||||
type: "DoWhileStatement";
|
||||
body: Statement;
|
||||
test: Expression;
|
||||
}
|
||||
|
||||
export interface ForStatement extends BaseStatement {
|
||||
type: "ForStatement";
|
||||
init?: VariableDeclaration | Expression | null;
|
||||
test?: Expression | null;
|
||||
update?: Expression | null;
|
||||
body: Statement;
|
||||
}
|
||||
|
||||
interface BaseForXStatement extends BaseStatement {
|
||||
left: VariableDeclaration | Pattern;
|
||||
right: Expression;
|
||||
body: Statement;
|
||||
}
|
||||
|
||||
export interface ForInStatement extends BaseForXStatement {
|
||||
type: "ForInStatement";
|
||||
}
|
||||
|
||||
export interface DebuggerStatement extends BaseStatement {
|
||||
type: "DebuggerStatement";
|
||||
}
|
||||
|
||||
export type Declaration =
|
||||
FunctionDeclaration | VariableDeclaration | ClassDeclaration;
|
||||
|
||||
interface BaseDeclaration extends BaseStatement { }
|
||||
|
||||
export interface FunctionDeclaration extends BaseFunction, BaseDeclaration {
|
||||
type: "FunctionDeclaration";
|
||||
/** It is null when a function declaration is a part of the `export default function` statement */
|
||||
id: Identifier | null;
|
||||
body: BlockStatement;
|
||||
}
|
||||
|
||||
export interface VariableDeclaration extends BaseDeclaration {
|
||||
type: "VariableDeclaration";
|
||||
declarations: Array<VariableDeclarator>;
|
||||
kind: "var" | "let" | "const";
|
||||
}
|
||||
|
||||
export interface VariableDeclarator extends BaseNode {
|
||||
type: "VariableDeclarator";
|
||||
id: Pattern;
|
||||
init?: Expression | null;
|
||||
}
|
||||
|
||||
// BOOKMARK(@littledivy) - we had to manipulate estree source :eyes:
|
||||
export type Expression =
|
||||
ThisExpression | ArrayExpression | ObjectExpression | FunctionExpression |
|
||||
ArrowFunctionExpression | YieldExpression | Literal | UnaryExpression |
|
||||
UpdateExpression | BinaryExpression | AssignmentExpression |
|
||||
LogicalExpression | MemberExpression | ConditionalExpression |
|
||||
CallExpression | NewExpression | SequenceExpression | TemplateLiteral |
|
||||
TaggedTemplateExpression | ClassExpression | MetaProperty | Identifier |
|
||||
AwaitExpression | ImportExpression | ChainExpression;
|
||||
|
||||
export interface BaseExpression extends BaseNode { }
|
||||
|
||||
type ChainElement = SimpleCallExpression | MemberExpression;
|
||||
|
||||
export interface ChainExpression extends BaseExpression {
|
||||
type: "ChainExpression";
|
||||
expression: ChainElement;
|
||||
}
|
||||
|
||||
export interface ThisExpression extends BaseExpression {
|
||||
type: "ThisExpression";
|
||||
}
|
||||
|
||||
export interface ArrayExpression extends BaseExpression {
|
||||
type: "ArrayExpression";
|
||||
elements: Array<Expression | SpreadElement>;
|
||||
}
|
||||
|
||||
export interface ObjectExpression extends BaseExpression {
|
||||
type: "ObjectExpression";
|
||||
properties: Array<Property | SpreadElement>;
|
||||
}
|
||||
|
||||
export interface Property extends BaseNode {
|
||||
type: "Property";
|
||||
key: Expression;
|
||||
value: Expression | Pattern; // Could be an AssignmentProperty
|
||||
kind: "init" | "get" | "set";
|
||||
method: boolean;
|
||||
shorthand: boolean;
|
||||
computed: boolean;
|
||||
}
|
||||
|
||||
export interface FunctionExpression extends BaseFunction, BaseExpression {
|
||||
id?: Identifier | null;
|
||||
type: "FunctionExpression";
|
||||
body: BlockStatement;
|
||||
}
|
||||
|
||||
export interface SequenceExpression extends BaseExpression {
|
||||
type: "SequenceExpression";
|
||||
expressions: Array<Expression>;
|
||||
}
|
||||
|
||||
export interface UnaryExpression extends BaseExpression {
|
||||
type: "UnaryExpression";
|
||||
operator: UnaryOperator;
|
||||
prefix: true;
|
||||
argument: Expression;
|
||||
}
|
||||
|
||||
export interface BinaryExpression extends BaseExpression {
|
||||
type: "BinaryExpression";
|
||||
operator: BinaryOperator;
|
||||
left: Expression;
|
||||
right: Expression;
|
||||
}
|
||||
|
||||
export interface AssignmentExpression extends BaseExpression {
|
||||
type: "AssignmentExpression";
|
||||
operator: AssignmentOperator;
|
||||
left: Pattern | MemberExpression;
|
||||
right: Expression;
|
||||
}
|
||||
|
||||
export interface UpdateExpression extends BaseExpression {
|
||||
type: "UpdateExpression";
|
||||
operator: UpdateOperator;
|
||||
argument: Expression;
|
||||
prefix: boolean;
|
||||
}
|
||||
|
||||
export interface LogicalExpression extends BaseExpression {
|
||||
type: "LogicalExpression";
|
||||
operator: LogicalOperator;
|
||||
left: Expression;
|
||||
right: Expression;
|
||||
}
|
||||
|
||||
export interface ConditionalExpression extends BaseExpression {
|
||||
type: "ConditionalExpression";
|
||||
test: Expression;
|
||||
alternate: Expression;
|
||||
consequent: Expression;
|
||||
}
|
||||
|
||||
interface BaseCallExpression extends BaseExpression {
|
||||
callee: Expression | Super;
|
||||
arguments: Array<Expression | SpreadElement>;
|
||||
}
|
||||
export type CallExpression = SimpleCallExpression | NewExpression;
|
||||
|
||||
export interface SimpleCallExpression extends BaseCallExpression {
|
||||
type: "CallExpression";
|
||||
optional: boolean;
|
||||
}
|
||||
|
||||
export interface NewExpression extends BaseCallExpression {
|
||||
type: "NewExpression";
|
||||
}
|
||||
|
||||
export interface MemberExpression extends BaseExpression, BasePattern {
|
||||
type: "MemberExpression";
|
||||
object: Expression | Super;
|
||||
property: Expression;
|
||||
computed: boolean;
|
||||
optional: boolean;
|
||||
}
|
||||
|
||||
export type Pattern =
|
||||
Identifier | ObjectPattern | ArrayPattern | RestElement |
|
||||
AssignmentPattern | MemberExpression;
|
||||
|
||||
// BOOKMARK(@littledivy): Had to manipulate estree source
|
||||
export interface BasePattern extends BaseNode { }
|
||||
|
||||
export interface SwitchCase extends BaseNode {
|
||||
type: "SwitchCase";
|
||||
test?: Expression | null;
|
||||
consequent: Array<Statement>;
|
||||
}
|
||||
|
||||
export interface CatchClause extends BaseNode {
|
||||
type: "CatchClause";
|
||||
param: Pattern | null;
|
||||
body: BlockStatement;
|
||||
}
|
||||
|
||||
export interface Identifier extends BaseNode, BaseExpression, BasePattern {
|
||||
type: "Identifier";
|
||||
name: string;
|
||||
}
|
||||
|
||||
export type Literal = SimpleLiteral | RegExpLiteral;
|
||||
|
||||
export interface SimpleLiteral extends BaseNode, BaseExpression {
|
||||
type: "Literal";
|
||||
value: string | boolean | number | null;
|
||||
raw?: string;
|
||||
}
|
||||
|
||||
export interface RegExpLiteral extends BaseNode, BaseExpression {
|
||||
type: "Literal";
|
||||
value?: RegExp | null;
|
||||
regex: {
|
||||
pattern: string;
|
||||
flags: string;
|
||||
};
|
||||
raw?: string;
|
||||
}
|
||||
|
||||
export type UnaryOperator =
|
||||
"-" | "+" | "!" | "~" | "typeof" | "void" | "delete";
|
||||
|
||||
export type BinaryOperator =
|
||||
"==" | "!=" | "===" | "!==" | "<" | "<=" | ">" | ">=" | "<<" |
|
||||
">>" | ">>>" | "+" | "-" | "*" | "/" | "%" | "**" | "|" | "^" | "&" | "in" |
|
||||
"instanceof";
|
||||
|
||||
export type LogicalOperator = "||" | "&&" | "??";
|
||||
|
||||
export type AssignmentOperator =
|
||||
"=" | "+=" | "-=" | "*=" | "/=" | "%=" | "**=" | "<<=" | ">>=" | ">>>=" |
|
||||
"|=" | "^=" | "&=";
|
||||
|
||||
export type UpdateOperator = "++" | "--";
|
||||
|
||||
export interface ForOfStatement extends BaseForXStatement {
|
||||
type: "ForOfStatement";
|
||||
await: boolean;
|
||||
}
|
||||
|
||||
export interface Super extends BaseNode {
|
||||
type: "Super";
|
||||
}
|
||||
|
||||
export interface SpreadElement extends BaseNode {
|
||||
type: "SpreadElement";
|
||||
argument: Expression;
|
||||
}
|
||||
|
||||
export interface ArrowFunctionExpression extends BaseExpression, BaseFunction {
|
||||
type: "ArrowFunctionExpression";
|
||||
expression: boolean;
|
||||
body: BlockStatement | Expression;
|
||||
}
|
||||
|
||||
export interface YieldExpression extends BaseExpression {
|
||||
type: "YieldExpression";
|
||||
argument?: Expression | null;
|
||||
delegate: boolean;
|
||||
}
|
||||
|
||||
export interface TemplateLiteral extends BaseExpression {
|
||||
type: "TemplateLiteral";
|
||||
quasis: Array<TemplateElement>;
|
||||
expressions: Array<Expression>;
|
||||
}
|
||||
|
||||
export interface TaggedTemplateExpression extends BaseExpression {
|
||||
type: "TaggedTemplateExpression";
|
||||
tag: Expression;
|
||||
quasi: TemplateLiteral;
|
||||
}
|
||||
|
||||
export interface TemplateElement extends BaseNode {
|
||||
type: "TemplateElement";
|
||||
tail: boolean;
|
||||
value: {
|
||||
cooked: string;
|
||||
raw: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface AssignmentProperty extends Property {
|
||||
value: Pattern;
|
||||
kind: "init";
|
||||
method: boolean; // false
|
||||
}
|
||||
|
||||
export interface ObjectPattern extends BasePattern {
|
||||
type: "ObjectPattern";
|
||||
properties: Array<AssignmentProperty | RestElement>;
|
||||
}
|
||||
|
||||
export interface ArrayPattern extends BasePattern {
|
||||
type: "ArrayPattern";
|
||||
elements: Array<Pattern>;
|
||||
}
|
||||
|
||||
export interface RestElement extends BasePattern {
|
||||
type: "RestElement";
|
||||
argument: Pattern;
|
||||
}
|
||||
|
||||
export interface AssignmentPattern extends BasePattern {
|
||||
type: "AssignmentPattern";
|
||||
left: Pattern;
|
||||
right: Expression;
|
||||
}
|
||||
|
||||
export type Class = ClassDeclaration | ClassExpression;
|
||||
interface BaseClass extends BaseNode {
|
||||
superClass?: Expression | null;
|
||||
body: ClassBody;
|
||||
}
|
||||
|
||||
export interface ClassBody extends BaseNode {
|
||||
type: "ClassBody";
|
||||
body: Array<MethodDefinition>;
|
||||
}
|
||||
|
||||
export interface MethodDefinition extends BaseNode {
|
||||
type: "MethodDefinition";
|
||||
key: Expression;
|
||||
value: FunctionExpression;
|
||||
kind: "constructor" | "method" | "get" | "set";
|
||||
computed: boolean;
|
||||
static: boolean;
|
||||
}
|
||||
|
||||
export interface ClassDeclaration extends BaseClass, BaseDeclaration {
|
||||
type: "ClassDeclaration";
|
||||
/** It is null when a class declaration is a part of the `export default class` statement */
|
||||
id: Identifier | null;
|
||||
}
|
||||
|
||||
export interface ClassExpression extends BaseClass, BaseExpression {
|
||||
type: "ClassExpression";
|
||||
id?: Identifier | null;
|
||||
}
|
||||
|
||||
export interface MetaProperty extends BaseExpression {
|
||||
type: "MetaProperty";
|
||||
meta: Identifier;
|
||||
property: Identifier;
|
||||
}
|
||||
|
||||
export type ModuleDeclaration =
|
||||
ImportDeclaration | ExportNamedDeclaration | ExportDefaultDeclaration |
|
||||
ExportAllDeclaration;
|
||||
interface BaseModuleDeclaration extends BaseNode { }
|
||||
|
||||
export type ModuleSpecifier =
|
||||
ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier |
|
||||
ExportSpecifier;
|
||||
interface BaseModuleSpecifier extends BaseNode {
|
||||
local: Identifier;
|
||||
}
|
||||
|
||||
export interface ImportDeclaration extends BaseModuleDeclaration {
|
||||
type: "ImportDeclaration";
|
||||
specifiers: Array<ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier>;
|
||||
source: Literal;
|
||||
}
|
||||
|
||||
export interface ImportSpecifier extends BaseModuleSpecifier {
|
||||
type: "ImportSpecifier";
|
||||
imported: Identifier;
|
||||
}
|
||||
|
||||
export interface ImportExpression extends BaseExpression {
|
||||
type: "ImportExpression";
|
||||
source: Expression;
|
||||
}
|
||||
|
||||
export interface ImportDefaultSpecifier extends BaseModuleSpecifier {
|
||||
type: "ImportDefaultSpecifier";
|
||||
}
|
||||
|
||||
export interface ImportNamespaceSpecifier extends BaseModuleSpecifier {
|
||||
type: "ImportNamespaceSpecifier";
|
||||
}
|
||||
|
||||
export interface ExportNamedDeclaration extends BaseModuleDeclaration {
|
||||
type: "ExportNamedDeclaration";
|
||||
declaration?: Declaration | null;
|
||||
specifiers: Array<ExportSpecifier>;
|
||||
source?: Literal | null;
|
||||
}
|
||||
|
||||
export interface ExportSpecifier extends BaseModuleSpecifier {
|
||||
type: "ExportSpecifier";
|
||||
exported: Identifier;
|
||||
}
|
||||
|
||||
export interface ExportDefaultDeclaration extends BaseModuleDeclaration {
|
||||
type: "ExportDefaultDeclaration";
|
||||
declaration: Declaration | Expression;
|
||||
}
|
||||
|
||||
export interface ExportAllDeclaration extends BaseModuleDeclaration {
|
||||
type: "ExportAllDeclaration";
|
||||
source: Literal;
|
||||
}
|
||||
|
||||
export interface AwaitExpression extends BaseExpression {
|
||||
type: "AwaitExpression";
|
||||
argument: Expression;
|
||||
}
|
@ -1,13 +1,14 @@
|
||||
{
|
||||
"imports": {
|
||||
"acorn": "https://cdn.skypack.dev/acorn",
|
||||
"estree": "https://cdn.skypack.dev/@types/estree?dts",
|
||||
"acorn": "https://cdn.skypack.dev/acorn?dts",
|
||||
"estree": "./estree.ts",
|
||||
"estree-walker": "https://cdn.skypack.dev/estree-walker",
|
||||
"magic-string": "https://cdn.skypack.dev/magic-string",
|
||||
"code-red": "https://cdn.skypack.dev/code-red",
|
||||
"magic-string": "https://cdn.skypack.dev/magic-string?dts",
|
||||
"code-red": "https://esm.sh/code-red",
|
||||
"is-reference": "https://cdn.skypack.dev/is-reference",
|
||||
"locate-character": "https://cdn.skypack.dev/locate-character",
|
||||
"periscopic": "https://cdn.skypack.dev/periscopic",
|
||||
"css-tree": "https://esm.sh/css-tree@1.0.0-alpha22"
|
||||
"css-tree": "https://esm.sh/css-tree@1.0.0-alpha22",
|
||||
"events@3.2.0/": "https://esm.sh/events/"
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,92 @@
|
||||
import * as svelte from '../../src/compiler/index.ts';
|
||||
import { assertEquals } from 'https://deno.land/std/testing/asserts.ts';
|
||||
async function try_require(file) {
|
||||
try {
|
||||
const mod = await import(file);
|
||||
return mod.default || mod;
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function normalize_warning(warning) {
|
||||
warning.frame = warning.frame
|
||||
.replace(/^\n/, '')
|
||||
.replace(/^\t+/gm, '')
|
||||
.replace(/\s+$/gm, '');
|
||||
delete warning.filename;
|
||||
delete warning.toString;
|
||||
return warning;
|
||||
}
|
||||
|
||||
const __dirname = new URL('.', import.meta.url).pathname;
|
||||
const files = Deno.readDirSync(`${__dirname}/samples`);
|
||||
for (const dir of files) {
|
||||
|
||||
if (dir[0] === '.') continue;
|
||||
// add .solo to a sample directory name to only run that test
|
||||
const solo = /\.solo/.test(dir.name);
|
||||
const skip = /\.skip/.test(dir.name);
|
||||
|
||||
if (solo && Deno.env.get("CI")) {
|
||||
throw new Error('Forgot to remove `solo: true` from test');
|
||||
}
|
||||
Deno.test({ name: dir.name, only: skip, fn: async () => {
|
||||
const config = await try_require(`./samples/${dir.name}/_config.js`) || {};
|
||||
const input = Deno
|
||||
.readTextFileSync(`${__dirname}/samples/${dir.name}/input.svelte`)
|
||||
.replace(/\s+$/, '')
|
||||
.replace(/\r/g, '');
|
||||
|
||||
const expected_warnings = (config.warnings || []).map(normalize_warning);
|
||||
|
||||
const dom = svelte.compile(
|
||||
input,
|
||||
Object.assign(config.compileOptions || {}, { format: 'cjs' })
|
||||
);
|
||||
|
||||
const ssr = svelte.compile(
|
||||
input,
|
||||
Object.assign(config.compileOptions || {}, { format: 'cjs', generate: 'ssr' })
|
||||
);
|
||||
|
||||
assertEquals(dom.css.code, ssr.css.code);
|
||||
|
||||
const dom_warnings = dom.warnings.map(normalize_warning);
|
||||
const ssr_warnings = ssr.warnings.map(normalize_warning);
|
||||
|
||||
assertEquals(dom_warnings, ssr_warnings);
|
||||
assertEquals(dom_warnings.map(normalize_warning), expected_warnings);
|
||||
|
||||
await Deno.writeTextFile(`${__dirname}/samples/${dir.name}/_actual.css`, dom.css.code);
|
||||
const expected = {
|
||||
html: read(`${__dirname}/samples/${dir.name}/expected.html`),
|
||||
css: read(`${__dirname}/samples/${dir.name}/expected.css`)
|
||||
};
|
||||
|
||||
const actual_css = dom.css.code.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz');
|
||||
try {
|
||||
assertEquals(actual_css, expected.css);
|
||||
} catch (error) {
|
||||
if (shouldUpdateExpected()) {
|
||||
await Deno.writeTextFile(`${__dirname}/samples/${dir}/expected.css`, actual_css);
|
||||
console.log(`Updated ${dir}/expected.css.`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}})
|
||||
|
||||
}
|
||||
|
||||
function shouldUpdateExpected() {
|
||||
return Deno.args.includes('--update');
|
||||
}
|
||||
|
||||
function read(file) {
|
||||
try {
|
||||
return Deno.readTextFileSync(file);
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,159 +0,0 @@
|
||||
import * as fs from 'fs';
|
||||
import { assert, env, svelte, setupHtmlEqual, shouldUpdateExpected } from '../helpers';
|
||||
|
||||
function try_require(file) {
|
||||
try {
|
||||
const mod = require(file);
|
||||
return mod.default || mod;
|
||||
} catch (err) {
|
||||
if (err.code !== 'MODULE_NOT_FOUND') throw err;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function normalize_warning(warning) {
|
||||
warning.frame = warning.frame
|
||||
.replace(/^\n/, '')
|
||||
.replace(/^\t+/gm, '')
|
||||
.replace(/\s+$/gm, '');
|
||||
delete warning.filename;
|
||||
delete warning.toString;
|
||||
return warning;
|
||||
}
|
||||
|
||||
function create(code) {
|
||||
const fn = new Function('module', 'exports', 'require', code);
|
||||
|
||||
const module = { exports: {} };
|
||||
fn(module, module.exports, id => {
|
||||
if (id === 'svelte') return require('../../index.js');
|
||||
if (id.startsWith('svelte/')) return require(id.replace('svelte', '../../'));
|
||||
|
||||
return require(id);
|
||||
});
|
||||
|
||||
return module.exports.default;
|
||||
}
|
||||
|
||||
describe('css', () => {
|
||||
before(() => {
|
||||
setupHtmlEqual();
|
||||
});
|
||||
|
||||
fs.readdirSync(`${__dirname}/samples`).forEach(dir => {
|
||||
if (dir[0] === '.') return;
|
||||
|
||||
// add .solo to a sample directory name to only run that test
|
||||
const solo = /\.solo/.test(dir);
|
||||
const skip = /\.skip/.test(dir);
|
||||
|
||||
if (solo && process.env.CI) {
|
||||
throw new Error('Forgot to remove `solo: true` from test');
|
||||
}
|
||||
|
||||
(solo ? it.only : skip ? it.skip : it)(dir, () => {
|
||||
const config = try_require(`./samples/${dir}/_config.js`) || {};
|
||||
const input = fs
|
||||
.readFileSync(`${__dirname}/samples/${dir}/input.svelte`, 'utf-8')
|
||||
.replace(/\s+$/, '')
|
||||
.replace(/\r/g, '');
|
||||
|
||||
const expected_warnings = (config.warnings || []).map(normalize_warning);
|
||||
|
||||
const dom = svelte.compile(
|
||||
input,
|
||||
Object.assign(config.compileOptions || {}, { format: 'cjs' })
|
||||
);
|
||||
|
||||
const ssr = svelte.compile(
|
||||
input,
|
||||
Object.assign(config.compileOptions || {}, { format: 'cjs', generate: 'ssr' })
|
||||
);
|
||||
|
||||
assert.equal(dom.css.code, ssr.css.code);
|
||||
|
||||
const dom_warnings = dom.warnings.map(normalize_warning);
|
||||
const ssr_warnings = ssr.warnings.map(normalize_warning);
|
||||
|
||||
assert.deepEqual(dom_warnings, ssr_warnings);
|
||||
assert.deepEqual(dom_warnings.map(normalize_warning), expected_warnings);
|
||||
|
||||
fs.writeFileSync(`${__dirname}/samples/${dir}/_actual.css`, dom.css.code);
|
||||
const expected = {
|
||||
html: read(`${__dirname}/samples/${dir}/expected.html`),
|
||||
css: read(`${__dirname}/samples/${dir}/expected.css`)
|
||||
};
|
||||
|
||||
const actual_css = dom.css.code.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz');
|
||||
try {
|
||||
assert.equal(actual_css, expected.css);
|
||||
} catch (error) {
|
||||
if (shouldUpdateExpected()) {
|
||||
fs.writeFileSync(`${__dirname}/samples/${dir}/expected.css`, actual_css);
|
||||
console.log(`Updated ${dir}/expected.css.`);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
let ClientComponent;
|
||||
let ServerComponent;
|
||||
|
||||
// we do this here, rather than in the expected.html !== null
|
||||
// block, to verify that valid code was generated
|
||||
try {
|
||||
ClientComponent = create(dom.js.code);
|
||||
} catch (err) {
|
||||
console.log(dom.js.code);
|
||||
throw err;
|
||||
}
|
||||
|
||||
try {
|
||||
ServerComponent = create(ssr.js.code);
|
||||
} catch (err) {
|
||||
console.log(dom.js.code);
|
||||
throw err;
|
||||
}
|
||||
|
||||
// verify that the right elements have scoping selectors
|
||||
if (expected.html !== null) {
|
||||
const window = env();
|
||||
|
||||
// dom
|
||||
try {
|
||||
const target = window.document.querySelector('main');
|
||||
|
||||
new ClientComponent({ target, props: config.props });
|
||||
const html = target.innerHTML;
|
||||
|
||||
fs.writeFileSync(`${__dirname}/samples/${dir}/_actual.html`, html);
|
||||
|
||||
const actual_html = html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz');
|
||||
assert.htmlEqual(actual_html, expected.html);
|
||||
|
||||
window.document.head.innerHTML = ''; // remove added styles
|
||||
} catch (err) {
|
||||
console.log(dom.js.code);
|
||||
throw err;
|
||||
}
|
||||
|
||||
// ssr
|
||||
try {
|
||||
const actual_ssr = ServerComponent.render(config.props).html.replace(/svelte(-ref)?-[a-z0-9]+/g, (m, $1) => $1 ? m : 'svelte-xyz');
|
||||
assert.htmlEqual(actual_ssr, expected.html);
|
||||
} catch (err) {
|
||||
console.log(ssr.js.code);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function read(file) {
|
||||
try {
|
||||
return fs.readFileSync(file, 'utf-8');
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,23 +1,13 @@
|
||||
import * as assert$1 from 'assert';
|
||||
import * as jsdom from 'jsdom';
|
||||
import glob from 'tiny-glob/sync';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as colors from 'kleur';
|
||||
export const assert = (assert$1 as unknown) as typeof assert$1 & { htmlEqual: (actual, expected, message?) => void };
|
||||
|
||||
// for coverage purposes, we need to test source files,
|
||||
// but for sanity purposes, we need to test dist files
|
||||
export function loadSvelte(test) {
|
||||
process.env.TEST = test ? 'true' : '';
|
||||
|
||||
const resolved = require.resolve('../compiler.js');
|
||||
|
||||
delete require.cache[resolved];
|
||||
return require(resolved);
|
||||
}
|
||||
import * as assert from 'https://esm.sh/assert';
|
||||
import * as jsdom from 'https://esm.sh/jsdom';
|
||||
import glob from 'https://esm.sh/tiny-glob/sync';
|
||||
import * as path from 'https://deno.land/std@0.75.0/node/path.ts';
|
||||
import * as fs from 'https://deno.land/std@0.75.0/node/fs.ts';
|
||||
import * as colors from 'https://esm.sh/kleur';
|
||||
// @ts-ignore
|
||||
import * as svelte from "../src/compiler/index.ts";
|
||||
|
||||
|
||||
export const svelte = loadSvelte();
|
||||
|
||||
export function exists(path) {
|
||||
try {
|
Loading…
Reference in new issue