Brandon Benvie (2013-12-03T21:12:28.000Z)
domenic at domenicdenicola.com (2013-12-10T01:34:28.757Z)
On 12/3/2013 11:29 AM, Allen Wirfs-Brock wrote: > I don't have the time right now, but as a rough approximation take the > most recent specification of [MixinProperties](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-mixinproperties) (which is the guts of > Object.mixin) > rewrite in in JS. Replace each call of RebindSuper(x,y) with > x.toMethod(y). Replace each call of SameValue(GetSuperBinding(x), > source) with (typeof x === "function"), This should be pretty close ```js function Assert(test) { if (!test) { throw new Error("Assertion failure"); } } function Type(value) { switch (typeof value) { case "string": return "String"; case "number": return "Number"; case "boolean": return "Boolean"; case "symbol"; return "Symbol"; case "undefined"; return "Undefined"; case "object": if (value === null) { return "Null"; } case "function": return "Object"; } } // 6.2.4.2 IsDataDescriptor function IsDataDescriptor(Desc) { // step 1 if (Desc === undefined) { return false; } // step 2 if (!("value" in desc || "writable" in desc)) { return false; } // step 3 return true; } // 7.4.2 IteratorNext function IteratorNext(iterator, value) { // Step 2-3 const result = iterator.next(value); // Step 4 if (Type(result) !== "Object") { throw new TypeError(); } // Step 5 return result; } // 7.4.3 IteratorComplete function IteratorComplete(iterResult) { // Step 1 Assert(Type(iterResult) === "Object"); // Step 2 const { done } = iterResult; // Step 3 return !!done; } // 7.4.5 IteratorStep function IteratorStep(iterator, value) { // Step 2-3 const result = IteratorNext(iterator, value); // Step 4-5 const done = IteratorComplete(result); // Step 6 if (done) { return false; } //Step 7 return result; } // 19.1.2.15 Object.mixin function mixin(target, source) { // step 1-2 const to = ToObject(target); // step 3-4 const from = ToObject(source); // step 5 return MixinProperties(to, from); } // 19.1.2.15.1 MixinProperties function MixinProperties(target, source) { // step 1 Assert(Type(target) === "Object"); // step 2 Assert(Type(source) === "Object"); // step 3 - 4 const keys = Object.getOwnPropertyKeys(source).values(); // step 5 let gotAllNames = false; // step 6 let pendingException = undefined; // step 7 while (gotAllNames === false) { // step 7.a - 7.b const next = IteratorStep(keys); // step 7.c if (next === false) { gotAllNames = true; // step 7.d } else { // step 7.d.i - 7.d.ii const nextKey = IteratorValue(next); // step 7.d.iv const desc = Object.getOwnPropertyDescriptor(source, nextKey); // step 7.d.v if (desc !== undefined) { // step 7.d.v.1 if (IsDataDescriptor(desc)) { // step 7.d.v.1.a const propValue = desc.value; // step 7.d.v.1.b if (typeof propValue === "function") { try { // step 7.d.v.1.b.i const newFunc = MixinProperties(propValue.toMethod(target), propValue); // step 7.d.v.1.b.iii desc.value = newFunc; } catch (e) { // step 7.d.v.1.b.ii if (pendingException === undefined) { pendingException = e; } } } } else { // step 7.d.v.2.a const getter = desc.get; // step 7.d.v.2.b if (typeof getter === "function") { try { // step 7.d.v.2.b.i const newFunc = MixinProperties(getter.toMethod(target), getter); // step 7.d.v.2.b.iii desc.get = newFunc; } catch (e) { // step 7.d.v.2.b.ii if (pendingException === undefined) { pendingException = e; } } } // step 7.d.v.2.c const setter = desc.set; // step 7.d.v.2.d if (typeof setter === "function") { try { // step 7.d.v.2.d.i const newFunc = MixinProperties(setter.toMethod(target), setter); // step 7.d.v.2.d.iii desc.set = newFunc; } catch (e) { // step 7.d.v.2.d.ii if (pendingException === undefined) { pendingException = e; } } } } } try { // step 7.d.v.3 Object.defineProperty(target, nextKey, desc); } catch (e) { // step 7.d.v.4 if (pendingException === undefined) { pendingException = e; } } } } // step 8 if (pendingException !== undefined) { throw pendingException; } // step 9 return target; } ```