Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
overlookmotel committed Sep 7, 2020
1 parent 2c3be9e commit 5b814d6
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 29 deletions.
38 changes: 17 additions & 21 deletions example/src/index.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
/* eeslint-disable no-console */

'use strict';

const {last} = require('lodash');
const input = function() {};
input.prototype = [11, 22];
Object.defineProperty(input.prototype, 'constructor', {value: input, writable: true, configurable: true});
input.prototype[Symbol.toStringTag] = 'Array';

let a = 1;
function outer() {
let b = a;
/*
class A extends Array {}
A.prototype[Symbol.toStringTag] = 'Object';
function inner() {
return `a = ${a}, b = ${b}`;
}
function setA(newA) {
a = newA;
}
function setB(newB) {
b = newB;
}
class A2 extends A {}
return {inner, setA, setB};
}
const input = A2;
*/

const {inner: inner1, setA, setB: setB1} = outer();
setA(100);
const {inner: inner2, setB: setB2} = outer();
setB1(200);
setB2(300);
/*
function input() {}
input.prototype = Array.prototype;
*/

module.exports = {inner1, inner2, last};
module.exports = input;
41 changes: 33 additions & 8 deletions lib/serialize/functions.js
Original file line number Diff line number Diff line change
Expand Up @@ -330,16 +330,20 @@ module.exports = {
);
}

const defaultProto = isGenerator // eslint-disable-line no-nested-ternary
? isAsync ? AsyncGeneratorPrototype : GeneratorPrototype
: isAsync ? AsyncFunctionPrototype : Function.prototype;

const protoDescriptor = Object.getOwnPropertyDescriptor(fn, 'prototype'),
proto = protoDescriptor ? protoDescriptor.value : undefined;
let protoValue;
if (!isArrowOrBound && ((!isAsync && !isMethod) || isGenerator)) {
// Should have prototype
if (isGenerator) {
// Prototype should not have constructor
// TODO Deal with where prototype redefined as non-object
if (
proto
&& Object.getPrototypeOf(proto) === defaultProto.prototype
&& Object.getOwnPropertyNames(proto).length === 0
&& Object.getOwnPropertySymbols(proto).length === 0
) {
Expand All @@ -353,9 +357,9 @@ module.exports = {
protoValue = proto;
}
} else {
// Prototype should have constructor - check it refers back to function
// TODO Deal with where prototype redefined as non-object
if (proto) { // eslint-disable-line no-lonely-if
// Prototype should be an object (not an Array, Set etc)
// and should have constructor - check constructor refers back to function
if (proto && protoIsPlainObject(proto)) { // eslint-disable-line no-lonely-if
const ctorDescriptor = Object.getOwnPropertyDescriptor(proto, 'constructor');
if (ctorDescriptor) {
const ctor = ctorDescriptor.value;
Expand All @@ -376,10 +380,6 @@ module.exports = {
if (proto) this.prototypes.set(proto, protoValue ? record : null);

// Wrap with properties
const defaultProto = isGenerator // eslint-disable-line no-nested-ternary
? isAsync ? AsyncGeneratorPrototype : GeneratorPrototype
: isAsync ? AsyncFunctionPrototype : Function.prototype;

// Workaround for Node v12 >= 12.16.0, where anonymous classes have a 'name' property
// defined as ''. On these Node versions, ignore the name prop if it's unchanged.
let skipNameKey = false;
Expand Down Expand Up @@ -509,6 +509,31 @@ function functionShouldForceDescriptor(key) {
return key === 'name';
}

const objectToString = Object.prototype.toString,
{toStringTag} = Symbol;

function protoIsPlainObject(prototype) {
const restoreDescriptors = [];

let obj = prototype;
do {
const descriptor = Object.getOwnPropertyDescriptor(obj, toStringTag);
if (descriptor) {
Object.defineProperty(obj, toStringTag, {value: null});
restoreDescriptors.push({proto: obj, descriptor});
}
obj = Object.getPrototypeOf(obj);
} while (obj);

const isPlain = objectToString.call(prototype) === '[object Object]';

for (const {proto, descriptor} of restoreDescriptors) {
Object.defineProperty(proto, toStringTag, descriptor);
}

return isPlain;
}

/**
* Create proxy to use as arguments for calling functions.
* Any function can be called with `fn(...argumentsProxy)`.
Expand Down

0 comments on commit 5b814d6

Please sign in to comment.