wc-compiler 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/wcc.dist.cjs +142 -27
- package/package.json +7 -2
- package/src/jsx-loader.js +142 -26
- package/src/wcc.js +2 -2
package/dist/wcc.dist.cjs
CHANGED
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var fs = require('fs');
|
|
6
|
-
var path = require('path');
|
|
7
|
-
var url = require('url');
|
|
8
6
|
|
|
9
7
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
10
8
|
|
|
@@ -27,7 +25,6 @@ function _interopNamespace(e) {
|
|
|
27
25
|
}
|
|
28
26
|
|
|
29
27
|
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
30
|
-
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
31
28
|
|
|
32
29
|
function noop() { }
|
|
33
30
|
|
|
@@ -27632,7 +27629,7 @@ var serialize = function(node, options) {
|
|
|
27632
27629
|
|
|
27633
27630
|
/* eslint-disable max-depth, complexity */
|
|
27634
27631
|
|
|
27635
|
-
|
|
27632
|
+
new URL(`file://${process.cwd()}/`);
|
|
27636
27633
|
|
|
27637
27634
|
// TODO same hack as definitions
|
|
27638
27635
|
// https://github.com/ProjectEvergreen/wcc/discussions/74
|
|
@@ -27647,7 +27644,7 @@ function getParse$1(html) {
|
|
|
27647
27644
|
}
|
|
27648
27645
|
|
|
27649
27646
|
function getParser(moduleURL) {
|
|
27650
|
-
const isJSX =
|
|
27647
|
+
const isJSX = moduleURL.pathname.split('.').pop() === 'jsx';
|
|
27651
27648
|
|
|
27652
27649
|
if (!isJSX) {
|
|
27653
27650
|
return;
|
|
@@ -27819,14 +27816,52 @@ function parseJsxElement(element, moduleContents = '') {
|
|
|
27819
27816
|
return string;
|
|
27820
27817
|
}
|
|
27821
27818
|
|
|
27819
|
+
// TODO handle if / else statements
|
|
27820
|
+
// https://github.com/ProjectEvergreen/wcc/issues/88
|
|
27821
|
+
function findThisReferences(context, statement) {
|
|
27822
|
+
const references = [];
|
|
27823
|
+
const isRenderFunctionContext = context === 'render';
|
|
27824
|
+
const { expression, type } = statement;
|
|
27825
|
+
const isConstructorThisAssignment = context === 'constructor'
|
|
27826
|
+
&& type === 'ExpressionStatement'
|
|
27827
|
+
&& expression.type === 'AssignmentExpression'
|
|
27828
|
+
&& expression.left.object.type === 'ThisExpression';
|
|
27829
|
+
|
|
27830
|
+
if (isConstructorThisAssignment) {
|
|
27831
|
+
// this.name = 'something'; // constructor
|
|
27832
|
+
references.push(expression.left.property.name);
|
|
27833
|
+
} else if (isRenderFunctionContext && type === 'VariableDeclaration') {
|
|
27834
|
+
statement.declarations.forEach(declaration => {
|
|
27835
|
+
const { init, id } = declaration;
|
|
27836
|
+
|
|
27837
|
+
if (init.object && init.object.type === 'ThisExpression') {
|
|
27838
|
+
// const { description } = this.todo;
|
|
27839
|
+
references.push(init.property.name);
|
|
27840
|
+
} else if (init.type === 'ThisExpression' && id && id.properties) {
|
|
27841
|
+
// const { description } = this.todo;
|
|
27842
|
+
id.properties.forEach((property) => {
|
|
27843
|
+
references.push(property.key.name);
|
|
27844
|
+
});
|
|
27845
|
+
}
|
|
27846
|
+
});
|
|
27847
|
+
}
|
|
27848
|
+
|
|
27849
|
+
return references;
|
|
27850
|
+
}
|
|
27851
|
+
|
|
27822
27852
|
function parseJsx(moduleURL) {
|
|
27823
27853
|
const moduleContents = fs__default["default"].readFileSync(moduleURL, 'utf-8');
|
|
27824
|
-
|
|
27825
|
-
|
|
27826
|
-
|
|
27854
|
+
// would be nice if we could do this instead, so we could know ahead of time
|
|
27855
|
+
// const { inferredObservability } = await import(moduleURL);
|
|
27856
|
+
// however, this requires making parseJsx async, but WCC acorn walking is done sync
|
|
27857
|
+
const hasOwnObservedAttributes = undefined;
|
|
27858
|
+
let inferredObservability = false;
|
|
27859
|
+
let observedAttributes = [];
|
|
27860
|
+
let tree = Parser$2.extend(jsx()).parse(moduleContents, {
|
|
27827
27861
|
ecmaVersion: 'latest',
|
|
27828
27862
|
sourceType: 'module'
|
|
27829
27863
|
});
|
|
27864
|
+
string = '';
|
|
27830
27865
|
|
|
27831
27866
|
simple(tree, {
|
|
27832
27867
|
ClassDeclaration(node) {
|
|
@@ -27834,29 +27869,46 @@ function parseJsx(moduleURL) {
|
|
|
27834
27869
|
const hasShadowRoot = moduleContents.slice(node.body.start, node.body.end).indexOf('this.attachShadow(') > 0;
|
|
27835
27870
|
|
|
27836
27871
|
for (const n1 of node.body.body) {
|
|
27837
|
-
if (n1.type === 'MethodDefinition'
|
|
27838
|
-
|
|
27839
|
-
|
|
27840
|
-
|
|
27841
|
-
|
|
27842
|
-
|
|
27843
|
-
|
|
27844
|
-
|
|
27845
|
-
|
|
27846
|
-
|
|
27847
|
-
|
|
27848
|
-
|
|
27849
|
-
|
|
27850
|
-
|
|
27851
|
-
|
|
27852
|
-
|
|
27853
|
-
|
|
27854
|
-
|
|
27872
|
+
if (n1.type === 'MethodDefinition') {
|
|
27873
|
+
const nodeName = n1.key.name;
|
|
27874
|
+
if (nodeName === 'render') {
|
|
27875
|
+
for (const n2 in n1.value.body.body) {
|
|
27876
|
+
const n = n1.value.body.body[n2];
|
|
27877
|
+
|
|
27878
|
+
if (n.type === 'VariableDeclaration') {
|
|
27879
|
+
observedAttributes = [
|
|
27880
|
+
...observedAttributes,
|
|
27881
|
+
...findThisReferences('render', n)
|
|
27882
|
+
];
|
|
27883
|
+
} else if (n.type === 'ReturnStatement' && n.argument.type === 'JSXElement') {
|
|
27884
|
+
const html = parseJsxElement(n.argument, moduleContents);
|
|
27885
|
+
const elementTree = getParse$1(html)(html);
|
|
27886
|
+
const elementRoot = hasShadowRoot ? 'this.shadowRoot' : 'this';
|
|
27887
|
+
|
|
27888
|
+
applyDomDepthSubstitutions(elementTree, undefined, hasShadowRoot);
|
|
27889
|
+
|
|
27890
|
+
const finalHtml = serialize(elementTree);
|
|
27891
|
+
const transformed = parse$1(`${elementRoot}.innerHTML = \`${finalHtml}\`;`, {
|
|
27892
|
+
ecmaVersion: 'latest',
|
|
27893
|
+
sourceType: 'module'
|
|
27894
|
+
});
|
|
27895
|
+
|
|
27896
|
+
n1.value.body.body[n2] = transformed;
|
|
27897
|
+
}
|
|
27855
27898
|
}
|
|
27856
27899
|
}
|
|
27857
27900
|
}
|
|
27858
27901
|
}
|
|
27859
27902
|
}
|
|
27903
|
+
},
|
|
27904
|
+
ExportNamedDeclaration(node) {
|
|
27905
|
+
const { declaration } = node;
|
|
27906
|
+
|
|
27907
|
+
if (declaration && declaration.type === 'VariableDeclaration' && declaration.kind === 'const' && declaration.declarations.length === 1) {
|
|
27908
|
+
if (declaration.declarations[0].id.name === 'inferredObservability') {
|
|
27909
|
+
inferredObservability = Boolean(node.declaration.declarations[0].init.raw);
|
|
27910
|
+
}
|
|
27911
|
+
}
|
|
27860
27912
|
}
|
|
27861
27913
|
}, {
|
|
27862
27914
|
// https://github.com/acornjs/acorn/issues/829#issuecomment-1172586171
|
|
@@ -27864,6 +27916,68 @@ function parseJsx(moduleURL) {
|
|
|
27864
27916
|
JSXElement: () => {}
|
|
27865
27917
|
});
|
|
27866
27918
|
|
|
27919
|
+
// TODO - signals: use constructor, render, HTML attributes? some, none, or all?
|
|
27920
|
+
if (inferredObservability && observedAttributes.length > 0 && !hasOwnObservedAttributes) {
|
|
27921
|
+
let insertPoint;
|
|
27922
|
+
for (const line of tree.body) {
|
|
27923
|
+
// test for class MyComponent vs export default class MyComponent
|
|
27924
|
+
if (line.type === 'ClassDeclaration' || (line.declaration && line.declaration.type) === 'ClassDeclaration') {
|
|
27925
|
+
const children = !line.declaration
|
|
27926
|
+
? line.body.body
|
|
27927
|
+
: line.declaration.body.body;
|
|
27928
|
+
for (const method of children) {
|
|
27929
|
+
if (method.key.name === 'constructor') {
|
|
27930
|
+
insertPoint = method.start - 1;
|
|
27931
|
+
break;
|
|
27932
|
+
}
|
|
27933
|
+
}
|
|
27934
|
+
}
|
|
27935
|
+
}
|
|
27936
|
+
|
|
27937
|
+
let newModuleContents = escodegen.generate(tree);
|
|
27938
|
+
|
|
27939
|
+
// TODO better way to determine value type?
|
|
27940
|
+
/* eslint-disable indent */
|
|
27941
|
+
newModuleContents = `${newModuleContents.slice(0, insertPoint)}
|
|
27942
|
+
static get observedAttributes() {
|
|
27943
|
+
return [${[...observedAttributes].map(attr => `'${attr}'`).join(',')}]
|
|
27944
|
+
}
|
|
27945
|
+
|
|
27946
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
27947
|
+
function getValue(value) {
|
|
27948
|
+
return value.charAt(0) === '{' || value.charAt(0) === '['
|
|
27949
|
+
? JSON.parse(value)
|
|
27950
|
+
: !isNaN(value)
|
|
27951
|
+
? parseInt(value, 10)
|
|
27952
|
+
: value === 'true' || value === 'false'
|
|
27953
|
+
? value === 'true' ? true : false
|
|
27954
|
+
: value;
|
|
27955
|
+
}
|
|
27956
|
+
if (newValue !== oldValue) {
|
|
27957
|
+
switch(name) {
|
|
27958
|
+
${observedAttributes.map((attr) => {
|
|
27959
|
+
return `
|
|
27960
|
+
case '${attr}':
|
|
27961
|
+
this.${attr} = getValue(newValue);
|
|
27962
|
+
break;
|
|
27963
|
+
`;
|
|
27964
|
+
}).join('\n')}
|
|
27965
|
+
}
|
|
27966
|
+
|
|
27967
|
+
this.render();
|
|
27968
|
+
}
|
|
27969
|
+
}
|
|
27970
|
+
|
|
27971
|
+
${newModuleContents.slice(insertPoint)}
|
|
27972
|
+
`;
|
|
27973
|
+
/* eslint-enable indent */
|
|
27974
|
+
|
|
27975
|
+
tree = Parser$2.extend(jsx()).parse(newModuleContents, {
|
|
27976
|
+
ecmaVersion: 'latest',
|
|
27977
|
+
sourceType: 'module'
|
|
27978
|
+
});
|
|
27979
|
+
}
|
|
27980
|
+
|
|
27867
27981
|
return tree;
|
|
27868
27982
|
}
|
|
27869
27983
|
|
|
@@ -27933,9 +28047,10 @@ function registerDependencies(moduleURL, definitions, depth = 0) {
|
|
|
27933
28047
|
ImportDeclaration(node) {
|
|
27934
28048
|
const specifier = node.source.value;
|
|
27935
28049
|
const isBareSpecifier = specifier.indexOf('.') !== 0 && specifier.indexOf('/') !== 0;
|
|
28050
|
+
const extension = specifier.split('.').pop();
|
|
27936
28051
|
|
|
27937
28052
|
// TODO would like to decouple .jsx from the core, ideally
|
|
27938
|
-
if (!isBareSpecifier && ['
|
|
28053
|
+
if (!isBareSpecifier && ['js', 'jsx'].includes(extension)) {
|
|
27939
28054
|
const dependencyModuleURL = new URL(node.source.value, moduleURL);
|
|
27940
28055
|
|
|
27941
28056
|
registerDependencies(dependencyModuleURL, definitions, nextDepth);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wc-compiler",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Experimental native Web Components compiler.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
"main": "src/wcc.js",
|
|
10
10
|
"type": "module",
|
|
11
11
|
"author": "Owen Buckley <owen@thegreenhouse.io>",
|
|
12
|
+
"keywords": [
|
|
13
|
+
"Web Components",
|
|
14
|
+
"JSX",
|
|
15
|
+
"Greenwood"
|
|
16
|
+
],
|
|
12
17
|
"license": "MIT",
|
|
13
18
|
"engines": {
|
|
14
19
|
"node": ">=14"
|
|
@@ -27,7 +32,7 @@
|
|
|
27
32
|
"build": "node ./build.js",
|
|
28
33
|
"serve": "node ./build.js && http-server ./dist --open",
|
|
29
34
|
"start": "npm run develop",
|
|
30
|
-
"test": "mocha --exclude \"./test/cases/jsx
|
|
35
|
+
"test": "mocha --exclude \"./test/cases/jsx*/**\" --exclude \"./test/cases/custom-extension/**\" \"./test/**/**/*.spec.js\"",
|
|
31
36
|
"test:exp": "c8 node --experimental-loader ./test-exp-loader.js ./node_modules/mocha/bin/mocha \"./test/**/**/*.spec.js\"",
|
|
32
37
|
"test:tdd": "npm run test -- --watch",
|
|
33
38
|
"test:tdd:exp": "npm run test:exp -- --watch",
|
package/src/jsx-loader.js
CHANGED
|
@@ -6,10 +6,8 @@ import escodegen from 'escodegen';
|
|
|
6
6
|
import fs from 'fs';
|
|
7
7
|
import jsx from 'acorn-jsx';
|
|
8
8
|
import { parse, parseFragment, serialize } from 'parse5';
|
|
9
|
-
import path from 'path';
|
|
10
|
-
import { URL, pathToFileURL } from 'url';
|
|
11
9
|
|
|
12
|
-
const baseURL =
|
|
10
|
+
const baseURL = new URL(`file://${process.cwd()}/`);
|
|
13
11
|
const jsxRegex = /\.(jsx)$/;
|
|
14
12
|
|
|
15
13
|
// TODO same hack as definitions
|
|
@@ -25,7 +23,7 @@ function getParse(html) {
|
|
|
25
23
|
}
|
|
26
24
|
|
|
27
25
|
export function getParser(moduleURL) {
|
|
28
|
-
const isJSX =
|
|
26
|
+
const isJSX = moduleURL.pathname.split('.').pop() === 'jsx';
|
|
29
27
|
|
|
30
28
|
if (!isJSX) {
|
|
31
29
|
return;
|
|
@@ -197,14 +195,52 @@ function parseJsxElement(element, moduleContents = '') {
|
|
|
197
195
|
return string;
|
|
198
196
|
}
|
|
199
197
|
|
|
198
|
+
// TODO handle if / else statements
|
|
199
|
+
// https://github.com/ProjectEvergreen/wcc/issues/88
|
|
200
|
+
function findThisReferences(context, statement) {
|
|
201
|
+
const references = [];
|
|
202
|
+
const isRenderFunctionContext = context === 'render';
|
|
203
|
+
const { expression, type } = statement;
|
|
204
|
+
const isConstructorThisAssignment = context === 'constructor'
|
|
205
|
+
&& type === 'ExpressionStatement'
|
|
206
|
+
&& expression.type === 'AssignmentExpression'
|
|
207
|
+
&& expression.left.object.type === 'ThisExpression';
|
|
208
|
+
|
|
209
|
+
if (isConstructorThisAssignment) {
|
|
210
|
+
// this.name = 'something'; // constructor
|
|
211
|
+
references.push(expression.left.property.name);
|
|
212
|
+
} else if (isRenderFunctionContext && type === 'VariableDeclaration') {
|
|
213
|
+
statement.declarations.forEach(declaration => {
|
|
214
|
+
const { init, id } = declaration;
|
|
215
|
+
|
|
216
|
+
if (init.object && init.object.type === 'ThisExpression') {
|
|
217
|
+
// const { description } = this.todo;
|
|
218
|
+
references.push(init.property.name);
|
|
219
|
+
} else if (init.type === 'ThisExpression' && id && id.properties) {
|
|
220
|
+
// const { description } = this.todo;
|
|
221
|
+
id.properties.forEach((property) => {
|
|
222
|
+
references.push(property.key.name);
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return references;
|
|
229
|
+
}
|
|
230
|
+
|
|
200
231
|
export function parseJsx(moduleURL) {
|
|
201
232
|
const moduleContents = fs.readFileSync(moduleURL, 'utf-8');
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
233
|
+
// would be nice if we could do this instead, so we could know ahead of time
|
|
234
|
+
// const { inferredObservability } = await import(moduleURL);
|
|
235
|
+
// however, this requires making parseJsx async, but WCC acorn walking is done sync
|
|
236
|
+
const hasOwnObservedAttributes = undefined;
|
|
237
|
+
let inferredObservability = false;
|
|
238
|
+
let observedAttributes = [];
|
|
239
|
+
let tree = acorn.Parser.extend(jsx()).parse(moduleContents, {
|
|
205
240
|
ecmaVersion: 'latest',
|
|
206
241
|
sourceType: 'module'
|
|
207
242
|
});
|
|
243
|
+
string = '';
|
|
208
244
|
|
|
209
245
|
walk.simple(tree, {
|
|
210
246
|
ClassDeclaration(node) {
|
|
@@ -212,29 +248,46 @@ export function parseJsx(moduleURL) {
|
|
|
212
248
|
const hasShadowRoot = moduleContents.slice(node.body.start, node.body.end).indexOf('this.attachShadow(') > 0;
|
|
213
249
|
|
|
214
250
|
for (const n1 of node.body.body) {
|
|
215
|
-
if (n1.type === 'MethodDefinition'
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
251
|
+
if (n1.type === 'MethodDefinition') {
|
|
252
|
+
const nodeName = n1.key.name;
|
|
253
|
+
if (nodeName === 'render') {
|
|
254
|
+
for (const n2 in n1.value.body.body) {
|
|
255
|
+
const n = n1.value.body.body[n2];
|
|
256
|
+
|
|
257
|
+
if (n.type === 'VariableDeclaration') {
|
|
258
|
+
observedAttributes = [
|
|
259
|
+
...observedAttributes,
|
|
260
|
+
...findThisReferences('render', n)
|
|
261
|
+
];
|
|
262
|
+
} else if (n.type === 'ReturnStatement' && n.argument.type === 'JSXElement') {
|
|
263
|
+
const html = parseJsxElement(n.argument, moduleContents);
|
|
264
|
+
const elementTree = getParse(html)(html);
|
|
265
|
+
const elementRoot = hasShadowRoot ? 'this.shadowRoot' : 'this';
|
|
266
|
+
|
|
267
|
+
applyDomDepthSubstitutions(elementTree, undefined, hasShadowRoot);
|
|
268
|
+
|
|
269
|
+
const finalHtml = serialize(elementTree);
|
|
270
|
+
const transformed = acorn.parse(`${elementRoot}.innerHTML = \`${finalHtml}\`;`, {
|
|
271
|
+
ecmaVersion: 'latest',
|
|
272
|
+
sourceType: 'module'
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
n1.value.body.body[n2] = transformed;
|
|
276
|
+
}
|
|
233
277
|
}
|
|
234
278
|
}
|
|
235
279
|
}
|
|
236
280
|
}
|
|
237
281
|
}
|
|
282
|
+
},
|
|
283
|
+
ExportNamedDeclaration(node) {
|
|
284
|
+
const { declaration } = node;
|
|
285
|
+
|
|
286
|
+
if (declaration && declaration.type === 'VariableDeclaration' && declaration.kind === 'const' && declaration.declarations.length === 1) {
|
|
287
|
+
if (declaration.declarations[0].id.name === 'inferredObservability') {
|
|
288
|
+
inferredObservability = Boolean(node.declaration.declarations[0].init.raw);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
238
291
|
}
|
|
239
292
|
}, {
|
|
240
293
|
// https://github.com/acornjs/acorn/issues/829#issuecomment-1172586171
|
|
@@ -242,6 +295,68 @@ export function parseJsx(moduleURL) {
|
|
|
242
295
|
JSXElement: () => {}
|
|
243
296
|
});
|
|
244
297
|
|
|
298
|
+
// TODO - signals: use constructor, render, HTML attributes? some, none, or all?
|
|
299
|
+
if (inferredObservability && observedAttributes.length > 0 && !hasOwnObservedAttributes) {
|
|
300
|
+
let insertPoint;
|
|
301
|
+
for (const line of tree.body) {
|
|
302
|
+
// test for class MyComponent vs export default class MyComponent
|
|
303
|
+
if (line.type === 'ClassDeclaration' || (line.declaration && line.declaration.type) === 'ClassDeclaration') {
|
|
304
|
+
const children = !line.declaration
|
|
305
|
+
? line.body.body
|
|
306
|
+
: line.declaration.body.body;
|
|
307
|
+
for (const method of children) {
|
|
308
|
+
if (method.key.name === 'constructor') {
|
|
309
|
+
insertPoint = method.start - 1;
|
|
310
|
+
break;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
let newModuleContents = escodegen.generate(tree);
|
|
317
|
+
|
|
318
|
+
// TODO better way to determine value type?
|
|
319
|
+
/* eslint-disable indent */
|
|
320
|
+
newModuleContents = `${newModuleContents.slice(0, insertPoint)}
|
|
321
|
+
static get observedAttributes() {
|
|
322
|
+
return [${[...observedAttributes].map(attr => `'${attr}'`).join(',')}]
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
326
|
+
function getValue(value) {
|
|
327
|
+
return value.charAt(0) === '{' || value.charAt(0) === '['
|
|
328
|
+
? JSON.parse(value)
|
|
329
|
+
: !isNaN(value)
|
|
330
|
+
? parseInt(value, 10)
|
|
331
|
+
: value === 'true' || value === 'false'
|
|
332
|
+
? value === 'true' ? true : false
|
|
333
|
+
: value;
|
|
334
|
+
}
|
|
335
|
+
if (newValue !== oldValue) {
|
|
336
|
+
switch(name) {
|
|
337
|
+
${observedAttributes.map((attr) => {
|
|
338
|
+
return `
|
|
339
|
+
case '${attr}':
|
|
340
|
+
this.${attr} = getValue(newValue);
|
|
341
|
+
break;
|
|
342
|
+
`;
|
|
343
|
+
}).join('\n')}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
this.render();
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
${newModuleContents.slice(insertPoint)}
|
|
351
|
+
`;
|
|
352
|
+
/* eslint-enable indent */
|
|
353
|
+
|
|
354
|
+
tree = acorn.Parser.extend(jsx()).parse(newModuleContents, {
|
|
355
|
+
ecmaVersion: 'latest',
|
|
356
|
+
sourceType: 'module'
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
245
360
|
return tree;
|
|
246
361
|
}
|
|
247
362
|
|
|
@@ -265,7 +380,8 @@ export async function load(url, context, defaultLoad) {
|
|
|
265
380
|
|
|
266
381
|
return {
|
|
267
382
|
format: 'module',
|
|
268
|
-
source: escodegen.generate(jsFromJsx)
|
|
383
|
+
source: escodegen.generate(jsFromJsx),
|
|
384
|
+
shortCircuit: true
|
|
269
385
|
};
|
|
270
386
|
}
|
|
271
387
|
|
package/src/wcc.js
CHANGED
|
@@ -8,7 +8,6 @@ import escodegen from 'escodegen';
|
|
|
8
8
|
import { getParser, parseJsx } from './jsx-loader.js';
|
|
9
9
|
import { parse, parseFragment, serialize } from 'parse5';
|
|
10
10
|
import fs from 'fs';
|
|
11
|
-
import path from 'path';
|
|
12
11
|
|
|
13
12
|
function getParse(html) {
|
|
14
13
|
return html.indexOf('<html>') >= 0 || html.indexOf('<body>') >= 0 || html.indexOf('<head>') >= 0
|
|
@@ -74,9 +73,10 @@ function registerDependencies(moduleURL, definitions, depth = 0) {
|
|
|
74
73
|
ImportDeclaration(node) {
|
|
75
74
|
const specifier = node.source.value;
|
|
76
75
|
const isBareSpecifier = specifier.indexOf('.') !== 0 && specifier.indexOf('/') !== 0;
|
|
76
|
+
const extension = specifier.split('.').pop();
|
|
77
77
|
|
|
78
78
|
// TODO would like to decouple .jsx from the core, ideally
|
|
79
|
-
if (!isBareSpecifier && ['
|
|
79
|
+
if (!isBareSpecifier && ['js', 'jsx'].includes(extension)) {
|
|
80
80
|
const dependencyModuleURL = new URL(node.source.value, moduleURL);
|
|
81
81
|
|
|
82
82
|
registerDependencies(dependencyModuleURL, definitions, nextDepth);
|