From 363902b79f794c88283056348493233048ee4b53 Mon Sep 17 00:00:00 2001 From: kanno <812137533@qq.com> Date: Fri, 24 Nov 2023 11:53:26 +0800 Subject: [PATCH 1/6] feat: support ensure `typescript5.x` --- src/index.ts | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index f879b71..10e523d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -46,6 +46,13 @@ const fileExists = (path: string) => { .catch(() => false); }; +const lookup = (entry: string, target: string): string => { + const dir = dirname(entry); + const targetFile = join(dir, target); + if (fs.existsSync(targetFile)) return targetFile; + return lookup(dir, target); +}; + function swc(options: PluginOptions = {}): RollupPlugin { const filter = createFilter( options.include || INCLUDE_REGEXP, @@ -68,7 +75,6 @@ function swc(options: PluginOptions = {}): RollupPlugin { return { name: 'swc', - async resolveId(importee, importer) { // ignore IDs with null character, these belong to other plugins if (importee.startsWith('\0')) { @@ -107,6 +113,23 @@ function swc(options: PluginOptions = {}): RollupPlugin { ? {} : getOptions(this, dirname(id), options.tsconfig); + let enaleExperimentalDecorators = false; + if (isTypeScript) { + try { + const tsPath = require.resolve('typescript', { paths: [process.cwd()] }); + const packageJsonPath = lookup(tsPath, 'package.json'); + const { version } = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); + const [major] = version.split(','); + // typescript 5.x + if (+major >= 5) enaleExperimentalDecorators = true; + } catch { + this.warn({ + message: 'Can\'t find typescript, please Check typescript has been installed.', + pluginCode: 'SWC_TYPESCRIPT_NOT_EXISTS' + }); + } + } + // TODO: SWC is about to add "preserve" jsx // https://github.com/swc-project/swc/pull/5661 // Respect "preserve" after swc adds the support @@ -118,10 +141,12 @@ function swc(options: PluginOptions = {}): RollupPlugin { parser: { syntax: isTypeScript ? 'typescript' : 'ecmascript', [isTypeScript ? 'tsx' : 'jsx']: isTypeScript ? isTsx : isJsx, - decorators: tsconfigOptions.experimentalDecorators + decorators: enaleExperimentalDecorators || tsconfigOptions.experimentalDecorators }, transform: { decoratorMetadata: tsconfigOptions.emitDecoratorMetadata, + // @ts-expect-error -- swc types loose this :( + decoratorVersion: enaleExperimentalDecorators ? '2022-03' : '2021-12', react: { runtime: useReact17NewTransform ? 'automatic' From 98430b349b1f17729f65317389a79fd5f89bd322 Mon Sep 17 00:00:00 2001 From: kanno <812137533@qq.com> Date: Fri, 24 Nov 2023 13:17:22 +0800 Subject: [PATCH 2/6] test: update test case --- src/index.ts | 2 +- test/__snapshots__/index.ts.snap | 1389 +++++++++++++++++++++++++++++ test/fixtures/decorators/index.ts | 9 + test/index.ts | 9 + tools/build.ts | 21 +- 5 files changed, 1428 insertions(+), 2 deletions(-) create mode 100644 test/fixtures/decorators/index.ts diff --git a/src/index.ts b/src/index.ts index 10e523d..d4d1e93 100644 --- a/src/index.ts +++ b/src/index.ts @@ -119,7 +119,7 @@ function swc(options: PluginOptions = {}): RollupPlugin { const tsPath = require.resolve('typescript', { paths: [process.cwd()] }); const packageJsonPath = lookup(tsPath, 'package.json'); const { version } = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); - const [major] = version.split(','); + const [major] = version.split('.'); // typescript 5.x if (+major >= 5) enaleExperimentalDecorators = true; } catch { diff --git a/test/__snapshots__/index.ts.snap b/test/__snapshots__/index.ts.snap index 174e842..838da79 100644 --- a/test/__snapshots__/index.ts.snap +++ b/test/__snapshots__/index.ts.snap @@ -1,5 +1,468 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`rollup-plugin-swc3 swc (rollup 2) detect decorator for typescript5 1`] = ` +"function _array_like_to_array(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i]; + return arr2; +} +function _array_with_holes(arr) { + if (Array.isArray(arr)) return arr; +} +function _class_call_check(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError(\\"Cannot call a class as a function\\"); + } +} +function _define_property(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + return obj; +} +function _iterable_to_array_limit(arr, i) { + var _i = arr == null ? null : typeof Symbol !== \\"undefined\\" && arr[Symbol.iterator] || arr[\\"@@iterator\\"]; + if (_i == null) return; + var _arr = []; + var _n = true; + var _d = false; + var _s, _e; + try { + for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){ + _arr.push(_s.value); + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally{ + try { + if (!_n && _i[\\"return\\"] != null) _i[\\"return\\"](); + } finally{ + if (_d) throw _e; + } + } + return _arr; +} +function _non_iterable_rest() { + throw new TypeError(\\"Invalid attempt to destructure non-iterable instance.\\\\\\\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\\"); +} +function _sliced_to_array(arr, i) { + return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest(); +} +function _unsupported_iterable_to_array(o, minLen) { + if (!o) return; + if (typeof o === \\"string\\") return _array_like_to_array(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === \\"Object\\" && o.constructor) n = o.constructor.name; + if (n === \\"Map\\" || n === \\"Set\\") return Array.from(n); + if (n === \\"Arguments\\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen); +} +function applyDecs2203RFactory() { + function createAddInitializerMethod(initializers, decoratorFinishedRef) { + return function addInitializer(initializer) { + assertNotFinished(decoratorFinishedRef, \\"addInitializer\\"); + assertCallable(initializer, \\"An initializer\\"); + initializers.push(initializer); + }; + } + function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) { + var kindStr; + switch(kind){ + case 1: + kindStr = \\"accessor\\"; + break; + case 2: + kindStr = \\"method\\"; + break; + case 3: + kindStr = \\"getter\\"; + break; + case 4: + kindStr = \\"setter\\"; + break; + default: + kindStr = \\"field\\"; + } + var ctx = { + kind: kindStr, + name: isPrivate ? \\"#\\" + name : name, + static: isStatic, + private: isPrivate, + metadata: metadata + }; + var decoratorFinishedRef = { + v: false + }; + if (kind !== 0) { + ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef); + } + var get, set; + if (kind === 0) { + if (isPrivate) { + get = desc.get; + set = desc.set; + } else { + get = function() { + return this[name]; + }; + set = function(v) { + this[name] = v; + }; + } + } else if (kind === 2) { + get = function() { + return desc.value; + }; + } else { + if (kind === 1 || kind === 3) { + get = function() { + return desc.get.call(this); + }; + } + if (kind === 1 || kind === 4) { + set = function(v) { + desc.set.call(this, v); + }; + } + } + ctx.access = get && set ? { + get: get, + set: set + } : get ? { + get: get + } : { + set: set + }; + try { + return dec(value, ctx); + } finally{ + decoratorFinishedRef.v = true; + } + } + function assertNotFinished(decoratorFinishedRef, fnName) { + if (decoratorFinishedRef.v) { + throw new Error(\\"attempted to call \\" + fnName + \\" after decoration was finished\\"); + } + } + function assertCallable(fn, hint) { + if (typeof fn !== \\"function\\") { + throw new TypeError(hint + \\" must be a function\\"); + } + } + function assertValidReturnValue(kind, value) { + var type = typeof value; + if (kind === 1) { + if (type !== \\"object\\" || value === null) { + throw new TypeError(\\"accessor decorators must return an object with get, set, or init properties or void 0\\"); + } + if (value.get !== undefined) { + assertCallable(value.get, \\"accessor.get\\"); + } + if (value.set !== undefined) { + assertCallable(value.set, \\"accessor.set\\"); + } + if (value.init !== undefined) { + assertCallable(value.init, \\"accessor.init\\"); + } + } else if (type !== \\"function\\") { + var hint; + if (kind === 0) { + hint = \\"field\\"; + } else if (kind === 10) { + hint = \\"class\\"; + } else { + hint = \\"method\\"; + } + throw new TypeError(hint + \\" decorators must return a function or void 0\\"); + } + } + function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) { + var decs = decInfo[0]; + var desc, init, value; + if (isPrivate) { + if (kind === 0 || kind === 1) { + desc = { + get: decInfo[3], + set: decInfo[4] + }; + } else if (kind === 3) { + desc = { + get: decInfo[3] + }; + } else if (kind === 4) { + desc = { + set: decInfo[3] + }; + } else { + desc = { + value: decInfo[3] + }; + } + } else if (kind !== 0) { + desc = Object.getOwnPropertyDescriptor(base, name); + } + if (kind === 1) { + value = { + get: desc.get, + set: desc.set + }; + } else if (kind === 2) { + value = desc.value; + } else if (kind === 3) { + value = desc.get; + } else if (kind === 4) { + value = desc.set; + } + var newValue, get, set; + if (typeof decs === \\"function\\") { + newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value); + if (newValue !== void 0) { + assertValidReturnValue(kind, newValue); + if (kind === 0) { + init = newValue; + } else if (kind === 1) { + init = newValue.init; + get = newValue.get || value.get; + set = newValue.set || value.set; + value = { + get: get, + set: set + }; + } else { + value = newValue; + } + } + } else { + for(var i = decs.length - 1; i >= 0; i--){ + var dec = decs[i]; + newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value); + if (newValue !== void 0) { + assertValidReturnValue(kind, newValue); + var newInit; + if (kind === 0) { + newInit = newValue; + } else if (kind === 1) { + newInit = newValue.init; + get = newValue.get || value.get; + set = newValue.set || value.set; + value = { + get: get, + set: set + }; + } else { + value = newValue; + } + if (newInit !== void 0) { + if (init === void 0) { + init = newInit; + } else if (typeof init === \\"function\\") { + init = [ + init, + newInit + ]; + } else { + init.push(newInit); + } + } + } + } + } + if (kind === 0 || kind === 1) { + if (init === void 0) { + init = function(instance, init) { + return init; + }; + } else if (typeof init !== \\"function\\") { + var ownInitializers = init; + init = function(instance, init) { + var value = init; + for(var i = 0; i < ownInitializers.length; i++){ + value = ownInitializers[i].call(instance, value); + } + return value; + }; + } else { + var originalInitializer = init; + init = function(instance, init) { + return originalInitializer.call(instance, init); + }; + } + ret.push(init); + } + if (kind !== 0) { + if (kind === 1) { + desc.get = value.get; + desc.set = value.set; + } else if (kind === 2) { + desc.value = value; + } else if (kind === 3) { + desc.get = value; + } else if (kind === 4) { + desc.set = value; + } + if (isPrivate) { + if (kind === 1) { + ret.push(function(instance, args) { + return value.get.call(instance, args); + }); + ret.push(function(instance, args) { + return value.set.call(instance, args); + }); + } else if (kind === 2) { + ret.push(value); + } else { + ret.push(function(instance, args) { + return value.call(instance, args); + }); + } + } else { + Object.defineProperty(base, name, desc); + } + } + } + function applyMemberDecs(Class, decInfos, metadata) { + var ret = []; + var protoInitializers; + var staticInitializers; + var existingProtoNonFields = new Map(); + var existingStaticNonFields = new Map(); + for(var i = 0; i < decInfos.length; i++){ + var decInfo = decInfos[i]; + if (!Array.isArray(decInfo)) continue; + var kind = decInfo[1]; + var name = decInfo[2]; + var isPrivate = decInfo.length > 3; + var isStatic = kind >= 5; + var base; + var initializers; + if (isStatic) { + base = Class; + kind = kind - 5; + if (kind !== 0) { + staticInitializers = staticInitializers || []; + initializers = staticInitializers; + } + } else { + base = Class.prototype; + if (kind !== 0) { + protoInitializers = protoInitializers || []; + initializers = protoInitializers; + } + } + if (kind !== 0 && !isPrivate) { + var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields; + var existingKind = existingNonFields.get(name) || 0; + if (existingKind === true || existingKind === 3 && kind !== 4 || existingKind === 4 && kind !== 3) { + throw new Error(\\"Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: \\" + name); + } else if (!existingKind && kind > 2) { + existingNonFields.set(name, kind); + } else { + existingNonFields.set(name, true); + } + } + applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata); + } + pushInitializers(ret, protoInitializers); + pushInitializers(ret, staticInitializers); + return ret; + } + function pushInitializers(ret, initializers) { + if (initializers) { + ret.push(function(instance) { + for(var i = 0; i < initializers.length; i++){ + initializers[i].call(instance); + } + return instance; + }); + } + } + function applyClassDecs(targetClass, classDecs, metadata) { + if (classDecs.length > 0) { + var initializers = []; + var newClass = targetClass; + var name = targetClass.name; + for(var i = classDecs.length - 1; i >= 0; i--){ + var decoratorFinishedRef = { + v: false + }; + try { + var nextNewClass = classDecs[i](newClass, { + kind: \\"class\\", + name: name, + addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef), + metadata + }); + } finally{ + decoratorFinishedRef.v = true; + } + if (nextNewClass !== undefined) { + assertValidReturnValue(10, nextNewClass); + newClass = nextNewClass; + } + } + return [ + defineMetadata(newClass, metadata), + function() { + for(var i = 0; i < initializers.length; i++){ + initializers[i].call(newClass); + } + } + ]; + } + } + function defineMetadata(Class, metadata) { + return Object.defineProperty(Class, Symbol.metadata || Symbol.for(\\"Symbol.metadata\\"), { + configurable: true, + enumerable: true, + value: metadata + }); + } + return function applyDecs2203R(targetClass, memberDecs, classDecs, parentClass) { + if (parentClass !== void 0) { + var parentMetadata = parentClass[Symbol.metadata || Symbol.for(\\"Symbol.metadata\\")]; + } + var metadata = Object.create(parentMetadata === void 0 ? null : parentMetadata); + var e = applyMemberDecs(targetClass, memberDecs, metadata); + if (!classDecs.length) defineMetadata(targetClass, metadata); + return { + e: e, + get c () { + return applyClassDecs(targetClass, classDecs, metadata); + } + }; + }; +} +function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) { + return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass); +} +var // @ts-expect-error +_init_name; +var printMemberName = function(target, memberName) { + console.log(memberName); +}; +var Person = function Person() { + _class_call_check(this, Person); + _define_property(this, \\"name\\", _init_name(this, \\"Jon\\")); +}; +var ref, ref1; +ref = _apply_decs_2203_r(Person, [ + [ + printMemberName, + 0, + \\"name\\" + ] +], []), ref1 = _sliced_to_array(ref.e, 1), _init_name = ref1[0]; +" +`; + exports[`rollup-plugin-swc3 swc (rollup 2) directive - include "use client" 1`] = ` "'use client'; function client() { @@ -268,6 +731,469 @@ export { foo }; " `; +exports[`rollup-plugin-swc3 swc (rollup 3) detect decorator for typescript5 1`] = ` +"function _array_like_to_array(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i]; + return arr2; +} +function _array_with_holes(arr) { + if (Array.isArray(arr)) return arr; +} +function _class_call_check(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError(\\"Cannot call a class as a function\\"); + } +} +function _define_property(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + return obj; +} +function _iterable_to_array_limit(arr, i) { + var _i = arr == null ? null : typeof Symbol !== \\"undefined\\" && arr[Symbol.iterator] || arr[\\"@@iterator\\"]; + if (_i == null) return; + var _arr = []; + var _n = true; + var _d = false; + var _s, _e; + try { + for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){ + _arr.push(_s.value); + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally{ + try { + if (!_n && _i[\\"return\\"] != null) _i[\\"return\\"](); + } finally{ + if (_d) throw _e; + } + } + return _arr; +} +function _non_iterable_rest() { + throw new TypeError(\\"Invalid attempt to destructure non-iterable instance.\\\\\\\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\\"); +} +function _sliced_to_array(arr, i) { + return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest(); +} +function _unsupported_iterable_to_array(o, minLen) { + if (!o) return; + if (typeof o === \\"string\\") return _array_like_to_array(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === \\"Object\\" && o.constructor) n = o.constructor.name; + if (n === \\"Map\\" || n === \\"Set\\") return Array.from(n); + if (n === \\"Arguments\\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen); +} +function applyDecs2203RFactory() { + function createAddInitializerMethod(initializers, decoratorFinishedRef) { + return function addInitializer(initializer) { + assertNotFinished(decoratorFinishedRef, \\"addInitializer\\"); + assertCallable(initializer, \\"An initializer\\"); + initializers.push(initializer); + }; + } + function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) { + var kindStr; + switch(kind){ + case 1: + kindStr = \\"accessor\\"; + break; + case 2: + kindStr = \\"method\\"; + break; + case 3: + kindStr = \\"getter\\"; + break; + case 4: + kindStr = \\"setter\\"; + break; + default: + kindStr = \\"field\\"; + } + var ctx = { + kind: kindStr, + name: isPrivate ? \\"#\\" + name : name, + static: isStatic, + private: isPrivate, + metadata: metadata + }; + var decoratorFinishedRef = { + v: false + }; + if (kind !== 0) { + ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef); + } + var get, set; + if (kind === 0) { + if (isPrivate) { + get = desc.get; + set = desc.set; + } else { + get = function() { + return this[name]; + }; + set = function(v) { + this[name] = v; + }; + } + } else if (kind === 2) { + get = function() { + return desc.value; + }; + } else { + if (kind === 1 || kind === 3) { + get = function() { + return desc.get.call(this); + }; + } + if (kind === 1 || kind === 4) { + set = function(v) { + desc.set.call(this, v); + }; + } + } + ctx.access = get && set ? { + get: get, + set: set + } : get ? { + get: get + } : { + set: set + }; + try { + return dec(value, ctx); + } finally{ + decoratorFinishedRef.v = true; + } + } + function assertNotFinished(decoratorFinishedRef, fnName) { + if (decoratorFinishedRef.v) { + throw new Error(\\"attempted to call \\" + fnName + \\" after decoration was finished\\"); + } + } + function assertCallable(fn, hint) { + if (typeof fn !== \\"function\\") { + throw new TypeError(hint + \\" must be a function\\"); + } + } + function assertValidReturnValue(kind, value) { + var type = typeof value; + if (kind === 1) { + if (type !== \\"object\\" || value === null) { + throw new TypeError(\\"accessor decorators must return an object with get, set, or init properties or void 0\\"); + } + if (value.get !== undefined) { + assertCallable(value.get, \\"accessor.get\\"); + } + if (value.set !== undefined) { + assertCallable(value.set, \\"accessor.set\\"); + } + if (value.init !== undefined) { + assertCallable(value.init, \\"accessor.init\\"); + } + } else if (type !== \\"function\\") { + var hint; + if (kind === 0) { + hint = \\"field\\"; + } else if (kind === 10) { + hint = \\"class\\"; + } else { + hint = \\"method\\"; + } + throw new TypeError(hint + \\" decorators must return a function or void 0\\"); + } + } + function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) { + var decs = decInfo[0]; + var desc, init, value; + if (isPrivate) { + if (kind === 0 || kind === 1) { + desc = { + get: decInfo[3], + set: decInfo[4] + }; + } else if (kind === 3) { + desc = { + get: decInfo[3] + }; + } else if (kind === 4) { + desc = { + set: decInfo[3] + }; + } else { + desc = { + value: decInfo[3] + }; + } + } else if (kind !== 0) { + desc = Object.getOwnPropertyDescriptor(base, name); + } + if (kind === 1) { + value = { + get: desc.get, + set: desc.set + }; + } else if (kind === 2) { + value = desc.value; + } else if (kind === 3) { + value = desc.get; + } else if (kind === 4) { + value = desc.set; + } + var newValue, get, set; + if (typeof decs === \\"function\\") { + newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value); + if (newValue !== void 0) { + assertValidReturnValue(kind, newValue); + if (kind === 0) { + init = newValue; + } else if (kind === 1) { + init = newValue.init; + get = newValue.get || value.get; + set = newValue.set || value.set; + value = { + get: get, + set: set + }; + } else { + value = newValue; + } + } + } else { + for(var i = decs.length - 1; i >= 0; i--){ + var dec = decs[i]; + newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value); + if (newValue !== void 0) { + assertValidReturnValue(kind, newValue); + var newInit; + if (kind === 0) { + newInit = newValue; + } else if (kind === 1) { + newInit = newValue.init; + get = newValue.get || value.get; + set = newValue.set || value.set; + value = { + get: get, + set: set + }; + } else { + value = newValue; + } + if (newInit !== void 0) { + if (init === void 0) { + init = newInit; + } else if (typeof init === \\"function\\") { + init = [ + init, + newInit + ]; + } else { + init.push(newInit); + } + } + } + } + } + if (kind === 0 || kind === 1) { + if (init === void 0) { + init = function(instance, init) { + return init; + }; + } else if (typeof init !== \\"function\\") { + var ownInitializers = init; + init = function(instance, init) { + var value = init; + for(var i = 0; i < ownInitializers.length; i++){ + value = ownInitializers[i].call(instance, value); + } + return value; + }; + } else { + var originalInitializer = init; + init = function(instance, init) { + return originalInitializer.call(instance, init); + }; + } + ret.push(init); + } + if (kind !== 0) { + if (kind === 1) { + desc.get = value.get; + desc.set = value.set; + } else if (kind === 2) { + desc.value = value; + } else if (kind === 3) { + desc.get = value; + } else if (kind === 4) { + desc.set = value; + } + if (isPrivate) { + if (kind === 1) { + ret.push(function(instance, args) { + return value.get.call(instance, args); + }); + ret.push(function(instance, args) { + return value.set.call(instance, args); + }); + } else if (kind === 2) { + ret.push(value); + } else { + ret.push(function(instance, args) { + return value.call(instance, args); + }); + } + } else { + Object.defineProperty(base, name, desc); + } + } + } + function applyMemberDecs(Class, decInfos, metadata) { + var ret = []; + var protoInitializers; + var staticInitializers; + var existingProtoNonFields = new Map(); + var existingStaticNonFields = new Map(); + for(var i = 0; i < decInfos.length; i++){ + var decInfo = decInfos[i]; + if (!Array.isArray(decInfo)) continue; + var kind = decInfo[1]; + var name = decInfo[2]; + var isPrivate = decInfo.length > 3; + var isStatic = kind >= 5; + var base; + var initializers; + if (isStatic) { + base = Class; + kind = kind - 5; + if (kind !== 0) { + staticInitializers = staticInitializers || []; + initializers = staticInitializers; + } + } else { + base = Class.prototype; + if (kind !== 0) { + protoInitializers = protoInitializers || []; + initializers = protoInitializers; + } + } + if (kind !== 0 && !isPrivate) { + var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields; + var existingKind = existingNonFields.get(name) || 0; + if (existingKind === true || existingKind === 3 && kind !== 4 || existingKind === 4 && kind !== 3) { + throw new Error(\\"Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: \\" + name); + } else if (!existingKind && kind > 2) { + existingNonFields.set(name, kind); + } else { + existingNonFields.set(name, true); + } + } + applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata); + } + pushInitializers(ret, protoInitializers); + pushInitializers(ret, staticInitializers); + return ret; + } + function pushInitializers(ret, initializers) { + if (initializers) { + ret.push(function(instance) { + for(var i = 0; i < initializers.length; i++){ + initializers[i].call(instance); + } + return instance; + }); + } + } + function applyClassDecs(targetClass, classDecs, metadata) { + if (classDecs.length > 0) { + var initializers = []; + var newClass = targetClass; + var name = targetClass.name; + for(var i = classDecs.length - 1; i >= 0; i--){ + var decoratorFinishedRef = { + v: false + }; + try { + var nextNewClass = classDecs[i](newClass, { + kind: \\"class\\", + name: name, + addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef), + metadata + }); + } finally{ + decoratorFinishedRef.v = true; + } + if (nextNewClass !== undefined) { + assertValidReturnValue(10, nextNewClass); + newClass = nextNewClass; + } + } + return [ + defineMetadata(newClass, metadata), + function() { + for(var i = 0; i < initializers.length; i++){ + initializers[i].call(newClass); + } + } + ]; + } + } + function defineMetadata(Class, metadata) { + return Object.defineProperty(Class, Symbol.metadata || Symbol.for(\\"Symbol.metadata\\"), { + configurable: true, + enumerable: true, + value: metadata + }); + } + return function applyDecs2203R(targetClass, memberDecs, classDecs, parentClass) { + if (parentClass !== void 0) { + var parentMetadata = parentClass[Symbol.metadata || Symbol.for(\\"Symbol.metadata\\")]; + } + var metadata = Object.create(parentMetadata === void 0 ? null : parentMetadata); + var e = applyMemberDecs(targetClass, memberDecs, metadata); + if (!classDecs.length) defineMetadata(targetClass, metadata); + return { + e: e, + get c () { + return applyClassDecs(targetClass, classDecs, metadata); + } + }; + }; +} +function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) { + return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass); +} +var // @ts-expect-error +_init_name; +var printMemberName = function(target, memberName) { + console.log(memberName); +}; +var Person = function Person() { + _class_call_check(this, Person); + _define_property(this, \\"name\\", _init_name(this, \\"Jon\\")); +}; +var ref, ref1; +ref = _apply_decs_2203_r(Person, [ + [ + printMemberName, + 0, + \\"name\\" + ] +], []), ref1 = _sliced_to_array(ref.e, 1), _init_name = ref1[0]; +" +`; + exports[`rollup-plugin-swc3 swc (rollup 3) directive - include "use client" 1`] = ` "'use client'; function client() { @@ -536,6 +1462,469 @@ export { foo }; " `; +exports[`rollup-plugin-swc3 swc (rollup 4) detect decorator for typescript5 1`] = ` +"function _array_like_to_array(arr, len) { + if (len == null || len > arr.length) len = arr.length; + for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i]; + return arr2; +} +function _array_with_holes(arr) { + if (Array.isArray(arr)) return arr; +} +function _class_call_check(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError(\\"Cannot call a class as a function\\"); + } +} +function _define_property(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true + }); + } else { + obj[key] = value; + } + return obj; +} +function _iterable_to_array_limit(arr, i) { + var _i = arr == null ? null : typeof Symbol !== \\"undefined\\" && arr[Symbol.iterator] || arr[\\"@@iterator\\"]; + if (_i == null) return; + var _arr = []; + var _n = true; + var _d = false; + var _s, _e; + try { + for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){ + _arr.push(_s.value); + if (i && _arr.length === i) break; + } + } catch (err) { + _d = true; + _e = err; + } finally{ + try { + if (!_n && _i[\\"return\\"] != null) _i[\\"return\\"](); + } finally{ + if (_d) throw _e; + } + } + return _arr; +} +function _non_iterable_rest() { + throw new TypeError(\\"Invalid attempt to destructure non-iterable instance.\\\\\\\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.\\"); +} +function _sliced_to_array(arr, i) { + return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest(); +} +function _unsupported_iterable_to_array(o, minLen) { + if (!o) return; + if (typeof o === \\"string\\") return _array_like_to_array(o, minLen); + var n = Object.prototype.toString.call(o).slice(8, -1); + if (n === \\"Object\\" && o.constructor) n = o.constructor.name; + if (n === \\"Map\\" || n === \\"Set\\") return Array.from(n); + if (n === \\"Arguments\\" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen); +} +function applyDecs2203RFactory() { + function createAddInitializerMethod(initializers, decoratorFinishedRef) { + return function addInitializer(initializer) { + assertNotFinished(decoratorFinishedRef, \\"addInitializer\\"); + assertCallable(initializer, \\"An initializer\\"); + initializers.push(initializer); + }; + } + function memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value) { + var kindStr; + switch(kind){ + case 1: + kindStr = \\"accessor\\"; + break; + case 2: + kindStr = \\"method\\"; + break; + case 3: + kindStr = \\"getter\\"; + break; + case 4: + kindStr = \\"setter\\"; + break; + default: + kindStr = \\"field\\"; + } + var ctx = { + kind: kindStr, + name: isPrivate ? \\"#\\" + name : name, + static: isStatic, + private: isPrivate, + metadata: metadata + }; + var decoratorFinishedRef = { + v: false + }; + if (kind !== 0) { + ctx.addInitializer = createAddInitializerMethod(initializers, decoratorFinishedRef); + } + var get, set; + if (kind === 0) { + if (isPrivate) { + get = desc.get; + set = desc.set; + } else { + get = function() { + return this[name]; + }; + set = function(v) { + this[name] = v; + }; + } + } else if (kind === 2) { + get = function() { + return desc.value; + }; + } else { + if (kind === 1 || kind === 3) { + get = function() { + return desc.get.call(this); + }; + } + if (kind === 1 || kind === 4) { + set = function(v) { + desc.set.call(this, v); + }; + } + } + ctx.access = get && set ? { + get: get, + set: set + } : get ? { + get: get + } : { + set: set + }; + try { + return dec(value, ctx); + } finally{ + decoratorFinishedRef.v = true; + } + } + function assertNotFinished(decoratorFinishedRef, fnName) { + if (decoratorFinishedRef.v) { + throw new Error(\\"attempted to call \\" + fnName + \\" after decoration was finished\\"); + } + } + function assertCallable(fn, hint) { + if (typeof fn !== \\"function\\") { + throw new TypeError(hint + \\" must be a function\\"); + } + } + function assertValidReturnValue(kind, value) { + var type = typeof value; + if (kind === 1) { + if (type !== \\"object\\" || value === null) { + throw new TypeError(\\"accessor decorators must return an object with get, set, or init properties or void 0\\"); + } + if (value.get !== undefined) { + assertCallable(value.get, \\"accessor.get\\"); + } + if (value.set !== undefined) { + assertCallable(value.set, \\"accessor.set\\"); + } + if (value.init !== undefined) { + assertCallable(value.init, \\"accessor.init\\"); + } + } else if (type !== \\"function\\") { + var hint; + if (kind === 0) { + hint = \\"field\\"; + } else if (kind === 10) { + hint = \\"class\\"; + } else { + hint = \\"method\\"; + } + throw new TypeError(hint + \\" decorators must return a function or void 0\\"); + } + } + function applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata) { + var decs = decInfo[0]; + var desc, init, value; + if (isPrivate) { + if (kind === 0 || kind === 1) { + desc = { + get: decInfo[3], + set: decInfo[4] + }; + } else if (kind === 3) { + desc = { + get: decInfo[3] + }; + } else if (kind === 4) { + desc = { + set: decInfo[3] + }; + } else { + desc = { + value: decInfo[3] + }; + } + } else if (kind !== 0) { + desc = Object.getOwnPropertyDescriptor(base, name); + } + if (kind === 1) { + value = { + get: desc.get, + set: desc.set + }; + } else if (kind === 2) { + value = desc.value; + } else if (kind === 3) { + value = desc.get; + } else if (kind === 4) { + value = desc.set; + } + var newValue, get, set; + if (typeof decs === \\"function\\") { + newValue = memberDec(decs, name, desc, initializers, kind, isStatic, isPrivate, metadata, value); + if (newValue !== void 0) { + assertValidReturnValue(kind, newValue); + if (kind === 0) { + init = newValue; + } else if (kind === 1) { + init = newValue.init; + get = newValue.get || value.get; + set = newValue.set || value.set; + value = { + get: get, + set: set + }; + } else { + value = newValue; + } + } + } else { + for(var i = decs.length - 1; i >= 0; i--){ + var dec = decs[i]; + newValue = memberDec(dec, name, desc, initializers, kind, isStatic, isPrivate, metadata, value); + if (newValue !== void 0) { + assertValidReturnValue(kind, newValue); + var newInit; + if (kind === 0) { + newInit = newValue; + } else if (kind === 1) { + newInit = newValue.init; + get = newValue.get || value.get; + set = newValue.set || value.set; + value = { + get: get, + set: set + }; + } else { + value = newValue; + } + if (newInit !== void 0) { + if (init === void 0) { + init = newInit; + } else if (typeof init === \\"function\\") { + init = [ + init, + newInit + ]; + } else { + init.push(newInit); + } + } + } + } + } + if (kind === 0 || kind === 1) { + if (init === void 0) { + init = function(instance, init) { + return init; + }; + } else if (typeof init !== \\"function\\") { + var ownInitializers = init; + init = function(instance, init) { + var value = init; + for(var i = 0; i < ownInitializers.length; i++){ + value = ownInitializers[i].call(instance, value); + } + return value; + }; + } else { + var originalInitializer = init; + init = function(instance, init) { + return originalInitializer.call(instance, init); + }; + } + ret.push(init); + } + if (kind !== 0) { + if (kind === 1) { + desc.get = value.get; + desc.set = value.set; + } else if (kind === 2) { + desc.value = value; + } else if (kind === 3) { + desc.get = value; + } else if (kind === 4) { + desc.set = value; + } + if (isPrivate) { + if (kind === 1) { + ret.push(function(instance, args) { + return value.get.call(instance, args); + }); + ret.push(function(instance, args) { + return value.set.call(instance, args); + }); + } else if (kind === 2) { + ret.push(value); + } else { + ret.push(function(instance, args) { + return value.call(instance, args); + }); + } + } else { + Object.defineProperty(base, name, desc); + } + } + } + function applyMemberDecs(Class, decInfos, metadata) { + var ret = []; + var protoInitializers; + var staticInitializers; + var existingProtoNonFields = new Map(); + var existingStaticNonFields = new Map(); + for(var i = 0; i < decInfos.length; i++){ + var decInfo = decInfos[i]; + if (!Array.isArray(decInfo)) continue; + var kind = decInfo[1]; + var name = decInfo[2]; + var isPrivate = decInfo.length > 3; + var isStatic = kind >= 5; + var base; + var initializers; + if (isStatic) { + base = Class; + kind = kind - 5; + if (kind !== 0) { + staticInitializers = staticInitializers || []; + initializers = staticInitializers; + } + } else { + base = Class.prototype; + if (kind !== 0) { + protoInitializers = protoInitializers || []; + initializers = protoInitializers; + } + } + if (kind !== 0 && !isPrivate) { + var existingNonFields = isStatic ? existingStaticNonFields : existingProtoNonFields; + var existingKind = existingNonFields.get(name) || 0; + if (existingKind === true || existingKind === 3 && kind !== 4 || existingKind === 4 && kind !== 3) { + throw new Error(\\"Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: \\" + name); + } else if (!existingKind && kind > 2) { + existingNonFields.set(name, kind); + } else { + existingNonFields.set(name, true); + } + } + applyMemberDec(ret, base, decInfo, name, kind, isStatic, isPrivate, initializers, metadata); + } + pushInitializers(ret, protoInitializers); + pushInitializers(ret, staticInitializers); + return ret; + } + function pushInitializers(ret, initializers) { + if (initializers) { + ret.push(function(instance) { + for(var i = 0; i < initializers.length; i++){ + initializers[i].call(instance); + } + return instance; + }); + } + } + function applyClassDecs(targetClass, classDecs, metadata) { + if (classDecs.length > 0) { + var initializers = []; + var newClass = targetClass; + var name = targetClass.name; + for(var i = classDecs.length - 1; i >= 0; i--){ + var decoratorFinishedRef = { + v: false + }; + try { + var nextNewClass = classDecs[i](newClass, { + kind: \\"class\\", + name: name, + addInitializer: createAddInitializerMethod(initializers, decoratorFinishedRef), + metadata + }); + } finally{ + decoratorFinishedRef.v = true; + } + if (nextNewClass !== undefined) { + assertValidReturnValue(10, nextNewClass); + newClass = nextNewClass; + } + } + return [ + defineMetadata(newClass, metadata), + function() { + for(var i = 0; i < initializers.length; i++){ + initializers[i].call(newClass); + } + } + ]; + } + } + function defineMetadata(Class, metadata) { + return Object.defineProperty(Class, Symbol.metadata || Symbol.for(\\"Symbol.metadata\\"), { + configurable: true, + enumerable: true, + value: metadata + }); + } + return function applyDecs2203R(targetClass, memberDecs, classDecs, parentClass) { + if (parentClass !== void 0) { + var parentMetadata = parentClass[Symbol.metadata || Symbol.for(\\"Symbol.metadata\\")]; + } + var metadata = Object.create(parentMetadata === void 0 ? null : parentMetadata); + var e = applyMemberDecs(targetClass, memberDecs, metadata); + if (!classDecs.length) defineMetadata(targetClass, metadata); + return { + e: e, + get c () { + return applyClassDecs(targetClass, classDecs, metadata); + } + }; + }; +} +function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) { + return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass); +} +var // @ts-expect-error +_init_name; +var printMemberName = function(target, memberName) { + console.log(memberName); +}; +var Person = function Person() { + _class_call_check(this, Person); + _define_property(this, \\"name\\", _init_name(this, \\"Jon\\")); +}; +var ref, ref1; +ref = _apply_decs_2203_r(Person, [ + [ + printMemberName, + 0, + \\"name\\" + ] +], []), ref1 = _sliced_to_array(ref.e, 1), _init_name = ref1[0]; +" +`; + exports[`rollup-plugin-swc3 swc (rollup 4) directive - include "use client" 1`] = ` "'use client'; function client() { diff --git a/test/fixtures/decorators/index.ts b/test/fixtures/decorators/index.ts new file mode 100644 index 0000000..94adbb9 --- /dev/null +++ b/test/fixtures/decorators/index.ts @@ -0,0 +1,9 @@ +const printMemberName = (target: any, memberName: string) => { + console.log(memberName); + }; + +class Person { + // @ts-expect-error + @printMemberName + name: string = "Jon"; +} \ No newline at end of file diff --git a/test/index.ts b/test/index.ts index 246bad4..b65da0e 100644 --- a/test/index.ts +++ b/test/index.ts @@ -337,6 +337,15 @@ const tests = (rollupImpl: typeof rollup2 | typeof rollup3 | typeof rollup4, iso rollupInvriant(output.find(i => i.fileName === 'client.js') as any).code.should.matchSnapshot(); rollupInvriant(output.find(i => i.fileName === 'server.js') as any).code.should.matchSnapshot(); }); + + it('detect decorator for typescript5', async () => { + const dir = await fixture('decorators'); + (await build( + rollupImpl, + { tsconfig: false }, + { input: './index.ts', dir } + ))[0].code.should.matchSnapshot(); + }); }; describe('rollup-plugin-swc3', () => { diff --git a/tools/build.ts b/tools/build.ts index 0a8795f..95d55cc 100644 --- a/tools/build.ts +++ b/tools/build.ts @@ -1,6 +1,7 @@ import { builtinModules } from 'module'; import { rollup, VERSION } from 'rollup'; +import type { Plugin } from 'rollup'; import dts from 'rollup-plugin-dts'; import { swc, defineRollupSwcOption } from '../src/index'; @@ -9,6 +10,24 @@ import pkg from '../package.json'; const deps = Object.keys(pkg.dependencies); const peerDeps = Object.keys(pkg.peerDependencies); +// Trasnform require.resolve +function injectShims(): Plugin { + return { + name: 'shim', + renderChunk(code, _, opt) { + if (opt.format === 'es') { + const shims = ` + import { createRequire } from 'module'; + const _require = createRequire(import.meta.url); + `; + code = code.replace('require.resolve', '_require.resolve'); + code = `${shims}\r\n${code}`; + return code; + } + } + }; +} + async function main() { const external = [...deps, ...peerDeps, ...builtinModules]; @@ -16,7 +35,7 @@ async function main() { const bundle = await rollup({ input: './src/index.ts', external, - plugins: [swc(defineRollupSwcOption({ + plugins: [injectShims(), swc(defineRollupSwcOption({ jsc: { target: 'es2019', minify: { From 4b0011123700d7768f130a96962fc68214aa47bb Mon Sep 17 00:00:00 2001 From: kanno <812137533@qq.com> Date: Fri, 24 Nov 2023 20:27:00 +0800 Subject: [PATCH 3/6] chore: remove unnecessary code --- src/index.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/index.ts b/src/index.ts index d4d1e93..0754032 100644 --- a/src/index.ts +++ b/src/index.ts @@ -46,13 +46,6 @@ const fileExists = (path: string) => { .catch(() => false); }; -const lookup = (entry: string, target: string): string => { - const dir = dirname(entry); - const targetFile = join(dir, target); - if (fs.existsSync(targetFile)) return targetFile; - return lookup(dir, target); -}; - function swc(options: PluginOptions = {}): RollupPlugin { const filter = createFilter( options.include || INCLUDE_REGEXP, @@ -116,8 +109,7 @@ function swc(options: PluginOptions = {}): RollupPlugin { let enaleExperimentalDecorators = false; if (isTypeScript) { try { - const tsPath = require.resolve('typescript', { paths: [process.cwd()] }); - const packageJsonPath = lookup(tsPath, 'package.json'); + const packageJsonPath = require.resolve('typescript/package.json', { paths: [process.cwd()] }); const { version } = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); const [major] = version.split('.'); // typescript 5.x From c3e936acfed46499a6639a735d42897e46a29fc4 Mon Sep 17 00:00:00 2001 From: kanno <812137533@qq.com> Date: Sat, 25 Nov 2023 19:01:17 +0800 Subject: [PATCH 4/6] chore: friendly advice Co-authored-by: Pionxzh --- src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.ts b/src/index.ts index 0754032..2cb2993 100644 --- a/src/index.ts +++ b/src/index.ts @@ -116,7 +116,7 @@ function swc(options: PluginOptions = {}): RollupPlugin { if (+major >= 5) enaleExperimentalDecorators = true; } catch { this.warn({ - message: 'Can\'t find typescript, please Check typescript has been installed.', + message: 'Failed to find TypeScript. Please check if TypeScript has been installed.', pluginCode: 'SWC_TYPESCRIPT_NOT_EXISTS' }); } From a9dbbc8d6c2105806c6a0612f763385b6ae71a02 Mon Sep 17 00:00:00 2001 From: kanno <812137533@qq.com> Date: Sat, 25 Nov 2023 19:13:42 +0800 Subject: [PATCH 5/6] fix: typo --- src/index.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index 2cb2993..91af495 100644 --- a/src/index.ts +++ b/src/index.ts @@ -106,14 +106,14 @@ function swc(options: PluginOptions = {}): RollupPlugin { ? {} : getOptions(this, dirname(id), options.tsconfig); - let enaleExperimentalDecorators = false; + let enableExperimentalDecorators = false; if (isTypeScript) { try { const packageJsonPath = require.resolve('typescript/package.json', { paths: [process.cwd()] }); const { version } = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); const [major] = version.split('.'); // typescript 5.x - if (+major >= 5) enaleExperimentalDecorators = true; + if (+major >= 5) enableExperimentalDecorators = true; } catch { this.warn({ message: 'Failed to find TypeScript. Please check if TypeScript has been installed.', @@ -133,12 +133,12 @@ function swc(options: PluginOptions = {}): RollupPlugin { parser: { syntax: isTypeScript ? 'typescript' : 'ecmascript', [isTypeScript ? 'tsx' : 'jsx']: isTypeScript ? isTsx : isJsx, - decorators: enaleExperimentalDecorators || tsconfigOptions.experimentalDecorators + decorators: enableExperimentalDecorators || tsconfigOptions.experimentalDecorators }, transform: { decoratorMetadata: tsconfigOptions.emitDecoratorMetadata, // @ts-expect-error -- swc types loose this :( - decoratorVersion: enaleExperimentalDecorators ? '2022-03' : '2021-12', + decoratorVersion: enableExperimentalDecorators ? '2022-03' : '2021-12', react: { runtime: useReact17NewTransform ? 'automatic' From e413ef7c259d17f8d35e53428decbc2deca141ca Mon Sep 17 00:00:00 2001 From: kanno <812137533@qq.com> Date: Sun, 26 Nov 2023 13:14:30 +0800 Subject: [PATCH 6/6] refactor: hoist judgment logic --- src/index.ts | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/src/index.ts b/src/index.ts index 91af495..b8f2956 100644 --- a/src/index.ts +++ b/src/index.ts @@ -66,6 +66,16 @@ function swc(options: PluginOptions = {}): RollupPlugin { return null; }; + let enableExperimentalDecorators = false; + try { + const packageJsonPath = require.resolve('typescript/package.json', { paths: [process.cwd()] }); + const { version } = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); + const [major] = version.split('.'); + // typescript 5.x + if (+major >= 5) enableExperimentalDecorators = true; + } catch { + } + return { name: 'swc', async resolveId(importee, importer) { @@ -106,22 +116,6 @@ function swc(options: PluginOptions = {}): RollupPlugin { ? {} : getOptions(this, dirname(id), options.tsconfig); - let enableExperimentalDecorators = false; - if (isTypeScript) { - try { - const packageJsonPath = require.resolve('typescript/package.json', { paths: [process.cwd()] }); - const { version } = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); - const [major] = version.split('.'); - // typescript 5.x - if (+major >= 5) enableExperimentalDecorators = true; - } catch { - this.warn({ - message: 'Failed to find TypeScript. Please check if TypeScript has been installed.', - pluginCode: 'SWC_TYPESCRIPT_NOT_EXISTS' - }); - } - } - // TODO: SWC is about to add "preserve" jsx // https://github.com/swc-project/swc/pull/5661 // Respect "preserve" after swc adds the support