GithubHelp home page GithubHelp logo

ajvincent / es-membrane Goto Github PK

View Code? Open in Web Editor NEW
108.0 108.0 13.0 6.62 MB

An ECMAScript implementation of a Membrane, allowing users to dynamically hide, override, or extend objects in JavaScript with controlled effects on the original objects.

License: ISC License

Makefile 0.10% JavaScript 65.04% HTML 18.39% CSS 2.27% Shell 0.01% TypeScript 14.19%

es-membrane's People

Contributors

ajvincent avatar davidturissini avatar dependabot[bot] avatar hawkrives avatar qk8333 avatar ssabrii avatar wsargent avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

es-membrane's Issues

Wrap the exported Membrane constructor in a Membrane

In other words, let's use the Membrane constructor and appropriate object graph handlers to protect private members of the Membrane from public access.

Bonus: dogfooding!

  • Hide private members of Membrane, ObjectGraphHandler instances
  • Assert that a ProxyMapping object is never returned from the Membrane
  • Freeze Membrane.prototype, ObjectGraphHandler.prototype, any graph handler set via ObjectGraphHandler.prototype.replaceProxy()
  • Ensure inherited graph handlers cannot override the fieldName property
  • Ensure graph handlers coming into replaceProxy() were first generated inside the Membrane before customization (that they're not proxies themselves)
  • Ensure graph handlers cannot use Object.setPrototypeOf() to override the prototype chain after they are passed into .replaceProxy()
  • Ensure no value returned from the Dogfood Membrane is wrapped in a Dogfood Membrane object graph, and then wrapped again in another Membrane object graph.
  • Tests for all "XXX" comments

Object Graph Handlers: Override decision on what is wrappable

ObjectGraphHandler.prototype.getWrappable(value) should usually return [false, value] for a primitive, or [true, value] for a non-primitive.

membrane.modifyRules(fieldName, proxy, getWrappable) replaces this method with getWrappable.

Major pieces:

  • Transforming a primitive into another primitive
  • Transforming a primitive into an object, so the Membrane can store references to it
  • Tracking method calls across parallel object graphs of the stored primitive, so we can get the impact of the changes in one graph from the other
  • Membrane-aware code to set up the initial conversion

Use Case: Deleting properties shouldn't propagate across the membrane

The tests for "allowLocalProperties" specifically allow the act of deleting properties to cross the membrane. Because it's unclear whether hiding is better or worse than actually deleting, I claim it's a separate use case.

  • Jasmine specification (disabled) demonstrating the use case
  • Implement object graph handlers to achieve the use case
  • Enable test for browser target
  • Enable test for node target

Build system code review

The current build system is probably not the best way for writing Node- and browser-friendly JavaScript code, and doesn't factor in import and export statements for ECMAScript 6. The build system therefore should be reviewed by a Node package authoring expert.

Use Case: Return value validation at proxy

  • Jasmine specification (disabled) demonstrating the use case
  • Implement object graph handlers to achieve the use case
  • Enable test for browser target
  • Enable test for node target

Object Graph Handlers: Filter own properties

If the "wet" object graph explicitly prevents Foo.prototype.hiddenPropName from being exposed, then it should be possible in the "dry" object graph to do the following:

var x = new DryFoo();
x.hiddenPropName = "notSoHidden";
expect(x.hiddenPropName).toBe("notSoHidden");

var X = getWet(x);
expect(X.hiddenPropName).not.toBe("notSoHidden");

The Membrane code also needs an API to specify how this sort of change would be implemented.

Wrapping a non-writable and non-configurable property

I'm just digging into the library now and noticed https://github.com/ajvincent/es7-membrane/blob/master/source/Membrane.js#L343. Is it possible to also wrap non-configurable and non-writable proxies in the object graph? I am interested in keeping a perfect mirror between the wet and dry spaces.

Here is the example I'm working on:

const dryWetMB = new Membrane({});

// 3. Establish "wet" ObjectGraphHandler.
const wetHandler = dryWetMB.getHandlerByField("wet", true);

// 4. Establish "dry" ObjectGraphHandler.
const dryHandler = dryWetMB.getHandlerByField("dry", true);

// 5. Establish "wet" view of an object.
// 6. Get a "dry" view of the same object.

const wrappedWindow = dryWetMB.convertArgumentToProxy(
    wetHandler,
    dryHandler,
    window,
  );
}

console.log(wrappedWindow.caches);

Object Graph Handlers: Multiplex dispatch handlers

Examples:

  • Logging proxy calls or testing that they ran in the correct order
  • Changing environment settings before and after a proxy runs
  • Preconditions, postconditions, aspect-oriented programming
  • Argument validation for external callers only
  • Comparing outputs of different implementations

Use Case: Logging entry, exit into traps

  • Jasmine specification (disabled) demonstrating the use case
  • Implement object graph handlers to achieve the use case
  • Enable test for browser target
  • Enable test for node target

Support ES6-style module imports, exports.

Node, CommonJS and browserify are all nice to have, but this is really supposed to be an ECMAScript-friendly module in all respects. That means import and export statements, hopefully without breaking existing browsers and Node targets...

License and contributing

Hey @ajvincent, great work on this project, it's fantastic! I would love to use this project in my other work and contribute. Is there any chance you could add a license to the repo?

Use Case: Argument Validation at proxy

  • Jasmine specification (disabled) demonstrating the use case
  • Implement object graph handlers to achieve the use case
  • Enable test for browser target
  • Enable test for node target

Use Case: Hide foreign stack frames in exceptions

  • Jasmine specification (disabled) demonstrating the use case
  • Implement object graph handlers to achieve the use case
  • Enable test for browser target
  • Enable test for node target

Note that truly hiding an Error's stack cannot begin until the Error enters an object graph handler. If you are in a "dry" object graph and "dry" code calls:

throw new Error("foo");

then the stack cannot be hidden at that line of code unless the Error constructor itself was overridden somehow.

ProxyMapping.prototype.setLocalFlag(fieldName, flagName)

ProxyMapping.prototype already has flags effectively for "allowLocalProperties" and "mustDeleteLocally". It will soon need flags for .preventExtensions, .setPrototypeOf.

Similarly, we will want methods:
ProxyMapping.prototype.getLocalFlag(fieldName, flagName);
ObjectGraphHandler.prototype.getLocalFlag(proxyMapping, flagName, recursePrototypes);

Experiment: Store "knownKeys" on ProxyMapping instead of defining keys explicitly

ObjectGraphHandler.prototype.fixOwnProperties explicitly defines properties, but this is probably bad. It would be better to cache the list of "known keys" on the ProxyMapping so that we don't require certain properties be defined (particularly since defining properties can sometimes be done only once, per proxy constraints).

Membrane API: Lock down sensitive methods

If a Membrane object leaks out, there are several ways a bad actor could cause problems:

Membrane.prototype.preventModifications() should be defined to prevent:

  • Creating a new ObjectGraphHandler
  • Calling convertArgumentToProxy with an override

The dogfood membrane can prevent some things:

  • Accessing the map, handlerStack, handlersByFieldName or modifyRules properties
  • Calling private methods.

Required for #5. Probably dependent on #6.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.