Skip to content

Commit

Permalink
Restore val:null in decorate with toJSON hack
Browse files Browse the repository at this point in the history
  • Loading branch information
aravindet committed Apr 16, 2024
1 parent c7b01db commit 9e277e4
Show file tree
Hide file tree
Showing 6 changed files with 18 additions and 18 deletions.
3 changes: 2 additions & 1 deletion src/common/coding/decodeTree.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { isBranch, isLink, isPrefix, isRange } from '../node/index.js';
import { NULL_VAL } from '../object.js';
import { keyAfter } from '../ops/index.js';
import { clone, cmp, isDef, isEmpty, isMaxKey, isMinKey } from '../util.js';
import { decode as decodeArgs, splitArgs } from './args.js';
Expand Down Expand Up @@ -90,7 +91,7 @@ function decode(nodes = [], { isGraph } = {}) {
delete item.$val;

if ($val === null) {
$val = { $val };
$val = NULL_VAL;
} else if (typeof $val === 'object') {
$val = clone($val);
Object.defineProperty($val, '$val', { value: true });
Expand Down
17 changes: 4 additions & 13 deletions src/common/coding/decorate.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { findFirst, isRange } from '../node/index.js';
import { NULL_VAL } from '../object.js';
import { IS_VAL, getNodeValue, unwrap } from '../ops/index.js';
import {
MIN_KEY,
Expand Down Expand Up @@ -26,7 +27,7 @@ const PRE = Symbol();
export default function decorate(rootGraph, rootQuery) {
// console.log('Decorating', rootGraph, rootQuery);
function construct(plumGraph, query) {
if (plumGraph === null) return null;
if (plumGraph === null || plumGraph === NULL_VAL) return plumGraph;
if (!isDef(plumGraph)) plumGraph = [];
if (query.$key) query = [query];

Expand Down Expand Up @@ -95,15 +96,15 @@ export default function decorate(rootGraph, rootQuery) {
} else if (query) {
if (Array.isArray(plumGraph) && !plumGraph.length) {
graph = undefined;
} else if (typeof plumGraph !== 'object' || !plumGraph) {
} else if (typeof plumGraph !== 'object') {
graph = plumGraph;
} else if (plumGraph[IS_VAL]) {
graph = Array.isArray(plumGraph)
? plumGraph.slice(0)
: { ...plumGraph };
graph.$val = true;
} else if (Array.isArray(plumGraph)) {
graph = deValNull(decodeGraph(plumGraph));
graph = decodeGraph(plumGraph);
} else {
throw Error('decorate.unexpected_graph');
}
Expand Down Expand Up @@ -180,16 +181,6 @@ export default function decorate(rootGraph, rootQuery) {
return result;
}

// Replace $val: null produced by
function deValNull(graph) {
if (typeof graph !== 'object' || !graph) return graph;
if ('$val' in graph && graph.$val !== true) return graph.$val;

// Important: update graph in-place to avoid losing non-enumerable props.
for (const prop in graph) graph[prop] = deValNull(graph[prop]);
return graph;
}

function addPageMeta(graph, args) {
if (args.$all) {
Object.assign(graph, { $page: args, $prev: null, $next: null });
Expand Down
5 changes: 3 additions & 2 deletions src/common/coding/test/decorate.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { page } from '@graffy/testing';
import { e } from '@graffy/testing/encoder.js';
import { NULL_VAL } from '../../object.js';
import { keyAfter as aft, keyBefore as bef } from '../../ops/step.js';
import { MAX_KEY, MIN_KEY } from '../../util.js';
import { decode } from '../base64.js';
Expand Down Expand Up @@ -174,13 +175,13 @@ describe('val_null', () => {
],
{ foo: 1 },
);
expect(result).toEqual({ foo: { bar: null } });
expect(result).toEqual({ foo: { bar: NULL_VAL } });
});

test('explicit', () => {
const result = decorate([{ key: e.foo, version: 0, value: null }], {
foo: 1,
});
expect(result).toEqual({ foo: null });
expect(result).toEqual({ foo: NULL_VAL });
});
});
3 changes: 2 additions & 1 deletion src/common/coding/test/roundTrip.test.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { NULL_VAL } from '../../object.js';
import {
decodeGraph,
decodeQuery,
Expand Down Expand Up @@ -58,7 +59,7 @@ describe('graph', () => {
});

test('val_null', () => {
roundTrip({ foo: { $val: null } });
roundTrip({ foo: { $val: null } }, { foo: NULL_VAL });
});

test('val_scalar', () => {
Expand Down
4 changes: 4 additions & 0 deletions src/common/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import isEqual from 'lodash/isEqual.js';
import { splitArgs } from './coding/index.js';
import { isEmpty } from './util.js';

export const NULL_VAL = {};
Object.defineProperty(NULL_VAL, '$val', { value: null });
Object.defineProperty(NULL_VAL, 'toJSON', { value: () => null });

export function mergeObject(base, change) {
if (
typeof change !== 'object' ||
Expand Down
4 changes: 3 additions & 1 deletion src/common/ops/path.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { findFirst, isBranch, isRange } from '../node/index.js';
import { NULL_VAL } from '../object.js';
import { cmp } from '../util.js';

export const IS_VAL = Symbol('IS_VAL');
Expand Down Expand Up @@ -53,7 +54,8 @@ export function unwrap(tree, path) {

export function getNodeValue(node) {
if (node.children) return node.children;
if (node.value && typeof node.value === 'object') {
if (node.value === null) return NULL_VAL;
if (typeof node.value === 'object') {
node.value[IS_VAL] = true;
}
return node.value;
Expand Down

0 comments on commit 9e277e4

Please sign in to comment.