├── .github └── workflows │ └── main.yml ├── .gitignore ├── README.md ├── dist ├── compiler │ ├── entry │ │ ├── data │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ ├── manager │ │ │ ├── generate │ │ │ │ ├── index.d.ts │ │ │ │ └── index.js │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ ├── name │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ ├── plugin │ │ │ ├── app-data │ │ │ │ ├── index.d.ts │ │ │ │ └── index.js │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── require-chunk-plugin │ │ │ │ ├── index.d.ts │ │ │ │ └── index.js │ │ │ └── split-package-plugin │ │ │ │ ├── index.d.ts │ │ │ │ └── index.js │ │ └── utils │ │ │ ├── index.d.ts │ │ │ └── index.js │ ├── index.d.ts │ ├── index.js │ ├── module │ │ ├── data │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ └── loader │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── state │ │ │ ├── identifier │ │ │ │ ├── event │ │ │ │ │ ├── index.d.ts │ │ │ │ │ └── index.js │ │ │ │ ├── index.d.ts │ │ │ │ ├── index.js │ │ │ │ ├── map │ │ │ │ │ ├── index.d.ts │ │ │ │ │ └── index.js │ │ │ │ ├── prop │ │ │ │ │ ├── index.d.ts │ │ │ │ │ └── index.js │ │ │ │ ├── util.d.ts │ │ │ │ └── util.js │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ └── map-scope │ │ │ │ ├── index.d.ts │ │ │ │ └── index.js │ │ │ └── transform │ │ │ ├── add-ready │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ │ ├── gen-data │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── json │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ │ ├── properties │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ │ ├── render │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ │ └── wxml │ │ │ ├── index.d.ts │ │ │ └── index.js │ ├── ts-transformer │ │ ├── fix-vue3-this │ │ │ ├── index.d.ts │ │ │ ├── index.js │ │ │ ├── state.d.ts │ │ │ └── state.js │ │ ├── util.d.ts │ │ └── util.js │ └── value-loader │ │ ├── index.d.ts │ │ └── index.js └── runtime │ ├── @vue_reactivity │ ├── index.d.ts │ └── index.js │ ├── base │ ├── index.d.ts │ ├── index.js │ └── store │ │ ├── diff │ │ ├── index.d.ts │ │ ├── index.js │ │ └── state │ │ │ ├── index.d.ts │ │ │ └── index.js │ │ ├── index.d.ts │ │ └── index.js │ ├── component │ ├── index.d.ts │ └── index.js │ ├── index.d.ts │ ├── index.js │ ├── page │ ├── index.d.ts │ └── index.js │ ├── reactivity │ ├── define │ │ ├── index.d.ts │ │ └── index.js │ ├── index.d.ts │ ├── index.js │ └── proxy │ │ ├── index.d.ts │ │ └── index.js │ └── utils │ ├── index.d.ts │ └── index.js ├── doc └── worker.svg ├── package.json └── src ├── compiler ├── entry │ ├── data │ │ └── index.ts │ ├── manager │ │ ├── generate │ │ │ └── index.ts │ │ └── index.ts │ ├── name │ │ └── index.ts │ ├── plugin │ │ ├── app-data │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── require-chunk-plugin │ │ │ └── index.ts │ │ └── split-package-plugin │ │ │ └── index.ts │ └── utils │ │ └── index.ts ├── index.ts ├── module │ ├── data │ │ └── index.ts │ └── loader │ │ ├── index.ts │ │ ├── state │ │ ├── identifier │ │ │ ├── event │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── map │ │ │ │ └── index.ts │ │ │ ├── prop │ │ │ │ └── index.ts │ │ │ └── util.ts │ │ ├── index.ts │ │ └── map-scope │ │ │ └── index.ts │ │ └── transform │ │ ├── add-ready │ │ └── index.ts │ │ ├── gen-data │ │ └── index.ts │ │ ├── index.ts │ │ ├── json │ │ └── index.ts │ │ ├── properties │ │ └── index.ts │ │ ├── render │ │ └── index.ts │ │ └── wxml │ │ └── index.ts ├── ts-transformer │ ├── fix-vue3-this │ │ ├── index.ts │ │ └── state.ts │ └── util.ts ├── tsconfig.json └── value-loader │ └── index.ts └── runtime ├── @vue_reactivity ├── index.d.ts └── index.ts ├── base ├── index.ts └── store │ ├── diff │ ├── index.ts │ └── state │ │ └── index.ts │ └── index.ts ├── component └── index.ts ├── index.ts ├── page └── index.ts ├── reactivity ├── define │ └── index.ts ├── index.ts └── proxy │ └── index.ts ├── tsconfig.json ├── typings ├── component.config.d.ts ├── event.d.ts ├── index.d.ts └── types │ ├── index.d.ts │ └── wx │ ├── index.d.ts │ ├── lib.wx.api.d.ts │ ├── lib.wx.app.d.ts │ ├── lib.wx.behavior.d.ts │ ├── lib.wx.cloud.d.ts │ ├── lib.wx.component.d.ts │ └── lib.wx.page.d.ts └── utils └── index.ts /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: publish package 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - package.json 9 | 10 | jobs: 11 | publish-gpr: 12 | runs-on: ubuntu-latest 13 | permissions: 14 | contents: read 15 | packages: write 16 | steps: 17 | - uses: actions/checkout@v3 18 | - uses: actions/setup-node@v3 19 | with: 20 | node-version: 16 21 | registry-url: https://registry.npmjs.org/ 22 | - run: npm publish 23 | env: 24 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | old_code/ 4 | 5 | # Editor directories and files 6 | .idea 7 | .vscode 8 | *.suo 9 | *.ntvs* 10 | *.njsproj 11 | *.sln 12 | 13 | Thumbs.db 14 | work.txt 15 | package-lock.json -------------------------------------------------------------------------------- /dist/compiler/entry/data/index.d.ts: -------------------------------------------------------------------------------- 1 | import ModuleData from "../../module/data"; 2 | import webpack from 'webpack'; 3 | export default class EntryData { 4 | name: string; 5 | isPage: boolean; 6 | components: Record; 7 | module: ModuleData; 8 | path: string; 9 | private sourceCache; 10 | private getSource; 11 | constructor({ name, path, page, components }: { 12 | name: string; 13 | path: string; 14 | page: boolean; 15 | components: Record; 16 | }); 17 | private getUsingComponents; 18 | private getJSON; 19 | getFiles(): { 20 | file: string; 21 | source: webpack.sources.Source; 22 | }[]; 23 | } 24 | -------------------------------------------------------------------------------- /dist/compiler/entry/data/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const data_1 = __importDefault(require("../../module/data")); 7 | const webpack_1 = __importDefault(require("webpack")); 8 | const lodash_merge_1 = __importDefault(require("lodash.merge")); 9 | class EntryData { 10 | getSource(type, code) { 11 | var _a; 12 | if (((_a = this.sourceCache[type]) === null || _a === void 0 ? void 0 : _a.code) === code) { 13 | return this.sourceCache[type].source; 14 | } 15 | else { 16 | this.sourceCache[type] = { 17 | code, 18 | source: new webpack_1.default.sources.CachedSource(new webpack_1.default.sources.RawSource(code)) 19 | }; 20 | return this.sourceCache[type].source; 21 | } 22 | } 23 | constructor({ name, path, page, components }) { 24 | this.sourceCache = {}; 25 | this.path = path; 26 | this.name = name; 27 | this.isPage = page; 28 | this.components = components; 29 | this.module = data_1.default.Pick(path); 30 | } 31 | getUsingComponents() { 32 | const components = {}; 33 | for (const name in this.components) { 34 | components[name] = '/' + this.components[name].replace(/\.js$/, '').replace(/\\/g, '/'); 35 | } 36 | return components; 37 | } 38 | getJSON() { 39 | return JSON.stringify((0, lodash_merge_1.default)({}, this.module.json, { 40 | usingComponents: this.getUsingComponents(), 41 | component: this.isPage ? undefined : true 42 | }), null, 2); 43 | } 44 | getFiles() { 45 | const files = []; 46 | const filename = this.name.replace(/\.js$/, ''); 47 | files.push({ 48 | file: filename + '.wxml', 49 | source: this.getSource('wxml', this.module.wxml) 50 | }); 51 | files.push({ 52 | file: filename + '.json', 53 | source: this.getSource('json', this.getJSON()) 54 | }); 55 | if (this.module.wxss) { 56 | files.push({ 57 | file: filename + '.wxss', 58 | source: this.getSource('wxss', this.module.wxss) 59 | }); 60 | } 61 | if (this.module.wxs) { 62 | files.push({ 63 | file: filename + '.wxs', 64 | source: this.getSource('wxs', this.module.wxs) 65 | }); 66 | } 67 | return files; 68 | } 69 | } 70 | exports.default = EntryData; 71 | -------------------------------------------------------------------------------- /dist/compiler/entry/manager/generate/index.d.ts: -------------------------------------------------------------------------------- 1 | type page = { 2 | path: string; 3 | root?: string; 4 | independent?: boolean; 5 | }; 6 | type entry = { 7 | path: string; 8 | root?: string; 9 | page: boolean; 10 | name: string; 11 | components: Record; 12 | }; 13 | export default function generateEntry(pages: page[], getName: (params: { 14 | path: string; 15 | root?: string; 16 | component?: boolean; 17 | }) => string): entry[]; 18 | export {}; 19 | -------------------------------------------------------------------------------- /dist/compiler/entry/manager/generate/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const data_1 = __importDefault(require("../../../module/data")); 7 | function generateNodes(pages) { 8 | const dict = {}; 9 | const getNode = (path) => { 10 | if (!dict[path]) { 11 | const node = { 12 | path, 13 | children: {}, 14 | parent: [] 15 | }; 16 | dict[path] = node; 17 | } 18 | return dict[path]; 19 | }; 20 | const addRelation = (node) => { 21 | const children = data_1.default.Pick(node.path).getChildren(); 22 | for (const key in children) { 23 | const child = getNode(children[key]); 24 | child.parent.push(node); 25 | node.children[key] = child; 26 | addRelation(child); 27 | } 28 | }; 29 | pages.forEach(page => { 30 | addRelation(getNode(page.path)); 31 | }); 32 | return dict; 33 | } 34 | //todo 需要优化 35 | function generateEntry(pages, getName) { 36 | let refs = generateNodes(pages); 37 | let packageSet = {}; 38 | pages.forEach(page => { 39 | const set = packageSet[page.path] = new Set(); 40 | set.add(page.root); 41 | }); 42 | const getPackages = (node) => { 43 | if (!packageSet[node.path]) { 44 | const set = packageSet[node.path] = new Set; 45 | node.parent.forEach(parent => { 46 | const packages = getPackages(parent); 47 | if (packages.has(undefined)) { 48 | set.add(undefined); 49 | } 50 | else { 51 | packages.forEach(value => { 52 | set.add(value); 53 | }); 54 | } 55 | }); 56 | } 57 | return packageSet[node.path]; 58 | }; 59 | const data = []; 60 | let dict = {}; 61 | const getEntry = (path, root, independent = false) => { 62 | const pack = packageSet[path].has(undefined) && !independent ? undefined : root; 63 | const rootEntry = dict[pack || ''] = dict[pack || ''] || {}; 64 | if (!rootEntry[path]) { 65 | data.push(rootEntry[path] = { 66 | path, 67 | root: pack, 68 | page: false, 69 | name: '', 70 | components: {} 71 | }); 72 | } 73 | return rootEntry[path]; 74 | }; 75 | const load = (node, independentRoot) => { 76 | const packages = getPackages(node); 77 | if (independentRoot) { 78 | packages.delete(independentRoot); 79 | } 80 | const entries = packages.has(undefined) ? [getEntry(node.path)] : [...packages].map(root => getEntry(node.path, root)); 81 | if (independentRoot) { 82 | entries.push(getEntry(node.path, independentRoot, true)); 83 | } 84 | for (const key in node.children) { 85 | const child = node.children[key]; 86 | load(child, independentRoot); 87 | entries.forEach(entry => { 88 | entry.components[key] = getEntry(child.path, entry.root, !!independentRoot); 89 | }); 90 | } 91 | return entries; 92 | }; 93 | pages.forEach(page => { 94 | load(refs[page.path], page.independent ? page.root : undefined).forEach(entry => { 95 | entry.page = true; 96 | }); 97 | }); 98 | data.forEach(item => { 99 | item.name = getName({ 100 | path: item.path, 101 | root: item.root, 102 | component: !item.page 103 | }); 104 | }); 105 | refs = null; 106 | packageSet = null; 107 | dict = null; 108 | return data; 109 | } 110 | exports.default = generateEntry; 111 | -------------------------------------------------------------------------------- /dist/compiler/entry/manager/index.d.ts: -------------------------------------------------------------------------------- 1 | import EntryData from '../data'; 2 | type oldData = { 3 | path: string; 4 | name: string; 5 | }; 6 | export default class EntryManager { 7 | data: EntryData[]; 8 | private nameCache; 9 | private pages; 10 | private loaded; 11 | loadOld(callback: (item: oldData) => void): void; 12 | needLoad(data: EntryData): boolean; 13 | addPage(path: string, root?: string, independent?: boolean): string; 14 | getRoot(name: string): string | undefined; 15 | setContext(context: string): void; 16 | getNotUsed(): string[]; 17 | generate(): void; 18 | clear(): void; 19 | } 20 | export {}; 21 | -------------------------------------------------------------------------------- /dist/compiler/entry/manager/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const data_1 = __importDefault(require("../data")); 7 | const name_1 = __importDefault(require("../name")); 8 | const generate_1 = __importDefault(require("./generate")); 9 | class EntryManager { 10 | constructor() { 11 | this.data = []; 12 | this.nameCache = new name_1.default; 13 | this.pages = []; 14 | this.loaded = new Set(); 15 | } 16 | loadOld(callback) { 17 | this.loaded.clear(); 18 | this.data 19 | .filter(item => !item.isPage) 20 | .forEach(item => { 21 | this.loaded.add(item.name); 22 | callback({ 23 | path: item.path, 24 | name: item.name 25 | }); 26 | }); 27 | this.clear(); 28 | } 29 | needLoad(data) { 30 | return !data.isPage && !this.loaded.has(data.name); 31 | } 32 | addPage(path, root, independent) { 33 | const name = this.nameCache.get({ path, root }); 34 | this.pages.push({ 35 | path, root, independent 36 | }); 37 | return name; 38 | } 39 | getRoot(name) { 40 | return this.nameCache.getPackage(name); 41 | } 42 | setContext(context) { 43 | this.nameCache.setContext(context); 44 | } 45 | getNotUsed() { 46 | const used = new Set(this.data.map(item => item.name)); 47 | const notUsed = []; 48 | this.loaded.forEach(name => { 49 | if (!used.has(name)) { 50 | notUsed.push(name); 51 | } 52 | }); 53 | return notUsed; 54 | } 55 | generate() { 56 | this.data = (0, generate_1.default)(this.pages, (params) => { 57 | return this.nameCache.get(params); 58 | }) 59 | .map(entry => { 60 | const components = {}; 61 | for (const key in entry.components) { 62 | components[key] = entry.components[key].name; 63 | } 64 | return new data_1.default({ 65 | name: entry.name, 66 | path: entry.path, 67 | page: entry.page, 68 | components 69 | }); 70 | }); 71 | } 72 | clear() { 73 | this.pages = []; 74 | this.data = []; 75 | } 76 | } 77 | exports.default = EntryManager; 78 | -------------------------------------------------------------------------------- /dist/compiler/entry/name/index.d.ts: -------------------------------------------------------------------------------- 1 | export default class EntryNameCache { 2 | private context; 3 | private packageDict; 4 | private cache; 5 | setContext(context: string): void; 6 | get(params: { 7 | path: string; 8 | root?: string; 9 | component?: boolean; 10 | }): string; 11 | getPackage(name: string): string | undefined; 12 | } 13 | -------------------------------------------------------------------------------- /dist/compiler/entry/name/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const path_1 = __importDefault(require("path")); 7 | class EntryNameCache { 8 | constructor() { 9 | this.context = ''; 10 | this.packageDict = {}; 11 | this.cache = {}; 12 | } 13 | setContext(context) { 14 | this.context = context; 15 | } 16 | get(params) { 17 | const key = params.root || ''; 18 | if (!this.cache[key]) { 19 | this.cache[key] = {}; 20 | } 21 | if (!this.cache[key][params.path]) { 22 | const name = path_1.default.join(params.root || '', params.component ? 'components' : '', path_1.default.relative(path_1.default.join(this.context, params.root || ''), params.path) 23 | .replace(/\.\.[\\/]/g, '@').replace(/\.[\\/]/g, '')).replace(/\.tsx$/, '.js'); 24 | this.cache[key][params.path] = name; 25 | this.packageDict[name] = params.root; 26 | } 27 | return this.cache[key][params.path]; 28 | } 29 | getPackage(name) { 30 | return this.packageDict[name]; 31 | } 32 | } 33 | exports.default = EntryNameCache; 34 | -------------------------------------------------------------------------------- /dist/compiler/entry/plugin/app-data/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import webpack from 'webpack'; 3 | export default class AppData { 4 | name: string; 5 | path: string; 6 | context: string; 7 | source: webpack.sources.Source | null; 8 | setContext(context: string): void; 9 | private ignorePattern; 10 | setIgnore(data?: Array): void; 11 | private ignore; 12 | private entries; 13 | private content; 14 | private roots; 15 | private independents; 16 | private update; 17 | getEntries(content: string | Buffer): { 18 | root?: string | undefined; 19 | path: string; 20 | independent?: boolean | undefined; 21 | }[]; 22 | getRoots(): string[]; 23 | isIndependent(root: string): boolean; 24 | } 25 | -------------------------------------------------------------------------------- /dist/compiler/entry/plugin/app-data/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const path_1 = __importDefault(require("path")); 7 | const webpack_1 = __importDefault(require("webpack")); 8 | class AppData { 9 | constructor() { 10 | this.name = 'app.json'; 11 | this.path = ''; 12 | this.context = ''; 13 | this.source = null; 14 | this.ignorePattern = []; 15 | this.entries = []; 16 | this.content = ''; 17 | this.roots = []; 18 | this.independents = new Set(); 19 | } 20 | setContext(context) { 21 | this.context = context; 22 | this.path = path_1.default.resolve(context, this.name); 23 | } 24 | setIgnore(data) { 25 | this.ignorePattern = data || []; 26 | } 27 | ignore(page) { 28 | return this.ignorePattern.some(item => { 29 | if (typeof item === 'string') { 30 | return page === item; 31 | } 32 | else { 33 | return item.test(page); 34 | } 35 | }); 36 | } 37 | update() { 38 | var _a, _b, _c, _d; 39 | this.entries = []; 40 | this.roots = []; 41 | this.independents.clear(); 42 | const data = JSON.parse(this.content); 43 | if (this.ignorePattern.length > 0) { 44 | data.pages = (_a = data.pages) === null || _a === void 0 ? void 0 : _a.filter(page => !this.ignore(page)); 45 | (_b = data.subpackages) === null || _b === void 0 ? void 0 : _b.forEach(({ root, pages }) => { 46 | pages = pages.filter(page => !this.ignore(root + '/' + page)); 47 | }); 48 | } 49 | this.source = new webpack_1.default.sources.CachedSource(new webpack_1.default.sources.RawSource(JSON.stringify(data, null, 2))); 50 | (_c = data.pages) === null || _c === void 0 ? void 0 : _c.forEach(item => { 51 | this.entries.push({ 52 | path: path_1.default.resolve(this.context, item + '.tsx') 53 | }); 54 | }); 55 | (_d = data.subpackages) === null || _d === void 0 ? void 0 : _d.forEach(({ root, pages, independent }) => { 56 | this.roots.push(root); 57 | independent && this.independents.add(root); 58 | pages.forEach(item => { 59 | this.entries.push({ 60 | root, 61 | path: path_1.default.resolve(this.context, root, item + '.tsx'), 62 | independent 63 | }); 64 | }); 65 | }); 66 | } 67 | getEntries(content) { 68 | if (typeof content !== 'string') { 69 | content = content.toString(); 70 | } 71 | if (this.content !== content) { 72 | this.content = content; 73 | this.update(); 74 | } 75 | return this.entries; 76 | } 77 | getRoots() { 78 | return this.roots; 79 | } 80 | isIndependent(root) { 81 | return this.independents.has(root); 82 | } 83 | } 84 | exports.default = AppData; 85 | -------------------------------------------------------------------------------- /dist/compiler/entry/plugin/index.d.ts: -------------------------------------------------------------------------------- 1 | import webpack from 'webpack'; 2 | export default class MPEntryPlugin { 3 | private options; 4 | private name; 5 | private manager; 6 | private app; 7 | constructor(options?: { 8 | ignore?: Array; 9 | }); 10 | apply(compiler: webpack.Compiler): void; 11 | } 12 | -------------------------------------------------------------------------------- /dist/compiler/entry/plugin/require-chunk-plugin/index.d.ts: -------------------------------------------------------------------------------- 1 | import webpack from 'webpack'; 2 | type options = { 3 | calcPath: (entry: webpack.Chunk, chunk: webpack.Chunk) => string; 4 | addPath: (paths: string[]) => string; 5 | }; 6 | export default class RequireChunkPlugin { 7 | private name; 8 | private options; 9 | constructor(options?: Partial); 10 | apply(compiler: webpack.Compiler): void; 11 | } 12 | export {}; 13 | -------------------------------------------------------------------------------- /dist/compiler/entry/plugin/require-chunk-plugin/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const webpack_1 = __importDefault(require("webpack")); 7 | const path_1 = __importDefault(require("path")); 8 | const ensure_posix_path_1 = __importDefault(require("ensure-posix-path")); 9 | class RequireChunkPlugin { 10 | constructor(options = {}) { 11 | this.name = 'RequireChunkPlugin'; 12 | this.options = { 13 | calcPath: options.calcPath || ((entry, chunk) => { 14 | return (0, ensure_posix_path_1.default)(path_1.default.relative(path_1.default.dirname(entry.name), chunk.name)); 15 | }), 16 | addPath: options.addPath || ((paths) => paths.map(path => `require("${path.replace(/\\/g, '\/')}");`).join('\n') + '\n') 17 | }; 18 | } 19 | apply(compiler) { 20 | compiler.hooks.compilation.tap(this.name, (compilation) => { 21 | webpack_1.default.javascript.JavascriptModulesPlugin.getCompilationHooks(compilation).render.tap(this.name, (source, { chunk, chunkGraph }) => { 22 | // isEntry 23 | if (chunkGraph.getNumberOfEntryModules(chunk) > 0) { 24 | const chunks = Array.from(chunk.getAllReferencedChunks()).filter(chunk_ => chunk_ !== chunk); 25 | if (chunks.length > 0) { 26 | return new webpack_1.default.sources.ConcatSource(this.options.addPath(chunks.map(c => this.options.calcPath(chunk, c))), source); 27 | } 28 | } 29 | return source; 30 | }); 31 | }); 32 | } 33 | } 34 | exports.default = RequireChunkPlugin; 35 | -------------------------------------------------------------------------------- /dist/compiler/entry/plugin/split-package-plugin/index.d.ts: -------------------------------------------------------------------------------- 1 | import webpack from 'webpack'; 2 | export default class SplitPackagePlugin { 3 | private options; 4 | name: string; 5 | constructor(options: { 6 | getRoot(name: string): string | undefined; 7 | getRoots(): string[]; 8 | isIndependent(name: string): boolean; 9 | }); 10 | packages: any[]; 11 | apply(compiler: webpack.Compiler): void; 12 | } 13 | -------------------------------------------------------------------------------- /dist/compiler/entry/plugin/split-package-plugin/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const webpack_1 = __importDefault(require("webpack")); 7 | const path_1 = __importDefault(require("path")); 8 | class SplitPackagePlugin { 9 | constructor(options) { 10 | this.options = options; 11 | this.name = 'SplitPackagePlugin'; 12 | this.packages = []; 13 | } 14 | apply(compiler) { 15 | compiler.hooks.compilation.tap(this.name, (compilation) => { 16 | compilation.hooks.afterOptimizeModules.tap(this.name, () => { 17 | this.packages = this.options.getRoots().map(root => { 18 | return { 19 | name: path_1.default.join(root, 'common.js'), 20 | chunks: (chunk) => this.options.getRoot(chunk.name) === root, 21 | minChunks: 2, 22 | priority: 5 23 | }; 24 | }); 25 | }); 26 | }); 27 | new webpack_1.default.optimize.SplitChunksPlugin({ 28 | maxAsyncRequests: Infinity, 29 | maxInitialRequests: Infinity, 30 | minSize: 0, 31 | cacheGroups: { 32 | common: { 33 | test: (module, { chunkGraph }) => { 34 | return chunkGraph.getModuleChunks(module).some(chunk => this.options.getRoot(chunk.name) === undefined); 35 | }, 36 | name: 'common.js', 37 | minChunks: 2, 38 | chunks: chunk => !this.options.isIndependent(chunk.name), 39 | priority: 10 40 | }, 41 | packages: () => { 42 | return this.packages; 43 | } 44 | } 45 | // { 46 | // default: false, 47 | // common: { 48 | // test: (module: webpack.Module, { chunkGraph }: { chunkGraph: webpack.ChunkGraph }) => { 49 | // return chunkGraph.getModuleChunks(module).some(chunk => this.options.getRoot(chunk.name) === undefined) 50 | // }, 51 | // name: 'common.js', 52 | // minChunks: 2, 53 | // chunks: chunk => !this.options.isIndependent(chunk.name) 54 | // }, 55 | // packages: (module: webpack.Module, { chunkGraph }: { chunkGraph: webpack.ChunkGraph }) => { 56 | // console.log('packages') 57 | // return this.options.getRoots().map(root => ({ 58 | // test: (module: webpack.Module, { chunkGraph }: { chunkGraph: webpack.ChunkGraph }) => { 59 | // return chunkGraph.getModuleChunks(module).some(chunk => this.options.getRoot(chunk.name) === root) 60 | // }, 61 | // name: path.join(root, 'common.js'), 62 | // minChunks: 2, 63 | // chunks: (chunk: webpack.Chunk) => this.options.getRoot(chunk.name) === root 64 | // })) 65 | // } 66 | // } 67 | }).apply(compiler); 68 | } 69 | } 70 | exports.default = SplitPackagePlugin; 71 | -------------------------------------------------------------------------------- /dist/compiler/entry/utils/index.d.ts: -------------------------------------------------------------------------------- 1 | export declare function genEntryName({ root, path, context, component }: { 2 | root?: string; 3 | path: string; 4 | context: string; 5 | component?: boolean; 6 | }): string; 7 | export declare function repalceAll(str: string, substr: string, newSubStr: string): string; 8 | -------------------------------------------------------------------------------- /dist/compiler/entry/utils/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.repalceAll = exports.genEntryName = void 0; 7 | const path_1 = __importDefault(require("path")); 8 | function genEntryName({ root, path, context, component = false }) { 9 | return path_1.default.join(root || '', component ? 'components' : '', path_1.default.relative(path_1.default.resolve(context, root || ''), path) 10 | .replace(/\.\.[\\/]/g, '@').replace(/\.[\\/]/g, '')).replace(/\.tsx$/, '.js'); 11 | } 12 | exports.genEntryName = genEntryName; 13 | function repalceAll(str, substr, newSubStr) { 14 | return str.replace(new RegExp(substr.replace(/([\|\.\^\$\*\+\?\\\/])/g, '\\$1'), 'g'), newSubStr); 15 | } 16 | exports.repalceAll = repalceAll; 17 | -------------------------------------------------------------------------------- /dist/compiler/index.d.ts: -------------------------------------------------------------------------------- 1 | import MPEntryPlugin from './entry/plugin'; 2 | import fixVue3This from './ts-transformer/fix-vue3-this'; 3 | declare const valueLoader: string; 4 | declare const tsxLoader: string; 5 | export { fixVue3This, valueLoader, tsxLoader }; 6 | export default MPEntryPlugin; 7 | -------------------------------------------------------------------------------- /dist/compiler/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.tsxLoader = exports.valueLoader = exports.fixVue3This = void 0; 7 | const plugin_1 = __importDefault(require("./entry/plugin")); 8 | const fix_vue3_this_1 = __importDefault(require("./ts-transformer/fix-vue3-this")); 9 | exports.fixVue3This = fix_vue3_this_1.default; 10 | const valueLoader = require.resolve('./value-loader'); 11 | exports.valueLoader = valueLoader; 12 | const tsxLoader = require.resolve('./module/loader'); 13 | exports.tsxLoader = tsxLoader; 14 | exports.default = plugin_1.default; 15 | -------------------------------------------------------------------------------- /dist/compiler/module/data/index.d.ts: -------------------------------------------------------------------------------- 1 | export default class ModuleData { 2 | path: string; 3 | static map: Map; 4 | static Init(path: string): ModuleData; 5 | static Has(path: string): boolean; 6 | static Pick(path: string): ModuleData; 7 | private constructor(); 8 | json: Record; 9 | wxml: string; 10 | wxss: string; 11 | wxs: string; 12 | private children; 13 | setJSON(json: Record): void; 14 | setWXML(value: string): void; 15 | addWXSS(value: string): void; 16 | setWXSS(value: string): void; 17 | setWXS(value: string): void; 18 | setStatic(type: 'wxss' | 'wxml' | 'json' | 'wxs', value: string): void; 19 | addChild(key: string, path: string): void; 20 | getChildren(): Record; 21 | destory(): void; 22 | } 23 | -------------------------------------------------------------------------------- /dist/compiler/module/data/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | class ModuleData { 4 | static Init(path) { 5 | const origin = this.map.get(path); 6 | if (origin) { 7 | origin.destory(); 8 | } 9 | const data = new ModuleData(path); 10 | this.map.set(path, data); 11 | return data; 12 | } 13 | static Has(path) { 14 | return this.map.has(path); 15 | } 16 | static Pick(path) { 17 | const data = this.map.get(path); 18 | if (!data) { 19 | throw new Error('module data not exist: ' + path); 20 | } 21 | return data; 22 | } 23 | constructor(path) { 24 | this.path = path; 25 | this.json = {}; 26 | this.wxml = ''; 27 | this.wxss = ''; 28 | this.wxs = ''; 29 | this.children = {}; 30 | } 31 | setJSON(json) { 32 | this.json = json; 33 | } 34 | setWXML(value) { 35 | this.wxml = value; 36 | } 37 | addWXSS(value) { 38 | this.wxss += value; 39 | } 40 | setWXSS(value) { 41 | this.wxss = value; 42 | } 43 | setWXS(value) { 44 | this.wxs = value; 45 | } 46 | setStatic(type, value) { 47 | switch (type) { 48 | case 'wxss': 49 | return this.setWXSS(value); 50 | case 'wxml': 51 | return this.setWXML(value); 52 | case 'wxs': 53 | return this.setWXS(value); 54 | case 'json': 55 | return this.setJSON(JSON.parse(value)); 56 | } 57 | } 58 | addChild(key, path) { 59 | this.children[key] = path; 60 | } 61 | getChildren() { 62 | return this.children; 63 | } 64 | destory() { 65 | this.children = null; 66 | } 67 | } 68 | exports.default = ModuleData; 69 | ModuleData.map = new Map(); 70 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/index.d.ts: -------------------------------------------------------------------------------- 1 | import { LoaderContext } from 'webpack'; 2 | export default function (this: LoaderContext, source: string): void; 3 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 4 | return new (P || (P = Promise))(function (resolve, reject) { 5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } 8 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 9 | }); 10 | }; 11 | var __importDefault = (this && this.__importDefault) || function (mod) { 12 | return (mod && mod.__esModule) ? mod : { "default": mod }; 13 | }; 14 | Object.defineProperty(exports, "__esModule", { value: true }); 15 | const webpack_1 = require("webpack"); 16 | const data_1 = __importDefault(require("../data")); 17 | const transform_1 = __importDefault(require("./transform")); 18 | const fs_1 = __importDefault(require("fs")); 19 | const state_1 = __importDefault(require("./state")); 20 | function default_1(source) { 21 | const data = data_1.default.Init(this.resourcePath); 22 | const state = new state_1.default(this.resourcePath); 23 | const callback = this.async(); 24 | (() => __awaiter(this, void 0, void 0, function* () { 25 | (0, transform_1.default)(source, state); 26 | data.setWXML(state.wxml); 27 | data.setJSON(state.json); 28 | for (const file of state.cssfile) { 29 | const { source, err } = yield new Promise((reslove) => { 30 | this.loadModule(file, (err, source) => { 31 | reslove({ 32 | err, 33 | source 34 | }); 35 | }); 36 | }); 37 | if (err) { 38 | this.emitError(err); 39 | continue; 40 | } 41 | if (source) { 42 | data.addWXSS(JSON.parse(source)); 43 | } 44 | } 45 | for (const name in state.components) { 46 | const component = state.components[name]; 47 | const { filename, err } = yield loadModule(this, component.path); 48 | if (err) { 49 | this.emitError(err); 50 | continue; 51 | } 52 | data.addChild(name, filename); 53 | if (/\.js$/.test(filename)) { 54 | // 原生组件 导入wxss wxml json wxs 55 | const componentData = data_1.default.Init(filename); 56 | const filepath = filename.replace(/\.js$/, ''); 57 | ['wxss', 'wxml', 'json', 'wxs'].forEach(ext => { 58 | const path = filepath + '.' + ext; 59 | if (fs_1.default.existsSync(path)) { 60 | componentData.setStatic(ext, fs_1.default.readFileSync(path).toString()); 61 | this.addDependency(path); 62 | } 63 | }); 64 | } 65 | else { 66 | state.setComponentNative(name); 67 | } 68 | } 69 | state.warning.forEach(warn => this.emitWarning(warn)); 70 | const code = state.generate(); 71 | state.destroy(); 72 | return code; 73 | }))().then(source => { 74 | callback(null, source); 75 | }).catch((e) => { 76 | callback(e); 77 | }); 78 | } 79 | exports.default = default_1; 80 | function loadModule(loaderContext, request) { 81 | // this.loadModule 会引起递归检测 82 | return new Promise((reslove) => { 83 | loaderContext.resolve(loaderContext.context, request, (err, path) => { 84 | if (err) 85 | return reslove({ 86 | filename: null, 87 | module: null, 88 | err 89 | }); 90 | const filename = path; 91 | const compilation = loaderContext._compilation; 92 | compilation.buildQueue.increaseParallelism(); 93 | compilation.addModuleChain(loaderContext.context, webpack_1.EntryPlugin.createDependency(filename, filename), (err, module) => { 94 | compilation.buildQueue.decreaseParallelism(); 95 | if (err) 96 | return reslove({ 97 | filename: null, 98 | module: null, 99 | err 100 | }); 101 | loaderContext.addDependency(filename); 102 | reslove({ 103 | filename, 104 | module: module 105 | }); 106 | }); 107 | }); 108 | }); 109 | } 110 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/identifier/event/index.d.ts: -------------------------------------------------------------------------------- 1 | import { iIdentifierItem } from ".."; 2 | import { NodePath } from '@babel/traverse'; 3 | import * as t from '@babel/types'; 4 | export default class EventIdentifier implements iIdentifierItem { 5 | private name; 6 | private path; 7 | private scope?; 8 | private value; 9 | constructor({ path, scope, name }: { 10 | path: NodePath; 11 | name: string; 12 | scope?: t.Expression; 13 | }); 14 | restore(): void; 15 | } 16 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/identifier/event/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | const t = __importStar(require("@babel/types")); 27 | const util_1 = require("../util"); 28 | class EventIdentifier { 29 | constructor({ path, scope, name }) { 30 | this.name = name; 31 | this.path = path; 32 | this.value = path.node; 33 | this.scope = scope; 34 | this.path.replaceWith(t.stringLiteral(name)); 35 | } 36 | restore() { 37 | this.path.replaceWith((0, util_1.genEventCall)(this.value, this.scope ? t.arrayExpression([t.stringLiteral(this.name), this.scope]) : t.stringLiteral(this.name))); 38 | this.name = null; 39 | this.path = null; 40 | this.scope = null; 41 | this.value = null; 42 | } 43 | } 44 | exports.default = EventIdentifier; 45 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/identifier/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from '@babel/traverse'; 2 | import * as t from '@babel/types'; 3 | import MapScope from '../map-scope'; 4 | import PropIdentifier from './prop'; 5 | export interface iIdentifierItem { 6 | restore(): void; 7 | } 8 | export default class DependencyIdentifier { 9 | private scope; 10 | private prefix; 11 | private _id; 12 | private data; 13 | constructor(scope: MapScope); 14 | private genName; 15 | map(path: NodePath): string[]; 16 | prop(path: NodePath): PropIdentifier; 17 | event(path: NodePath): { 18 | scope: t.BinaryExpression | t.Identifier | undefined; 19 | name: string; 20 | }; 21 | restore(): void; 22 | destroy(): void; 23 | } 24 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/identifier/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const map_1 = __importDefault(require("./map")); 7 | const prop_1 = __importDefault(require("./prop")); 8 | const event_1 = __importDefault(require("./event")); 9 | const util_1 = require("./util"); 10 | class DependencyIdentifier { 11 | constructor(scope) { 12 | this.scope = scope; 13 | this.prefix = { 14 | prop: 'p', 15 | event: 'e', 16 | scope: 's' 17 | }; 18 | this._id = { 19 | prop: 0, 20 | event: 0, 21 | scope: 0 22 | }; 23 | this.data = []; 24 | } 25 | genName(type) { 26 | return this.prefix[type] + (this._id[type]++); 27 | } 28 | map(path) { 29 | const name = this.genName('prop'); 30 | const calleeObject = path.get('callee.object'); 31 | const scope = this.scope.getScope(calleeObject); 32 | this.data.push(new map_1.default({ 33 | name, path, scope 34 | })); 35 | return scope; 36 | } 37 | prop(path) { 38 | const name = this.genName('prop'); 39 | const scope = this.scope.getScope(path); 40 | const prop = new prop_1.default({ 41 | name, path, scope 42 | }); 43 | this.data.push(prop); 44 | return prop; 45 | } 46 | event(path) { 47 | const name = this.genName('event'); 48 | const scope = (0, util_1.genExpression)(this.scope.getScope(path)); 49 | this.data.push(new event_1.default({ 50 | name, path, scope 51 | })); 52 | return { 53 | scope, name 54 | }; 55 | } 56 | restore() { 57 | this.data.forEach(item => { 58 | item.restore(); 59 | }); 60 | this.data = []; 61 | } 62 | destroy() { 63 | } 64 | } 65 | exports.default = DependencyIdentifier; 66 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/identifier/map/index.d.ts: -------------------------------------------------------------------------------- 1 | import { iIdentifierItem } from ".."; 2 | import { NodePath } from '@babel/traverse'; 3 | import * as t from '@babel/types'; 4 | export default class MapIdentifier implements iIdentifierItem { 5 | private name; 6 | private path; 7 | private calleeObject; 8 | private scope; 9 | private key?; 10 | constructor({ path, scope, name }: { 11 | path: NodePath; 12 | name: string; 13 | scope: string[]; 14 | }); 15 | restore(): void; 16 | } 17 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/identifier/map/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | const t = __importStar(require("@babel/types")); 27 | const util_1 = require("../util"); 28 | class MapIdentifier { 29 | constructor({ path, scope, name }) { 30 | this.name = name; 31 | this.path = path; 32 | this.scope = scope; 33 | this.key = findMapKey(path); 34 | const node = (0, util_1.mergeMember)(t.identifier(name), scope); 35 | const calleeObject = path.get('callee.object'); 36 | this.calleeObject = calleeObject.node; 37 | calleeObject.replaceWith(node); 38 | } 39 | restore() { 40 | const calleeObject = this.path.get('callee.object'); 41 | calleeObject.replaceWith(this.calleeObject); 42 | const arrowFn = this.path.get('arguments')[0]; 43 | if (arrowFn.isArrowFunctionExpression()) { 44 | const jsxElement = arrowFn.get('body'); 45 | if (jsxElement.isJSXElement()) { 46 | jsxElement.replaceWith(t.sequenceExpression([jsxElement.node, this.key || t.nullLiteral()])); 47 | } 48 | } 49 | // _$p(a.map(item => [key|null, ...]), name: string|string[], deepDiff: true) 50 | this.path.replaceWith((0, util_1.genPropCall)(this.path.node, this.scope.length > 0 ? t.arrayExpression([t.stringLiteral(this.name), ...this.scope.map(key => t.identifier(key))]) : t.stringLiteral(this.name))); 51 | this.name = null; 52 | this.path = null; 53 | this.calleeObject = null; 54 | this.scope = null; 55 | this.key = null; 56 | } 57 | } 58 | exports.default = MapIdentifier; 59 | function findMapKey(path) { 60 | const arrowFn = path.get('arguments')[0]; 61 | if (arrowFn.isArrowFunctionExpression()) { 62 | const jsxElement = arrowFn.get('body'); 63 | if (jsxElement.isJSXElement()) { 64 | const attr = jsxElement.get('openingElement').get('attributes').find(path => { 65 | return path.isJSXAttribute() && path.node.name.name === 'key'; 66 | }); 67 | const value = attr === null || attr === void 0 ? void 0 : attr.get('value'); 68 | if (value === null || value === void 0 ? void 0 : value.isJSXExpressionContainer()) { 69 | const expression = value.node.expression; 70 | if (!t.isJSXEmptyExpression(expression)) { 71 | value.replaceWith(t.stringLiteral("*this")); 72 | return expression; 73 | } 74 | } 75 | else if (value === null || value === void 0 ? void 0 : value.isStringLiteral()) { 76 | const param = arrowFn.node.params[0] = (arrowFn.node.params[0] || path.scope.generateUidIdentifier('t')); 77 | const key = value.node.value; 78 | if (key === '*this') { 79 | return param; 80 | } 81 | else { 82 | value.replaceWith(t.stringLiteral("*this")); 83 | return t.memberExpression(param, t.identifier(key), false); 84 | } 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/identifier/prop/index.d.ts: -------------------------------------------------------------------------------- 1 | import { iIdentifierItem } from ".."; 2 | import { NodePath } from '@babel/traverse'; 3 | import * as t from '@babel/types'; 4 | export default class PropIdentifier implements iIdentifierItem { 5 | private name; 6 | private path; 7 | private scope; 8 | private value; 9 | private native; 10 | constructor({ path, scope, name }: { 11 | path: NodePath; 12 | name: string; 13 | scope: string[]; 14 | }); 15 | setNative(): void; 16 | restore(): void; 17 | } 18 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/identifier/prop/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | const t = __importStar(require("@babel/types")); 27 | const util_1 = require("../util"); 28 | class PropIdentifier { 29 | constructor({ path, scope, name }) { 30 | this.native = false; 31 | this.name = name; 32 | this.path = path; 33 | this.scope = scope; 34 | this.value = path.node; 35 | this.path.replaceWith((0, util_1.mergeMember)(t.identifier(name), scope)); 36 | } 37 | setNative() { 38 | this.native = true; 39 | } 40 | restore() { 41 | this.path.replaceWith((0, util_1.genPropCall)(this.value, this.scope.length > 0 ? t.arrayExpression([t.stringLiteral(this.name), ...this.scope.map(key => t.identifier(key))]) : t.stringLiteral(this.name), this.native)); 42 | this.name = null; 43 | this.path = null; 44 | this.scope = null; 45 | this.value = null; 46 | } 47 | } 48 | exports.default = PropIdentifier; 49 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/identifier/util.d.ts: -------------------------------------------------------------------------------- 1 | import * as t from '@babel/types'; 2 | export declare function mergeMember(identifier: t.Identifier, indexs: string[]): t.Identifier | t.MemberExpression; 3 | export declare function genExpression(indexs: string[]): t.BinaryExpression | t.Identifier | undefined; 4 | export declare const fnName: { 5 | prop: string; 6 | event: string; 7 | }; 8 | export declare function genPropCall(value: t.Expression, name: t.StringLiteral | t.ArrayExpression, native?: boolean): t.CallExpression; 9 | export declare function genEventCall(value: t.Expression, name: t.StringLiteral | t.ArrayExpression): t.CallExpression; 10 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/identifier/util.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | exports.genEventCall = exports.genPropCall = exports.fnName = exports.genExpression = exports.mergeMember = void 0; 27 | const t = __importStar(require("@babel/types")); 28 | function mergeMember(identifier, indexs) { 29 | let node = identifier; 30 | indexs.forEach(index => { 31 | node = t.memberExpression(node, t.identifier(index), true); 32 | }); 33 | return node; 34 | } 35 | exports.mergeMember = mergeMember; 36 | function genExpression(indexs) { 37 | let property = undefined; 38 | for (const index of indexs) { 39 | if (!property) { 40 | property = t.identifier(index); 41 | } 42 | else { 43 | property = t.binaryExpression('+', t.binaryExpression('+', property, t.stringLiteral('_')), t.identifier(index)); 44 | } 45 | } 46 | return property; 47 | } 48 | exports.genExpression = genExpression; 49 | exports.fnName = { 50 | prop: '_$p', 51 | event: '_$e' 52 | }; 53 | function genPropCall(value, name, native) { 54 | return t.callExpression(t.identifier(exports.fnName.prop), [ 55 | value, 56 | name 57 | ].concat(native ? t.booleanLiteral(true) : [])); 58 | } 59 | exports.genPropCall = genPropCall; 60 | function genEventCall(value, name) { 61 | return t.callExpression(t.identifier(exports.fnName.event), [ 62 | value, 63 | name 64 | ]); 65 | } 66 | exports.genEventCall = genEventCall; 67 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from "@babel/traverse"; 2 | import DependencyIdentifier from "./identifier"; 3 | import MapScope from "./map-scope"; 4 | import * as t from '@babel/types'; 5 | import PropIdentifier from "./identifier/prop"; 6 | export default class State { 7 | debug: boolean; 8 | constructor(filename: string); 9 | json: any; 10 | cssfile: string[]; 11 | wxml: string; 12 | setWXML(value: string): void; 13 | setJSON(value: any): void; 14 | addCss(file: string): void; 15 | components: Record; 19 | addComponent(name: string, path: string): void; 20 | setComponentNative(name: string): void; 21 | private callbacks; 22 | before(callback: () => void): void; 23 | private generator?; 24 | setGenerator(generator: () => string): void; 25 | generate(): string; 26 | events: string[]; 27 | addEvent(name: string): void; 28 | mapScope: MapScope; 29 | identifier: DependencyIdentifier; 30 | enterMap(path: NodePath, scope: string[]): void; 31 | exitMap(): void; 32 | genMap(path: NodePath): string[]; 33 | genProp(path: NodePath, component?: string): void; 34 | genEvent(path: NodePath): { 35 | scope: t.BinaryExpression | t.Identifier | undefined; 36 | name: string; 37 | }; 38 | warning: Error[]; 39 | addWarning(warn: Error): void; 40 | destroy(): void; 41 | } 42 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const identifier_1 = __importDefault(require("./identifier")); 7 | const map_scope_1 = __importDefault(require("./map-scope")); 8 | class State { 9 | constructor(filename) { 10 | this.debug = false; 11 | this.json = {}; 12 | this.cssfile = []; 13 | this.wxml = ''; 14 | this.components = {}; 15 | this.callbacks = []; 16 | this.events = []; 17 | this.mapScope = new map_scope_1.default(); 18 | this.identifier = new identifier_1.default(this.mapScope); 19 | this.warning = []; 20 | } 21 | setWXML(value) { 22 | this.wxml = value; 23 | } 24 | setJSON(value) { 25 | this.json = value; 26 | } 27 | addCss(file) { 28 | this.cssfile.push(file); 29 | } 30 | addComponent(name, path) { 31 | this.components[name] = this.components[name] || { 32 | path, 33 | props: [] 34 | }; 35 | } 36 | setComponentNative(name) { 37 | this.components[name].props.forEach(prop => { 38 | prop.setNative(); 39 | }); 40 | } 41 | before(callback) { 42 | this.callbacks.push(callback); 43 | } 44 | setGenerator(generator) { 45 | this.generator = generator; 46 | } 47 | generate() { 48 | var _a; 49 | this.identifier.restore(); 50 | this.callbacks.forEach(fn => fn()); 51 | return ((_a = this.generator) === null || _a === void 0 ? void 0 : _a.call(this)) || ''; 52 | } 53 | addEvent(name) { 54 | this.events.push(name); 55 | } 56 | enterMap(path, scope) { 57 | this.mapScope.enter(path, scope); 58 | } 59 | exitMap() { 60 | this.mapScope.exit(); 61 | } 62 | genMap(path) { 63 | return this.identifier.map(path); 64 | } 65 | genProp(path, component) { 66 | path.skip(); 67 | const prop = this.identifier.prop(path); 68 | if (component) { 69 | this.components[component].props.push(prop); 70 | } 71 | } 72 | genEvent(path) { 73 | path.skip(); 74 | const { scope, name } = this.identifier.event(path); 75 | this.events.push(name); 76 | return { scope, name }; 77 | } 78 | addWarning(warn) { 79 | this.warning.push(warn); 80 | } 81 | destroy() { 82 | this.mapScope.destroy(); 83 | this.identifier.destroy(); 84 | this.json = null; 85 | this.events = null; 86 | this.callbacks = null; 87 | this.generator = null; 88 | this.components = null; 89 | this.warning = null; 90 | this.cssfile = null; 91 | } 92 | } 93 | exports.default = State; 94 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/map-scope/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from '@babel/traverse'; 2 | import * as t from '@babel/types'; 3 | export default class MapScope { 4 | private data; 5 | private dict; 6 | private push; 7 | enter(path: NodePath, parent: string[]): void; 8 | exit(): void; 9 | private has; 10 | private getIndex; 11 | private update; 12 | getScope(path: NodePath): string[]; 13 | destroy(): void; 14 | } 15 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/state/map-scope/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | const t = __importStar(require("@babel/types")); 27 | class MapScope { 28 | constructor() { 29 | this.data = []; 30 | this.dict = {}; 31 | } 32 | push(item, index, parent) { 33 | this.data.push([item, index, parent]); 34 | this.update(); 35 | } 36 | enter(path, parent) { 37 | const arrowFn = path.get('arguments')[0]; 38 | if (!arrowFn.isArrowFunctionExpression()) { 39 | throw path.buildCodeFrameError('Map only support ArrowFunctionExpression'); 40 | } 41 | const params = arrowFn.node.params; 42 | let item = params[0]; 43 | let index = params[1]; 44 | if ((item && !t.isIdentifier(item)) || (index && !t.isIdentifier(index))) { 45 | throw path.buildCodeFrameError('Map params only support Identifier'); 46 | } 47 | if (!item) { 48 | item = path.scope.generateUidIdentifier('t'); 49 | params.push(item); 50 | } 51 | if (!index) { 52 | index = path.scope.generateUidIdentifier('i'); 53 | params.push(index); 54 | } 55 | else { 56 | const name = index.name; 57 | // 重复的index重命名 58 | if (this.has(name)) { 59 | arrowFn.scope.rename(name); 60 | } 61 | } 62 | this.push(item.name, index.name, parent); 63 | } 64 | exit() { 65 | this.data.pop(); 66 | this.update(); 67 | } 68 | has(id) { 69 | return this.getIndex(id) !== undefined; 70 | } 71 | getIndex(id) { 72 | return this.dict[id]; 73 | } 74 | update() { 75 | const dict = {}; 76 | this.data.forEach(([item, index, parent]) => { 77 | dict[item] = dict[index] = [index].concat(parent); 78 | }); 79 | this.dict = dict; 80 | } 81 | getScope(path) { 82 | var _a; 83 | const result = []; 84 | if (this.data.length > 0) { 85 | const indexs = new Set(); 86 | path.traverse({ 87 | Identifier: item => { 88 | var _a; 89 | if (t.isReferenced(item.node, item.parent)) { 90 | const name = item.node.name; 91 | if (item.scope.getBinding(name) === path.parentPath.scope.getBinding(name)) { 92 | (_a = this.getIndex(name)) === null || _a === void 0 ? void 0 : _a.forEach(index => { 93 | indexs.add(index); 94 | }); 95 | } 96 | } 97 | } 98 | }); 99 | // traverse 不会遍历当前元素 100 | if (path.isIdentifier()) { 101 | (_a = this.getIndex(path.node.name)) === null || _a === void 0 ? void 0 : _a.forEach(index => { 102 | indexs.add(index); 103 | }); 104 | } 105 | result.push(...indexs); 106 | indexs.clear(); 107 | } 108 | return result; 109 | } 110 | destroy() { 111 | this.data = null; 112 | this.dict = null; 113 | } 114 | } 115 | exports.default = MapScope; 116 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/add-ready/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from "@babel/traverse"; 2 | import * as t from '@babel/types'; 3 | export default function addReady(path: NodePath): void; 4 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/add-ready/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | const t = __importStar(require("@babel/types")); 27 | // 通过给顶层代码添加条件表达式保证第一个元素拥有wx:if="{{ p0 }}"作为初始化状态 28 | function addReady(path) { 29 | if (path.isLogicalExpression()) { 30 | // a &&
-> 不变 31 | // a ||
-> (true && !a) &&
32 | if (path.node.operator === '||') { 33 | path.replaceWith(t.logicalExpression('&&', t.logicalExpression('&&', t.booleanLiteral(true), t.unaryExpression('!', path.node.left)), path.node.right)); 34 | } 35 | } 36 | else if (path.isConditionalExpression()) { 37 | // a ?
:
-> 不变 38 | } 39 | else { 40 | path.replaceWith(t.logicalExpression('&&', t.booleanLiteral(true), path.node)); 41 | } 42 | } 43 | exports.default = addReady; 44 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/gen-data/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from "@babel/traverse"; 2 | import * as t from '@babel/types'; 3 | import State from "../../state"; 4 | export default function genData(path: NodePath, state: State): void; 5 | export declare function isMapCallExpression(node: t.CallExpression): boolean; 6 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/index.d.ts: -------------------------------------------------------------------------------- 1 | import State from '../state'; 2 | export default function transform(source: string, state: State): void; 3 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __importDefault = (this && this.__importDefault) || function (mod) { 26 | return (mod && mod.__esModule) ? mod : { "default": mod }; 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | const t = __importStar(require("@babel/types")); 30 | const parser = __importStar(require("@babel/parser")); 31 | const traverse_1 = __importDefault(require("@babel/traverse")); 32 | const generator_1 = __importDefault(require("@babel/generator")); 33 | const json_1 = __importDefault(require("./json")); 34 | const render_1 = __importDefault(require("./render")); 35 | const properties_1 = __importDefault(require("./properties")); 36 | const wxml_1 = __importDefault(require("./wxml")); 37 | const add_ready_1 = __importDefault(require("./add-ready")); 38 | const gen_data_1 = __importDefault(require("./gen-data")); 39 | function transform(source, state) { 40 | const file = parser.parse(source, { 41 | plugins: ['typescript', 'jsx', 'classProperties', 'decorators-legacy'], 42 | sourceType: 'module' 43 | }); 44 | (0, traverse_1.default)(file, { 45 | ImportDeclaration: { 46 | enter: path => { 47 | if (path.node.specifiers.length === 0) { 48 | if (/\.(sass|scss|css|wxss)$/.test(path.node.source.value)) { 49 | state.addCss(path.node.source.value); 50 | path.remove(); 51 | } 52 | } 53 | } 54 | }, 55 | ExportDefaultDeclaration: { 56 | enter: path => { 57 | var _a; 58 | path.skip(); 59 | const declaration = path.get('declaration'); 60 | if (declaration.isClassDeclaration()) { 61 | state.setJSON((0, json_1.default)(declaration) || {}); 62 | const render = declaration.get('body.body').find(item => { 63 | if (item.isClassMethod()) { 64 | const key = item.get('key'); 65 | if (key.isIdentifier()) { 66 | return key.node.name === 'render'; 67 | } 68 | } 69 | return false; 70 | }); 71 | if (render) { 72 | const argument = (_a = render.get('body.body').find(item => { 73 | return item.isReturnStatement(); 74 | })) === null || _a === void 0 ? void 0 : _a.get('argument'); 75 | if (argument === null || argument === void 0 ? void 0 : argument.isExpression()) { 76 | (0, add_ready_1.default)(argument); 77 | (0, gen_data_1.default)(argument, state); 78 | state.setWXML((0, generator_1.default)((0, wxml_1.default)(argument), { comments: false }).code); 79 | } 80 | state.before(() => { 81 | (0, render_1.default)(render); 82 | }); 83 | } 84 | /** 85 | * export default class -> (class).create({ 86 | * events: [], 87 | * properties: {} 88 | * }) 89 | **/ 90 | path.replaceWith(t.expressionStatement(t.callExpression(t.memberExpression(t.toExpression(declaration.node), t.identifier('create')), [ 91 | t.objectExpression([ 92 | t.objectProperty(t.identifier('events'), t.valueToNode(state.events)), 93 | t.objectProperty(t.identifier('properties'), t.objectExpression((0, properties_1.default)(declaration))) 94 | ]) 95 | ]))); 96 | } 97 | } 98 | } 99 | }); 100 | state.setGenerator(() => { 101 | return (0, generator_1.default)(file, { comments: false }).code; 102 | }); 103 | } 104 | exports.default = transform; 105 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/json/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from "@babel/traverse"; 2 | import * as t from '@babel/types'; 3 | export default function getJSON(path: NodePath): any; 4 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/json/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const generator_1 = __importDefault(require("@babel/generator")); 7 | function getJSON(path) { 8 | const json = path.get('body.body').find(item => { 9 | if (item.isClassProperty()) { 10 | const key = item.get('key'); 11 | if (key.isIdentifier()) { 12 | return key.node.name === '$json'; 13 | } 14 | } 15 | return false; 16 | }); 17 | if (json) { 18 | const node = json.get('value').node; 19 | if (node) { 20 | return eval(`(${(0, generator_1.default)(node, { comments: false }).code})`); 21 | } 22 | json.remove(); 23 | } 24 | } 25 | exports.default = getJSON; 26 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/properties/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from "@babel/traverse"; 2 | import * as t from '@babel/types'; 3 | export default function getProperties(path: NodePath): t.ObjectProperty[]; 4 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/properties/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | const t = __importStar(require("@babel/types")); 27 | function getProperties(path) { 28 | const declaration = path.node; 29 | const result = []; 30 | if (t.isTSTypeParameterInstantiation(declaration.superTypeParameters)) { 31 | const objectType = declaration.superTypeParameters.params[0]; 32 | if (t.isTSTypeLiteral(objectType)) { 33 | objectType.members.forEach(property => { 34 | if (t.isTSMethodSignature(property)) { 35 | if (t.isIdentifier(property.key)) { 36 | result.push(t.objectProperty(property.key, t.identifier('null'))); 37 | } 38 | } 39 | else if (t.isTSPropertySignature(property) && property.typeAnnotation) { 40 | if (t.isIdentifier(property.key)) { 41 | const type = property.typeAnnotation.typeAnnotation; 42 | result.push(t.objectProperty(property.key, t.isTSStringKeyword(type) ? 43 | t.identifier('String') : 44 | t.isTSNumberKeyword(type) ? 45 | t.identifier('Number') : 46 | t.isTSBooleanKeyword(type) ? 47 | t.identifier('Boolean') : 48 | t.identifier('null'))); 49 | } 50 | } 51 | else { 52 | // `unknown component params type ${property.type}` 53 | } 54 | }); 55 | } 56 | } 57 | return result; 58 | } 59 | exports.default = getProperties; 60 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/render/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from "@babel/traverse"; 2 | import * as t from '@babel/types'; 3 | export default function transformEffect(render: NodePath): void; 4 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/render/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | const t = __importStar(require("@babel/types")); 27 | const util_1 = require("../../state/identifier/util"); 28 | function transformEffect(render) { 29 | render.node.params = renderParams; 30 | render.traverse({ 31 | JSXElement: { 32 | exit: path => { 33 | const children = path.node.children.reduce((res, item) => { 34 | if (t.isJSXExpressionContainer(item) && !t.isJSXEmptyExpression(item.expression)) { 35 | res.push(item.expression); 36 | } 37 | else if (t.isArrayExpression(item)) { 38 | item.elements.forEach(item => { 39 | if (t.isExpression(item)) { 40 | res.push(item); 41 | } 42 | }); 43 | } 44 | return res; 45 | }, []); 46 | const attrs = path.node.openingElement.attributes 47 | .reduce((res, item) => { 48 | if (t.isJSXAttribute(item) && t.isJSXExpressionContainer(item.value) && !t.isJSXEmptyExpression(item.value.expression)) { 49 | if (t.isJSXNamespacedName(item.name) || (t.isJSXIdentifier(item.name) && !/^data-/.test(item.name.name))) { 50 | res.push(item.value.expression); 51 | } 52 | } 53 | return res; 54 | }, []); 55 | if (children.length > 0 || attrs.length > 0) { 56 | path.replaceWith(t.arrayExpression(children.concat(attrs))); 57 | } 58 | else { 59 | if (path.parentPath.isConditionalExpression()) { 60 | path.replaceWith(t.nullLiteral()); 61 | } 62 | else { 63 | path.remove(); 64 | } 65 | } 66 | } 67 | } 68 | }); 69 | } 70 | exports.default = transformEffect; 71 | const typeAnnotation = t.tsTypeAnnotation(t.tsFunctionType(t.tsTypeParameterDeclaration([ 72 | t.tsTypeParameter(null, null, 'T') 73 | ]), [ 74 | addTsTypeAnnotation(t.identifier('a'), t.tsTypeAnnotation(t.tsTypeReference(t.identifier('T')))), 75 | addTsTypeAnnotation(t.restElement(t.identifier('args')), t.tsTypeAnnotation(t.tsAnyKeyword())) 76 | ], t.tsTypeAnnotation(t.tsTypeReference(t.identifier('T'))))); 77 | const renderParams = [ 78 | addTsTypeAnnotation(t.identifier(util_1.fnName.prop), typeAnnotation), 79 | addTsTypeAnnotation(t.identifier(util_1.fnName.event), typeAnnotation) 80 | ]; 81 | function addTsTypeAnnotation(expression, type) { 82 | // @ts-ignore 83 | expression.typeAnnotation = type; 84 | return expression; 85 | } 86 | -------------------------------------------------------------------------------- /dist/compiler/module/loader/transform/wxml/index.d.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from '@babel/traverse'; 2 | import * as t from '@babel/types'; 3 | export default function getWXML(path: NodePath): t.Expression | t.JSXEmptyExpression; 4 | -------------------------------------------------------------------------------- /dist/compiler/ts-transformer/fix-vue3-this/index.d.ts: -------------------------------------------------------------------------------- 1 | import ts from 'typescript'; 2 | declare const fixVue3This: ts.TransformerFactory; 3 | export default fixVue3This; 4 | -------------------------------------------------------------------------------- /dist/compiler/ts-transformer/fix-vue3-this/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const typescript_1 = __importDefault(require("typescript")); 7 | const state_1 = __importDefault(require("./state")); 8 | const util_1 = require("../util"); 9 | const fixVue3This = (context) => { 10 | return sourceFile => { 11 | if (sourceFile.languageVariant !== typescript_1.default.LanguageVariant.Standard || sourceFile.isDeclarationFile) { 12 | return sourceFile; 13 | } 14 | const state = new state_1.default(); 15 | sourceFile = typescript_1.default.visitEachChild(sourceFile, node => { 16 | if (node.kind === typescript_1.default.SyntaxKind.ClassDeclaration) { 17 | return typescript_1.default.visitEachChild(node, node => { 18 | if (typescript_1.default.isConstructorDeclaration(node) || typescript_1.default.isPropertyDeclaration(node)) { 19 | return (0, util_1.traverse)(node, { 20 | enter: node => { 21 | if (node.kind === typescript_1.default.SyntaxKind.ArrowFunction) { 22 | state.enterArrow(); 23 | } 24 | else if (node.kind === typescript_1.default.SyntaxKind.FunctionExpression) { 25 | return node; 26 | } 27 | else if (state.isInArrow()) { 28 | state.active(node); 29 | if (typescript_1.default.isBinaryExpression(node) && node.operatorToken.kind === typescript_1.default.SyntaxKind.FirstAssignment) { 30 | state.add(node.left); 31 | } 32 | else if (typescript_1.default.isCallExpression(node)) { 33 | state.add(node.expression); 34 | } 35 | else if (state.isActived() && typescript_1.default.isPropertyAccessExpression(node) && node.expression.kind === typescript_1.default.SyntaxKind.ThisKeyword) { 36 | return context.factory.updatePropertyAccessExpression(node, context.factory.createCallExpression(state.identifier, [], [node.expression]), node.name); 37 | } 38 | } 39 | }, 40 | exit: node => { 41 | if (node.kind === typescript_1.default.SyntaxKind.ArrowFunction) { 42 | state.leaveArrow(); 43 | } 44 | else { 45 | state.leave(node); 46 | } 47 | } 48 | }, context); 49 | } 50 | return node; 51 | }, context); 52 | } 53 | return node; 54 | }, context); 55 | if (state.isChanged()) { 56 | return (0, util_1.addStatement)(sourceFile, typescript_1.default.factory.createVariableStatement(undefined, typescript_1.default.factory.createVariableDeclarationList([ 57 | typescript_1.default.factory.createVariableDeclaration(state.identifier, undefined, undefined, typescript_1.default.factory.createAsExpression(typescript_1.default.factory.createPropertyAccessExpression(typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier('require'), undefined, [typescript_1.default.factory.createStringLiteral('march-mp')]), typescript_1.default.factory.createIdentifier('reactive')), typescript_1.default.factory.createFunctionTypeNode([ 58 | typescript_1.default.factory.createTypeParameterDeclaration(undefined, 'T') 59 | ], [ 60 | typescript_1.default.factory.createParameterDeclaration(undefined, undefined, 'data', undefined, typescript_1.default.factory.createTypeReferenceNode("T")) 61 | ], typescript_1.default.factory.createTypeReferenceNode("T")))) 62 | ], typescript_1.default.NodeFlags.Const))); 63 | } 64 | return sourceFile; 65 | }; 66 | }; 67 | exports.default = fixVue3This; 68 | -------------------------------------------------------------------------------- /dist/compiler/ts-transformer/fix-vue3-this/state.d.ts: -------------------------------------------------------------------------------- 1 | import ts from 'typescript'; 2 | export default class FixThisState { 3 | private _identifier?; 4 | get identifier(): ts.Identifier; 5 | isChanged(): boolean; 6 | private arrowCount; 7 | isInArrow(): boolean; 8 | enterArrow(): void; 9 | leaveArrow(): void; 10 | private data; 11 | add(node: ts.Node): void; 12 | private getLast; 13 | private removeLast; 14 | isActived(): boolean; 15 | active(node: ts.Node): void; 16 | leave(node: ts.Node): void; 17 | log(): void; 18 | } 19 | -------------------------------------------------------------------------------- /dist/compiler/ts-transformer/fix-vue3-this/state.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | const typescript_1 = __importDefault(require("typescript")); 7 | const util_1 = require("../util"); 8 | class FixThisState { 9 | constructor() { 10 | this.arrowCount = 0; 11 | this.data = []; 12 | } 13 | get identifier() { 14 | if (this._identifier) { 15 | return this._identifier; 16 | } 17 | else { 18 | return this._identifier = typescript_1.default.factory.createUniqueName('reactive'); 19 | } 20 | } 21 | isChanged() { 22 | return this._identifier !== undefined; 23 | } 24 | isInArrow() { 25 | return this.arrowCount > 0; 26 | } 27 | enterArrow() { 28 | this.arrowCount++; 29 | } 30 | leaveArrow() { 31 | this.arrowCount--; 32 | } 33 | add(node) { 34 | this.data.unshift({ 35 | node, status: 0 36 | }); 37 | } 38 | getLast() { 39 | return this.data[0]; 40 | } 41 | removeLast() { 42 | this.data.splice(0, 1); 43 | } 44 | isActived() { 45 | var _a; 46 | return ((_a = this.getLast()) === null || _a === void 0 ? void 0 : _a.status) === 1; 47 | } 48 | active(node) { 49 | const item = this.getLast(); 50 | if ((item === null || item === void 0 ? void 0 : item.node) === node) { 51 | // console.log('actived', toCode(node)) 52 | item.status = 1; 53 | } 54 | } 55 | leave(node) { 56 | var _a; 57 | if (((_a = this.getLast()) === null || _a === void 0 ? void 0 : _a.node) === node) { 58 | this.removeLast(); 59 | } 60 | } 61 | log() { 62 | console.log('------------'); 63 | this.data.forEach(item => { 64 | console.log((0, util_1.toCode)(item.node)); 65 | }); 66 | console.log('------------'); 67 | } 68 | } 69 | exports.default = FixThisState; 70 | -------------------------------------------------------------------------------- /dist/compiler/ts-transformer/util.d.ts: -------------------------------------------------------------------------------- 1 | import ts from 'typescript'; 2 | export declare function traverse(node: ts.Node, visitor: { 3 | enter?: (node: ts.Node) => ts.Node | void; 4 | exit?: (node: ts.Node) => void; 5 | }, context: ts.TransformationContext): ts.Node; 6 | export declare function isPropertyAccessExpression(node: ts.Node): node is ts.PropertyAccessExpression; 7 | export declare function isBinaryExpression(node: ts.Node): node is ts.BinaryExpression; 8 | export declare function isCallExpression(node: ts.Node): node is ts.CallExpression; 9 | export declare function isImportDeclaration(node: ts.Node): node is ts.ImportDeclaration; 10 | export declare function isStringLiteral(node: ts.Node): node is ts.StringLiteral; 11 | export declare function addStatement(sourceFile: ts.SourceFile, statement: ts.Statement): ts.SourceFile; 12 | export declare function toCode(node: ts.Node): string; 13 | -------------------------------------------------------------------------------- /dist/compiler/ts-transformer/util.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | exports.toCode = exports.addStatement = exports.isStringLiteral = exports.isImportDeclaration = exports.isCallExpression = exports.isBinaryExpression = exports.isPropertyAccessExpression = exports.traverse = void 0; 27 | const typescript_1 = __importStar(require("typescript")); 28 | function traverse(node, visitor, context) { 29 | var _a, _b; 30 | let result = (_a = visitor.enter) === null || _a === void 0 ? void 0 : _a.call(visitor, node); 31 | if (!result) { 32 | result = typescript_1.default.visitEachChild(node, node => traverse(node, visitor, context), context); 33 | } 34 | (_b = visitor.exit) === null || _b === void 0 ? void 0 : _b.call(visitor, result); 35 | return result; 36 | } 37 | exports.traverse = traverse; 38 | function isPropertyAccessExpression(node) { 39 | return node.kind === typescript_1.default.SyntaxKind.PropertyAccessExpression; 40 | } 41 | exports.isPropertyAccessExpression = isPropertyAccessExpression; 42 | function isBinaryExpression(node) { 43 | return node.kind === typescript_1.default.SyntaxKind.BinaryExpression; 44 | } 45 | exports.isBinaryExpression = isBinaryExpression; 46 | function isCallExpression(node) { 47 | return node.kind === typescript_1.default.SyntaxKind.CallExpression; 48 | } 49 | exports.isCallExpression = isCallExpression; 50 | function isImportDeclaration(node) { 51 | return node.kind === typescript_1.default.SyntaxKind.ImportDeclaration; 52 | } 53 | exports.isImportDeclaration = isImportDeclaration; 54 | function isStringLiteral(node) { 55 | return node.kind === typescript_1.default.SyntaxKind.StringLiteral; 56 | } 57 | exports.isStringLiteral = isStringLiteral; 58 | function addStatement(sourceFile, statement) { 59 | return typescript_1.default.factory.updateSourceFile(sourceFile, [ 60 | statement, 61 | ...sourceFile.statements 62 | ], sourceFile.isDeclarationFile, sourceFile.referencedFiles, sourceFile.typeReferenceDirectives, sourceFile.hasNoDefaultLib, sourceFile.libReferenceDirectives); 63 | } 64 | exports.addStatement = addStatement; 65 | function toCode(node) { 66 | const printer = typescript_1.default.createPrinter(); 67 | return printer.printNode(typescript_1.EmitHint.Expression, node, typescript_1.default.createSourceFile('a.ts', '', typescript_1.default.ScriptTarget.Latest)); 68 | } 69 | exports.toCode = toCode; 70 | -------------------------------------------------------------------------------- /dist/compiler/value-loader/index.d.ts: -------------------------------------------------------------------------------- 1 | export default function (source: string): string; 2 | -------------------------------------------------------------------------------- /dist/compiler/value-loader/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | function default_1(source) { 4 | return `${JSON.stringify(source)}`; 5 | } 6 | exports.default = default_1; 7 | -------------------------------------------------------------------------------- /dist/runtime/@vue_reactivity/index.d.ts: -------------------------------------------------------------------------------- 1 | declare const ITERATE_KEY: unique symbol; 2 | declare function effect(fn: any, options?: Readonly<{}>): { 3 | (...args: any[]): any; 4 | id: number; 5 | _isEffect: boolean; 6 | active: boolean; 7 | raw: any; 8 | deps: any[]; 9 | options: any; 10 | }; 11 | declare function stop(effect: any): void; 12 | declare function pauseTracking(): void; 13 | declare function enableTracking(): void; 14 | declare function resetTracking(): void; 15 | declare function track(target: any, type: any, key: any): void; 16 | declare function trigger(target: any, type: any, key: any, newValue: any, oldValue: any, oldTarget: any): void; 17 | declare function reactive(target: any): any; 18 | declare function shallowReactive(target: any): any; 19 | declare function readonly(target: any): any; 20 | declare function shallowReadonly(target: any): any; 21 | declare function isReactive(value: any): any; 22 | declare function isReadonly(value: any): boolean; 23 | declare function isProxy(value: any): any; 24 | declare function toRaw(observed: any): any; 25 | declare function markRaw(value: any): any; 26 | declare function isRef(r: any): boolean; 27 | declare function ref(value: any): any; 28 | declare function shallowRef(value: any): any; 29 | declare function triggerRef(ref: any): void; 30 | declare function unref(ref: any): any; 31 | declare function customRef(factory: any): { 32 | __v_isRef: boolean; 33 | value: any; 34 | }; 35 | declare function toRefs(object: any): {}; 36 | declare function toRef(object: any, key: any): { 37 | __v_isRef: boolean; 38 | value: any; 39 | }; 40 | declare function computed(getterOrOptions: any): { 41 | __v_isRef: boolean; 42 | effect: { 43 | (...args: any[]): any; 44 | id: number; 45 | _isEffect: boolean; 46 | active: boolean; 47 | raw: any; 48 | deps: any[]; 49 | options: any; 50 | }; 51 | value: any; 52 | }; 53 | export { ITERATE_KEY, computed, customRef, effect, enableTracking, isProxy, isReactive, isReadonly, isRef, markRaw, pauseTracking, reactive, readonly, ref, resetTracking, shallowReactive, shallowReadonly, shallowRef, stop, toRaw, toRef, toRefs, track, trigger, triggerRef, unref }; 54 | -------------------------------------------------------------------------------- /dist/runtime/base/index.d.ts: -------------------------------------------------------------------------------- 1 | import RuntimeStore from './store'; 2 | type pageInstance = WechatMiniprogram.Page.Instance<{}, {}>; 3 | type componentInstance = WechatMiniprogram.Component.Instance<{}, {}, {}>; 4 | type wxInstance = pageInstance | componentInstance; 5 | export default class MPBase { 6 | static debug: boolean; 7 | static dataMap: WeakMap; 8 | static init(instance: wxInstance, data: T, callback?: () => void): T; 9 | static bindData(instance: wxInstance, data: T): T; 10 | static getData(instance: wxInstance): MPBase; 11 | static getRawData(instance: wxInstance): MPBase; 12 | static destory(instance: wxInstance): void; 13 | static initEventsMethods(events: string[]): Record void>; 14 | protected $store: RuntimeStore; 15 | protected $ready: boolean; 16 | private $readyCallback; 17 | protected $onReady(callback: () => void): void; 18 | private $setReady; 19 | protected $destoryCallback: Array<() => void>; 20 | protected $destory(): void; 21 | /**编译后覆盖 render函数 */ 22 | protected render(genProp: (value: T, key: Array | string, native?: boolean) => T, genEvent: (value: T, key: Array | string) => T): any; 23 | } 24 | export {}; 25 | -------------------------------------------------------------------------------- /dist/runtime/base/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var reactivity_1 = require("../reactivity"); 4 | var store_1 = require("./store"); 5 | var MPBase = /** @class */ (function () { 6 | function MPBase() { 7 | this.$store = new store_1.default; 8 | this.$ready = false; 9 | this.$readyCallback = []; 10 | this.$destoryCallback = []; 11 | } 12 | MPBase.init = function (instance, data, callback) { 13 | var _this = this; 14 | Object.defineProperty(data, "$this", { 15 | enumerable: false, 16 | configurable: false, 17 | get: function () { 18 | return reactivity_1.default.markRaw(instance); 19 | } 20 | }); 21 | data.$onReady(function () { 22 | callback === null || callback === void 0 ? void 0 : callback(); 23 | }); 24 | var proxyData = reactivity_1.default.reactive(data); 25 | var stop = reactivity_1.default.effect(function (pause, resume) { 26 | if (!data.$store) { 27 | return; 28 | } 29 | var timeId = instance.is + Math.random(); 30 | if (_this.debug) { 31 | console.time(timeId); 32 | } 33 | data.$store.start(); 34 | proxyData.render( 35 | // prop 构建 36 | function (value, key, native) { 37 | data.$store.addProp(key, reactivity_1.default.toRaw(value), native); 38 | return value; 39 | }, 40 | // event 构建 41 | function (fn, key) { 42 | data.$store.addEvent(Array.isArray(key) ? key.join('.') : key, fn); 43 | return fn; 44 | }); 45 | pause(); 46 | try { 47 | var state = data.$store.end(); 48 | if (_this.debug) { 49 | console.timeEnd(timeId); 50 | } 51 | if (state) { 52 | if (_this.debug) { 53 | console.log(instance.is, state); 54 | } 55 | instance.setData(state, function () { 56 | if (!data.$ready) { 57 | data.$setReady(); 58 | } 59 | }); 60 | } 61 | } 62 | catch (e) { 63 | throw e; 64 | } 65 | finally { 66 | resume(); 67 | } 68 | }); 69 | data.$destoryCallback.push(function () { 70 | stop(); 71 | }); 72 | return this.bindData(instance, proxyData); 73 | }; 74 | MPBase.bindData = function (instance, data) { 75 | this.dataMap.set(instance, data); 76 | return data; 77 | }; 78 | MPBase.getData = function (instance) { 79 | return this.dataMap.get(instance); 80 | }; 81 | MPBase.getRawData = function (instance) { 82 | return reactivity_1.default.toRaw(this.getData(instance)); 83 | }; 84 | MPBase.destory = function (instance) { 85 | this.getData(instance).$destory(); 86 | this.dataMap.delete(instance); 87 | }; 88 | MPBase.initEventsMethods = function (events) { 89 | var methods = {}; 90 | var self = this; 91 | events.forEach(function (name) { 92 | methods[name] = function (event) { 93 | var data = self.getData(this); 94 | var dataset = event.currentTarget.dataset; 95 | var key = dataset[name] !== undefined ? [name, dataset[name]].join('.') : name; 96 | data.$store.runEvent(key, event.detail, event); 97 | }; 98 | }); 99 | return methods; 100 | }; 101 | MPBase.prototype.$onReady = function (callback) { 102 | if (this.$ready) { 103 | callback(); 104 | } 105 | else { 106 | this.$readyCallback.push(callback); 107 | } 108 | }; 109 | MPBase.prototype.$setReady = function () { 110 | this.$ready = true; 111 | this.$readyCallback.forEach(function (cb) { return cb(); }); 112 | this.$readyCallback = []; 113 | }; 114 | MPBase.prototype.$destory = function () { 115 | this.$destoryCallback.forEach(function (fn) { return fn(); }); 116 | this.$destoryCallback = []; 117 | this.$readyCallback = []; 118 | this.$store.destroy(); 119 | this.$store = null; 120 | }; 121 | /**编译后覆盖 render函数 */ 122 | MPBase.prototype.render = function (genProp, genEvent) { }; 123 | MPBase.debug = false; 124 | MPBase.dataMap = new WeakMap(); 125 | return MPBase; 126 | }()); 127 | exports.default = MPBase; 128 | -------------------------------------------------------------------------------- /dist/runtime/base/store/diff/index.d.ts: -------------------------------------------------------------------------------- 1 | export default class Diff { 2 | private data; 3 | private state; 4 | reset(): void; 5 | get(): Record | undefined; 6 | add(key: string | string[], value: any, native?: boolean): void; 7 | destroy(): void; 8 | private getValue; 9 | private setValue; 10 | private deep; 11 | } 12 | -------------------------------------------------------------------------------- /dist/runtime/base/store/diff/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __values = (this && this.__values) || function(o) { 3 | var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; 4 | if (m) return m.call(o); 5 | if (o && typeof o.length === "number") return { 6 | next: function () { 7 | if (o && i >= o.length) o = void 0; 8 | return { value: o && o[i++], done: !o }; 9 | } 10 | }; 11 | throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); 12 | }; 13 | Object.defineProperty(exports, "__esModule", { value: true }); 14 | var state_1 = require("./state"); 15 | var Diff = /** @class */ (function () { 16 | function Diff() { 17 | this.data = {}; 18 | this.state = new state_1.default; 19 | } 20 | Diff.prototype.reset = function () { 21 | this.state.reset(); 22 | }; 23 | Diff.prototype.get = function () { 24 | var _this = this; 25 | var data = this.state.get(); 26 | if (data.length > 0) { 27 | var result_1 = {}; 28 | data.forEach(function (item) { 29 | result_1[item.name] = _this.getValue(item.path); 30 | }); 31 | return result_1; 32 | } 33 | }; 34 | Diff.prototype.add = function (key, value, native) { 35 | var oldValue = this.getValue(key); 36 | if (native) { 37 | if (oldValue !== value) { 38 | this.setValue(key, value); 39 | this.state.add(key); 40 | } 41 | } 42 | else { 43 | var newValue = this.deep(oldValue, value, key); 44 | if (newValue !== oldValue) { 45 | this.setValue(key, newValue); 46 | } 47 | } 48 | }; 49 | Diff.prototype.destroy = function () { 50 | this.state.destroy(); 51 | this.data = null; 52 | }; 53 | Diff.prototype.getValue = function (key) { 54 | return Array.isArray(key) ? get(this.data, key) : this.data[key]; 55 | }; 56 | Diff.prototype.setValue = function (key, value) { 57 | if (Array.isArray(key)) { 58 | set(this.data, key, value); 59 | } 60 | else { 61 | this.data[key] = value; 62 | } 63 | }; 64 | Diff.prototype.deep = function (value, newValue, keys) { 65 | var _this = this; 66 | if (Array.isArray(newValue)) { 67 | if (keys !== undefined && (!value || value.length !== newValue.length)) { 68 | this.state.add(keys); 69 | keys = undefined; 70 | } 71 | return newValue.map(function (item, index) { return _this.deep(value ? value[index] : undefined, item, keys !== undefined ? concat(keys, index) : undefined); }); 72 | } 73 | else if (isRecord(newValue)) { 74 | var result = {}; 75 | for (var key in newValue) { 76 | result[key] = this.deep(value ? value[key] : undefined, newValue[key], keys !== undefined ? concat(keys, key) : undefined); 77 | } 78 | return result; 79 | } 80 | else { 81 | if (keys !== undefined && value !== newValue) { 82 | this.state.add(keys); 83 | } 84 | return newValue; 85 | } 86 | }; 87 | return Diff; 88 | }()); 89 | exports.default = Diff; 90 | function concat(keys, key) { 91 | return [].concat(keys).concat(key); 92 | } 93 | function get(obj, keys) { 94 | var e_1, _a; 95 | try { 96 | for (var keys_1 = __values(keys), keys_1_1 = keys_1.next(); !keys_1_1.done; keys_1_1 = keys_1.next()) { 97 | var key = keys_1_1.value; 98 | obj = obj[key]; 99 | if (obj === undefined) { 100 | return obj; 101 | } 102 | } 103 | } 104 | catch (e_1_1) { e_1 = { error: e_1_1 }; } 105 | finally { 106 | try { 107 | if (keys_1_1 && !keys_1_1.done && (_a = keys_1.return)) _a.call(keys_1); 108 | } 109 | finally { if (e_1) throw e_1.error; } 110 | } 111 | return obj; 112 | } 113 | function set(obj, keys, value) { 114 | keys.slice(0, -1).forEach(function (key) { 115 | if (!obj[key]) { 116 | obj[key] = []; 117 | } 118 | obj = obj[key]; 119 | }); 120 | obj[keys.slice(-1)[0]] = value; 121 | } 122 | function isObject(data) { 123 | return typeof data === 'object' && data !== null; 124 | } 125 | function isRecord(data) { 126 | return Object.prototype.toString.call(data) === '[object Object]'; 127 | } 128 | -------------------------------------------------------------------------------- /dist/runtime/base/store/diff/state/index.d.ts: -------------------------------------------------------------------------------- 1 | type result = { 2 | dict: Record | null; 3 | children: data[] | null; 4 | }; 5 | type data = { 6 | name: string; 7 | path: string; 8 | length: number; 9 | } & result; 10 | export default class DiffState { 11 | data: data[]; 12 | dict: Record; 13 | add(keys: string | string[]): void; 14 | get(): { 15 | name: string; 16 | path: string[]; 17 | }[]; 18 | reset(): void; 19 | destroy(): void; 20 | } 21 | export {}; 22 | -------------------------------------------------------------------------------- /dist/runtime/base/store/diff/state/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __read = (this && this.__read) || function (o, n) { 3 | var m = typeof Symbol === "function" && o[Symbol.iterator]; 4 | if (!m) return o; 5 | var i = m.call(o), r, ar = [], e; 6 | try { 7 | while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); 8 | } 9 | catch (error) { e = { error: error }; } 10 | finally { 11 | try { 12 | if (r && !r.done && (m = i["return"])) m.call(i); 13 | } 14 | finally { if (e) throw e.error; } 15 | } 16 | return ar; 17 | }; 18 | var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { 19 | if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { 20 | if (ar || !(i in from)) { 21 | if (!ar) ar = Array.prototype.slice.call(from, 0, i); 22 | ar[i] = from[i]; 23 | } 24 | } 25 | return to.concat(ar || Array.prototype.slice.call(from)); 26 | }; 27 | Object.defineProperty(exports, "__esModule", { value: true }); 28 | var DiffState = /** @class */ (function () { 29 | function DiffState() { 30 | this.data = []; 31 | this.dict = {}; 32 | } 33 | DiffState.prototype.add = function (keys) { 34 | var children = Array.isArray(keys) ? __spreadArray([], __read(keys), false) : [keys]; 35 | var result = { 36 | dict: this.dict, 37 | children: this.data 38 | }; 39 | while (result.dict && result.children && children.length > 0) { 40 | var key = children.splice(0, 1)[0]; 41 | var hasNext = children.length > 0; 42 | if (!result.dict[key]) { 43 | var data_1 = { 44 | name: typeof key === 'number' ? "[".concat(key, "]") : ".".concat(key), 45 | path: key, 46 | dict: hasNext ? {} : null, 47 | children: hasNext ? [] : null, 48 | get length() { 49 | if (this.children) { 50 | return this.children.reduce(function (s, i) { return s + i.length; }, 0); 51 | } 52 | return 1; 53 | } 54 | }; 55 | result.dict[key] = data_1; 56 | result.children.push(data_1); 57 | } 58 | var data = result.dict[key]; 59 | if (data.length > 20) { 60 | data.children = data.dict = null; 61 | } 62 | result.dict = data.dict; 63 | result.children = data.children; 64 | } 65 | }; 66 | DiffState.prototype.get = function () { 67 | var result = []; 68 | var forEach = function (data, name, path) { 69 | name = name + data.name; 70 | path = path.concat(data.path); 71 | if (data.children) { 72 | data.children.forEach(function (item) { 73 | forEach(item, name, path); 74 | }); 75 | } 76 | else { 77 | result.push({ 78 | name: name, 79 | path: path 80 | }); 81 | } 82 | }; 83 | this.data.forEach(function (item) { 84 | forEach(item, '', []); 85 | }); 86 | return result; 87 | }; 88 | DiffState.prototype.reset = function () { 89 | this.data = []; 90 | this.dict = {}; 91 | }; 92 | DiffState.prototype.destroy = function () { 93 | this.data = null; 94 | this.dict = null; 95 | }; 96 | return DiffState; 97 | }()); 98 | exports.default = DiffState; 99 | -------------------------------------------------------------------------------- /dist/runtime/base/store/index.d.ts: -------------------------------------------------------------------------------- 1 | export default class RuntimeStore { 2 | private diff; 3 | addProp(key: string | string[], value: any, native?: boolean): void; 4 | start(): void; 5 | end(): Record | undefined; 6 | private events; 7 | addEvent(key: string, fn: any): void; 8 | runEvent(key: string, arg: any, event: Event.Base, void>): void; 9 | /**框架组件属性代理 */ 10 | private propRecord; 11 | private propProxy; 12 | private proxyProp; 13 | /**事件属性代理 */ 14 | private fnRecord; 15 | private fnProxy; 16 | private proxyFn; 17 | destroy(): void; 18 | } 19 | -------------------------------------------------------------------------------- /dist/runtime/base/store/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var utils_1 = require("../../utils"); 4 | var diff_1 = require("./diff"); 5 | var RuntimeStore = /** @class */ (function () { 6 | function RuntimeStore() { 7 | this.diff = new diff_1.default; 8 | this.events = {}; 9 | /**框架组件属性代理 */ 10 | this.propRecord = {}; 11 | this.propProxy = {}; 12 | /**事件属性代理 */ 13 | this.fnRecord = {}; 14 | this.fnProxy = {}; 15 | } 16 | RuntimeStore.prototype.addProp = function (key, value, native) { 17 | if (value === undefined) { 18 | value = null; 19 | } 20 | else if (native) { 21 | if (isObject(value)) { 22 | value = this.proxyProp(value, key); 23 | } 24 | else if (typeof value === 'function') { 25 | value = this.proxyFn(value, key); 26 | } 27 | } 28 | this.diff.add(key, value, native); 29 | }; 30 | RuntimeStore.prototype.start = function () { 31 | this.diff.reset(); 32 | }; 33 | RuntimeStore.prototype.end = function () { 34 | return this.diff.get(); 35 | }; 36 | RuntimeStore.prototype.addEvent = function (key, fn) { 37 | this.events[key] = fn; 38 | }; 39 | RuntimeStore.prototype.runEvent = function (key, arg, event) { 40 | this.events[key].call(null, arg, event); 41 | }; 42 | RuntimeStore.prototype.proxyProp = function (value, key) { 43 | var k = Array.isArray(key) ? key.join('_') : key; 44 | if (this.propRecord[k] !== value) { 45 | this.propRecord[k] = value; 46 | this.propProxy[k] = (0, utils_1.buildMPData)(value); 47 | } 48 | return this.propProxy[k]; 49 | }; 50 | RuntimeStore.prototype.proxyFn = function (value, key) { 51 | var _this = this; 52 | var k = Array.isArray(key) ? key.join('_') : key; 53 | this.fnRecord[k] = value; 54 | if (!this.fnProxy[k]) { 55 | this.fnProxy[k] = (0, utils_1.buildMPData)(function () { 56 | var args = []; 57 | for (var _i = 0; _i < arguments.length; _i++) { 58 | args[_i] = arguments[_i]; 59 | } 60 | return _this.fnRecord[k].apply(null, args); 61 | }); 62 | } 63 | return this.fnProxy[k]; 64 | }; 65 | RuntimeStore.prototype.destroy = function () { 66 | this.diff.destroy(); 67 | this.events = null; 68 | this.fnRecord = null; 69 | this.fnProxy = null; 70 | this.propRecord = null; 71 | this.propRecord = null; 72 | }; 73 | return RuntimeStore; 74 | }()); 75 | exports.default = RuntimeStore; 76 | function isObject(data) { 77 | return typeof data === 'object' && data !== null; 78 | } 79 | -------------------------------------------------------------------------------- /dist/runtime/component/index.d.ts: -------------------------------------------------------------------------------- 1 | import MPBase from "../base"; 2 | export default class MPComponent< 3 | /**组件需要传入参数 */ 4 | T extends object = {}, 5 | /**有默认值的组件参数名称, 默认值请申明在static propsDefault中*/ 6 | P extends keyof T = never> extends MPBase { 7 | /**组件数据监控 { 字段名称: 运行的组件方法名称 } */ 8 | static observers: Record; 9 | /**组件参数默认值 */ 10 | static propsDefault: Record; 11 | /**组件参数 编译后覆盖 */ 12 | static properties: Record; 13 | static $options: any; 14 | static create({ properties, events }: { 15 | properties: Record; 16 | events: string[]; 17 | }): string; 18 | protected created?(): void; 19 | protected detached?(): void; 20 | protected attached?(): void; 21 | protected readonly $this: WechatMiniprogram.Component.Instance<{}, {}, {}>; 22 | readonly $props: T & ([P] extends [never] ? {} : { 23 | [key in P]-?: T[P]; 24 | }); 25 | constructor(args?: Readonly); 26 | } 27 | -------------------------------------------------------------------------------- /dist/runtime/component/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || (function () { 3 | var extendStatics = function (d, b) { 4 | extendStatics = Object.setPrototypeOf || 5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 6 | function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; 7 | return extendStatics(d, b); 8 | }; 9 | return function (d, b) { 10 | if (typeof b !== "function" && b !== null) 11 | throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); 12 | extendStatics(d, b); 13 | function __() { this.constructor = d; } 14 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 15 | }; 16 | })(); 17 | var __assign = (this && this.__assign) || function () { 18 | __assign = Object.assign || function(t) { 19 | for (var s, i = 1, n = arguments.length; i < n; i++) { 20 | s = arguments[i]; 21 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) 22 | t[p] = s[p]; 23 | } 24 | return t; 25 | }; 26 | return __assign.apply(this, arguments); 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | var base_1 = require("../base"); 30 | var reactivity_1 = require("../reactivity"); 31 | var utils_1 = require("../utils"); 32 | var MPComponent = /** @class */ (function (_super) { 33 | __extends(MPComponent, _super); 34 | function MPComponent(args) { 35 | if (args === void 0) { args = {}; } 36 | var _this = _super.call(this) || this; 37 | Object.defineProperty(_this, '$props', { 38 | enumerable: false, 39 | writable: true, 40 | configurable: true, 41 | value: reactivity_1.default.reactive({}) 42 | }); 43 | return _this; 44 | } 45 | MPComponent.create = function (_a) { 46 | var properties = _a.properties, events = _a.events; 47 | var methods = this.initEventsMethods(events); 48 | this.properties = properties; 49 | // 将默认值赋值给properties 50 | for (var key in this.properties) { 51 | if (this.propsDefault[key] !== undefined) { 52 | this.properties[key] = { 53 | type: this.properties[key], 54 | value: this.propsDefault[key], 55 | }; 56 | } 57 | } 58 | var observers = {}; 59 | var _loop_1 = function (key) { 60 | var obMethodName = this_1.observers[key]; 61 | observers[key] = function (newData) { 62 | var data = Self.getData(this); 63 | var oldValue = data.$props[key]; 64 | if (!(0, utils_1.isMPDataReady)(newData)) { 65 | console.log('MPData is not Ready', newData); 66 | return; 67 | } 68 | var newValue = (0, utils_1.originMPData)(newData, this.is + '->observers->' + key); 69 | if (oldValue === newValue) { 70 | return; 71 | } 72 | reactivity_1.default.set(data.$props, key, newValue); 73 | // data.$props[key] = newValue 74 | if (obMethodName) { 75 | // 运行监控数据映射的函数 76 | var method = data[obMethodName]; 77 | if (method) { 78 | method.apply(data, [newValue, oldValue]); 79 | } 80 | else { 81 | console.error("observer method ".concat(obMethodName, " is not exist")); 82 | } 83 | } 84 | }; 85 | }; 86 | var this_1 = this; 87 | // 映射定义的监控变量和触发函数 88 | for (var key in this.properties) { 89 | _loop_1(key); 90 | } 91 | var Self = this; 92 | return Component({ 93 | options: __assign({}, this.$options), 94 | observers: observers, 95 | properties: this.properties, 96 | lifetimes: { 97 | created: function () { 98 | var _a; 99 | var data = new Self(); 100 | Self.bindData(this, data); 101 | (_a = data.created) === null || _a === void 0 ? void 0 : _a.call(data); 102 | }, 103 | attached: function () { 104 | var data = Self.init(this, Self.getData(this), function () { 105 | var _a; 106 | (_a = data.attached) === null || _a === void 0 ? void 0 : _a.call(data); 107 | }); 108 | }, 109 | detached: function () { 110 | var _a; 111 | var data = Self.getData(this); 112 | (_a = data.detached) === null || _a === void 0 ? void 0 : _a.call(data); 113 | Self.destory(this); 114 | } 115 | }, 116 | methods: methods 117 | }); 118 | }; 119 | /**组件数据监控 { 字段名称: 运行的组件方法名称 } */ 120 | MPComponent.observers = {}; 121 | /**组件参数默认值 */ 122 | MPComponent.propsDefault = {}; 123 | /**组件参数 编译后覆盖 */ 124 | MPComponent.properties = {}; 125 | MPComponent.$options = {}; 126 | return MPComponent; 127 | }(base_1.default)); 128 | exports.default = MPComponent; 129 | -------------------------------------------------------------------------------- /dist/runtime/index.d.ts: -------------------------------------------------------------------------------- 1 | import MPComponent from "./component"; 2 | import MPPage from "./page"; 3 | declare const MarchMP: { 4 | Page: typeof MPPage; 5 | Component: typeof MPComponent; 6 | }; 7 | declare namespace MarchMP { 8 | type Page = MPPage; 9 | type Component = MPComponent; 10 | } 11 | export declare function toRaw(data: T): T; 12 | export declare function markRaw(data: T): T; 13 | export declare function reactive(data: T): T; 14 | export { MPPage, MPComponent }; 15 | export default MarchMP; 16 | -------------------------------------------------------------------------------- /dist/runtime/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.MPComponent = exports.MPPage = exports.reactive = exports.markRaw = exports.toRaw = void 0; 4 | var component_1 = require("./component"); 5 | exports.MPComponent = component_1.default; 6 | var page_1 = require("./page"); 7 | exports.MPPage = page_1.default; 8 | var reactivity_1 = require("./reactivity"); 9 | var MarchMP = { 10 | Page: page_1.default, 11 | Component: component_1.default, 12 | }; 13 | function toRaw(data) { 14 | return reactivity_1.default.toRaw(data); 15 | } 16 | exports.toRaw = toRaw; 17 | function markRaw(data) { 18 | return reactivity_1.default.markRaw(data); 19 | } 20 | exports.markRaw = markRaw; 21 | function reactive(data) { 22 | return reactivity_1.default.reactive(data); 23 | } 24 | exports.reactive = reactive; 25 | exports.default = MarchMP; 26 | -------------------------------------------------------------------------------- /dist/runtime/page/index.d.ts: -------------------------------------------------------------------------------- 1 | import MPBase from "../base"; 2 | export default class MPPage extends MPBase { 3 | protected readonly $this: WechatMiniprogram.Page.Instance<{}, {}>; 4 | protected onLoad?(data: Record): void; 5 | protected onShow?(): void; 6 | protected onHide?(): void; 7 | protected onUnload?(): void; 8 | protected onReady?(): void; 9 | static create({ events }: { 10 | events: string[]; 11 | }): void; 12 | } 13 | -------------------------------------------------------------------------------- /dist/runtime/page/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __extends = (this && this.__extends) || (function () { 3 | var extendStatics = function (d, b) { 4 | extendStatics = Object.setPrototypeOf || 5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || 6 | function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; 7 | return extendStatics(d, b); 8 | }; 9 | return function (d, b) { 10 | if (typeof b !== "function" && b !== null) 11 | throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); 12 | extendStatics(d, b); 13 | function __() { this.constructor = d; } 14 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); 15 | }; 16 | })(); 17 | var __assign = (this && this.__assign) || function () { 18 | __assign = Object.assign || function(t) { 19 | for (var s, i = 1, n = arguments.length; i < n; i++) { 20 | s = arguments[i]; 21 | for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) 22 | t[p] = s[p]; 23 | } 24 | return t; 25 | }; 26 | return __assign.apply(this, arguments); 27 | }; 28 | Object.defineProperty(exports, "__esModule", { value: true }); 29 | var base_1 = require("../base"); 30 | var readySymbol = Symbol(); 31 | var MPPage = /** @class */ (function (_super) { 32 | __extends(MPPage, _super); 33 | function MPPage() { 34 | return _super !== null && _super.apply(this, arguments) || this; 35 | } 36 | MPPage.create = function (_a) { 37 | var events = _a.events; 38 | var methods = this.initEventsMethods(events); 39 | var Self = this; 40 | return Page(__assign({ onLoad: function (args) { 41 | var _this = this; 42 | var data = Self.init(this, new Self(), function () { 43 | var _a, _b; 44 | (_a = data.onLoad) === null || _a === void 0 ? void 0 : _a.call(data, args); 45 | (_b = data.onShow) === null || _b === void 0 ? void 0 : _b.call(data); 46 | Reflect.set(_this, readySymbol, true); 47 | }); 48 | }, onReady: function () { 49 | var data = Self.getData(this); 50 | data.$onReady(function () { 51 | var _a; 52 | (_a = data.onReady) === null || _a === void 0 ? void 0 : _a.call(data); 53 | }); 54 | }, onShow: function () { 55 | var _a; 56 | if (Reflect.get(this, readySymbol)) { 57 | var data = Self.getData(this); 58 | (_a = data.onShow) === null || _a === void 0 ? void 0 : _a.call(data); 59 | } 60 | }, onHide: function () { 61 | var _a; 62 | var data = Self.getData(this); 63 | (_a = data.onHide) === null || _a === void 0 ? void 0 : _a.call(data); 64 | }, onUnload: function () { 65 | var _a; 66 | var data = Self.getData(this); 67 | (_a = data.onUnload) === null || _a === void 0 ? void 0 : _a.call(data); 68 | Self.destory(this); 69 | } }, methods)); 70 | }; 71 | return MPPage; 72 | }(base_1.default)); 73 | exports.default = MPPage; 74 | -------------------------------------------------------------------------------- /dist/runtime/reactivity/define/index.d.ts: -------------------------------------------------------------------------------- 1 | import Reactivity from ".."; 2 | declare const DefineReactivity: Reactivity; 3 | export default DefineReactivity; 4 | -------------------------------------------------------------------------------- /dist/runtime/reactivity/define/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var vue_reactivity_1 = require("vue-reactivity"); 4 | var DefineReactivity = { 5 | reactive: function (data) { 6 | return (0, vue_reactivity_1.reactive)(data); 7 | }, 8 | effect: function (callback) { 9 | return (0, vue_reactivity_1.watchEffect)(function () { 10 | callback(function () { return (0, vue_reactivity_1.pushTarget)(); }, function () { return (0, vue_reactivity_1.popTarget)(); }); 11 | }); 12 | }, 13 | toRaw: function (data) { 14 | return (0, vue_reactivity_1.toRaw)(data); 15 | }, 16 | markRaw: function (data) { 17 | return (0, vue_reactivity_1.markRaw)(data); 18 | }, 19 | set: function (data, key, value) { 20 | (0, vue_reactivity_1.set)(data, key, value); 21 | } 22 | }; 23 | exports.default = DefineReactivity; 24 | -------------------------------------------------------------------------------- /dist/runtime/reactivity/index.d.ts: -------------------------------------------------------------------------------- 1 | interface Reactivity { 2 | reactive(data: T): T; 3 | effect(callback: (pause: () => void, resume: () => void) => void): () => void; 4 | toRaw(data: T): T; 5 | markRaw(data: T): T; 6 | set(data: T, key: K, value: T[K]): void; 7 | } 8 | declare const Reactivity: { 9 | use(type: 'proxy' | 'define'): void; 10 | reactive(data: T): T; 11 | effect(callback: (pause: () => void, resume: () => void) => void): () => void; 12 | toRaw(data: T_1): T_1; 13 | markRaw(data: T_2): T_2; 14 | set(data: T_3, key: K, value: T_3[K]): void; 15 | }; 16 | export default Reactivity; 17 | -------------------------------------------------------------------------------- /dist/runtime/reactivity/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var define_1 = require("./define"); 4 | var proxy_1 = require("./proxy"); 5 | var proxy = proxy_1.default; 6 | var define = define_1.default; 7 | var actived = proxy_1.default; 8 | var Reactivity = { 9 | use: function (type) { 10 | actived = type === 'proxy' ? proxy : define; 11 | }, 12 | reactive: function (data) { 13 | return actived.reactive(data); 14 | }, 15 | effect: function (callback) { 16 | return actived.effect(callback); 17 | }, 18 | toRaw: function (data) { 19 | return actived.toRaw(data); 20 | }, 21 | markRaw: function (data) { 22 | return actived.markRaw(data); 23 | }, 24 | set: function (data, key, value) { 25 | actived.set(data, key, value); 26 | } 27 | }; 28 | exports.default = Reactivity; 29 | -------------------------------------------------------------------------------- /dist/runtime/reactivity/proxy/index.d.ts: -------------------------------------------------------------------------------- 1 | import Reactivity from ".."; 2 | declare const ProxyReactivity: Reactivity; 3 | export default ProxyReactivity; 4 | -------------------------------------------------------------------------------- /dist/runtime/reactivity/proxy/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var _vue_reactivity_1 = require("../../@vue_reactivity"); 4 | var ProxyReactivity = { 5 | reactive: function (data) { 6 | return (0, _vue_reactivity_1.reactive)(data); 7 | }, 8 | effect: function (callback) { 9 | var result = (0, _vue_reactivity_1.effect)(function () { 10 | callback(function () { return (0, _vue_reactivity_1.pauseTracking)(); }, function () { return (0, _vue_reactivity_1.enableTracking)(); }); 11 | }); 12 | return function () { 13 | (0, _vue_reactivity_1.stop)(result); 14 | }; 15 | }, 16 | toRaw: function (data) { 17 | return (0, _vue_reactivity_1.toRaw)(data); 18 | }, 19 | markRaw: function (data) { 20 | return (0, _vue_reactivity_1.markRaw)(data); 21 | }, 22 | set: function (data, key, value) { 23 | data[key] = value; 24 | } 25 | }; 26 | exports.default = ProxyReactivity; 27 | -------------------------------------------------------------------------------- /dist/runtime/utils/index.d.ts: -------------------------------------------------------------------------------- 1 | export declare function buildMPData(object: T): { 2 | __origin__fn: () => T; 3 | }; 4 | export declare function initMPData(object: T): boolean; 5 | export declare function isMPDataReady(object: T): boolean; 6 | export declare function originMPData(object: T, info?: string, other?: any): T; 7 | -------------------------------------------------------------------------------- /dist/runtime/utils/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.originMPData = exports.isMPDataReady = exports.initMPData = exports.buildMPData = void 0; 4 | var originKey = '__origin__fn'; 5 | function buildMPData(object) { 6 | var _a; 7 | var result = (_a = {}, 8 | _a[originKey] = function () { return object; }, 9 | _a); 10 | return result; 11 | } 12 | exports.buildMPData = buildMPData; 13 | function initMPData(object) { 14 | if (isObject(object)) { 15 | var fn = Reflect.get(object, originKey); 16 | if (!fn) { 17 | Reflect.set(object, originKey, function () { return object; }); 18 | return true; 19 | } 20 | } 21 | return false; 22 | } 23 | exports.initMPData = initMPData; 24 | function isMPDataReady(object) { 25 | if (isObject(object)) { 26 | var originFn = Reflect.get(object, originKey); 27 | if (originFn) { 28 | return true; 29 | } 30 | else { 31 | return false; 32 | } 33 | } 34 | return true; 35 | } 36 | exports.isMPDataReady = isMPDataReady; 37 | function originMPData(object, info, other) { 38 | if (isObject(object)) { 39 | var originFn = Reflect.get(object, originKey); 40 | if (originFn) { 41 | return originFn(); 42 | } 43 | else { 44 | console.warn('----unset origin data----', info, object, other); 45 | } 46 | } 47 | return object; 48 | } 49 | exports.originMPData = originMPData; 50 | function isObject(data) { 51 | return typeof data === 'object' && data !== null && !Array.isArray(data); 52 | } 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "march-mp", 3 | "version": "1.0.6", 4 | "description": "", 5 | "author": "gityoog", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/gityoog/march-mp.git" 9 | }, 10 | "license": "ISC", 11 | "main": "./dist/runtime/index.js", 12 | "scripts": { 13 | "build": "rimraf ./dist && tsc -p ./src/runtime/tsconfig.json && tsc -p ./src/compiler/tsconfig.json" 14 | }, 15 | "dependencies": { 16 | "@babel/generator": "^7.15.0", 17 | "@babel/parser": "^7.15.3", 18 | "@babel/traverse": "^7.15.0", 19 | "@babel/types": "^7.15.0", 20 | "copy-webpack-plugin": "^9.0.1", 21 | "ensure-posix-path": "^1.1.1", 22 | "lodash.merge": "^4.6.2", 23 | "vue-reactivity": "^1.0.3" 24 | }, 25 | "devDependencies": { 26 | "@types/babel__generator": "^7.6.3", 27 | "@types/babel__traverse": "^7.14.2", 28 | "@types/copy-webpack-plugin": "^8.0.1", 29 | "@types/lodash.merge": "^4.6.6", 30 | "rimraf": "^3.0.2", 31 | "tapable": "^2.2.1", 32 | "typescript": "^4.8.3" 33 | }, 34 | "peerDependencies": { 35 | "typescript": ">=4.7.0", 36 | "webpack": ">=5.0.0" 37 | } 38 | } -------------------------------------------------------------------------------- /src/compiler/entry/data/index.ts: -------------------------------------------------------------------------------- 1 | import ModuleData from "../../module/data" 2 | import webpack from 'webpack' 3 | import merge from 'lodash.merge' 4 | 5 | type sourceType = 'wxml' | 'json' | 'wxss' | 'wxs' 6 | export default class EntryData { 7 | name: string 8 | isPage: boolean 9 | components: Record 10 | module: ModuleData 11 | path: string 12 | 13 | private sourceCache: { 14 | [K in sourceType]?: { 15 | code: string 16 | source: webpack.sources.CachedSource 17 | } 18 | } = {} 19 | 20 | private getSource(type: sourceType, code: string) { 21 | if (this.sourceCache[type]?.code === code) { 22 | return this.sourceCache[type]!.source 23 | } else { 24 | this.sourceCache[type] = { 25 | code, 26 | source: new webpack.sources.CachedSource(new webpack.sources.RawSource(code)) 27 | } 28 | return this.sourceCache[type]!.source 29 | } 30 | } 31 | 32 | constructor({ name, path, page, components }: { 33 | name: string 34 | path: string 35 | page: boolean 36 | components: Record 37 | }) { 38 | this.path = path 39 | this.name = name 40 | this.isPage = page 41 | this.components = components 42 | this.module = ModuleData.Pick(path) 43 | } 44 | 45 | private getUsingComponents() { 46 | const components: Record = {} 47 | for (const name in this.components) { 48 | components[name] = '/' + this.components[name].replace(/\.js$/, '').replace(/\\/g, '/') 49 | } 50 | return components 51 | } 52 | 53 | private getJSON() { 54 | return JSON.stringify(merge({}, this.module.json, { 55 | usingComponents: this.getUsingComponents(), 56 | component: this.isPage ? undefined : true 57 | }), null, 2) 58 | } 59 | 60 | getFiles() { 61 | const files: { 62 | file: string 63 | source: webpack.sources.Source 64 | }[] = [] 65 | const filename = this.name.replace(/\.js$/, '') 66 | 67 | files.push({ 68 | file: filename + '.wxml', 69 | source: this.getSource('wxml', this.module.wxml) 70 | }) 71 | 72 | files.push({ 73 | file: filename + '.json', 74 | source: this.getSource('json', this.getJSON()) 75 | }) 76 | 77 | if (this.module.wxss) { 78 | files.push({ 79 | file: filename + '.wxss', 80 | source: this.getSource('wxss', this.module.wxss) 81 | }) 82 | } 83 | 84 | if (this.module.wxs) { 85 | files.push({ 86 | file: filename + '.wxs', 87 | source: this.getSource('wxs', this.module.wxs) 88 | }) 89 | } 90 | 91 | return files 92 | } 93 | } -------------------------------------------------------------------------------- /src/compiler/entry/manager/generate/index.ts: -------------------------------------------------------------------------------- 1 | import ModuleData from "../../../module/data" 2 | 3 | type node = { 4 | path: string 5 | children: Record 6 | parent: node[] 7 | } 8 | 9 | type page = { 10 | path: string 11 | root?: string 12 | independent?: boolean 13 | } 14 | 15 | function generateNodes(pages: page[]) { 16 | const dict: Record = {} 17 | const getNode = (path: string) => { 18 | if (!dict[path]) { 19 | const node: node = { 20 | path, 21 | children: {}, 22 | parent: [] 23 | } 24 | dict[path] = node 25 | } 26 | return dict[path] 27 | } 28 | const addRelation = (node: node) => { 29 | const children = ModuleData.Pick(node.path).getChildren() 30 | for (const key in children) { 31 | const child = getNode(children[key]) 32 | child.parent.push(node) 33 | node.children[key] = child 34 | addRelation(child) 35 | } 36 | } 37 | pages.forEach(page => { 38 | addRelation(getNode(page.path)) 39 | }) 40 | return dict 41 | } 42 | 43 | type entry = { 44 | path: string 45 | root?: string 46 | page: boolean 47 | name: string 48 | components: Record 49 | } 50 | 51 | //todo 需要优化 52 | export default function generateEntry(pages: page[], getName: (params: { path: string, root?: string, component?: boolean }) => string) { 53 | let refs = generateNodes(pages) 54 | let packageSet: Record> = {} 55 | pages.forEach(page => { 56 | const set = packageSet[page.path] = new Set() 57 | set.add(page.root) 58 | }) 59 | const getPackages = (node: node) => { 60 | if (!packageSet[node.path]) { 61 | const set = packageSet[node.path] = new Set 62 | node.parent.forEach(parent => { 63 | const packages = getPackages(parent) 64 | if (packages.has(undefined)) { 65 | set.add(undefined) 66 | } else { 67 | packages.forEach(value => { 68 | set.add(value) 69 | }) 70 | } 71 | }) 72 | } 73 | return packageSet[node.path] 74 | } 75 | 76 | const data: entry[] = [] 77 | let dict: Record> = {} 78 | const getEntry = (path: string, root?: string, independent: boolean = false) => { 79 | const pack = packageSet[path].has(undefined) && !independent ? undefined : root 80 | const rootEntry = dict[pack || ''] = dict[pack || ''] || {} 81 | if (!rootEntry[path]) { 82 | data.push( 83 | rootEntry[path] = { 84 | path, 85 | root: pack, 86 | page: false, 87 | name: '', 88 | components: {} 89 | } 90 | ) 91 | } 92 | return rootEntry[path] 93 | } 94 | const load = (node: node, independentRoot?: string) => { 95 | const packages = getPackages(node) 96 | if (independentRoot) { 97 | packages.delete(independentRoot) 98 | } 99 | const entries = packages.has(undefined) ? [getEntry(node.path)] : [...packages].map(root => getEntry(node.path, root)) 100 | if (independentRoot) { 101 | entries.push( 102 | getEntry(node.path, independentRoot, true) 103 | ) 104 | } 105 | for (const key in node.children) { 106 | const child = node.children[key] 107 | load(child, independentRoot) 108 | entries.forEach(entry => { 109 | entry.components[key] = getEntry(child.path, entry.root, !!independentRoot) 110 | }) 111 | } 112 | return entries 113 | } 114 | 115 | pages.forEach(page => { 116 | load(refs[page.path], page.independent ? page.root! : undefined).forEach(entry => { 117 | entry.page = true 118 | }) 119 | }) 120 | 121 | data.forEach(item => { 122 | item.name = getName({ 123 | path: item.path, 124 | root: item.root, 125 | component: !item.page 126 | }) 127 | }) 128 | refs = null! 129 | packageSet = null! 130 | dict = null! 131 | 132 | return data 133 | } -------------------------------------------------------------------------------- /src/compiler/entry/manager/index.ts: -------------------------------------------------------------------------------- 1 | import EntryData from '../data' 2 | import EntryNameCache from '../name' 3 | import generateEntry from './generate' 4 | 5 | type oldData = { 6 | path: string 7 | name: string 8 | } 9 | 10 | export default class EntryManager { 11 | data: EntryData[] = [] 12 | private nameCache = new EntryNameCache 13 | private pages: { 14 | path: string 15 | root?: string 16 | independent?: boolean 17 | }[] = [] 18 | private loaded = new Set() 19 | 20 | loadOld(callback: (item: oldData) => void) { 21 | this.loaded.clear() 22 | this.data 23 | .filter(item => !item.isPage) 24 | .forEach(item => { 25 | this.loaded.add(item.name) 26 | callback({ 27 | path: item.path, 28 | name: item.name 29 | }) 30 | }) 31 | this.clear() 32 | } 33 | needLoad(data: EntryData) { 34 | return !data.isPage && !this.loaded.has(data.name) 35 | } 36 | addPage(path: string, root?: string, independent?: boolean) { 37 | const name = this.nameCache.get({ path, root }) 38 | this.pages.push({ 39 | path, root, independent 40 | }) 41 | return name 42 | } 43 | getRoot(name: string) { 44 | return this.nameCache.getPackage(name) 45 | } 46 | setContext(context: string) { 47 | this.nameCache.setContext(context) 48 | } 49 | getNotUsed() { 50 | const used = new Set(this.data.map(item => item.name)) 51 | const notUsed: string[] = [] 52 | this.loaded.forEach(name => { 53 | if (!used.has(name)) { 54 | notUsed.push(name) 55 | } 56 | }) 57 | return notUsed 58 | } 59 | generate() { 60 | this.data = generateEntry(this.pages, (params: { path: string, root?: string, component?: boolean }) => { 61 | return this.nameCache.get(params) 62 | }) 63 | .map(entry => { 64 | const components: Record = {} 65 | for (const key in entry.components) { 66 | components[key] = entry.components[key].name 67 | } 68 | return new EntryData({ 69 | name: entry.name, 70 | path: entry.path, 71 | page: entry.page, 72 | components 73 | }) 74 | }) 75 | } 76 | clear() { 77 | this.pages = [] 78 | this.data = [] 79 | } 80 | } -------------------------------------------------------------------------------- /src/compiler/entry/name/index.ts: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | 3 | export default class EntryNameCache { 4 | private context = '' 5 | private packageDict: Record = {} 6 | private cache: Record> = {} 7 | 8 | setContext(context: string) { 9 | this.context = context 10 | } 11 | get(params: { path: string, root?: string, component?: boolean }) { 12 | const key = params.root || '' 13 | if (!this.cache[key]) { 14 | this.cache[key] = {} 15 | } 16 | if (!this.cache[key][params.path]) { 17 | const name = path.join( 18 | params.root || '', 19 | params.component ? 'components' : '', 20 | path.relative(path.join(this.context, params.root || ''), params.path) 21 | .replace(/\.\.[\\/]/g, '@').replace(/\.[\\/]/g, '') 22 | ).replace(/\.tsx$/, '.js') 23 | this.cache[key][params.path] = name 24 | this.packageDict[name] = params.root 25 | } 26 | return this.cache[key][params.path] 27 | } 28 | 29 | getPackage(name: string) { 30 | return this.packageDict[name] 31 | } 32 | } -------------------------------------------------------------------------------- /src/compiler/entry/plugin/app-data/index.ts: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import webpack from 'webpack' 3 | 4 | export default class AppData { 5 | name = 'app.json' 6 | path = '' 7 | context = '' 8 | source: webpack.sources.Source | null = null 9 | setContext(context: string) { 10 | this.context = context 11 | this.path = path.resolve(context, this.name) 12 | } 13 | private ignorePattern: Array = [] 14 | 15 | setIgnore(data?: Array) { 16 | this.ignorePattern = data || [] 17 | } 18 | 19 | private ignore(page: string) { 20 | return this.ignorePattern.some(item => { 21 | if (typeof item === 'string') { 22 | return page === item 23 | } else { 24 | return item.test(page) 25 | } 26 | }) 27 | } 28 | private entries: { 29 | root?: string 30 | path: string 31 | independent?: boolean 32 | }[] = [] 33 | private content: string = '' 34 | private roots: string[] = [] 35 | private independents = new Set() 36 | private update() { 37 | this.entries = [] 38 | this.roots = [] 39 | this.independents.clear() 40 | const data = JSON.parse(this.content) as { 41 | pages?: string[] 42 | subpackages?: { 43 | root: string 44 | pages: string[] 45 | independent?: boolean 46 | }[] 47 | } 48 | if (this.ignorePattern.length > 0) { 49 | data.pages = data.pages?.filter(page => !this.ignore(page)) 50 | data.subpackages?.forEach(({ root, pages }) => { 51 | pages = pages.filter(page => !this.ignore(root + '/' + page)) 52 | }) 53 | } 54 | this.source = new webpack.sources.CachedSource( 55 | new webpack.sources.RawSource(JSON.stringify(data, null, 2)) 56 | ) 57 | data.pages?.forEach(item => { 58 | this.entries.push({ 59 | path: path.resolve(this.context, item + '.tsx') 60 | }) 61 | }) 62 | data.subpackages?.forEach(({ root, pages, independent }) => { 63 | this.roots.push(root) 64 | independent && this.independents.add(root) 65 | pages.forEach(item => { 66 | this.entries.push({ 67 | root, 68 | path: path.resolve(this.context, root, item + '.tsx'), 69 | independent 70 | }) 71 | }) 72 | }) 73 | } 74 | getEntries(content: string | Buffer) { 75 | if (typeof content !== 'string') { 76 | content = content.toString() 77 | } 78 | if (this.content !== content) { 79 | this.content = content 80 | this.update() 81 | } 82 | return this.entries 83 | } 84 | getRoots() { 85 | return this.roots 86 | } 87 | isIndependent(root: string) { 88 | return this.independents.has(root) 89 | } 90 | } -------------------------------------------------------------------------------- /src/compiler/entry/plugin/require-chunk-plugin/index.ts: -------------------------------------------------------------------------------- 1 | import webpack from 'webpack' 2 | import path from 'path' 3 | import EnsurePosixPath from 'ensure-posix-path' 4 | 5 | type options = { 6 | calcPath: (entry: webpack.Chunk, chunk: webpack.Chunk) => string 7 | addPath: (paths: string[]) => string 8 | } 9 | export default class RequireChunkPlugin { 10 | private name = 'RequireChunkPlugin' 11 | private options: options 12 | constructor(options: Partial = {}) { 13 | this.options = { 14 | calcPath: options.calcPath || ((entry, chunk) => { 15 | return EnsurePosixPath(path.relative(path.dirname(entry.name!), chunk.name!)) 16 | }), 17 | addPath: options.addPath || ((paths) => paths.map(path => `require("${path.replace(/\\/g, '\/')}");`).join('\n') + '\n') 18 | } 19 | } 20 | apply(compiler: webpack.Compiler) { 21 | compiler.hooks.compilation.tap(this.name, (compilation) => { 22 | webpack.javascript.JavascriptModulesPlugin.getCompilationHooks(compilation).render.tap(this.name, (source, { chunk, chunkGraph }) => { 23 | // isEntry 24 | if (chunkGraph.getNumberOfEntryModules(chunk) > 0) { 25 | const chunks = Array.from(chunk.getAllReferencedChunks()).filter(chunk_ => chunk_ !== chunk) 26 | if (chunks.length > 0) { 27 | return new webpack.sources.ConcatSource(this.options.addPath(chunks.map(c => this.options.calcPath(chunk, c))), source) 28 | } 29 | } 30 | return source 31 | }) 32 | }) 33 | } 34 | } -------------------------------------------------------------------------------- /src/compiler/entry/plugin/split-package-plugin/index.ts: -------------------------------------------------------------------------------- 1 | import webpack, { ChunkGraph, web } from 'webpack' 2 | import path from 'path' 3 | 4 | export default class SplitPackagePlugin { 5 | name = 'SplitPackagePlugin' 6 | constructor(private options: { 7 | getRoot(name: string): string | undefined 8 | getRoots(): string[] 9 | isIndependent(name: string): boolean 10 | }) { } 11 | packages: any[] = [] 12 | apply(compiler: webpack.Compiler) { 13 | compiler.hooks.compilation.tap(this.name, (compilation) => { 14 | compilation.hooks.afterOptimizeModules.tap(this.name, () => { 15 | this.packages = this.options.getRoots().map(root => { 16 | return { 17 | name: path.join(root, 'common.js'), 18 | chunks: (chunk: { name: string }) => this.options.getRoot(chunk.name) === root, 19 | minChunks: 2, 20 | priority: 5 21 | } 22 | }) 23 | }) 24 | }) 25 | new webpack.optimize.SplitChunksPlugin({ 26 | maxAsyncRequests: Infinity, 27 | maxInitialRequests: Infinity, 28 | minSize: 0, 29 | cacheGroups: { 30 | common: { 31 | test: (module: webpack.Module, { chunkGraph }: { chunkGraph: webpack.ChunkGraph }) => { 32 | return chunkGraph.getModuleChunks(module).some(chunk => this.options.getRoot(chunk.name!) === undefined) 33 | }, 34 | name: 'common.js', 35 | minChunks: 2, 36 | chunks: chunk => !this.options.isIndependent(chunk.name!), 37 | priority: 10 38 | }, 39 | packages: () => { 40 | return this.packages 41 | } 42 | } 43 | // { 44 | // default: false, 45 | // common: { 46 | // test: (module: webpack.Module, { chunkGraph }: { chunkGraph: webpack.ChunkGraph }) => { 47 | // return chunkGraph.getModuleChunks(module).some(chunk => this.options.getRoot(chunk.name) === undefined) 48 | // }, 49 | // name: 'common.js', 50 | // minChunks: 2, 51 | // chunks: chunk => !this.options.isIndependent(chunk.name) 52 | // }, 53 | // packages: (module: webpack.Module, { chunkGraph }: { chunkGraph: webpack.ChunkGraph }) => { 54 | // console.log('packages') 55 | // return this.options.getRoots().map(root => ({ 56 | // test: (module: webpack.Module, { chunkGraph }: { chunkGraph: webpack.ChunkGraph }) => { 57 | // return chunkGraph.getModuleChunks(module).some(chunk => this.options.getRoot(chunk.name) === root) 58 | // }, 59 | // name: path.join(root, 'common.js'), 60 | // minChunks: 2, 61 | // chunks: (chunk: webpack.Chunk) => this.options.getRoot(chunk.name) === root 62 | // })) 63 | // } 64 | // } 65 | }).apply(compiler) 66 | } 67 | } -------------------------------------------------------------------------------- /src/compiler/entry/utils/index.ts: -------------------------------------------------------------------------------- 1 | import Path from 'path' 2 | 3 | export function genEntryName({ root, path, context, component = false }: { root?: string, path: string, context: string, component?: boolean }) { 4 | return Path.join( 5 | root || '', 6 | component ? 'components' : '', 7 | Path.relative(Path.resolve(context, root || ''), path) 8 | .replace(/\.\.[\\/]/g, '@').replace(/\.[\\/]/g, '') 9 | ).replace(/\.tsx$/, '.js') 10 | } 11 | 12 | export function repalceAll(str: string, substr: string, newSubStr: string) { 13 | return str.replace( 14 | new RegExp(substr.replace(/([\|\.\^\$\*\+\?\\\/])/g, '\\$1'), 'g'), newSubStr 15 | ) 16 | } -------------------------------------------------------------------------------- /src/compiler/index.ts: -------------------------------------------------------------------------------- 1 | import MPEntryPlugin from './entry/plugin' 2 | import fixVue3This from './ts-transformer/fix-vue3-this' 3 | 4 | const valueLoader = require.resolve('./value-loader') 5 | const tsxLoader = require.resolve('./module/loader') 6 | 7 | export { 8 | fixVue3This, 9 | valueLoader, 10 | tsxLoader 11 | } 12 | 13 | export default MPEntryPlugin -------------------------------------------------------------------------------- /src/compiler/module/data/index.ts: -------------------------------------------------------------------------------- 1 | export default class ModuleData { 2 | static map = new Map() 3 | static Init(path: string) { 4 | const origin = this.map.get(path) 5 | if (origin) { 6 | origin.destory() 7 | } 8 | const data = new ModuleData(path) 9 | this.map.set(path, data) 10 | return data 11 | } 12 | static Has(path: string) { 13 | return this.map.has(path) 14 | } 15 | static Pick(path: string) { 16 | const data = this.map.get(path) 17 | if (!data) { 18 | throw new Error('module data not exist: ' + path) 19 | } 20 | return data 21 | } 22 | private constructor(public path: string) { } 23 | json = {} as Record 24 | wxml = '' 25 | wxss = '' 26 | wxs = '' 27 | private children: Record = {} 28 | setJSON(json: Record) { 29 | this.json = json 30 | } 31 | setWXML(value: string) { 32 | this.wxml = value 33 | } 34 | addWXSS(value: string) { 35 | this.wxss += value 36 | } 37 | setWXSS(value: string) { 38 | this.wxss = value 39 | } 40 | setWXS(value: string) { 41 | this.wxs = value 42 | } 43 | setStatic(type: 'wxss' | 'wxml' | 'json' | 'wxs', value: string) { 44 | switch (type) { 45 | case 'wxss': 46 | return this.setWXSS(value) 47 | case 'wxml': 48 | return this.setWXML(value) 49 | case 'wxs': 50 | return this.setWXS(value) 51 | case 'json': 52 | return this.setJSON(JSON.parse(value)) 53 | } 54 | } 55 | addChild(key: string, path: string) { 56 | this.children[key] = path 57 | } 58 | getChildren() { 59 | return this.children 60 | } 61 | destory() { 62 | this.children = null! 63 | } 64 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/index.ts: -------------------------------------------------------------------------------- 1 | import { LoaderContext, EntryPlugin, Dependency } from 'webpack' 2 | import ModuleData from '../data' 3 | import transform from './transform' 4 | import fs from 'fs' 5 | import webpack from 'webpack' 6 | import State from './state' 7 | 8 | export default function (this: LoaderContext, source: string) { 9 | const data = ModuleData.Init(this.resourcePath) 10 | const state = new State(this.resourcePath) 11 | const callback = this.async(); 12 | 13 | (async () => { 14 | transform(source, state) 15 | data.setWXML(state.wxml) 16 | data.setJSON(state.json) 17 | 18 | for (const file of state.cssfile) { 19 | const { source, err } = await new Promise<{ 20 | source: string 21 | err?: Error | null 22 | }>((reslove) => { 23 | this.loadModule(file, (err, source) => { 24 | reslove({ 25 | err, 26 | source 27 | }) 28 | }) 29 | }) 30 | if (err) { 31 | this.emitError(err) 32 | continue 33 | } 34 | if (source) { 35 | data.addWXSS(JSON.parse(source)) 36 | } 37 | } 38 | 39 | for (const name in state.components) { 40 | const component = state.components[name] 41 | const { filename, err } = await loadModule(this, component.path) 42 | if (err) { 43 | this.emitError(err) 44 | continue 45 | } 46 | data.addChild(name, filename) 47 | if (/\.js$/.test(filename)) { 48 | // 原生组件 导入wxss wxml json wxs 49 | const componentData = ModuleData.Init(filename) 50 | const filepath = filename.replace(/\.js$/, ''); 51 | (['wxss', 'wxml', 'json', 'wxs'] as const).forEach(ext => { 52 | const path = filepath + '.' + ext 53 | if (fs.existsSync(path)) { 54 | componentData.setStatic(ext, fs.readFileSync(path).toString()) 55 | this.addDependency(path) 56 | } 57 | }) 58 | } else { 59 | state.setComponentNative(name) 60 | } 61 | } 62 | state.warning.forEach(warn => this.emitWarning(warn)) 63 | const code = state.generate() 64 | state.destroy() 65 | return code 66 | })().then(source => { 67 | callback(null, source) 68 | }).catch((e: Error) => { 69 | callback(e) 70 | }) 71 | } 72 | 73 | function loadModule(loaderContext: LoaderContext, request: string) { 74 | // this.loadModule 会引起递归检测 75 | return new Promise<{ 76 | filename: string 77 | module: webpack.Module 78 | err?: Error 79 | }>((reslove) => { 80 | loaderContext.resolve(loaderContext.context, request, (err, path) => { 81 | if (err) return reslove({ 82 | filename: null!, 83 | module: null!, 84 | err 85 | }) 86 | const filename = path as string 87 | const compilation = loaderContext._compilation! 88 | compilation.buildQueue.increaseParallelism() 89 | compilation.addModuleChain(loaderContext.context, EntryPlugin.createDependency(filename, filename), (err, module) => { 90 | compilation.buildQueue.decreaseParallelism() 91 | if (err) return reslove({ 92 | filename: null!, 93 | module: null!, 94 | err 95 | }) 96 | loaderContext.addDependency(filename) 97 | reslove({ 98 | filename, 99 | module: module! 100 | }) 101 | }) 102 | }) 103 | }) 104 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/state/identifier/event/index.ts: -------------------------------------------------------------------------------- 1 | import { iIdentifierItem } from ".." 2 | import { NodePath } from '@babel/traverse' 3 | import * as t from '@babel/types' 4 | import { genEventCall } from "../util" 5 | 6 | export default class EventIdentifier implements iIdentifierItem { 7 | private name 8 | private path: NodePath 9 | private scope?: t.Expression 10 | private value: t.Node 11 | 12 | constructor({ path, scope, name }: { 13 | path: NodePath 14 | name: string 15 | scope?: t.Expression 16 | }) { 17 | this.name = name 18 | this.path = path 19 | this.value = path.node 20 | this.scope = scope 21 | 22 | this.path.replaceWith(t.stringLiteral(name)) 23 | } 24 | restore() { 25 | this.path.replaceWith( 26 | genEventCall( 27 | this.value as t.Expression, 28 | this.scope ? t.arrayExpression([t.stringLiteral(this.name), this.scope]) : t.stringLiteral(this.name) 29 | ) 30 | ) 31 | 32 | this.name = null! 33 | this.path = null! 34 | this.scope = null! 35 | this.value = null! 36 | } 37 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/state/identifier/index.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from '@babel/traverse' 2 | import * as t from '@babel/types' 3 | import MapScope from '../map-scope' 4 | import MapIdentifier from './map' 5 | import PropIdentifier from './prop' 6 | import EventIdentifier from './event' 7 | import { genExpression } from './util' 8 | 9 | export interface iIdentifierItem { 10 | restore(): void 11 | } 12 | 13 | export default class DependencyIdentifier { 14 | private prefix = { 15 | prop: 'p', 16 | event: 'e', 17 | scope: 's' 18 | } 19 | private _id = { 20 | prop: 0, 21 | event: 0, 22 | scope: 0 23 | } 24 | private data: iIdentifierItem[] = [] 25 | 26 | constructor(private scope: MapScope) { } 27 | 28 | private genName(type: 'prop' | 'event' | 'scope') { 29 | return this.prefix[type] + (this._id[type]++) 30 | } 31 | 32 | map(path: NodePath) { 33 | const name = this.genName('prop') 34 | const calleeObject = path.get('callee.object') as NodePath 35 | const scope = this.scope.getScope(calleeObject) 36 | this.data.push( 37 | new MapIdentifier({ 38 | name, path, scope 39 | }) 40 | ) 41 | return scope 42 | } 43 | 44 | prop(path: NodePath) { 45 | const name = this.genName('prop') 46 | const scope = this.scope.getScope(path) 47 | const prop = new PropIdentifier({ 48 | name, path, scope 49 | }) 50 | this.data.push(prop) 51 | return prop 52 | } 53 | 54 | event(path: NodePath) { 55 | const name = this.genName('event') 56 | const scope = genExpression(this.scope.getScope(path)) 57 | this.data.push( 58 | new EventIdentifier({ 59 | name, path, scope 60 | }) 61 | ) 62 | return { 63 | scope, name 64 | } 65 | } 66 | 67 | restore() { 68 | this.data.forEach(item => { 69 | item.restore() 70 | }) 71 | this.data = [] 72 | } 73 | 74 | destroy() { 75 | 76 | } 77 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/state/identifier/map/index.ts: -------------------------------------------------------------------------------- 1 | import { iIdentifierItem } from ".." 2 | import { NodePath } from '@babel/traverse' 3 | import * as t from '@babel/types' 4 | import { genPropCall, mergeMember } from "../util" 5 | import generate from '@babel/generator' 6 | 7 | export default class MapIdentifier implements iIdentifierItem { 8 | private name 9 | private path: NodePath 10 | private calleeObject: t.Node 11 | private scope: string[] 12 | private key?: t.Expression 13 | constructor({ path, scope, name }: { 14 | path: NodePath 15 | name: string 16 | scope: string[] 17 | }) { 18 | this.name = name 19 | this.path = path 20 | this.scope = scope 21 | this.key = findMapKey(path) 22 | const node = mergeMember(t.identifier(name), scope) 23 | const calleeObject = path.get('callee.object') as NodePath 24 | this.calleeObject = calleeObject.node 25 | calleeObject.replaceWith(node) 26 | } 27 | restore() { 28 | const calleeObject = this.path.get('callee.object') as NodePath 29 | calleeObject.replaceWith(this.calleeObject) 30 | 31 | const arrowFn = this.path.get('arguments')[0] 32 | if (arrowFn.isArrowFunctionExpression()) { 33 | const jsxElement = arrowFn.get('body') 34 | if (jsxElement.isJSXElement()) { 35 | jsxElement.replaceWith( 36 | t.sequenceExpression([jsxElement.node, this.key || t.nullLiteral()]) 37 | ) 38 | } 39 | } 40 | // _$p(a.map(item => [key|null, ...]), name: string|string[], deepDiff: true) 41 | 42 | this.path.replaceWith( 43 | genPropCall( 44 | this.path.node, 45 | this.scope.length > 0 ? t.arrayExpression([t.stringLiteral(this.name), ...this.scope.map(key => t.identifier(key))]) : t.stringLiteral(this.name) 46 | ) 47 | ) 48 | 49 | this.name = null! 50 | this.path = null! 51 | this.calleeObject = null! 52 | this.scope = null! 53 | this.key = null! 54 | } 55 | } 56 | 57 | 58 | function findMapKey(path: NodePath) { 59 | const arrowFn = path.get('arguments')[0] 60 | if (arrowFn.isArrowFunctionExpression()) { 61 | const jsxElement = arrowFn.get('body') 62 | if (jsxElement.isJSXElement()) { 63 | const attr = jsxElement.get('openingElement').get('attributes').find(path => { 64 | return path.isJSXAttribute() && path.node.name.name === 'key' 65 | }) as NodePath | null 66 | const value = attr?.get('value') 67 | if (value?.isJSXExpressionContainer()) { 68 | const expression = value.node.expression 69 | if (!t.isJSXEmptyExpression(expression)) { 70 | value.replaceWith(t.stringLiteral("*this")) 71 | return expression 72 | } 73 | } else if (value?.isStringLiteral()) { 74 | const param = arrowFn.node.params[0] = (arrowFn.node.params[0] || path.scope.generateUidIdentifier('t')) as t.Identifier 75 | const key = value.node.value 76 | if (key === '*this') { 77 | return param 78 | } else { 79 | value.replaceWith(t.stringLiteral("*this")) 80 | return t.memberExpression(param, t.identifier(key), false) 81 | } 82 | } 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/state/identifier/prop/index.ts: -------------------------------------------------------------------------------- 1 | import { iIdentifierItem } from ".." 2 | import { NodePath } from '@babel/traverse' 3 | import * as t from '@babel/types' 4 | import { genPropCall, mergeMember } from "../util" 5 | 6 | export default class PropIdentifier implements iIdentifierItem { 7 | private name 8 | private path: NodePath 9 | private scope: string[] 10 | private value: t.Node 11 | private native = false 12 | constructor({ path, scope, name }: { 13 | path: NodePath 14 | name: string 15 | scope: string[] 16 | }) { 17 | this.name = name 18 | this.path = path 19 | this.scope = scope 20 | this.value = path.node 21 | 22 | this.path.replaceWith( 23 | mergeMember(t.identifier(name), scope) 24 | ) 25 | } 26 | 27 | setNative() { 28 | this.native = true 29 | } 30 | 31 | restore() { 32 | this.path.replaceWith( 33 | genPropCall( 34 | this.value as t.Expression, 35 | this.scope.length > 0 ? t.arrayExpression([t.stringLiteral(this.name), ...this.scope.map(key => t.identifier(key))]) : t.stringLiteral(this.name), 36 | this.native 37 | ) 38 | ) 39 | 40 | this.name = null! 41 | this.path = null! 42 | this.scope = null! 43 | this.value = null! 44 | } 45 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/state/identifier/util.ts: -------------------------------------------------------------------------------- 1 | import * as t from '@babel/types' 2 | 3 | export function mergeMember(identifier: t.Identifier, indexs: string[]): t.Identifier | t.MemberExpression { 4 | let node: t.Identifier | t.MemberExpression = identifier 5 | indexs.forEach(index => { 6 | node = t.memberExpression(node, t.identifier(index), true) 7 | }) 8 | return node 9 | } 10 | 11 | export function genExpression(indexs: string[]) { 12 | let property: t.Expression | undefined = undefined 13 | for (const index of indexs) { 14 | if (!property) { 15 | property = t.identifier(index) 16 | } else { 17 | property = t.binaryExpression( 18 | '+', 19 | t.binaryExpression( 20 | '+', 21 | property, 22 | t.stringLiteral('_') 23 | ), 24 | t.identifier(index) 25 | ) 26 | } 27 | } 28 | return property 29 | } 30 | 31 | export const fnName = { 32 | prop: '_$p', 33 | event: '_$e' 34 | } 35 | 36 | export function genPropCall(value: t.Expression, name: t.StringLiteral | t.ArrayExpression, native?: boolean) { 37 | return t.callExpression(t.identifier(fnName.prop), [ 38 | value, 39 | name 40 | ].concat(native ? t.booleanLiteral(true) : [])) 41 | } 42 | 43 | export function genEventCall(value: t.Expression, name: t.StringLiteral | t.ArrayExpression) { 44 | return t.callExpression(t.identifier(fnName.event), [ 45 | value, 46 | name 47 | ]) 48 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/state/index.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from "@babel/traverse" 2 | import DependencyIdentifier from "./identifier" 3 | import MapScope from "./map-scope" 4 | import * as t from '@babel/types' 5 | import PropIdentifier from "./identifier/prop" 6 | 7 | export default class State { 8 | debug = false 9 | constructor(filename: string) { 10 | 11 | } 12 | json: any = {} 13 | cssfile: string[] = [] 14 | wxml = '' 15 | 16 | setWXML(value: string) { 17 | this.wxml = value 18 | } 19 | 20 | setJSON(value: any) { 21 | this.json = value 22 | } 23 | 24 | addCss(file: string) { 25 | this.cssfile.push(file) 26 | } 27 | 28 | components: Record = {} 32 | 33 | addComponent(name: string, path: string) { 34 | this.components[name] = this.components[name] || { 35 | path, 36 | props: [] 37 | } 38 | } 39 | 40 | setComponentNative(name: string) { 41 | this.components[name].props.forEach(prop => { 42 | prop.setNative() 43 | }) 44 | } 45 | 46 | private callbacks: Array<() => void> = [] 47 | before(callback: () => void) { 48 | this.callbacks.push(callback) 49 | } 50 | 51 | private generator?: () => string 52 | setGenerator(generator: () => string) { 53 | this.generator = generator 54 | } 55 | 56 | generate() { 57 | this.identifier.restore() 58 | this.callbacks.forEach(fn => fn()) 59 | return this.generator?.() || '' 60 | } 61 | 62 | events: string[] = [] 63 | addEvent(name: string) { 64 | this.events.push(name) 65 | } 66 | 67 | mapScope = new MapScope() 68 | identifier = new DependencyIdentifier(this.mapScope) 69 | 70 | enterMap(path: NodePath, scope: string[]) { 71 | this.mapScope.enter(path, scope) 72 | } 73 | 74 | exitMap() { 75 | this.mapScope.exit() 76 | } 77 | 78 | genMap(path: NodePath) { 79 | return this.identifier.map(path) 80 | } 81 | 82 | genProp(path: NodePath, component?: string) { 83 | path.skip() 84 | const prop = this.identifier.prop(path) 85 | if (component) { 86 | this.components[component].props.push(prop) 87 | } 88 | } 89 | 90 | genEvent(path: NodePath) { 91 | path.skip() 92 | const { scope, name } = this.identifier.event(path) 93 | this.events.push(name) 94 | return { scope, name } 95 | } 96 | 97 | 98 | warning: Error[] = [] 99 | 100 | addWarning(warn: Error) { 101 | this.warning.push(warn) 102 | } 103 | 104 | destroy() { 105 | this.mapScope.destroy() 106 | this.identifier.destroy() 107 | this.json = null! 108 | this.events = null! 109 | this.callbacks = null! 110 | this.generator = null! 111 | this.components = null! 112 | this.warning = null! 113 | this.cssfile = null! 114 | } 115 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/state/map-scope/index.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from '@babel/traverse' 2 | import * as t from '@babel/types' 3 | 4 | export default class MapScope { 5 | private data: [string, string, string[]][] = [] 6 | private dict: Record = {} 7 | private push(item: string, index: string, parent: string[]) { 8 | this.data.push([item, index, parent]) 9 | this.update() 10 | } 11 | enter(path: NodePath, parent: string[]) { 12 | const arrowFn = path.get('arguments')[0] 13 | if (!arrowFn.isArrowFunctionExpression()) { 14 | throw path.buildCodeFrameError('Map only support ArrowFunctionExpression') 15 | } 16 | const params = arrowFn.node.params 17 | let item = params[0] 18 | let index = params[1] 19 | if ((item && !t.isIdentifier(item)) || (index && !t.isIdentifier(index))) { 20 | throw path.buildCodeFrameError('Map params only support Identifier') 21 | } 22 | if (!item) { 23 | item = path.scope.generateUidIdentifier('t') 24 | params.push(item) 25 | } 26 | if (!index) { 27 | index = path.scope.generateUidIdentifier('i') 28 | params.push(index) 29 | } else { 30 | const name = index.name 31 | // 重复的index重命名 32 | if (this.has(name)) { 33 | arrowFn.scope.rename(name) 34 | } 35 | } 36 | this.push(item.name, index.name, parent) 37 | } 38 | exit() { 39 | this.data.pop() 40 | this.update() 41 | } 42 | private has(id: string) { 43 | return this.getIndex(id) !== undefined 44 | } 45 | private getIndex(id: string): string[] | undefined { 46 | return this.dict[id] 47 | } 48 | private update() { 49 | const dict: Record = {} 50 | this.data.forEach(([item, index, parent]) => { 51 | dict[item] = dict[index] = [index].concat(parent) 52 | }) 53 | this.dict = dict 54 | } 55 | 56 | getScope(path: NodePath) { 57 | const result: string[] = [] 58 | if (this.data.length > 0) { 59 | const indexs = new Set() 60 | path.traverse({ 61 | Identifier: item => { 62 | if (t.isReferenced(item.node, item.parent)) { 63 | const name = item.node.name 64 | if (item.scope.getBinding(name) === path.parentPath!.scope.getBinding(name)) { 65 | this.getIndex(name)?.forEach(index => { 66 | indexs.add(index) 67 | }) 68 | } 69 | } 70 | } 71 | }) 72 | // traverse 不会遍历当前元素 73 | if (path.isIdentifier()) { 74 | this.getIndex(path.node.name)?.forEach(index => { 75 | indexs.add(index) 76 | }) 77 | } 78 | result.push(...indexs) 79 | indexs.clear() 80 | } 81 | return result 82 | } 83 | destroy() { 84 | this.data = null! 85 | this.dict = null! 86 | } 87 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/transform/add-ready/index.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from "@babel/traverse" 2 | import * as t from '@babel/types' 3 | 4 | // 通过给顶层代码添加条件表达式保证第一个元素拥有wx:if="{{ p0 }}"作为初始化状态 5 | export default function addReady(path: NodePath) { 6 | if (path.isLogicalExpression()) { 7 | // a &&
-> 不变 8 | // a ||
-> (true && !a) &&
9 | if (path.node.operator === '||') { 10 | path.replaceWith( 11 | t.logicalExpression('&&', t.logicalExpression('&&', t.booleanLiteral(true), 12 | t.unaryExpression('!', path.node.left)), path.node.right) 13 | ) 14 | } 15 | } else if (path.isConditionalExpression()) { 16 | // a ?
:
-> 不变 17 | } else { 18 | path.replaceWith( 19 | t.logicalExpression('&&', t.booleanLiteral(true), path.node) 20 | ) 21 | } 22 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/transform/index.ts: -------------------------------------------------------------------------------- 1 | import * as t from '@babel/types' 2 | import * as parser from '@babel/parser' 3 | import traverse, { NodePath } from '@babel/traverse' 4 | import generate from '@babel/generator' 5 | import getJSON from './json' 6 | import State from '../state' 7 | import transformRender from './render' 8 | import getProperties from './properties' 9 | import getWXML from './wxml' 10 | import addReady from './add-ready' 11 | import genData from './gen-data' 12 | 13 | export default function transform(source: string, state: State) { 14 | const file = parser.parse(source, { 15 | plugins: ['typescript', 'jsx', 'classProperties', 'decorators-legacy'], 16 | sourceType: 'module' 17 | }) 18 | traverse(file, { 19 | ImportDeclaration: { 20 | enter: path => { 21 | if (path.node.specifiers.length === 0) { 22 | if (/\.(sass|scss|css|wxss)$/.test(path.node.source.value)) { 23 | state.addCss(path.node.source.value) 24 | path.remove() 25 | } 26 | } 27 | } 28 | }, 29 | ExportDefaultDeclaration: { 30 | enter: path => { 31 | path.skip() 32 | const declaration = path.get('declaration') 33 | if (declaration.isClassDeclaration()) { 34 | state.setJSON(getJSON(declaration) || {}) 35 | 36 | const render = declaration.get('body.body').find(item => { 37 | if (item.isClassMethod()) { 38 | const key = item.get('key') 39 | if (key.isIdentifier()) { 40 | return key.node.name === 'render' 41 | } 42 | } 43 | return false 44 | }) as NodePath | undefined 45 | 46 | if (render) { 47 | const argument = (render.get('body.body').find(item => { 48 | return item.isReturnStatement() 49 | }) as NodePath | undefined)?.get('argument') 50 | if (argument?.isExpression()) { 51 | addReady(argument) 52 | genData(argument, state) 53 | state.setWXML( 54 | generate(getWXML(argument), { comments: false }).code 55 | ) 56 | } 57 | state.before(() => { 58 | transformRender(render) 59 | }) 60 | } 61 | 62 | /** 63 | * export default class -> (class).create({ 64 | * events: [], 65 | * properties: {} 66 | * }) 67 | **/ 68 | path.replaceWith( 69 | t.expressionStatement( 70 | t.callExpression( 71 | t.memberExpression( 72 | t.toExpression( 73 | declaration.node 74 | ), 75 | t.identifier('create') 76 | ), 77 | [ 78 | t.objectExpression([ 79 | t.objectProperty(t.identifier('events'), t.valueToNode(state.events)), 80 | t.objectProperty(t.identifier('properties'), t.objectExpression( 81 | getProperties(declaration) 82 | )) 83 | ]) 84 | ] 85 | ) 86 | ) 87 | ) 88 | } 89 | } 90 | } 91 | }) 92 | state.setGenerator(() => { 93 | return generate(file, { comments: false }).code 94 | }) 95 | } 96 | -------------------------------------------------------------------------------- /src/compiler/module/loader/transform/json/index.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from "@babel/traverse" 2 | import * as t from '@babel/types' 3 | import generate from '@babel/generator' 4 | 5 | export default function getJSON(path: NodePath) { 6 | const json = path.get('body.body').find(item => { 7 | if (item.isClassProperty()) { 8 | const key = item.get('key') 9 | if (key.isIdentifier()) { 10 | return key.node.name === '$json' 11 | } 12 | } 13 | return false 14 | }) as NodePath | undefined 15 | 16 | if (json) { 17 | const node = json.get('value').node 18 | if (node) { 19 | return eval(`(${generate(node, { comments: false }).code})`) 20 | } 21 | json.remove() 22 | } 23 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/transform/properties/index.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from "@babel/traverse" 2 | import * as t from '@babel/types' 3 | 4 | export default function getProperties(path: NodePath) { 5 | const declaration = path.node 6 | const result: t.ObjectProperty[] = [] 7 | if (t.isTSTypeParameterInstantiation(declaration.superTypeParameters)) { 8 | const objectType = declaration.superTypeParameters.params[0] 9 | if (t.isTSTypeLiteral(objectType)) { 10 | objectType.members.forEach(property => { 11 | if (t.isTSMethodSignature(property)) { 12 | if (t.isIdentifier(property.key)) { 13 | result.push( 14 | t.objectProperty( 15 | property.key, 16 | t.identifier('null') 17 | ) 18 | ) 19 | } 20 | } else if (t.isTSPropertySignature(property) && property.typeAnnotation) { 21 | if (t.isIdentifier(property.key)) { 22 | const type = property.typeAnnotation.typeAnnotation 23 | result.push( 24 | t.objectProperty( 25 | property.key, 26 | t.isTSStringKeyword(type) ? 27 | t.identifier('String') : 28 | t.isTSNumberKeyword(type) ? 29 | t.identifier('Number') : 30 | t.isTSBooleanKeyword(type) ? 31 | t.identifier('Boolean') : 32 | t.identifier('null') 33 | ) 34 | ) 35 | } 36 | } else { 37 | // `unknown component params type ${property.type}` 38 | } 39 | }) 40 | } 41 | } 42 | return result 43 | } -------------------------------------------------------------------------------- /src/compiler/module/loader/transform/render/index.ts: -------------------------------------------------------------------------------- 1 | import { NodePath } from "@babel/traverse" 2 | import * as t from '@babel/types' 3 | import { fnName } from "../../state/identifier/util" 4 | 5 | export default function transformEffect(render: NodePath) { 6 | render.node.params = renderParams 7 | render.traverse({ 8 | JSXElement: { 9 | exit: path => { 10 | const children = path.node.children.reduce((res, item) => { 11 | if (t.isJSXExpressionContainer(item) && !t.isJSXEmptyExpression(item.expression)) { 12 | res.push(item.expression) 13 | } else if (t.isArrayExpression(item)) { 14 | (item as t.ArrayExpression).elements.forEach(item => { 15 | if (t.isExpression(item)) { 16 | res.push(item) 17 | } 18 | }) 19 | } 20 | return res 21 | }, [] as t.Expression[]) 22 | 23 | const attrs = path.node.openingElement.attributes 24 | .reduce((res, item) => { 25 | if (t.isJSXAttribute(item) && t.isJSXExpressionContainer(item.value) && !t.isJSXEmptyExpression(item.value.expression)) { 26 | if (t.isJSXNamespacedName(item.name) || (t.isJSXIdentifier(item.name) && !/^data-/.test(item.name.name))) { 27 | res.push(item.value.expression) 28 | } 29 | } 30 | return res 31 | }, [] as t.Expression[]) 32 | 33 | if (children.length > 0 || attrs.length > 0) { 34 | path.replaceWith(t.arrayExpression(children.concat(attrs))) 35 | } else { 36 | if (path.parentPath.isConditionalExpression()) { 37 | path.replaceWith(t.nullLiteral()) 38 | } else { 39 | path.remove() 40 | } 41 | } 42 | } 43 | } 44 | }) 45 | } 46 | 47 | 48 | 49 | const typeAnnotation = t.tsTypeAnnotation( 50 | t.tsFunctionType( 51 | t.tsTypeParameterDeclaration([ 52 | t.tsTypeParameter(null, null, 'T') 53 | ]), 54 | [ 55 | addTsTypeAnnotation( 56 | t.identifier('a'), 57 | t.tsTypeAnnotation( 58 | t.tsTypeReference( 59 | t.identifier('T') 60 | ) 61 | ) 62 | ), 63 | addTsTypeAnnotation( 64 | t.restElement( 65 | t.identifier('args') 66 | ), 67 | t.tsTypeAnnotation(t.tsAnyKeyword()) 68 | ) 69 | ], 70 | t.tsTypeAnnotation( 71 | t.tsTypeReference( 72 | t.identifier('T') 73 | ) 74 | ) 75 | ) 76 | ) 77 | 78 | 79 | const renderParams = [ 80 | addTsTypeAnnotation(t.identifier(fnName.prop), typeAnnotation), 81 | addTsTypeAnnotation(t.identifier(fnName.event), typeAnnotation) 82 | ] 83 | 84 | function addTsTypeAnnotation(expression: T, type: t.TSTypeAnnotation): T { 85 | // @ts-ignore 86 | expression.typeAnnotation = type 87 | return expression 88 | } 89 | 90 | -------------------------------------------------------------------------------- /src/compiler/ts-transformer/fix-vue3-this/index.ts: -------------------------------------------------------------------------------- 1 | import ts from 'typescript' 2 | import FixThisState from './state' 3 | import { traverse, addStatement } from '../util' 4 | 5 | const fixVue3This: ts.TransformerFactory = (context) => { 6 | return sourceFile => { 7 | if (sourceFile.languageVariant !== ts.LanguageVariant.Standard || sourceFile.isDeclarationFile) { 8 | return sourceFile 9 | } 10 | const state = new FixThisState() 11 | sourceFile = ts.visitEachChild(sourceFile, node => { 12 | if (node.kind === ts.SyntaxKind.ClassDeclaration) { 13 | return ts.visitEachChild(node, node => { 14 | if (ts.isConstructorDeclaration(node) || ts.isPropertyDeclaration(node)) { 15 | return traverse(node, { 16 | enter: node => { 17 | if (node.kind === ts.SyntaxKind.ArrowFunction) { 18 | state.enterArrow() 19 | } else if (node.kind === ts.SyntaxKind.FunctionExpression) { 20 | return node 21 | } else if (state.isInArrow()) { 22 | state.active(node) 23 | if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.FirstAssignment) { 24 | state.add(node.left) 25 | } 26 | else if (ts.isCallExpression(node)) { 27 | state.add(node.expression) 28 | } 29 | else if (state.isActived() && ts.isPropertyAccessExpression(node) && node.expression.kind === ts.SyntaxKind.ThisKeyword) { 30 | return context.factory.updatePropertyAccessExpression(node, context.factory.createCallExpression(state.identifier, [], [node.expression as ts.ThisExpression]), node.name) 31 | } 32 | } 33 | }, 34 | exit: node => { 35 | if (node.kind === ts.SyntaxKind.ArrowFunction) { 36 | state.leaveArrow() 37 | } else { 38 | state.leave(node) 39 | } 40 | } 41 | }, context) 42 | } 43 | return node 44 | }, context) 45 | } 46 | return node 47 | }, context) 48 | if (state.isChanged()) { 49 | return addStatement(sourceFile, 50 | ts.factory.createVariableStatement(undefined, 51 | ts.factory.createVariableDeclarationList([ 52 | ts.factory.createVariableDeclaration( 53 | state.identifier, 54 | undefined, 55 | undefined, 56 | ts.factory.createAsExpression( 57 | ts.factory.createPropertyAccessExpression( 58 | ts.factory.createCallExpression( 59 | ts.factory.createIdentifier('require'), 60 | undefined, 61 | [ts.factory.createStringLiteral('march-mp')] 62 | ), 63 | ts.factory.createIdentifier('reactive') 64 | ), 65 | ts.factory.createFunctionTypeNode([ 66 | ts.factory.createTypeParameterDeclaration(undefined, 'T') 67 | ], [ 68 | ts.factory.createParameterDeclaration(undefined, undefined, 'data', undefined, ts.factory.createTypeReferenceNode("T")) 69 | ], ts.factory.createTypeReferenceNode("T")) 70 | ) 71 | ) 72 | ], ts.NodeFlags.Const) 73 | ) 74 | ) 75 | } 76 | return sourceFile 77 | } 78 | } 79 | 80 | export default fixVue3This -------------------------------------------------------------------------------- /src/compiler/ts-transformer/fix-vue3-this/state.ts: -------------------------------------------------------------------------------- 1 | import ts, { EmitHint } from 'typescript' 2 | import { toCode } from '../util' 3 | 4 | export default class FixThisState { 5 | private _identifier?: ts.Identifier 6 | get identifier() { 7 | if (this._identifier) { 8 | return this._identifier 9 | } else { 10 | return this._identifier = ts.factory.createUniqueName('reactive') 11 | } 12 | } 13 | isChanged() { 14 | return this._identifier !== undefined 15 | } 16 | 17 | private arrowCount = 0 18 | 19 | isInArrow() { 20 | return this.arrowCount > 0 21 | } 22 | enterArrow() { 23 | this.arrowCount++ 24 | } 25 | leaveArrow() { 26 | this.arrowCount-- 27 | } 28 | 29 | private data: { 30 | node: ts.Node 31 | status: 0 | 1 32 | }[] = [] 33 | 34 | add(node: ts.Node) { 35 | this.data.unshift({ 36 | node, status: 0 37 | }) 38 | } 39 | 40 | private getLast(): { node: ts.Node, status: 0 | 1 } | undefined { 41 | return this.data[0] 42 | } 43 | 44 | private removeLast() { 45 | this.data.splice(0, 1) 46 | } 47 | 48 | isActived() { 49 | return this.getLast()?.status === 1 50 | } 51 | 52 | active(node: ts.Node) { 53 | const item = this.getLast() 54 | if (item?.node === node) { 55 | // console.log('actived', toCode(node)) 56 | item.status = 1 57 | } 58 | } 59 | 60 | leave(node: ts.Node) { 61 | if (this.getLast()?.node === node) { 62 | this.removeLast() 63 | } 64 | } 65 | 66 | log() { 67 | console.log('------------') 68 | this.data.forEach(item => { 69 | console.log(toCode(item.node)) 70 | }) 71 | console.log('------------') 72 | } 73 | } -------------------------------------------------------------------------------- /src/compiler/ts-transformer/util.ts: -------------------------------------------------------------------------------- 1 | import ts, { EmitHint } from 'typescript' 2 | 3 | export function traverse(node: ts.Node, visitor: { 4 | enter?: (node: ts.Node) => ts.Node | void 5 | exit?: (node: ts.Node) => void 6 | }, context: ts.TransformationContext): ts.Node { 7 | let result = visitor.enter?.(node) 8 | if (!result) { 9 | result = ts.visitEachChild(node, node => traverse(node, visitor, context), context) 10 | } 11 | visitor.exit?.(result) 12 | return result 13 | } 14 | 15 | export function isPropertyAccessExpression(node: ts.Node): node is ts.PropertyAccessExpression { 16 | return node.kind === ts.SyntaxKind.PropertyAccessExpression 17 | } 18 | 19 | export function isBinaryExpression(node: ts.Node): node is ts.BinaryExpression { 20 | return node.kind === ts.SyntaxKind.BinaryExpression 21 | } 22 | 23 | export function isCallExpression(node: ts.Node): node is ts.CallExpression { 24 | return node.kind === ts.SyntaxKind.CallExpression 25 | } 26 | 27 | export function isImportDeclaration(node: ts.Node): node is ts.ImportDeclaration { 28 | return node.kind === ts.SyntaxKind.ImportDeclaration 29 | } 30 | 31 | export function isStringLiteral(node: ts.Node): node is ts.StringLiteral { 32 | return node.kind === ts.SyntaxKind.StringLiteral 33 | } 34 | 35 | export function addStatement(sourceFile: ts.SourceFile, statement: ts.Statement) { 36 | return ts.factory.updateSourceFile( 37 | sourceFile, 38 | [ 39 | statement, 40 | ...sourceFile.statements 41 | ], 42 | sourceFile.isDeclarationFile, 43 | sourceFile.referencedFiles, 44 | sourceFile.typeReferenceDirectives, 45 | sourceFile.hasNoDefaultLib, 46 | sourceFile.libReferenceDirectives 47 | ) 48 | } 49 | 50 | export function toCode(node: ts.Node) { 51 | const printer = ts.createPrinter() 52 | return printer.printNode(EmitHint.Expression, node, ts.createSourceFile('a.ts', '', ts.ScriptTarget.Latest)) 53 | } -------------------------------------------------------------------------------- /src/compiler/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "allowSyntheticDefaultImports": true, 5 | "moduleResolution": "node", 6 | "module": "CommonJS", 7 | "target": "ES2016", 8 | "outDir": "../../dist/compiler", 9 | "declaration": true, 10 | "downlevelIteration": true, 11 | "esModuleInterop": true 12 | }, 13 | "include": [ 14 | "./**/*" 15 | ] 16 | } -------------------------------------------------------------------------------- /src/compiler/value-loader/index.ts: -------------------------------------------------------------------------------- 1 | export default function (source: string) { 2 | return `${JSON.stringify(source)}` 3 | } -------------------------------------------------------------------------------- /src/runtime/base/index.ts: -------------------------------------------------------------------------------- 1 | 2 | import Reactivity from '../reactivity' 3 | import RuntimeStore from './store' 4 | 5 | type pageInstance = WechatMiniprogram.Page.Instance<{}, {}> 6 | type componentInstance = WechatMiniprogram.Component.Instance<{}, {}, {}> 7 | type wxInstance = pageInstance | componentInstance 8 | 9 | export default class MPBase { 10 | static debug = false 11 | static dataMap = new WeakMap() 12 | 13 | static init(instance: wxInstance, data: T, callback?: () => void): T { 14 | Object.defineProperty(data, "$this", { 15 | enumerable: false, 16 | configurable: false, 17 | get() { 18 | return Reactivity.markRaw(instance) 19 | } 20 | }) 21 | data.$onReady(() => { 22 | callback?.() 23 | }) 24 | const proxyData = Reactivity.reactive(data) as T 25 | const stop = Reactivity.effect((pause, resume) => { 26 | if (!data.$store) { 27 | return 28 | } 29 | const timeId = instance.is + Math.random() 30 | if (this.debug) { 31 | console.time(timeId) 32 | } 33 | data.$store.start() 34 | proxyData.render( 35 | // prop 构建 36 | (value, key, native) => { 37 | data.$store.addProp(key, Reactivity.toRaw(value), native) 38 | return value 39 | }, 40 | // event 构建 41 | (fn, key) => { 42 | data.$store.addEvent(Array.isArray(key) ? key.join('.') : key, fn) 43 | return fn 44 | } 45 | ) 46 | pause() 47 | try { 48 | const state = data.$store.end() 49 | if (this.debug) { 50 | console.timeEnd(timeId) 51 | } 52 | if (state) { 53 | if (this.debug) { 54 | console.log(instance.is, state) 55 | } 56 | instance.setData(state, () => { 57 | if (!data.$ready) { 58 | data.$setReady() 59 | } 60 | }) 61 | } 62 | } catch (e) { 63 | throw e 64 | } finally { 65 | resume() 66 | } 67 | }) 68 | data.$destoryCallback.push(() => { 69 | stop() 70 | }) 71 | return this.bindData(instance, proxyData) 72 | } 73 | static bindData(instance: wxInstance, data: T): T { 74 | this.dataMap.set(instance, data) 75 | return data 76 | } 77 | static getData(instance: wxInstance) { 78 | return this.dataMap.get(instance)! 79 | } 80 | static getRawData(instance: wxInstance) { 81 | return Reactivity.toRaw(this.getData(instance)) 82 | } 83 | static destory(instance: wxInstance) { 84 | this.getData(instance).$destory() 85 | this.dataMap.delete(instance) 86 | } 87 | static initEventsMethods(events: string[]) { 88 | const methods: Record void> = {} 89 | const self = this 90 | events.forEach((name) => { 91 | methods[name] = function (this: wxInstance, event: Event.Base, void>) { 92 | const data = self.getData(this) 93 | const dataset = event.currentTarget.dataset 94 | const key = dataset[name] !== undefined ? [name, dataset[name]].join('.') : name 95 | data.$store.runEvent(key, event.detail, event) 96 | } 97 | }) 98 | return methods 99 | } 100 | protected $store = new RuntimeStore 101 | protected $ready: boolean = false 102 | private $readyCallback: Array<() => void> = [] 103 | protected $onReady(callback: () => void) { 104 | if (this.$ready) { 105 | callback() 106 | } else { 107 | this.$readyCallback.push(callback) 108 | } 109 | } 110 | private $setReady() { 111 | this.$ready = true 112 | this.$readyCallback.forEach(cb => cb()) 113 | this.$readyCallback = [] 114 | } 115 | 116 | protected $destoryCallback: Array<() => void> = [] 117 | protected $destory() { 118 | this.$destoryCallback.forEach(fn => fn()) 119 | this.$destoryCallback = [] 120 | this.$readyCallback = [] 121 | this.$store.destroy() 122 | this.$store = null! 123 | } 124 | 125 | /**编译后覆盖 render函数 */ 126 | protected render(genProp: (value: T, key: Array | string, native?: boolean) => T, genEvent: (value: T, key: Array | string) => T): any { } 127 | } -------------------------------------------------------------------------------- /src/runtime/base/store/diff/index.ts: -------------------------------------------------------------------------------- 1 | import DiffState from "./state" 2 | 3 | export default class Diff { 4 | private data: Record = {} 5 | private state = new DiffState 6 | 7 | reset() { 8 | this.state.reset() 9 | } 10 | 11 | get() { 12 | const data = this.state.get() 13 | if (data.length > 0) { 14 | const result: Record = {} 15 | data.forEach(item => { 16 | result[item.name] = this.getValue(item.path) 17 | }) 18 | return result 19 | } 20 | } 21 | 22 | add(key: string | string[], value: any, native?: boolean) { 23 | const oldValue = this.getValue(key) 24 | if (native) { 25 | if (oldValue !== value) { 26 | this.setValue(key, value) 27 | this.state.add(key) 28 | } 29 | } else { 30 | const newValue = this.deep(oldValue, value, key) 31 | if (newValue !== oldValue) { 32 | this.setValue(key, newValue) 33 | } 34 | } 35 | } 36 | 37 | destroy() { 38 | this.state.destroy() 39 | this.data = null! 40 | } 41 | 42 | private getValue(key: string | string[]) { 43 | return Array.isArray(key) ? get(this.data, key) : this.data[key] 44 | } 45 | 46 | private setValue(key: string | string[], value: any) { 47 | if (Array.isArray(key)) { 48 | set(this.data, key, value) 49 | } else { 50 | this.data[key] = value 51 | } 52 | } 53 | 54 | private deep(value: any, newValue: any, keys?: string | string[]): any { 55 | if (Array.isArray(newValue)) { 56 | if (keys !== undefined && (!value || value.length !== newValue.length)) { 57 | this.state.add(keys) 58 | keys = undefined 59 | } 60 | return newValue.map((item, index) => this.deep(value ? value[index] : undefined, item, keys !== undefined ? concat(keys, index as unknown as string) : undefined)) 61 | } else if (isRecord(newValue)) { 62 | const result: any = {} 63 | for (const key in newValue) { 64 | result[key] = this.deep(value ? value[key] : undefined, newValue[key], keys !== undefined ? concat(keys, key) : undefined) 65 | } 66 | return result 67 | } else { 68 | if (keys !== undefined && value !== newValue) { 69 | this.state.add(keys) 70 | } 71 | return newValue 72 | } 73 | } 74 | } 75 | 76 | function concat(keys: string | string[], key: string) { 77 | return ([] as string[]).concat(keys).concat(key) 78 | } 79 | 80 | function get(obj: any, keys: string[]) { 81 | for (const key of keys) { 82 | obj = obj[key] 83 | if (obj === undefined) { 84 | return obj 85 | } 86 | } 87 | return obj 88 | } 89 | 90 | function set(obj: any, keys: string[], value: any) { 91 | keys.slice(0, -1).forEach(key => { 92 | if (!obj[key]) { 93 | obj[key] = [] 94 | } 95 | obj = obj[key] 96 | }) 97 | obj[keys.slice(-1)[0]] = value 98 | } 99 | 100 | 101 | function isObject(data: unknown): data is Record { 102 | return typeof data === 'object' && data !== null 103 | } 104 | 105 | function isRecord(data: unknown): data is Record { 106 | return Object.prototype.toString.call(data) === '[object Object]' 107 | } -------------------------------------------------------------------------------- /src/runtime/base/store/diff/state/index.ts: -------------------------------------------------------------------------------- 1 | type result = { 2 | dict: Record | null 3 | children: data[] | null 4 | } 5 | 6 | type data = { 7 | name: string 8 | path: string 9 | length: number 10 | } & result 11 | 12 | 13 | export default class DiffState { 14 | data: data[] = [] 15 | dict: Record = {} 16 | 17 | add(keys: string | string[]) { 18 | const children = Array.isArray(keys) ? [...keys] : [keys] 19 | let result: result = { 20 | dict: this.dict, 21 | children: this.data 22 | } 23 | while (result.dict && result.children && children.length > 0) { 24 | const key = children.splice(0, 1)[0] 25 | const hasNext = children.length > 0 26 | if (!result.dict[key]) { 27 | const data = { 28 | name: typeof key === 'number' ? `[${key}]` : `.${key}`, 29 | path: key, 30 | dict: hasNext ? {} : null, 31 | children: hasNext ? [] : null, 32 | get length() { 33 | if (this.children) { 34 | return this.children.reduce((s, i) => s + i.length, 0) 35 | } 36 | return 1 37 | } 38 | } as data 39 | result.dict[key] = data 40 | result.children.push(data) 41 | } 42 | const data = result.dict[key] 43 | if (data.length > 20) { 44 | data.children = data.dict = null 45 | } 46 | result.dict = data.dict 47 | result.children = data.children 48 | } 49 | } 50 | 51 | get() { 52 | const result: { 53 | name: string 54 | path: string[] 55 | }[] = [] 56 | const forEach = (data: data, name: string, path: string[]) => { 57 | name = name + data.name 58 | path = path.concat(data.path) 59 | if (data.children) { 60 | data.children.forEach(item => { 61 | forEach(item, name, path) 62 | }) 63 | } else { 64 | result.push({ 65 | name, 66 | path 67 | }) 68 | } 69 | } 70 | this.data.forEach(item => { 71 | forEach(item, '', []) 72 | }) 73 | return result 74 | } 75 | 76 | reset() { 77 | this.data = [] 78 | this.dict = {} 79 | } 80 | 81 | destroy() { 82 | this.data = null! 83 | this.dict = null! 84 | } 85 | } -------------------------------------------------------------------------------- /src/runtime/base/store/index.ts: -------------------------------------------------------------------------------- 1 | import { buildMPData } from "../../utils" 2 | import Diff from './diff' 3 | 4 | export default class RuntimeStore { 5 | private diff = new Diff 6 | 7 | addProp(key: string | string[], value: any, native?: boolean) { 8 | if (value === undefined) { 9 | value = null 10 | } else if (native) { 11 | if (isObject(value)) { 12 | value = this.proxyProp(value, key) 13 | } else if (typeof value === 'function') { 14 | value = this.proxyFn(value, key) 15 | } 16 | } 17 | this.diff.add(key, value, native) 18 | } 19 | 20 | start() { 21 | this.diff.reset() 22 | } 23 | 24 | end() { 25 | return this.diff.get() 26 | } 27 | 28 | private events: Record any> = {} 29 | 30 | addEvent(key: string, fn: any) { 31 | this.events[key] = fn 32 | } 33 | 34 | runEvent(key: string, arg: any, event: Event.Base, void>) { 35 | this.events[key].call(null, arg, event) 36 | } 37 | 38 | /**框架组件属性代理 */ 39 | private propRecord: Record = {} 40 | private propProxy: Record = {} 41 | private proxyProp(value: any, key: string | string[]) { 42 | const k = Array.isArray(key) ? key.join('_') : key 43 | if (this.propRecord[k] !== value) { 44 | this.propRecord[k] = value 45 | this.propProxy[k] = buildMPData(value) 46 | } 47 | return this.propProxy[k] 48 | } 49 | 50 | /**事件属性代理 */ 51 | private fnRecord: Record any> = {} 52 | private fnProxy: Record = {} 53 | private proxyFn(value: (...args: any[]) => any, key: string | string[]) { 54 | const k = Array.isArray(key) ? key.join('_') : key 55 | this.fnRecord[k] = value 56 | if (!this.fnProxy[k]) { 57 | this.fnProxy[k] = buildMPData((...args: any[]) => this.fnRecord[k].apply(null, args)) 58 | } 59 | return this.fnProxy[k] 60 | } 61 | 62 | destroy() { 63 | this.diff.destroy() 64 | this.events = null! 65 | this.fnRecord = null! 66 | this.fnProxy = null! 67 | this.propRecord = null! 68 | this.propRecord = null! 69 | } 70 | } 71 | 72 | function isObject(data: unknown): data is object { 73 | return typeof data === 'object' && data !== null 74 | } -------------------------------------------------------------------------------- /src/runtime/component/index.ts: -------------------------------------------------------------------------------- 1 | import MPBase from "../base" 2 | import Reactivity from "../reactivity" 3 | import { isMPDataReady, originMPData } from "../utils" 4 | 5 | type componentInstance = WechatMiniprogram.Component.Instance<{}, {}, {}> 6 | export default class MPComponent< 7 | /**组件需要传入参数 */ 8 | T extends object = {}, 9 | /**有默认值的组件参数名称, 默认值请申明在static propsDefault中*/ 10 | P extends keyof T = never 11 | > extends MPBase { 12 | 13 | /**组件数据监控 { 字段名称: 运行的组件方法名称 } */ 14 | static observers: Record = {}; 15 | 16 | /**组件参数默认值 */ 17 | static propsDefault: Record = {}; 18 | 19 | /**组件参数 编译后覆盖 */ 20 | static properties: Record = {}; 21 | 22 | static $options: any = {}; 23 | 24 | static create({ properties, events }: { 25 | properties: Record 26 | events: string[] 27 | }) { 28 | const methods = this.initEventsMethods(events) 29 | this.properties = properties 30 | // 将默认值赋值给properties 31 | for (const key in this.properties) { 32 | if (this.propsDefault[key] !== undefined) { 33 | this.properties[key] = { 34 | type: this.properties[key], 35 | value: this.propsDefault[key], 36 | } 37 | } 38 | } 39 | 40 | const observers: Record void> = {} 41 | // 映射定义的监控变量和触发函数 42 | for (const key in this.properties) { 43 | const obMethodName = this.observers[key] 44 | observers[key] = function (newData) { 45 | const data = Self.getData(this) as MPComponent 46 | const oldValue = data.$props[key] 47 | if (!isMPDataReady(newData)) { 48 | console.log('MPData is not Ready', newData) 49 | return 50 | } 51 | const newValue = originMPData(newData, this.is + '->observers->' + key) 52 | if (oldValue === newValue) { 53 | return 54 | } 55 | Reactivity.set(data.$props, key, newValue) 56 | // data.$props[key] = newValue 57 | if (obMethodName) { 58 | // 运行监控数据映射的函数 59 | const method = (data)[obMethodName] 60 | if (method) { 61 | method.apply(data, [newValue, oldValue]) 62 | } else { 63 | console.error(`observer method ${obMethodName} is not exist`) 64 | } 65 | } 66 | } 67 | } 68 | 69 | const Self = this 70 | return Component({ 71 | options: { 72 | ...this.$options 73 | }, 74 | observers, 75 | properties: this.properties, 76 | lifetimes: { 77 | created() { 78 | const data = new Self() 79 | Self.bindData(this, data) 80 | data.created?.() 81 | }, 82 | attached() { 83 | const data = Self.init(this, Self.getData(this) as MPComponent, () => { 84 | data.attached?.() 85 | }) 86 | }, 87 | detached() { 88 | const data = Self.getData(this) as MPComponent 89 | data.detached?.() 90 | Self.destory(this) 91 | } 92 | }, 93 | methods: methods 94 | }) 95 | } 96 | protected created?(): void 97 | protected detached?(): void 98 | protected attached?(): void 99 | protected readonly $this!: WechatMiniprogram.Component.Instance<{}, {}, {}> 100 | readonly $props!: T & ([P] extends [never] ? {} : { [key in P]-?: T[P] }) 101 | 102 | constructor(args: Readonly = {} as T) { 103 | super() 104 | 105 | Object.defineProperty(this, '$props', { 106 | enumerable: false, 107 | writable: true, 108 | configurable: true, 109 | value: Reactivity.reactive({}) 110 | }) 111 | } 112 | 113 | } -------------------------------------------------------------------------------- /src/runtime/index.ts: -------------------------------------------------------------------------------- 1 | import MPComponent from "./component" 2 | import MPPage from "./page" 3 | import Reactivity from "./reactivity" 4 | 5 | const MarchMP = { 6 | Page: MPPage, 7 | Component: MPComponent, 8 | } 9 | 10 | namespace MarchMP { 11 | export type Page = MPPage 12 | export type Component = MPComponent 13 | } 14 | 15 | export function toRaw(data: T): T { 16 | return Reactivity.toRaw(data) 17 | } 18 | 19 | export function markRaw(data: T): T { 20 | return Reactivity.markRaw(data) 21 | } 22 | 23 | export function reactive(data: T): T { 24 | return Reactivity.reactive(data) 25 | } 26 | 27 | export { 28 | MPPage, 29 | MPComponent 30 | } 31 | 32 | export default MarchMP -------------------------------------------------------------------------------- /src/runtime/page/index.ts: -------------------------------------------------------------------------------- 1 | import MPBase from "../base" 2 | 3 | const readySymbol = Symbol() 4 | export default class MPPage extends MPBase { 5 | protected readonly $this!: WechatMiniprogram.Page.Instance<{}, {}> 6 | 7 | protected onLoad?(data: Record): void 8 | protected onShow?(): void 9 | protected onHide?(): void 10 | protected onUnload?(): void 11 | protected onReady?(): void 12 | 13 | static create({ events }: { 14 | events: string[] 15 | }) { 16 | const methods = this.initEventsMethods(events) 17 | const Self = this 18 | return Page({ 19 | onLoad(args: any) { 20 | const data = Self.init(this, new Self(), () => { 21 | data.onLoad?.(args) 22 | data.onShow?.() 23 | Reflect.set(this, readySymbol, true) 24 | }) 25 | }, 26 | onReady() { 27 | const data = Self.getData(this) as MPPage 28 | data.$onReady(() => { 29 | data.onReady?.() 30 | }) 31 | }, 32 | onShow() { 33 | if (Reflect.get(this, readySymbol)) { 34 | const data = Self.getData(this) as MPPage 35 | data.onShow?.() 36 | } 37 | }, 38 | onHide() { 39 | const data = Self.getData(this) as MPPage 40 | data.onHide?.() 41 | }, 42 | onUnload() { 43 | const data = Self.getData(this) as MPPage 44 | data.onUnload?.() 45 | Self.destory(this) 46 | }, 47 | ...methods 48 | }) 49 | } 50 | } -------------------------------------------------------------------------------- /src/runtime/reactivity/define/index.ts: -------------------------------------------------------------------------------- 1 | import Reactivity from ".." 2 | import { reactive, watchEffect, pushTarget, popTarget, toRaw, markRaw, set } from 'vue-reactivity' 3 | 4 | const DefineReactivity: Reactivity = { 5 | reactive(data: T): T { 6 | return reactive(data) as T 7 | }, 8 | effect(callback: (pause: () => void, resume: () => void) => void): () => void { 9 | return watchEffect(() => { 10 | callback(() => pushTarget(), () => popTarget()) 11 | }) 12 | }, 13 | toRaw(data: T): T { 14 | return toRaw(data) 15 | }, 16 | markRaw(data: T): T { 17 | return markRaw(data) as T 18 | }, 19 | set(data: T, key: K, value: T[K]): void { 20 | set(data, key as string, value) 21 | } 22 | } 23 | 24 | export default DefineReactivity -------------------------------------------------------------------------------- /src/runtime/reactivity/index.ts: -------------------------------------------------------------------------------- 1 | import DefineReactivity from "./define" 2 | import ProxyReactivity from "./proxy" 3 | 4 | interface Reactivity { 5 | reactive(data: T): T 6 | effect(callback: (pause: () => void, resume: () => void) => void): () => void 7 | toRaw(data: T): T 8 | markRaw(data: T): T 9 | set(data: T, key: K, value: T[K]): void 10 | } 11 | 12 | const proxy = ProxyReactivity 13 | const define = DefineReactivity 14 | 15 | let actived: Reactivity = ProxyReactivity 16 | 17 | const Reactivity = { 18 | use(type: 'proxy' | 'define') { 19 | actived = type === 'proxy' ? proxy : define 20 | }, 21 | reactive(data: T): T { 22 | return actived.reactive(data) 23 | }, 24 | effect(callback: (pause: () => void, resume: () => void) => void): () => void { 25 | return actived.effect(callback) 26 | }, 27 | toRaw(data: T): T { 28 | return actived.toRaw(data) 29 | }, 30 | markRaw(data: T): T { 31 | return actived.markRaw(data) 32 | }, 33 | set(data: T, key: K, value: T[K]): void { 34 | actived.set(data, key, value) 35 | } 36 | } 37 | 38 | export default Reactivity -------------------------------------------------------------------------------- /src/runtime/reactivity/proxy/index.ts: -------------------------------------------------------------------------------- 1 | import Reactivity from ".." 2 | import { reactive, effect, stop, pauseTracking, enableTracking, toRaw, markRaw } from '../../@vue_reactivity' 3 | 4 | const ProxyReactivity: Reactivity = { 5 | reactive(data: T): T { 6 | return reactive(data) as T 7 | }, 8 | effect(callback: (pause: () => void, resume: () => void) => void): () => void { 9 | const result = effect(() => { 10 | callback(() => pauseTracking(), () => enableTracking()) 11 | }) 12 | return () => { 13 | stop(result) 14 | } 15 | }, 16 | toRaw(data: T): T { 17 | return toRaw(data) 18 | }, 19 | markRaw(data: T): T { 20 | return markRaw(data) as T 21 | }, 22 | set(data: T, key: K, value: T[K]): void { 23 | data[key] = value 24 | } 25 | } 26 | 27 | export default ProxyReactivity -------------------------------------------------------------------------------- /src/runtime/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "allowSyntheticDefaultImports": true, 5 | "moduleResolution": "node", 6 | "module": "CommonJS", 7 | "target": "ES5", 8 | "outDir": "../../dist/runtime", 9 | "declaration": true, 10 | "downlevelIteration": true 11 | }, 12 | "include": [ 13 | "./**/*" 14 | ] 15 | } -------------------------------------------------------------------------------- /src/runtime/typings/component.config.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace Component { 2 | export namespace config { 3 | interface map { 4 | /** 中心经度 */ 5 | longitude: number 6 | 7 | /** 中心纬度 */ 8 | latitude: number 9 | 10 | /** 11 | * 缩放级别,取值范围为3-20 12 | * 默认值16 13 | */ 14 | scale?: number 15 | 16 | /** 显示带有方向的当前定位点 */ 17 | "show-location"?: boolean 18 | 19 | } 20 | export namespace map { 21 | export namespace events { 22 | export type bindcallouttap = (event: { markerId: number }) => void 23 | } 24 | interface marker { 25 | id?: number 26 | latitude: number 27 | longitude: number 28 | title?: string 29 | zIndex?: number 30 | iconPath: string 31 | rotate?: number 32 | alpha?: number 33 | width?: number | string 34 | height?: number | string 35 | anchor?: { x: number, y: number } 36 | callout?: { 37 | content?: string 38 | color?: string 39 | fontSize?: string 40 | borderRadius?: number 41 | borderWidth?: number 42 | borderColor?: string 43 | bgColor?: string 44 | padding?: number 45 | display?: 'BYCLICK' | 'ALWAYS' 46 | textAlign?: 'left' | 'right' | 'center' 47 | } 48 | } 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/runtime/typings/event.d.ts: -------------------------------------------------------------------------------- 1 | 2 | declare namespace Event { 3 | type Base = { 4 | type: string 5 | currentTarget: currentTarget 6 | detail: D 7 | } 8 | type currentTarget = { 9 | dataset: T 10 | } 11 | type Change = { 12 | type: 'change' 13 | currentTarget: currentTarget 14 | detail: D 15 | } 16 | type Input = { 17 | type: 'input' 18 | currentTarget: currentTarget 19 | detail: { 20 | value: string 21 | cursor: number 22 | keyCode: number 23 | } 24 | } 25 | type Tap = { 26 | type: 'tap' 27 | currentTarget: currentTarget 28 | } 29 | type SwitchChange = { 30 | currentTarget: currentTarget 31 | detail: { 32 | value: boolean 33 | } 34 | } 35 | type ColumnChange = { 36 | type: 'columnchange' 37 | currentTarget: currentTarget 38 | detail: { 39 | column: number 40 | value: number 41 | } 42 | } 43 | type ImageUpload = { currentTarget: currentTarget, type: 'update', detail: ({ type: 'add' } | { type: 'preview', index: number } | { type: 'remove', index: number }) & { from: 'imageupload' } } 44 | } -------------------------------------------------------------------------------- /src/runtime/typings/index.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | /// 4 | 5 | type PartialAll = { 6 | [P in keyof T]?: PartialAll 7 | } 8 | 9 | declare namespace WechatMiniprogram { 10 | namespace Component { 11 | interface InstanceMethods { 12 | setData(data: T & Partial & IAnyObject, callback?: () => void): void 13 | } 14 | } 15 | interface Wx { 16 | requestWithCookie: WechatMiniprogram.Wx['request'] 17 | uploadFileWithCookie: WechatMiniprogram.Wx['uploadFile'] 18 | test: any 19 | } 20 | } -------------------------------------------------------------------------------- /src/runtime/typings/types/index.d.ts: -------------------------------------------------------------------------------- 1 | /// -------------------------------------------------------------------------------- /src/runtime/typings/types/wx/index.d.ts: -------------------------------------------------------------------------------- 1 | /*! ***************************************************************************** 2 | Copyright (c) 2019 Tencent, Inc. All rights reserved. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | ***************************************************************************** */ 10 | 11 | /// 12 | /// 13 | /// 14 | /// 15 | /// 16 | /// 17 | 18 | declare namespace WechatMiniprogram { 19 | type IAnyObject = Record 20 | type Optional = F extends (arg: infer P) => infer R ? (arg?: P) => R : F 21 | type OptionalInterface = { [K in keyof T]: Optional } 22 | } 23 | 24 | 25 | /** 引入插件。返回插件通过 `main` 暴露的接口。 */ 26 | declare function requirePlugin( 27 | /** 需要引入的插件的 alias */ 28 | module: string 29 | ): any -------------------------------------------------------------------------------- /src/runtime/typings/types/wx/lib.wx.behavior.d.ts: -------------------------------------------------------------------------------- 1 | /*! ***************************************************************************** 2 | Copyright (c) 2019 Tencent, Inc. All rights reserved. 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | ***************************************************************************** */ 10 | 11 | declare namespace WechatMiniprogram { 12 | namespace Behavior { 13 | type Instance< 14 | TData extends DataOption, 15 | TProperty extends PropertyOption, 16 | TMethod extends MethodOption 17 | > = Component.Instance 18 | type TrivialInstance = Instance 19 | type TrivialOption = Options 20 | type Options< 21 | TData extends DataOption, 22 | TProperty extends PropertyOption, 23 | TMethod extends MethodOption 24 | > = Partial> & 25 | Partial> & 26 | Partial> & 27 | Partial & 28 | Partial & 29 | ThisType> 30 | interface Constructor { 31 | < 32 | TData extends DataOption, 33 | TProperty extends PropertyOption, 34 | TMethod extends MethodOption 35 | >( 36 | options: Options, 37 | ): string 38 | } 39 | 40 | type DataOption = Component.DataOption 41 | type PropertyOption = Component.PropertyOption 42 | type MethodOption = Component.MethodOption 43 | type Data = Component.Data 44 | type Property

= Component.Property

45 | type Method = Component.Method 46 | 47 | type DefinitionFilter = Component.DefinitionFilter 48 | type Lifetimes = Component.Lifetimes 49 | 50 | interface OtherOption { 51 | /** 类似于mixins和traits的组件间代码复用机制,参见 [behaviors](behaviors.md) */ 52 | behaviors: string[] 53 | /** 定义段过滤器,用于自定义组件扩展,参见 [自定义组件扩展](extend.md) 54 | * 55 | * 最低基础库: `2.2.3` */ 56 | definitionFilter?: DefinitionFilter 57 | } 58 | } 59 | } 60 | /** 注册一个 `behavior`,接受一个 `Object` 类型的参数。*/ 61 | declare const Behavior: WechatMiniprogram.Behavior.Constructor 62 | -------------------------------------------------------------------------------- /src/runtime/utils/index.ts: -------------------------------------------------------------------------------- 1 | const originKey = '__origin__fn' 2 | 3 | export function buildMPData(object: T) { 4 | const result = { 5 | [originKey]: () => object 6 | } 7 | return result 8 | } 9 | 10 | export function initMPData(object: T) { 11 | if (isObject(object)) { 12 | const fn = Reflect.get(object, originKey) 13 | if (!fn) { 14 | Reflect.set(object, originKey, () => object) 15 | return true 16 | } 17 | } 18 | return false 19 | } 20 | 21 | export function isMPDataReady(object: T) { 22 | if (isObject(object)) { 23 | const originFn = Reflect.get(object, originKey) 24 | if (originFn) { 25 | return true 26 | } else { 27 | return false 28 | } 29 | } 30 | return true 31 | } 32 | 33 | export function originMPData(object: T, info?: string, other?: any) { 34 | if (isObject(object)) { 35 | const originFn = Reflect.get(object, originKey) as () => T 36 | if (originFn) { 37 | return originFn() 38 | } else { 39 | console.warn('----unset origin data----', info, object, other) 40 | } 41 | } 42 | return object 43 | } 44 | 45 | function isObject(data: unknown): data is object { 46 | return typeof data === 'object' && data !== null && !Array.isArray(data) 47 | } --------------------------------------------------------------------------------