@fluffjs/cli 0.3.1 → 0.3.2

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.
@@ -86,7 +86,7 @@ export class ComponentCompiler {
86
86
  const componentDir = path.dirname(filePath);
87
87
  const parser = this.createTemplateParser(filePath);
88
88
  reactivePropertiesMap.delete(filePath);
89
- if (source.includes('@Reactive') || source.includes('@Input')) {
89
+ if (source.includes('@Reactive') || source.includes('@Input') || source.includes('@HostListener') || source.includes('@HostBinding') || source.includes('@Watch') || source.includes('@ViewChild') || source.includes('@LinkedProperty')) {
90
90
  source = await this.transformReactiveProperties(source, filePath, production);
91
91
  }
92
92
  const metadata = await this.extractComponentMetadata(source, filePath);
@@ -190,8 +190,16 @@ export default function reactivePlugin() {
190
190
  t.variableDeclaration('const', [t.variableDeclarator(t.identifier('__v'), t.memberExpression(t.thisExpression(), t.identifier(getterName)))]),
191
191
  updateStatement
192
192
  ]));
193
+ const watchedProps = [];
194
+ memberPath.traverse({
195
+ MemberExpression(mePath) {
196
+ if (t.isThisExpression(mePath.node.object) && t.isIdentifier(mePath.node.property)) {
197
+ watchedProps.push(mePath.node.property.name);
198
+ }
199
+ }
200
+ });
193
201
  newMembers.push(updateMethod);
194
- getterHostBindingUpdates.push(`__updateHostBinding_${getterName}`);
202
+ getterHostBindingUpdates.push({ updateMethodName: `__updateHostBinding_${getterName}`, watchedProps });
195
203
  }
196
204
  }
197
205
  decorators.splice(hostBindingIndex, 1);
@@ -383,8 +391,13 @@ export default function reactivePlugin() {
383
391
  for (const { propName, className, privateName } of classHostBindingDefs) {
384
392
  constructorStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('__defineClassHostBinding')), [t.stringLiteral(propName), t.stringLiteral(className), t.stringLiteral(privateName)])));
385
393
  }
386
- for (const updateMethodName of getterHostBindingUpdates) {
394
+ for (const { updateMethodName, watchedProps } of getterHostBindingUpdates) {
387
395
  constructorStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier(updateMethodName)), [])));
396
+ for (const prop of watchedProps) {
397
+ if (reactiveProps.has(prop)) {
398
+ constructorStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier('__baseSubscriptions')), t.identifier('push')), [t.callExpression(t.memberExpression(t.memberExpression(t.memberExpression(t.thisExpression(), t.identifier(`__${prop}`)), t.identifier('onChange')), t.identifier('subscribe')), [t.arrowFunctionExpression([], t.callExpression(t.memberExpression(t.thisExpression(), t.identifier(updateMethodName)), []))])])));
399
+ }
400
+ }
388
401
  }
389
402
  for (const { propName, privateName } of propertyHostBindingInits) {
390
403
  constructorStatements.push(t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.thisExpression(), t.identifier(propName)), t.memberExpression(t.thisExpression(), t.identifier(privateName)))));
@@ -420,8 +433,19 @@ export default function reactivePlugin() {
420
433
  const watchClassProp = t.classProperty(t.identifier(propName), t.callExpression(t.arrowFunctionExpression([], t.blockStatement(iife)), []));
421
434
  path.pushContainer('body', watchClassProp);
422
435
  }
436
+ const globalListenerCleanups = [];
423
437
  for (const { methodName, eventName } of hostListeners) {
424
- const [baseEvent, ...modifiers] = eventName.split('.');
438
+ let target = 'this';
439
+ let eventPart = eventName;
440
+ if (eventName.startsWith('document:')) {
441
+ target = 'document';
442
+ eventPart = eventName.slice('document:'.length);
443
+ }
444
+ else if (eventName.startsWith('window:')) {
445
+ target = 'window';
446
+ eventPart = eventName.slice('window:'.length);
447
+ }
448
+ const [baseEvent, ...modifiers] = eventPart.split('.');
425
449
  let handlerBody = t.emptyStatement();
426
450
  if (modifiers.length > 0) {
427
451
  const conditions = modifiers.map(mod => {
@@ -439,10 +463,23 @@ export default function reactivePlugin() {
439
463
  else {
440
464
  handlerBody = t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier(methodName)), [t.identifier('__ev')]));
441
465
  }
442
- constructorStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('addEventListener')), [
443
- t.stringLiteral(baseEvent),
444
- t.arrowFunctionExpression([t.identifier('__ev')], t.blockStatement([handlerBody]))
445
- ])));
466
+ const handlerFn = t.arrowFunctionExpression([t.identifier('__ev')], t.blockStatement([handlerBody]));
467
+ if (target === 'this') {
468
+ constructorStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(t.thisExpression(), t.identifier('addEventListener')), [
469
+ t.stringLiteral(baseEvent),
470
+ handlerFn
471
+ ])));
472
+ }
473
+ else {
474
+ const handlerPropName = `__${methodName}Handler`;
475
+ const targetExpr = target === 'document' ? t.identifier('document') : t.identifier('window');
476
+ constructorStatements.push(t.expressionStatement(t.assignmentExpression('=', t.memberExpression(t.thisExpression(), t.identifier(handlerPropName)), handlerFn)));
477
+ constructorStatements.push(t.expressionStatement(t.callExpression(t.memberExpression(targetExpr, t.identifier('addEventListener')), [
478
+ t.stringLiteral(baseEvent),
479
+ t.memberExpression(t.thisExpression(), t.identifier(handlerPropName))
480
+ ])));
481
+ globalListenerCleanups.push(t.expressionStatement(t.callExpression(t.memberExpression(target === 'document' ? t.identifier('document') : t.identifier('window'), t.identifier('removeEventListener')), [t.stringLiteral(baseEvent), t.memberExpression(t.thisExpression(), t.identifier(handlerPropName))])));
482
+ }
446
483
  }
447
484
  if (constructorStatements.length > 0) {
448
485
  const constructor = path.node.body.find((m) => t.isClassMethod(m) && m.kind === 'constructor');
@@ -456,6 +493,15 @@ export default function reactivePlugin() {
456
493
  ])));
457
494
  }
458
495
  }
496
+ if (globalListenerCleanups.length > 0) {
497
+ const disconnectedCallback = path.node.body.find((m) => t.isClassMethod(m) && t.isIdentifier(m.key) && m.key.name === 'disconnectedCallback');
498
+ if (disconnectedCallback) {
499
+ disconnectedCallback.body.body.unshift(...globalListenerCleanups);
500
+ }
501
+ else {
502
+ path.pushContainer('body', t.classMethod('method', t.identifier('disconnectedCallback'), [], t.blockStatement(globalListenerCleanups)));
503
+ }
504
+ }
459
505
  },
460
506
  ClassDeclaration(path, state) {
461
507
  const decorators = path.node.decorators ?? [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluffjs/cli",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "type": "module",
5
5
  "main": "./index.js",
6
6
  "module": "./index.js",