Skip to content

Commit e20b864

Browse files
feat(core)!: make path(s) abstract
Mainly just a matter of type. Path(s) no longer need to be a string. Now it can be an URL object for instance. Then now, initial reference path is `undefined`
1 parent 605c0e1 commit e20b864

File tree

7 files changed

+74
-51
lines changed

7 files changed

+74
-51
lines changed

src/createSFCModule.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ModuleExport, Options } from './types'
1+
import { ModuleExport, Options, AbstractPath } from './types'
22

3-
export declare function createSFCModule (source: string, filename: string, options: Options): Promise<ModuleExport>
3+
export declare function createSFCModule (source: string, filename: AbstractPath, options: Options): Promise<ModuleExport>
44
export declare const vueVersion : string

src/createVue2SFCModule.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ import {
4646
import {
4747
Options,
4848
ModuleExport,
49-
CustomBlockCallback
49+
CustomBlockCallback,
50+
AbstractPath
5051
} from './types'
5152

5253
import {
@@ -75,23 +76,24 @@ const isProd : boolean = process.env.NODE_ENV === 'production';
7576
* @internal
7677
*/
7778

78-
export async function createSFCModule(source : string, filename : string, options : Options) : Promise<ModuleExport> {
79+
export async function createSFCModule(source : string, filename : AbstractPath, options : Options) : Promise<ModuleExport> {
7980

80-
const component = {};
81+
const strFilename = filename.toString();
8182

83+
const component = {};
8284

8385
const { delimiters, moduleCache, compiledCache, getResource, addStyle, log, additionalBabelPlugins = [], customBlockHandler } = options;
8486

8587
const descriptor = sfc_parse({
8688
source,
87-
filename,
89+
filename: strFilename,
8890
needMap: genSourcemap,
8991
compiler: vueTemplateCompiler as VueTemplateCompiler}
9092
);
9193

9294
const customBlockCallbacks : CustomBlockCallback[] = customBlockHandler !== undefined ? await Promise.all( descriptor.customBlocks.map((block ) => customBlockHandler(block, filename, options)) ) : [];
9395

94-
const componentHash = hash(filename, version);
96+
const componentHash = hash(strFilename, version);
9597
const scopeId = `data-v-${componentHash}`;
9698

9799
// hack: asynchronously preloads the language processor before it is required by the synchronous preprocessCustomRequire() callback, see below
@@ -109,7 +111,7 @@ export async function createSFCModule(source : string, filename : string, option
109111
const compileTemplateOptions : TemplateCompileOptions = descriptor.template ? {
110112
// hack, since sourceMap is not configurable an we want to get rid of source-map dependency. see genSourcemap
111113
source: descriptor.template.src ? (await getResource({ refPath: filename, relPath: descriptor.template.src }, options).getContent()).content.toString() : descriptor.template.content,
112-
filename,
114+
filename: strFilename,
113115
compiler: vueTemplateCompiler as VueTemplateCompiler,
114116
compilerOptions: {
115117
delimiters,
@@ -159,11 +161,11 @@ export async function createSFCModule(source : string, filename : string, option
159161
...babelParserPlugins
160162
],
161163
sourceType: 'module',
162-
sourceFilename: filename
164+
sourceFilename: strFilename
163165
});
164166

165167
} catch(ex) {
166-
log?.('error', 'SFC script', formatErrorLineColumn(ex.message, filename, source, ex.loc.line, ex.loc.column + 1) );
168+
log?.('error', 'SFC script', formatErrorLineColumn(ex.message, strFilename, source, ex.loc.line, ex.loc.column + 1) );
167169
throw ex;
168170
}
169171

@@ -212,7 +214,7 @@ export async function createSFCModule(source : string, filename : string, option
212214
}
213215
}
214216

215-
log?.('error', 'SFC template', formatErrorStartEnd(err.msg, filename, compileTemplateOptions.source.trim(), err.start, err.end ));
217+
log?.('error', 'SFC template', formatErrorStartEnd(err.msg, strFilename, compileTemplateOptions.source.trim(), err.start, err.end ));
216218
}
217219
}
218220

@@ -225,7 +227,7 @@ export async function createSFCModule(source : string, filename : string, option
225227
}
226228
}
227229

228-
log?.('info', 'SFC template', formatErrorStartEnd(err.msg, filename, source, err.start, err.end ));
230+
log?.('info', 'SFC template', formatErrorStartEnd(err.msg, strFilename, source, err.start, err.end ));
229231
}
230232

231233
return await transformJSCode(template.code, true, filename, options);
@@ -244,7 +246,7 @@ export async function createSFCModule(source : string, filename : string, option
244246

245247
const compileStyleOptions: StyleCompileOptions = {
246248
source: src,
247-
filename,
249+
filename: strFilename,
248250
id: scopeId,
249251
scoped: descStyle.scoped !== undefined ? descStyle.scoped : false,
250252
trim: false,
@@ -266,7 +268,7 @@ export async function createSFCModule(source : string, filename : string, option
266268
preventCache();
267269
for ( const err of compiledStyle.errors ) {
268270

269-
log?.('error', 'SFC style', formatError(err, filename, source));
271+
log?.('error', 'SFC style', formatError(err, strFilename, source));
270272
}
271273
}
272274

src/createVue3SFCModule.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ import {
4747
import {
4848
Options,
4949
ModuleExport,
50-
CustomBlockCallback
50+
CustomBlockCallback,
51+
AbstractPath
5152
} from './types'
5253

5354

@@ -76,23 +77,24 @@ const isProd : boolean = process.env.NODE_ENV === 'production';
7677
* @internal
7778
*/
7879

79-
export async function createSFCModule(source : string, filename : string, options : Options) : Promise<ModuleExport> {
80+
export async function createSFCModule(source : string, filename : AbstractPath, options : Options) : Promise<ModuleExport> {
8081

81-
const component = {};
82+
const strFilename = filename.toString();
8283

84+
const component = {};
8385

8486
const { delimiters, moduleCache, compiledCache, getResource, addStyle, log, additionalBabelPlugins = [], customBlockHandler } = options;
8587

8688
// vue-loader next: https://github.com/vuejs/vue-loader/blob/next/src/index.ts#L91
8789
const { descriptor, errors } = sfc_parse(source, {
88-
filename,
90+
filename: strFilename,
8991
sourceMap: genSourcemap,
9092
});
9193

9294

9395
const customBlockCallbacks : CustomBlockCallback[] = customBlockHandler !== undefined ? await Promise.all( descriptor.customBlocks.map((block) => customBlockHandler(block, filename, options)) ) : [];
9496

95-
const componentHash = hash(filename, version);
97+
const componentHash = hash(strFilename, version);
9698
const scopeId = `data-v-${componentHash}`;
9799

98100
// hack: asynchronously preloads the language processor before it is required by the synchronous preprocessCustomRequire() callback, see below
@@ -170,13 +172,13 @@ export async function createSFCModule(source : string, filename : string, option
170172
...babelParserPlugins
171173
],
172174
sourceType: 'module',
173-
sourceFilename: filename,
175+
sourceFilename: strFilename,
174176
startLine: scriptBlock.loc.start.line,
175177
});
176178

177179
} catch(ex) {
178180

179-
log?.('error', 'SFC script', formatErrorLineColumn(ex.message, filename, source, ex.loc.line, ex.loc.column + 1) );
181+
log?.('error', 'SFC script', formatErrorLineColumn(ex.message, strFilename, source, ex.loc.line, ex.loc.column + 1) );
180182
throw ex;
181183
}
182184
} else {
@@ -224,12 +226,12 @@ export async function createSFCModule(source : string, filename : string, option
224226
for ( const err of template.errors ) {
225227
if (typeof err === 'object') {
226228
if (err.loc) {
227-
log?.('error', 'SFC template', formatErrorLineColumn(err.message, filename, source, err.loc.start.line + descriptor.template.loc.start.line - 1, err.loc.start.column) );
229+
log?.('error', 'SFC template', formatErrorLineColumn(err.message, strFilename, source, err.loc.start.line + descriptor.template.loc.start.line - 1, err.loc.start.column) );
228230
} else {
229-
log?.('error', 'SFC template', formatError(err.message, filename, source) );
231+
log?.('error', 'SFC template', formatError(err.message, strFilename, source) );
230232
}
231233
} else {
232-
log?.('error', 'SFC template', formatError(err, filename, source) );
234+
log?.('error', 'SFC template', formatError(err, strFilename, source) );
233235
}
234236
}
235237
}

src/index.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@ import {
1414
Resource,
1515
PathContext,
1616
LangProcessor,
17+
AbstractPath,
1718
} from './types'
1819

20+
1921
/**
2022
* the version of the library (process.env.VERSION is set by webpack, at compile-time)
2123
*/
@@ -48,14 +50,25 @@ function throwNotDefined(details : string) : never {
4850
const defaultPathHandlers : PathHandlers = {
4951
extname(filepath) {
5052

51-
return Path.extname(filepath);
53+
return Path.extname(filepath.toString());
5254
},
5355
resolve({ refPath, relPath } : PathContext) {
5456

57+
// initial resolution: refPath is not defined
58+
if ( refPath === undefined )
59+
return relPath;
60+
5561
// note :
5662
// normalize('./test') -> 'test'
5763
// normalize('/test') -> '/test'
58-
return (relPath[0] !== '.' && relPath[0] !== '/') ? relPath : Path.normalize(Path.join(Path.dirname(refPath), relPath));
64+
65+
const relPathStr = relPath.toString();
66+
67+
// a module name ?
68+
if ( relPathStr[0] !== '.' && relPathStr[0] !== '/' )
69+
return relPath;
70+
71+
return Path.normalize(Path.join(Path.dirname(refPath.toString()), relPathStr));
5972
}
6073
}
6174

@@ -65,7 +78,7 @@ function defaultGetResource(pathCx : PathContext, options : Options) : Resource
6578
const { pathHandlers: { resolve }, getFile } = options;
6679
const path = resolve(pathCx);
6780
return {
68-
id: path,
81+
id: path.toString(),
6982
path: path,
7083
getContent: () => getFile(path),
7184
};
@@ -113,7 +126,7 @@ function defaultGetResource(pathCx : PathContext, options : Options) : Resource
113126
* ```
114127
*
115128
*/
116-
export async function loadModule(path : string, options : Options = throwNotDefined('options')) : Promise<ModuleExport> {
129+
export async function loadModule(path : AbstractPath, options : Options = throwNotDefined('options')) : Promise<ModuleExport> {
117130

118131
const {
119132
moduleCache = throwNotDefined('options.moduleCache'),
@@ -128,7 +141,7 @@ export async function loadModule(path : string, options : Options = throwNotDefi
128141
Object.setPrototypeOf(moduleCache, null);
129142

130143
// TBD: remove this in v1.0
131-
async function normalizedGetFile(path : string) : Promise<File> {
144+
async function normalizedGetFile(path : AbstractPath) : Promise<File> {
132145

133146
const res = await getFile(path);
134147
return typeof res === 'object' ? res : { content: res, extname: pathHandlers.extname(path) };
@@ -142,7 +155,7 @@ export async function loadModule(path : string, options : Options = throwNotDefi
142155
getFile: normalizedGetFile,
143156
};
144157

145-
return await loadModuleInternal( { refPath: '/', relPath: path }, normalizedOptions);
158+
return await loadModuleInternal( { refPath: undefined, relPath: path }, normalizedOptions);
146159
}
147160

148161
/**

src/tools.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
Module,
3333
LoadingType,
3434
PathContext,
35+
AbstractPath,
3536
} from './types'
3637

3738
import { createSFCModule } from './createSFCModule'
@@ -91,9 +92,9 @@ export function formatErrorStartEnd(message : string, path : string, source : st
9192
/**
9293
* @internal
9394
*/
94-
export function hash(...valueList : string[]) : string {
95+
export function hash(...valueList : any[]) : string {
9596

96-
return valueList.reduce((hashInstance, val) => hashInstance.append(val ? val : ""), new SparkMD5()).end().slice(0, 8);
97+
return valueList.reduce((hashInstance, val) => hashInstance.append(String(val)), new SparkMD5()).end().slice(0, 8);
9798
}
9899

99100

@@ -103,7 +104,7 @@ export function formatErrorStartEnd(message : string, path : string, source : st
103104
* preventCache usage: non-fatal error
104105
* @internal
105106
*/
106-
export async function withCache( cacheInstance : Cache, key : string[], valueFactory : ValueFactory ) : Promise<any> {
107+
export async function withCache( cacheInstance : Cache, key : any[], valueFactory : ValueFactory ) : Promise<any> {
107108

108109
let cachePrevented = false;
109110

@@ -202,7 +203,7 @@ export function parseDeps(fileAst : t.File) : string[] {
202203
/**
203204
* @internal
204205
*/
205-
export async function transformJSCode(source : string, moduleSourceType : boolean, filename : string, options : Options) : Promise<[string[], string]> {
206+
export async function transformJSCode(source : string, moduleSourceType : boolean, filename : AbstractPath, options : Options) : Promise<[string[], string]> {
206207

207208
const { additionalBabelPlugins = [], log } = options;
208209

@@ -212,11 +213,11 @@ export async function transformJSCode(source : string, moduleSourceType : boolea
212213
ast = babel_parse(source, {
213214
// doc: https://babeljs.io/docs/en/babel-parser#options
214215
sourceType: moduleSourceType ? 'module' : 'script',
215-
sourceFilename: filename,
216+
sourceFilename: filename.toString(),
216217
});
217218
} catch(ex) {
218219

219-
log?.('error', 'parse script', formatErrorLineColumn(ex.message, filename, source, ex.loc.line, ex.loc.column + 1) );
220+
log?.('error', 'parse script', formatErrorLineColumn(ex.message, filename.toString(), source, ex.loc.line, ex.loc.column + 1) );
220221
throw ex;
221222
}
222223

@@ -297,7 +298,7 @@ export async function loadModuleInternal(pathCx : PathContext, options : Options
297298
* Create a cjs module
298299
* @internal
299300
*/
300-
export function createModule(refPath : string, source : string, options : Options) : Module {
301+
export function createModule(refPath : AbstractPath, source : string, options : Options) : Module {
301302

302303
const { moduleCache, pathHandlers: { resolve }, getResource } = options;
303304

@@ -330,7 +331,7 @@ export function createModule(refPath : string, source : string, options : Option
330331
/**
331332
* @internal
332333
*/
333-
export async function createJSModule(source : string, moduleSourceType : boolean, filename : string, options : Options) : Promise<ModuleExport> {
334+
export async function createJSModule(source : string, moduleSourceType : boolean, filename : AbstractPath, options : Options) : Promise<ModuleExport> {
334335

335336
const { compiledCache } = options;
336337

@@ -348,7 +349,7 @@ export async function createJSModule(source : string, moduleSourceType : boolean
348349
* Just load and cache given dependencies.
349350
* @internal
350351
*/
351-
export async function loadDeps(refPath : string, deps : string[], options : Options) : Promise<void> {
352+
export async function loadDeps(refPath : AbstractPath, deps : AbstractPath[], options : Options) : Promise<void> {
352353

353354
await Promise.all(deps.map(relPath => loadModuleInternal({ refPath, relPath }, options)))
354355
}
@@ -357,7 +358,7 @@ export async function loadDeps(refPath : string, deps : string[], options : Opti
357358
/**
358359
* Default implementation of handleModule
359360
*/
360-
async function defaultHandleModule(extname : string, source : string, path : string, options : Options) : Promise<ModuleExport | null> {
361+
async function defaultHandleModule(extname : string, source : string, path : AbstractPath, options : Options) : Promise<ModuleExport | null> {
361362

362363
switch (extname) {
363364
case '.vue': return createSFCModule(source.toString(), path, options);

0 commit comments

Comments
 (0)