Skip to content

Commit

Permalink
Merge pull request #24 from wentout/proto
Browse files Browse the repository at this point in the history
some optimizations
  • Loading branch information
wentout committed Aug 15, 2022
2 parents e197494 + abc5434 commit 61f5bce
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 32 deletions.
1 change: 1 addition & 0 deletions lib/errors.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ export declare const ErrorsNames: {
ACCESS_DENIED: string;
MISSING_PROP: string;
RIP_FUNCTIONS: string;
FORBIDDEN_RE: string;
};
3 changes: 2 additions & 1 deletion lib/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ exports.ErrorsNames = {
TYPE_MISMATCH: 'Type Mismatch',
ACCESS_DENIED: 'Value Access Denied',
MISSING_PROP: 'Attempt to Access to Undefined Prop',
RIP_FUNCTIONS: 'Functions are Restricted'
RIP_FUNCTIONS: 'Functions are Restricted',
FORBIDDEN_RE: 'Re-Assirnment is Forbidden'
};
11 changes: 10 additions & 1 deletion lib/fields.d.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,11 @@
export declare const SymbolInitialValue: unique symbol;
export declare const FieldConstructor: ObjectConstructor;
interface FieldDefinition {
[SymbolInitialValue]: unknown;
}
export declare class FieldConstructor implements FieldDefinition {
[SymbolInitialValue]: unknown;
get get(): (this: FieldDefinition) => unknown;
get set(): () => never;
constructor(value: unknown);
}
export {};
25 changes: 20 additions & 5 deletions lib/fields.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,23 @@
Object.defineProperty(exports, "__esModule", { value: true });
exports.FieldConstructor = exports.SymbolInitialValue = void 0;
exports.SymbolInitialValue = Symbol('Initial Value');
exports.FieldConstructor = function (value) {
this[exports.SymbolInitialValue] = value;
};
Object.freeze(exports.FieldConstructor.prototype);
Object.seal(exports.FieldConstructor.prototype);
const errors_1 = require("./errors");
class FieldConstructor {
constructor(value) {
this[exports.SymbolInitialValue] = value;
}
get get() {
const self = this;
return function () {
return self[exports.SymbolInitialValue];
};
}
get set() {
return function () {
throw new TypeError(errors_1.ErrorsNames.FORBIDDEN_RE);
};
}
}
exports.FieldConstructor = FieldConstructor;
Object.freeze(FieldConstructor.prototype);
Object.seal(FieldConstructor.prototype);
13 changes: 10 additions & 3 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,18 @@ const createProperty = (propName, initialValue, receiver) => {
const descriptor = (isObject && (value instanceof fields_1.FieldConstructor)) ?
value
: Object.assign({ enumerable: true }, resolver[type](value, receiver));
const result = Reflect.defineProperty(receiver, propName, descriptor);
return result;
try {
const result = Reflect.defineProperty(receiver, propName, descriptor);
return result;
}
catch (error) {
throw error;
}
};
const props2skip = new Set([Symbol.toStringTag, Symbol.iterator]);
const util = require('util');
const props2skip = new Set([util.inspect.custom, Symbol.toStringTag, Symbol.iterator]);
const hasNodeInspect = (util && util.inspect && util.inspect.custom);
hasNodeInspect && (props2skip.add(util.inspect.custom));
const handlers = {
get(target, prop, receiver) {
const result = Reflect.get(target, prop, receiver);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "typeomatica",
"version": "0.2.7",
"version": "0.2.8",
"description": "type logic against javascript metaprogramming",
"main": "lib/index.js",
"scripts": {
Expand Down
3 changes: 2 additions & 1 deletion src/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ export const ErrorsNames = {
TYPE_MISMATCH: 'Type Mismatch',
ACCESS_DENIED: 'Value Access Denied',
MISSING_PROP: 'Attempt to Access to Undefined Prop',
RIP_FUNCTIONS: 'Functions are Restricted'
RIP_FUNCTIONS: 'Functions are Restricted',
FORBIDDEN_RE: 'Re-Assirnment is Forbidden'
};
26 changes: 23 additions & 3 deletions src/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

export const SymbolInitialValue = Symbol('Initial Value');

import { ErrorsNames } from './errors'

interface FieldDefinition {
[SymbolInitialValue]: unknown
// get?: unknown
Expand All @@ -11,9 +13,27 @@ interface FieldDefinition {
// writable: boolean
}

export const FieldConstructor = function (this: FieldDefinition, value: unknown) {
this[SymbolInitialValue] = value;
} as ObjectConstructor;
// export const FieldConstructor = function (this: FieldDefinition, value: unknown) {
// this[SymbolInitialValue] = value;
// } as ObjectConstructor;

export class FieldConstructor implements FieldDefinition {
[SymbolInitialValue]: unknown
public get get () {
const self = this;
return function (this: FieldDefinition) {
return self[SymbolInitialValue];
}
}
public get set () {
return function () {
throw new TypeError(ErrorsNames.FORBIDDEN_RE);
}
}
constructor (value: unknown) {
this[SymbolInitialValue] = value;
}
}

// Object.assign(FieldConstructor.prototype, {
// configurable: false,
Expand Down
14 changes: 11 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,20 @@ const createProperty = (propName: string, initialValue: unknown, receiver: objec
// debugger;
// }

const result = Reflect.defineProperty(receiver, propName, descriptor);
return result;
try {
const result = Reflect.defineProperty(receiver, propName, descriptor);
return result;
} catch (error) {
// debugger;
throw error;
}

};

const props2skip = new Set([Symbol.toStringTag, Symbol.iterator]);
const util = require('util');
const props2skip = new Set([util.inspect.custom, Symbol.toStringTag, Symbol.iterator]);
const hasNodeInspect = (util && util.inspect && util.inspect.custom);
hasNodeInspect && (props2skip.add(util.inspect.custom));

const handlers = {
get(target: object, prop: string | symbol, receiver: object) {
Expand All @@ -103,6 +110,7 @@ const handlers = {
}, {}));
}
}
// @ts-ignore
if (props2skip.has(prop)) {
return undefined;
}
Expand Down
111 changes: 97 additions & 14 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,37 +72,83 @@ const extendedSetInstance = new ExtendedSet;
const MUTATION_VALUE = -2;


class MyFieldConstructor extends FieldConstructor {
class MyFieldConstructorNoRe extends FieldConstructor {
_value: string
constructor(value: string) {
super(value);
Reflect.defineProperty(this, 'enumerable', {
value: true
});
this._value = value;
}
}
class MyFieldConstructorReGet extends MyFieldConstructorNoRe {
constructor(value: string) {
super(value);
const self = this;
Reflect.defineProperty(this, 'enumerable', {
value: true
});
Reflect.defineProperty(this, 'get', {
get () {
get() {
return function () {
return value;
return self._value;
}
}
},
enumerable: true
});
}
}
class MyFieldConstructorReSet extends MyFieldConstructorNoRe {
constructor(value: string) {
super(value);
const self = this;
Reflect.defineProperty(this, 'enumerable', {
value: true
});
Reflect.defineProperty(this, 'set', {
get () {
return function (_value: string) {
value = _value;
get() {
return function (value: string) {
self._value = value;
}
},
enumerable: true
});
}
}
class MyFieldConstructor extends MyFieldConstructorReGet {
constructor(value: string) {
super(value);
const self = this;
Reflect.defineProperty(this, 'enumerable', {
value: true
});
Reflect.defineProperty(this, 'set', {
get() {
return function (value: string) {
self._value = value;
}
},
enumerable: true
});
}
}

const myField = new MyFieldConstructor('initial value');
const myFieldReGet = new MyFieldConstructorReGet('initial value for get check');
const myFieldReSet = new MyFieldConstructorReSet('initial value for set check');

const myField = new MyFieldConstructor('zzz');
class MadeFieldClass extends BaseClass { myField = myField };
class SecondMadeFieldClass extends BaseClass { myField = myField };
class MadeFieldClass extends BaseClass { myField = myField as unknown | string };
class SecondMadeFieldClass extends BaseClass { myField = myField as unknown | string };
const madeFieldInstance = new MadeFieldClass;
const secondMadeFieldInstance = new MadeFieldClass;
const thirdMadeFieldInstance = new SecondMadeFieldClass;

class MadeReGet extends BaseClass { myField = myFieldReGet as unknown | string }
class MadeReSet extends BaseClass { myField = myFieldReSet as unknown | string }
const madeReGet = new MadeReGet;
const madeReSet = new MadeReSet;

describe('props tests', () => {

test('base instance has props', () => {
Expand Down Expand Up @@ -172,12 +218,45 @@ describe('props tests', () => {
});

test('correct custom field creation', () => {
expect(madeFieldInstance.myField).toEqual('zzz');
expect(madeFieldInstance.myField).toEqual('initial value');
});

test('correct custom field assignment', () => {
madeFieldInstance.myField = 123;
expect(secondMadeFieldInstance.myField).toEqual(123);
expect(thirdMadeFieldInstance.myField).toEqual(123);
madeFieldInstance.myField = 'replaced';
expect(secondMadeFieldInstance.myField).toEqual('replaced');
expect(thirdMadeFieldInstance.myField).toEqual('replaced');
});

test('correct custom field no-re-assignment', () => {
expect(madeReGet.myField).toEqual('initial value for get check');
expect(() => {

madeReGet.myField = 'replaced';

}).toThrow(new TypeError('Re-Assirnment is Forbidden'));
});

test('correct custom field setter only', () => {
madeReSet.myField = 'replaced';
expect(madeReSet.myField).toEqual('initial value for set check');
});

test('takes error on wrong field definition', () => {
expect(() => {
class WrongFieldConstructor extends FieldConstructor {
value: number
constructor(value: number) {
super(value)
this.value = value;
}
}
const wrongField = new WrongFieldConstructor(123);
class WithWrongField extends BaseClass {
erroredField = wrongField
}
new WithWrongField;

}).toThrow();
});

test('correct custom missing prop search creation', () => {
Expand All @@ -188,6 +267,10 @@ describe('props tests', () => {
const util = require('util');
// @ts-ignore
expect(madeFieldInstance[util.inspect.custom]).toEqual(undefined);
// @ts-ignore
const inspected = util.inspect(madeFieldInstance);
const expected = 'MadeFieldClass { myField: [Getter/Setter] }';
expect(expected).toEqual(expected);
});

test('wrong assignment to objects', () => {
Expand Down

0 comments on commit 61f5bce

Please sign in to comment.