4.0 KiB
Naprawa Pipes - Problem z kontekstem ewaluacji
Problem zgłoszony przez użytkownika
W aplikacji IoT/Ant kod:
<pre>{{ 123 | json }}</pre>
<pre>{{ "string" | json }}</pre>
<pre>{{ true | json }}</pre>
Powodował, że cały komponent się "wysypał" bez błędów - wcześniej na metodach było po prostu "undefined".
Analiza problemu
1. Transformacja była poprawna
Transformer poprawnie generował kod:
this._pipes?.['json']?.transform(123)
2. Problem był w runtime
W template-renderer.ts wyrażenia są ewaluowane za pomocą:
private eval(expr: string): any {
return new Function('c', `with(c){return ${expr}}`)(this.component);
}
W kontekście with(c), this odnosi się do globalnego obiektu, a nie do komponentu c. Dlatego this._pipes było undefined.
Rozwiązanie
Zmieniono generowany kod z this._pipes na _pipes:
Przed:
this._pipes?.['json']?.transform(123)
Po:
_pipes?.['json']?.transform(123)
Teraz _pipes jest dostępne bezpośrednio z kontekstu komponentu c w with(c).
Zmieniony plik
/web/quarc/cli/processors/template/template-transformer.ts:
private transformPipeExpression(expression: string): string {
const parts = this.splitByPipe(expression);
if (parts.length === 1) {
return expression;
}
let result = parts[0].trim();
for (let i = 1; i < parts.length; i++) {
const pipePart = parts[i].trim();
const colonIndex = pipePart.indexOf(':');
if (colonIndex === -1) {
const pipeName = pipePart.trim();
result = `_pipes?.['${pipeName}']?.transform(${result})`; // ← Zmiana
} else {
const pipeName = pipePart.substring(0, colonIndex).trim();
const argsStr = pipePart.substring(colonIndex + 1).trim();
const args = argsStr.split(':').map(arg => arg.trim());
const argsJoined = args.join(', ');
result = `_pipes?.['${pipeName}']?.transform(${result}, ${argsJoined})`; // ← Zmiana
}
}
return result;
}
Testy
Testy jednostkowe
✅ test-pipes.ts - 31/31 testów przeszło
✅ test-pipe-with-logical-operators.ts - 7/7 testów przeszło
✅ test-pipe-transformation-detailed.ts - wszystkie transformacje poprawne
Build aplikacji
✅ /web/IoT/Ant/assets/resources/quarc - build przeszedł pomyślnie
Utworzone pipes
Zestaw podstawowych pipes gotowych do użycia:
- UpperCasePipe -
{{ text | uppercase }} - LowerCasePipe -
{{ text | lowercase }} - JsonPipe -
{{ obj | json }} - CamelCasePipe -
{{ 'hello-world' | camelcase }}→helloWorld - PascalCasePipe -
{{ 'hello-world' | pascalcase }}→HelloWorld - SnakeCasePipe -
{{ 'helloWorld' | snakecase }}→hello_world - KebabCasePipe -
{{ 'helloWorld' | kebabcase }}→hello-world - SubstrPipe -
{{ text | substr:0:10 }} - DatePipe -
{{ date | date:'yyyy-MM-dd' }}
Przykład użycia
import { Component, signal } from '@quarc/core';
import { JsonPipe, UpperCasePipe } from '@quarc/core';
@Component({
selector: 'app-example',
template: `
<div>{{ name | uppercase }}</div>
<pre>{{ data | json }}</pre>
<div>{{ value || 'default' | uppercase }}</div>
`,
imports: [JsonPipe, UpperCasePipe],
})
export class ExampleComponent {
name = signal('hello');
data = signal({ test: 123 });
value = signal(null);
}
Dokumentacja
Pełna dokumentacja pipes dostępna w:
/web/quarc/core/pipes/README.md/web/quarc/PIPE_IMPLEMENTATION_FIX.md
Podsumowanie
Problem został całkowicie rozwiązany:
- ✅ Pipes są poprawnie transformowane w czasie kompilacji
- ✅ Pipes są dostępne w runtime przez kontekst komponentu
- ✅ Operatory logiczne
||i&&nie są mylone z pipe separator| - ✅ Wszystkie testy jednostkowe przechodzą
- ✅ Build aplikacji działa poprawnie