@blamejs/blamejs-shop 0.5.12 → 0.5.13
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/CHANGELOG.md +2 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/vendor/MANIFEST.json +632 -416
- package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
- package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
- package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
- package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
- package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
- package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
- package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
- package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
- package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
- package/lib/vendor/blamejs/.gitignore +2 -0
- package/lib/vendor/blamejs/CHANGELOG.md +122 -0
- package/lib/vendor/blamejs/NOTICE +26 -1
- package/lib/vendor/blamejs/SECURITY.md +1 -1
- package/lib/vendor/blamejs/api-snapshot.json +207 -5
- package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
- package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
- package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
- package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
- package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
- package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
- package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
- package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
- package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
- package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
- package/lib/vendor/blamejs/index.js +6 -0
- package/lib/vendor/blamejs/lib/a2a.js +4 -4
- package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
- package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
- package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
- package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
- package/lib/vendor/blamejs/lib/archive-read.js +8 -0
- package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
- package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
- package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
- package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
- package/lib/vendor/blamejs/lib/audit.js +71 -8
- package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
- package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
- package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
- package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
- package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
- package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
- package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
- package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
- package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
- package/lib/vendor/blamejs/lib/backup/index.js +16 -5
- package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
- package/lib/vendor/blamejs/lib/base32.js +21 -0
- package/lib/vendor/blamejs/lib/break-glass.js +19 -10
- package/lib/vendor/blamejs/lib/bundler.js +5 -1
- package/lib/vendor/blamejs/lib/cache-status.js +3 -7
- package/lib/vendor/blamejs/lib/calendar.js +21 -1
- package/lib/vendor/blamejs/lib/cbor.js +12 -1
- package/lib/vendor/blamejs/lib/cert.js +29 -11
- package/lib/vendor/blamejs/lib/cli.js +94 -24
- package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
- package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
- package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
- package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
- package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
- package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
- package/lib/vendor/blamejs/lib/content-digest.js +2 -1
- package/lib/vendor/blamejs/lib/cookies.js +13 -3
- package/lib/vendor/blamejs/lib/cose.js +31 -16
- package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
- package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
- package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
- package/lib/vendor/blamejs/lib/crypto.js +314 -19
- package/lib/vendor/blamejs/lib/csp.js +11 -3
- package/lib/vendor/blamejs/lib/daemon.js +270 -24
- package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
- package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
- package/lib/vendor/blamejs/lib/db-query.js +34 -7
- package/lib/vendor/blamejs/lib/db.js +18 -6
- package/lib/vendor/blamejs/lib/dbsc.js +17 -0
- package/lib/vendor/blamejs/lib/dev.js +21 -2
- package/lib/vendor/blamejs/lib/dsr.js +157 -102
- package/lib/vendor/blamejs/lib/external-db.js +41 -2
- package/lib/vendor/blamejs/lib/file-upload.js +25 -7
- package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
- package/lib/vendor/blamejs/lib/forms.js +113 -27
- package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
- package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
- package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
- package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
- package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
- package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
- package/lib/vendor/blamejs/lib/guard-html.js +26 -53
- package/lib/vendor/blamejs/lib/guard-image.js +24 -5
- package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
- package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
- package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
- package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
- package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
- package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
- package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
- package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
- package/lib/vendor/blamejs/lib/guard-time.js +1 -1
- package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
- package/lib/vendor/blamejs/lib/html-balance.js +3 -3
- package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
- package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
- package/lib/vendor/blamejs/lib/http-client.js +39 -7
- package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
- package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
- package/lib/vendor/blamejs/lib/i18n.js +35 -21
- package/lib/vendor/blamejs/lib/incident-report.js +8 -1
- package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
- package/lib/vendor/blamejs/lib/json-path.js +23 -1
- package/lib/vendor/blamejs/lib/jwk.js +20 -3
- package/lib/vendor/blamejs/lib/link-header.js +2 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
- package/lib/vendor/blamejs/lib/log-stream.js +8 -3
- package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
- package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
- package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
- package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
- package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
- package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
- package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
- package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
- package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
- package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
- package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
- package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
- package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
- package/lib/vendor/blamejs/lib/mail.js +15 -5
- package/lib/vendor/blamejs/lib/metrics.js +268 -63
- package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
- package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
- package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
- package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
- package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
- package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
- package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
- package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
- package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
- package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
- package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
- package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
- package/lib/vendor/blamejs/lib/network-dns.js +21 -2
- package/lib/vendor/blamejs/lib/network-tls.js +69 -7
- package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
- package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
- package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
- package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
- package/lib/vendor/blamejs/lib/outbox.js +1 -1
- package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
- package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
- package/lib/vendor/blamejs/lib/permissions.js +6 -3
- package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
- package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
- package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
- package/lib/vendor/blamejs/lib/pubsub.js +20 -9
- package/lib/vendor/blamejs/lib/queue-local.js +8 -1
- package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
- package/lib/vendor/blamejs/lib/redact.js +54 -0
- package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
- package/lib/vendor/blamejs/lib/restore.js +19 -0
- package/lib/vendor/blamejs/lib/retention.js +12 -4
- package/lib/vendor/blamejs/lib/router.js +60 -6
- package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
- package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
- package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
- package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
- package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
- package/lib/vendor/blamejs/lib/safe-object.js +80 -0
- package/lib/vendor/blamejs/lib/safe-path.js +52 -4
- package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
- package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
- package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
- package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
- package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
- package/lib/vendor/blamejs/lib/scheduler.js +8 -1
- package/lib/vendor/blamejs/lib/security-assert.js +6 -6
- package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
- package/lib/vendor/blamejs/lib/self-update.js +517 -87
- package/lib/vendor/blamejs/lib/server-timing.js +2 -4
- package/lib/vendor/blamejs/lib/session.js +34 -12
- package/lib/vendor/blamejs/lib/sql.js +15 -1
- package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
- package/lib/vendor/blamejs/lib/static.js +55 -13
- package/lib/vendor/blamejs/lib/storage.js +8 -2
- package/lib/vendor/blamejs/lib/subject.js +6 -1
- package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
- package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
- package/lib/vendor/blamejs/lib/tsa.js +34 -13
- package/lib/vendor/blamejs/lib/uri-template.js +8 -1
- package/lib/vendor/blamejs/lib/vault/index.js +13 -0
- package/lib/vendor/blamejs/lib/vc.js +44 -5
- package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
- package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
- package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
- package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
- package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
- package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
- package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
- package/lib/vendor/blamejs/lib/watcher.js +89 -17
- package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
- package/lib/vendor/blamejs/lib/webhook.js +12 -2
- package/lib/vendor/blamejs/lib/ws-client.js +32 -1
- package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
- package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
- package/lib/vendor/blamejs/package-lock.json +2 -2
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
- package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
- package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
- package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
- package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
- package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
- package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
- package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
- package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
- package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
- package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
- package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
- package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
- package/lib/vendor/blamejs/socket.yml +94 -0
- package/lib/vendor/blamejs/test/00-primitives.js +605 -0
- package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
- package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
- package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
- package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
- package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
- package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
- package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
- package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
- package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
- package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
- package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
- package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
- package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
- package/lib/vendor/blamejs/test/smoke.js +2 -0
- package/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
- package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
- package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
- package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
- package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
- package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
- package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
- package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
- package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
- package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
- package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
- package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
- package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
- package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
- package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
- package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
|
@@ -0,0 +1,582 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
/**
|
|
5
|
+
* b.template — the eval-free server-side HTML template engine.
|
|
6
|
+
*
|
|
7
|
+
* escapeHtml has its own dedicated pin (template-escape-html.test.js); this
|
|
8
|
+
* file exercises the render/compile machinery and — the point of the file —
|
|
9
|
+
* the error / adversarial / defensive / option-default branches that the
|
|
10
|
+
* happy-path examples never reach: path-containment rejection, unterminated
|
|
11
|
+
* and malformed tags, the expression-grammar parse errors, the eval-time
|
|
12
|
+
* guards (own-property-only member access, call-of-non-function), the
|
|
13
|
+
* string-source (renderString) byte cap + resolve-callback contract, extends
|
|
14
|
+
* / partial recursion caps, cache/reset behavior, precompileAll boot
|
|
15
|
+
* validation, and the create() opt validation (viewsDir, sandbox opts).
|
|
16
|
+
*
|
|
17
|
+
* The XSS boundary is asserted throughout: {{ expr }} output is HTML-escaped,
|
|
18
|
+
* {{{ raw }}} is not, and injection-shaped data lands escaped in the output.
|
|
19
|
+
*
|
|
20
|
+
* Run standalone: `node test/layer-0-primitives/template.test.js`
|
|
21
|
+
* Or via smoke: `node test/smoke.js`
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
var helpers = require("../helpers");
|
|
25
|
+
var b = helpers.b;
|
|
26
|
+
var fs = helpers.fs;
|
|
27
|
+
var os = helpers.os;
|
|
28
|
+
var path = helpers.path;
|
|
29
|
+
var check = helpers.check;
|
|
30
|
+
|
|
31
|
+
var NUL = String.fromCharCode(0);
|
|
32
|
+
|
|
33
|
+
// ---- tiny local fixtures ----
|
|
34
|
+
|
|
35
|
+
function _mkdir() {
|
|
36
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-template-"));
|
|
37
|
+
}
|
|
38
|
+
function _write(dir, rel, content) {
|
|
39
|
+
var abs = path.join(dir, rel);
|
|
40
|
+
fs.mkdirSync(path.dirname(abs), { recursive: true });
|
|
41
|
+
fs.writeFileSync(abs, content);
|
|
42
|
+
}
|
|
43
|
+
function _rm(dir) { fs.rmSync(dir, { recursive: true, force: true }); }
|
|
44
|
+
|
|
45
|
+
// A file-backed engine seeded with a { relPath -> content } map.
|
|
46
|
+
function _fileEngine(files, opts) {
|
|
47
|
+
var dir = _mkdir();
|
|
48
|
+
Object.keys(files || {}).forEach(function (rel) { _write(dir, rel, files[rel]); });
|
|
49
|
+
var engine = b.template.create(Object.assign({ viewsDir: dir }, opts || {}));
|
|
50
|
+
return { dir: dir, engine: engine, cleanup: function () { _rm(dir); } };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function _expectThrows(label, fn, substr) {
|
|
54
|
+
var threw = null;
|
|
55
|
+
try { fn(); } catch (e) { threw = e; }
|
|
56
|
+
check(label + " — throws", threw !== null);
|
|
57
|
+
if (substr && threw) {
|
|
58
|
+
check(label + " — message contains " + JSON.stringify(substr),
|
|
59
|
+
String(threw.message).indexOf(substr) !== -1);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ============================================================
|
|
64
|
+
// Happy-path render (files) — the baseline the error branches sit around
|
|
65
|
+
// ============================================================
|
|
66
|
+
|
|
67
|
+
function testFileRenderHappyPathEscapes() {
|
|
68
|
+
var ctx = _fileEngine({
|
|
69
|
+
"page.html":
|
|
70
|
+
"<h1>{{ title }}</h1>" +
|
|
71
|
+
"{% if show %}<p>{{ body }}</p>{% else %}<p>hidden</p>{% endif %}" +
|
|
72
|
+
"<ul>{% for item in items %}<li>{{ item.name }}</li>{% endfor %}</ul>" +
|
|
73
|
+
"<footer>{{{ rawHtml }}}</footer>",
|
|
74
|
+
});
|
|
75
|
+
try {
|
|
76
|
+
var out = ctx.engine.render("page", {
|
|
77
|
+
title: "<script>alert(1)</script>",
|
|
78
|
+
show: true,
|
|
79
|
+
body: "a & b",
|
|
80
|
+
items: [{ name: "<b>x</b>" }, { name: "y'z" }],
|
|
81
|
+
rawHtml: "<em>trusted</em>",
|
|
82
|
+
});
|
|
83
|
+
// {{ }} escapes the five attack chars; {{{ }}} passes raw.
|
|
84
|
+
check("title HTML-escaped in {{ }}",
|
|
85
|
+
out.indexOf("<h1><script>alert(1)</script></h1>") !== -1);
|
|
86
|
+
check("if-branch body escaped", out.indexOf("<p>a & b</p>") !== -1);
|
|
87
|
+
check("for-loop escapes each item",
|
|
88
|
+
out.indexOf("<li><b>x</b></li>") !== -1 &&
|
|
89
|
+
out.indexOf("<li>y'z</li>") !== -1);
|
|
90
|
+
check("{{{ raw }}} not escaped", out.indexOf("<footer><em>trusted</em></footer>") !== -1);
|
|
91
|
+
|
|
92
|
+
// else-branch + no-else (elseBody null) paths.
|
|
93
|
+
var elseOut = ctx.engine.render("page", { title: "t", show: false, body: "x", items: [], rawHtml: "" });
|
|
94
|
+
check("else branch renders when cond false", elseOut.indexOf("<p>hidden</p>") !== -1);
|
|
95
|
+
check("empty for-loop emits nothing", elseOut.indexOf("<ul></ul>") !== -1);
|
|
96
|
+
check("engine exposes resolved viewsDir", ctx.engine.viewsDir === path.resolve(ctx.dir));
|
|
97
|
+
check("engine exposes escapeHtml", ctx.engine.escapeHtml === b.template.escapeHtml);
|
|
98
|
+
} finally {
|
|
99
|
+
ctx.cleanup();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// ============================================================
|
|
104
|
+
// Path containment — _resolveViewPath rejections
|
|
105
|
+
// ============================================================
|
|
106
|
+
|
|
107
|
+
function testViewPathContainment() {
|
|
108
|
+
var ctx = _fileEngine({ "index.html": "ok" });
|
|
109
|
+
try {
|
|
110
|
+
check("valid view renders", ctx.engine.render("index") === "ok");
|
|
111
|
+
_expectThrows("view name with ..", function () { ctx.engine.render("../secret"); },
|
|
112
|
+
"forbidden character");
|
|
113
|
+
_expectThrows("view name with NUL", function () { ctx.engine.render("foo" + NUL + "bar"); },
|
|
114
|
+
"forbidden character");
|
|
115
|
+
_expectThrows("empty view name", function () { ctx.engine.render(""); },
|
|
116
|
+
"non-empty string");
|
|
117
|
+
_expectThrows("non-string view name", function () { ctx.engine.render(123); },
|
|
118
|
+
"non-empty string");
|
|
119
|
+
_expectThrows("missing view", function () { ctx.engine.render("does-not-exist"); },
|
|
120
|
+
"view not found");
|
|
121
|
+
// Absolute view name (no "..") resolves outside viewsDir → escape guard.
|
|
122
|
+
var escapee = path.parse(ctx.dir).root + "blamejs_escape_probe";
|
|
123
|
+
_expectThrows("absolute name escapes viewsDir", function () { ctx.engine.render(escapee); },
|
|
124
|
+
"escapes viewsDir");
|
|
125
|
+
} finally {
|
|
126
|
+
ctx.cleanup();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ============================================================
|
|
131
|
+
// Partials — inlining, missing → empty, recursion cap
|
|
132
|
+
// ============================================================
|
|
133
|
+
|
|
134
|
+
function testPartials() {
|
|
135
|
+
var ctx = _fileEngine({
|
|
136
|
+
"host.html": "top {{> header }} mid {{> missing }} bot",
|
|
137
|
+
"partials/header.html": "<nav>{{ label }}</nav>",
|
|
138
|
+
"loop-host.html": "{{> loopy }}",
|
|
139
|
+
"partials/loopy.html": "x{{> loopy }}",
|
|
140
|
+
});
|
|
141
|
+
try {
|
|
142
|
+
var out = ctx.engine.render("host", { label: "a<b" });
|
|
143
|
+
check("present partial inlined + inner expr escaped",
|
|
144
|
+
out === "top <nav>a<b</nav> mid bot");
|
|
145
|
+
check("missing partial inlines empty (no crash)", out.indexOf("mid bot") !== -1);
|
|
146
|
+
_expectThrows("self-referential partial hits recursion cap",
|
|
147
|
+
function () { ctx.engine.render("loop-host", {}); },
|
|
148
|
+
"partial recursion depth exceeded");
|
|
149
|
+
} finally {
|
|
150
|
+
ctx.cleanup();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// ============================================================
|
|
155
|
+
// Layout inheritance — extends/block, override, cycle, misplacement
|
|
156
|
+
// ============================================================
|
|
157
|
+
|
|
158
|
+
function testLayoutInheritance() {
|
|
159
|
+
var ctx = _fileEngine({
|
|
160
|
+
"child.html": '{% extends "layout" %}{% block content %}<i>{{ who }}</i>{% endblock %}',
|
|
161
|
+
"layout.html": "<main>{% block content %}default{% endblock %}<span>{% block side %}s{% endblock %}</span></main>",
|
|
162
|
+
// extends cycle a→b→a
|
|
163
|
+
"cyc-a.html": '{% extends "cyc-b" %}',
|
|
164
|
+
"cyc-b.html": '{% extends "cyc-a" %}',
|
|
165
|
+
});
|
|
166
|
+
try {
|
|
167
|
+
var out = ctx.engine.render("child", { who: "a&b" });
|
|
168
|
+
check("child block overrides parent placeholder + escapes",
|
|
169
|
+
out.indexOf("<main><i>a&b</i>") !== -1);
|
|
170
|
+
check("un-overridden parent block keeps its default",
|
|
171
|
+
out.indexOf("<span>s</span>") !== -1);
|
|
172
|
+
_expectThrows("extends cycle hits inheritance depth cap",
|
|
173
|
+
function () { ctx.engine.render("cyc-a", {}); },
|
|
174
|
+
"layout inheritance depth exceeded");
|
|
175
|
+
_expectThrows("{% extends %} not at top is rejected",
|
|
176
|
+
function () { ctx.engine.renderString('hi {% extends "layout" %}'); },
|
|
177
|
+
"must be the first non-whitespace");
|
|
178
|
+
} finally {
|
|
179
|
+
ctx.cleanup();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// ============================================================
|
|
184
|
+
// String-source path — renderString / compileString byte cap + resolve
|
|
185
|
+
// ============================================================
|
|
186
|
+
|
|
187
|
+
function testStringSource() {
|
|
188
|
+
var engine = b.template.create(); // no viewsDir → string-only engine
|
|
189
|
+
|
|
190
|
+
// Happy: escaping still applies on the string path.
|
|
191
|
+
check("renderString escapes {{ }}",
|
|
192
|
+
engine.renderString("<p>{{ v }}</p>", { v: "<x>" }) === "<p><x></p>");
|
|
193
|
+
check("renderString {{{ }}} raw on string path",
|
|
194
|
+
engine.renderString("{{{ v }}}", { v: "<x>" }) === "<x>");
|
|
195
|
+
check("renderString plain literal (no tags)",
|
|
196
|
+
engine.renderString("just text") === "just text");
|
|
197
|
+
|
|
198
|
+
// Source-type + byte cap.
|
|
199
|
+
_expectThrows("compileString rejects non-string source",
|
|
200
|
+
function () { engine.compileString(123); }, "must be a string");
|
|
201
|
+
_expectThrows("renderString honors opts.maxBytes cap",
|
|
202
|
+
function () { engine.renderString("hello", {}, { maxBytes: 3 }); },
|
|
203
|
+
"exceeds maxBytes=3");
|
|
204
|
+
// Default 256 KiB cap on hostile string input.
|
|
205
|
+
_expectThrows("renderString hits default byte cap on oversized input",
|
|
206
|
+
function () { engine.renderString("x".repeat(300000)); }, "exceeds maxBytes");
|
|
207
|
+
|
|
208
|
+
// resolve-callback contract.
|
|
209
|
+
_expectThrows("opts.resolve must be a function",
|
|
210
|
+
function () { engine.renderString("x", {}, { resolve: 123 }); },
|
|
211
|
+
"resolve must be a function");
|
|
212
|
+
_expectThrows("extends on string path without resolve throws",
|
|
213
|
+
function () { engine.renderString('{% extends "base" %}'); },
|
|
214
|
+
"needs opts.resolve");
|
|
215
|
+
|
|
216
|
+
var resolveLayout = function () {
|
|
217
|
+
return "<main>{% block body %}def{% endblock %}</main>";
|
|
218
|
+
};
|
|
219
|
+
check("extends resolves through opts.resolve",
|
|
220
|
+
engine.renderString('{% extends "base" %}{% block body %}<b>{{ w }}</b>{% endblock %}',
|
|
221
|
+
{ w: "a&b" }, { resolve: resolveLayout }) ===
|
|
222
|
+
"<main><b>a&b</b></main>");
|
|
223
|
+
|
|
224
|
+
// Two-arg disambiguation: renderString(source, { resolve }) — the middle arg
|
|
225
|
+
// is the opts object (data omitted) when it carries a function `resolve`.
|
|
226
|
+
check("renderString(source, {resolve}) treats 2nd arg as opts",
|
|
227
|
+
engine.renderString('{% extends "b" %}{% block c %}Z{% endblock %}',
|
|
228
|
+
{ resolve: function () { return "{% block c %}d{% endblock %}"; } }) === "Z");
|
|
229
|
+
|
|
230
|
+
// Missing partial on the string path (resolve → null) inlines empty.
|
|
231
|
+
check("string-path missing partial inlines empty",
|
|
232
|
+
engine.renderString("a{{> p }}b", {}, { resolve: function () { return null; } }) === "ab");
|
|
233
|
+
// Partial on the string path with NO resolve configured also inlines empty
|
|
234
|
+
// (loadPartial returns null when resolve is absent — no throw, unlike extends).
|
|
235
|
+
check("string-path partial without resolve inlines empty",
|
|
236
|
+
engine.renderString("a{{> p }}b") === "ab");
|
|
237
|
+
check("string-path present partial inlined",
|
|
238
|
+
engine.renderString("a{{> p }}b", {}, { resolve: function () { return "X"; } }) === "aXb");
|
|
239
|
+
|
|
240
|
+
// The per-resolved-source byte cap (_capped) fires on oversized layout/partial.
|
|
241
|
+
_expectThrows("resolved layout over cap rejected",
|
|
242
|
+
function () {
|
|
243
|
+
engine.renderString('{% extends "big" %}{% block b %}x{% endblock %}',
|
|
244
|
+
{}, { maxBytes: 80, resolve: function () { return "{% block b %}" + "y".repeat(500) + "{% endblock %}"; } });
|
|
245
|
+
}, "resolved layout");
|
|
246
|
+
_expectThrows("resolved partial over cap rejected",
|
|
247
|
+
function () {
|
|
248
|
+
engine.renderString("a{{> big }}b",
|
|
249
|
+
{}, { maxBytes: 80, resolve: function () { return "y".repeat(500); } });
|
|
250
|
+
}, "resolved partial");
|
|
251
|
+
|
|
252
|
+
// String-path extends / partial recursion caps.
|
|
253
|
+
_expectThrows("string extends cycle hits cap",
|
|
254
|
+
function () { engine.renderString('{% extends "a" %}', {}, { resolve: function () { return '{% extends "a" %}'; } }); },
|
|
255
|
+
"layout inheritance depth exceeded");
|
|
256
|
+
_expectThrows("string partial cycle hits cap",
|
|
257
|
+
function () { engine.renderString("{{> p }}", {}, { resolve: function () { return "{{> p }}"; } }); },
|
|
258
|
+
"partial recursion depth exceeded");
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ============================================================
|
|
262
|
+
// Block tokenizer / parser structural errors
|
|
263
|
+
// ============================================================
|
|
264
|
+
|
|
265
|
+
function testTokenizeAndParseErrors() {
|
|
266
|
+
var e = b.template.create();
|
|
267
|
+
_expectThrows("unterminated {{ }}", function () { e.renderString("a {{ x"); }, "unterminated {{ expression }}");
|
|
268
|
+
_expectThrows("unterminated {{{ }}}", function () { e.renderString("a {{{ x"); }, "unterminated {{{ raw }}}");
|
|
269
|
+
_expectThrows("unterminated {% %}", function () { e.renderString("a {% x"); }, "unterminated {% directive %}");
|
|
270
|
+
|
|
271
|
+
_expectThrows("malformed directive (non-alpha head)",
|
|
272
|
+
function () { e.renderString("{% 123 %}"); }, "malformed directive");
|
|
273
|
+
_expectThrows("unknown directive",
|
|
274
|
+
function () { e.renderString("{% frobnicate %}"); }, "unknown directive");
|
|
275
|
+
_expectThrows("invalid for syntax (no 'in')",
|
|
276
|
+
function () { e.renderString("{% for x %}{% endfor %}"); }, "invalid for syntax");
|
|
277
|
+
_expectThrows("truncated if → unexpected end of template",
|
|
278
|
+
function () { e.renderString("{% if a %}yes"); }, "unexpected end of template");
|
|
279
|
+
_expectThrows("truncated for → unexpected end of template",
|
|
280
|
+
function () { e.renderString("{% for x in xs %}body"); }, "unexpected end of template");
|
|
281
|
+
|
|
282
|
+
// Stray {% block %} outside an extends is accepted (default already inlined).
|
|
283
|
+
check("stray block passes through as no-op",
|
|
284
|
+
e.renderString("{% block b %}hi{% endblock %}") === "hi");
|
|
285
|
+
// An UNPAIRED block / endblock survives the pre-parse block substitution and
|
|
286
|
+
// reaches the parser's block/endblock pass-through (a no-op there).
|
|
287
|
+
check("stray unpaired {% endblock %} is a parser no-op",
|
|
288
|
+
e.renderString("x{% endblock %}y") === "xy");
|
|
289
|
+
check("stray unclosed {% block %} open is a parser no-op",
|
|
290
|
+
e.renderString("a{% block z %}b") === "ab");
|
|
291
|
+
check("if/else/endif renders then-branch",
|
|
292
|
+
e.renderString("{% if a %}Y{% else %}N{% endif %}", { a: 1 }) === "Y");
|
|
293
|
+
check("if with no else and false cond → empty (elseBody null)",
|
|
294
|
+
e.renderString("{% if a %}Y{% endif %}", { a: 0 }) === "");
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// ============================================================
|
|
298
|
+
// Expression grammar — operators + parse errors
|
|
299
|
+
// ============================================================
|
|
300
|
+
|
|
301
|
+
function testExpressionGrammar() {
|
|
302
|
+
var e = b.template.create();
|
|
303
|
+
function r(src, data) { return e.renderString("{{ " + src + " }}", data || {}); }
|
|
304
|
+
|
|
305
|
+
check("addition", r("1 + 2") === "3");
|
|
306
|
+
check("subtraction", r("10 - 3") === "7");
|
|
307
|
+
check("multiplication", r("2 * 4") === "8");
|
|
308
|
+
check("division", r("9 / 3") === "3");
|
|
309
|
+
check("paren precedence", r("(1 + 2) * 3") === "9");
|
|
310
|
+
check("unary minus", r("-n", { n: 5 }) === "-5");
|
|
311
|
+
check("unary not", r("!flag", { flag: false }) === "true");
|
|
312
|
+
check("logical and", r("a && b", { a: true, b: "kept" }) === "kept");
|
|
313
|
+
check("logical or", r("a || b", { a: 0, b: "fallback" }) === "fallback");
|
|
314
|
+
check("loose ==", r("a == b", { a: 1, b: "1" }) === "true");
|
|
315
|
+
check("strict ===", r("a === b", { a: 1, b: "1" }) === "false");
|
|
316
|
+
check("loose !=", r("a != b", { a: 1, b: 2 }) === "true");
|
|
317
|
+
check("strict !==", r("a !== b", { a: 1, b: 1 }) === "false");
|
|
318
|
+
check("less than", r("a < b", { a: 1, b: 2 }) === "true");
|
|
319
|
+
check("less-equal", r("a <= b", { a: 2, b: 2 }) === "true");
|
|
320
|
+
check("greater than", r("a > b", { a: 3, b: 2 }) === "true");
|
|
321
|
+
check("greater-equal", r("a >= b", { a: 2, b: 3 }) === "false");
|
|
322
|
+
check("ternary", r("c ? 'yes' : 'no'", { c: true }) === "yes");
|
|
323
|
+
check("boolean literal true", r("true") === "true");
|
|
324
|
+
check("boolean literal false", r("false") === "false");
|
|
325
|
+
check("null literal → empty", r("null") === "");
|
|
326
|
+
check("number literal", r("42") === "42");
|
|
327
|
+
check("decimal literal", r(".5") === "0.5");
|
|
328
|
+
|
|
329
|
+
// String escape sequences in the expression tokenizer (raw output so the
|
|
330
|
+
// control chars survive, not HTML-escaped).
|
|
331
|
+
check("string \\n escape", e.renderString('{{{ "a\\nb" }}}') === "a\nb");
|
|
332
|
+
check("string \\t escape", e.renderString('{{{ "a\\tb" }}}') === "a\tb");
|
|
333
|
+
check("string \\r escape", e.renderString('{{{ "a\\rb" }}}') === "a\rb");
|
|
334
|
+
check("string \\\\ escape", e.renderString('{{{ "a\\\\b" }}}') === "a\\b");
|
|
335
|
+
check("unknown string escape passes char through",
|
|
336
|
+
e.renderString('{{{ "a\\qb" }}}') === "aqb");
|
|
337
|
+
|
|
338
|
+
// Parse-time errors.
|
|
339
|
+
_expectThrows("empty expression", function () { r(""); }, "unexpected end of expression");
|
|
340
|
+
_expectThrows("member without ident", function () { r("a."); }, "expected IDENT");
|
|
341
|
+
// expect() names the actually-present token (not just EOF) — `.` followed by
|
|
342
|
+
// a non-identifier reports the token: an operator carries its op ("OP:+"),
|
|
343
|
+
// a value token carries just its kind ("STRING").
|
|
344
|
+
_expectThrows("member followed by operator names the op",
|
|
345
|
+
function () { r("a.+"); }, "got OP:+");
|
|
346
|
+
_expectThrows("member followed by value token names its kind",
|
|
347
|
+
function () { r('a."str"'); }, "got STRING");
|
|
348
|
+
_expectThrows("unclosed computed idx", function () { r("a[0"); }, "expected OP(])");
|
|
349
|
+
_expectThrows("unclosed paren group", function () { r("(1"); }, "expected OP(");
|
|
350
|
+
_expectThrows("unterminated call arg-list", function () { r("f("); }, "expected OP(");
|
|
351
|
+
_expectThrows("unexpected token (bare op)", function () { r(")"); }, "unexpected token in expression");
|
|
352
|
+
_expectThrows("trailing tokens (ident)", function () { r("a b"); }, "trailing tokens");
|
|
353
|
+
// Trailing token that IS an operator reports its op in the message.
|
|
354
|
+
_expectThrows("trailing operator token names its op", function () { r("a ]"); }, "OP:]");
|
|
355
|
+
_expectThrows("unterminated string", function () { r('"abc'); }, "unterminated string");
|
|
356
|
+
_expectThrows("unexpected char in expr", function () { r("@"); }, "unexpected character in expression");
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// ============================================================
|
|
360
|
+
// Expression evaluator — member guards, calls, this-binding
|
|
361
|
+
// ============================================================
|
|
362
|
+
|
|
363
|
+
function testEvalSemantics() {
|
|
364
|
+
var e = b.template.create();
|
|
365
|
+
function r(src, data) { return e.renderString("{{ " + src + " }}", data || {}); }
|
|
366
|
+
|
|
367
|
+
// Member on null/undefined → undefined → empty (no crash).
|
|
368
|
+
check("member on missing base → empty", r("a.b.c", {}) === "");
|
|
369
|
+
check("computed member reads own prop",
|
|
370
|
+
r("obj[key]", { obj: { hit: "yes" }, key: "hit" }) === "yes");
|
|
371
|
+
check("array .length is legitimate", r("arr.length", { arr: [1, 2, 3] }) === "3");
|
|
372
|
+
check("array non-index member miss → empty (own-prop guard)",
|
|
373
|
+
r("arr.missing", { arr: [1, 2, 3] }) === "");
|
|
374
|
+
|
|
375
|
+
// Prototype-chain access is blocked — only own props resolve.
|
|
376
|
+
check("obj.constructor is undefined (not the Function)",
|
|
377
|
+
r("obj.constructor", { obj: { a: 1 } }) === "");
|
|
378
|
+
check("obj.__proto__ is undefined (own-prop guard)",
|
|
379
|
+
r("obj.__proto__", { obj: { a: 1 } }) === "");
|
|
380
|
+
check("obj.toString is undefined (inherited, blocked)",
|
|
381
|
+
r("obj.toString", { obj: { a: 1 } }) === "");
|
|
382
|
+
|
|
383
|
+
// Operator-provided helper calls, with `this` bound to the receiver.
|
|
384
|
+
check("helper call from data scope",
|
|
385
|
+
r("fmt(x)", { fmt: function (n) { return "n=" + n; }, x: 7 }) === "n=7");
|
|
386
|
+
check("call with a leading unary-minus arg parses",
|
|
387
|
+
r("fmt(-1)", { fmt: function (n) { return "n=" + n; } }) === "n=-1");
|
|
388
|
+
check("multi-argument call (comma-separated arg list)",
|
|
389
|
+
r("cat(a, b, c)", { cat: function (x, y, z) { return x + y + z; }, a: "p", b: "q", c: "r" }) === "pqr");
|
|
390
|
+
check("method call binds this to receiver",
|
|
391
|
+
r("obj.greet()", { obj: { who: "Ada", greet: function () { return this.who; } } }) === "Ada");
|
|
392
|
+
_expectThrows("calling a non-function (identifier) throws + names it",
|
|
393
|
+
function () { r("notfn()", { notfn: "a string" }); }, "cannot call non-function: notfn");
|
|
394
|
+
_expectThrows("calling a non-function member names the property",
|
|
395
|
+
function () { r("o.x()", { o: { x: "not a fn" } }); }, "cannot call non-function: x");
|
|
396
|
+
_expectThrows("calling a non-function non-name callee reports <expr>",
|
|
397
|
+
function () { r("(1)()", {}); }, "cannot call non-function: <expr>");
|
|
398
|
+
|
|
399
|
+
// Ternary false-branch selects the else expression.
|
|
400
|
+
check("ternary false branch selects else",
|
|
401
|
+
r("c ? 'yes' : 'no'", { c: false }) === "no");
|
|
402
|
+
|
|
403
|
+
// for-loop over a non-array-like (a number) iterates nothing.
|
|
404
|
+
check("for over non-iterable emits nothing",
|
|
405
|
+
e.renderString("{% for x in n %}!{% endfor %}", { n: 5 }) === "");
|
|
406
|
+
// for over a string is length-indexable → iterates chars.
|
|
407
|
+
check("for over string iterates code units",
|
|
408
|
+
e.renderString("{% for c in s %}{{ c }}{% endfor %}", { s: "ab" }) === "ab");
|
|
409
|
+
// Raw expr resolving to null/undefined emits nothing.
|
|
410
|
+
check("raw expr null → empty", e.renderString("[{{{ missing }}}]") === "[]");
|
|
411
|
+
// Escaped expr resolving to undefined emits empty string.
|
|
412
|
+
check("escaped expr undefined → empty", e.renderString("[{{ missing }}]") === "[]");
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// ============================================================
|
|
416
|
+
// Engine option validation + cache/reset + precompileAll
|
|
417
|
+
// ============================================================
|
|
418
|
+
|
|
419
|
+
function testCreateOptsAndCache() {
|
|
420
|
+
// Unknown opt rejected by validateOpts.
|
|
421
|
+
_expectThrows("unknown create opt rejected",
|
|
422
|
+
function () { b.template.create({ bogusOption: 1 }); }, "unknown option");
|
|
423
|
+
// Nonexistent viewsDir rejected.
|
|
424
|
+
_expectThrows("nonexistent viewsDir rejected",
|
|
425
|
+
function () { b.template.create({ viewsDir: path.join(os.tmpdir(), "blamejs-no-such-" + Date.now()) }); },
|
|
426
|
+
"viewsDir does not exist");
|
|
427
|
+
|
|
428
|
+
// String-only engine (no viewsDir) → file APIs refuse.
|
|
429
|
+
var stringOnly = b.template.create();
|
|
430
|
+
_expectThrows("render() without viewsDir refuses",
|
|
431
|
+
function () { stringOnly.render("x"); }, "viewsDir not configured");
|
|
432
|
+
_expectThrows("compile() without viewsDir refuses",
|
|
433
|
+
function () { stringOnly.compile("x"); }, "viewsDir not configured");
|
|
434
|
+
_expectThrows("precompileAll() without viewsDir refuses",
|
|
435
|
+
function () { stringOnly.precompileAll(); }, "viewsDir not configured");
|
|
436
|
+
|
|
437
|
+
// Custom escapeHtml override is used by {{ }} interpolation.
|
|
438
|
+
var ctx = _fileEngine({ "v.html": "[{{ x }}]" }, { escapeHtml: function () { return "REPLACED"; } });
|
|
439
|
+
try {
|
|
440
|
+
check("custom escapeHtml override applied", ctx.engine.render("v", { x: "<b>" }) === "[REPLACED]");
|
|
441
|
+
check("engine.escapeHtml is the override", ctx.engine.escapeHtml("anything") === "REPLACED");
|
|
442
|
+
} finally {
|
|
443
|
+
ctx.cleanup();
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// cache ON (default): edit-after-compile is NOT seen until reset().
|
|
447
|
+
var cached = _fileEngine({ "p.html": "v1" });
|
|
448
|
+
try {
|
|
449
|
+
check("first render v1", cached.engine.render("p") === "v1");
|
|
450
|
+
_write(cached.dir, "p.html", "v2");
|
|
451
|
+
check("cache-on: stale AST still returns v1", cached.engine.render("p") === "v1");
|
|
452
|
+
cached.engine.reset();
|
|
453
|
+
check("reset() drops cache → v2", cached.engine.render("p") === "v2");
|
|
454
|
+
} finally {
|
|
455
|
+
cached.cleanup();
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// cache OFF: every render re-reads the file.
|
|
459
|
+
var live = _fileEngine({ "p.html": "a" }, { cache: false });
|
|
460
|
+
try {
|
|
461
|
+
check("cache-off first read a", live.engine.render("p") === "a");
|
|
462
|
+
_write(live.dir, "p.html", "b");
|
|
463
|
+
check("cache-off sees edit immediately → b", live.engine.render("p") === "b");
|
|
464
|
+
} finally {
|
|
465
|
+
live.cleanup();
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function testPrecompileAll() {
|
|
470
|
+
var ok = _fileEngine({
|
|
471
|
+
"a.html": "{{ x }}",
|
|
472
|
+
"sub/b.html": "{% if y %}z{% endif %}",
|
|
473
|
+
});
|
|
474
|
+
try {
|
|
475
|
+
var list = ok.engine.precompileAll();
|
|
476
|
+
check("precompileAll returns every compiled view", list.length === 2);
|
|
477
|
+
check("precompileAll walks subdirs",
|
|
478
|
+
list.indexOf("a") !== -1 && list.indexOf("sub/b") !== -1);
|
|
479
|
+
} finally {
|
|
480
|
+
ok.cleanup();
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
var bad = _fileEngine({ "broken.html": "{% frobnicate %}" });
|
|
484
|
+
try {
|
|
485
|
+
var threw = null;
|
|
486
|
+
try { bad.engine.precompileAll(); } catch (err) { threw = err; }
|
|
487
|
+
check("precompileAll surfaces a parse error", threw !== null);
|
|
488
|
+
check("wrapped error names the offending view",
|
|
489
|
+
threw && threw.viewName === "broken" &&
|
|
490
|
+
String(threw.message).indexOf("precompile failed for view 'broken'") !== -1);
|
|
491
|
+
check("wrapped error keeps the underlying cause", threw && threw.cause instanceof Error);
|
|
492
|
+
} finally {
|
|
493
|
+
bad.cleanup();
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// ============================================================
|
|
498
|
+
// Sandbox-helper opt validation (construction only — no worker spun)
|
|
499
|
+
// ============================================================
|
|
500
|
+
|
|
501
|
+
function testSandboxHelperValidation() {
|
|
502
|
+
var dir = _mkdir();
|
|
503
|
+
try {
|
|
504
|
+
_expectThrows("sandboxHelpers must be an object (array rejected)",
|
|
505
|
+
function () { b.template.create({ viewsDir: dir, sandbox: true, sandboxHelpers: [] }); },
|
|
506
|
+
"sandboxHelpers must be");
|
|
507
|
+
_expectThrows("sandboxOpts must be an object (array rejected)",
|
|
508
|
+
function () { b.template.create({ viewsDir: dir, sandbox: true, sandboxHelpers: {}, sandboxOpts: [] }); },
|
|
509
|
+
"sandboxOpts must be an object");
|
|
510
|
+
_expectThrows("helper source must be a non-empty string (empty rejected)",
|
|
511
|
+
function () { b.template.create({ viewsDir: dir, sandbox: true, sandboxHelpers: { h: "" } }); },
|
|
512
|
+
"must be a non-empty string");
|
|
513
|
+
_expectThrows("helper source must be a string (number rejected)",
|
|
514
|
+
function () { b.template.create({ viewsDir: dir, sandbox: true, sandboxHelpers: { h: 123 } }); },
|
|
515
|
+
"must be a non-empty string");
|
|
516
|
+
// sandbox:true with sandboxHelpers omitted defaults to an empty helper set.
|
|
517
|
+
var noHelpers = b.template.create({ viewsDir: dir, sandbox: true });
|
|
518
|
+
check("sandbox true without sandboxHelpers still builds",
|
|
519
|
+
noHelpers && typeof noHelpers.render === "function");
|
|
520
|
+
// Valid sandbox config builds the engine (helper is wrapped, not run).
|
|
521
|
+
var engine = b.template.create({
|
|
522
|
+
viewsDir: dir, sandbox: true,
|
|
523
|
+
sandboxHelpers: { upper: "return String(input).toUpperCase();" },
|
|
524
|
+
sandboxOpts: { timeoutMs: 100 },
|
|
525
|
+
});
|
|
526
|
+
check("valid sandbox config yields an engine", engine && typeof engine.render === "function");
|
|
527
|
+
} finally {
|
|
528
|
+
_rm(dir);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
// ============================================================
|
|
533
|
+
// Module-level render() + lazy default engine (<cwd>/views)
|
|
534
|
+
// ============================================================
|
|
535
|
+
|
|
536
|
+
function testModuleRenderDefault() {
|
|
537
|
+
var origCwd = process.cwd();
|
|
538
|
+
var base = fs.mkdtempSync(path.join(os.tmpdir(), "blamejs-template-cwd-"));
|
|
539
|
+
try {
|
|
540
|
+
// No <cwd>/views → the lazy default refuses.
|
|
541
|
+
b.template._resetDefaultForTest();
|
|
542
|
+
process.chdir(base);
|
|
543
|
+
_expectThrows("module render without <cwd>/views throws",
|
|
544
|
+
function () { b.template.render("welcome", {}); }, "which doesn't exist");
|
|
545
|
+
|
|
546
|
+
// Create <cwd>/views and render through the module singleton.
|
|
547
|
+
b.template._resetDefaultForTest();
|
|
548
|
+
fs.mkdirSync(path.join(base, "views"));
|
|
549
|
+
fs.writeFileSync(path.join(base, "views", "welcome.html"), "<h1>Hi {{ name }}</h1>");
|
|
550
|
+
var out = b.template.render("welcome", { name: "<b>" });
|
|
551
|
+
check("module render binds <cwd>/views + escapes", out === "<h1>Hi <b></h1>");
|
|
552
|
+
} finally {
|
|
553
|
+
b.template._resetDefaultForTest();
|
|
554
|
+
process.chdir(origCwd);
|
|
555
|
+
_rm(base);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// ============================================================
|
|
560
|
+
|
|
561
|
+
function run() {
|
|
562
|
+
testFileRenderHappyPathEscapes();
|
|
563
|
+
testViewPathContainment();
|
|
564
|
+
testPartials();
|
|
565
|
+
testLayoutInheritance();
|
|
566
|
+
testStringSource();
|
|
567
|
+
testTokenizeAndParseErrors();
|
|
568
|
+
testExpressionGrammar();
|
|
569
|
+
testEvalSemantics();
|
|
570
|
+
testCreateOptsAndCache();
|
|
571
|
+
testPrecompileAll();
|
|
572
|
+
testSandboxHelperValidation();
|
|
573
|
+
testModuleRenderDefault();
|
|
574
|
+
|
|
575
|
+
console.log("OK — template (" + helpers.getChecks() + " checks)");
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
module.exports = { run: run };
|
|
579
|
+
if (require.main === module) {
|
|
580
|
+
try { run(); process.exit(0); }
|
|
581
|
+
catch (e) { console.error("FAIL: " + (e && e.message)); process.exit(1); }
|
|
582
|
+
}
|