knockoutjs replaced slow obj.__proto__ with Object.setPrototypeOf()

This commit is contained in:
djmaze 2020-10-28 20:19:38 +01:00
parent d49916731f
commit 5a0215987a
7 changed files with 100 additions and 157 deletions

View file

@ -59,14 +59,10 @@ ko.computed = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, opt
computedObservable.hasWriteFunction = typeof writeFunction === "function";
// Inherit from 'subscribable'
if (!ko.utils.canSetPrototype) {
// 'subscribable' won't be on the prototype chain unless we put it there directly
ko.utils.extend(computedObservable, ko.subscribable['fn']);
}
ko.subscribable['fn'].init(computedObservable);
// Inherit from 'computed'
ko.utils.setPrototypeOfOrExtend(computedObservable, computedFn);
Object.setPrototypeOf(computedObservable, computedFn);
if (options['pure']) {
state.pure = true;
@ -485,9 +481,7 @@ var deferEvaluationOverrides = {
// Note that for browsers that don't support proto assignment, the
// inheritance chain is created manually in the ko.computed constructor
if (ko.utils.canSetPrototype) {
ko.utils.setPrototypeOf(computedFn, ko.subscribable['fn']);
}
Object.setPrototypeOf(computedFn, ko.subscribable['fn']);
// Set the proto values for ko.computed
var protoProp = ko.observable.protoProperty; // == "__ko_proto__"

View file

@ -23,14 +23,10 @@ ko.observable = initialValue => {
observable[observableLatestValue] = initialValue;
// Inherit from 'subscribable'
if (!ko.utils.canSetPrototype) {
// 'subscribable' won't be on the prototype chain unless we put it there directly
ko.utils.extend(observable, ko.subscribable['fn']);
}
ko.subscribable['fn'].init(observable);
// Inherit from 'observable'
ko.utils.setPrototypeOfOrExtend(observable, observableFn);
Object.setPrototypeOf(observable, observableFn);
return observable;
}
@ -52,9 +48,7 @@ var observableFn = {
// Note that for browsers that don't support proto assignment, the
// inheritance chain is created manually in the ko.observable constructor
if (ko.utils.canSetPrototype) {
ko.utils.setPrototypeOf(observableFn, ko.subscribable['fn']);
}
Object.setPrototypeOf(observableFn, ko.subscribable['fn']);
var protoProperty = ko.observable.protoProperty = '__ko_proto__';
observableFn[protoProperty] = ko.observable;

View file

@ -5,7 +5,7 @@ ko.observableArray = initialValues => {
throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
var result = ko.observable(initialValues);
ko.utils.setPrototypeOfOrExtend(result, ko.observableArray['fn']);
Object.setPrototypeOf(result, ko.observableArray['fn']);
return result.extend({'trackArrayChanges':true});
};
@ -57,9 +57,7 @@ ko.observableArray['fn'] = {
// Note that for browsers that don't support proto assignment, the
// inheritance chain is created manually in the ko.observableArray constructor
if (ko.utils.canSetPrototype) {
ko.utils.setPrototypeOf(ko.observableArray['fn'], ko.observable['fn']);
}
Object.setPrototypeOf(ko.observableArray['fn'], ko.observable['fn']);
// Populate ko.observableArray.fn with read/write functions from native arrays
// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array

View file

@ -27,7 +27,7 @@ ko.subscription.prototype.disposeWhenNodeIsRemoved = function (node) {
};
ko.subscribable = function () {
ko.utils.setPrototypeOfOrExtend(this, ko_subscribable_fn);
Object.setPrototypeOf(this, ko_subscribable_fn);
ko_subscribable_fn.init(this);
}
@ -187,9 +187,7 @@ ko.exportProperty(ko_subscribable_fn, 'getSubscriptionsCount', ko_subscribable_f
// For browsers that support proto assignment, we overwrite the prototype of each
// observable instance. Since observables are functions, we need Function.prototype
// to still be in the prototype chain.
if (ko.utils.canSetPrototype) {
ko.utils.setPrototypeOf(ko_subscribable_fn, Function.prototype);
}
Object.setPrototypeOf(ko_subscribable_fn, Function.prototype);
ko.subscribable['fn'] = ko_subscribable_fn;

View file

@ -7,10 +7,6 @@ ko.utils = (() => {
source && Object.entries(source).forEach(prop => target[prop[0]] = prop[1]);
return target;
},
setPrototypeOf = (obj, proto) => {
obj.__proto__ = proto;
return obj;
},
// For details on the pattern for changing node classes
// see: https://github.com/knockout/knockout/issues/1597
toggleDomNodeCssClass = (node, classNames, shouldHaveClass) => {
@ -22,8 +18,6 @@ ko.utils = (() => {
}
};
var canSetPrototype = ({ __proto__: [] } instanceof Array);
return {
arrayRemoveItem: (array, itemToRemove) => {
var index = array.indexOf(itemToRemove);
@ -35,14 +29,8 @@ ko.utils = (() => {
}
},
canSetPrototype: canSetPrototype,
extend: extend,
setPrototypeOf: setPrototypeOf,
setPrototypeOfOrExtend: canSetPrototype ? setPrototypeOf : extend,
objectForEach: objectForEach,
objectMap: (source, mapping, mappingOwner) => {