Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proxies #16

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions katas/es6/language/proxy/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 49: Proxy - apis
// To do: make all tests pass, leave the assert lines unchanged!

describe('handler can have different traps', function() {

it('"apply" is a trap for a function call', function() {
var value = "";

let doSomething = function(arg) {
value = "Yeah! I'm safe!";
};

let doSomethingProxy = new Proxy(doSomething, {
apply(target, thisArg, argumentsList) {
value = "Oh gosh, it's a trap!";
}
});

doSomethingProxy();
assert.equal(value, "Oh gosh, it's a trap!");
});

it('"construct" is a trap for the "new" operator', function() {
var value = "";

let DoSomething = function(arg) {
value = "Yeah! I'm safe!";
};

let DoSomethingProxy = new Proxy(DoSomething, {
construct(target, argumentsList) {
value = "Oh gosh, they got me!";
return target;
}
});

var instance = new DoSomethingProxy();
assert.equal(value, "Oh gosh, they got me!");
});

it('"defineProperty" is a trap for Object.defineProperty()', function() {});
it('"deleteProperty" is a trap for the "delete" operator', function() {});
it('"enumerate" is a trap for for...in statements', function() {});
it('"get" is a trap for getting a property value', function() {});
it('"getOwnPropertyDescriptor" is a trap for Object.getOwnPropertyDescriptor()', function() {});
it('"getPrototypeOf" is a trap for the [[GetPrototypeOf]] internal method', function() {});
it('"has" is a trap for the in operator', function() {});
it('"isExtensible" is a trap for Object.isExtensible()', function() {});
it('"ownKeys" is a trap for Object.getOwnPropertyNames()', function() {});
it('"preventExtensions" is a trap for Object.preventExtensions()', function() {});
it('"set" is a trap for setting a property value', function() {});
it('"setPrototypeOf" is a trap for Object.setPrototypeOf()', function() {});
});
46 changes: 46 additions & 0 deletions katas/es6/language/proxy/basics.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 49: Proxy - basics
// To do: make all tests pass, leave the assert lines unchanged!

describe('proxies bring intercession to JavaScript', function() {

it('is made of handler, traps and target', function() {
let target = {};
let handler = {
// get is a trap
get(target, propKey, receiver) {
return 123;
}
};
let proxy = new Proxy(target, handler);

assert.equal(proxy.foo, 123);
});

it('can intercept operation on objects such as get and set', function() {
let target = {};
let handler = {
get(target, propKey, receiver) {
if (propKey === 'foo') {
return 123;
}
return target[propKey];
},
set(target, propKey, value) {
if (propKey === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('The age is not an integer');
}
}

target[propKey] = value;
return true;
}
};

let proxy = new Proxy(target, handler);

proxy.age = 26;
assert.equal(proxy.age, 26);
assert.equal(proxy.foo, 123);
});
});
91 changes: 91 additions & 0 deletions katas/es6/language/proxy/behaviour.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// 49: Proxy - behaviour
// To do: make all tests pass, leave the assert lines unchanged!

describe('handler has traps', function() {

describe('traps are the operations defined on the handler object', function() {
it('is called when the handler implements it', function() {
let target = {
foo: 987
};

let handler = {
get(target, propKey, receiver) {
return 123;
}
};

let proxy = new Proxy(target, handler);

assert.equal(proxy.foo, 123);
});

it('is not called when the handler does not implement it but target works as a fallback', function() {
let target = {
foo: 987
};

let handler = {
has(target, propKey, receiver) {
return true;
}
};

let proxy = new Proxy(target, handler);

assert.equal(proxy.foo, 987);
});
});
});

describe('target object is the aimed object to be intercepted', function() {

it ('target property is not called when a trap intercepts its opertion', function() {
var counter = (function() {
var that = {};
that.value = 0;

that.increments = function() {
that.value = that.value + 1;
}

return that;
})();

let handler = {
apply(target, propKey, receiver) {
return 999;
}
};

let proxyIncrement = new Proxy(counter.increments, handler);

assert.equal(proxyIncrement(), 999);
assert.equal(counter.value, 0);
});

it ('must be done manually', function() {
var counter = (function() {
var that = {};
that.value = 0;

that.increments = function() {
that.value = that.value + 1;
}

return that;
})();

let handler = {
apply(target, propKey, receiver) {
target();
return 999;
}
};

let proxyIncrement = new Proxy(counter.increments, handler);

assert.equal(proxyIncrement(), 999);
assert.equal(counter.value, 1);
});
});