Skip to content

different behavior between v8.deserialize(v8.serialize(Array<mixed-ArrayBuffer-and-ArrayBufferView>)) and structuredClone(Array<mixed-ArrayBuffer-and-ArrayBufferView>) #48153

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
navegador5 opened this issue May 24, 2023 · 0 comments

Comments

@navegador5
Copy link

navegador5 commented May 24, 2023

Version

Node.js v20.1.0.

Platform

Linux dev 5.15.0-71-generic #78-Ubuntu SMP x86_64 x86_64 x86_64 GNU/Linux

Subsystem

I am not sure. but I think it should be located at _writeHostObject, coz I saw TreatArrayBufferViewsAsHostObjects is always true

What steps will reproduce the bug?

var ab      = new ArrayBuffer(4);
var u8view  = new Uint8Array(ab);
var u16view = new Uint16Array(ab);
var dv      = new DataView(ab);
u16view[0] = 65535
/*
> u8view.buffer === u16view.buffer
true
> u8view.buffer === dv.buffer
true
> 
> dv.buffer === ab
true
> 

> 
65535
> 
> ab
ArrayBuffer { [Uint8Contents]: <ff ff 00 00>, byteLength: 4 }
> 
*/


var wrap_in_ary = [ab,u8view,u16view,dv];    // wrap them in a small array, make sure they can find the referenced-array-buffer  
/*
> wrap_in_ary
[
  ArrayBuffer { [Uint8Contents]: <ff ff 00 00>, byteLength: 4 },
  Uint8Array(4) [ 255, 255, 0, 0 ],
  Uint16Array(2) [ 65535, 0 ],
  DataView {
    byteLength: 4,
    byteOffset: 0,
    buffer: ArrayBuffer { [Uint8Contents]: <ff ff 00 00>, byteLength: 4 }
  }
]
> 
*/


//---IF i dupe them using  structuredClone,  everything is OK,  each-ab-view(also the data-view) can point-to the same array-buffer

var dupe_with_sc = structuredClone(wrap_in_ary);

/*
[
  ArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 },
  Uint8Array(4) [ 0, 0, 0, 0 ],
  Uint16Array(2) [ 0, 0 ],
  DataView {
    byteLength: 4,
    byteOffset: 0,
    buffer: ArrayBuffer { [Uint8Contents]: <00 00 00 00>, byteLength: 4 }
  }
]
*/

var [ab_using_sc,  nu8_using_sc,   nu16_using_sc,   ndv_using_sc] = dupe_with_sc
/*

//---correct ,their have the same buffer: 

assert(ab_using_sc  === nu8_using_sc.buffer);
assert(ab_using_sc  === nu16_using_sc.buffer);
assert(ab_using_sc  === ndv_using_sc.buffer);


//they USE the same array-buffer
> var u32vw = new Uint32Array(ab_using_sc)
> u32vw[0] = 2**32-1
4294967295
> 
> 
> 
> ab_using_sc
ArrayBuffer { [Uint8Contents]: <ff ff ff ff>, byteLength: 4 }
> 
> 
> ndv_using_sc
DataView {
  byteLength: 4,
  byteOffset: 0,
  buffer: ArrayBuffer { [Uint8Contents]: <ff ff ff ff>, byteLength: 4 }
}
> 
> nu8_using_sc
Uint8Array(4) [ 255, 255, 255, 255 ]
> 
> nu16_using_sc
Uint16Array(2) [ 65535, 65535 ]
> 

//recover it
u32vw[0] = 65535

*/



//BUT  IF i use   v8.deserialize(v8.serialize(wrap_in_ary))  some thing goes differnet


var dupe = v8.serialize(wrap_in_ary);
/*
> dupe                                                                           sub-type:dataview
                                                                                       |
<Buffer ff 0d 41 04 [42 04 ff ff 00 00| 5c 01 04 ff ff 00 00| 5c 04 04 ff ff 00 00| 5c 09 04 ff ff 00 00 | 24 00 04]>
                      |                                                             |
                    ary-buf                                                        host
> 
*/

var deser = v8.deserialize(dupe)

/*
> deser
[
  ArrayBuffer { [Uint8Contents]: <ff ff 00 00>, byteLength: 4 },        // different with the-new-dataview     【#1】 
  Uint8Array(4) [ 255, 255, 0, 0 ],                                     // correct : nu8.byteOffset  13 | nu8.byteLength  4  | nu8.buffer  point-to-the-new-dataview
  Uint16Array(2) [ 65535, 0 ],                                          // correct : nu16.byteOffset 20 | nu16.byteLength 4  | nu16.buffer point-to-the-new-dataview
  DataView {                                                            // different with the-new-array-buf  at 【#1】                    
    byteLength: 4,
    byteOffset: 27,
    buffer: ArrayBuffer {
      [Uint8Contents]: <ff 0d 41 04 42 04 ff ff 00 00 5c 01 04 ff ff 00 00 5c 04 04 ff ff 00 00 5c 09 04 ff ff 00 00 24 00 04>,
      byteLength: 34
    }
  }
]
> 
*/

var [nab,nu8,nu16,ndv] = deser;


/* 


//---CORRECT---  nu8 nu16 ndv  share the same-buffer

assert (nu8.buffer === nu16.buffer)
assert (nu8.buffer === ndv.buffer)

// nab NOT 
> assert(nu8.buffer === nab)
Uncaught AssertionError [ERR_ASSERTION]: false == true
    at REPL108:1:1
    at Script.runInThisContext (node:vm:129:12)
    at REPLServer.defaultEval (node:repl:571:29)
    at bound (node:domain:421:15)
    at REPLServer.runBound [as eval] (node:domain:432:12)
    at REPLServer.onLine (node:repl:898:10)
    at REPLServer.emit (node:events:539:35)
    at REPLServer.emit (node:domain:475:12)
    at [_onLine] [as _onLine] (node:internal/readline/interface:424:12)
    at [_line] [as _line] (node:internal/readline/interface:885:18) {
  generatedMessage: true,
  code: 'ERR_ASSERTION',
  actual: false,
  expected: true,
  operator: '=='
}
> 

> var nab_u32vw = new Uint32Array(nab)
undefined
> nab_u32vw[0] = 2**32-1
4294967295
> 
> nab
ArrayBuffer { [Uint8Contents]: <ff ff ff ff>, byteLength: 4 }
> 
> ndv
DataView {
  byteLength: 4,
  byteOffset: 27,
  buffer: ArrayBuffer {               unchanged
    [Uint8Contents]: <ff 0f 41 04 |42 04 ff ff 00 00| 5c 01 04 6f ff 00 00 5c 04 04 ff ff 00 00 5c 09 04 ff ff 00 00 24 00 04>,
    byteLength: 34
  }
}
> 

*/

How often does it reproduce? Is there a required condition?

always

What is the expected behavior? Why is that the expected behavior?

I think its behavior should be same with structuredClone

What do you see instead?

different behavior with structuredClone

Additional information

No response

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants
@navegador5 and others