Skip to content

Commit

Permalink
Allow exceptional values in Hashes + make tsconfig use strict mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuri Yuri committed Nov 1, 2022
1 parent e518d3b commit a811c86
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 20 deletions.
20 changes: 16 additions & 4 deletions lib/dump/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { dump } from '.';
import { MarshalStandardObject } from '../types';

// str.each_char.each_slice(2).map { |s| s.join.to_i(16).chr }.join
describe('Marshal', () => {
Expand Down Expand Up @@ -126,27 +127,38 @@ describe('Marshal', () => {
});

it('dumps extended object made from JS world', () => {
type JSPointObject = MarshalStandardObject & {
'@x': number;
'@y': number;
'@z': number;
x: number;
y: number;
z: number;
};
const makePointObject = (x: number, y: number, z: number) => {
const pointObject = {
const pointObject: JSPointObject = {
__class: Symbol.for('PointObject'),
__extendedModules: [
{ __class: 'Module' as const, name: 'PrettyPrinter' },
{ __class: 'Module' as const, name: 'Point3D' },
],
'@x': -1,
'@y': -1,
'@z': -1,
get x() {
return this['@x'] as number;
return this['@x'];
},
set x(v: number) {
this['@x'] = v;
},
get y() {
return this['@y'] as number;
return this['@y'];
},
set y(v: number) {
this['@y'] = v;
},
get z() {
return this['@z'] as number;
return this['@z'];
},
set z(v: number) {
this['@z'] = v;
Expand Down
20 changes: 14 additions & 6 deletions lib/dump/objects.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { COMMON_ENCODING_SYMBOL, ENCODING_SYMBOL } from '../load/encoded';
import { isMarshalExtendableObject } from '../typeGuards';
import { MarshalDataObject, MarshalHash, MarshalMarshalObject, MarshalStandardObject, MarshalStructObject, MarshalUserObject } from '../types';
import type {
MarshalDataObject,
MarshalHash,
MarshalMarshalObject,
MarshalObject,
MarshalStandardObject,
MarshalStructObject,
MarshalUserObject,
} from '../types';
import { marshalDumpObjectLink } from './link';
import { MarshalDumpContext, w_byte, w_bytes, w_long, w_remember } from './r_helpers';
import { marshalDumpString } from './strings';
Expand Down Expand Up @@ -83,14 +91,14 @@ export const marshalDumpHash = (context: MarshalDumpContext, object: MarshalHash
} else {
marshalDumpString(context, key);
}
context.marshalDump(context, object[key]);
context.marshalDump(context, object[key] as MarshalObject);
});
if (object.__default) context.marshalDump(context, object.__default);
if (ivar.length > 0) {
w_long(context, ivar.length);
ivar.forEach((key) => {
marshalDumpSymbol(context, Symbol.for(key));
context.marshalDump(context, object[key]);
context.marshalDump(context, object[key] as MarshalObject);
});
}
};
Expand All @@ -104,13 +112,13 @@ export const marshalDumpStruct = (context: MarshalDumpContext, object: MarshalSt
w_long(context, keys.length);
keys.forEach((key) => {
marshalDumpSymbol(context, Symbol.for(key));
context.marshalDump(context, object[key]);
context.marshalDump(context, object[key] as MarshalObject);
});
if (ivar.length > 0) {
w_long(context, ivar.length);
ivar.forEach((key) => {
marshalDumpSymbol(context, Symbol.for(key));
context.marshalDump(context, object[key]);
context.marshalDump(context, object[key] as MarshalObject);
});
}
};
Expand All @@ -122,6 +130,6 @@ export const marshalDumpStandardObject = (context: MarshalDumpContext, object: M
w_long(context, ivar.length);
ivar.forEach((key) => {
marshalDumpSymbol(context, Symbol.for(key));
context.marshalDump(context, object[key]);
context.marshalDump(context, object[key] as MarshalObject);
});
};
4 changes: 3 additions & 1 deletion lib/dump/r_helpers.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import type { MarshalObject } from '../types';

export type MarshalDumpContext = {
buffer: Buffer;
length: number;
objects: unknown[];
symbols: symbol[];
marshalDump: (context: MarshalDumpContext, object: unknown) => void;
marshalDump: (context: MarshalDumpContext, object: MarshalObject) => void;
};

export const expandBuffer = (context: MarshalDumpContext, needed: number) => {
Expand Down
3 changes: 2 additions & 1 deletion lib/load/extended.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { MarshalError } from '../errors';
import { MarshalObject } from '../types';
import { marshalLoadModule } from './modules';
import { MarshalContext, r_byte } from './r_helper';
import { r_unique } from './r_symbol';
import { withSubContext } from './withSubContext';

export const marshalLoadExtended = (context: MarshalContext, extMod: ReturnType<typeof marshalLoadModule>[] = []) => {
export const marshalLoadExtended = (context: MarshalContext, extMod: ReturnType<typeof marshalLoadModule>[] = []): MarshalObject => {
const path = withSubContext(context, false, r_unique);
const name = Symbol.keyFor(path);
if (!name) throw new MarshalError(`${path.toString()} is unknown to the JS realm.`);
Expand Down
19 changes: 16 additions & 3 deletions lib/load/hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,23 @@ export const marshalLoadHash = (context: MarshalContext): MarshalHash => {
while (length--) {
const key = r_object(context);
const value = r_object(context);
if (typeof key !== 'string' && typeof key !== 'symbol') {
throw new MarshalError(`Cannot support non symbol or string key in Hashes in JS, received: ${typeof key}`);
switch (typeof key) {
case 'string':
case 'symbol':
hash[key] = value;
break;
case 'number':
hash[key.toString()] = value;
break;
case 'boolean':
hash[key ? 'true' : 'false'] = value;
break;
case 'object':
hash[key ? key.toString() : 'null'] = value;
break;
default:
throw new MarshalError(`Cannot support non symbol or string key in Hashes in JS, received: ${typeof key}`);
}
hash[key] = value;
}
return hash;
};
Expand Down
2 changes: 1 addition & 1 deletion lib/load/objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export const marshalLoadObject = (context: MarshalContext) => {

export const marshalLoadData = (context: MarshalContext) => {
const path = withSubContext(context, false, r_unique);
const object: MarshalDataObject = r_entry(context, { __class: path, __load_data: undefined });
const object: MarshalDataObject = r_entry(context, { __class: path, __load_data: null });
// Ruby calls _load_data with r so we'll extend the object itself with __load_data: r
object.__load_data = r_object(context);
return object;
Expand Down
6 changes: 3 additions & 3 deletions lib/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export type MarshalModuleOrClassObject = {

export type MarshalHash = {
__class: 'Hash';
__default?: unknown;
__default?: MarshalObject;
__extendedModules?: MarshalModuleObject[];
} & Record<string | symbol, unknown>;

Expand All @@ -26,7 +26,7 @@ export type MarshalStandardObject = {

export type MarshalMarshalObject = {
__class: symbol;
__marshal_load: unknown;
__marshal_load: MarshalObject;
};

export type MarshalUserObject = {
Expand All @@ -37,7 +37,7 @@ export type MarshalUserObject = {

export type MarshalDataObject = {
__class: symbol;
__load_data: unknown;
__load_data: MarshalObject;
};

export type MarshalStructObject = {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"bin": "dist/index.js",
"main": "dist/index.js",
"name": "ts-marshal",
"version": "0.0.4",
"version": "0.0.5",
"description": "Typescript library to deserialize Ruby Marshal-i-zed objects",
"author": {
"email": "dont-email@communityscriptproject.com",
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"moduleResolution": "node",
"sourceMap": true,
"strictNullChecks": true,
"strict": true,
},
"exclude": [
"index.d.ts",
Expand Down

0 comments on commit a811c86

Please sign in to comment.