Adoption of the Typed Array Specification

# Arun Ranganathan (15 years ago)

Greetings, TC-39 WG and script mavens!

Browser vendors participating in the WebGL WG intend to implement the "Typed Arrays" specification, allowing for greater manipulation of binary data:

cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/TypedArray-spec.html

The draft specification (a work in progress) resides at Khronos, which is typically an unusual home for something integral to the rest of the web platform. Khronos is where we work on WebGL, which enjoys Google, Opera, Mozilla, and Apple participation, amongst other organizations.

The general usefulness of constructs such as ArrayBuffers (covered in the "Typed Arrays" draft specification) lends itself to other web platform specifications, such as the File API, parts of which are implemented in Firefox 3.6.3:

dev.w3.org/2006/webapi/FileAPI

In the above draft (also a work in progress), the Blob interface exposes an ArrayBuffer property, which can then be used with different views.

While implementations are currently proceeding unimpeded by standards-track considerations, it would be useful if Typed Arrays were taken on as a work item by TC-39, for more general inclusion in JavaScript. Should it live elsewhere, and if so, where?

-- A*

# Mark S. Miller (15 years ago)

On Thu, May 13, 2010 at 5:57 AM, Arun Ranganathan <arun at mozilla.com> wrote:

Greetings, TC-39 WG and script mavens!

Browser vendors participating in the WebGL WG intend to implement the "Typed Arrays" specification, allowing for greater manipulation of binary data:

cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/TypedArray-spec.html

The draft specification (a work in progress) resides at Khronos, which is typically an unusual home for something integral to the rest of the web platform. Khronos is where we work on WebGL, which enjoys Google, Opera, Mozilla, and Apple participation, amongst other organizations.

The general usefulness of constructs such as ArrayBuffers (covered in the "Typed Arrays" draft specification) lends itself to other web platform specifications, such as the File API, parts of which are implemented in Firefox 3.6.3:

dev.w3.org/2006/webapi/FileAPI

In the above draft (also a work in progress), the Blob interface exposes an ArrayBuffer property, which can then be used with different views.

While implementations are currently proceeding unimpeded by standards-track considerations, it would be useful if Typed Arrays were taken on as a work item by TC-39, for more general inclusion in JavaScript. Should it live elsewhere, and if so, where?

strawman:typed_arrays

I agree it should be taken on by TC39. On the strawman page, you are listed as the champion of this proposal. It is on the agenda (see 6.4 or 6.5) for the upcoming May 24/25 meeting. Hope to see you there!

# Kenneth Russell (15 years ago)

On Thu, May 13, 2010 at 8:19 AM, Mark S. Miller <erights at google.com> wrote:

On Thu, May 13, 2010 at 5:57 AM, Arun Ranganathan <arun at mozilla.com> wrote:

Greetings, TC-39 WG and script mavens!

Browser vendors participating in the WebGL WG intend to implement the "Typed Arrays" specification, allowing for greater manipulation of binary data:

cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/TypedArray-spec.html

The draft specification (a work in progress) resides at Khronos, which is typically an unusual home for something integral to the rest of the web platform.  Khronos is where we work on WebGL, which enjoys Google, Opera, Mozilla, and Apple participation, amongst other organizations.

The general usefulness of constructs such as ArrayBuffers (covered in the "Typed Arrays" draft specification) lends itself to other web platform specifications, such as the File API, parts of which are implemented in Firefox 3.6.3:

dev.w3.org/2006/webapi/FileAPI

In the above draft (also a work in progress), the Blob interface exposes an ArrayBuffer property, which can then be used with different views.

While implementations are currently proceeding unimpeded by standards-track considerations, it would be useful if Typed Arrays were taken on as a work item by TC-39, for more general inclusion in JavaScript.  Should it live elsewhere, and if so, where?

strawman:typed_arrays

Can this page be updated to point to the current draft of the TypedArray spec?

cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/TypedArray-spec.html

Thanks,

# Allen Wirfs-Brock (15 years ago)

Arun,

Thanks for forcing this into our attention. At a functional level, this appears to be proceeding in a reasonable direction. However, I think there are some problematic issues about the form and depth of the specification as well as related process issues.

The first words of the specification are " This specification describes additional core ECMAScript types...". This isn't something that the Khronos Group can do, as the ECMAScrpt specification including its core data types are under the control of Ecma TC39 and any modification or extensions to it will have to be approved by it and the Ecma general assembly. Since Mozilla is a member of both TC39 and Khronos you are doing the right thing by bringing this to TC39 and I'm sure we can work together on this matter.

However, I think the above statement about "core ECMAScript types" may exemplify a misperception that has deeper technical implications. The existing formulation of the Typed Array Specification really doesn't have anything in it involving "core ECMAScript types". Instead, it uses W3C WebIDL conventions to specify the behavior of a new family of what, in ECMAScript terminology, are known as "host objects". Host object, are objects that exist outside of an ECMAScript implementation but which may be accessed from within ECMAScrpt programs. Host objects, do not necessarily conform to the full semantics of ECMAScript objects and may not necessarily fully support or interoperate with all features of the ECMAScrpt language. For example, host objects may be anomalous in their support of prototype inheritance and in their implementation of the various property attributes. Historically, WebIDL based specifications have not addressed such issues and this has resulted in many interoperability issues among browsers.

The Khronos Group certainly has every right to specify "host objects" to serve as interfaces to their technologies. However, if the desire is for this form of binary data to be integrated into ECMAScript as a "core types" that is available in all ECMAScript implementations (independent of the host environment) then this needs to be addressed by TC39 using its specification techniques which will ensure that the necessary types and features fully integrate into the language. The existing Typed Array spec. probably works as a specification of a set of "host objects" and it is a good starting point as a set of functional requirements for new ECMAScript functionality but it is not adequate as the specification of a core ECMAScript extension. Hopefully, this is something we can take care of in the context of TC39.

Again, thanks for forcing this issue. Allen Wirfs-Brock Microsoft

# Kenneth Russell (15 years ago)

On Thu, May 13, 2010 at 11:29 AM, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com> wrote:

Arun,

Thanks for forcing this into our attention.  At a functional level, this appears to be proceeding in a reasonable direction.  However, I think there are some problematic issues about the form and depth of the specification as well as related process issues.

The first words of the specification are " This specification describes additional core ECMAScript types...".    This isn't something that the Khronos Group can do, as the ECMAScrpt specification including its core data types are under the control of Ecma TC39 and any modification or extensions to it will have to be approved by it and the Ecma general assembly.  Since Mozilla is a member of both TC39 and Khronos you are doing the right thing by bringing this to TC39 and I'm sure we can work together on this matter.

However, I think the above statement about "core ECMAScript types" may exemplify a misperception that has deeper technical implications.  The existing formulation of the  Typed Array Specification really doesn't have anything in it involving "core ECMAScript types".  Instead, it uses W3C WebIDL conventions to specify the behavior of a new family of what, in ECMAScript terminology, are known as "host objects".  Host object, are objects that exist outside of an ECMAScript implementation but which may be accessed from within ECMAScrpt programs.  Host objects, do not necessarily conform to the full semantics of ECMAScript objects and may not necessarily fully  support or interoperate with all features of the ECMAScrpt language.   For example, host objects may be anomalous in their support of prototype inheritance and in their implementation of the various property attributes.  Historically, WebIDL based specifications have not addressed such issues and this has resulted in many i  nteroperability issues among browsers.

The Khronos Group certainly has every right to specify "host objects"  to serve as interfaces to their technologies.  However, if the desire is for this form of binary data to be integrated into ECMAScript as a "core types" that is available in all ECMAScript implementations (independent of the host environment) then this needs to be addressed by TC39 using its specification techniques which will ensure that the necessary types and features fully integrate into the language.  The existing Typed Array spec. probably works as a specification of a set of "host objects" and it is a good starting point as a set of functional requirements for new ECMAScript functionality  but it is not adequate as the specification of a core ECMAScript extension.  Hopefully, this is something we can take care of in the context of TC39.

Allen,

Thanks for the feedback. I've revised this text in the TypedArray spec, as you're right that it isn't appropriate to describe these types as part of ECMAScript at the present time.

# Erik Arvidsson (15 years ago)

I'm surprised no one has said this yet but here goes:

ArrayBuffer needs to extend Array. In other words instances of ArrayBuffer needs to also be instances of Array

var ab = new ArrayBuffer; assert(ab instanceof ArrayBuffer); assert(ab instanceof Array);

You will also need to make sure that all the internal methods are defined. See 8.12 Algorithms for Object Internal Methods of ES5. For example what does it mean to do [[Delete]] on a byte array?

# Vladimir Vukicevic (15 years ago)

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways. At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in). Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

  • Vlad

----- "Erik Arvidsson" <erik.arvidsson at gmail.com> wrote:

I'm surprised no one has said this yet but here goes:

ArrayBuffer needs to extend Array. In other words instances of ArrayBuffer needs to also be instances of Array

var ab = new ArrayBuffer; assert(ab instanceof ArrayBuffer); assert(ab instanceof Array);

You will also need to make sure that all the internal methods are defined. See 8.12 Algorithms for Object Internal Methods of ES5. For example what does it mean to do [[Delete]] on a byte array?

# Mark S. Miller (15 years ago)

On Thu, May 13, 2010 at 5:15 PM, Vladimir Vukicevic <vladimir at mozilla.com>wrote:

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways. At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in). Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

in ES5:

var x = [];
for (var i = 0; i < N; i++) {
    x.push(0);
}
Object.seal(x);

The x that results from the above code is fully populated, of fixed length, and must remain fully populated. It is much closer to what programmers coming from other languages might regard as an array.

UInt8Array can even be described as

function UInt8Array(size) {
  const result = [];
  for (let i = 0; i < size; i++) {
    let value = 0; // Relies on ES-Harmony block level scoping of "let"
    Object.defineProperty(result, i, {
      get: function() { return value; },
      set: function(newValue) {
        if (notUInt8(newValue)) { throw new TypeError("oops"); }
        value = newValue;
      },
      enumerable: true
    }
  }
  return Object.seal(result);
}

Since the result is simply a constrained array, it still inherits all our nice shiny higher order methods from Array.prototype.

I am of course not suggesting that it be implemented that way. I'm not sure I'm even suggesting that it be specified that way. I'm only observing that a fixed length type-limited array is not necessarily at odds with the concepts already present in the language.

# Vladimir Vukicevic (15 years ago)

Ah right -- sorry, I keep thinking in terms of ES4. A sealed object certainly makes sense, though it also means that other named properties can't be attached... this was brought up as a desired thing, though I would be quite happy to just have them be sealed. Anyways, certainly something that should be discussed... the spec as written was using an odd mix of Web IDL and other language because we weren't sure where or how it would land. This is where I think the input of the ES group would be very welcome -- I don't think we have the ES language knowledge to really define this in terms of how it could look as an ES core feature.

However, another consideration is that the WebGL spec isn't ES specific, and yet has to depend on typed arrays. So perhaps we're really talking about two different specs: a main typed array spec that uses Web IDL and can be implemented generically in any language, as well as a separate spec describing ES types that happen to fulfill the requirements of typed arrays.

  • Vlad

----- "Mark S. Miller" <erights at google.com> wrote:

On Thu, May 13, 2010 at 5:15 PM, Vladimir Vukicevic < vladimir at mozilla.com > wrote:

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways. At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in). Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

in ES5:

var x = []; for (var i = 0; i < N; i++) { x.push(0); } Object.seal(x);

The x that results from the above code is fully populated, of fixed length, and must remain fully populated. It is much closer to what programmers coming from other languages might regard as an array.

UInt8Array can even be described as

function UInt8Array(size) { const result = []; for (let i = 0; i < size; i++) { let value = 0; // Relies on ES-Harmony block level scoping of "let" Object.defineProperty(result, i, { get: function() { return value; }, set: function(newValue) { if (notUInt8(newValue)) { throw new TypeError("oops"); } value = newValue; }, enumerable: true } } return Object.seal(result); }

Since the result is simply a constrained array, it still inherits all our nice shiny higher order methods from Array.prototype.

I am of course not suggesting that it be implemented that way. I'm not sure I'm even suggesting that it be specified that way. I'm only observing that a fixed length type-limited array is not necessarily at odds with the concepts already present in the language.

  • Vlad

----- "Erik Arvidsson" < erik.arvidsson at gmail.com > wrote:

I'm surprised no one has said this yet but here goes:

ArrayBuffer needs to extend Array. In other words instances of ArrayBuffer needs to also be instances of Array

var ab = new ArrayBuffer; assert(ab instanceof ArrayBuffer); assert(ab instanceof Array);

You will also need to make sure that all the internal methods are defined. See 8.12 Algorithms for Object Internal Methods of ES5. For example what does it mean to do [[Delete]] on a byte array?

# Garrett Smith (15 years ago)

On Thu, May 13, 2010 at 5:34 PM, Mark S. Miller <erights at google.com> wrote:

On Thu, May 13, 2010 at 5:15 PM, Vladimir Vukicevic <vladimir at mozilla.com> wrote:

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways.  At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in).  Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

in ES5:     var x = [];     for (var i = 0; i < N; i++) {         x.push(0);     }     Object.seal(x);

That is verbose.

The x that results from the above code is fully populated, of fixed length, and must remain fully populated. It is much closer to what programmers coming from other languages might regard as an array.

A FixedArrayLiteral would be better but the language does not have such construct.

var noElisions = [ length:N, sealed: true ];

# Mark S. Miller (15 years ago)

On Thu, May 13, 2010 at 5:43 PM, Vladimir Vukicevic <vladimir at mozilla.com>wrote:

Ah right -- sorry, I keep thinking in terms of ES4. A sealed object certainly makes sense, though it also means that other named properties can't be attached... this was brought up as a desired thing,

No problem:

function UInt8Array(size) {
  const result = [];
  for (let i = 0; i < size; i++) {
    let value = 0; // Relies on ES-Harmony block level scoping of "let"
    Object.defineProperty(result, i, {
      get: function() { return value; },
      set: function(newValue) {
        if (notUInt8(newValue)) { throw new TypeError("oops"); }
        value = newValue;
      },
      enumerable: true
    });
  }
  Object.defineProperty(result, 'length', {value: size});
  return result;
}
# Allen Wirfs-Brock (15 years ago)

Vladimir Vukicevic vladimir at mozilla.com<mailto:vladimir at mozilla.com> said: However, another consideration is that the WebGL spec isn't ES specific, and yet has to depend on typed arrays. So perhaps we're really talking about two different specs: a main typed array spec that uses Web IDL and can be implemented generically in any language, as well as a separate spec describing ES types that happen to fulfill the requirements of typed arrays.

If that is a concern, how do you expect these interfaces to work with other languages. In a C++ binding are the view objects and the buffer objects still going be distinct objects or are you expect to merge them into native C++ objects. I think that there is a pretty fundamental question here: does your (and similar) application need to expose binary buffers that exist natively in the implementation technology of your subsystem and which can be interchange among multiple client languages. Or, are you able and willing to directly work with native JavaScript buffer objects (assuming that such things exist) even it that a less natural form of access on your part. In the first case, “host objects” may be exactly what you need. If the second is what you would like, then we probably need a EcmaScript extension.

# Allen Wirfs-Brock (15 years ago)

I agree that you'd probably want make use of the Array.prototype methods in this domain but that doesn't necessarily require that (ab instanceof Array) is true. Also I would think that it is the various view objects where you would really want to make use of the Array methods.

# Alex Russell (15 years ago)

On May 13, 2010, at 4:57 PM, Erik Arvidsson wrote:

I'm surprised no one has said this yet but here goes:

ArrayBuffer needs to extend Array. In other words instances of ArrayBuffer needs to also be instances of Array

var ab = new ArrayBuffer; assert(ab instanceof ArrayBuffer); assert(ab instanceof Array);

You will also need to make sure that all the internal methods are defined. See 8.12 Algorithms for Object Internal Methods of ES5. For example what does it mean to do [[Delete]] on a byte array?

Similarly, I know that there's some concern about mutability, fixed-length, etc. for a byte-handling array type. The current TypedArray spec only deals with fixed arrays which is somewhat at odds with the Array type ancestry. Finding a way to have a mutable version of TypedArray to better fill the normal Array contract seems a natural extension of the current proposal.

# Alex Russell (15 years ago)

On May 13, 2010, at 5:15 PM, Vladimir Vukicevic wrote:

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways.

Sounds like a bug to be fixed ;-)

At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in). Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

That the length property of a particular array subclass leaves the constructor non-configurable and read-only isn't much of a trick in ES5. That said, why doesn't TypedArray spec a mutable variant? Surely it'd be useful.

-- Alex Russell slightlyoff at google.com alex at dojotoolkit.org BE03 E88D EABB 2116 CC49 8259 CF78 E242 59C3 9723

# Oliver Hunt (15 years ago)

On May 13, 2010, at 10:21 PM, Alex Russell wrote:

On May 13, 2010, at 5:15 PM, Vladimir Vukicevic wrote:

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways.

Sounds like a bug to be fixed ;-)

At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in). Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

That the length property of a particular array subclass leaves the constructor non-configurable and read-only isn't much of a trick in ES5. That said, why doesn't TypedArray spec a mutable variant? Surely it'd be useful.

The data is mutable, the length is not -- this is more in line with arrays in other languages, but more importantly the whole point of the typed array spec was to provide a compact typed storage mechanism. Allowing the length to be changed runs counter to this as it effectively puts us back in the position of supporting sparse arrays.

# Alex Russell (15 years ago)

On May 13, 2010, at 11:09 PM, Oliver Hunt wrote:

On May 13, 2010, at 10:21 PM, Alex Russell wrote:

On May 13, 2010, at 5:15 PM, Vladimir Vukicevic wrote:

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways.

Sounds like a bug to be fixed ;-)

At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in). Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

That the length property of a particular array subclass leaves the constructor non-configurable and read-only isn't much of a trick in ES5. That said, why doesn't TypedArray spec a mutable variant? Surely it'd be useful.

The data is mutable, the length is not -- this is more in line with arrays in other languages, but more importantly the whole point of the typed array spec was to provide a compact typed storage mechanism. Allowing the length to be changed runs counter to this as it effectively puts us back in the position of supporting sparse arrays.

To be clear, I'm supportive of a fixed-length array type for efficient handling of byte types. I'm also in favor of supporting mutable-length arrays for these types as well, perhaps as a separate subtype of Array or a type that shares some traits but not others. I get the need to optimize the case of "I'm representing a buffer somewhere in some C code and need to do it as fast as possible", but I just don't think that should be the exclusive use of relatively efficient byte arrays, even if it's the one that's motivating WebGL at the moment.

-- Alex Russell slightlyoff at google.com alex at dojotoolkit.org BE03 E88D EABB 2116 CC49 8259 CF78 E242 59C3 9723

# Chris Marrin (15 years ago)

On May 13, 2010, at 4:57 PM, Erik Arvidsson wrote:

I'm surprised no one has said this yet but here goes:

ArrayBuffer needs to extend Array. In other words instances of ArrayBuffer needs to also be instances of Array

I don't believe ArrayBuffer behaves like a superset of Array at all. It is intended to be an opaque type whose data is not accessible except via "views" into a range of the buffer (possibly the entire buffer).

But I can understand your concern about the naming, which can of course be changed.

# Mike Shaver (15 years ago)

On Fri, May 14, 2010 at 2:09 AM, Oliver Hunt <oliver at apple.com> wrote:

The data is mutable, the length is not -- this is more in line with arrays in other languages, but more importantly the whole point of the typed array spec was to provide a compact typed storage mechanism.  Allowing the length to be changed runs counter to this as it effectively puts us back in the position of supporting sparse arrays.

I don't see why that's the case. You can define the semantics such that length-extension zero-fills (or NaN-fills, if you like to hurt kittens) rather than permitting sparseness, and it would seem to meet all the requirements of the typedarray spec.

Mike

# Chris Marrin (15 years ago)

On May 13, 2010, at 10:21 PM, Alex Russell wrote:

On May 13, 2010, at 5:15 PM, Vladimir Vukicevic wrote:

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways.

Sounds like a bug to be fixed ;-)

At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in). Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

That the length property of a particular array subclass leaves the constructor non-configurable and read-only isn't much of a trick in ES5. That said, why doesn't TypedArray spec a mutable variant? Surely it'd be useful.

One of the important aspects of ArrayBuffer is its fixed length. As I mentioned before, perhaps the issue here is the poor naming (using "Array" in the names of objects that don't behave in the same way as the ES Array object). The names can be changed but I think we need the concept of a fixed length buffer with fixed views into it.

# Chris Marrin (15 years ago)

On May 14, 2010, at 7:22 AM, Mike Shaver wrote:

On Fri, May 14, 2010 at 2:09 AM, Oliver Hunt <oliver at apple.com> wrote:

The data is mutable, the length is not -- this is more in line with arrays in other languages, but more importantly the whole point of the typed array spec was to provide a compact typed storage mechanism. Allowing the length to be changed runs counter to this as it effectively puts us back in the position of supporting sparse arrays.

I don't see why that's the case. You can define the semantics such that length-extension zero-fills (or NaN-fills, if you like to hurt kittens) rather than permitting sparseness, and it would seem to meet all the requirements of the typedarray spec.

As Ollie mentioned, ArrayBuffers need to be able to be mapped to hardware storage (either on the CPU or GPU). So anything that might change the underlying storage address (such as resizing the array) would be problematic.

# Mike Shaver (15 years ago)

On Fri, May 14, 2010 at 10:30 AM, Chris Marrin <cmarrin at apple.com> wrote:

As Ollie mentioned, ArrayBuffers need to be able to be mapped to hardware storage (either on the CPU or GPU). So anything that might change the underlying storage address (such as resizing the array) would be problematic.

Resizing might invalidate some addresses, yes, but it seems like those mappings aren't necessarily fixed for the lifetime of the object. I can create an ArrayBuffer and then do a bunch of stuff with it before I ever hand it to WebGL, even today -- why should we make authors manually create a new AB and copy?

Aren't these buffers allocated and deallocated and copied by C programs, too? It might be that extending an ArrayBuffer doesn't give you the semantics you want, just as realloc might fail if you aren't careful about updating the hardware mappings. I presume that people use malloc (or the VBO/etc. equivalent) to create them, and can realloc to their heart's content as long as they don't break their contract with the places they've passed it to.

Mike

# Allen Wirfs-Brock (15 years ago)

Name is important. As a stawman I suggest replacing the name ArrayBuffer with BinaryBlob (Binary is redundant in this context but I'd be worried about name conflicts with just Blob). BinaryBuffer would also work but the word buffer may carry implications for some people that do really apply here.

# Alex Russell (15 years ago)

On May 14, 2010, at 7:27 AM, Chris Marrin wrote:

On May 13, 2010, at 10:21 PM, Alex Russell wrote:

On May 13, 2010, at 5:15 PM, Vladimir Vukicevic wrote:

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways.

Sounds like a bug to be fixed ;-)

At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in). Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

That the length property of a particular array subclass leaves the constructor non-configurable and read-only isn't much of a trick in ES5. That said, why doesn't TypedArray spec a mutable variant? Surely it'd be useful.

One of the important aspects of ArrayBuffer is its fixed length. As I mentioned before, perhaps the issue here is the poor naming (using "Array" in the names of objects that don't behave in the same way as the ES Array object). The names can be changed but I think we need the concept of a fixed length buffer with fixed views into it.

Yes, yes, I get that everyone with a C buffer they want to expose to JS wants a variant of ArrayBuffer that's fixed. But what I'm arguing for is that we can keep everything rational (instead of adding a "host object", committee speak for "alien weirdo") by making one type of ArrayBuffer (FixedArrayBuffer?) have a fixed length but also support a mutable length ArrayBuffer. Not exclusive, but in parallel and in a way that allows all of this to have a rational class hierarchy.

-- Alex Russell slightlyoff at google.com alex at dojotoolkit.org BE03 E88D EABB 2116 CC49 8259 CF78 E242 59C3 9723

# Allen Wirfs-Brock (15 years ago)

-----Original Message----- From: es-discuss-bounces at mozilla.org [mailto:es-discuss- bounces at mozilla.org] On Behalf Of Alex Russell ...

Yes, yes, I get that everyone with a C buffer they want to expose to JS wants a variant of ArrayBuffer that's fixed. But what I'm arguing for is that we can keep everything rational (instead of adding a "host object", committee speak for "alien weirdo") by making one type of ArrayBuffer (FixedArrayBuffer?) have a fixed length but also support a mutable length ArrayBuffer. Not exclusive, but in parallel and in a way that allows all of this to have a rational class hierarchy.

What's your use case for a variable length ArrayBuffer? ArrayBuffer seems like a low level building block that is going to be uses as a basis for constructing other higher level abstractions. As such it should be as simple and efficient as possible. The more complex we make the primitive entity the more likely it is to have implementation inefficiencies induced by features that are unlikely to be needed for some of the higher level uses. Consider growable buffers. At an implementation level, growth is either going to require copying or use of segmented buffers. The copying alterative probably requires an extra level of indirection on each access. The multi-segment approach complicates (and hence probably slows down) all accesses and certainly iterative operations. In either case, there is a penalty that accrues for the most common use case of a non-growable buffer.

These are the sorts of trade-offs that library writers should be making. They can decided if it is more appropriate to build an abstraction that that grows by copying (probably best for infrequent growth and lots of iterative operations) or grows by segmentation (probably better for frequent growth with minimal iteration). They can even include both in a library.

The core language should be providing the primitive that enable this sort of library design while minimizing low level overhead. From that perspective I think a fixed size ArrayBuffer is exactly what is needed. However, it is also important that efficient copying is supported, possibly via a ArrayBuffer constructer alternative.

# Erik Arvidsson (15 years ago)

On Fri, May 14, 2010 at 10:06, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com> wrote:

What's your use case for a variable length ArrayBuffer?

I'm happy with fixed length array buffer but exceptions rubs me the wrong way. Consistence with Array leads to less surprises which leads to less bugs.

These are the sorts of trade-offs that library writers should be making.  They can decided if it is more appropriate to build an abstraction that that grows by copying (probably best for infrequent growth and lots of iterative operations) or grows by segmentation (probably better for frequent growth with minimal iteration).  They can even include both in a library.

The core language should be providing the primitive that enable this sort of library design while minimizing low level overhead.  From that perspective I think a fixed size ArrayBuffer is exactly what is needed.  However, it is also important that efficient copying is supported, possibly via a ArrayBuffer constructer alternative.

I agree that we need to provide the missing primitives, however;

If we only provide the primitives usability will suffer.

If we only provide primitives all js libraries will have to reimplement a usable abstraction layer. This is leads to more code which leads to higher latency and slower application.

# Alex Russell (15 years ago)

On May 14, 2010, at 11:04 AM, Erik Arvidsson wrote:

On Fri, May 14, 2010 at 10:06, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com> wrote:

What's your use case for a variable length ArrayBuffer?

I'm happy with fixed length array buffer but exceptions rubs me the wrong way. Consistence with Array leads to less surprises which leads to less bugs.

These are the sorts of trade-offs that library writers should be making. They can decided if it is more appropriate to build an abstraction that that grows by copying (probably best for infrequent growth and lots of iterative operations) or grows by segmentation (probably better for frequent growth with minimal iteration). They can even include both in a library.

The core language should be providing the primitive that enable this sort of library design while minimizing low level overhead. From that perspective I think a fixed size ArrayBuffer is exactly what is needed. However, it is also important that efficient copying is supported, possibly via a ArrayBuffer constructer alternative.

I agree that we need to provide the missing primitives, however;

If we only provide the primitives usability will suffer.

If we only provide primitives all js libraries will have to reimplement a usable abstraction layer. This is leads to more code which leads to higher latency and slower application.

+1. What Erik said.

-- Alex Russell slightlyoff at google.com alex at dojotoolkit.org BE03 E88D EABB 2116 CC49 8259 CF78 E242 59C3 9723

# Boris Zbarsky (15 years ago)

On 5/14/10 2:04 PM, Erik Arvidsson wrote:

If we only provide primitives all js libraries will have to reimplement a usable abstraction layer

You seem to assume that there is One True usable abstraction layer. I think Allen's point was that depending on what you're trying to do you want different abstraction layers.

# Allen Wirfs-Brock (15 years ago)

-----Original Message----- From: es-discuss-bounces at mozilla.org [mailto:es-discuss- bounces at mozilla.org] On Behalf Of Boris Zbarsky Sent: Friday, May 14, 2010 11:11 AM ..

You seem to assume that there is One True usable abstraction layer. I think Allen's point was that depending on what you're trying to do you want different abstraction layers.

-Boris

Exactly. I think it is also reasonable for the basic library that is part of the core language to provide higher level support for the most commonly used abstractions. Beyond that, the language should focus on low overhead primitives that enable library authors to support more specialized requirements.

# Erik Arvidsson (15 years ago)

On Fri, May 14, 2010 at 11:24, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com> wrote:

Exactly.  I think it is also reasonable for the basic library that is part of the core language to provide higher level support for the most commonly used abstractions.  Beyond that, the language should focus on low overhead primitives that enable library authors to support more specialized requirements.

Then I think we agree :-)

# Kenneth Russell (15 years ago)

On Thu, May 13, 2010 at 10:21 PM, Alex Russell <alex at dojotoolkit.org> wrote:

On May 13, 2010, at 5:15 PM, Vladimir Vukicevic wrote:

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways.

Sounds like a bug to be fixed ;-)

At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in). Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

That the length property of a particular array subclass leaves the constructor non-configurable and read-only isn't much of a trick in ES5. That said, why doesn't TypedArray spec a mutable variant? Surely it'd be useful.

push(), and mutation of the length in general, are ill-defined when there are multiple views of the same region. Consider this simple case of two arrays referencing disjoint regions of an ArrayBuffer. While it is simple, it maps directly to many uses in OpenGL and WebGL programs,

var buf = new ArrayBuffer(2 * Int16Array.BYTES_PER_ELEMENT + 4 * Int32Array.BYTES_PER_ELEMENT); var shorts = new Int16Array(buf, 0, 2); var ints = new Int32Array(buf, 2 * Int16Array.BYTES_PER_ELEMENT, 4);

What happens if shorts.push(value) is called? Is the starting point of the Int32Array moved out to make room for the new element? If so, does the ArrayBuffer grow? Or does the Int16Array simply reference more of the storage of the existing ArrayBuffer?

Now consider the case where the two arrays overlap. This is again common usage in OpenGL programs; it is how interleaved vertex data is constructed.

var buf = new ArrayBuffer(16000); var shorts = new Int16Array(buf, 0, 1000); // Room to grow var ints = new Int32Array(buf, 0, 500);

What happens if shorts.push() is called? In this case plausibly the right answer is that the view grows toward the end of the ArrayBuffer. This is probably a different answer than what seems obvious for the first case above.

Adding all of ECMAScript arrays' semantics to these TypedArrays will make it impossible to understand how they work. It will also likely prevent them from performing well. They are currently implemented with high performance in multiple browsers, and if that property is destroyed then the WebGL working group will have to create another specification to allow good performance to be achieved again.

# Vladimir Vukicevic (15 years ago)

----- "Kenneth Russell" <kbr at google.com> wrote:

On Thu, May 13, 2010 at 10:21 PM, Alex Russell <alex at dojotoolkit.org> wrote:

On May 13, 2010, at 5:15 PM, Vladimir Vukicevic wrote:

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways.

Sounds like a bug to be fixed ;-)

At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in). Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

That the length property of a particular array subclass leaves the constructor non-configurable and read-only isn't much of a trick in ES5. That said, why doesn't TypedArray spec a mutable variant? Surely it'd be useful.

push(), and mutation of the length in general, are ill-defined when there are multiple views of the same region. Consider this simple case of two arrays referencing disjoint regions of an ArrayBuffer. While it is simple, it maps directly to many uses in OpenGL and WebGL programs,

var buf = new ArrayBuffer(2 * Int16Array.BYTES_PER_ELEMENT + 4 * Int32Array.BYTES_PER_ELEMENT); var shorts = new Int16Array(buf, 0, 2); var ints = new Int32Array(buf, 2 * Int16Array.BYTES_PER_ELEMENT, 4);

What happens if shorts.push(value) is called? Is the starting point of the Int32Array moved out to make room for the new element? If so, does the ArrayBuffer grow? Or does the Int16Array simply reference more of the storage of the existing ArrayBuffer?

The other issue here is if the ArrayBuffer itself can change size -- growth has the problem of potentially needing to reallocate the storage, as was pointed out, but all views can be updated to point to the new storage. But if it shrinks, e.g. "buf.length = 2;" above, the views that are already depending on it would become illegal. The views make changing the arraybuffer size problematic.

# Chris Marrin (15 years ago)

On May 14, 2010, at 9:28 AM, Allen Wirfs-Brock wrote:

Name is important. As a stawman I suggest replacing the name ArrayBuffer with BinaryBlob (Binary is redundant in this context but I'd be worried about name conflicts with just Blob). BinaryBuffer would also work but the word buffer may carry implications for some people that do really apply here.

"Binary" isn't really informative. Perhaps DataBuffer?

Allen

-----Original Message----- From: es-discuss-bounces at mozilla.org [mailto:es-discuss- bounces at mozilla.org] On Behalf Of Chris Marrin Sent: Friday, May 14, 2010 7:27 AM To: Alex Russell Cc: arun at mozilla.com; public-script-coord at w3.org; Erik Arvidsson; es- discuss at mozilla.org Subject: Re: Adoption of the Typed Array Specification

On May 13, 2010, at 10:21 PM, Alex Russell wrote:

On May 13, 2010, at 5:15 PM, Vladimir Vukicevic wrote:

This is difficult to do, given the goals of typed arrays -- they wouldn't behave like normal Arrays in most meaningful ways.

Sounds like a bug to be fixed ;-)

At the core, an ArrayBuffer is of fixed size, and it doesn't make sense to index an ArrayBuffer directly (because there's no indication of what format the data should be accessed in). Making the array view types instances of Array might work, but again given that they're fixed length, there's a significant difference there.

That the length property of a particular array subclass leaves the constructor non-configurable and read-only isn't much of a trick in ES5. That said, why doesn't TypedArray spec a mutable variant? Surely it'd be useful.

One of the important aspects of ArrayBuffer is its fixed length. As I mentioned before, perhaps the issue here is the poor naming (using "Array" in the names of objects that don't behave in the same way as the ES Array object). The names can be changed but I think we need the concept of a fixed length buffer with fixed views into it.


es-discuss mailing list es-discuss at mozilla.org, mail.mozilla.org/listinfo/es-discuss


~Chris cmarrin at apple.com

# Allen Wirfs-Brock (15 years ago)

DataBuffer sounds like another name that is likely to collide with lots of existing use. If you don' like binary, then another alternative that feels fairly collusion safe is ByteBlob

# Arun Ranganathan (15 years ago)

On 5/13/10 8:19 AM, Mark S. Miller wrote:

On Thu, May 13, 2010 at 5:57 AM, Arun Ranganathan<arun at mozilla.com> wrote:

Greetings, TC-39 WG and script mavens!

Browser vendors participating in the WebGL WG intend to implement the "Typed Arrays" specification, allowing for greater manipulation of binary data:

cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/TypedArray-spec.html

The draft specification (a work in progress) resides at Khronos, which is typically an unusual home for something integral to the rest of the web platform. Khronos is where we work on WebGL, which enjoys Google, Opera, Mozilla, and Apple participation, amongst other organizations.

The general usefulness of constructs such as ArrayBuffers (covered in the "Typed Arrays" draft specification) lends itself to other web platform specifications, such as the File API, parts of which are implemented in Firefox 3.6.3:

dev.w3.org/2006/webapi/FileAPI

In the above draft (also a work in progress), the Blob interface exposes an ArrayBuffer property, which can then be used with different views.

While implementations are currently proceeding unimpeded by standards-track considerations, it would be useful if Typed Arrays were taken on as a work item by TC-39, for more general inclusion in JavaScript. Should it live elsewhere, and if so, where?

strawman:typed_arrays

I agree it should be taken on by TC39. On the strawman page, you are listed as the champion of this proposal. It is on the agenda (see 6.4 or 6.5) for the upcoming May 24/25 meeting. Hope to see you there!

Mark: the WebGL F2F coincides with this, and occurs on May 25 and May 26 at the Mozilla campus in Mountain View. If the TC39 meeting also takes place in the Bay Area, I'm amenable to hosting a joint meeting in the afternoon of May 25. I have proposed this to J. Neumann.

-- A*

# Mark S. Miller (15 years ago)

On Fri, May 14, 2010 at 6:08 PM, Arun Ranganathan <arun at mozilla.com> wrote:

Mark: the WebGL F2F coincides with this, and occurs on May 25 and May 26 at the Mozilla campus in Mountain View. If the TC39 meeting also takes place in the Bay Area, I'm amenable to hosting a joint meeting in the afternoon of May 25. I have proposed this to J. Neumann.

+1. Thanks for suggesting it.

# Jorge (15 years ago)

On 15/05/2010, at 01:16, Allen Wirfs-Brock wrote:

DataBuffer sounds like another name that is likely to collide with lots of existing use. If you don' like binary, then another alternative that feels fairly collusion safe is ByteBlob

Perhaps it's time to innovate: ... a Binary Large^h^h^h^h^h OBject : a Bob.

# Kenneth Russell (15 years ago)

On Thu, May 13, 2010 at 8:28 PM, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com> wrote:

Vladimir Vukicevic vladimir at mozilla.com said:

However, another consideration is that the WebGL spec isn't ES specific, and yet has to depend on typed arrays.  So perhaps we're really talking about two different specs: a main typed array spec that uses Web IDL and can be implemented generically in any language, as well as a separate spec describing ES types that happen to fulfill the requirements of typed arrays.

If that is a concern, how do you expect these interfaces to work with other languages.  In a C++ binding are the view objects and the buffer objects still going be distinct objects or are you expect to merge them into native C++ objects.   I think that there is a pretty fundamental question here: does your (and similar) application need to expose binary buffers that exist natively in the  implementation technology of your subsystem and which can be interchange among multiple client languages.  Or, are you able and willing to directly work with native JavaScript buffer objects (assuming that such things exist) even it that a less natural form of access on your part.  In the first case, “host objects” may be exactly what you need.  If the second is what you would like, then we probably need a EcmaScript extension.

Using hypothetical native JavaScript buffer objects would be compatible with our current relatively simple use of TypedArrays. However, we have begun to explore more advanced use cases including sharing TypedArrays among web workers, and between ECMAScript and browser plugins. In these situations, if we were to use native JavaScript buffer objects, we would need to specify additional behavior for the objects.

In the Java platform, the NIO buffer classes provide similar functionality, and provide a bridge to the outside world. The Java APIs [1] specify how values can be fetched and stored in the buffers. A few entry points in the Java Native Interface [2] specify how external C code can wrap a region of memory in a NIO buffer and thereby expose it to Java. If it were possible to specify similar functionality in an ECMAScript extension, I think it would enable all of the use cases mentioned above.

-Ken

[1] java.sun.com/javase/6/docs/api/java/nio/package-summary.html [2] java.sun.com/j2se/1.4.2/docs/guide/jni/jni-14.html#NewDirectByteBuffer

# Kenneth Russell (15 years ago)

On Fri, May 14, 2010 at 9:28 AM, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com> wrote:

Name is important.  As a stawman I suggest replacing the name ArrayBuffer with BinaryBlob  (Binary is redundant in this context but I'd be worried about name conflicts with just Blob).  BinaryBuffer would also work but the word buffer may carry implications for some people that do really apply here.

Out of curiosity what are the implications of the word "buffer"?

Out of the naming suggestions proposed here I still prefer "ArrayBuffer". It meshes with the name of the spec -- TypedArrays -- and indicates that it's the buffer which backs the various views.

# Jürg Lehni (15 years ago)

But why not simply TypedArray then?

Jürg

# Jonas Sicking (15 years ago)

Resending this now that i'm signed up on the es-discuss list.

On Thu, May 13, 2010 at 4:57 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote:

I'm surprised no one has said this yet but here goes:

ArrayBuffer needs to extend Array. In other words instances of ArrayBuffer needs to also be instances of Array

var ab = new ArrayBuffer; assert(ab instanceof ArrayBuffer); assert(ab instanceof Array);

You will also need to make sure that all the internal methods are defined. See 8.12 Algorithms for Object Internal Methods of ES5. For example what does it mean to do [[Delete]] on a byte array?

My biggest beef with ArrayBuffer is that since it can be cast between Int8 and Int16, it exposes endianness of the CPU the code is running on. I.e. it will be very easy to write code that works on Intel CPUs, but not on Motorola 68K CPUs.

I don't have much faith in that website developers will test the endiannness of the CPU they are running on and manually convert, rather than cast, if the endianness is "wrong".

/ Jonas

# Erik Corry (15 years ago)

2010/5/18 Kenneth Russell <kbr at google.com>:

On Thu, May 13, 2010 at 8:28 PM, Allen Wirfs-Brock <Allen.Wirfs-Brock at microsoft.com> wrote:

Vladimir Vukicevic vladimir at mozilla.com said:

However, another consideration is that the WebGL spec isn't ES specific, and yet has to depend on typed arrays.  So perhaps we're really talking about two different specs: a main typed array spec that uses Web IDL and can be implemented generically in any language, as well as a separate spec describing ES types that happen to fulfill the requirements of typed arrays.

If that is a concern, how do you expect these interfaces to work with other languages.  In a C++ binding are the view objects and the buffer objects still going be distinct objects or are you expect to merge them into native C++ objects.   I think that there is a pretty fundamental question here: does your (and similar) application need to expose binary buffers that exist natively in the  implementation technology of your subsystem and which can be interchange among multiple client languages.  Or, are you able and willing to directly work with native JavaScript buffer objects (assuming that such things exist) even it that a less natural form of access on your part.  In the first case, “host objects” may be exactly what you need.  If the second is what you would like, then we probably need a EcmaScript extension.

Using hypothetical native JavaScript buffer objects would be compatible with our current relatively simple use of TypedArrays. However, we have begun to explore more advanced use cases including sharing TypedArrays among web workers, and between ECMAScript and browser plugins. In these situations, if we were to use native JavaScript buffer objects, we would need to specify additional behavior for the objects.

This looks like a can of worms to me. Shared buffers break with the shared-nothing and message-passing paradigms and necessitate synchronization primitives.

# Chris Marrin (15 years ago)

On May 18, 2010, at 12:09 AM, Jonas Sicking wrote:

Resending this now that i'm signed up on the es-discuss list.

On Thu, May 13, 2010 at 4:57 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote:

I'm surprised no one has said this yet but here goes:

ArrayBuffer needs to extend Array. In other words instances of ArrayBuffer needs to also be instances of Array

var ab = new ArrayBuffer; assert(ab instanceof ArrayBuffer); assert(ab instanceof Array);

You will also need to make sure that all the internal methods are defined. See 8.12 Algorithms for Object Internal Methods of ES5. For example what does it mean to do [[Delete]] on a byte array?

My biggest beef with ArrayBuffer is that since it can be cast between Int8 and Int16, it exposes endianness of the CPU the code is running on. I.e. it will be very easy to write code that works on Intel CPUs, but not on Motorola 68K CPUs.

I don't have much faith in that website developers will test the endiannness of the CPU they are running on and manually convert, rather than cast, if the endianness is "wrong".

In developing TypedArrays, we had endless discussions about the endianness problem. We ended up with the conclusion that there is no practical way to avoid it AND keep a reasonable feature set AND not end up with an extremely complex API. I don't think this will be a problem in practical use. The most common use of TypedArrays will not use ArrayBuffers at all. If programmers start mapping different ranges of an ArrayBuffer to different views, they need to have advanced knowledge and they have to use care. If they choose to "over-map" the same range to different views on purpose, they had better really understand what they are doing. If they do it accidentally, they have made a programming error. If that error results in the wrong data being used due to endianness or some other error, I don't think it matters.

There is the issue of the naive programmer over-mapping and having it work on some machines and not on others. But I think those cases will be rare. I think the danger of that is worth the features that over-mapping provides.


~Chris cmarrin at apple.com

# Mark S. Miller (15 years ago)

On Tue, May 18, 2010 at 9:12 AM, Chris Marrin <cmarrin at apple.com> wrote:

On May 18, 2010, at 12:09 AM, Jonas Sicking wrote:

Resending this now that i'm signed up on the es-discuss list.

On Thu, May 13, 2010 at 4:57 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote:

I'm surprised no one has said this yet but here goes:

ArrayBuffer needs to extend Array. In other words instances of ArrayBuffer needs to also be instances of Array

var ab = new ArrayBuffer; assert(ab instanceof ArrayBuffer); assert(ab instanceof Array);

You will also need to make sure that all the internal methods are defined. See 8.12 Algorithms for Object Internal Methods of ES5. For example what does it mean to do [[Delete]] on a byte array?

My biggest beef with ArrayBuffer is that since it can be cast between Int8 and Int16, it exposes endianness of the CPU the code is running on. I.e. it will be very easy to write code that works on Intel CPUs, but not on Motorola 68K CPUs.

I don't have much faith in that website developers will test the endiannness of the CPU they are running on and manually convert, rather than cast, if the endianness is "wrong".

In developing TypedArrays, we had endless discussions about the endianness problem. We ended up with the conclusion that there is no practical way to avoid it AND keep a reasonable feature set AND not end up with an extremely complex API.

Is a summary of these discussions, and the structure of tradeoffs they reveal, written down anywhere? Can they be? These non-portable endianness problems are very non-JavaScript-y. If you are asking us to accept these problems into JavaScript, we need more than a summary of your conclusions. We need to understand why seemingly more pleasant options were not. And we need to go over these tradeoffs ourselves. We might have a different weighting, and so make different choices.

# Jonas Sicking (15 years ago)

On Tue, May 18, 2010 at 9:12 AM, Chris Marrin <cmarrin at apple.com> wrote:

On May 18, 2010, at 12:09 AM, Jonas Sicking wrote:

Resending this now that i'm signed up on the es-discuss list.

On Thu, May 13, 2010 at 4:57 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote:

I'm surprised no one has said this yet but here goes:

ArrayBuffer needs to extend Array. In other words instances of ArrayBuffer needs to also be instances of Array

var ab = new ArrayBuffer; assert(ab instanceof ArrayBuffer); assert(ab instanceof Array);

You will also need to make sure that all the internal methods are defined. See 8.12 Algorithms for Object Internal Methods of ES5. For example what does it mean to do [[Delete]] on a byte array?

My biggest beef with ArrayBuffer is that since it can be cast between Int8 and Int16, it exposes endianness of the CPU the code is running on. I.e. it will be very easy to write code that works on Intel CPUs, but not on Motorola 68K CPUs.

I don't have much faith in that website developers will test the endiannness of the CPU they are running on and manually convert, rather than cast, if the endianness is "wrong".

In developing TypedArrays, we had endless discussions about the endianness problem. We ended up with the conclusion that there is no practical way to avoid it AND keep a reasonable feature set AND not end up with an extremely complex API. I don't think this will be a problem in practical use. The most common use of TypedArrays will not use ArrayBuffers at all. If programmers start mapping different ranges of an ArrayBuffer to different views, they need to have advanced knowledge and they have to use care. If they choose to "over-map" the same range to different views on purpose, they had better really understand what they are doing. If they do it accidentally, they have made a programming error. If that error results in the wrong data being used due to endianness or some other error, I don't think it matters.

This is almost even more unfortunate :)

I.e. the fact that this type-casting isn't even a needed or desired feature, but rather a side effect of various other tradeoffs. I.e. we're adding a very unfortunate feature to the language, without even really wanting the feature itself.

Like Mark I'd love to see the requirements and the discussions that made you arrive at the current proposal. I'd love to have ArrayBuffers be a native part of Javascript and be to binary data what js strings are to text. I.e. something returned any time someone wanted to represent in-memory binary data. But it's unfortunate if that data type has these properties.

/ Jonas

# Kenneth Russell (15 years ago)

On Tue, May 18, 2010 at 9:20 AM, Mark S. Miller <erights at google.com> wrote:

On Tue, May 18, 2010 at 9:12 AM, Chris Marrin <cmarrin at apple.com> wrote:

On May 18, 2010, at 12:09 AM, Jonas Sicking wrote:

Resending this now that i'm signed up on the es-discuss list.

On Thu, May 13, 2010 at 4:57 PM, Erik Arvidsson <erik.arvidsson at gmail.com> wrote:

I'm surprised no one has said this yet but here goes:

ArrayBuffer needs to extend Array. In other words instances of ArrayBuffer needs to also be instances of Array

var ab = new ArrayBuffer; assert(ab instanceof ArrayBuffer); assert(ab instanceof Array);

You will also need to make sure that all the internal methods are defined. See 8.12 Algorithms for Object Internal Methods of ES5. For example what does it mean to do [[Delete]] on a byte array?

My biggest beef with ArrayBuffer is that since it can be cast between Int8 and Int16, it exposes endianness of the CPU the code is running on. I.e. it will be very easy to write code that works on Intel CPUs, but not on Motorola 68K CPUs.

I don't have much faith in that website developers will test the endiannness of the CPU they are running on and manually convert, rather than cast, if the endianness is "wrong".

In developing TypedArrays, we had endless discussions about the endianness problem. We ended up with the conclusion that there is no practical way to avoid it AND keep a reasonable feature set AND not end up with an extremely complex API.

Is a summary of these discussions, and the structure of tradeoffs they reveal, written down anywhere? Can they be? These non-portable endianness problems are very non-JavaScript-y. If you are asking us to accept these problems into JavaScript, we need more than a summary of your conclusions. We need to understand why seemingly more pleasant options were not. And we need to go over these tradeoffs ourselves. We might have a different weighting, and so make different choices.

Producing a complete writeup will take time. The discussions are archived in Khronos teleconference recordings, meeting minutes and mailing lists that predate the public WebGL list. There are roughly 200 email messages on this topic spread over several threads, and looking back through them, some of the biggest decisions were made during conference calls.

Hopefully the summary below will be of some use.

The design requirements were:

  1. Support interleaved, heterogeneous vertex data: for example, three floats for the position followed by four unsigned bytes for the color. Interleaved vertex data is required for high performance 3D rendering.

  2. Support slicing a large region of memory into smaller chunks. Many OpenGL programs set up vertices for multiple objects in a single buffer and upload the buffer to the graphics card with one API call rather than several.

  3. Support the fastest possible dynamic generation of vertices.

The early discussions in the WebGL WG attempted to maintain 100% safety and correctness for the programmer. One proposal was to drop support for case (1), which was considered unacceptable. Other proposals involved specifying the vertex layout. One such proposal involved a "pattern" array where heterogeneous elements would be indexed. In example (1), above, patternArray[0..2] would index the first three floats, patternArray[3..6] would index the subsequent four unsigned bytes, etc. This design was discarded as unoptimizable.

Another proposal involved creating multiple views from the specification of the vertex layout. Multiple views would still refer to the same memory region, but the indexing of each view would be non-contiguous. In case (1) above, two array-like objects would be created by specifying this vertex format; call them "floatArray" and "byteArray". floatArray[0..2] would be contiguous in memory; floatArray[3] would be discontiguous, and the first coordinate of the second vertex. byteArray[0..3] would be the four bytes of the first vertex's color; byteArray[4] would be the first color channel of the second vertex. This approach was discarded for several reasons, including unoptimizability and incompatibility with the OpenGL API.

The current TypedArray spec meets all of the requirements of OpenGL and WebGL programmers. See cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/WebGL-spec.html#5.13 for the full code of example (1). It would be undesirable to lose any of the current properties in the interest of protecting the programmer. Higher-level APIs which are completely safe from endianness issues can be built in ECMAScript on top of these primitives.

Note that the typed arrays themselves, since they use the host platform's native endianness, do not directly support file and network I/O. File formats specify a particular endianness for multi-byte values. The DataView interface in the TypedArray spec is an attempt to address this use case with a different kind of view in which the methods can still be optimized to a few machine instructions each. The expectation is that higher-level, stream-like APIs can be built on top of the DataView in ECMAScript.

# Allen Wirfs-Brock (15 years ago)

From: Kenneth Russell [mailto:kbr at google.com] Out of curiosity what are the implications of the word "buffer"?

The usage isn't absolute, but the term "buffer" is often used to for areas of memory that hold transient data. Often data that is being moved from one place or representation to another. See, for example, the definitions at www.cheap56k.com/glossary/Buffer.html and www.techweb.com/encyclopedia/defineterm.jhtml?term=buffer .

In the TypedArray proposal, ArrayBuffers are not necessarily used in such a transient manner. They can be used to implement such buffers, but they may also be used to implement other storage use cases. Such usage decisions are really in the domain of the application design, not the core library design. To me, that raises a flag about the use of the term "Buffer" in that context.

The use of "Array" also seems inappropriate. In the TypedArrayProposal, ArrayBuffer isn't even used exclusively as the backing store for view objects that provide Array-like access. It is also used as the backing store for DataView that provides heterogeneous data access. In addition, ArrayBuffer (as currently spec'ed) doesn't directly provide any JavaScript array-like behaviors, so use of "Array" in its name also seems misleading for that reason.

That's why I would generally prefer an application and access neutral name such as Blob, BinaryData, ByteBlob, etc.

# Allen Wirfs-Brock (15 years ago)

-----Original Message----- On Behalf Of Jonas Sicking ... I'd love to have ArrayBuffers be a native part of Javascript and be to binary data what js strings are to text. I.e. something returned any time someone wanted to represent in-memory binary data. But it's unfortunate if that data type has these properties.

Endian issues are inherent in at least two situations:

  1. allowing multiple-sized accesses (any of byte, 16-bit int, 32-bit int, etc.) to common underlying byte addressable memory
  2. moving byte-streams that encode multi-byte integers from one endian domain to the other.

If you have byte addressable data and allow either of these things then it is possible to run into endian issues. Fortunately, you can usually wrap the raw data with abstractions that don't expose the problems. But the rope is going to be there if you have this basic functionality. Personally, I think the functionality is valuable enough to justify itself, even if it means that some programmer may get in trouble with it.

# Chris Marrin (15 years ago)

On May 18, 2010, at 6:12 PM, Allen Wirfs-Brock wrote:

From: Kenneth Russell [mailto:kbr at google.com] Out of curiosity what are the implications of the word "buffer"?

The usage isn't absolute, but the term "buffer" is often used to for areas of memory that hold transient data. Often data that is being moved from one place or representation to another. See, for example, the definitions at www.cheap56k.com/glossary/Buffer.html and www.techweb.com/encyclopedia/defineterm.jhtml?term=buffer .

In the TypedArray proposal, ArrayBuffers are not necessarily used in such a transient manner. They can be used to implement such buffers, but they may also be used to implement other storage use cases. Such usage decisions are really in the domain of the application design, not the core library design. To me, that raises a flag about the use of the term "Buffer" in that context.

I disagree with this assessment. The "transient" nature of buffers is not universal. One of your own citations define it as:

A reserved segment of memory used to hold data while it is being processed

That's a very good description of what ArrayBuffer is. I also don't think we need to avoid "Array", especially if we keep the "Typed" prefix. TypedArrays are very much like the Array object, except that the data is typed. Perhaps we could use TypedArrayBuffer as the buffer object. That would match better with the base class of TypedArray, which specializes into Int8Array, etc. It seems like a rational naming for a family of objects.

We will never have the "perfect" name. We need something authors understand after reading the spec. The rest is just bikeshedding.

The use of "Array" also seems inappropriate. In the TypedArrayProposal, ArrayBuffer isn't even used exclusively as the backing store for view objects that provide Array-like access. It is also used as the backing store for DataView that provides heterogeneous data access. In addition, ArrayBuffer (as currently spec'ed) doesn't directly provide any JavaScript array-like behaviors, so use of "Array" in its name also seems misleading for that reason.

That's why I would generally prefer an application and access neutral name such as Blob, BinaryData, ByteBlob, etc.

I dislike the term Blob, especially since the File API is using that term to mean a different object type. The name DataView is arguable since it doesn't match the conventions used in any of the other objects in this family, even though it is just a TypedArray that has API for heterogenous types. I have other opinions about DataView and how it is defined, but that is for another conversation.


~Chris cmarrin at apple.com