Skip to content

Commit

Permalink
a bit faster set
Browse files Browse the repository at this point in the history
  • Loading branch information
xaviergonz committed Mar 24, 2024
1 parent 8913696 commit a486c9a
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 21 deletions.
2 changes: 1 addition & 1 deletion apps/benchmark/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const tcModes: (ModelAutoTypeCheckingMode | false)[] = [
ModelAutoTypeCheckingMode.AlwaysOff,
]

const waitBetweenBenchmarks = () => sleep(500)
const waitBetweenBenchmarks = () => sleep(1000)

for (const tcMode of tcModes) {
let name = ""
Expand Down
62 changes: 42 additions & 20 deletions packages/lib/src/modelShared/sharedInternalModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ import { assertIsClassOrDataModelClass } from "./utils"
function createGetModelInstanceDataField<M extends AnyModel | AnyDataModel>(
modelProp: AnyModelProp,
modelPropName: string
): (model: M) => unknown {
): (this: M) => unknown {
const transformFn = modelProp._transform?.transform

if (!transformFn) {
// no need to use get since these vars always get on the initial $
return (model) => model.$[modelPropName]
return function (this) {
return this.$[modelPropName]
}
}

const transformValue = (model: M, value: unknown) =>
Expand All @@ -42,26 +44,26 @@ function createGetModelInstanceDataField<M extends AnyModel | AnyDataModel>(
applySet(model.$, modelPropName, newValue)
})

return (model) => {
return function (this) {
// no need to use get since these vars always get on the initial $
const value = model.$[modelPropName]
return transformValue(model, value)
const value = this.$[modelPropName]
return transformValue(this, value)
}
}

function setModelInstanceDataField<M extends AnyModel | AnyDataModel>(
model: M,
type SetModelInstanceDataFieldFn = <M extends AnyModel | AnyDataModel>(
modelProp: AnyModelProp,
modelPropName: string,
model: M,
value: unknown
): void {
// hack to only permit setting these values once fully constructed
// this is to ignore abstract properties being set by babel
// see https://github.com/xaviergonz/mobx-keystone/issues/18
if (!(model as any)[modelInitializedSymbol]) {
return
}

) => boolean | void

const setModelInstanceDataField: SetModelInstanceDataFieldFn = (
modelProp,
modelPropName,
model,
value
): void => {
if (modelProp._setter === "assign" && !getCurrentActionContext()) {
// use apply set instead to wrap it in an action
applySet(model, modelPropName as any, value)
Expand All @@ -84,6 +86,22 @@ function setModelInstanceDataField<M extends AnyModel | AnyDataModel>(
model.$[modelPropName] = untransformedValue
}

const setModelInstanceDataFieldWithPrecheck: SetModelInstanceDataFieldFn = (
modelProp,
modelPropName,
model,
value
): boolean => {
// hack to only permit setting these values once fully constructed
// this is to ignore abstract properties being set by babel
// see https://github.com/xaviergonz/mobx-keystone/issues/18
if (!(model as any)[modelInitializedSymbol]) {
return false
}
setModelInstanceDataField(modelProp, modelPropName, model, value)
return true
}

const idGenerator = () => getGlobalConfig().modelIdGenerator()
const tPropForId = tProp(typesString, idGenerator)
tPropForId._isId = true
Expand Down Expand Up @@ -246,16 +264,20 @@ export function sharedInternalModel<
ThisModel.prototype = Object.create(base.prototype)
ThisModel.prototype.constructor = ThisModel

let setFn: SetModelInstanceDataFieldFn = (modelProp, modelPropName, model, value) => {
if (setModelInstanceDataFieldWithPrecheck(modelProp, modelPropName, model, value)) {
setFn = setModelInstanceDataField
}
}

for (const [propName, propData] of Object.entries(modelProps)) {
if (!(basePropNames as Set<string>).has(propName)) {
const get = createGetModelInstanceDataField(propData, propName)

Object.defineProperty(ThisModel.prototype, propName, {
get() {
return get(this)
},
set(value: any) {
setModelInstanceDataField(this, propData, propName, value)
get,
set(value: unknown) {
setFn(propData, propName, this, value)
},
enumerable: true,
configurable: false,
Expand Down

0 comments on commit a486c9a

Please sign in to comment.