Brandon Benvie (2013-12-03T21:12:28.000Z)
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 (which is the guts of 
> Object.mixin) 
> http://people.mozilla.org/~jorendorff/es6-draft.html#sec-mixinproperties 
> <http://people.mozilla.org/%7Ejorendorff/es6-draft.html#sec-mixinproperties> and 
> 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;
}
```
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;
}
```