Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Socket
Sign inDemoInstall

observable-membrane

Package Overview
Dependencies
Maintainers
11
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

observable-membrane - npm Package Compare versions

Comparing version 0.25.0 to 0.26.0

12

CHANGELOG.md

@@ -1,3 +0,3 @@

<a name="0.25.0"></a>
# 0.25.0 (2018-07-18)
<a name="0.26.0"></a>
# 0.26.0 (2018-11-19)

@@ -7,2 +7,5 @@

* bundle generation for cjs ([78b420a](https://github.com/salesforce/observable-membrane/commit/78b420a))
* entry point ([4231ecb](https://github.com/salesforce/observable-membrane/commit/4231ecb))
* issue [#20](https://github.com/salesforce/observable-membrane/issues/20) - supporting access to value via descriptor ([#22](https://github.com/salesforce/observable-membrane/issues/22)) ([4bd4751](https://github.com/salesforce/observable-membrane/commit/4bd4751))
* linting ([ac2d448](https://github.com/salesforce/observable-membrane/commit/ac2d448))

@@ -17,2 +20,7 @@ * simplify build ([13bd2ee](https://github.com/salesforce/observable-membrane/commit/13bd2ee))

### Performance Improvements
* fix for small perf regression associated to defineProperties(). ([9c54ec0](https://github.com/salesforce/observable-membrane/commit/9c54ec0))

252

dist/commonjs/observable-membrane.js

@@ -7,5 +7,4 @@ /**

const { isArray } = Array;
const { getPrototypeOf, create: ObjectCreate, defineProperty: ObjectDefineProperty, defineProperties: ObjectDefineProperties, isExtensible, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, preventExtensions, } = Object;
const { getPrototypeOf, create: ObjectCreate, defineProperty: ObjectDefineProperty, defineProperties: ObjectDefineProperties, isExtensible, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, preventExtensions, hasOwnProperty, } = Object;
const { push: ArrayPush, concat: ArrayConcat, map: ArrayMap, } = Array.prototype;
const ObjectDotPrototype = Object.prototype;
const OtS = {}.toString;

@@ -26,2 +25,5 @@ function toString(obj) {

}
function isFunction(obj) {
return typeof obj === 'function';
}
const TargetSlot = Symbol();

@@ -35,13 +37,2 @@ // TODO: we are using a funky and leaky abstraction here to try to identify if

: (replicaOrAny) => (replicaOrAny && replicaOrAny[TargetSlot]) || replicaOrAny;
function isObservable(value) {
// intentionally checking for null and undefined
if (value == null) {
return false;
}
if (isArray(value)) {
return true;
}
const proto = getPrototypeOf(value);
return (proto === ObjectDotPrototype || proto === null || getPrototypeOf(proto) === null);
}
function isObject(obj) {

@@ -51,6 +42,9 @@ return typeof obj === 'object';

function wrapValue(membrane, value) {
return membrane.valueIsObservable(value) ? membrane.getProxy(value) : value;
}
// Unwrap property descriptors
// We only need to unwrap if value is specified
function unwrapDescriptor(descriptor) {
if ('value' in descriptor) {
if (hasOwnProperty.call(descriptor, 'value')) {
descriptor.value = unwrap(descriptor.value);

@@ -60,8 +54,2 @@ }

}
function wrapDescriptor(membrane, descriptor) {
if ('value' in descriptor) {
descriptor.value = isObservable(descriptor.value) ? membrane.getProxy(descriptor.value) : descriptor.value;
}
return descriptor;
}
function lockShadowTarget(membrane, shadowTarget, originalTarget) {

@@ -71,3 +59,3 @@ const targetKeys = ArrayConcat.call(getOwnPropertyNames(originalTarget), getOwnPropertySymbols(originalTarget));

let descriptor = getOwnPropertyDescriptor(originalTarget, key);
// We do not need to wrap the descriptor if not configurable
// We do not need to wrap the descriptor if configurable
// Because we can deal with wrapping it when user goes through

@@ -78,3 +66,3 @@ // Get own property descriptor. There is also a chance that this descriptor

if (!descriptor.configurable) {
descriptor = wrapDescriptor(membrane, descriptor);
descriptor = wrapDescriptor(membrane, descriptor, wrapValue);
}

@@ -86,9 +74,5 @@ ObjectDefineProperty(shadowTarget, key, descriptor);

class ReactiveProxyHandler {
constructor(membrane, value, options) {
constructor(membrane, value) {
this.originalTarget = value;
this.membrane = membrane;
if (!isUndefined(options)) {
this.valueMutated = options.valueMutated;
this.valueObserved = options.valueObserved;
}
}

@@ -101,16 +85,12 @@ get(shadowTarget, key) {

const value = originalTarget[key];
const { valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { valueObserved } = membrane;
valueObserved(originalTarget, key);
return membrane.getProxy(value);
}
set(shadowTarget, key, value) {
const { originalTarget, valueMutated } = this;
const { originalTarget, membrane: { valueMutated } } = this;
const oldValue = originalTarget[key];
if (oldValue !== value) {
originalTarget[key] = value;
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
}

@@ -122,5 +102,3 @@ else if (key === 'length' && isArray(originalTarget)) {

// to support this use case.
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
}

@@ -130,7 +108,5 @@ return true;

deleteProperty(shadowTarget, key) {
const { originalTarget, valueMutated } = this;
const { originalTarget, membrane: { valueMutated } } = this;
delete originalTarget[key];
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
return true;

@@ -145,6 +121,4 @@ }

has(shadowTarget, key) {
const { originalTarget, valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { originalTarget, membrane: { valueObserved } } = this;
valueObserved(originalTarget, key);
return key in originalTarget;

@@ -178,7 +152,6 @@ }

getOwnPropertyDescriptor(shadowTarget, key) {
const { originalTarget, membrane, valueObserved } = this;
const { originalTarget, membrane } = this;
const { valueObserved } = this.membrane;
// keys looked up via hasOwnProperty need to be reactive
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
valueObserved(originalTarget, key);
let desc = getOwnPropertyDescriptor(originalTarget, key);

@@ -189,3 +162,10 @@ if (isUndefined(desc)) {

const shadowDescriptor = getOwnPropertyDescriptor(shadowTarget, key);
if (!desc.configurable && !shadowDescriptor) {
if (!isUndefined(shadowDescriptor)) {
return shadowDescriptor;
}
// Note: by accessing the descriptor, the key is marked as observed
// but access to the value, setter or getter (if available) cannot observe
// mutations, just like regular methods, in which case we just do nothing.
desc = wrapDescriptor(membrane, desc, wrapValue);
if (!desc.configurable) {
// If descriptor from original target is not configurable,

@@ -196,6 +176,5 @@ // We must copy the wrapped descriptor over to the shadow target.

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Invariants
desc = wrapDescriptor(membrane, desc);
ObjectDefineProperty(shadowTarget, key, desc);
}
return shadowDescriptor || desc;
return desc;
}

@@ -209,3 +188,4 @@ preventExtensions(shadowTarget) {

defineProperty(shadowTarget, key, descriptor) {
const { originalTarget, membrane, valueMutated } = this;
const { originalTarget, membrane } = this;
const { valueMutated } = membrane;
const { configurable } = descriptor;

@@ -219,3 +199,3 @@ // We have to check for value in descriptor

// value is present. This eliminates getter and setter descriptors
if ('writable' in descriptor && !('value' in descriptor)) {
if (hasOwnProperty.call(descriptor, 'writable') && !hasOwnProperty.call(descriptor, 'value')) {
const originalDescriptor = getOwnPropertyDescriptor(originalTarget, key);

@@ -226,7 +206,5 @@ descriptor.value = originalDescriptor.value;

if (configurable === false) {
ObjectDefineProperty(shadowTarget, key, wrapDescriptor(membrane, descriptor));
ObjectDefineProperty(shadowTarget, key, wrapDescriptor(membrane, descriptor, wrapValue));
}
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
return true;

@@ -236,15 +214,9 @@ }

function wrapDescriptor$1(membrane, descriptor) {
if ('value' in descriptor) {
descriptor.value = isObservable(descriptor.value) ? membrane.getReadOnlyProxy(descriptor.value) : descriptor.value;
}
return descriptor;
function wrapReadOnlyValue(membrane, value) {
return membrane.valueIsObservable(value) ? membrane.getReadOnlyProxy(value) : value;
}
class ReadOnlyHandler {
constructor(membrane, value, options) {
constructor(membrane, value) {
this.originalTarget = value;
this.membrane = membrane;
if (!isUndefined(options)) {
this.valueObserved = options.valueObserved;
}
}

@@ -257,6 +229,4 @@ get(shadowTarget, key) {

const value = originalTarget[key];
const { valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { valueObserved } = membrane;
valueObserved(originalTarget, key);
return membrane.getReadOnlyProxy(value);

@@ -285,7 +255,4 @@ }

has(shadowTarget, key) {
const { originalTarget } = this;
const { valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { originalTarget, membrane: { valueObserved } } = this;
valueObserved(originalTarget, key);
return key in originalTarget;

@@ -304,7 +271,6 @@ }

getOwnPropertyDescriptor(shadowTarget, key) {
const { originalTarget, membrane, valueObserved } = this;
const { originalTarget, membrane } = this;
const { valueObserved } = membrane;
// keys looked up via hasOwnProperty need to be reactive
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
valueObserved(originalTarget, key);
let desc = getOwnPropertyDescriptor(originalTarget, key);

@@ -315,3 +281,13 @@ if (isUndefined(desc)) {

const shadowDescriptor = getOwnPropertyDescriptor(shadowTarget, key);
if (!desc.configurable && !shadowDescriptor) {
if (!isUndefined(shadowDescriptor)) {
return shadowDescriptor;
}
// Note: by accessing the descriptor, the key is marked as observed
// but access to the value or getter (if available) cannot be observed,
// just like regular methods, in which case we just do nothing.
desc = wrapDescriptor(membrane, desc, wrapReadOnlyValue);
if (hasOwnProperty.call(desc, 'set')) {
desc.set = undefined; // readOnly membrane does not allow setters
}
if (!desc.configurable) {
// If descriptor from original target is not configurable,

@@ -322,6 +298,5 @@ // We must copy the wrapped descriptor over to the shadow target.

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Invariants
desc = wrapDescriptor$1(membrane, desc);
ObjectDefineProperty(shadowTarget, key, desc);
}
return shadowDescriptor || desc;
return desc;
}

@@ -417,15 +392,64 @@ preventExtensions(shadowTarget) {

}
const ObjectDotPrototype = Object.prototype;
function defaultValueIsObservable(value) {
// intentionally checking for null and undefined
if (value == null) {
return false;
}
if (isArray(value)) {
return true;
}
const proto = getPrototypeOf(value);
return (proto === ObjectDotPrototype || proto === null || getPrototypeOf(proto) === null);
}
const defaultValueObserved = (obj, key) => {
/* do nothing */
};
const defaultValueMutated = (obj, key) => {
/* do nothing */
};
const defaultValueDistortion = (value) => value;
function wrapDescriptor(membrane, descriptor, getValue) {
const { set, get } = descriptor;
if (hasOwnProperty.call(descriptor, 'value')) {
descriptor.value = getValue(membrane, descriptor.value);
}
else {
if (!isUndefined(get)) {
descriptor.get = function () {
// invoking the original getter with the original target
return getValue(membrane, get.call(unwrap(this)));
};
}
if (!isUndefined(set)) {
descriptor.set = function (value) {
// At this point we don't have a clear indication of whether
// or not a valid mutation will occur, we don't have the key,
// and we are not sure why and how they are invoking this setter.
// Nevertheless we preserve the original semantics by invoking the
// original setter with the original target and the unwrapped value
set.call(unwrap(this), membrane.unwrapProxy(value));
};
}
}
return descriptor;
}
class ReactiveMembrane {
constructor(options) {
this.valueDistortion = defaultValueDistortion;
this.valueMutated = defaultValueMutated;
this.valueObserved = defaultValueObserved;
this.valueIsObservable = defaultValueIsObservable;
this.objectGraph = new WeakMap();
if (!isUndefined(options)) {
this.valueDistortion = options.valueDistortion;
this.valueMutated = options.valueMutated;
this.valueObserved = options.valueObserved;
const { valueDistortion, valueMutated, valueObserved, valueIsObservable } = options;
this.valueDistortion = isFunction(valueDistortion) ? valueDistortion : defaultValueDistortion;
this.valueMutated = isFunction(valueMutated) ? valueMutated : defaultValueMutated;
this.valueObserved = isFunction(valueObserved) ? valueObserved : defaultValueObserved;
this.valueIsObservable = isFunction(valueIsObservable) ? valueIsObservable : defaultValueIsObservable;
}
}
getProxy(value) {
const { valueDistortion } = this;
const distorted = isUndefined(valueDistortion) ? value : valueDistortion(value);
if (isObservable(distorted)) {
const distorted = this.valueDistortion(value);
if (this.valueIsObservable(distorted)) {
const o = this.getReactiveState(distorted);

@@ -439,5 +463,4 @@ // when trying to extract the writable version of a readonly

getReadOnlyProxy(value) {
const { valueDistortion } = this;
const distorted = isUndefined(valueDistortion) ? value : valueDistortion(value);
if (isObservable(distorted)) {
const distorted = this.valueDistortion(value);
if (this.valueIsObservable(distorted)) {
return this.getReactiveState(distorted).readOnly;

@@ -451,4 +474,3 @@ }

getReactiveState(value) {
const membrane = this;
const { objectGraph, valueMutated, valueObserved, } = membrane;
const { objectGraph, } = this;
value = unwrap(value);

@@ -459,29 +481,19 @@ let reactiveState = objectGraph.get(value);

}
reactiveState = ObjectDefineProperties(ObjectCreate(null), {
reactive: {
get() {
const reactiveHandler = new ReactiveProxyHandler(membrane, value, {
valueMutated,
valueObserved,
});
// caching the reactive proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), reactiveHandler);
ObjectDefineProperty(this, 'reactive', { value: proxy });
return proxy;
},
configurable: true,
const membrane = this;
reactiveState = {
get reactive() {
const reactiveHandler = new ReactiveProxyHandler(membrane, value);
// caching the reactive proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), reactiveHandler);
ObjectDefineProperty(this, 'reactive', { value: proxy });
return proxy;
},
readOnly: {
get() {
const readOnlyHandler = new ReadOnlyHandler(membrane, value, {
valueObserved,
});
// caching the readOnly proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), readOnlyHandler);
ObjectDefineProperty(this, 'readOnly', { value: proxy });
return proxy;
},
configurable: true,
get readOnly() {
const readOnlyHandler = new ReadOnlyHandler(membrane, value);
// caching the readOnly proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), readOnlyHandler);
ObjectDefineProperty(this, 'readOnly', { value: proxy });
return proxy;
}
});
};
objectGraph.set(value, reactiveState);

@@ -488,0 +500,0 @@ return reactiveState;

@@ -5,5 +5,4 @@ /**

const { isArray } = Array;
const { getPrototypeOf, create: ObjectCreate, defineProperty: ObjectDefineProperty, defineProperties: ObjectDefineProperties, isExtensible, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, preventExtensions, } = Object;
const { getPrototypeOf, create: ObjectCreate, defineProperty: ObjectDefineProperty, defineProperties: ObjectDefineProperties, isExtensible, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, preventExtensions, hasOwnProperty, } = Object;
const { push: ArrayPush, concat: ArrayConcat, map: ArrayMap, } = Array.prototype;
const ObjectDotPrototype = Object.prototype;
const OtS = {}.toString;

@@ -24,2 +23,5 @@ function toString(obj) {

}
function isFunction(obj) {
return typeof obj === 'function';
}
const TargetSlot = Symbol();

@@ -33,13 +35,2 @@ // TODO: we are using a funky and leaky abstraction here to try to identify if

: (replicaOrAny) => (replicaOrAny && replicaOrAny[TargetSlot]) || replicaOrAny;
function isObservable(value) {
// intentionally checking for null and undefined
if (value == null) {
return false;
}
if (isArray(value)) {
return true;
}
const proto = getPrototypeOf(value);
return (proto === ObjectDotPrototype || proto === null || getPrototypeOf(proto) === null);
}
function isObject(obj) {

@@ -49,6 +40,9 @@ return typeof obj === 'object';

function wrapValue(membrane, value) {
return membrane.valueIsObservable(value) ? membrane.getProxy(value) : value;
}
// Unwrap property descriptors
// We only need to unwrap if value is specified
function unwrapDescriptor(descriptor) {
if ('value' in descriptor) {
if (hasOwnProperty.call(descriptor, 'value')) {
descriptor.value = unwrap(descriptor.value);

@@ -58,8 +52,2 @@ }

}
function wrapDescriptor(membrane, descriptor) {
if ('value' in descriptor) {
descriptor.value = isObservable(descriptor.value) ? membrane.getProxy(descriptor.value) : descriptor.value;
}
return descriptor;
}
function lockShadowTarget(membrane, shadowTarget, originalTarget) {

@@ -69,3 +57,3 @@ const targetKeys = ArrayConcat.call(getOwnPropertyNames(originalTarget), getOwnPropertySymbols(originalTarget));

let descriptor = getOwnPropertyDescriptor(originalTarget, key);
// We do not need to wrap the descriptor if not configurable
// We do not need to wrap the descriptor if configurable
// Because we can deal with wrapping it when user goes through

@@ -76,3 +64,3 @@ // Get own property descriptor. There is also a chance that this descriptor

if (!descriptor.configurable) {
descriptor = wrapDescriptor(membrane, descriptor);
descriptor = wrapDescriptor(membrane, descriptor, wrapValue);
}

@@ -84,9 +72,5 @@ ObjectDefineProperty(shadowTarget, key, descriptor);

class ReactiveProxyHandler {
constructor(membrane, value, options) {
constructor(membrane, value) {
this.originalTarget = value;
this.membrane = membrane;
if (!isUndefined(options)) {
this.valueMutated = options.valueMutated;
this.valueObserved = options.valueObserved;
}
}

@@ -99,16 +83,12 @@ get(shadowTarget, key) {

const value = originalTarget[key];
const { valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { valueObserved } = membrane;
valueObserved(originalTarget, key);
return membrane.getProxy(value);
}
set(shadowTarget, key, value) {
const { originalTarget, valueMutated } = this;
const { originalTarget, membrane: { valueMutated } } = this;
const oldValue = originalTarget[key];
if (oldValue !== value) {
originalTarget[key] = value;
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
}

@@ -120,5 +100,3 @@ else if (key === 'length' && isArray(originalTarget)) {

// to support this use case.
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
}

@@ -128,7 +106,5 @@ return true;

deleteProperty(shadowTarget, key) {
const { originalTarget, valueMutated } = this;
const { originalTarget, membrane: { valueMutated } } = this;
delete originalTarget[key];
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
return true;

@@ -143,6 +119,4 @@ }

has(shadowTarget, key) {
const { originalTarget, valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { originalTarget, membrane: { valueObserved } } = this;
valueObserved(originalTarget, key);
return key in originalTarget;

@@ -176,7 +150,6 @@ }

getOwnPropertyDescriptor(shadowTarget, key) {
const { originalTarget, membrane, valueObserved } = this;
const { originalTarget, membrane } = this;
const { valueObserved } = this.membrane;
// keys looked up via hasOwnProperty need to be reactive
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
valueObserved(originalTarget, key);
let desc = getOwnPropertyDescriptor(originalTarget, key);

@@ -187,3 +160,10 @@ if (isUndefined(desc)) {

const shadowDescriptor = getOwnPropertyDescriptor(shadowTarget, key);
if (!desc.configurable && !shadowDescriptor) {
if (!isUndefined(shadowDescriptor)) {
return shadowDescriptor;
}
// Note: by accessing the descriptor, the key is marked as observed
// but access to the value, setter or getter (if available) cannot observe
// mutations, just like regular methods, in which case we just do nothing.
desc = wrapDescriptor(membrane, desc, wrapValue);
if (!desc.configurable) {
// If descriptor from original target is not configurable,

@@ -194,6 +174,5 @@ // We must copy the wrapped descriptor over to the shadow target.

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Invariants
desc = wrapDescriptor(membrane, desc);
ObjectDefineProperty(shadowTarget, key, desc);
}
return shadowDescriptor || desc;
return desc;
}

@@ -207,3 +186,4 @@ preventExtensions(shadowTarget) {

defineProperty(shadowTarget, key, descriptor) {
const { originalTarget, membrane, valueMutated } = this;
const { originalTarget, membrane } = this;
const { valueMutated } = membrane;
const { configurable } = descriptor;

@@ -217,3 +197,3 @@ // We have to check for value in descriptor

// value is present. This eliminates getter and setter descriptors
if ('writable' in descriptor && !('value' in descriptor)) {
if (hasOwnProperty.call(descriptor, 'writable') && !hasOwnProperty.call(descriptor, 'value')) {
const originalDescriptor = getOwnPropertyDescriptor(originalTarget, key);

@@ -224,7 +204,5 @@ descriptor.value = originalDescriptor.value;

if (configurable === false) {
ObjectDefineProperty(shadowTarget, key, wrapDescriptor(membrane, descriptor));
ObjectDefineProperty(shadowTarget, key, wrapDescriptor(membrane, descriptor, wrapValue));
}
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
return true;

@@ -234,15 +212,9 @@ }

function wrapDescriptor$1(membrane, descriptor) {
if ('value' in descriptor) {
descriptor.value = isObservable(descriptor.value) ? membrane.getReadOnlyProxy(descriptor.value) : descriptor.value;
}
return descriptor;
function wrapReadOnlyValue(membrane, value) {
return membrane.valueIsObservable(value) ? membrane.getReadOnlyProxy(value) : value;
}
class ReadOnlyHandler {
constructor(membrane, value, options) {
constructor(membrane, value) {
this.originalTarget = value;
this.membrane = membrane;
if (!isUndefined(options)) {
this.valueObserved = options.valueObserved;
}
}

@@ -255,6 +227,4 @@ get(shadowTarget, key) {

const value = originalTarget[key];
const { valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { valueObserved } = membrane;
valueObserved(originalTarget, key);
return membrane.getReadOnlyProxy(value);

@@ -283,7 +253,4 @@ }

has(shadowTarget, key) {
const { originalTarget } = this;
const { valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { originalTarget, membrane: { valueObserved } } = this;
valueObserved(originalTarget, key);
return key in originalTarget;

@@ -302,7 +269,6 @@ }

getOwnPropertyDescriptor(shadowTarget, key) {
const { originalTarget, membrane, valueObserved } = this;
const { originalTarget, membrane } = this;
const { valueObserved } = membrane;
// keys looked up via hasOwnProperty need to be reactive
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
valueObserved(originalTarget, key);
let desc = getOwnPropertyDescriptor(originalTarget, key);

@@ -313,3 +279,13 @@ if (isUndefined(desc)) {

const shadowDescriptor = getOwnPropertyDescriptor(shadowTarget, key);
if (!desc.configurable && !shadowDescriptor) {
if (!isUndefined(shadowDescriptor)) {
return shadowDescriptor;
}
// Note: by accessing the descriptor, the key is marked as observed
// but access to the value or getter (if available) cannot be observed,
// just like regular methods, in which case we just do nothing.
desc = wrapDescriptor(membrane, desc, wrapReadOnlyValue);
if (hasOwnProperty.call(desc, 'set')) {
desc.set = undefined; // readOnly membrane does not allow setters
}
if (!desc.configurable) {
// If descriptor from original target is not configurable,

@@ -320,6 +296,5 @@ // We must copy the wrapped descriptor over to the shadow target.

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Invariants
desc = wrapDescriptor$1(membrane, desc);
ObjectDefineProperty(shadowTarget, key, desc);
}
return shadowDescriptor || desc;
return desc;
}

@@ -415,15 +390,64 @@ preventExtensions(shadowTarget) {

}
const ObjectDotPrototype = Object.prototype;
function defaultValueIsObservable(value) {
// intentionally checking for null and undefined
if (value == null) {
return false;
}
if (isArray(value)) {
return true;
}
const proto = getPrototypeOf(value);
return (proto === ObjectDotPrototype || proto === null || getPrototypeOf(proto) === null);
}
const defaultValueObserved = (obj, key) => {
/* do nothing */
};
const defaultValueMutated = (obj, key) => {
/* do nothing */
};
const defaultValueDistortion = (value) => value;
function wrapDescriptor(membrane, descriptor, getValue) {
const { set, get } = descriptor;
if (hasOwnProperty.call(descriptor, 'value')) {
descriptor.value = getValue(membrane, descriptor.value);
}
else {
if (!isUndefined(get)) {
descriptor.get = function () {
// invoking the original getter with the original target
return getValue(membrane, get.call(unwrap(this)));
};
}
if (!isUndefined(set)) {
descriptor.set = function (value) {
// At this point we don't have a clear indication of whether
// or not a valid mutation will occur, we don't have the key,
// and we are not sure why and how they are invoking this setter.
// Nevertheless we preserve the original semantics by invoking the
// original setter with the original target and the unwrapped value
set.call(unwrap(this), membrane.unwrapProxy(value));
};
}
}
return descriptor;
}
class ReactiveMembrane {
constructor(options) {
this.valueDistortion = defaultValueDistortion;
this.valueMutated = defaultValueMutated;
this.valueObserved = defaultValueObserved;
this.valueIsObservable = defaultValueIsObservable;
this.objectGraph = new WeakMap();
if (!isUndefined(options)) {
this.valueDistortion = options.valueDistortion;
this.valueMutated = options.valueMutated;
this.valueObserved = options.valueObserved;
const { valueDistortion, valueMutated, valueObserved, valueIsObservable } = options;
this.valueDistortion = isFunction(valueDistortion) ? valueDistortion : defaultValueDistortion;
this.valueMutated = isFunction(valueMutated) ? valueMutated : defaultValueMutated;
this.valueObserved = isFunction(valueObserved) ? valueObserved : defaultValueObserved;
this.valueIsObservable = isFunction(valueIsObservable) ? valueIsObservable : defaultValueIsObservable;
}
}
getProxy(value) {
const { valueDistortion } = this;
const distorted = isUndefined(valueDistortion) ? value : valueDistortion(value);
if (isObservable(distorted)) {
const distorted = this.valueDistortion(value);
if (this.valueIsObservable(distorted)) {
const o = this.getReactiveState(distorted);

@@ -437,5 +461,4 @@ // when trying to extract the writable version of a readonly

getReadOnlyProxy(value) {
const { valueDistortion } = this;
const distorted = isUndefined(valueDistortion) ? value : valueDistortion(value);
if (isObservable(distorted)) {
const distorted = this.valueDistortion(value);
if (this.valueIsObservable(distorted)) {
return this.getReactiveState(distorted).readOnly;

@@ -449,4 +472,3 @@ }

getReactiveState(value) {
const membrane = this;
const { objectGraph, valueMutated, valueObserved, } = membrane;
const { objectGraph, } = this;
value = unwrap(value);

@@ -457,29 +479,19 @@ let reactiveState = objectGraph.get(value);

}
reactiveState = ObjectDefineProperties(ObjectCreate(null), {
reactive: {
get() {
const reactiveHandler = new ReactiveProxyHandler(membrane, value, {
valueMutated,
valueObserved,
});
// caching the reactive proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), reactiveHandler);
ObjectDefineProperty(this, 'reactive', { value: proxy });
return proxy;
},
configurable: true,
const membrane = this;
reactiveState = {
get reactive() {
const reactiveHandler = new ReactiveProxyHandler(membrane, value);
// caching the reactive proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), reactiveHandler);
ObjectDefineProperty(this, 'reactive', { value: proxy });
return proxy;
},
readOnly: {
get() {
const readOnlyHandler = new ReadOnlyHandler(membrane, value, {
valueObserved,
});
// caching the readOnly proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), readOnlyHandler);
ObjectDefineProperty(this, 'readOnly', { value: proxy });
return proxy;
},
configurable: true,
get readOnly() {
const readOnlyHandler = new ReadOnlyHandler(membrane, value);
// caching the readOnly proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), readOnlyHandler);
ObjectDefineProperty(this, 'readOnly', { value: proxy });
return proxy;
}
});
};
objectGraph.set(value, reactiveState);

@@ -486,0 +498,0 @@ return reactiveState;

@@ -1,12 +0,6 @@

import { ReactiveMembrane, ReactiveMembraneShadowTarget, ReactiveMembraneMutationCallback, ReactiveMembraneAccessCallback } from './reactive-membrane';
export interface ReactiveProxyHandlerInit {
valueMutated?: ReactiveMembraneMutationCallback;
valueObserved?: ReactiveMembraneAccessCallback;
}
import { ReactiveMembrane, ReactiveMembraneShadowTarget } from './reactive-membrane';
export declare class ReactiveProxyHandler {
private originalTarget;
private membrane;
private valueObserved?;
private valueMutated?;
constructor(membrane: ReactiveMembrane, value: any, options?: ReactiveProxyHandlerInit);
constructor(membrane: ReactiveMembrane, value: any);
get(shadowTarget: ReactiveMembraneShadowTarget, key: PropertyKey): any;

@@ -13,0 +7,0 @@ set(shadowTarget: ReactiveMembraneShadowTarget, key: PropertyKey, value: any): boolean;

@@ -5,2 +5,3 @@ export declare type ReactiveMembraneShadowTarget = object | any[];

export declare type ReactiveMembraneDistortionCallback = (value: any) => any;
export declare type ReactiveMembraneObservableCallback = (value: any) => boolean;
export interface ObservableMembraneInit {

@@ -10,7 +11,10 @@ valueMutated?: ReactiveMembraneMutationCallback;

valueDistortion?: ReactiveMembraneDistortionCallback;
valueIsObservable?: ReactiveMembraneObservableCallback;
}
export declare function wrapDescriptor(membrane: ReactiveMembrane, descriptor: PropertyDescriptor, getValue: (membrane: ReactiveMembrane, originalValue: any) => any): PropertyDescriptor;
export declare class ReactiveMembrane {
private valueDistortion?;
private valueMutated?;
private valueObserved?;
valueDistortion: ReactiveMembraneDistortionCallback;
valueMutated: ReactiveMembraneMutationCallback;
valueObserved: ReactiveMembraneAccessCallback;
valueIsObservable: ReactiveMembraneObservableCallback;
private objectGraph;

@@ -17,0 +21,0 @@ constructor(options?: ObservableMembraneInit);

@@ -1,10 +0,6 @@

import { ReactiveMembrane, ReactiveMembraneShadowTarget, ReactiveMembraneAccessCallback } from './reactive-membrane';
export interface ReadOnlyHandlerInit {
valueObserved?: ReactiveMembraneAccessCallback;
}
import { ReactiveMembrane, ReactiveMembraneShadowTarget } from './reactive-membrane';
export declare class ReadOnlyHandler {
private originalTarget;
private membrane;
private valueObserved?;
constructor(membrane: ReactiveMembrane, value: any, options?: ReadOnlyHandlerInit);
constructor(membrane: ReactiveMembrane, value: any);
get(shadowTarget: ReactiveMembraneShadowTarget, key: PropertyKey): any;

@@ -11,0 +7,0 @@ set(shadowTarget: ReactiveMembraneShadowTarget, key: PropertyKey, value: any): boolean;

@@ -11,3 +11,6 @@ declare const isArray: (arg: any) => arg is any[];

(o: any, propertyKey: PropertyKey): PropertyDescriptor | undefined;
}, getOwnPropertyNames: (o: any) => string[], getOwnPropertySymbols: (o: any) => symbol[], preventExtensions: <T>(o: T) => T;
}, getOwnPropertyNames: (o: any) => string[], getOwnPropertySymbols: (o: any) => symbol[], preventExtensions: <T>(o: T) => T, hasOwnProperty: {
(v: string): boolean;
(v: PropertyKey): boolean;
};
declare const ArrayPush: (...items: any[]) => number, ArrayConcat: {

@@ -17,8 +20,8 @@ (...items: ConcatArray<any>[]): any[];

}, ArrayMap: <U>(callbackfn: (value: any, index: number, array: any[]) => U, thisArg?: any) => U[];
export { ArrayPush, ArrayConcat, ArrayMap, isArray, getPrototypeOf, ObjectCreate, ObjectDefineProperty, ObjectDefineProperties, isExtensible, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, preventExtensions };
export { ArrayPush, ArrayConcat, ArrayMap, isArray, getPrototypeOf, ObjectCreate, ObjectDefineProperty, ObjectDefineProperties, isExtensible, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, preventExtensions, hasOwnProperty };
export declare function toString(obj: any): string;
export declare function isUndefined(obj: any): obj is undefined;
export declare function isFunction(obj: any): obj is Function;
export declare const TargetSlot: unique symbol;
export declare const unwrap: (replicaOrAny: any) => any;
export declare function isObservable(value: any): boolean;
export declare function isObject(obj: any): obj is object;

@@ -11,5 +11,4 @@ /**

const { isArray } = Array;
const { getPrototypeOf, create: ObjectCreate, defineProperty: ObjectDefineProperty, defineProperties: ObjectDefineProperties, isExtensible, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, preventExtensions, } = Object;
const { getPrototypeOf, create: ObjectCreate, defineProperty: ObjectDefineProperty, defineProperties: ObjectDefineProperties, isExtensible, getOwnPropertyDescriptor, getOwnPropertyNames, getOwnPropertySymbols, preventExtensions, hasOwnProperty, } = Object;
const { push: ArrayPush, concat: ArrayConcat, map: ArrayMap, } = Array.prototype;
const ObjectDotPrototype = Object.prototype;
const OtS = {}.toString;

@@ -30,2 +29,5 @@ function toString(obj) {

}
function isFunction(obj) {
return typeof obj === 'function';
}
const TargetSlot = Symbol();

@@ -39,13 +41,2 @@ // TODO: we are using a funky and leaky abstraction here to try to identify if

: (replicaOrAny) => (replicaOrAny && replicaOrAny[TargetSlot]) || replicaOrAny;
function isObservable(value) {
// intentionally checking for null and undefined
if (value == null) {
return false;
}
if (isArray(value)) {
return true;
}
const proto = getPrototypeOf(value);
return (proto === ObjectDotPrototype || proto === null || getPrototypeOf(proto) === null);
}
function isObject(obj) {

@@ -55,6 +46,9 @@ return typeof obj === 'object';

function wrapValue(membrane, value) {
return membrane.valueIsObservable(value) ? membrane.getProxy(value) : value;
}
// Unwrap property descriptors
// We only need to unwrap if value is specified
function unwrapDescriptor(descriptor) {
if ('value' in descriptor) {
if (hasOwnProperty.call(descriptor, 'value')) {
descriptor.value = unwrap(descriptor.value);

@@ -64,8 +58,2 @@ }

}
function wrapDescriptor(membrane, descriptor) {
if ('value' in descriptor) {
descriptor.value = isObservable(descriptor.value) ? membrane.getProxy(descriptor.value) : descriptor.value;
}
return descriptor;
}
function lockShadowTarget(membrane, shadowTarget, originalTarget) {

@@ -75,3 +63,3 @@ const targetKeys = ArrayConcat.call(getOwnPropertyNames(originalTarget), getOwnPropertySymbols(originalTarget));

let descriptor = getOwnPropertyDescriptor(originalTarget, key);
// We do not need to wrap the descriptor if not configurable
// We do not need to wrap the descriptor if configurable
// Because we can deal with wrapping it when user goes through

@@ -82,3 +70,3 @@ // Get own property descriptor. There is also a chance that this descriptor

if (!descriptor.configurable) {
descriptor = wrapDescriptor(membrane, descriptor);
descriptor = wrapDescriptor(membrane, descriptor, wrapValue);
}

@@ -90,9 +78,5 @@ ObjectDefineProperty(shadowTarget, key, descriptor);

class ReactiveProxyHandler {
constructor(membrane, value, options) {
constructor(membrane, value) {
this.originalTarget = value;
this.membrane = membrane;
if (!isUndefined(options)) {
this.valueMutated = options.valueMutated;
this.valueObserved = options.valueObserved;
}
}

@@ -105,16 +89,12 @@ get(shadowTarget, key) {

const value = originalTarget[key];
const { valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { valueObserved } = membrane;
valueObserved(originalTarget, key);
return membrane.getProxy(value);
}
set(shadowTarget, key, value) {
const { originalTarget, valueMutated } = this;
const { originalTarget, membrane: { valueMutated } } = this;
const oldValue = originalTarget[key];
if (oldValue !== value) {
originalTarget[key] = value;
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
}

@@ -126,5 +106,3 @@ else if (key === 'length' && isArray(originalTarget)) {

// to support this use case.
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
}

@@ -134,7 +112,5 @@ return true;

deleteProperty(shadowTarget, key) {
const { originalTarget, valueMutated } = this;
const { originalTarget, membrane: { valueMutated } } = this;
delete originalTarget[key];
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
return true;

@@ -149,6 +125,4 @@ }

has(shadowTarget, key) {
const { originalTarget, valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { originalTarget, membrane: { valueObserved } } = this;
valueObserved(originalTarget, key);
return key in originalTarget;

@@ -182,7 +156,6 @@ }

getOwnPropertyDescriptor(shadowTarget, key) {
const { originalTarget, membrane, valueObserved } = this;
const { originalTarget, membrane } = this;
const { valueObserved } = this.membrane;
// keys looked up via hasOwnProperty need to be reactive
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
valueObserved(originalTarget, key);
let desc = getOwnPropertyDescriptor(originalTarget, key);

@@ -193,3 +166,10 @@ if (isUndefined(desc)) {

const shadowDescriptor = getOwnPropertyDescriptor(shadowTarget, key);
if (!desc.configurable && !shadowDescriptor) {
if (!isUndefined(shadowDescriptor)) {
return shadowDescriptor;
}
// Note: by accessing the descriptor, the key is marked as observed
// but access to the value, setter or getter (if available) cannot observe
// mutations, just like regular methods, in which case we just do nothing.
desc = wrapDescriptor(membrane, desc, wrapValue);
if (!desc.configurable) {
// If descriptor from original target is not configurable,

@@ -200,6 +180,5 @@ // We must copy the wrapped descriptor over to the shadow target.

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Invariants
desc = wrapDescriptor(membrane, desc);
ObjectDefineProperty(shadowTarget, key, desc);
}
return shadowDescriptor || desc;
return desc;
}

@@ -213,3 +192,4 @@ preventExtensions(shadowTarget) {

defineProperty(shadowTarget, key, descriptor) {
const { originalTarget, membrane, valueMutated } = this;
const { originalTarget, membrane } = this;
const { valueMutated } = membrane;
const { configurable } = descriptor;

@@ -223,3 +203,3 @@ // We have to check for value in descriptor

// value is present. This eliminates getter and setter descriptors
if ('writable' in descriptor && !('value' in descriptor)) {
if (hasOwnProperty.call(descriptor, 'writable') && !hasOwnProperty.call(descriptor, 'value')) {
const originalDescriptor = getOwnPropertyDescriptor(originalTarget, key);

@@ -230,7 +210,5 @@ descriptor.value = originalDescriptor.value;

if (configurable === false) {
ObjectDefineProperty(shadowTarget, key, wrapDescriptor(membrane, descriptor));
ObjectDefineProperty(shadowTarget, key, wrapDescriptor(membrane, descriptor, wrapValue));
}
if (!isUndefined(valueMutated)) {
valueMutated(originalTarget, key);
}
valueMutated(originalTarget, key);
return true;

@@ -240,15 +218,9 @@ }

function wrapDescriptor$1(membrane, descriptor) {
if ('value' in descriptor) {
descriptor.value = isObservable(descriptor.value) ? membrane.getReadOnlyProxy(descriptor.value) : descriptor.value;
}
return descriptor;
function wrapReadOnlyValue(membrane, value) {
return membrane.valueIsObservable(value) ? membrane.getReadOnlyProxy(value) : value;
}
class ReadOnlyHandler {
constructor(membrane, value, options) {
constructor(membrane, value) {
this.originalTarget = value;
this.membrane = membrane;
if (!isUndefined(options)) {
this.valueObserved = options.valueObserved;
}
}

@@ -261,6 +233,4 @@ get(shadowTarget, key) {

const value = originalTarget[key];
const { valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { valueObserved } = membrane;
valueObserved(originalTarget, key);
return membrane.getReadOnlyProxy(value);

@@ -289,7 +259,4 @@ }

has(shadowTarget, key) {
const { originalTarget } = this;
const { valueObserved } = this;
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
const { originalTarget, membrane: { valueObserved } } = this;
valueObserved(originalTarget, key);
return key in originalTarget;

@@ -308,7 +275,6 @@ }

getOwnPropertyDescriptor(shadowTarget, key) {
const { originalTarget, membrane, valueObserved } = this;
const { originalTarget, membrane } = this;
const { valueObserved } = membrane;
// keys looked up via hasOwnProperty need to be reactive
if (!isUndefined(valueObserved)) {
valueObserved(originalTarget, key);
}
valueObserved(originalTarget, key);
let desc = getOwnPropertyDescriptor(originalTarget, key);

@@ -319,3 +285,13 @@ if (isUndefined(desc)) {

const shadowDescriptor = getOwnPropertyDescriptor(shadowTarget, key);
if (!desc.configurable && !shadowDescriptor) {
if (!isUndefined(shadowDescriptor)) {
return shadowDescriptor;
}
// Note: by accessing the descriptor, the key is marked as observed
// but access to the value or getter (if available) cannot be observed,
// just like regular methods, in which case we just do nothing.
desc = wrapDescriptor(membrane, desc, wrapReadOnlyValue);
if (hasOwnProperty.call(desc, 'set')) {
desc.set = undefined; // readOnly membrane does not allow setters
}
if (!desc.configurable) {
// If descriptor from original target is not configurable,

@@ -326,6 +302,5 @@ // We must copy the wrapped descriptor over to the shadow target.

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/getOwnPropertyDescriptor#Invariants
desc = wrapDescriptor$1(membrane, desc);
ObjectDefineProperty(shadowTarget, key, desc);
}
return shadowDescriptor || desc;
return desc;
}

@@ -417,15 +392,64 @@ preventExtensions(shadowTarget) {

}
const ObjectDotPrototype = Object.prototype;
function defaultValueIsObservable(value) {
// intentionally checking for null and undefined
if (value == null) {
return false;
}
if (isArray(value)) {
return true;
}
const proto = getPrototypeOf(value);
return (proto === ObjectDotPrototype || proto === null || getPrototypeOf(proto) === null);
}
const defaultValueObserved = (obj, key) => {
/* do nothing */
};
const defaultValueMutated = (obj, key) => {
/* do nothing */
};
const defaultValueDistortion = (value) => value;
function wrapDescriptor(membrane, descriptor, getValue) {
const { set, get } = descriptor;
if (hasOwnProperty.call(descriptor, 'value')) {
descriptor.value = getValue(membrane, descriptor.value);
}
else {
if (!isUndefined(get)) {
descriptor.get = function () {
// invoking the original getter with the original target
return getValue(membrane, get.call(unwrap(this)));
};
}
if (!isUndefined(set)) {
descriptor.set = function (value) {
// At this point we don't have a clear indication of whether
// or not a valid mutation will occur, we don't have the key,
// and we are not sure why and how they are invoking this setter.
// Nevertheless we preserve the original semantics by invoking the
// original setter with the original target and the unwrapped value
set.call(unwrap(this), membrane.unwrapProxy(value));
};
}
}
return descriptor;
}
class ReactiveMembrane {
constructor(options) {
this.valueDistortion = defaultValueDistortion;
this.valueMutated = defaultValueMutated;
this.valueObserved = defaultValueObserved;
this.valueIsObservable = defaultValueIsObservable;
this.objectGraph = new WeakMap();
if (!isUndefined(options)) {
this.valueDistortion = options.valueDistortion;
this.valueMutated = options.valueMutated;
this.valueObserved = options.valueObserved;
const { valueDistortion, valueMutated, valueObserved, valueIsObservable } = options;
this.valueDistortion = isFunction(valueDistortion) ? valueDistortion : defaultValueDistortion;
this.valueMutated = isFunction(valueMutated) ? valueMutated : defaultValueMutated;
this.valueObserved = isFunction(valueObserved) ? valueObserved : defaultValueObserved;
this.valueIsObservable = isFunction(valueIsObservable) ? valueIsObservable : defaultValueIsObservable;
}
}
getProxy(value) {
const { valueDistortion } = this;
const distorted = isUndefined(valueDistortion) ? value : valueDistortion(value);
if (isObservable(distorted)) {
const distorted = this.valueDistortion(value);
if (this.valueIsObservable(distorted)) {
const o = this.getReactiveState(distorted);

@@ -439,5 +463,4 @@ // when trying to extract the writable version of a readonly

getReadOnlyProxy(value) {
const { valueDistortion } = this;
const distorted = isUndefined(valueDistortion) ? value : valueDistortion(value);
if (isObservable(distorted)) {
const distorted = this.valueDistortion(value);
if (this.valueIsObservable(distorted)) {
return this.getReactiveState(distorted).readOnly;

@@ -451,4 +474,3 @@ }

getReactiveState(value) {
const membrane = this;
const { objectGraph, valueMutated, valueObserved, } = membrane;
const { objectGraph, } = this;
value = unwrap(value);

@@ -459,29 +481,19 @@ let reactiveState = objectGraph.get(value);

}
reactiveState = ObjectDefineProperties(ObjectCreate(null), {
reactive: {
get() {
const reactiveHandler = new ReactiveProxyHandler(membrane, value, {
valueMutated,
valueObserved,
});
// caching the reactive proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), reactiveHandler);
ObjectDefineProperty(this, 'reactive', { value: proxy });
return proxy;
},
configurable: true,
const membrane = this;
reactiveState = {
get reactive() {
const reactiveHandler = new ReactiveProxyHandler(membrane, value);
// caching the reactive proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), reactiveHandler);
ObjectDefineProperty(this, 'reactive', { value: proxy });
return proxy;
},
readOnly: {
get() {
const readOnlyHandler = new ReadOnlyHandler(membrane, value, {
valueObserved,
});
// caching the readOnly proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), readOnlyHandler);
ObjectDefineProperty(this, 'readOnly', { value: proxy });
return proxy;
},
configurable: true,
get readOnly() {
const readOnlyHandler = new ReadOnlyHandler(membrane, value);
// caching the readOnly proxy after the first time it is accessed
const proxy = new Proxy(createShadowTarget(value), readOnlyHandler);
ObjectDefineProperty(this, 'readOnly', { value: proxy });
return proxy;
}
});
};
objectGraph.set(value, reactiveState);

@@ -488,0 +500,0 @@ return reactiveState;

@@ -1,1 +0,1 @@

(function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.ObservableMembrane=b()})(this,function(){"use strict";function a(a){return a===void 0}function b(a){if(null==a)return!1;if(i(a))return!0;const b=j(a);return b===v||null===b||null===j(b)}function c(a){return"object"==typeof a}function d(a){return"value"in a&&(a.value=y(a.value)),a}function e(a,c){return"value"in c&&(c.value=b(c.value)?a.getProxy(c.value):c.value),c}function f(a,b,c){const d=t.call(p(c),q(c));d.forEach(d=>{let f=o(c,d);f.configurable||(f=e(a,f)),l(b,d,f)}),r(b)}function g(a,c){return"value"in c&&(c.value=b(c.value)?a.getReadOnlyProxy(c.value):c.value),c}function h(a){let b;return i(a)?b=[]:c(a)&&(b={}),b}const{isArray:i}=Array,{getPrototypeOf:j,create:k,defineProperty:l,defineProperties:m,isExtensible:n,getOwnPropertyDescriptor:o,getOwnPropertyNames:p,getOwnPropertySymbols:q,preventExtensions:r}=Object,{push:s,concat:t,map:u}=Array.prototype,v=Object.prototype,w=Symbol(),{getKey:x}=Proxy,y=x?a=>a&&x(a,w)||a:a=>a&&a[w]||a;class z{constructor(b,c,d){this.originalTarget=c,this.membrane=b,a(d)||(this.valueMutated=d.valueMutated,this.valueObserved=d.valueObserved)}get(b,c){const{originalTarget:d,membrane:e}=this;if(c===w)return d;const f=d[c],{valueObserved:g}=this;return a(g)||g(d,c),e.getProxy(f)}set(b,c,d){const{originalTarget:e,valueMutated:f}=this,g=e[c];return g===d?"length"===c&&i(e)&&!a(f)&&f(e,c):(e[c]=d,!a(f)&&f(e,c)),!0}deleteProperty(b,c){const{originalTarget:d,valueMutated:e}=this;return delete d[c],a(e)||e(d,c),!0}apply(){}construct(){}has(b,c){const{originalTarget:d,valueObserved:e}=this;return a(e)||e(d,c),c in d}ownKeys(){const{originalTarget:a}=this;return t.call(p(a),q(a))}isExtensible(a){const b=n(a);if(!b)return b;const{originalTarget:c,membrane:d}=this,e=n(c);return e||f(d,a,c),e}setPrototypeOf(){}getPrototypeOf(){const{originalTarget:a}=this;return j(a)}getOwnPropertyDescriptor(b,c){const{originalTarget:d,membrane:f,valueObserved:g}=this;a(g)||g(d,c);let h=o(d,c);if(a(h))return h;const i=o(b,c);return h.configurable||i||(h=e(f,h),l(b,c,h)),i||h}preventExtensions(a){const{originalTarget:b,membrane:c}=this;return f(c,a,b),r(b),!0}defineProperty(b,c,f){const{originalTarget:g,membrane:h,valueMutated:i}=this,{configurable:j}=f;if("writable"in f&&!("value"in f)){const a=o(g,c);f.value=a.value}return l(g,c,d(f)),!1===j&&l(b,c,e(h,f)),a(i)||i(g,c),!0}}class A{constructor(b,c,d){this.originalTarget=c,this.membrane=b,a(d)||(this.valueObserved=d.valueObserved)}get(b,c){const{membrane:d,originalTarget:e}=this;if(c===w)return e;const f=e[c],{valueObserved:g}=this;return a(g)||g(e,c),d.getReadOnlyProxy(f)}set(){return!1}deleteProperty(){return!1}apply(){}construct(){}has(b,c){const{originalTarget:d}=this,{valueObserved:e}=this;return a(e)||e(d,c),c in d}ownKeys(){const{originalTarget:a}=this;return t.call(p(a),q(a))}setPrototypeOf(){}getOwnPropertyDescriptor(b,c){const{originalTarget:d,membrane:e,valueObserved:f}=this;a(f)||f(d,c);let h=o(d,c);if(a(h))return h;const i=o(b,c);return h.configurable||i||(h=g(e,h),l(b,c,h)),i||h}preventExtensions(){return!1}defineProperty(){return!1}}return class{constructor(b){this.objectGraph=new WeakMap,a(b)||(this.valueDistortion=b.valueDistortion,this.valueMutated=b.valueMutated,this.valueObserved=b.valueObserved)}getProxy(c){const{valueDistortion:d}=this,e=a(d)?c:d(c);if(b(e)){const a=this.getReactiveState(e);return a.readOnly===c?c:a.reactive}return e}getReadOnlyProxy(c){const{valueDistortion:d}=this,e=a(d)?c:d(c);return b(e)?this.getReactiveState(e).readOnly:e}unwrapProxy(a){return y(a)}getReactiveState(a){const b=this,{objectGraph:c,valueMutated:d,valueObserved:e}=b;a=y(a);let f=c.get(a);return f?f:(f=m(k(null),{reactive:{get(){const c=new z(b,a,{valueMutated:d,valueObserved:e}),f=new Proxy(h(a),c);return l(this,"reactive",{value:f}),f},configurable:!0},readOnly:{get(){const c=new A(b,a,{valueObserved:e}),d=new Proxy(h(a),c);return l(this,"readOnly",{value:d}),d},configurable:!0}}),c.set(a,f),f)}}});
(function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.ObservableMembrane=b()})(this,function(){"use strict";function a(a){return a===void 0}function b(a){return"function"==typeof a}function c(a){return"object"==typeof a}function d(a,b){return a.valueIsObservable(b)?a.getProxy(b):b}function e(a){return u.call(a,"value")&&(a.value=A(a.value)),a}function f(a,b,c){const e=w.call(r(c),s(c));e.forEach(e=>{let f=q(c,e);f.configurable||(f=j(a,f,d)),n(b,e,f)}),t(b)}function g(a,b){return a.valueIsObservable(b)?a.getReadOnlyProxy(b):b}function h(a){let b;return k(a)?b=[]:c(a)&&(b={}),b}function i(a){if(null==a)return!1;if(k(a))return!0;const b=l(a);return b===D||null===b||null===l(b)}function j(b,c,d){const{set:e,get:f}=c;return u.call(c,"value")?c.value=d(b,c.value):(!a(f)&&(c.get=function(){return d(b,f.call(A(this)))}),!a(e)&&(c.set=function(a){e.call(A(this),b.unwrapProxy(a))})),c}const{isArray:k}=Array,{getPrototypeOf:l,create:m,defineProperty:n,defineProperties:o,isExtensible:p,getOwnPropertyDescriptor:q,getOwnPropertyNames:r,getOwnPropertySymbols:s,preventExtensions:t,hasOwnProperty:u}=Object,{push:v,concat:w,map:x}=Array.prototype,y=Symbol(),{getKey:z}=Proxy,A=z?a=>a&&z(a,y)||a:a=>a&&a[y]||a;class B{constructor(a,b){this.originalTarget=b,this.membrane=a}get(a,b){const{originalTarget:c,membrane:d}=this;if(b===y)return c;const e=c[b],{valueObserved:f}=d;return f(c,b),d.getProxy(e)}set(a,b,c){const{originalTarget:d,membrane:{valueMutated:e}}=this,f=d[b];return f===c?"length"===b&&k(d)&&e(d,b):(d[b]=c,e(d,b)),!0}deleteProperty(a,b){const{originalTarget:c,membrane:{valueMutated:d}}=this;return delete c[b],d(c,b),!0}apply(){}construct(){}has(a,b){const{originalTarget:c,membrane:{valueObserved:d}}=this;return d(c,b),b in c}ownKeys(){const{originalTarget:a}=this;return w.call(r(a),s(a))}isExtensible(a){const b=p(a);if(!b)return b;const{originalTarget:c,membrane:d}=this,e=p(c);return e||f(d,a,c),e}setPrototypeOf(){}getPrototypeOf(){const{originalTarget:a}=this;return l(a)}getOwnPropertyDescriptor(b,c){const{originalTarget:e,membrane:f}=this,{valueObserved:g}=this.membrane;g(e,c);let h=q(e,c);if(a(h))return h;const i=q(b,c);return a(i)?(h=j(f,h,d),h.configurable||n(b,c,h),h):i}preventExtensions(a){const{originalTarget:b,membrane:c}=this;return f(c,a,b),t(b),!0}defineProperty(a,b,c){const{originalTarget:f,membrane:g}=this,{valueMutated:h}=g,{configurable:i}=c;if(u.call(c,"writable")&&!u.call(c,"value")){const a=q(f,b);c.value=a.value}return n(f,b,e(c)),!1===i&&n(a,b,j(g,c,d)),h(f,b),!0}}class C{constructor(a,b){this.originalTarget=b,this.membrane=a}get(a,b){const{membrane:c,originalTarget:d}=this;if(b===y)return d;const e=d[b],{valueObserved:f}=c;return f(d,b),c.getReadOnlyProxy(e)}set(){return!1}deleteProperty(){return!1}apply(){}construct(){}has(a,b){const{originalTarget:c,membrane:{valueObserved:d}}=this;return d(c,b),b in c}ownKeys(){const{originalTarget:a}=this;return w.call(r(a),s(a))}setPrototypeOf(){}getOwnPropertyDescriptor(b,c){const{originalTarget:d,membrane:e}=this,{valueObserved:f}=e;f(d,c);let h=q(d,c);if(a(h))return h;const i=q(b,c);return a(i)?(h=j(e,h,g),u.call(h,"set")&&(h.set=void 0),h.configurable||n(b,c,h),h):i}preventExtensions(){return!1}defineProperty(){return!1}}const D=Object.prototype,E=()=>{},F=()=>{},G=a=>a;return class{constructor(c){if(this.valueDistortion=G,this.valueMutated=F,this.valueObserved=E,this.valueIsObservable=i,this.objectGraph=new WeakMap,!a(c)){const{valueDistortion:a,valueMutated:d,valueObserved:e,valueIsObservable:f}=c;this.valueDistortion=b(a)?a:G,this.valueMutated=b(d)?d:F,this.valueObserved=b(e)?e:E,this.valueIsObservable=b(f)?f:i}}getProxy(a){const b=this.valueDistortion(a);if(this.valueIsObservable(b)){const c=this.getReactiveState(b);return c.readOnly===a?a:c.reactive}return b}getReadOnlyProxy(a){const b=this.valueDistortion(a);return this.valueIsObservable(b)?this.getReactiveState(b).readOnly:b}unwrapProxy(a){return A(a)}getReactiveState(a){const{objectGraph:b}=this;a=A(a);let c=b.get(a);if(c)return c;const d=this;return c={get reactive(){const b=new B(d,a),c=new Proxy(h(a),b);return n(this,"reactive",{value:c}),c},get readOnly(){const b=new C(d,a),c=new Proxy(h(a),b);return n(this,"readOnly",{value:c}),c}},b.set(a,c),c}}});
{
"name": "observable-membrane",
"version": "0.25.0",
"version": "0.26.0",
"description": "A Javascript Membrane implementation using Proxies to observe mutation on an object graph",

@@ -5,0 +5,0 @@ "main": "dist/commonjs/observable-membrane.js",

@@ -10,2 +10,3 @@ # Observable Membrane

* [Tom van Cutsem's original article, "Isolating application sub-components with membranes"](https://tvcutsem.github.io/membranes)
* [Tom van Cutsem's original article, "Membranes in JavaScript"](https://tvcutsem.github.io/js-membranes)

@@ -198,2 +199,6 @@ * [es-membrane library by Alexander J. Vincent](https://github.com/ajvincent/es-membrane)

## Example
There are [runnable examples](https://github.com/salesforce/observable-membrane/tree/master/examples) in this Git repository. You must build this package as described in the [Contributing Guide](CONTRIBUTING.md) before attempting to run the examples. Additionally, some of the examples might be relying on features that are not supported in all browsers (e.g.: [reactivo-element](https://github.com/salesforce/observable-membrane/tree/master/examples/reactivo-element) example relies on Web Components APIs).
## API

@@ -200,0 +205,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc