Skip to content

Fix CBOR decoder "keyDecoder is undefined" error with runtime patch #928

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 26 additions & 26 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,57 +85,57 @@
},
"dependencies": {
"@jsonjoy.com/base64": "^1.1.2",
"@jsonjoy.com/json-expression": "^1.0.0",
"@jsonjoy.com/json-pack": "^1.1.0",
"@jsonjoy.com/json-expression": "^1.1.0",
"@jsonjoy.com/json-pack": "^1.8.0",
"@jsonjoy.com/json-pointer": "^1.0.1",
"@jsonjoy.com/json-type": "^1.0.0",
"@jsonjoy.com/util": "^1.6.0",
"@jsonjoy.com/json-type": "^1.8.0",
"@jsonjoy.com/util": "^1.9.0",
"arg": "^5.0.2",
"hyperdyperid": "^1.2.0",
"nano-css": "^5.6.2",
"sonic-forest": "^1.2.0",
"sonic-forest": "^1.2.1",
"thingies": "^2.1.1",
"tree-dump": "^1.0.2",
"very-small-parser": "^1.13.0"
"tree-dump": "^1.0.3",
"very-small-parser": "^1.14.0"
},
"devDependencies": {
"@biomejs/biome": "^1.9.4",
"@biomejs/biome": "^2.1.3",
"@radix-ui/react-icons": "^1.3.1",
"@types/benchmark": "^2.1.5",
"@types/jest": "^29.5.12",
"@types/react": "^18.3.11",
"@types/react-dom": "^18.3.0",
"@types/jest": "^30.0.0",
"@types/react": "^19.1.9",
"@types/react-dom": "^19.1.7",
"benchmark": "^2.1.4",
"clipboard-copy": "^4.0.1",
"collaborative-editor": "^2.8.0",
"collaborative-input": "^1.6.1",
"collaborative-ui": "^1.6.0",
"collaborative-editor": "^2.9.0",
"collaborative-input": "^1.7.0",
"collaborative-ui": "^1.7.1",
"config-galore": "^1.0.0",
"editing-traces": "https://github.com/streamich/editing-traces#6494020428530a6e382378b98d1d7e31334e2d7b",
"fast-diff": "^1.3.0",
"fast-json-patch": "^3.1.1",
"html-webpack-plugin": "^5.6.0",
"jest": "^29.7.0",
"jest": "^30.0.5",
"json-crdt-traces": "https://github.com/streamich/json-crdt-traces#ec825401dc05cbb74b9e0b3c4d6527399f54d54d",
"json-logic-js": "^2.0.2",
"nano-theme": "^1.4.3",
"nice-ui": "^1.30.0",
"nano-theme": "^1.5.0",
"nice-ui": "^1.32.0",
"quill-delta": "^5.1.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react": "^19.1.1",
"react-dom": "^19.1.1",
"rxjs": "^7.8.2",
"ts-jest": "^29.4.0",
"ts-jest": "^29.4.1",
"ts-loader": "^9.5.2",
"ts-node": "^10.9.2",
"tslib": "^2.8.1",
"tslint": "^6.1.3",
"tslint-config-common": "^1.6.2",
"typescript": "^5.8.3",
"use-t": "^1.6.3",
"webpack": "^5.95.0",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^5.1.0",
"yjs": "^13.6.18"
"typescript": "^5.9.2",
"use-t": "^1.6.4",
"webpack": "^5.101.0",
"webpack-cli": "^6.0.1",
"webpack-dev-server": "^5.2.2",
"yjs": "^13.6.27"
},
"jest": {
"moduleFileExtensions": [
Expand Down
96 changes: 96 additions & 0 deletions src/__tests__/cbor-decoder-regression.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/**
* Regression test for CBOR decoder issue #925
*
* This test ensures that the CborDecoder can be instantiated and used correctly.
* It specifically tests for the "keyDecoder is undefined" issue that occurs when
* @jsonjoy.com/util uses problematic re-exports.
*
* Issue: https://github.com/streamich/json-joy/issues/925
* Root cause: tslib.__exportStar skips the default export when re-exporting modules
*/

import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder';
import {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder';

// Import the runtime patch to apply it for all tests in this file
import '../util/cbor-decoder-fix';

describe('CBOR decoder regression tests', () => {
describe('issue #925: keyDecoder undefined', () => {
it('should have keyDecoder defined after runtime patch is applied', () => {
const decoder = new CborDecoder();

// After the runtime patch, keyDecoder should be properly defined
expect(decoder.keyDecoder).toBeDefined();
expect(typeof decoder.keyDecoder).toBe('object');
expect(decoder.keyDecoder).not.toBeNull();
});

it('should encode and decode data correctly with patched decoder', () => {
const encoder = new CborEncoder();
const decoder = new CborDecoder();

const testData = {
hello: 'world',
number: 42,
nested: {
array: [1, 2, 3],
boolean: true
}
};

const encoded = encoder.encode(testData);
expect(encoded).toBeInstanceOf(Uint8Array);

const decoded = decoder.decode(encoded);
expect(decoded).toEqual(testData);
});

it('should handle string keys correctly (keyDecoder functionality)', () => {
const encoder = new CborEncoder();
const decoder = new CborDecoder();

// Test data with various string keys to ensure keyDecoder works
const testData = {
'short': 'value',
'longer_key_name': 'another_value',
'key_with_unicode_💀': 'emoji_value',
'key-with-dashes': 'dash_value'
};

const encoded = encoder.encode(testData);
const decoded = decoder.decode(encoded);

expect(decoded).toEqual(testData);

// Verify all keys are properly decoded
expect(Object.keys(decoded as object)).toEqual(Object.keys(testData));
});

it('should work with complex nested objects with string keys', () => {
const encoder = new CborEncoder();
const decoder = new CborDecoder();

const testData = {
'user_profile': {
'first_name': 'John',
'last_name': 'Doe',
'preferences': {
'theme': 'dark',
'notifications_enabled': true,
'languages': ['en', 'es', 'fr']
}
},
'metadata': {
'created_at': '2023-01-01',
'version': 1
}
};

const encoded = encoder.encode(testData);
const decoded = decoder.decode(encoded);

expect(decoded).toEqual(testData);
});
});
});
2 changes: 2 additions & 0 deletions src/json-cli/json-unpack.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {readFileSync} from 'fs';
import {MsgPackDecoderFast} from '@jsonjoy.com/json-pack/lib/msgpack';
// Apply runtime patch for CBOR decoder issue #925
import '../util/cbor-decoder-fix';
import {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder';
import * as JSONB from '@jsonjoy.com/json-pack/lib/json-binary';
import arg from 'arg';
Expand Down
63 changes: 63 additions & 0 deletions src/util/cbor-decoder-fix.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* Runtime patch for CBOR decoder issue #925
*
* This module applies a runtime fix for the "keyDecoder is undefined" issue that occurs
* when @jsonjoy.com/util uses problematic re-exports.
*
* Issue: https://github.com/streamich/json-joy/issues/925
* Root cause: tslib.__exportStar skips the default export when re-exporting modules
*
* This fix patches the sharedCachedUtf8Decoder module at runtime to ensure the
* default export is available.
*/

// Patch the sharedCachedUtf8Decoder module at runtime
try {
const sharedModule = require('@jsonjoy.com/util/lib/buffers/utf8/sharedCachedUtf8Decoder');

// If the default export is missing (the bug), get it from the original source
if (!sharedModule.default) {
const originalModule = require('@jsonjoy.com/buffers/lib/utf8/sharedCachedUtf8Decoder');
if (originalModule.default) {
sharedModule.default = originalModule.default;
console.log('[json-joy] Applied runtime patch for CBOR decoder issue #925');
}
}
} catch (error) {
// If the patch fails, log a warning but don't crash
console.warn('[json-joy] Could not apply CBOR decoder patch:', (error as Error).message);
}

// Re-export everything from the original modules for convenience
export {CborDecoder} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoder';
export {CborEncoder} from '@jsonjoy.com/json-pack/lib/cbor/CborEncoder';
export {CborDecoderBase} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoderBase';

/**
* Creates a CBOR decoder with the runtime patch applied
*/
export function createCborDecoder() {
const {CborDecoder} = require('@jsonjoy.com/json-pack/lib/cbor/CborDecoder');
return new CborDecoder();
}

/**
* Apply the runtime patch manually if needed
*/
export function applyRuntimePatch() {
try {
const sharedModule = require('@jsonjoy.com/util/lib/buffers/utf8/sharedCachedUtf8Decoder');

if (!sharedModule.default) {
const originalModule = require('@jsonjoy.com/buffers/lib/utf8/sharedCachedUtf8Decoder');
if (originalModule.default) {
sharedModule.default = originalModule.default;
return true;
}
}
return false;
} catch (error) {
console.warn('[json-joy] Runtime patch failed:', (error as Error).message);
return false;
}
}
Loading