diff --git a/src/createVue3SFCModule.ts b/src/createVue3SFCModule.ts index f7bfeaf..e8d3a2f 100644 --- a/src/createVue3SFCModule.ts +++ b/src/createVue3SFCModule.ts @@ -44,6 +44,7 @@ type PreprocessLang = SFCAsyncStyleCompileOptions['preprocessLang']; * the version of the library */ import { version, vueVersion } from './index' +import { RawSourceMap } from '@vue/component-compiler-utils/dist/types' // @ts-ignore const targetBrowserBabelPluginsHash : string = hash(...Object.keys({ ...(typeof ___targetBrowserBabelPlugins !== 'undefined' ? ___targetBrowserBabelPlugins : {}) })); @@ -55,7 +56,10 @@ const genSourcemap : boolean = !!process.env.GEN_SOURCEMAP; */ const isProd : boolean = process.env.NODE_ENV === 'production'; - +/** + * @internal + */ +const buildMapComment = (map : RawSourceMap) => `//# sourceMappingURL=data:application/json;charset=utf-8;base64,${btoa(JSON.stringify(map))}` /** * @internal @@ -118,6 +122,7 @@ export async function createSFCModule(source : string, filename : AbstractPath, scoped: hasScoped, id: scopeId, slotted: descriptor.slotted, + inMap: descriptor.template.map, compilerOptions: { isCustomElement, whitespace, @@ -180,6 +185,9 @@ export async function createSFCModule(source : string, filename : AbstractPath, templateOptions: compileTemplateOptions, }); + if(scriptBlock.map) + scriptBlock.content += `\r\n${buildMapComment(scriptBlock.map)}` + // note: // scriptBlock.content is the script code after vue transformations // scriptBlock.scriptAst is the script AST before vue transformations @@ -192,7 +200,7 @@ export async function createSFCModule(source : string, filename : AbstractPath, compileTemplateOptions.compilerOptions.bindingMetadata = bindingMetadata; await loadDeps(filename, depsList, options); - Object.assign(component, interopRequireDefault(createCJSModule(filename, transformedScriptSource, options).exports).default); + Object.assign(component, interopRequireDefault((await createCJSModule(filename, transformedScriptSource, options)).exports).default); } @@ -237,11 +245,14 @@ export async function createSFCModule(source : string, filename : AbstractPath, for ( const err of template.tips ) log?.('info', 'SFC template', err); + if(template.map) + template.code += `\r\n${buildMapComment(template.map)}` + return await transformJSCode(template.code, true, descriptor.filename, additionalBabelParserPlugins, additionalBabelPlugins, log, devMode); }); await loadDeps(filename, templateDepsList, options); - Object.assign(component, createCJSModule(filename, templateTransformedSource, options).exports); + Object.assign(component, (await createCJSModule(filename, templateTransformedSource, options)).exports); } diff --git a/src/tools.ts b/src/tools.ts index fc7cb57..7c8d965 100644 --- a/src/tools.ts +++ b/src/tools.ts @@ -253,7 +253,7 @@ export async function transformJSCode(source : string, moduleSourceType : boolea comments: devMode, retainLines: devMode, //envName: devMode ? 'development' : 'production', see 'process.env.BABEL_ENV': JSON.stringify(mode), - + filename: filename.toString(), //minified, sourceType: moduleSourceType ? 'module' : 'script', }); @@ -324,7 +324,7 @@ export async function loadModuleInternal(pathCx : PathContext, options : Options * Create a cjs module * @internal */ -export function defaultCreateCJSModule(refPath : AbstractPath, source : string, options : Options) : Module { +export async function defaultCreateCJSModule(refPath : AbstractPath, source : string, options : Options) : Promise { const { moduleCache, pathResolve, getResource } = options; @@ -348,8 +348,31 @@ export function defaultCreateCJSModule(refPath : AbstractPath, source : string, // see https://github.com/nodejs/node/blob/a46b21f556a83e43965897088778ddc7d46019ae/lib/internal/modules/cjs/loader.js#L195-L198 // see https://github.com/nodejs/node/blob/a46b21f556a83e43965897088778ddc7d46019ae/lib/internal/modules/cjs/loader.js#L1102 - const moduleFunction = Function('exports', 'require', 'module', '__filename', '__dirname', '__vsfcl_import__', source); - moduleFunction.call(module.exports, module.exports, require, module, refPath, pathResolve({ refPath, relPath: '.' }, options), importFunction); + const wrappedSource = `(exports, require, module, __filename, __dirname, __vsfcl_import__) => { ${source} \r\n }` + + let ast = babel_parse(wrappedSource, { + sourceType: 'module', + sourceFilename: refPath.toString(), + }); + + const transformedScript = await babel_transformFromAstAsync(ast, wrappedSource, { + sourceMaps: "inline", + babelrc: false, + configFile: false, + highlightCode: false, + filename: refPath.toString(), + sourceType: 'module', + }); + + if ( transformedScript === null || transformedScript.code == null ) { // == null or undefined + + const msg = `unable to transform script "${refPath.toString()}"`; + options.log?.('error', msg); + throw new Error(msg) + } + + + eval(transformedScript.code)(module.exports, require, module, refPath, pathResolve({ refPath, relPath: '.' }, options), importFunction) return module; } @@ -379,7 +402,7 @@ export async function createJSModule(source : string, moduleSourceType : boolean }); await loadDeps(filename, depsList, options); - return createCJSModule(filename, transformedSource, options).exports; + return (await createCJSModule(filename, transformedSource, options)).exports; } diff --git a/src/types.ts b/src/types.ts index dcdecdb..f8a130f 100644 --- a/src/types.ts +++ b/src/types.ts @@ -377,7 +377,7 @@ export type Options = { * creates a CommonJS module from JS source string. * *(optional)* */ - createCJSModule(refPath : AbstractPath, source : string, options : Options) : Module, + createCJSModule(refPath : AbstractPath, source : string, options : Options) : Promise,