-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Use maybe_initialize
for non-deferred HasProps
initialization
#14431
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: branch-4.0
Are you sure you want to change the base?
Conversation
Should we go ahead and start a |
Yes, good idea. |
@bokeh/dev I've gone ahead and created |
cec8878
to
cdc072f
Compare
@ianthomas23 do you have ready any concrete examples of the sort of things this would enable that are not currently possible, e.g. with JS framework integrations? I would be interested to run/study them. |
@bryevdv Yes, see the bokehjs-examples repo. There are plain vanilla TypeScript examples and a React and a Vue example. It is not well documented yet, I'll be spending my last planned 1.5 days to fix this in the next 2 weeks, and will also change the example included to not include random numbers so that they are deterministic and I can use playwright screenshot tests in CI. If you want to try them out before I have updated the documentation, the best approach is to download the 2 artifacts from the latest CI run (https://github.com/bokeh/bokehjs-examples/actions/runs/14555646830). The rm -rf node_modules
npm install
npm run build
npm run serve to see it working. |
c40c1b0
to
98f426f
Compare
There were two bokehjs integration tests that were failing, but now pass. The tests were regressions for issues #13104 and #13771 that defined new figure classes derived from the bokeh/bokehjs/src/lib/api/figure.ts Line 286 in 131ed5c
attrs .
However, the new |
c2e996f
to
df95ad5
Compare
@mattpap what shall we do here for 4.0? I believe you had mentioned an alternate approach but unless it's something that can be put forward sooner rather than later, or can avoid the API change entirely, then I think we have to consider that something is better than nothing in terms of making BokehJS more widely adoptable. |
This is a candidate fix for #13732.
Initialisation of
HasProps
-derived classes in BokehJS currently occurs in theHasProps
constructor, provided it is not deferred because we are deserialising from JSON. This sets attributes of derived classes which can be dangerous as those attributes are not guaranteed to exist before we have reached the bodies of the derived-class constructors. This limits the use of BokehJS in frontend-only applications (i.e. without Python).Here the problem is fixed by explicitly initialising in the final constructor rather than in
HasProps
. This is achieved by the constructor of each class derived fromHasProps
calling a new functionmaybe_initialize
. If it is called from a final constructor and initialisation has not been deferred then initialisation occurs. The code path for deferred initialisation is not altered except for multiple calls tomaybe_initialize
which immediately return. The runtime identification of if an object is of a specific class has to be done carefully as it has to work when BokehJS is minified and actual class names are replaced by single letters. FortunatelySomeClass.__name__
andobject.constructor.__name__
already exist in BokehJS for this.The initialisation is explicit, occurring precisely where it should occur. This PR is necessarily large as it touches many files, but the changes are simple to understand.
Testing this locally there are just 2 BokehJS unit test failures, and it works with my various experiments of using BokehJS in TypeScript projects. The size of the built
bokeh.min.js
increases from 1106 kB to 1119 kB, so a 1.2% increase.There are two separate
Figure
classes in the same class hierarchy (models/plots/figure.ts
andapi/figure.ts
) which potentially could break the class name identification used due to non-uniqueness. However the latter is derived from the former and does not add any new attributes or properties, so it works provided there is nomaybe_initialize
call in the latter.Strictly speaking only concrete (non-abstract) classes need the
maybe_initialize
call. However,node make test:defaults
instantiates abstract classes too so it has been necessary to add constructors containingmaybe_initialize
to all classes derived fromHasProps
. This includes classes used for testing.Within the Bokeh repo this is fully backward-compatible (assuming I can fix the few failing tests), but it is an API breaking change for anyone who has written a BokehJS custom extension as each class derived from
HasProps
will now have to have a constructor that callsmaybe_initialize
in the correct way. There could potentially be some specialised used of derived classes here that is broken by this, so this is targetting Bokeh 4.0.