Skip to content

Commit

Permalink
patch latest WCC TypeScript changes
Browse files Browse the repository at this point in the history
  • Loading branch information
thescientist13 committed Jun 18, 2024
1 parent 335900f commit 4ae525d
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 211 deletions.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@
"stylelint-config-standard": "^20.0.0"
},
"dependencies": {
"acorn-typescript": "^1.4.13",
"sucrase": "^3.35.0"
}
}
276 changes: 71 additions & 205 deletions patches/wc-compiler+0.13.0.patch
Original file line number Diff line number Diff line change
@@ -1,265 +1,131 @@
diff --git a/node_modules/wc-compiler/src/jsx-loader.js b/node_modules/wc-compiler/src/jsx-loader.js
index 53297cc..d8fdb6f 100644
index 53297cc..843e3e6 100644
--- a/node_modules/wc-compiler/src/jsx-loader.js
+++ b/node_modules/wc-compiler/src/jsx-loader.js
@@ -8,9 +8,29 @@ import jsx from '@projectevergreen/acorn-jsx-esm';
@@ -8,6 +8,7 @@ import jsx from '@projectevergreen/acorn-jsx-esm';
import { parse, parseFragment, serialize } from 'parse5';
// Need an acorn plugin for now - https://github.com/ProjectEvergreen/greenwood/issues/1218
import { importAttributes } from 'acorn-import-attributes';
+// import tsc from 'typescript';
+import tsPlugin from 'acorn-typescript';
+import { transform } from 'sucrase';

const jsxRegex = /\.(jsx)$/;

+const tsConfig = {
+ compilerOptions: {
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "target": "ESNext",
+ "isolatedModules": true,
+ "esModuleInterop": true,
+ "noEmit": true,
+ "allowImportingTsExtensions": true,
+ "outDir": "dist",
+ "lib": [ "esnext" ],
+ "types": [ "node" ],
+ "baseUrl": "./",
+ }
+}
+
// TODO same hack as definitions
// https://github.com/ProjectEvergreen/wcc/discussions/74
let string;
@@ -35,7 +55,8 @@ export function getParser(moduleURL) {
config: {
// https://github.com/acornjs/acorn/issues/829#issuecomment-1172586171
...walk.base,
- JSXElement: () => {}
+ JSXElement: () => {},
+ // TSInterfaceDeclaration: () => {}
}
};
}
@@ -231,16 +252,22 @@ function findThisReferences(context, statement) {
}
@@ -97,7 +98,7 @@ function parseJsxElement(element, moduleContents = '') {
if (expression.property.type === 'Identifier') {
// we leave markers for `this` so we can replace it later while also NOT accidentally replacing
// legitimate uses of this that might be actual content / markup of the custom element
- string += ` ${name}="__this__.${expression.property.name}()"`;
+ string += ` ${name}='__this__.${expression.property.name}()'`;
}
}
}
@@ -109,7 +110,7 @@ function parseJsxElement(element, moduleContents = '') {
if (expression.type === 'ArrowFunctionExpression') {
if (expression.body && expression.body.type === 'CallExpression') {
const { start, end } = expression;
- string += ` ${name}="${moduleContents.slice(start, end).replace(/this./g, '__this__.').replace('() => ', '')}"`;
+ string += ` ${name}='${moduleContents.slice(start, end).replace(/this./g, '__this__.').replace('() => ', '')}'`;
}
}

@@ -119,7 +120,7 @@ function parseJsxElement(element, moduleContents = '') {
if (left.object.type === 'ThisExpression') {
if (left.property.type === 'Identifier') {
// very naive (fine grained?) reactivity
- string += ` ${name}="__this__.${left.property.name}${expression.operator}${right.raw}; __this__.render();"`;
+ string += ` ${name}='__this__.${left.property.name}${expression.operator}${right.raw}; __this__.render();'`;
}
}
}
@@ -129,8 +130,8 @@ function parseJsxElement(element, moduleContents = '') {
// Can all these be parsed using one function>
if (attribute.value) {
if (attribute.value.type === 'Literal') {
- // xxx="yyy" >
- string += ` ${name}="${attribute.value.value}"`;
+ // xxx='yyy' >
+ string += ` ${name}='${attribute.value.value}'`;
} else if (attribute.value.type === 'JSXExpressionContainer') {
// xxx={allTodos.length} >
const { value } = attribute;
@@ -232,13 +233,17 @@ function findThisReferences(context, statement) {

export function parseJsx(moduleURL) {
- const moduleContents = fs.readFileSync(moduleURL, 'utf-8');
+ console.log('parseJsx');
+ let moduleContents = fs.readFileSync(moduleURL, 'utf-8');
+ // const result = transform(moduleContents, {
+ // transforms: ["typescript"],
+ // })
+ // moduleContents = tsc.transpileModule(moduleContents, tsConfig).outputText;
const moduleContents = fs.readFileSync(moduleURL, 'utf-8');
+ const result = transform(moduleContents, {
+ transforms: ['typescript', 'jsx'],
+ jsxRuntime: 'preserve'
+ });
// would be nice if we could do this instead, so we could know ahead of time
// const { inferredObservability } = await import(moduleURL);
// however, this requires making parseJsx async, but WCC acorn walking is done sync
const hasOwnObservedAttributes = undefined;
let inferredObservability = false;
let observedAttributes = [];
- let tree = acorn.Parser.extend(jsx(), importAttributes).parse(moduleContents, {
+ let tree = acorn.Parser.extend(/* tsPlugin()*/jsx(), importAttributes).parse(moduleContents, {
+ let tree = acorn.Parser.extend(jsx(), importAttributes).parse(result.code, {
ecmaVersion: 'latest',
- sourceType: 'module'
+ sourceType: 'module',
+ // locations: true
});
string = '';

@@ -310,9 +337,9 @@ export function parseJsx(moduleURL) {
}
}
}, {
- // https://github.com/acornjs/acorn/issues/829#issuecomment-1172586171
...walk.base,
- JSXElement: () => {}
+ JSXElement: () => {},
+ // TSInterfaceDeclaration: () => {}
sourceType: 'module'
});

// TODO - signals: use constructor, render, HTML attributes? some, none, or all?
@@ -363,9 +390,15 @@ export function parseJsx(moduleURL) {
`;
/* eslint-enable indent */

- tree = acorn.Parser.extend(jsx()).parse(newModuleContents, {
+ tree = acorn.Parser.extend(/*tsPlugin()*/jsx()).parse(newModuleContents, {
ecmaVersion: 'latest',
- sourceType: 'module'
+ sourceType: 'module',
+ // locations: true
+ }, {
+ // https://github.com/acornjs/acorn/issues/829#issuecomment-1172586171
+ ...walk.base,
+ JSXElement: () => {},
+ // TSInterfaceDeclaration: () => {}
});
}

diff --git a/node_modules/wc-compiler/src/wcc.js b/node_modules/wc-compiler/src/wcc.js
index 1247f3b..562bc10 100644
index 1247f3b..35884d4 100644
--- a/node_modules/wc-compiler/src/wcc.js
+++ b/node_modules/wc-compiler/src/wcc.js
@@ -10,6 +10,27 @@ import { parse, parseFragment, serialize } from 'parse5';
@@ -9,6 +9,7 @@ import { getParser, parseJsx } from './jsx-loader.js';
import { parse, parseFragment, serialize } from 'parse5';
// Need an acorn plugin for now - https://github.com/ProjectEvergreen/greenwood/issues/1218
import { importAttributes } from 'acorn-import-attributes';
import fs from 'fs';
+// import tsc from 'typescript';
+import tsPlugin from 'acorn-typescript';
+import { transform } from 'sucrase';
+
+// TODO get from consumer?
+const tsConfig = {
+ compilerOptions: {
+ "skipLibCheck": true,
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "target": "ESNext",
+ "isolatedModules": true,
+ "esModuleInterop": true,
+ "noEmit": true,
+ "allowImportingTsExtensions": true,
+ "outDir": "dist",
+ "lib": [ "esnext" ],
+ "types": [ "node" ],
+ "baseUrl": "./",
+ }
+}
import fs from 'fs';

function getParse(html) {
return html.indexOf('<html>') >= 0 || html.indexOf('<body>') >= 0 || html.indexOf('<head>') >= 0
@@ -60,15 +81,41 @@ async function renderComponentRoots(tree, definitions) {
}
@@ -61,6 +62,10 @@ async function renderComponentRoots(tree, definitions) {

function registerDependencies(moduleURL, definitions, depth = 0) {
- const moduleContents = fs.readFileSync(moduleURL, 'utf-8');
+ let moduleContents = fs.readFileSync(moduleURL, 'utf-8');
+
+ // transform(code, {transforms: ["typescript", "imports"]}).code;
const moduleContents = fs.readFileSync(moduleURL, 'utf-8');
+ const result = transform(moduleContents, {
+ transforms: ["typescript", "jsx"],
+ // jsxPragma: opts.jsxPragma,
+ // jsxFragmentPragma: opts.jsxFragmentPragma,
+ // enableLegacyTypeScriptModuleInterop: opts.enableLegacyTypeScriptModuleInterop,
+ // enableLegacyBabel5ModuleInterop: opts.enableLegacyBabel5ModuleInterop,
+ // production: opts.production,
+ // disableESTransforms: opts.disableESTransforms,
+ // filePath: id,
+ // sourceMapOptions: {
+ // compiledFilename: id
+ // }
+ transforms: ['typescript', 'jsx'],
+ jsxRuntime: 'preserve'
+ });
+
+ console.log('$$$$$$', result.code);
+ // return {
+ // code: result.code,
+ // map: result.sourceMap
+ // };
+
+ // moduleContents = tsc.transpileModule(moduleContents, tsConfig).outputText;
const nextDepth = depth += 1;
const customParser = getParser(moduleURL);
const parser = customParser ? customParser.parser : acorn.Parser;
const config = customParser ? customParser.config : {
- ...walk.base
+ // https://github.com/acornjs/acorn/issues/829#issuecomment-1172586171
+ ...walk.base,
+ JSXElement: () => {},
+ // TSInterfaceDeclaration: () => {}
@@ -68,7 +73,7 @@ function registerDependencies(moduleURL, definitions, depth = 0) {
...walk.base
};

- walk.simple(parser.extend(importAttributes).parse(moduleContents, {
+ walk.simple(acorn.Parser.extend(importAttributes).parse(result.code, {
+ walk.simple(parser.extend(importAttributes).parse(result.code, {
ecmaVersion: 'latest',
sourceType: 'module'
}), {
@@ -76,10 +123,12 @@ function registerDependencies(moduleURL, definitions, depth = 0) {
const specifier = node.source.value;
const isBareSpecifier = specifier.indexOf('.') !== 0 && specifier.indexOf('/') !== 0;
@@ -78,7 +83,8 @@ function registerDependencies(moduleURL, definitions, depth = 0) {
const extension = specifier.split('.').pop();
+ console.log({ extension });

// TODO would like to decouple .jsx from the core, ideally
- if (!isBareSpecifier && ['js', 'jsx'].includes(extension)) {
+ if (!isBareSpecifier && ['js', 'jsx', 'ts', 'tsx'].includes(extension)) {
+ // https://github.com/ProjectEvergreen/wcc/issues/122
+ if (!isBareSpecifier && ['js', 'jsx', 'ts'].includes(extension)) {
const dependencyModuleURL = new URL(node.source.value, moduleURL);
+ console.log({ dependencyModuleURL });

registerDependencies(dependencyModuleURL, definitions, nextDepth);
}
@@ -90,40 +139,56 @@ function registerDependencies(moduleURL, definitions, depth = 0) {
const tagName = args[0].type === 'Literal'
? args[0].value // single and double quotes
: args[0].quasis[0].value.raw; // template literal
- const tree = parseJsx(moduleURL);
+ // TODO restore this
+ // const tree = parseJsx(moduleURL);
const isEntry = nextDepth - 1 === 1;

definitions[tagName] = {
instanceName: args[1].name,
moduleURL,
- source: generate(tree),
+ // source: generate(tree),
url: moduleURL,
isEntry
};
}
}
- }, config);
+ // }, {
+ // https://github.com/acornjs/acorn/issues/829#issuecomment-1172586171
+ // ...walk.base,
+ // JSXElement: () => {},
+ // TSInterfaceDeclaration: () => {}
+ });
}
@@ -107,6 +113,10 @@ function registerDependencies(moduleURL, definitions, depth = 0) {

async function getTagName(moduleURL) {
- const moduleContents = await fs.promises.readFile(moduleURL, 'utf-8');
+ let moduleContents = fs.readFileSync(moduleURL, 'utf-8');
+ // moduleContents = tsc.transpileModule(moduleContents, tsConfig).outputText;
+ const result = transform(moduleContents, {transforms: ["typescript"]}).code;
const moduleContents = await fs.promises.readFile(moduleURL, 'utf-8');
+ const result = transform(moduleContents, {
+ transforms: ['typescript', 'jsx'],
+ jsxRuntime: 'preserve'
+ });
const customParser = getParser(moduleURL);
const parser = customParser ? customParser.parser : acorn.Parser;
const config = customParser ? customParser.config : {
- ...walk.base
+ // https://github.com/acornjs/acorn/issues/829#issuecomment-1172586171
+ ...walk.base,
+ JSXElement: () => {}
@@ -114,7 +124,7 @@ async function getTagName(moduleURL) {
};
let tagName;

- walk.simple(parser.extend(importAttributes).parse(moduleContents, {
+ walk.simple(acorn.Parser.extend(/*tsPlugin(),*/ importAttributes).parse(result.code, {
+ walk.simple(parser.extend(importAttributes).parse(result.code, {
ecmaVersion: 'latest',
- sourceType: 'module'
+ sourceType: 'module',
+ // locations: true
sourceType: 'module'
}), {
ExpressionStatement(node) {
if (isCustomElementDefinitionNode(node)) {
tagName = node.expression.arguments[0].value;
}
}
- }, config);
+ // }, {
+ // https://github.com/acornjs/acorn/issues/829#issuecomment-1172586171
+ // ...walk.base,
+ // TSInterfaceDeclaration: () => {},
+ // JSXElement: () => {}
+ });

return tagName;
}
@@ -134,6 +199,8 @@ async function initializeCustomElement(elementURL, tagName, attrs = [], definiti
registerDependencies(elementURL, definitions, depth);
}

+ console.log('initializeCustomElement', { elementURL });
+
// https://github.com/ProjectEvergreen/wcc/pull/67/files#r902061804
// https://github.com/ProjectEvergreen/wcc/pull/159
const { href } = elementURL;
5 changes: 0 additions & 5 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4723,11 +4723,6 @@ acorn-jsx@^5.3.2:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==

acorn-typescript@^1.4.13:
version "1.4.13"
resolved "https://registry.yarnpkg.com/acorn-typescript/-/acorn-typescript-1.4.13.tgz#5f851c8bdda0aa716ffdd5f6ac084df8acc6f5ea"
integrity sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==

acorn-walk@^7.1.1:
version "7.2.0"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
Expand Down

0 comments on commit 4ae525d

Please sign in to comment.