tc39 / proposal-limited-arraybuffer Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
Since JavaScript and WebAssembly can communicate with each other by accessing the same Arraybuffer, and the WebAssembly.Memory
object has the ability to export its internal Arraybuffer by calling the buffer
method on it. If so, what would be the behavior if we freeze the exported Arraybuffer and mutate the corresponding memory of this Arraybuffer by the Wasm instruction like i32.store
οΌWithout messing things up, I think the better ways are:
var memory = new WebAssembly.Memory({ initial:10, maximum:100 });
var arraybuffer = memory.buffer; // returns an Arraybuffer instance.
arraybuffer.prototype.freeze(); // freeze the buffer.
WebAssembly.instantiateStreaming(fetch('memory.wasm'), { js: { mem: memory } })
.then(obj => {
// ...
// call the exported method which would mutate the value of a specific location of memory,
// what should be the behavior here?
});
In conclusion, I think ArrayBuffer itself should not take the responsibility of the mutability, this ability should be controlled by the view lying on it. How do you think?
Consider an application using JavaScript and WebAssembly, communicating through the Wasm heap.
If the JS wants to pass around a read-only slice of the Wasm heap (a JS ArrayBuffer object), the JS must either pass around a TypedArray and always make sure to use it's .byteLength and .byteOffset properties to ensure correct usage, or copy the memory in the slice into a new ArrayBuffer.
One wants the slice to be read-only in order to prevent writing to the memory, and one doesn't want to move around the entire ArrayBuffer object, as that would allow reading into the memory at practically arbitrary locations.
Without being able to do both, view a section of an ArrayBuffer, and mark it as read-only, developers will have to find a workaround, which will likely come to creating ad-hoc wrapper classes or copying.
Could sliced views be introduced into the proposal alongside read-only views?
The only two questions that I would have regarding an introduction of the idea would be the following:
From the README:
Cannot construct the read-write view from readOnlyView.buffer
To prevent this problem ^, and the potential problem mentioned on the 5th slide of the current stage 1 proposal slides, I suggest introducing a new class, ReadOnlyArrayBuffer
, analogous to the present SharedArrayBuffer
.
By constructing a ReadOnlyArrayBuffer
from a read-write ArrayBuffer
, and creating a TypedArray view on the read-only buffer, TypedArray.buffer will yield the same ReadOnlyArrayBuffer
object.
Example:
const rw_buffer = new ArrayBuffer (10);
const rw_view = new Uint8Array(rw_buffer);
// nothing changes here
for ( let i = 0; i < 10; ++i ) {
rw_view[i] = I;
}
const ro_buffer = new ReadOnlyArrayBuffer(rw_buffer);
const ro_view = Uint8Array(ro_buffer);
assert(ro_buffer === ro_view.buffer);
// ro_view is an Uint8Array containing 0..=10
for ( let i = 0; i < 10; ++i ) {
assert(ro_view[i] === i);
}
ro_view[0] = 1; // TypeError
The class would be usable in almost every place that ArrayBuffers and SharedArrayBuffers are currently usable, including DataViews, and any WebIDL functions that accept ArrayBuffer sources.
(On second thought, wouldn't there need to be a SharedReadOnlyArrayBuffer
too?)
I can see freezing buffers being handy; just started to use them seriously for image data.
Do you think there should be an API to test if said buffer is already frozen or not?
TIA
Originally posted by @tomByrer in https://github.com/Jack-Works/proposal-freeze-arraybuffer-and-readonly-view/discussions/4
based on the meeting conclusion. we should investigate the problem & solution together instead of one-by-one
This must copy the data into a new readonly array buffer. For the data properties to be truly readonly, they must be frozen with non-configurable, non-writable descriptors, so the Object.getOwnPropertyDescriptor(typedarray, '0')
must have { configurable: false, writeable: false }
(and a data value). However, if the readonly view of the underlying buffer
shared the same memory, the data property could be changed by the original readwrite buffer:
const readwrite = new Uint8Array(1);
assert.equal(readwrite[0], 0);
assert.equal(Object.getOwnPropertyDescriptor(readwrite, '0').configurable, true);
assert.equal(Object.getOwnPropertyDescriptor(readwrite, '0').writable, true);
const readonly = new Uint8Array(array.buffer, { readonly: true });
assert.equal(readonly[0], 0);
assert.equal(Object.getOwnPropertyDescriptor(readonly, '0').configurable, false);
assert.equal(Object.getOwnPropertyDescriptor(readonly, '0').writable, false);
// This cannot change the readonly data, per the proxy invariants
readwrite[0] = 1;
// This data property must always report `value === 0`, per the proxy invariants
assert.equal(readonly[0], 0);
This just means the underlying buffer must be copied to a new readonly buffer, and isn't just a "view" of the underlying data.
Follow-on of discussion in #13, I organized ideas with a new "new integrity level" that freeze the internal state of an object. What do you think?
(cc @erights, @ljharb, @phoddie, @syg)
Object.freeze
)harden
harden
is recursive, stabilize
is not.harden
care about the property descriptors, stabilize
only care about the meaningful fields (and internal slots) that play roles in its data structure.isStable(x)
stablilzed(x)
Data type | Status | Description |
---|---|---|
Primitive (1 , true ) |
π | Born stabilized. |
Boxed primitive (new Number(1) ) |
π | Born stabilized. |
Array |
β | Make its all array index properties unconfigurable and non-writable. Refuse to add new array index properties. |
ArrayBuffer |
β | Refuse to modify data inside [[ArrayBufferData]] (but allowing detach to transfer).Refuse to modify [[ArrayBufferByteLength]] (refuse to expand/shrink size). |
Date |
β | Refuse to modify [[DateValue]] . |
Errors (EvalError , ...) |
β | To be decided. |
FinalizationRegistry & WeakRef |
β | To be decided. |
Function |
πβ | Can you change it anyway? Make length and name unconfigurable? |
globalThis |
β | To be decided. Refuse to define new global variable? What about DOM with ID? |
Iterators (ArrayIterator , ...) |
β | To be decided. |
Map & Set |
β | Refuse to modify [[MapData]] or [[SetData]] field. |
Promise |
β | Refuse to be stabilized. It's either already stabilized (fulfilled/rejected), or useless after hardened (pending). |
Proxy |
β‘οΈ | Passthrough. It will invoke the [[Get]] trap with Symbol.harden . |
RegExp |
β | Make its lastIndex property non-writable.Refuse to compile() . |
ShadowRealm |
β | To be decided. Possible options: β Refuse to be stabilized β Refuse to compile new code (by evaluate , eval , Function or importValue ) |
TypedArrays/DataView |
β | Refuse to be stabilized. It is a view, you must freeze the underlying buffer with the buffer directly. |
WeakMap & WeakSet |
β | Refuse to modify [[WeakMapData]] or [[WeakSetData]] field. |
Symbol.stabilize
protocol:
class T {
#data = new Set()
#hardened = false
;[Symbol.stabilize]() {
harden(this.#data)
this.#hardened = true
}
add(x) {
this.#data.add(x)
}
}
Those methods are useful but not directly related to the new integrity level, and not possible to make a unified protocol for all objects. I list them case-by-case.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.