-
Notifications
You must be signed in to change notification settings - Fork 27.9k
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
Fix updates failing during output of a notebook #144868
Conversation
@@ -32,7 +60,7 @@ export class ExtHostNotebookDocuments implements extHostProtocol.ExtHostNotebook | |||
$acceptModelChanged(uri: UriComponents, event: SerializableObjectWithBuffers<extHostProtocol.NotebookCellsChangedEventDto>, isDirty: boolean, newMetadata?: NotebookDocumentMetadata): void { | |||
const document = this._notebooksAndEditors.getNotebookDocument(URI.revive(uri)); | |||
const e = document.acceptModelChanged(event.value, isDirty, newMetadata); | |||
this._onDidChangeNotebookDocument.fire(deepFreeze(e)); | |||
this._onDidChangeNotebookDocument.fire(partialFreeze(e)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was getting this with a full freeze:
ERR Cannot freeze array buffer views with elements: TypeError: Cannot freeze array buffer views with elements
at Function.freeze (<anonymous>)
at deepFreeze (d:\Source\vscode\out\vs\base\common\objects.js:36:20)
at ExtHostNotebookDocuments.$acceptModelChanged (d:\Source\vscode\out\vs\workbench\api\common\extHostNotebookDocuments.js:32:77)
at RPCProtocol._doInvokeHandler (d:\Source\vscode\out\vs\workbench\services\extensions\common\rpcProtocol.js:399:27)
at RPCProtocol._invokeHandler (d:\Source\vscode\out\vs\workbench\services\extensions\common\rpcProtocol.js:384:45)
at RPCProtocol._receiveRequest (d:\Source\vscode\out\vs\workbench\services\extensions\common\rpcProtocol.js:311:32)
at RPCProtocol._receiveOneMessage (d:\Source\vscode\out\vs\workbench\services\extensions\common\rpcProtocol.js:243:26)
at d:\Source\vscode\out\vs\workbench\services\extensions\common\rpcProtocol.js:115:52
at Listener.invoke (d:\Source\vscode\out\vs\base\common\event.js:420:27)
at Emitter.fire (d:\Source\vscode\out\vs\base\common\event.js:559:34)**
**
because the output.items.data were not freezable.
if (!append) { | ||
output.items.length = 0; | ||
output.items.length = 0; // This crashes without a copy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also noticed this throwing an exception while running the same code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have a stack trace? Is it throwing because the event processing froze it? That wouldn't be good...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I believe it's crashing because of the freeze.
To repro this issue:
print("Start")
import time
for i in range(100):
time.sleep(0.1)
print(i)
print("End")
|
|
||
const hasBuffer = (typeof Buffer !== 'undefined'); | ||
|
||
export function partialFreeze<T>(obj: T): T { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bit messy, hoping you guys have a cleaner way to do this. Maybe modifying the original deepFreeze to do the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe modifying the original deepFreeze to do the same?
💯% All users of deepFreeze
should benefit from this goodness. There is already a check to decide to decent on an object or not. This check should be extended.
Also, this shouldn't be checking for Buffer
- that's a nodejs only type and where are here in common
-land. I also believe the error is coming from the underlying typed array, this fails the same way
> var a = new Uint8Array(12)
undefined
> Object.freeze(a)
Uncaught TypeError: Cannot freeze array buffer views with elements
at Function.freeze (<anonymous>)
There should be a check iff an object is a typed array - quite a few candidates according to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays#typed_array_views. Good news is they are instanceof-able, e.g candidate instanceof Float32Array
works etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for far. I have added a few comments and suggestions for improvements. I will also push a change that removes the deepFreeze to unblock you.
|
||
const hasBuffer = (typeof Buffer !== 'undefined'); | ||
|
||
export function partialFreeze<T>(obj: T): T { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe modifying the original deepFreeze to do the same?
💯% All users of deepFreeze
should benefit from this goodness. There is already a check to decide to decent on an object or not. This check should be extended.
Also, this shouldn't be checking for Buffer
- that's a nodejs only type and where are here in common
-land. I also believe the error is coming from the underlying typed array, this fails the same way
> var a = new Uint8Array(12)
undefined
> Object.freeze(a)
Uncaught TypeError: Cannot freeze array buffer views with elements
at Function.freeze (<anonymous>)
There should be a check iff an object is a typed array - quite a few candidates according to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays#typed_array_views. Good news is they are instanceof-able, e.g candidate instanceof Float32Array
works etc.
if (!append) { | ||
output.items.length = 0; | ||
output.items.length = 0; // This crashes without a copy |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have a stack trace? Is it throwing because the event processing froze it? That wouldn't be good...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest to take in the changes for deepFreeze
(checking for typed array) but no cloning of outputs or such. Instead, the event itself shouldn't likely be using deepFreeze
but some level of shallow freeze.
I modified deepFreeze to support an exclusion list. I then used this at the event location to exclude freezing the outputs. |
Not a fan of that tbh -
It is my bad that I started with |
Yeah that makes more sense. Only freeze event properties, not the notebook itself. |
@@ -294,6 +294,10 @@ export class ExtHostNotebookDocument { | |||
} | |||
} | |||
|
|||
// Freeze event properties so handlers cannot accidentally modify them | |||
deepFreeze(result.cellChanges); | |||
deepFreeze(result.contentChanges); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shallow freeze only, otherwise NotebookCell
instances are frozen
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes this should just be object.freeze instead of deepFreeze
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although it's weird that the output wasn't frozen? I think I need to debug the actual contents here to see what's in them. Object. freeze would certainly work but there might be more that can be frozen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
Ops, post merge (while writing the TPI) I realised this was still freezing the notebook itself and its metadata. Pushed another change on top of things |
This PR fixes microsoft/vscode-jupyter#9327
Outputs that contain any data would crash during an update preventing the cell output update from coming through to an extension.
I believe the issue was originally caused by this commit (our tests started failing this morning):
#144679