<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.3/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.3/ http://www.mediawiki.org/xml/export-0.3.xsd" version="0.3" xml:lang="en">
  <siteinfo>
    <sitename>CommonJS Spec Wiki</sitename>
    <base>http://wiki.commonjs.org/wiki/CommonJS</base>
    <generator>MediaWiki 1.15.3</generator>
    <case>first-letter</case>
    <namespaces>
      <namespace key="-2">Media</namespace>
      <namespace key="-1">Special</namespace>
      <namespace key="0" />
      <namespace key="1">Talk</namespace>
      <namespace key="2">User</namespace>
      <namespace key="3">User talk</namespace>
      <namespace key="4">CommonJS</namespace>
      <namespace key="5">CommonJS talk</namespace>
      <namespace key="6">File</namespace>
      <namespace key="7">File talk</namespace>
      <namespace key="8">MediaWiki</namespace>
      <namespace key="9">MediaWiki talk</namespace>
      <namespace key="10">Template</namespace>
      <namespace key="11">Template talk</namespace>
      <namespace key="12">Help</namespace>
      <namespace key="13">Help talk</namespace>
      <namespace key="14">Category</namespace>
      <namespace key="15">Category talk</namespace>
      <namespace key="102">Property</namespace>
      <namespace key="103">Property talk</namespace>
      <namespace key="104">Type</namespace>
      <namespace key="105">Type talk</namespace>
      <namespace key="106">Form</namespace>
      <namespace key="107">Form talk</namespace>
      <namespace key="108">Concept</namespace>
      <namespace key="109">Concept talk</namespace>
      <namespace key="170">Filter</namespace>
      <namespace key="171">Filter talk</namespace>
      <namespace key="200">Website</namespace>
      <namespace key="201">Website talk</namespace>
    </namespaces>
  </siteinfo>
  <page>
    <title>OldAPI</title>
    <id>3</id>
    <revision>
      <id>25</id>
      <timestamp>2009-04-14T05:39:14Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Added an index of module proposals.</comment>
      <text xml:space="preserve">Here are sections for proposed standard modules.

* [[ServerJS/API/console]]
* [[ServerJS/API/system]]
* [[ServerJS/API/binary]]
* [[ServerJS/API/file]]
* [[ServerJS/API/io]]
* [[ServerJS/API/ioString]]</text>
    </revision>
    <revision>
      <id>26</id>
      <timestamp>2009-09-09T22:13:48Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>1 revision:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve">Here are sections for proposed standard modules.

* [[ServerJS/API/console]]
* [[ServerJS/API/system]]
* [[ServerJS/API/binary]]
* [[ServerJS/API/file]]
* [[ServerJS/API/io]]
* [[ServerJS/API/ioString]]</text>
    </revision>
    <revision>
      <id>617</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API]] to [[CommonJS/API]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve">Here are sections for proposed standard modules.

* [[ServerJS/API/console]]
* [[ServerJS/API/system]]
* [[ServerJS/API/binary]]
* [[ServerJS/API/file]]
* [[ServerJS/API/io]]
* [[ServerJS/API/ioString]]</text>
    </revision>
    <revision>
      <id>784</id>
      <timestamp>2009-09-09T22:39:58Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-ServerJS +CommonJS)</comment>
      <text xml:space="preserve">Here are sections for proposed standard modules.

* [[CommonJS/API/console]]
* [[CommonJS/API/system]]
* [[CommonJS/API/binary]]
* [[CommonJS/API/file]]
* [[CommonJS/API/io]]
* [[CommonJS/API/ioString]]</text>
    </revision>
    <revision>
      <id>965</id>
      <timestamp>2009-09-10T03:11:55Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <text xml:space="preserve">{{Old}}
Here are sections for proposed standard modules.

* [[CommonJS/API/console]]
* [[CommonJS/API/system]]
* [[CommonJS/API/binary]]
* [[CommonJS/API/file]]
* [[CommonJS/API/io]]
* [[CommonJS/API/ioString]]</text>
    </revision>
    <revision>
      <id>967</id>
      <timestamp>2009-09-10T03:13:56Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API]] to [[OldAPI]]</comment>
      <text xml:space="preserve">{{Old}}
Here are sections for proposed standard modules.

* [[CommonJS/API/console]]
* [[CommonJS/API/system]]
* [[CommonJS/API/binary]]
* [[CommonJS/API/file]]
* [[CommonJS/API/io]]
* [[CommonJS/API/ioString]]</text>
    </revision>
    <revision>
      <id>999</id>
      <timestamp>2009-09-10T03:15:35Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-CommonJS/API +OldAPI)</comment>
      <text xml:space="preserve">{{Old}}
Here are sections for proposed standard modules.

* [[OldAPI/console]]
* [[OldAPI/system]]
* [[OldAPI/binary]]
* [[OldAPI/file]]
* [[OldAPI/io]]
* [[OldAPI/ioString]]</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/ProposalK</title>
    <id>4</id>
    <revision>
      <id>27</id>
      <timestamp>2009-02-18T08:10:51Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>New page: * File Module API [[ServerJS/API/file/ProposalK]] * IO Module API [[ServerJS/API/io/ProposalK]] * Iterations Module API [[ServerJS/API/iter/ProposalK]]</comment>
      <text xml:space="preserve">* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]
* Iterations Module API [[ServerJS/API/iter/ProposalK]]</text>
    </revision>
    <revision>
      <id>28</id>
      <timestamp>2009-02-18T08:14:18Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Added a reference to the posix module API proposal</comment>
      <text xml:space="preserve">* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]
* Iterations Module API [[ServerJS/API/iter/ProposalK]]
* Posix Module API [[ServerJS/API/posix/ProposalK]]</text>
    </revision>
    <revision>
      <id>29</id>
      <timestamp>2009-02-18T21:38:17Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Added a link to the sets proposal for ServerJS</comment>
      <text xml:space="preserve">* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]
* Posix Module API [[ServerJS/API/posix/ProposalK]]
* Iterations Module API [[ServerJS/API/iter/ProposalK]]
* Sets Module API [[ServerJS/API/set/ProposalK]]</text>
    </revision>
    <revision>
      <id>30</id>
      <timestamp>2009-02-18T22:01:10Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Added a link to the dictionary proposal for ServerJS</comment>
      <text xml:space="preserve">* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]
* Posix Module API [[ServerJS/API/posix/ProposalK]]
* Iterations Module API [[ServerJS/API/iter/ProposalK]]
* Sets Module API [[ServerJS/API/set/ProposalK]]
* Dictionaries Module API [[ServerJS/API/dict/ProposalK]]</text>
    </revision>
    <revision>
      <id>31</id>
      <timestamp>2009-02-18T22:15:40Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Added a link to the list proposal for ServerJS</comment>
      <text xml:space="preserve">* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]
* Posix Module API [[ServerJS/API/posix/ProposalK]]
* Iterations Module API [[ServerJS/API/iter/ProposalK]]
* Sets Module API [[ServerJS/API/set/ProposalK]]
* Dictionaries Module API [[ServerJS/API/dict/ProposalK]]
* Lists Module API [[ServerJS/API/list/ProposalK]]</text>
    </revision>
    <revision>
      <id>32</id>
      <timestamp>2009-02-18T22:50:17Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Added some story behind the ProposalK for ServerJS API.</comment>
      <text xml:space="preserve">
== Synopsis ==

In JavaScript there are both &quot;rhinocerous&quot;, native patterns for collection
types embodied by the usage and generic methods of &lt;tt&gt;Array&lt;/tt&gt; and
&lt;tt&gt;Object&lt;/tt&gt;.  However these objects and their patterns have several disadvantages
which give rise to the need for &quot;best practices&quot; in user-defined collections.

* &lt;tt&gt;.length&lt;/tt&gt; assignment is not observable in pure-JS interoperably
* &lt;tt&gt;[index]&lt;/tt&gt; assignment is only special for &lt;tt&gt;Array&lt;/tt&gt; and inheriting &lt;tt&gt;Array does not imbue types with their specialness.
* &lt;tt&gt;[name]&lt;/tt&gt; assignment can have name collisions between names in an object's prototype chain and those that it ought to contain.  Assigning arbitrary strings in this domain can potentially mask builtins.
* The &lt;tt&gt;in&lt;/tt&gt; operator cannot be safely used on &lt;tt&gt;Object&lt;/tt&gt; instances to check for containment or iteration.  You have to use the &lt;tt&gt;Object.prototype.hasOwnProperty.call&lt;/tt&gt; method instead.
* Proxies for native objects cannot observe indexing or length assignment.
* &lt;tt&gt;Array&lt;/tt&gt;'s constructor is not strictly variadic.  That is, creating an Array with a single value that is a number must be done with Array literals.  &lt;tt&gt;Array&lt;/tt&gt; and &lt;tt&gt;Object&lt;/tt&gt; do not support copy construction.
* &lt;tt&gt;Object&lt;/tt&gt; can only be used for mappings from a domain of strings.

However, there are distinct advantages of playing nicely with these types, like 
being able to use the &lt;tt&gt;Array.prototype&lt;/tt&gt; generic methods.  For this reason,
there need to be two layers of collection types: those that play well with
natives (&quot;rhinocerous types&quot;, if you will), and those that can be manipulated
in pure JavaScript using a new set of conventional names.  With these
user-defined types, it's necessary to use methods for all interaction with
the underlying collection.

We can create a system of base types that support
mutual copy construction and mutual interface implementation.
That is, all collections should be constructable
by passing an iterable as their argument, and in turn all collections should
be iterable.  Python does this well, but we can do one step better by making
the default iteration on dictionary mappings to render an iterable of
(key, value) pairs instead of simply the keys.  We can also define orthogonal
interfaces intrinsic to each of the three main collection types and cross
implement those interfaces in each other type to the extent it make sense.
That is, a List is a duck-type for a Dict where the keys are offsets.
A Dict is a Set of pairs.  A Set is an unordered List.

Methods intrinsic to:
* Set (unordered values): insert, remove, retrieve, discard
* Dict (unordered pairs): get, set, del, has, put, cut
* List (ordered values, (index value pairs)): push, pop, shift, unshift

But List implements all of these Dict interface, and Dict can inherit Set.

This is a proposal for modules to be included in the standard library.
Since there's some coupling between iteration and stream IO, I've begun
layout out those modules as well.  My recommendation is to implement
the IO, file, and socket modules in the standard library.  That would leave
each platform to implement a &quot;posix&quot; module with all the routines that
these other libraries would need.

This is very rough draft status.  I imagine there's a lot of room for
discussion on nomenclature and intended scope for the ServerJS
standard library.

== API ==

* Iterations Module API [[ServerJS/API/iter/ProposalK]]
* Sets Module API [[ServerJS/API/set/ProposalK]]
* Dictionaries Module API [[ServerJS/API/dict/ProposalK]]
* Lists Module API [[ServerJS/API/list/ProposalK]]
* Posix Module API [[ServerJS/API/posix/ProposalK]]
* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]</text>
    </revision>
    <revision>
      <id>33</id>
      <timestamp>2009-02-18T22:53:45Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>/* Synopsis */</comment>
      <text xml:space="preserve">
== Synopsis ==

In JavaScript there are both &quot;rhinocerous&quot;, native patterns for collection
types embodied by the usage and generic methods of &lt;tt&gt;Array&lt;/tt&gt; and
&lt;tt&gt;Object&lt;/tt&gt;.  However these objects and their patterns have several disadvantages
which give rise to the need for &quot;best practices&quot; in user-defined collections.

* &lt;tt&gt;.length&lt;/tt&gt; assignment is not observable in pure-JS interoperably
* &lt;tt&gt;[index]&lt;/tt&gt; assignment is only special for &lt;tt&gt;Array&lt;/tt&gt; and inheriting &lt;tt&gt;Array does not imbue types with their specialness.
* [name] assignment can have name collisions between names in an object's prototype chain and those that it ought to contain.  Assigning arbitrary strings in this domain can potentially mask builtins.
* The &lt;tt&gt;in&lt;/tt&gt; operator cannot be safely used on &lt;tt&gt;Object&lt;/tt&gt; instances to check for containment or iteration.  You have to use the &lt;tt&gt;Object.prototype.hasOwnProperty.call&lt;/tt&gt; method instead.
* Proxies for native objects cannot observe indexing or length assignment.
* &lt;tt&gt;Array&lt;/tt&gt;'s constructor is not strictly variadic.  That is, creating an Array with a single value that is a number must be done with Array literals.  &lt;tt&gt;Array&lt;/tt&gt; and &lt;tt&gt;Object&lt;/tt&gt; do not support copy construction.
* &lt;tt&gt;Object&lt;/tt&gt; can only be used for mappings from a domain of strings.

However, there are distinct advantages of playing nicely with these types, like 
being able to use the &lt;tt&gt;Array.prototype&lt;/tt&gt; generic methods.  For this reason,
there need to be two layers of collection types: those that play well with
natives (&quot;rhinocerous types&quot;, if you will), and those that can be manipulated
in pure JavaScript using a new set of conventional names.  With these
user-defined types, it's necessary to use methods for all interaction with
the underlying collection.

We can create a system of base types that support
mutual copy construction and mutual interface implementation.
That is, all collections should be constructable
by passing an iterable as their argument, and in turn all collections should
be iterable.  Python does this well, but we can do one step better by making
the default iteration on dictionary mappings to render an iterable of
(key, value) pairs instead of simply the keys.  We can also define orthogonal
interfaces intrinsic to each of the three main collection types and cross
implement those interfaces in each other type to the extent it make sense.
That is, a List is a duck-type for a Dict where the keys are offsets.
A Dict is a Set of pairs.  A Set is an unordered List.

Methods intrinsic to:
* Set (unordered values): insert, remove, retrieve, discard
* Dict (unordered pairs): get, set, del, has, put, cut
* List (ordered values, (index value pairs)): push, pop, shift, unshift

But List implements all of these Dict interface, and Dict can inherit Set.

This is a proposal for modules to be included in the standard library.
Since there's some coupling between iteration and stream IO, I've begun
layout out those modules as well.  My recommendation is to implement
the IO, file, and socket modules in the standard library.  That would leave
each platform to implement a &quot;posix&quot; module with all the routines that
these other libraries would need.

This is very rough draft status.  I imagine there's a lot of room for
discussion on nomenclature and intended scope for the ServerJS
standard library.

== API ==

* Iterations Module API [[ServerJS/API/iter/ProposalK]]
* Sets Module API [[ServerJS/API/set/ProposalK]]
* Dictionaries Module API [[ServerJS/API/dict/ProposalK]]
* Lists Module API [[ServerJS/API/list/ProposalK]]
* Posix Module API [[ServerJS/API/posix/ProposalK]]
* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]</text>
    </revision>
    <revision>
      <id>34</id>
      <timestamp>2009-02-18T23:07:41Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <text xml:space="preserve">== Synopsis ==

In JavaScript there are both &quot;rhinocerous&quot;, native patterns for collection
types embodied by the usage and generic methods of &lt;tt&gt;Array&lt;/tt&gt; and
&lt;tt&gt;Object&lt;/tt&gt;.  However these objects and their patterns have several disadvantages
which give rise to the need for &quot;best practices&quot; in user-defined collections.

* &lt;tt&gt;.length&lt;/tt&gt; assignment is not observable in pure-JS interoperably
* &lt;tt&gt;[index]&lt;/tt&gt; assignment is only special for &lt;tt&gt;Array&lt;/tt&gt; and inheriting &lt;tt&gt;Array&lt;/tt&gt; does not imbue types with their specialness.
* &lt;tt&gt;[name]&lt;/tt&gt; assignment can have name collisions between names in an object's prototype chain and those that it ought to contain.  Assigning arbitrary strings in this domain can potentially mask builtins.
* The &lt;tt&gt;in&lt;/tt&gt; operator cannot be safely used on &lt;tt&gt;Object&lt;/tt&gt; instances to check for containment or iteration.  You have to use the &lt;tt&gt;Object.prototype.hasOwnProperty.call&lt;/tt&gt; method instead.
* Proxies for native objects cannot observe indexing or length assignment.
* &lt;tt&gt;Array&lt;/tt&gt;'s constructor is not strictly variadic.  That is, creating an Array with a single value that is a number must be done with Array literals.  &lt;tt&gt;Array&lt;/tt&gt; and &lt;tt&gt;Object&lt;/tt&gt; do not support copy construction.
* &lt;tt&gt;Object&lt;/tt&gt; can only be used for mappings from a domain of strings.

However, there are distinct advantages of playing nicely with these types, like 
being able to use the &lt;tt&gt;Array.prototype&lt;/tt&gt; generic methods.  For this reason,
there need to be two layers of collection types: those that play well with
natives (&quot;rhinocerous types&quot;, if you will), and those that can be manipulated
in pure JavaScript using a new set of conventional names.  With these
user-defined types, it's necessary to use methods for all interaction with
the underlying collection.

We can create a system of base types that support
mutual copy construction and mutual interface implementation.
That is, all collections should be constructable
by passing an iterable as their argument, and in turn all collections should
be iterable.  Python does this well, but we can do one step better by making
the default iteration on dictionary mappings to render an iterable of
(key, value) pairs instead of simply the keys.  We can also define orthogonal
interfaces intrinsic to each of the three main collection types and cross
implement those interfaces in each other type to the extent it make sense.
That is, a List is a duck-type for a Dict where the keys are offsets.
A Dict is a Set of pairs.  A Set is an unordered List.

Methods intrinsic to:
* Set (unordered values): insert, remove, retrieve, discard
* Dict (unordered pairs): get, set, del, has, put, cut
* List (ordered values, (index value pairs)): push, pop, shift, unshift

But List implements all of these Dict interface, and Dict can inherit Set.

This is a proposal for modules to be included in the standard library.
Since there's some coupling between iteration and stream IO, I've begun
layout out those modules as well.  My recommendation is to implement
the IO, file, and socket modules in the standard library.  That would leave
each platform to implement a &quot;posix&quot; module with all the routines that
these other libraries would need.

This is very rough draft status.  I imagine there's a lot of room for
discussion on nomenclature and intended scope for the ServerJS
standard library.

== API ==

* Iterations Module API [[ServerJS/API/iter/ProposalK]]
* Sets Module API [[ServerJS/API/set/ProposalK]]
* Dictionaries Module API [[ServerJS/API/dict/ProposalK]]
* Lists Module API [[ServerJS/API/list/ProposalK]]
* Posix Module API [[ServerJS/API/posix/ProposalK]]
* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]</text>
    </revision>
    <revision>
      <id>35</id>
      <timestamp>2009-02-20T00:04:52Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>/* API */</comment>
      <text xml:space="preserve">== Synopsis ==

In JavaScript there are both &quot;rhinocerous&quot;, native patterns for collection
types embodied by the usage and generic methods of &lt;tt&gt;Array&lt;/tt&gt; and
&lt;tt&gt;Object&lt;/tt&gt;.  However these objects and their patterns have several disadvantages
which give rise to the need for &quot;best practices&quot; in user-defined collections.

* &lt;tt&gt;.length&lt;/tt&gt; assignment is not observable in pure-JS interoperably
* &lt;tt&gt;[index]&lt;/tt&gt; assignment is only special for &lt;tt&gt;Array&lt;/tt&gt; and inheriting &lt;tt&gt;Array&lt;/tt&gt; does not imbue types with their specialness.
* &lt;tt&gt;[name]&lt;/tt&gt; assignment can have name collisions between names in an object's prototype chain and those that it ought to contain.  Assigning arbitrary strings in this domain can potentially mask builtins.
* The &lt;tt&gt;in&lt;/tt&gt; operator cannot be safely used on &lt;tt&gt;Object&lt;/tt&gt; instances to check for containment or iteration.  You have to use the &lt;tt&gt;Object.prototype.hasOwnProperty.call&lt;/tt&gt; method instead.
* Proxies for native objects cannot observe indexing or length assignment.
* &lt;tt&gt;Array&lt;/tt&gt;'s constructor is not strictly variadic.  That is, creating an Array with a single value that is a number must be done with Array literals.  &lt;tt&gt;Array&lt;/tt&gt; and &lt;tt&gt;Object&lt;/tt&gt; do not support copy construction.
* &lt;tt&gt;Object&lt;/tt&gt; can only be used for mappings from a domain of strings.

However, there are distinct advantages of playing nicely with these types, like 
being able to use the &lt;tt&gt;Array.prototype&lt;/tt&gt; generic methods.  For this reason,
there need to be two layers of collection types: those that play well with
natives (&quot;rhinocerous types&quot;, if you will), and those that can be manipulated
in pure JavaScript using a new set of conventional names.  With these
user-defined types, it's necessary to use methods for all interaction with
the underlying collection.

We can create a system of base types that support
mutual copy construction and mutual interface implementation.
That is, all collections should be constructable
by passing an iterable as their argument, and in turn all collections should
be iterable.  Python does this well, but we can do one step better by making
the default iteration on dictionary mappings to render an iterable of
(key, value) pairs instead of simply the keys.  We can also define orthogonal
interfaces intrinsic to each of the three main collection types and cross
implement those interfaces in each other type to the extent it make sense.
That is, a List is a duck-type for a Dict where the keys are offsets.
A Dict is a Set of pairs.  A Set is an unordered List.

Methods intrinsic to:
* Set (unordered values): insert, remove, retrieve, discard
* Dict (unordered pairs): get, set, del, has, put, cut
* List (ordered values, (index value pairs)): push, pop, shift, unshift

But List implements all of these Dict interface, and Dict can inherit Set.

This is a proposal for modules to be included in the standard library.
Since there's some coupling between iteration and stream IO, I've begun
layout out those modules as well.  My recommendation is to implement
the IO, file, and socket modules in the standard library.  That would leave
each platform to implement a &quot;posix&quot; module with all the routines that
these other libraries would need.

This is very rough draft status.  I imagine there's a lot of room for
discussion on nomenclature and intended scope for the ServerJS
standard library.

== API ==

* Iterations Module API [[ServerJS/API/iter/ProposalK]]
* Sets Module API [[ServerJS/API/set/ProposalK]]
* Dictionaries Module API [[ServerJS/API/dict/ProposalK]]
* Lists Module API [[ServerJS/API/list/ProposalK]]
* Binary Module API [[ServerJS/API/binary/ProposalK]]
* Posix Module API [[ServerJS/API/posix/ProposalK]]
* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]</text>
    </revision>
    <revision>
      <id>36</id>
      <timestamp>2009-02-20T00:05:26Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>/* Synopsis */</comment>
      <text xml:space="preserve">== Synopsis ==

In JavaScript there are both &quot;javascriptish/rhinocerous&quot;, native patterns for collection
types embodied by the usage and generic methods of &lt;tt&gt;Array&lt;/tt&gt; and
&lt;tt&gt;Object&lt;/tt&gt;.  However these objects and their patterns have several disadvantages
which give rise to the need for &quot;best practices&quot; in user-defined collections.

* &lt;tt&gt;.length&lt;/tt&gt; assignment is not observable in pure-JS interoperably
* &lt;tt&gt;[index]&lt;/tt&gt; assignment is only special for &lt;tt&gt;Array&lt;/tt&gt; and inheriting &lt;tt&gt;Array&lt;/tt&gt; does not imbue types with their specialness.
* &lt;tt&gt;[name]&lt;/tt&gt; assignment can have name collisions between names in an object's prototype chain and those that it ought to contain.  Assigning arbitrary strings in this domain can potentially mask builtins.
* The &lt;tt&gt;in&lt;/tt&gt; operator cannot be safely used on &lt;tt&gt;Object&lt;/tt&gt; instances to check for containment or iteration.  You have to use the &lt;tt&gt;Object.prototype.hasOwnProperty.call&lt;/tt&gt; method instead.
* Proxies for native objects cannot observe indexing or length assignment.
* &lt;tt&gt;Array&lt;/tt&gt;'s constructor is not strictly variadic.  That is, creating an Array with a single value that is a number must be done with Array literals.  &lt;tt&gt;Array&lt;/tt&gt; and &lt;tt&gt;Object&lt;/tt&gt; do not support copy construction.
* &lt;tt&gt;Object&lt;/tt&gt; can only be used for mappings from a domain of strings.

However, there are distinct advantages of playing nicely with these types, like 
being able to use the &lt;tt&gt;Array.prototype&lt;/tt&gt; generic methods.  For this reason,
there need to be two layers of collection types: those that play well with
natives (&quot;rhinocerous types&quot;, if you will), and those that can be manipulated
in pure JavaScript using a new set of conventional names.  With these
user-defined types, it's necessary to use methods for all interaction with
the underlying collection.

We can create a system of base types that support
mutual copy construction and mutual interface implementation.
That is, all collections should be constructable
by passing an iterable as their argument, and in turn all collections should
be iterable.  Python does this well, but we can do one step better by making
the default iteration on dictionary mappings to render an iterable of
(key, value) pairs instead of simply the keys.  We can also define orthogonal
interfaces intrinsic to each of the three main collection types and cross
implement those interfaces in each other type to the extent it make sense.
That is, a List is a duck-type for a Dict where the keys are offsets.
A Dict is a Set of pairs.  A Set is an unordered List.

Methods intrinsic to:
* Set (unordered values): insert, remove, retrieve, discard
* Dict (unordered pairs): get, set, del, has, put, cut
* List (ordered values, (index value pairs)): push, pop, shift, unshift

But List implements all of these Dict interface, and Dict can inherit Set.

This is a proposal for modules to be included in the standard library.
Since there's some coupling between iteration and stream IO, I've begun
layout out those modules as well.  My recommendation is to implement
the IO, file, and socket modules in the standard library.  That would leave
each platform to implement a &quot;posix&quot; module with all the routines that
these other libraries would need.

This is very rough draft status.  I imagine there's a lot of room for
discussion on nomenclature and intended scope for the ServerJS
standard library.

== API ==

* Iterations Module API [[ServerJS/API/iter/ProposalK]]
* Sets Module API [[ServerJS/API/set/ProposalK]]
* Dictionaries Module API [[ServerJS/API/dict/ProposalK]]
* Lists Module API [[ServerJS/API/list/ProposalK]]
* Binary Module API [[ServerJS/API/binary/ProposalK]]
* Posix Module API [[ServerJS/API/posix/ProposalK]]
* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]</text>
    </revision>
    <revision>
      <id>37</id>
      <timestamp>2009-09-09T22:13:49Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>10 revisions:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve">== Synopsis ==

In JavaScript there are both &quot;javascriptish/rhinocerous&quot;, native patterns for collection
types embodied by the usage and generic methods of &lt;tt&gt;Array&lt;/tt&gt; and
&lt;tt&gt;Object&lt;/tt&gt;.  However these objects and their patterns have several disadvantages
which give rise to the need for &quot;best practices&quot; in user-defined collections.

* &lt;tt&gt;.length&lt;/tt&gt; assignment is not observable in pure-JS interoperably
* &lt;tt&gt;[index]&lt;/tt&gt; assignment is only special for &lt;tt&gt;Array&lt;/tt&gt; and inheriting &lt;tt&gt;Array&lt;/tt&gt; does not imbue types with their specialness.
* &lt;tt&gt;[name]&lt;/tt&gt; assignment can have name collisions between names in an object's prototype chain and those that it ought to contain.  Assigning arbitrary strings in this domain can potentially mask builtins.
* The &lt;tt&gt;in&lt;/tt&gt; operator cannot be safely used on &lt;tt&gt;Object&lt;/tt&gt; instances to check for containment or iteration.  You have to use the &lt;tt&gt;Object.prototype.hasOwnProperty.call&lt;/tt&gt; method instead.
* Proxies for native objects cannot observe indexing or length assignment.
* &lt;tt&gt;Array&lt;/tt&gt;'s constructor is not strictly variadic.  That is, creating an Array with a single value that is a number must be done with Array literals.  &lt;tt&gt;Array&lt;/tt&gt; and &lt;tt&gt;Object&lt;/tt&gt; do not support copy construction.
* &lt;tt&gt;Object&lt;/tt&gt; can only be used for mappings from a domain of strings.

However, there are distinct advantages of playing nicely with these types, like 
being able to use the &lt;tt&gt;Array.prototype&lt;/tt&gt; generic methods.  For this reason,
there need to be two layers of collection types: those that play well with
natives (&quot;rhinocerous types&quot;, if you will), and those that can be manipulated
in pure JavaScript using a new set of conventional names.  With these
user-defined types, it's necessary to use methods for all interaction with
the underlying collection.

We can create a system of base types that support
mutual copy construction and mutual interface implementation.
That is, all collections should be constructable
by passing an iterable as their argument, and in turn all collections should
be iterable.  Python does this well, but we can do one step better by making
the default iteration on dictionary mappings to render an iterable of
(key, value) pairs instead of simply the keys.  We can also define orthogonal
interfaces intrinsic to each of the three main collection types and cross
implement those interfaces in each other type to the extent it make sense.
That is, a List is a duck-type for a Dict where the keys are offsets.
A Dict is a Set of pairs.  A Set is an unordered List.

Methods intrinsic to:
* Set (unordered values): insert, remove, retrieve, discard
* Dict (unordered pairs): get, set, del, has, put, cut
* List (ordered values, (index value pairs)): push, pop, shift, unshift

But List implements all of these Dict interface, and Dict can inherit Set.

This is a proposal for modules to be included in the standard library.
Since there's some coupling between iteration and stream IO, I've begun
layout out those modules as well.  My recommendation is to implement
the IO, file, and socket modules in the standard library.  That would leave
each platform to implement a &quot;posix&quot; module with all the routines that
these other libraries would need.

This is very rough draft status.  I imagine there's a lot of room for
discussion on nomenclature and intended scope for the ServerJS
standard library.

== API ==

* Iterations Module API [[ServerJS/API/iter/ProposalK]]
* Sets Module API [[ServerJS/API/set/ProposalK]]
* Dictionaries Module API [[ServerJS/API/dict/ProposalK]]
* Lists Module API [[ServerJS/API/list/ProposalK]]
* Binary Module API [[ServerJS/API/binary/ProposalK]]
* Posix Module API [[ServerJS/API/posix/ProposalK]]
* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]</text>
    </revision>
    <revision>
      <id>619</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/ProposalK]] to [[CommonJS/API/ProposalK]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve">== Synopsis ==

In JavaScript there are both &quot;javascriptish/rhinocerous&quot;, native patterns for collection
types embodied by the usage and generic methods of &lt;tt&gt;Array&lt;/tt&gt; and
&lt;tt&gt;Object&lt;/tt&gt;.  However these objects and their patterns have several disadvantages
which give rise to the need for &quot;best practices&quot; in user-defined collections.

* &lt;tt&gt;.length&lt;/tt&gt; assignment is not observable in pure-JS interoperably
* &lt;tt&gt;[index]&lt;/tt&gt; assignment is only special for &lt;tt&gt;Array&lt;/tt&gt; and inheriting &lt;tt&gt;Array&lt;/tt&gt; does not imbue types with their specialness.
* &lt;tt&gt;[name]&lt;/tt&gt; assignment can have name collisions between names in an object's prototype chain and those that it ought to contain.  Assigning arbitrary strings in this domain can potentially mask builtins.
* The &lt;tt&gt;in&lt;/tt&gt; operator cannot be safely used on &lt;tt&gt;Object&lt;/tt&gt; instances to check for containment or iteration.  You have to use the &lt;tt&gt;Object.prototype.hasOwnProperty.call&lt;/tt&gt; method instead.
* Proxies for native objects cannot observe indexing or length assignment.
* &lt;tt&gt;Array&lt;/tt&gt;'s constructor is not strictly variadic.  That is, creating an Array with a single value that is a number must be done with Array literals.  &lt;tt&gt;Array&lt;/tt&gt; and &lt;tt&gt;Object&lt;/tt&gt; do not support copy construction.
* &lt;tt&gt;Object&lt;/tt&gt; can only be used for mappings from a domain of strings.

However, there are distinct advantages of playing nicely with these types, like 
being able to use the &lt;tt&gt;Array.prototype&lt;/tt&gt; generic methods.  For this reason,
there need to be two layers of collection types: those that play well with
natives (&quot;rhinocerous types&quot;, if you will), and those that can be manipulated
in pure JavaScript using a new set of conventional names.  With these
user-defined types, it's necessary to use methods for all interaction with
the underlying collection.

We can create a system of base types that support
mutual copy construction and mutual interface implementation.
That is, all collections should be constructable
by passing an iterable as their argument, and in turn all collections should
be iterable.  Python does this well, but we can do one step better by making
the default iteration on dictionary mappings to render an iterable of
(key, value) pairs instead of simply the keys.  We can also define orthogonal
interfaces intrinsic to each of the three main collection types and cross
implement those interfaces in each other type to the extent it make sense.
That is, a List is a duck-type for a Dict where the keys are offsets.
A Dict is a Set of pairs.  A Set is an unordered List.

Methods intrinsic to:
* Set (unordered values): insert, remove, retrieve, discard
* Dict (unordered pairs): get, set, del, has, put, cut
* List (ordered values, (index value pairs)): push, pop, shift, unshift

But List implements all of these Dict interface, and Dict can inherit Set.

This is a proposal for modules to be included in the standard library.
Since there's some coupling between iteration and stream IO, I've begun
layout out those modules as well.  My recommendation is to implement
the IO, file, and socket modules in the standard library.  That would leave
each platform to implement a &quot;posix&quot; module with all the routines that
these other libraries would need.

This is very rough draft status.  I imagine there's a lot of room for
discussion on nomenclature and intended scope for the ServerJS
standard library.

== API ==

* Iterations Module API [[ServerJS/API/iter/ProposalK]]
* Sets Module API [[ServerJS/API/set/ProposalK]]
* Dictionaries Module API [[ServerJS/API/dict/ProposalK]]
* Lists Module API [[ServerJS/API/list/ProposalK]]
* Binary Module API [[ServerJS/API/binary/ProposalK]]
* Posix Module API [[ServerJS/API/posix/ProposalK]]
* File Module API [[ServerJS/API/file/ProposalK]]
* IO Module API [[ServerJS/API/io/ProposalK]]</text>
    </revision>
    <revision>
      <id>785</id>
      <timestamp>2009-09-09T22:40:09Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-ServerJS +CommonJS)</comment>
      <text xml:space="preserve">== Synopsis ==

In JavaScript there are both &quot;javascriptish/rhinocerous&quot;, native patterns for collection
types embodied by the usage and generic methods of &lt;tt&gt;Array&lt;/tt&gt; and
&lt;tt&gt;Object&lt;/tt&gt;.  However these objects and their patterns have several disadvantages
which give rise to the need for &quot;best practices&quot; in user-defined collections.

* &lt;tt&gt;.length&lt;/tt&gt; assignment is not observable in pure-JS interoperably
* &lt;tt&gt;[index]&lt;/tt&gt; assignment is only special for &lt;tt&gt;Array&lt;/tt&gt; and inheriting &lt;tt&gt;Array&lt;/tt&gt; does not imbue types with their specialness.
* &lt;tt&gt;[name]&lt;/tt&gt; assignment can have name collisions between names in an object's prototype chain and those that it ought to contain.  Assigning arbitrary strings in this domain can potentially mask builtins.
* The &lt;tt&gt;in&lt;/tt&gt; operator cannot be safely used on &lt;tt&gt;Object&lt;/tt&gt; instances to check for containment or iteration.  You have to use the &lt;tt&gt;Object.prototype.hasOwnProperty.call&lt;/tt&gt; method instead.
* Proxies for native objects cannot observe indexing or length assignment.
* &lt;tt&gt;Array&lt;/tt&gt;'s constructor is not strictly variadic.  That is, creating an Array with a single value that is a number must be done with Array literals.  &lt;tt&gt;Array&lt;/tt&gt; and &lt;tt&gt;Object&lt;/tt&gt; do not support copy construction.
* &lt;tt&gt;Object&lt;/tt&gt; can only be used for mappings from a domain of strings.

However, there are distinct advantages of playing nicely with these types, like 
being able to use the &lt;tt&gt;Array.prototype&lt;/tt&gt; generic methods.  For this reason,
there need to be two layers of collection types: those that play well with
natives (&quot;rhinocerous types&quot;, if you will), and those that can be manipulated
in pure JavaScript using a new set of conventional names.  With these
user-defined types, it's necessary to use methods for all interaction with
the underlying collection.

We can create a system of base types that support
mutual copy construction and mutual interface implementation.
That is, all collections should be constructable
by passing an iterable as their argument, and in turn all collections should
be iterable.  Python does this well, but we can do one step better by making
the default iteration on dictionary mappings to render an iterable of
(key, value) pairs instead of simply the keys.  We can also define orthogonal
interfaces intrinsic to each of the three main collection types and cross
implement those interfaces in each other type to the extent it make sense.
That is, a List is a duck-type for a Dict where the keys are offsets.
A Dict is a Set of pairs.  A Set is an unordered List.

Methods intrinsic to:
* Set (unordered values): insert, remove, retrieve, discard
* Dict (unordered pairs): get, set, del, has, put, cut
* List (ordered values, (index value pairs)): push, pop, shift, unshift

But List implements all of these Dict interface, and Dict can inherit Set.

This is a proposal for modules to be included in the standard library.
Since there's some coupling between iteration and stream IO, I've begun
layout out those modules as well.  My recommendation is to implement
the IO, file, and socket modules in the standard library.  That would leave
each platform to implement a &quot;posix&quot; module with all the routines that
these other libraries would need.

This is very rough draft status.  I imagine there's a lot of room for
discussion on nomenclature and intended scope for the CommonJS
standard library.

== API ==

* Iterations Module API [[CommonJS/API/iter/ProposalK]]
* Sets Module API [[CommonJS/API/set/ProposalK]]
* Dictionaries Module API [[CommonJS/API/dict/ProposalK]]
* Lists Module API [[CommonJS/API/list/ProposalK]]
* Binary Module API [[CommonJS/API/binary/ProposalK]]
* Posix Module API [[CommonJS/API/posix/ProposalK]]
* File Module API [[CommonJS/API/file/ProposalK]]
* IO Module API [[CommonJS/API/io/ProposalK]]</text>
    </revision>
    <revision>
      <id>969</id>
      <timestamp>2009-09-10T03:13:56Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/ProposalK]] to [[OldAPI/ProposalK]]</comment>
      <text xml:space="preserve">== Synopsis ==

In JavaScript there are both &quot;javascriptish/rhinocerous&quot;, native patterns for collection
types embodied by the usage and generic methods of &lt;tt&gt;Array&lt;/tt&gt; and
&lt;tt&gt;Object&lt;/tt&gt;.  However these objects and their patterns have several disadvantages
which give rise to the need for &quot;best practices&quot; in user-defined collections.

* &lt;tt&gt;.length&lt;/tt&gt; assignment is not observable in pure-JS interoperably
* &lt;tt&gt;[index]&lt;/tt&gt; assignment is only special for &lt;tt&gt;Array&lt;/tt&gt; and inheriting &lt;tt&gt;Array&lt;/tt&gt; does not imbue types with their specialness.
* &lt;tt&gt;[name]&lt;/tt&gt; assignment can have name collisions between names in an object's prototype chain and those that it ought to contain.  Assigning arbitrary strings in this domain can potentially mask builtins.
* The &lt;tt&gt;in&lt;/tt&gt; operator cannot be safely used on &lt;tt&gt;Object&lt;/tt&gt; instances to check for containment or iteration.  You have to use the &lt;tt&gt;Object.prototype.hasOwnProperty.call&lt;/tt&gt; method instead.
* Proxies for native objects cannot observe indexing or length assignment.
* &lt;tt&gt;Array&lt;/tt&gt;'s constructor is not strictly variadic.  That is, creating an Array with a single value that is a number must be done with Array literals.  &lt;tt&gt;Array&lt;/tt&gt; and &lt;tt&gt;Object&lt;/tt&gt; do not support copy construction.
* &lt;tt&gt;Object&lt;/tt&gt; can only be used for mappings from a domain of strings.

However, there are distinct advantages of playing nicely with these types, like 
being able to use the &lt;tt&gt;Array.prototype&lt;/tt&gt; generic methods.  For this reason,
there need to be two layers of collection types: those that play well with
natives (&quot;rhinocerous types&quot;, if you will), and those that can be manipulated
in pure JavaScript using a new set of conventional names.  With these
user-defined types, it's necessary to use methods for all interaction with
the underlying collection.

We can create a system of base types that support
mutual copy construction and mutual interface implementation.
That is, all collections should be constructable
by passing an iterable as their argument, and in turn all collections should
be iterable.  Python does this well, but we can do one step better by making
the default iteration on dictionary mappings to render an iterable of
(key, value) pairs instead of simply the keys.  We can also define orthogonal
interfaces intrinsic to each of the three main collection types and cross
implement those interfaces in each other type to the extent it make sense.
That is, a List is a duck-type for a Dict where the keys are offsets.
A Dict is a Set of pairs.  A Set is an unordered List.

Methods intrinsic to:
* Set (unordered values): insert, remove, retrieve, discard
* Dict (unordered pairs): get, set, del, has, put, cut
* List (ordered values, (index value pairs)): push, pop, shift, unshift

But List implements all of these Dict interface, and Dict can inherit Set.

This is a proposal for modules to be included in the standard library.
Since there's some coupling between iteration and stream IO, I've begun
layout out those modules as well.  My recommendation is to implement
the IO, file, and socket modules in the standard library.  That would leave
each platform to implement a &quot;posix&quot; module with all the routines that
these other libraries would need.

This is very rough draft status.  I imagine there's a lot of room for
discussion on nomenclature and intended scope for the CommonJS
standard library.

== API ==

* Iterations Module API [[CommonJS/API/iter/ProposalK]]
* Sets Module API [[CommonJS/API/set/ProposalK]]
* Dictionaries Module API [[CommonJS/API/dict/ProposalK]]
* Lists Module API [[CommonJS/API/list/ProposalK]]
* Binary Module API [[CommonJS/API/binary/ProposalK]]
* Posix Module API [[CommonJS/API/posix/ProposalK]]
* File Module API [[CommonJS/API/file/ProposalK]]
* IO Module API [[CommonJS/API/io/ProposalK]]</text>
    </revision>
    <revision>
      <id>1000</id>
      <timestamp>2009-09-10T03:15:45Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-CommonJS/API +OldAPI)</comment>
      <text xml:space="preserve">== Synopsis ==

In JavaScript there are both &quot;javascriptish/rhinocerous&quot;, native patterns for collection
types embodied by the usage and generic methods of &lt;tt&gt;Array&lt;/tt&gt; and
&lt;tt&gt;Object&lt;/tt&gt;.  However these objects and their patterns have several disadvantages
which give rise to the need for &quot;best practices&quot; in user-defined collections.

* &lt;tt&gt;.length&lt;/tt&gt; assignment is not observable in pure-JS interoperably
* &lt;tt&gt;[index]&lt;/tt&gt; assignment is only special for &lt;tt&gt;Array&lt;/tt&gt; and inheriting &lt;tt&gt;Array&lt;/tt&gt; does not imbue types with their specialness.
* &lt;tt&gt;[name]&lt;/tt&gt; assignment can have name collisions between names in an object's prototype chain and those that it ought to contain.  Assigning arbitrary strings in this domain can potentially mask builtins.
* The &lt;tt&gt;in&lt;/tt&gt; operator cannot be safely used on &lt;tt&gt;Object&lt;/tt&gt; instances to check for containment or iteration.  You have to use the &lt;tt&gt;Object.prototype.hasOwnProperty.call&lt;/tt&gt; method instead.
* Proxies for native objects cannot observe indexing or length assignment.
* &lt;tt&gt;Array&lt;/tt&gt;'s constructor is not strictly variadic.  That is, creating an Array with a single value that is a number must be done with Array literals.  &lt;tt&gt;Array&lt;/tt&gt; and &lt;tt&gt;Object&lt;/tt&gt; do not support copy construction.
* &lt;tt&gt;Object&lt;/tt&gt; can only be used for mappings from a domain of strings.

However, there are distinct advantages of playing nicely with these types, like 
being able to use the &lt;tt&gt;Array.prototype&lt;/tt&gt; generic methods.  For this reason,
there need to be two layers of collection types: those that play well with
natives (&quot;rhinocerous types&quot;, if you will), and those that can be manipulated
in pure JavaScript using a new set of conventional names.  With these
user-defined types, it's necessary to use methods for all interaction with
the underlying collection.

We can create a system of base types that support
mutual copy construction and mutual interface implementation.
That is, all collections should be constructable
by passing an iterable as their argument, and in turn all collections should
be iterable.  Python does this well, but we can do one step better by making
the default iteration on dictionary mappings to render an iterable of
(key, value) pairs instead of simply the keys.  We can also define orthogonal
interfaces intrinsic to each of the three main collection types and cross
implement those interfaces in each other type to the extent it make sense.
That is, a List is a duck-type for a Dict where the keys are offsets.
A Dict is a Set of pairs.  A Set is an unordered List.

Methods intrinsic to:
* Set (unordered values): insert, remove, retrieve, discard
* Dict (unordered pairs): get, set, del, has, put, cut
* List (ordered values, (index value pairs)): push, pop, shift, unshift

But List implements all of these Dict interface, and Dict can inherit Set.

This is a proposal for modules to be included in the standard library.
Since there's some coupling between iteration and stream IO, I've begun
layout out those modules as well.  My recommendation is to implement
the IO, file, and socket modules in the standard library.  That would leave
each platform to implement a &quot;posix&quot; module with all the routines that
these other libraries would need.

This is very rough draft status.  I imagine there's a lot of room for
discussion on nomenclature and intended scope for the CommonJS
standard library.

== API ==

* Iterations Module API [[OldAPI/iter/ProposalK]]
* Sets Module API [[OldAPI/set/ProposalK]]
* Dictionaries Module API [[OldAPI/dict/ProposalK]]
* Lists Module API [[OldAPI/list/ProposalK]]
* Binary Module API [[OldAPI/binary/ProposalK]]
* Posix Module API [[OldAPI/posix/ProposalK]]
* File Module API [[OldAPI/file/ProposalK]]
* IO Module API [[OldAPI/io/ProposalK]]</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/binary</title>
    <id>5</id>
    <revision>
      <id>38</id>
      <timestamp>2009-04-14T05:03:47Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Created page with 'Please see the [[ServerJS/Binary|Binary]] proposal for details about the contents of the &quot;binary&quot; module.'</comment>
      <text xml:space="preserve">Please see the [[ServerJS/Binary|Binary]] proposal for details about the contents of the &quot;binary&quot; module.</text>
    </revision>
    <revision>
      <id>39</id>
      <timestamp>2009-09-09T22:13:49Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>1 revision:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve">Please see the [[ServerJS/Binary|Binary]] proposal for details about the contents of the &quot;binary&quot; module.</text>
    </revision>
    <revision>
      <id>621</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/binary]] to [[CommonJS/API/binary]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve">Please see the [[ServerJS/Binary|Binary]] proposal for details about the contents of the &quot;binary&quot; module.</text>
    </revision>
    <revision>
      <id>786</id>
      <timestamp>2009-09-09T22:40:18Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-ServerJS +CommonJS)</comment>
      <text xml:space="preserve">Please see the [[CommonJS/Binary|Binary]] proposal for details about the contents of the &quot;binary&quot; module.</text>
    </revision>
    <revision>
      <id>971</id>
      <timestamp>2009-09-10T03:13:56Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/binary]] to [[OldAPI/binary]]</comment>
      <text xml:space="preserve">Please see the [[CommonJS/Binary|Binary]] proposal for details about the contents of the &quot;binary&quot; module.</text>
    </revision>
    <revision>
      <id>1212</id>
      <timestamp>2009-09-12T02:31:12Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-CommonJS/ +)</comment>
      <text xml:space="preserve">Please see the [[Binary|Binary]] proposal for details about the contents of the &quot;binary&quot; module.</text>
    </revision>
    <revision>
      <id>1247</id>
      <timestamp>2009-09-12T04:40:59Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-\[\[(.+?)\|\1\]\] +[[\1]])</comment>
      <text xml:space="preserve">Please see the [[Binary]] proposal for details about the contents of the &quot;binary&quot; module.</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/binary/ProposalK</title>
    <id>6</id>
    <revision>
      <id>40</id>
      <timestamp>2009-02-20T00:03:30Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Added a preliminary API for Binary types in ServerJS.</comment>
      <text xml:space="preserve"> 
 /*** Binary
     Returns a  representation of an array of bytes.
     Accepts a Binary, or an Array of Numbers.
     Throws an error if any Number is greater than or equal to 256,
     less than 0, or of sub-integer precision.
 */
 
 /**** length
 */
 
 /**** get
 */
 
 /**** set
 */
 
 /**** slice
 */
 
 /**** concat
 */
 
 /**** indexOf
 */
 
 /**** replace
 */
 
 /**** toSource
 */
 
 /**** toString
 */
 
 /**** toSource
 */</text>
    </revision>
    <revision>
      <id>41</id>
      <timestamp>2009-09-09T22:13:49Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>1 revision:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve"> 
 /*** Binary
     Returns a  representation of an array of bytes.
     Accepts a Binary, or an Array of Numbers.
     Throws an error if any Number is greater than or equal to 256,
     less than 0, or of sub-integer precision.
 */
 
 /**** length
 */
 
 /**** get
 */
 
 /**** set
 */
 
 /**** slice
 */
 
 /**** concat
 */
 
 /**** indexOf
 */
 
 /**** replace
 */
 
 /**** toSource
 */
 
 /**** toString
 */
 
 /**** toSource
 */</text>
    </revision>
    <revision>
      <id>623</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/binary/ProposalK]] to [[CommonJS/API/binary/ProposalK]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve"> 
 /*** Binary
     Returns a  representation of an array of bytes.
     Accepts a Binary, or an Array of Numbers.
     Throws an error if any Number is greater than or equal to 256,
     less than 0, or of sub-integer precision.
 */
 
 /**** length
 */
 
 /**** get
 */
 
 /**** set
 */
 
 /**** slice
 */
 
 /**** concat
 */
 
 /**** indexOf
 */
 
 /**** replace
 */
 
 /**** toSource
 */
 
 /**** toString
 */
 
 /**** toSource
 */</text>
    </revision>
    <revision>
      <id>973</id>
      <timestamp>2009-09-10T03:13:56Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/binary/ProposalK]] to [[OldAPI/binary/ProposalK]]</comment>
      <text xml:space="preserve"> 
 /*** Binary
     Returns a  representation of an array of bytes.
     Accepts a Binary, or an Array of Numbers.
     Throws an error if any Number is greater than or equal to 256,
     less than 0, or of sub-integer precision.
 */
 
 /**** length
 */
 
 /**** get
 */
 
 /**** set
 */
 
 /**** slice
 */
 
 /**** concat
 */
 
 /**** indexOf
 */
 
 /**** replace
 */
 
 /**** toSource
 */
 
 /**** toString
 */
 
 /**** toSource
 */</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/console</title>
    <id>7</id>
    <revision>
      <id>42</id>
      <timestamp>2009-04-14T05:20:53Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Added a preliminary proposal for the console module API.</comment>
      <text xml:space="preserve">The &quot;console&quot; top-level module must be available in all platforms.  The module must provide the following exports:

; log(message, [level]): logs a message.  The level may be any of &quot;log&quot;, &quot;info&quot;, &quot;warn&quot;, &quot;error&quot;, &quot;debug&quot;, &quot;pass&quot;, &quot;fail&quot;, null, or undefined.  Other labels beginning with &quot;x&quot; and a platform-specific identifier are reserved for the corresponding platform.
; info(message) : logs an informational message
; warn(message) : logs a warning message
; error(message) : logs an error message
; debug(message) : logs a debug message
; pass(name) : logs the success of a test
; fail(name) : logs the failure of a test

Message may be any object reference.


= Prior Art =
* [http://getfirebug.com/logging.html Firebug]
* [http://developer.apple.com/internet/safari/faq.html#anchor14 Safari 1.3 Console]
* [http://operawiki.info/OperaJSConsole Opera JavaScript Console]
* Internet Explorer 8 JavaScript Console

= Relevant Discussions =

= Show of Hands =

= Implementations =</text>
    </revision>
    <revision>
      <id>43</id>
      <timestamp>2009-04-14T05:22:13Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <text xml:space="preserve">The &quot;console&quot; top-level module must be available in all platforms.  The module must provide the following exports:

; log(message) : logs a message
; info(message) : logs an informational message
; warn(message) : logs a warning message
; error(message) : logs an error message
; debug(message) : logs a debug message
; pass(name) : logs the success of a test
; fail(name) : logs the failure of a test
; print(message, [level]): logs a message.  The level may be any of &quot;log&quot;, &quot;info&quot;, &quot;warn&quot;, &quot;error&quot;, &quot;debug&quot;, &quot;pass&quot;, &quot;fail&quot;, null, or undefined.  Other labels beginning with &quot;x&quot; and a platform-specific identifier are reserved for the corresponding platform.

Messages may be any reference.  Names must be strings.


= Prior Art =
* [http://getfirebug.com/logging.html Firebug]
* [http://developer.apple.com/internet/safari/faq.html#anchor14 Safari 1.3 Console]
* [http://operawiki.info/OperaJSConsole Opera JavaScript Console]
* Internet Explorer 8 JavaScript Console

= Relevant Discussions =

= Show of Hands =

= Implementations =</text>
    </revision>
    <revision>
      <id>44</id>
      <timestamp>2009-04-14T05:38:09Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Added a summary.</comment>
      <text xml:space="preserve">Many client-side libraries already support a JavaScript console object.  Since this functionality is useful on the server, and to ease migration of client-side JavaScript to the server, server-side JavaScript platforms need to provide a &quot;console&quot; object suitable for use with minimal modification to existing scripts.  Rather than provide a &quot;console&quot; free variable like web browsers, interoperable JavaScript modules may explicitly import the &quot;console&quot; module and bind it to a module local &quot;console&quot; variable.

= Specification =

The &quot;console&quot; top-level module must be available in all platforms.  The module must provide the following exports:

; log(message) : logs a message
; info(message) : logs an informational message
; warn(message) : logs a warning message
; error(message) : logs an error message
; debug(message) : logs a debug message
; pass(name) : logs the success of a test
; fail(name) : logs the failure of a test
; print(message, [level]): logs a message.  The level may be any of &quot;log&quot;, &quot;info&quot;, &quot;warn&quot;, &quot;error&quot;, &quot;debug&quot;, &quot;pass&quot;, &quot;fail&quot;, null, or undefined.  Other labels beginning with &quot;x&quot; and a platform-specific identifier are reserved for the corresponding platform.

Messages may be any reference.  Names must be strings.


= Prior Art =
* [http://getfirebug.com/logging.html Firebug]
* [http://developer.apple.com/internet/safari/faq.html#anchor14 Safari 1.3 Console]
* [http://operawiki.info/OperaJSConsole Opera JavaScript Console]
* Internet Explorer 8 JavaScript Console

= Relevant Discussions =

= Show of Hands =

= Implementations =</text>
    </revision>
    <revision>
      <id>45</id>
      <timestamp>2009-04-14T18:34:58Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Redacted print, pass, and fail.</comment>
      <text xml:space="preserve">Many client-side libraries already support a JavaScript console object.  Since this functionality is useful on the server, and to ease migration of client-side JavaScript to the server, server-side JavaScript platforms need to provide a &quot;console&quot; object suitable for use with minimal modification to existing scripts.  Rather than provide a &quot;console&quot; free variable like web browsers, interoperable JavaScript modules may explicitly import the &quot;console&quot; module and bind it to a module local &quot;console&quot; variable.

= Specification =

The &quot;console&quot; top-level module must be available in all platforms.  The module must provide the following exports:

; log(message) : logs a message
; info(message) : logs an informational message
; warn(message) : logs a warning message
; error(message) : logs an error message

Messages may be any reference.  Names must be strings.


= Prior Art =
* [http://getfirebug.com/logging.html Firebug]
* [http://developer.apple.com/internet/safari/faq.html#anchor14 Safari 1.3 Console]
* [http://operawiki.info/OperaJSConsole Opera JavaScript Console]
* Internet Explorer 8 JavaScript Console

= Relevant Discussions =

= Show of Hands =

= Implementations =</text>
    </revision>
    <revision>
      <id>46</id>
      <timestamp>2009-09-09T22:13:50Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>4 revisions:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve">Many client-side libraries already support a JavaScript console object.  Since this functionality is useful on the server, and to ease migration of client-side JavaScript to the server, server-side JavaScript platforms need to provide a &quot;console&quot; object suitable for use with minimal modification to existing scripts.  Rather than provide a &quot;console&quot; free variable like web browsers, interoperable JavaScript modules may explicitly import the &quot;console&quot; module and bind it to a module local &quot;console&quot; variable.

= Specification =

The &quot;console&quot; top-level module must be available in all platforms.  The module must provide the following exports:

; log(message) : logs a message
; info(message) : logs an informational message
; warn(message) : logs a warning message
; error(message) : logs an error message

Messages may be any reference.  Names must be strings.


= Prior Art =
* [http://getfirebug.com/logging.html Firebug]
* [http://developer.apple.com/internet/safari/faq.html#anchor14 Safari 1.3 Console]
* [http://operawiki.info/OperaJSConsole Opera JavaScript Console]
* Internet Explorer 8 JavaScript Console

= Relevant Discussions =

= Show of Hands =

= Implementations =</text>
    </revision>
    <revision>
      <id>625</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/console]] to [[CommonJS/API/console]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve">Many client-side libraries already support a JavaScript console object.  Since this functionality is useful on the server, and to ease migration of client-side JavaScript to the server, server-side JavaScript platforms need to provide a &quot;console&quot; object suitable for use with minimal modification to existing scripts.  Rather than provide a &quot;console&quot; free variable like web browsers, interoperable JavaScript modules may explicitly import the &quot;console&quot; module and bind it to a module local &quot;console&quot; variable.

= Specification =

The &quot;console&quot; top-level module must be available in all platforms.  The module must provide the following exports:

; log(message) : logs a message
; info(message) : logs an informational message
; warn(message) : logs a warning message
; error(message) : logs an error message

Messages may be any reference.  Names must be strings.


= Prior Art =
* [http://getfirebug.com/logging.html Firebug]
* [http://developer.apple.com/internet/safari/faq.html#anchor14 Safari 1.3 Console]
* [http://operawiki.info/OperaJSConsole Opera JavaScript Console]
* Internet Explorer 8 JavaScript Console

= Relevant Discussions =

= Show of Hands =

= Implementations =</text>
    </revision>
    <revision>
      <id>975</id>
      <timestamp>2009-09-10T03:13:56Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/console]] to [[OldAPI/console]]</comment>
      <text xml:space="preserve">Many client-side libraries already support a JavaScript console object.  Since this functionality is useful on the server, and to ease migration of client-side JavaScript to the server, server-side JavaScript platforms need to provide a &quot;console&quot; object suitable for use with minimal modification to existing scripts.  Rather than provide a &quot;console&quot; free variable like web browsers, interoperable JavaScript modules may explicitly import the &quot;console&quot; module and bind it to a module local &quot;console&quot; variable.

= Specification =

The &quot;console&quot; top-level module must be available in all platforms.  The module must provide the following exports:

; log(message) : logs a message
; info(message) : logs an informational message
; warn(message) : logs a warning message
; error(message) : logs an error message

Messages may be any reference.  Names must be strings.


= Prior Art =
* [http://getfirebug.com/logging.html Firebug]
* [http://developer.apple.com/internet/safari/faq.html#anchor14 Safari 1.3 Console]
* [http://operawiki.info/OperaJSConsole Opera JavaScript Console]
* Internet Explorer 8 JavaScript Console

= Relevant Discussions =

= Show of Hands =

= Implementations =</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/dict/ProposalK</title>
    <id>8</id>
    <revision>
      <id>47</id>
      <timestamp>2009-02-18T22:00:48Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Added a proposal for a dictionary module for ServerJS</comment>
      <text xml:space="preserve"> 
 /*** Dict
     an unordered collection of key to value mappings.
     Unlike `Object`, a `Dict` object's key domain includes any
     object, with better performance when the `hash` of each
     key does not collide.  That is, the `Number` ``1`` and the
     `String` ``&quot;1&quot;`` are distinct objects.
 
     `Dict` inherits from  `Iterable` and `Set`, overriding the `eq` and
     `hash` of the underlying `Set` to use versions that hash and compare
     equivalence based on the pair component of key value pairs.
 
     Different than Python ``dict``:
 
     - ``update``: `add`
     - ``has_key``: `hasKey`
     - ``iteritems``: `itemsIter`
     - ``iterkeys``: `keysIter`
     - ``itervalues``: `valuesIter`
     - ``fromkeys(S, v)``: ``Dict(each(S.keys(), function (k) {return [k, v]}))``
     - ``setdefault``: use `set` and `get`
     - ``__del__`` -&gt; `remove`
     - ``__contains__`` -&gt; `has`
 
     Same as Python:
 
     - `get`
     - `clear`
     - `copy`
     - `items`
     - `keys`
     - `values`
     - `pop`
 
 */
 
     /**** keysIter
         returns an `Iter` of keys from the 
         key and value pairs (items) in the dictionary.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** keys
         returns a `Set` of keys from the 
         key and value pairs (items) in the dictionary.
         Uses `keysIter` and `itemsIter`.
 
         - `stateless`
     */
 
     /**** valuesIter
         returns an `Iter` of values from the
         key and value pairs (items) in the dictinoary.
         Uses `itemsiter`.
 
         - `stateless`
     */
 
     /**** values
         returns a `List` of values from the
         key and value pairs (items) in the dictionary.
         Uses `valuesIter` and `itemsIter`.
 
         - `stateless`
     */
 
     /**** itemsIter
         returns an iteration, `Iter`, of the key and
         value pairs (items) in the dictionary.
         Items are represented as native JavaScript
         `Array` objects.
         Uses `iter`, which is defined for the
         `Set` base-type.
 
         - `stateless`
     */
 
     /**** items
         returns a `List` of the key and value
         pairs (items) in the dictionary.
         Items are represnted as native JavaScript
         `Array` objects.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** get
         returns the value of an item in
         the dictionary that has a given
         key.  If there is item for the key,
         attempts to return a default value, 
         checking whether you've specified
         a default value to return as a second
         argument, or deferring to `getDefault`.
         If no acceptable default exists,
         throws a `KeyError`.
 
         accepts:
         - a key (any object)
         - an optional default value, which
            can be `undefined` or `null`
            if you wish to avoid throwing
            a `KeyError`.
 
         - `stateless`
     */
 
     /**** set 
         stores a key and corresponding value
         (an item) in the dictionary.  If
         an item already exists in the dictionary
         that has the same key, it is overwritten.
 
         - stateful
         - chainable
     */
 
     /**** put
         an alias for `set`
     */
 
     /**** has
         returns whether a dictionary contains
         a given key.
     */
 
     /**** cut
         returns the value for a given key and
         removes the corresponding key, value pair
         from the dictionary.
 
         - `stateful`
     */
 
     /**** del
         deletes the key and value pair (item)
         in the dictionary
         that has a given key.
 
         - `stateful`
         - `chainable`
     */
 
     /**** getDefault
         an overridable function that returns
         a value or throws a KeyError if you
         attempt to `get` an item for a key
         that the dictionary does not contain.
 
         - `stateless`, but overrides may
            be stateful.
     */
 
     /**** hasValue
         returns whether the dictionary contains
         an item with the given value.
 
         - `stateless`
     */
 
     /**** hasKey
         an alias of `has`
 
         - `stateless`
     */
 
     /**** update
         Sets the given iterable of key value pairs on this
         dictionary, overriding any existing keys.
 
         - `stateful`
         - `chainable`
     */
 
     /**** updated
         Returns a new copy of this dictionary that has been
         updated with the pairs in a given iterable.
         
         - `stateless`
         - `chainable`
     */
 
     /**** complete
         Sets the given iterable of key value pairs on this
         dictionary, except for those with existing keys.
 
         - `stateful`
         - `chainable`
     */
 
     /**** completed
         Returns a new copy of this dictionary that has been
         completed with the pairs in a given iterable.
 
         - `stateless`
         - `chainable`
     */
 
     /**** find
         - `stateless`
     */
 
     /**** findReverse
         since dictionary keys are not ordered, `findReverse`
         is an alias of `find`.
 
         - `stateless`
     */
 
     /**** add
         - `stateful`
         - `chainable`
     */
 
     /**** added
         - `stateless`
         - `chainable`
     */
 
     /**** eq
         - `stateless`
     */
 
     /**** repr
         - `stateless`
     */
 
     /**** string
         - `stateless`
     */
 
     /**** hash
         - `stateless`
     */
 
     /**** invoke
         an alias of `get` that permits a dictionary
         to be used as a unary relation on its 
         domain of keys to its range of values.
     */
 
 /*** toDict
 */
 
 /*** toObject
     Creates a new native JavaScript `Object`
     from any instance.
 
     Defers to any user defined `toObject` method
     of the given object.  Failing that, defers
     to `dict` to convert the given object to
     a `Dict` and then creates an `Object` from
     that dictionary's key value pairs.
 */
 
 /*** hasKey
     - `polymorphic`
 */
 
 /*** hasValue
     - `polymorphic`
 */
 
 /*** update
     - `polymoprhic`
     - `stateful`
     - `chainable`
 */
 
 /*** updated
     - `polymorphic`
     - `stateless`
     - `chainable`
 */
 
 /*** complete
     - `polymoprhic`
     - `stateful`
     - `chainable`
 */
 
 /*** completed
     - `polymorphic`
     - `stateless`
     - `chainable`
 */
 
 /*** clear
     removes all key value pairs from list and dict-like objects
     including native Arrays, Objects, and types that override
     the `clear` function like `Dict` and `List`.
 
     - `polymorphic`
     - `stateful`
     - `chainable`
 */
 
 /*** keys
     - `polymorphic`
     - `stateless`
 */
 
 /*** keysIter
     - `polymorphic`
     - `stateless`
 */
 
 /*** values
     - `polymorphic`
     - `stateless`
 */
 
 /*** valuesIter
     - `polymorphic`
     - `stateless`
 */
 
 /*** items
     - `polymorphic`
     - `stateless`
 */
 
 /*** itemsIter
     - `polymorphic`
     - `stateless`
 */</text>
    </revision>
    <revision>
      <id>48</id>
      <timestamp>2009-02-18T22:02:34Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>s/itemsiter/itemsIter</comment>
      <text xml:space="preserve"> 
 /*** Dict
     an unordered collection of key to value mappings.
     Unlike `Object`, a `Dict` object's key domain includes any
     object, with better performance when the `hash` of each
     key does not collide.  That is, the `Number` ``1`` and the
     `String` ``&quot;1&quot;`` are distinct objects.
 
     `Dict` inherits from  `Iterable` and `Set`, overriding the `eq` and
     `hash` of the underlying `Set` to use versions that hash and compare
     equivalence based on the pair component of key value pairs.
 
     Different than Python ``dict``:
 
     - ``update``: `add`
     - ``has_key``: `hasKey`
     - ``iteritems``: `itemsIter`
     - ``iterkeys``: `keysIter`
     - ``itervalues``: `valuesIter`
     - ``fromkeys(S, v)``: ``Dict(each(S.keys(), function (k) {return [k, v]}))``
     - ``setdefault``: use `set` and `get`
     - ``__del__`` -&gt; `remove`
     - ``__contains__`` -&gt; `has`
 
     Same as Python:
 
     - `get`
     - `clear`
     - `copy`
     - `items`
     - `keys`
     - `values`
     - `pop`
 
 */
 
     /**** keysIter
         returns an `Iter` of keys from the 
         key and value pairs (items) in the dictionary.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** keys
         returns a `Set` of keys from the 
         key and value pairs (items) in the dictionary.
         Uses `keysIter` and `itemsIter`.
 
         - `stateless`
     */
 
     /**** valuesIter
         returns an `Iter` of values from the
         key and value pairs (items) in the dictinoary.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** values
         returns a `List` of values from the
         key and value pairs (items) in the dictionary.
         Uses `valuesIter` and `itemsIter`.
 
         - `stateless`
     */
 
     /**** itemsIter
         returns an iteration, `Iter`, of the key and
         value pairs (items) in the dictionary.
         Items are represented as native JavaScript
         `Array` objects.
         Uses `iter`, which is defined for the
         `Set` base-type.
 
         - `stateless`
     */
 
     /**** items
         returns a `List` of the key and value
         pairs (items) in the dictionary.
         Items are represnted as native JavaScript
         `Array` objects.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** get
         returns the value of an item in
         the dictionary that has a given
         key.  If there is item for the key,
         attempts to return a default value, 
         checking whether you've specified
         a default value to return as a second
         argument, or deferring to `getDefault`.
         If no acceptable default exists,
         throws a `KeyError`.
 
         accepts:
         - a key (any object)
         - an optional default value, which
            can be `undefined` or `null`
            if you wish to avoid throwing
            a `KeyError`.
 
         - `stateless`
     */
 
     /**** set 
         stores a key and corresponding value
         (an item) in the dictionary.  If
         an item already exists in the dictionary
         that has the same key, it is overwritten.
 
         - stateful
         - chainable
     */
 
     /**** put
         an alias for `set`
     */
 
     /**** has
         returns whether a dictionary contains
         a given key.
     */
 
     /**** cut
         returns the value for a given key and
         removes the corresponding key, value pair
         from the dictionary.
 
         - `stateful`
     */
 
     /**** del
         deletes the key and value pair (item)
         in the dictionary
         that has a given key.
 
         - `stateful`
         - `chainable`
     */
 
     /**** getDefault
         an overridable function that returns
         a value or throws a KeyError if you
         attempt to `get` an item for a key
         that the dictionary does not contain.
 
         - `stateless`, but overrides may
            be stateful.
     */
 
     /**** hasValue
         returns whether the dictionary contains
         an item with the given value.
 
         - `stateless`
     */
 
     /**** hasKey
         an alias of `has`
 
         - `stateless`
     */
 
     /**** update
         Sets the given iterable of key value pairs on this
         dictionary, overriding any existing keys.
 
         - `stateful`
         - `chainable`
     */
 
     /**** updated
         Returns a new copy of this dictionary that has been
         updated with the pairs in a given iterable.
         
         - `stateless`
         - `chainable`
     */
 
     /**** complete
         Sets the given iterable of key value pairs on this
         dictionary, except for those with existing keys.
 
         - `stateful`
         - `chainable`
     */
 
     /**** completed
         Returns a new copy of this dictionary that has been
         completed with the pairs in a given iterable.
 
         - `stateless`
         - `chainable`
     */
 
     /**** find
         - `stateless`
     */
 
     /**** findReverse
         since dictionary keys are not ordered, `findReverse`
         is an alias of `find`.
 
         - `stateless`
     */
 
     /**** add
         - `stateful`
         - `chainable`
     */
 
     /**** added
         - `stateless`
         - `chainable`
     */
 
     /**** eq
         - `stateless`
     */
 
     /**** repr
         - `stateless`
     */
 
     /**** string
         - `stateless`
     */
 
     /**** hash
         - `stateless`
     */
 
     /**** invoke
         an alias of `get` that permits a dictionary
         to be used as a unary relation on its 
         domain of keys to its range of values.
     */
 
 /*** toDict
 */
 
 /*** toObject
     Creates a new native JavaScript `Object`
     from any instance.
 
     Defers to any user defined `toObject` method
     of the given object.  Failing that, defers
     to `dict` to convert the given object to
     a `Dict` and then creates an `Object` from
     that dictionary's key value pairs.
 */
 
 /*** hasKey
     - `polymorphic`
 */
 
 /*** hasValue
     - `polymorphic`
 */
 
 /*** update
     - `polymoprhic`
     - `stateful`
     - `chainable`
 */
 
 /*** updated
     - `polymorphic`
     - `stateless`
     - `chainable`
 */
 
 /*** complete
     - `polymoprhic`
     - `stateful`
     - `chainable`
 */
 
 /*** completed
     - `polymorphic`
     - `stateless`
     - `chainable`
 */
 
 /*** clear
     removes all key value pairs from list and dict-like objects
     including native Arrays, Objects, and types that override
     the `clear` function like `Dict` and `List`.
 
     - `polymorphic`
     - `stateful`
     - `chainable`
 */
 
 /*** keys
     - `polymorphic`
     - `stateless`
 */
 
 /*** keysIter
     - `polymorphic`
     - `stateless`
 */
 
 /*** values
     - `polymorphic`
     - `stateless`
 */
 
 /*** valuesIter
     - `polymorphic`
     - `stateless`
 */
 
 /*** items
     - `polymorphic`
     - `stateless`
 */
 
 /*** itemsIter
     - `polymorphic`
     - `stateless`
 */</text>
    </revision>
    <revision>
      <id>49</id>
      <timestamp>2009-09-09T22:13:50Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>2 revisions:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve"> 
 /*** Dict
     an unordered collection of key to value mappings.
     Unlike `Object`, a `Dict` object's key domain includes any
     object, with better performance when the `hash` of each
     key does not collide.  That is, the `Number` ``1`` and the
     `String` ``&quot;1&quot;`` are distinct objects.
 
     `Dict` inherits from  `Iterable` and `Set`, overriding the `eq` and
     `hash` of the underlying `Set` to use versions that hash and compare
     equivalence based on the pair component of key value pairs.
 
     Different than Python ``dict``:
 
     - ``update``: `add`
     - ``has_key``: `hasKey`
     - ``iteritems``: `itemsIter`
     - ``iterkeys``: `keysIter`
     - ``itervalues``: `valuesIter`
     - ``fromkeys(S, v)``: ``Dict(each(S.keys(), function (k) {return [k, v]}))``
     - ``setdefault``: use `set` and `get`
     - ``__del__`` -&gt; `remove`
     - ``__contains__`` -&gt; `has`
 
     Same as Python:
 
     - `get`
     - `clear`
     - `copy`
     - `items`
     - `keys`
     - `values`
     - `pop`
 
 */
 
     /**** keysIter
         returns an `Iter` of keys from the 
         key and value pairs (items) in the dictionary.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** keys
         returns a `Set` of keys from the 
         key and value pairs (items) in the dictionary.
         Uses `keysIter` and `itemsIter`.
 
         - `stateless`
     */
 
     /**** valuesIter
         returns an `Iter` of values from the
         key and value pairs (items) in the dictinoary.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** values
         returns a `List` of values from the
         key and value pairs (items) in the dictionary.
         Uses `valuesIter` and `itemsIter`.
 
         - `stateless`
     */
 
     /**** itemsIter
         returns an iteration, `Iter`, of the key and
         value pairs (items) in the dictionary.
         Items are represented as native JavaScript
         `Array` objects.
         Uses `iter`, which is defined for the
         `Set` base-type.
 
         - `stateless`
     */
 
     /**** items
         returns a `List` of the key and value
         pairs (items) in the dictionary.
         Items are represnted as native JavaScript
         `Array` objects.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** get
         returns the value of an item in
         the dictionary that has a given
         key.  If there is item for the key,
         attempts to return a default value, 
         checking whether you've specified
         a default value to return as a second
         argument, or deferring to `getDefault`.
         If no acceptable default exists,
         throws a `KeyError`.
 
         accepts:
         - a key (any object)
         - an optional default value, which
            can be `undefined` or `null`
            if you wish to avoid throwing
            a `KeyError`.
 
         - `stateless`
     */
 
     /**** set 
         stores a key and corresponding value
         (an item) in the dictionary.  If
         an item already exists in the dictionary
         that has the same key, it is overwritten.
 
         - stateful
         - chainable
     */
 
     /**** put
         an alias for `set`
     */
 
     /**** has
         returns whether a dictionary contains
         a given key.
     */
 
     /**** cut
         returns the value for a given key and
         removes the corresponding key, value pair
         from the dictionary.
 
         - `stateful`
     */
 
     /**** del
         deletes the key and value pair (item)
         in the dictionary
         that has a given key.
 
         - `stateful`
         - `chainable`
     */
 
     /**** getDefault
         an overridable function that returns
         a value or throws a KeyError if you
         attempt to `get` an item for a key
         that the dictionary does not contain.
 
         - `stateless`, but overrides may
            be stateful.
     */
 
     /**** hasValue
         returns whether the dictionary contains
         an item with the given value.
 
         - `stateless`
     */
 
     /**** hasKey
         an alias of `has`
 
         - `stateless`
     */
 
     /**** update
         Sets the given iterable of key value pairs on this
         dictionary, overriding any existing keys.
 
         - `stateful`
         - `chainable`
     */
 
     /**** updated
         Returns a new copy of this dictionary that has been
         updated with the pairs in a given iterable.
         
         - `stateless`
         - `chainable`
     */
 
     /**** complete
         Sets the given iterable of key value pairs on this
         dictionary, except for those with existing keys.
 
         - `stateful`
         - `chainable`
     */
 
     /**** completed
         Returns a new copy of this dictionary that has been
         completed with the pairs in a given iterable.
 
         - `stateless`
         - `chainable`
     */
 
     /**** find
         - `stateless`
     */
 
     /**** findReverse
         since dictionary keys are not ordered, `findReverse`
         is an alias of `find`.
 
         - `stateless`
     */
 
     /**** add
         - `stateful`
         - `chainable`
     */
 
     /**** added
         - `stateless`
         - `chainable`
     */
 
     /**** eq
         - `stateless`
     */
 
     /**** repr
         - `stateless`
     */
 
     /**** string
         - `stateless`
     */
 
     /**** hash
         - `stateless`
     */
 
     /**** invoke
         an alias of `get` that permits a dictionary
         to be used as a unary relation on its 
         domain of keys to its range of values.
     */
 
 /*** toDict
 */
 
 /*** toObject
     Creates a new native JavaScript `Object`
     from any instance.
 
     Defers to any user defined `toObject` method
     of the given object.  Failing that, defers
     to `dict` to convert the given object to
     a `Dict` and then creates an `Object` from
     that dictionary's key value pairs.
 */
 
 /*** hasKey
     - `polymorphic`
 */
 
 /*** hasValue
     - `polymorphic`
 */
 
 /*** update
     - `polymoprhic`
     - `stateful`
     - `chainable`
 */
 
 /*** updated
     - `polymorphic`
     - `stateless`
     - `chainable`
 */
 
 /*** complete
     - `polymoprhic`
     - `stateful`
     - `chainable`
 */
 
 /*** completed
     - `polymorphic`
     - `stateless`
     - `chainable`
 */
 
 /*** clear
     removes all key value pairs from list and dict-like objects
     including native Arrays, Objects, and types that override
     the `clear` function like `Dict` and `List`.
 
     - `polymorphic`
     - `stateful`
     - `chainable`
 */
 
 /*** keys
     - `polymorphic`
     - `stateless`
 */
 
 /*** keysIter
     - `polymorphic`
     - `stateless`
 */
 
 /*** values
     - `polymorphic`
     - `stateless`
 */
 
 /*** valuesIter
     - `polymorphic`
     - `stateless`
 */
 
 /*** items
     - `polymorphic`
     - `stateless`
 */
 
 /*** itemsIter
     - `polymorphic`
     - `stateless`
 */</text>
    </revision>
    <revision>
      <id>627</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/dict/ProposalK]] to [[CommonJS/API/dict/ProposalK]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve"> 
 /*** Dict
     an unordered collection of key to value mappings.
     Unlike `Object`, a `Dict` object's key domain includes any
     object, with better performance when the `hash` of each
     key does not collide.  That is, the `Number` ``1`` and the
     `String` ``&quot;1&quot;`` are distinct objects.
 
     `Dict` inherits from  `Iterable` and `Set`, overriding the `eq` and
     `hash` of the underlying `Set` to use versions that hash and compare
     equivalence based on the pair component of key value pairs.
 
     Different than Python ``dict``:
 
     - ``update``: `add`
     - ``has_key``: `hasKey`
     - ``iteritems``: `itemsIter`
     - ``iterkeys``: `keysIter`
     - ``itervalues``: `valuesIter`
     - ``fromkeys(S, v)``: ``Dict(each(S.keys(), function (k) {return [k, v]}))``
     - ``setdefault``: use `set` and `get`
     - ``__del__`` -&gt; `remove`
     - ``__contains__`` -&gt; `has`
 
     Same as Python:
 
     - `get`
     - `clear`
     - `copy`
     - `items`
     - `keys`
     - `values`
     - `pop`
 
 */
 
     /**** keysIter
         returns an `Iter` of keys from the 
         key and value pairs (items) in the dictionary.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** keys
         returns a `Set` of keys from the 
         key and value pairs (items) in the dictionary.
         Uses `keysIter` and `itemsIter`.
 
         - `stateless`
     */
 
     /**** valuesIter
         returns an `Iter` of values from the
         key and value pairs (items) in the dictinoary.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** values
         returns a `List` of values from the
         key and value pairs (items) in the dictionary.
         Uses `valuesIter` and `itemsIter`.
 
         - `stateless`
     */
 
     /**** itemsIter
         returns an iteration, `Iter`, of the key and
         value pairs (items) in the dictionary.
         Items are represented as native JavaScript
         `Array` objects.
         Uses `iter`, which is defined for the
         `Set` base-type.
 
         - `stateless`
     */
 
     /**** items
         returns a `List` of the key and value
         pairs (items) in the dictionary.
         Items are represnted as native JavaScript
         `Array` objects.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** get
         returns the value of an item in
         the dictionary that has a given
         key.  If there is item for the key,
         attempts to return a default value, 
         checking whether you've specified
         a default value to return as a second
         argument, or deferring to `getDefault`.
         If no acceptable default exists,
         throws a `KeyError`.
 
         accepts:
         - a key (any object)
         - an optional default value, which
            can be `undefined` or `null`
            if you wish to avoid throwing
            a `KeyError`.
 
         - `stateless`
     */
 
     /**** set 
         stores a key and corresponding value
         (an item) in the dictionary.  If
         an item already exists in the dictionary
         that has the same key, it is overwritten.
 
         - stateful
         - chainable
     */
 
     /**** put
         an alias for `set`
     */
 
     /**** has
         returns whether a dictionary contains
         a given key.
     */
 
     /**** cut
         returns the value for a given key and
         removes the corresponding key, value pair
         from the dictionary.
 
         - `stateful`
     */
 
     /**** del
         deletes the key and value pair (item)
         in the dictionary
         that has a given key.
 
         - `stateful`
         - `chainable`
     */
 
     /**** getDefault
         an overridable function that returns
         a value or throws a KeyError if you
         attempt to `get` an item for a key
         that the dictionary does not contain.
 
         - `stateless`, but overrides may
            be stateful.
     */
 
     /**** hasValue
         returns whether the dictionary contains
         an item with the given value.
 
         - `stateless`
     */
 
     /**** hasKey
         an alias of `has`
 
         - `stateless`
     */
 
     /**** update
         Sets the given iterable of key value pairs on this
         dictionary, overriding any existing keys.
 
         - `stateful`
         - `chainable`
     */
 
     /**** updated
         Returns a new copy of this dictionary that has been
         updated with the pairs in a given iterable.
         
         - `stateless`
         - `chainable`
     */
 
     /**** complete
         Sets the given iterable of key value pairs on this
         dictionary, except for those with existing keys.
 
         - `stateful`
         - `chainable`
     */
 
     /**** completed
         Returns a new copy of this dictionary that has been
         completed with the pairs in a given iterable.
 
         - `stateless`
         - `chainable`
     */
 
     /**** find
         - `stateless`
     */
 
     /**** findReverse
         since dictionary keys are not ordered, `findReverse`
         is an alias of `find`.
 
         - `stateless`
     */
 
     /**** add
         - `stateful`
         - `chainable`
     */
 
     /**** added
         - `stateless`
         - `chainable`
     */
 
     /**** eq
         - `stateless`
     */
 
     /**** repr
         - `stateless`
     */
 
     /**** string
         - `stateless`
     */
 
     /**** hash
         - `stateless`
     */
 
     /**** invoke
         an alias of `get` that permits a dictionary
         to be used as a unary relation on its 
         domain of keys to its range of values.
     */
 
 /*** toDict
 */
 
 /*** toObject
     Creates a new native JavaScript `Object`
     from any instance.
 
     Defers to any user defined `toObject` method
     of the given object.  Failing that, defers
     to `dict` to convert the given object to
     a `Dict` and then creates an `Object` from
     that dictionary's key value pairs.
 */
 
 /*** hasKey
     - `polymorphic`
 */
 
 /*** hasValue
     - `polymorphic`
 */
 
 /*** update
     - `polymoprhic`
     - `stateful`
     - `chainable`
 */
 
 /*** updated
     - `polymorphic`
     - `stateless`
     - `chainable`
 */
 
 /*** complete
     - `polymoprhic`
     - `stateful`
     - `chainable`
 */
 
 /*** completed
     - `polymorphic`
     - `stateless`
     - `chainable`
 */
 
 /*** clear
     removes all key value pairs from list and dict-like objects
     including native Arrays, Objects, and types that override
     the `clear` function like `Dict` and `List`.
 
     - `polymorphic`
     - `stateful`
     - `chainable`
 */
 
 /*** keys
     - `polymorphic`
     - `stateless`
 */
 
 /*** keysIter
     - `polymorphic`
     - `stateless`
 */
 
 /*** values
     - `polymorphic`
     - `stateless`
 */
 
 /*** valuesIter
     - `polymorphic`
     - `stateless`
 */
 
 /*** items
     - `polymorphic`
     - `stateless`
 */
 
 /*** itemsIter
     - `polymorphic`
     - `stateless`
 */</text>
    </revision>
    <revision>
      <id>977</id>
      <timestamp>2009-09-10T03:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/dict/ProposalK]] to [[OldAPI/dict/ProposalK]]</comment>
      <text xml:space="preserve"> 
 /*** Dict
     an unordered collection of key to value mappings.
     Unlike `Object`, a `Dict` object's key domain includes any
     object, with better performance when the `hash` of each
     key does not collide.  That is, the `Number` ``1`` and the
     `String` ``&quot;1&quot;`` are distinct objects.
 
     `Dict` inherits from  `Iterable` and `Set`, overriding the `eq` and
     `hash` of the underlying `Set` to use versions that hash and compare
     equivalence based on the pair component of key value pairs.
 
     Different than Python ``dict``:
 
     - ``update``: `add`
     - ``has_key``: `hasKey`
     - ``iteritems``: `itemsIter`
     - ``iterkeys``: `keysIter`
     - ``itervalues``: `valuesIter`
     - ``fromkeys(S, v)``: ``Dict(each(S.keys(), function (k) {return [k, v]}))``
     - ``setdefault``: use `set` and `get`
     - ``__del__`` -&gt; `remove`
     - ``__contains__`` -&gt; `has`
 
     Same as Python:
 
     - `get`
     - `clear`
     - `copy`
     - `items`
     - `keys`
     - `values`
     - `pop`
 
 */
 
     /**** keysIter
         returns an `Iter` of keys from the 
         key and value pairs (items) in the dictionary.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** keys
         returns a `Set` of keys from the 
         key and value pairs (items) in the dictionary.
         Uses `keysIter` and `itemsIter`.
 
         - `stateless`
     */
 
     /**** valuesIter
         returns an `Iter` of values from the
         key and value pairs (items) in the dictinoary.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** values
         returns a `List` of values from the
         key and value pairs (items) in the dictionary.
         Uses `valuesIter` and `itemsIter`.
 
         - `stateless`
     */
 
     /**** itemsIter
         returns an iteration, `Iter`, of the key and
         value pairs (items) in the dictionary.
         Items are represented as native JavaScript
         `Array` objects.
         Uses `iter`, which is defined for the
         `Set` base-type.
 
         - `stateless`
     */
 
     /**** items
         returns a `List` of the key and value
         pairs (items) in the dictionary.
         Items are represnted as native JavaScript
         `Array` objects.
         Uses `itemsIter`.
 
         - `stateless`
     */
 
     /**** get
         returns the value of an item in
         the dictionary that has a given
         key.  If there is item for the key,
         attempts to return a default value, 
         checking whether you've specified
         a default value to return as a second
         argument, or deferring to `getDefault`.
         If no acceptable default exists,
         throws a `KeyError`.
 
         accepts:
         - a key (any object)
         - an optional default value, which
            can be `undefined` or `null`
            if you wish to avoid throwing
            a `KeyError`.
 
         - `stateless`
     */
 
     /**** set 
         stores a key and corresponding value
         (an item) in the dictionary.  If
         an item already exists in the dictionary
         that has the same key, it is overwritten.
 
         - stateful
         - chainable
     */
 
     /**** put
         an alias for `set`
     */
 
     /**** has
         returns whether a dictionary contains
         a given key.
     */
 
     /**** cut
         returns the value for a given key and
         removes the corresponding key, value pair
         from the dictionary.
 
         - `stateful`
     */
 
     /**** del
         deletes the key and value pair (item)
         in the dictionary
         that has a given key.
 
         - `stateful`
         - `chainable`
     */
 
     /**** getDefault
         an overridable function that returns
         a value or throws a KeyError if you
         attempt to `get` an item for a key
         that the dictionary does not contain.
 
         - `stateless`, but overrides may
            be stateful.
     */
 
     /**** hasValue
         returns whether the dictionary contains
         an item with the given value.
 
         - `stateless`
     */
 
     /**** hasKey
         an alias of `has`
 
         - `stateless`
     */
 
     /**** update
         Sets the given iterable of key value pairs on this
         dictionary, overriding any existing keys.
 
         - `stateful`
         - `chainable`
     */
 
     /**** updated
         Returns a new copy of this dictionary that has been
         updated with the pairs in a given iterable.
         
         - `stateless`
         - `chainable`
     */
 
     /**** complete
         Sets the given iterable of key value pairs on this
         dictionary, except for those with existing keys.
 
         - `stateful`
         - `chainable`
     */
 
     /**** completed
         Returns a new copy of this dictionary that has been
         completed with the pairs in a given iterable.
 
         - `stateless`
         - `chainable`
     */
 
     /**** find
         - `stateless`
     */
 
     /**** findReverse
         since dictionary keys are not ordered, `findReverse`
         is an alias of `find`.
 
         - `stateless`
     */
 
     /**** add
         - `stateful`
         - `chainable`
     */
 
     /**** added
         - `stateless`
         - `chainable`
     */
 
     /**** eq
         - `stateless`
     */
 
     /**** repr
         - `stateless`
     */
 
     /**** string
         - `stateless`
     */
 
     /**** hash
         - `stateless`
     */
 
     /**** invoke
         an alias of `get` that permits a dictionary
         to be used as a unary relation on its 
         domain of keys to its range of values.
     */
 
 /*** toDict
 */
 
 /*** toObject
     Creates a new native JavaScript `Object`
     from any instance.
 
     Defers to any user defined `toObject` method
     of the given object.  Failing that, defers
     to `dict` to convert the given object to
     a `Dict` and then creates an `Object` from
     that dictionary's key value pairs.
 */
 
 /*** hasKey
     - `polymorphic`
 */
 
 /*** hasValue
     - `polymorphic`
 */
 
 /*** update
     - `polymoprhic`
     - `stateful`
     - `chainable`
 */
 
 /*** updated
     - `polymorphic`
     - `stateless`
     - `chainable`
 */
 
 /*** complete
     - `polymoprhic`
     - `stateful`
     - `chainable`
 */
 
 /*** completed
     - `polymorphic`
     - `stateless`
     - `chainable`
 */
 
 /*** clear
     removes all key value pairs from list and dict-like objects
     including native Arrays, Objects, and types that override
     the `clear` function like `Dict` and `List`.
 
     - `polymorphic`
     - `stateful`
     - `chainable`
 */
 
 /*** keys
     - `polymorphic`
     - `stateless`
 */
 
 /*** keysIter
     - `polymorphic`
     - `stateless`
 */
 
 /*** values
     - `polymorphic`
     - `stateless`
 */
 
 /*** valuesIter
     - `polymorphic`
     - `stateless`
 */
 
 /*** items
     - `polymorphic`
     - `stateless`
 */
 
 /*** itemsIter
     - `polymorphic`
     - `stateless`
 */</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/file</title>
    <id>9</id>
    <revision>
      <id>50</id>
      <timestamp>2009-03-13T07:02:34Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Posted current notes for the file module API</comment>
      <text xml:space="preserve"> 
 Alright.  The task of the month is to ratify a File API.
 There's been relatively little discussion on this topic.
 There's not much opportunity to advance the state of the
 art with yet another file API, which means that this will
 inevitably degenerate into shed painting, but it must be
 done!  Let's just slog through this shall we?
 
 I've composed all of the functions from Ruby, Python, 
 and Java into a very long list here.  Please note which
 names you prefer, whether you feel a particular function
 ought to not be part of the standard API, any functions
 that are missing, and of course
 comment and discuss semantics.  I will attempt
 to reserve my opinions for a follow up post.
 
 Let's begin with some high level preferences.  There
 are a few naming choices that can be applied throughout
 the following document with rigor.  Rather than note
 every occurrence of the offending word, please state your
 general preference:
 
 
 1. make vs create
 
     make: Wes Garland (for dirs)
     create: George Mosochovitis, Wes Garland (for file mode)
 
 2. dir vs directory
 
     dir:
     directory: Tom Robinson, Kevin Dangoor, George Mosochovitis, Wes Garland
 
 3. cur vs current
 
     cur:
     current: Tom Robinson, Kevin Dangoor, Wes Garland, Kris Kowal
 
 4. canonize, realize, normalize, qualify,
    canon, real, normal, qualified, absolute,
    canonicalize
 
     remove . and ..:
         normalize: Tom Robinson, Kevin Dangoor, Kris Kowal, George Mosochovitis
         qualify: Wes Garland
     remove . and .., start at /:
         absolute: Tom Robinson, Kevin Dangoor, Kris Kowal
     remove . and .., start at /, follow symlinks:
         canonical: Tom Robinson, Kevin Dangoor, Kris Kowal
         real: Tom Robinson, Kevin Dangoor
 
     Could apply for either of the two latter:
         absolute: George Moscochovitis, Wes Garland
         qualified: Wes Garland
 
 5. constantCase vs CONSTANT_CASE vs kConstantCase
 
     There's a lot of legacy Netscape code with
     the pseudo Hungarian kConstantCase.
 
     CONSTANT_CASE: Tom Robinson, Kevin Dangoor
     constantCase: Kris Kowal, Wes Garland
 
 
 6. Should &quot;static&quot; File methods be placed in
 
    require('file').File or : Tom Robinson, George Mosochovitis
    require('file') : Kris Kowal, Wes Garland
 
    e.g.,
 
    var files = require('file');
    files.move(a, b)
 
    vs.
 
    var File = require('file').File;
    File.move(a, b);
 
     Tom Robinson: should we use encoding here?
     Wes Garland: &quot;b&quot; should be stricken
     Wes Garland: encoding should actually be an encode function
     Kris Kowal: encoding should be the name of an encoding module
 
 7. Choose:
 
    a.) setX/getX  vs
        a.) For all functions for which it would make sense to have a setter and a getter.
             (It would not make sense to have a setSize, so size() would be permissible)
        b.) For all functions that get things
             (getSize, getMtime, setMtime, getBaseName)
 
    b.) setX/X
 
         Kris Kowal
 
    c.) pick and choose; no overarching convention
 
    d.) X property with getters and setters
 
         for:
             Davey Waterson
             Wes Garland
             Daniel Friesen
         against:
             Tom Robinson
             Kris Kowal
 
 exists(path) - Wes Garland
     Python: exists (uses stat(path) and checks for exception)
     Ruby: exist? exists?
 linkExists(path)
     Python: lexists
         Returns whether a file exists, even if it
         ultimately refers to a broken symbolic link.
     Java: not provided
 
     Wes Garland: exists(path, true)
     Kris Kowal: linkExists(path)
 
 move(source, target)
     Ruby: move
 rename(source, target)
     Ruby: rename
 copy(source, target)
     Ruby: copy
 
 systemCopy(source, target):
     Ruby: syscopy
     Copies a file from to to. If to is a directory, copies from to to/from.
 
     unnecessary - Wes Garland
 
 makeDirectory(path)
     Unix: mkdir
     createDirectory
 makePath(path)
     Ruby: makedirs
     Unix: mkdir -p
     mkpath, mkdirs, createPath, createDirectories
 
     Wes Garland: makeDirectory(path, true)
     Kris Kowal: makePath(path)
 
 makeTempFile(prefix, suffix)
     Java: createTempFile
     Python: mktemp
     mktemp(prefix, suffix), makeTemporary, makeTemp
 
     Wes Garland: this should be ommitted in favor of an alternate File constructor
 
 remove(path)
     Ruby: unlink, delete
     Python: unlink, remove
     Java: delete
     Posix: unlink
     Unix: rm (remove)
 
     Tom Robinson, Kevin Dangoor: remove, definitely not delete
     Wes Garland: unlink, but remove and delete are fine
 
 
 symlink(source, target)
     Ruby: symlink(old, new)
 link(source, target)
     Creates a hard link
     Ruby: File.link(old_name, new_name) =&gt; 0
         Creates a new name for an existing file using a hard link.
         Will not overwrite new_name if it already exists
         (raising a subclass of SystemCallError).
         Not available on all platforms.
 
     Wes Garland: link(source, target, hard:Boolean)
     Kris Kowal: symlink, link
 
 truncate(file_name, length)
 create(path)
     Java: create
     Posix: creat
 lock(path, &quot;shared|exculsive&quot;) - Wes Garland
     writeLock(path), readLock(path)
 tryLock(path, &quot;shared|exclusive&quot;) - Wes Garland
 unlock(path) - Wes Garland
     opens a lock
 
 dup(fileno) - unnecessary Wes Garland
 dup2(fileno, fileno) - unnecessary Wes Garland
     
 
 
 Weights and Measures
 ====================
 
 [new] Stat(path)
     returns a Stat object (more later)
 stat(path)
     returns an Array
     Posix: stat
     Java: omitted
 updateStat(:Stat) - Wes Garland
 setStat(:Stat)
 linkStat(path):
     Python: lstat
 
     Wes Garland: stat(path, true)
     Kris Kowal: linkStat(path)
 
 atime(path) - Tom Robinson, Kevin Dangoor
     Java: omitted
     Python: getatime
     Ruby: atime
     lastAccessed
 mtime(path) - Tom Robinson, Kevin Dangoor
     Java: lastModified
     Python: getmtime
     Ruby: mtime
     stat(path).st_mtime
     lastModified
 touch(path) - Kris Kowal
     setLastModified(path, date)
     setMtime(path, date)
 ctime(path) - Tom Robinson, Kevin Dangoor
     Unix: touch
     Java: omitted
     Python: getctime
     Ruby: ctime
     lastNodeModified
 size(path) - Tom Robinson, Kevin Dangoor
     Ruby: size?
     Java: length
     Python: getsize
     Posix: size: stat(path).st_size
     getLength, length, getSize, size
 
 
 
 Ownership
 =========
 
 getOwner(path)
 getGroupOwner(path)
 setOwner(path, user, [group])
     chown
 setGroupOwner(path, group)
     chown
 setLinkOwner(path, owner, [group])
     Ruby: file.lchown(owner_int, group_int, file_name,..) =&gt; integer
         Equivalent to File::chown, but does not follow symbolic links
         (so it will change the owner associated with the link,
         not the file referenced by the link).
         Often not available. Returns number of files in the argument list.
 
     Wes Garland: use SetOwner(path, owner, group, true)
 
 setLinkGroupOwner(path, group)
 isOwned()
     Ruby: owned?
         Returns true if the named file exists and the effective
         used id of the calling process is the owner of the file.
 isGroupOwned()
     Ruby: grpowned?
         Returns true if the named file exists and the effective
         group id of the calling process is the owner of the file.
         Returns false on Windows.
 
 
 Please Sir, Can I Have Some More
 ================================
 
 isReadable(path)
     Java: canRead
     Ruby: readable
 isReallyReadable(path)
     Ruby: readable_real?
     returns whether the file is readable by the current
     process owner.
 isWritable(path)
     Java: canWrite
     Ruby: writable
 isReallyWritable(path)
     Ruby: writable_real?
 isExecutable(path)
     Ruby: executable?
     Python: omitted
 isReallyExecutable(path)
     Ruby: executable_real? 
 isSticky(path)
     returns whether the sticky bit is set, which is to say
     that anyone can create a file in the directory
     but cannot delete those created by other users.
 executesAsOwner(path)
     returns whether the file has the SID bit set.
 executesAsGroupOwner(path)
     returns whether the file has the GID bit set.
 
 setMode(path, mode)
     Posix: chmod
     Unix: chmod
     Ruby: chmod
 getMode(path)
 setLinkMode(path, mode)
     Ruby: File.lchmod(mode_int, file_name, ...) =&gt; integer
         Equivalent to File::chmod, but does not follow
         symbolic links (so it will change the permissions
         associated with the link, not the file
         referenced by the link).  Often not available.
 setReadOnly(true|false)
 
 getModeMask()
     Ruby: umask()
 setModeMask(umask)
     Ruby: umask(umask)
 
 
 What is My Name
 ===============
 
 dirName(path)
     Python: dirname
         Returns the directory that contains the given path
     Ruby: File.dirname(file_name)
 
     Wes Garland: dirname
     Kris Kowal: dirName
 
 baseName(path)
     Java: File(fileName).getName()
     Python: basename(file_name)
     Ruby: basename(file_name, [suffix])
     Unix: basename name [suffix]
 
     Wes Garland: basename
     Kris Kowal: baseName
 
 extension(path)
     Ruby: extname
     extensionName
 
     extension: George Mosochovitis, Wes Garland, Kris Kowal
 
 split
     Ruby: split
     Python: split
         Split a path in head (everything up to the last '/') and tail (the
         rest).  If the path ends in '/', tail will be empty.  If there is no
         '/' in the path, head  will be empty.
         Trailing '/'es are stripped from head unless it is the root.
 pathComponents(path)
     Wes Garland
 splitExtension
     Python: splitext
         Split a path in root and extension.
         The extension is everything starting at the last dot in the last
         pathname component; the root is everything before that.
         It is always true that root + ext == p.
 splitDrive
     Python: splitDrive
         Split a pathname into a drive specification and the rest of the
         path.  Useful on DOS/Windows/NT; on Unix, the drive is always empty.
 
 
 Where Did I Come From
 =====================
 
 getType(fileName)
     Ruby: ftype(file_name)
         Identifies the type of the named file; the return
         string is one of ``file‚Äô‚Äô, ``directory‚Äô‚Äô, ``characterSpecial‚Äô‚Äô,
         ``blockSpecial‚Äô‚Äô, ``fifo‚Äô‚Äô, ``link‚Äô‚Äô, ``socket‚Äô‚Äô, or ``unknown‚Äô‚Äô.
 
     Wes Garland: type or osType
 
 isFile
     Python: isfile
     Java: isFile
     Ruby: file?
 isDirectory
     Java: isDirectory
     Python: isdir
     Ruby: directory?
 isLink
     Java: omitted
     Python: islink
     Ruby: symlink?
     isSymlink would be more accurate since it doesn't
     test hard links, but everything's a hard link so it's
     not like the name &quot;isLink&quot; will ever be needed for
     that purpose.
 isMount
     Python: ismount with some question of inter-unix compatibility
     undesirable - Wes Garland
 isSocket
     Ruby: socket?
 isPipe
     Ruby: pipe?
 isBlockDevice
     Ruby: blockdev?(file_name)
 
 
 Where Am I
 ==========
 
 cwd
     Python: os.getcwd
     Unix: pwd
     getCwd, workingDir, presentWorkingDir, currentWorkingDir
 
 Projection
 ----------
 
 join(base, path)
     Python: join(base, rel)
     Java: File(parent, child)
 resolve(path, [base=cwd])
     the path to a given path from another
     Python: resolve(rel, abs = '.') -&gt; join(abs, rel)
     Python: abspath(path) -&gt; normpath(join(cwd(), path))
     unnecessary - Wes Garland
 relative(source, target)
     the relative path from source to target
 parent(path)
     Java: getParent
     Wes Garland: needs to be clear whether it's the lexical parent on the path
     or the parent link in the file system
 concatName(base, rel)
     Ruby: catname(from, to)
         If to is a valid directory, from will be appended to to,
         adding and escaping backslashes as necessary. Otherwise, to will
         be returned. Useful for appending from to to only if the filename
         was not specified in to.
     unnecessary - Wes Garland
 
 Identification
 --------------
 
 absolute(path)
     follows symlinks from the root and produces
     a canonical, normal form of a path
     Python: realpath
     Unix: realpath
     realize, realPath, canon, canonize, canonical, getCanonical, normalize
 isAbsolute(path)
     Java: isAbsolute
     Python: isabs
 normalize(path)
     Python: normpath
         Normalize a path, e.g. A//B, A/./B and A/foo/../B all become A/B.
         It should be understood that this may change the meaning of the path
         if it contains symbolic links!
     Jack: canonicalize
     canon, canonize, canonical, normal, getCanonical, getNormal
 normalizeCase(path)
     Python: normcase
         Normalize the case of a pathname.  Trivial in Posix, string.lower on Mac.
         On MS-DOS this may also turn slashes into backslashes; however, other
         normalizations (such as optimizing '../' away) are not allowed
         (another function should be defined to do that).
     unnecessary - Wes Garland
 samePath(a, b)
     Python: samefile
     Ruby: identical?
 sameFile(a, b)
     Python: sameopenfile
 sameStat(a, b)
     Python: sameStat
     Returns whether the inode and dev are the same
 
 
 Platform Constants
 ------------------
 
 selfDirectory ('.')
     Python: curdir
 parentDirectory ('..')
     Python: pardir
     parDir
 extensionSeparator
     Java: separator
     Python: extsep
     extsep, extSep, extensionSeparator, EXTENSION_SEPARATOR
 separator
     Java: pathSeparator
     Python: sep
     sep, separator, SEPARATOR
 alternateSeparator
     Python: altsep
     altsep alternateSeparator ALTERNATE_SEPARATOR
 deviceNull
     Python: devnull
     devNull
     DEV_NULL:
     unnecessary - Wes Garland
 path
     Python: defpath = ':/bin:/usr/bin'
     PATH
     unnecessary - Wes Garland
 supportsUnicodeFileName
     Python: supports_unicode_filenames
 
 
 What is a &quot;Phone Book&quot;
 ======================
 
 match(pattern, fileName)
     Ruby: fnmatch(pattern, file_name, [flags])
 glob(pattern) - Wes Garland, Kris Kowal
     Ruby: Dir[pattern]
 list(path)
     Python: os.listdir
     Ruby: Dir[path_glob]
     listdir, Dir
     listFiles, listDirs
 listIter
     next
     prev
 listRoots
     List the available filesystem roots.
 
 expand
     Python: expandUser -&gt; expandVars -&gt; normalize -&gt; real
     Ruby: expand_path
 expandUser
     Python: expanduser
     expands '~user'
 expandVars
     Python: expandvars
     expands shell variables like $var and ${var}
     unnecessary - Wes Garland
 
 
 Is That Really Necessary
 ========================
 
 isHidden
     Java: isHidden
     no - Wes Garland
 isZero(fileName)
     Ruby: zero?
     Perl: -z
     returns whether the file exists and is of zero length
     no - Wes Garland
 compare(source, target)
     Ruby: compare
     no - Wes Garland
 install(from, to, [mode], [verbose = false])
     Ruby: install
         If src is not the same as dest, copies it and changes the permission
         mode to mode. If dest is a directory, destination is dest/src. If
         mode is not set, default is used. If verbose is set to true, the
         name of each file copied will be printed.
     no - Wes Garland
 url(path)
     Java: toURL
     no - Wes Garland
 uri(path)
     Java: toURI
     no - Wes Garland
 walk
     Python: Walk a directory tree.
     no - Kris Kowal
 commonPrefix
     return the longest common prefix of a list of paths.
     no - Kris Kowal
 
 
 File Type
 ===========
 
 [new] File(path, &quot;+rwab&quot;, encoding)
 
     File(fileNo:Number)
     File(path:String, mode, encoding)
     File({path, mode, buffering, encoding, newLine})
     File({directory, prefix}) - temp file
     File({command})
 
     Mode:
         +, update
         a, append
         r, read
         w, write
         x, exclusive (lock)
         c, canon (nonblocking)
         
     construction implicitly opens
     does the javascript GC call a destructor function?  needs to.
          - Kris Kowal, Wes Garland
 
     Java: FileStream
     Python: open is also file.  file is generally preferred
 
 read() actual:Number
     reads to eof and returns binary
 read(length) actual:Number
     Tom Robinson, Kevin Dangoor, Wes Garland, Kris Kowal:
        should return Binary and Binary should have .toString(encoding=default)
 readLine() :String
 next()
 readInto(buffer:Binary) actual:Number
 write(:Binary) actual:Number
 seek(pos:Number, whence:Number code)
 tell() pos:Cookie
 truncate([pos:Cookie])
 close() undefined
 readable()
     whether it was opened for reading
 writable()
     whether it was opened for writing
 seekable()
     whether there is random access
 fileNo
     undefined if the underlying implementation does not use file descriptors
 raw()
     raw is undefined if there is no underlying unbuffered file object
 
 readLine() :String
     returns &quot;&quot; if EOF hit immediately
     alternately input() to distinguish from read
 next()
     next line
     throws if EOF hit immediately
 iter() 
     returns self (since it implements next())
 forEach(relation)
 each(relation)
 
 readLines()
 
 writeLine()
     writeln, print
 writeLines(lines)
 
 isEOF
     isEof - Kris Kowal
     atEOF - Wes Garland, maybe
 fcntl - not recommended , use ioctl - Wes Garland
 getFileNo - not recommended, - Wes Garland
 toNumber an alias for `getFileNo` - not recommeded - Wes Garland
 getLineNo - encoding dependent, not recommended - Wes Garland
 isTty
     isTTY - Wes Garland
 rewind
 flush
 seek
 stat
 select
 fsync
 ioctl
 truncate
 writeLock
 readLock
 unlock
 dup()
 stat
 lastAccessed
 lastModified
 setLastModified
 lastNodeModified
 getSize
 setPos
     Posix/Python: seek
 getPos
     Posix/Python: tell
 isReadable
 isReallyReadable
 isWritable
 isReallyWritable
 isExecutable
 isReallyExecutable
 executesAsOwner
 executesAsGroupOwner
 setMode
 getMode
 setReadOnly
 pathComponents - Wes Garland
 drive
 extensions
 baseName
 dirName
 absolute
     fullPath - Wes Garland
 
 
 Directory Type
 ==============
 list
 forEach
 each
 iter
 isSticky
 remove
 match
 glob
 
 
 Stat Type
 =========
 
 permissions   Permissions
 inode         Number  // optional
 linkCount     Number  // optional
 owner         String
 group         String  // optional
 size          Number
 atime         Date
 mtime         Date
 ctime         Date
 
 Permissions Type
 ================
 
 owner [&quot;read&quot;, &quot;write&quot;]
 group [&quot;read&quot;]
 world []
 sticky
 setuid
 setgid
 
 
 Binary Type
 ===========
 
 Binary(:Array, [width, endian])
 Binary(:String, [ecoding])
 Binary.fromArray(:Array, [width, endian])
 Binary.fromString(:String, [encoding])
 Binary.createBuffer(length, [fill = 0])
 Binary.prototype.toString(encoding)
 Array.prototype.toBinary([width, endian])
 
 
 Todo
 ====
 
 Split File into File and IO base (Tom Robinson, Kevin Dangoor)
 Clarify difference between canRead, isReadable, and select
 Resolve the default encoding for Binary.toString()
 Note distinction between read():Binary and input():String, as well as write(:Binary) and print(String)
 getEncoding
 setEncoding
 
 George Mosochovitis: divide among FileSystem, Path, and File
 
 
 References
 ==========
 
 http://www.python.org/dev/peps/pep-3116/
 http://www.erights.org/javadoc/java/io/File.html
 http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html
 http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html
 http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html
 http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html
 http://docs.python.org/library/os.path.html
 http://www.ruby-doc.org/core/classes/File.html
 http://www.ruby-doc.org/core/classes/IO.html</text>
    </revision>
    <revision>
      <id>51</id>
      <timestamp>2009-03-24T23:16:45Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Draft 2 of File API discussion</comment>
      <text xml:space="preserve">= High Level =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal


= API and Proposed Names =

== File System Object ==

* the location of the file system type.
** environment.fs
** The file module would not expose a FileSystem constructor, since that implies &quot;ambient authority&quot; to get wholesale access to the file system, although platform specific modules that depend on ambient authority in a permissive environment might be used to construct this FileSystem object, and it could be then safely chrooted or passed directly to a sandbox in its environment with the same name.  The &quot;fs&quot; object would conform to the following API.
* the location of the file system object provided to your environment.
** is provided as &quot;environment.fs&quot; in all modules and has all of the properties and methods defined for the FileSystem type:
*** Kris Kowal

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.    If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* moves a file from a source to a target path.  both paths are joined on the current working directory.
** move(source, target):
*** uncontested

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
*** uncontested

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente

* makes any directories that are missing on a given path.  Does not throw an exception if any of the base paths are missing, and does not throw an exception if all of the path already exists.  Only throws an exception if it can't make the path exist.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
*** uncontested

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
** update(path, stat):
*** Wes Garland

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal

* locks the file at a given path with either an exclusive or shared lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal

* attempts to lock a file at a given path.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
** tryLock(path, &quot;shared|exclusive&quot;):
*** Wes Garland

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* returns the size of the corresponding file.
** size(path)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.
** open(path, &quot;+arwxc&quot;, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)

* returns whether a given path matches a glob pattern.
** match(pattern, path)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem.

* a string directing a path up to the parent of the current directory, usually '..'.
** parent
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)

* a string directing a path back to itself, usually '.'.
** self

* a string that contains the path separator, usually '/', '\', or ':'.
** separator

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** alternateSeparator

* a string that contains the extension separator, usually '.'.
** extensionSeparator

* whether the file system supports unicode file names
** supportsUnicodeFileNames

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.
** absolute(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)

* returns the intrinsic path to a given file.  Resolves the path relative to the current working directory.  This involves tracing the hard parent links of it and its ancestors until reaching the root of the file system.  If the file system was returned by chroot, returns undefined if the parent links traverse to a path that's inaccessible from the chroot, if the file system is chrooted.
** canonical(path)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)

== Stat Object ==

* the Date that the file was last accessed.
** lastAccessed:
*** Kris Kowal
** atime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file was last modified.
** lastModified:
*** Kris Kowal
*** Mario Valente
** mtime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file's stat/metadata was last modified.
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** ctime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** ommit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** ommit entirely:
*** Wes Garland

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  

== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)

* returns whether the cursor is at the end of the IO stream.
** isEof():
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** eof()

* flushes buffers for an IO stream
** flush()

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= File Module =

The file module would export a copy of every property on &quot;environment.fs&quot;, for convenience.  Thus::

 require('file').open(foo)

Would be equivalent to:

 environment.fs.open(foo)


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= References =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
: http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>52</id>
      <timestamp>2009-03-24T23:20:27Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>fixed the last reference formatting</comment>
      <text xml:space="preserve">= High Level =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal


= API and Proposed Names =

== File System Object ==

* the location of the file system type.
** environment.fs
** The file module would not expose a FileSystem constructor, since that implies &quot;ambient authority&quot; to get wholesale access to the file system, although platform specific modules that depend on ambient authority in a permissive environment might be used to construct this FileSystem object, and it could be then safely chrooted or passed directly to a sandbox in its environment with the same name.  The &quot;fs&quot; object would conform to the following API.
* the location of the file system object provided to your environment.
** is provided as &quot;environment.fs&quot; in all modules and has all of the properties and methods defined for the FileSystem type:
*** Kris Kowal

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.    If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* moves a file from a source to a target path.  both paths are joined on the current working directory.
** move(source, target):
*** uncontested

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
*** uncontested

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente

* makes any directories that are missing on a given path.  Does not throw an exception if any of the base paths are missing, and does not throw an exception if all of the path already exists.  Only throws an exception if it can't make the path exist.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
*** uncontested

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
** update(path, stat):
*** Wes Garland

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal

* locks the file at a given path with either an exclusive or shared lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal

* attempts to lock a file at a given path.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
** tryLock(path, &quot;shared|exclusive&quot;):
*** Wes Garland

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* returns the size of the corresponding file.
** size(path)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.
** open(path, &quot;+arwxc&quot;, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)

* returns whether a given path matches a glob pattern.
** match(pattern, path)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem.

* a string directing a path up to the parent of the current directory, usually '..'.
** parent
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)

* a string directing a path back to itself, usually '.'.
** self

* a string that contains the path separator, usually '/', '\', or ':'.
** separator

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** alternateSeparator

* a string that contains the extension separator, usually '.'.
** extensionSeparator

* whether the file system supports unicode file names
** supportsUnicodeFileNames

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.
** absolute(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)

* returns the intrinsic path to a given file.  Resolves the path relative to the current working directory.  This involves tracing the hard parent links of it and its ancestors until reaching the root of the file system.  If the file system was returned by chroot, returns undefined if the parent links traverse to a path that's inaccessible from the chroot, if the file system is chrooted.
** canonical(path)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)

== Stat Object ==

* the Date that the file was last accessed.
** lastAccessed:
*** Kris Kowal
** atime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file was last modified.
** lastModified:
*** Kris Kowal
*** Mario Valente
** mtime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file's stat/metadata was last modified.
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** ctime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** ommit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** ommit entirely:
*** Wes Garland

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  

== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)

* returns whether the cursor is at the end of the IO stream.
** isEof():
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** eof()

* flushes buffers for an IO stream
** flush()

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= File Module =

The file module would export a copy of every property on &quot;environment.fs&quot;, for convenience.  Thus::

 require('file').open(foo)

Would be equivalent to:

 environment.fs.open(foo)


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= References =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>53</id>
      <timestamp>2009-03-24T23:36:13Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>/* References */</comment>
      <text xml:space="preserve">= High Level =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal


= API and Proposed Names =

== File System Object ==

* the location of the file system type.
** environment.fs
** The file module would not expose a FileSystem constructor, since that implies &quot;ambient authority&quot; to get wholesale access to the file system, although platform specific modules that depend on ambient authority in a permissive environment might be used to construct this FileSystem object, and it could be then safely chrooted or passed directly to a sandbox in its environment with the same name.  The &quot;fs&quot; object would conform to the following API.
* the location of the file system object provided to your environment.
** is provided as &quot;environment.fs&quot; in all modules and has all of the properties and methods defined for the FileSystem type:
*** Kris Kowal

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.    If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* moves a file from a source to a target path.  both paths are joined on the current working directory.
** move(source, target):
*** uncontested

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
*** uncontested

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente

* makes any directories that are missing on a given path.  Does not throw an exception if any of the base paths are missing, and does not throw an exception if all of the path already exists.  Only throws an exception if it can't make the path exist.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
*** uncontested

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
** update(path, stat):
*** Wes Garland

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal

* locks the file at a given path with either an exclusive or shared lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal

* attempts to lock a file at a given path.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
** tryLock(path, &quot;shared|exclusive&quot;):
*** Wes Garland

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* returns the size of the corresponding file.
** size(path)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.
** open(path, &quot;+arwxc&quot;, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)

* returns whether a given path matches a glob pattern.
** match(pattern, path)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem.

* a string directing a path up to the parent of the current directory, usually '..'.
** parent
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)

* a string directing a path back to itself, usually '.'.
** self

* a string that contains the path separator, usually '/', '\', or ':'.
** separator

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** alternateSeparator

* a string that contains the extension separator, usually '.'.
** extensionSeparator

* whether the file system supports unicode file names
** supportsUnicodeFileNames

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.
** absolute(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)

* returns the intrinsic path to a given file.  Resolves the path relative to the current working directory.  This involves tracing the hard parent links of it and its ancestors until reaching the root of the file system.  If the file system was returned by chroot, returns undefined if the parent links traverse to a path that's inaccessible from the chroot, if the file system is chrooted.
** canonical(path)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)

== Stat Object ==

* the Date that the file was last accessed.
** lastAccessed:
*** Kris Kowal
** atime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file was last modified.
** lastModified:
*** Kris Kowal
*** Mario Valente
** mtime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file's stat/metadata was last modified.
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** ctime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** ommit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** ommit entirely:
*** Wes Garland

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  

== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)

* returns whether the cursor is at the end of the IO stream.
** isEof():
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** eof()

* flushes buffers for an IO stream
** flush()

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= File Module =

The file module would export a copy of every property on &quot;environment.fs&quot;, for convenience.  Thus::

 require('file').open(foo)

Would be equivalent to:

 environment.fs.open(foo)


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= Inspiration =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>54</id>
      <timestamp>2009-03-25T07:58:13Z</timestamp>
      <contributor>
        <ip>Ondras</ip>
      </contributor>
      <comment>/* High Level */</comment>
      <text xml:space="preserve">= High Level =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
#** Ondrej Zara
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#** Ondrej Zara
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#** Ondrej Zara
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#** expand:
#*** Ondrej Zara
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#** normalize:
#*** Ondrej Zara
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
#** Ondrej Zara
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#** Ondrej Zara
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal

= API and Proposed Names =

== File System Object ==

* the location of the file system type.
** environment.fs
** The file module would not expose a FileSystem constructor, since that implies &quot;ambient authority&quot; to get wholesale access to the file system, although platform specific modules that depend on ambient authority in a permissive environment might be used to construct this FileSystem object, and it could be then safely chrooted or passed directly to a sandbox in its environment with the same name.  The &quot;fs&quot; object would conform to the following API.
* the location of the file system object provided to your environment.
** is provided as &quot;environment.fs&quot; in all modules and has all of the properties and methods defined for the FileSystem type:
*** Kris Kowal

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.    If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* moves a file from a source to a target path.  both paths are joined on the current working directory.
** move(source, target):
*** uncontested

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
*** uncontested

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente

* makes any directories that are missing on a given path.  Does not throw an exception if any of the base paths are missing, and does not throw an exception if all of the path already exists.  Only throws an exception if it can't make the path exist.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
*** uncontested

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
** update(path, stat):
*** Wes Garland

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal

* locks the file at a given path with either an exclusive or shared lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal

* attempts to lock a file at a given path.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
** tryLock(path, &quot;shared|exclusive&quot;):
*** Wes Garland

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* returns the size of the corresponding file.
** size(path)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.
** open(path, &quot;+arwxc&quot;, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)

* returns whether a given path matches a glob pattern.
** match(pattern, path)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem.

* a string directing a path up to the parent of the current directory, usually '..'.
** parent
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)

* a string directing a path back to itself, usually '.'.
** self

* a string that contains the path separator, usually '/', '\', or ':'.
** separator

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** alternateSeparator

* a string that contains the extension separator, usually '.'.
** extensionSeparator

* whether the file system supports unicode file names
** supportsUnicodeFileNames

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.
** absolute(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)

* returns the intrinsic path to a given file.  Resolves the path relative to the current working directory.  This involves tracing the hard parent links of it and its ancestors until reaching the root of the file system.  If the file system was returned by chroot, returns undefined if the parent links traverse to a path that's inaccessible from the chroot, if the file system is chrooted.
** canonical(path)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)

== Stat Object ==

* the Date that the file was last accessed.
** lastAccessed:
*** Kris Kowal
** atime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file was last modified.
** lastModified:
*** Kris Kowal
*** Mario Valente
** mtime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file's stat/metadata was last modified.
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** ctime:
*** Tom Robinson
*** Kevin Dangoor

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** ommit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** ommit entirely:
*** Wes Garland

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  

== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)

* returns whether the cursor is at the end of the IO stream.
** isEof():
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** eof()

* flushes buffers for an IO stream
** flush()

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= File Module =

The file module would export a copy of every property on &quot;environment.fs&quot;, for convenience.  Thus::

 require('file').open(foo)

Would be equivalent to:

 environment.fs.open(foo)


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= Inspiration =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>55</id>
      <timestamp>2009-03-25T08:03:52Z</timestamp>
      <contributor>
        <ip>Ondras</ip>
      </contributor>
      <comment>/* Stat Object */</comment>
      <text xml:space="preserve">= High Level =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
#** Ondrej Zara
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#** Ondrej Zara
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#** Ondrej Zara
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#** expand:
#*** Ondrej Zara
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#** normalize:
#*** Ondrej Zara
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
#** Ondrej Zara
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#** Ondrej Zara
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal

= API and Proposed Names =

== File System Object ==

* the location of the file system type.
** environment.fs
** The file module would not expose a FileSystem constructor, since that implies &quot;ambient authority&quot; to get wholesale access to the file system, although platform specific modules that depend on ambient authority in a permissive environment might be used to construct this FileSystem object, and it could be then safely chrooted or passed directly to a sandbox in its environment with the same name.  The &quot;fs&quot; object would conform to the following API.
* the location of the file system object provided to your environment.
** is provided as &quot;environment.fs&quot; in all modules and has all of the properties and methods defined for the FileSystem type:
*** Kris Kowal

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.    If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* moves a file from a source to a target path.  both paths are joined on the current working directory.
** move(source, target):
*** uncontested

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
*** uncontested

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente

* makes any directories that are missing on a given path.  Does not throw an exception if any of the base paths are missing, and does not throw an exception if all of the path already exists.  Only throws an exception if it can't make the path exist.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
*** uncontested

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
** update(path, stat):
*** Wes Garland

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal

* locks the file at a given path with either an exclusive or shared lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal

* attempts to lock a file at a given path.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
** tryLock(path, &quot;shared|exclusive&quot;):
*** Wes Garland

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* returns the size of the corresponding file.
** size(path)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.
** open(path, &quot;+arwxc&quot;, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)

* returns whether a given path matches a glob pattern.
** match(pattern, path)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem.

* a string directing a path up to the parent of the current directory, usually '..'.
** parent
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)

* a string directing a path back to itself, usually '.'.
** self

* a string that contains the path separator, usually '/', '\', or ':'.
** separator

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** alternateSeparator

* a string that contains the extension separator, usually '.'.
** extensionSeparator

* whether the file system supports unicode file names
** supportsUnicodeFileNames

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.
** absolute(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)

* returns the intrinsic path to a given file.  Resolves the path relative to the current working directory.  This involves tracing the hard parent links of it and its ancestors until reaching the root of the file system.  If the file system was returned by chroot, returns undefined if the parent links traverse to a path that's inaccessible from the chroot, if the file system is chrooted.
** canonical(path)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)

== Stat Object ==

* the Date that the file was last accessed.
** lastAccessed:
*** Kris Kowal
** atime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara

* the Date that the file was last modified.
** lastModified:
*** Kris Kowal
*** Mario Valente
** mtime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara

* the Date that the file's stat/metadata was last modified.
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** ctime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** ommit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** ommit entirely:
*** Wes Garland
*** Ondrej Zara

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size
*** Ondrej Zara

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device

== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  

== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)

* returns whether the cursor is at the end of the IO stream.
** isEof():
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** eof()

* flushes buffers for an IO stream
** flush()

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= File Module =

The file module would export a copy of every property on &quot;environment.fs&quot;, for convenience.  Thus::

 require('file').open(foo)

Would be equivalent to:

 environment.fs.open(foo)


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= Inspiration =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>56</id>
      <timestamp>2009-03-25T22:14:02Z</timestamp>
      <contributor>
        <ip>Gmosx</ip>
      </contributor>
      <minor/>
      <comment>/* High Level */</comment>
      <text xml:space="preserve">= High Level =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
#** Ondrej Zara
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#** Ondrej Zara
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#** Ondrej Zara
#** George Moschovitis
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#** expand:
#*** Ondrej Zara
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#** normalize:
#*** Ondrej Zara
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
#** Ondrej Zara
#** George Moschovitis
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#** Ondrej Zara
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal

= API and Proposed Names =

== File System Object ==

* the location of the file system type.
** environment.fs
** The file module would not expose a FileSystem constructor, since that implies &quot;ambient authority&quot; to get wholesale access to the file system, although platform specific modules that depend on ambient authority in a permissive environment might be used to construct this FileSystem object, and it could be then safely chrooted or passed directly to a sandbox in its environment with the same name.  The &quot;fs&quot; object would conform to the following API.
* the location of the file system object provided to your environment.
** is provided as &quot;environment.fs&quot; in all modules and has all of the properties and methods defined for the FileSystem type:
*** Kris Kowal

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.    If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* moves a file from a source to a target path.  both paths are joined on the current working directory.
** move(source, target):
*** uncontested

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
*** uncontested

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente

* makes any directories that are missing on a given path.  Does not throw an exception if any of the base paths are missing, and does not throw an exception if all of the path already exists.  Only throws an exception if it can't make the path exist.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
*** uncontested

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
** update(path, stat):
*** Wes Garland

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal

* locks the file at a given path with either an exclusive or shared lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal

* attempts to lock a file at a given path.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
** tryLock(path, &quot;shared|exclusive&quot;):
*** Wes Garland

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)

* returns the size of the corresponding file.
** size(path)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.
** open(path, &quot;+arwxc&quot;, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)

* returns whether a given path matches a glob pattern.
** match(pattern, path)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem.

* a string directing a path up to the parent of the current directory, usually '..'.
** parent
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)

* a string directing a path back to itself, usually '.'.
** self

* a string that contains the path separator, usually '/', '\', or ':'.
** separator

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** alternateSeparator

* a string that contains the extension separator, usually '.'.
** extensionSeparator

* whether the file system supports unicode file names
** supportsUnicodeFileNames

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.
** absolute(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)

* returns the intrinsic path to a given file.  Resolves the path relative to the current working directory.  This involves tracing the hard parent links of it and its ancestors until reaching the root of the file system.  If the file system was returned by chroot, returns undefined if the parent links traverse to a path that's inaccessible from the chroot, if the file system is chrooted.
** canonical(path)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)

== Stat Object ==

* the Date that the file was last accessed.
** lastAccessed:
*** Kris Kowal
** atime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara

* the Date that the file was last modified.
** lastModified:
*** Kris Kowal
*** Mario Valente
** mtime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara

* the Date that the file's stat/metadata was last modified.
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** ctime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** ommit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** ommit entirely:
*** Wes Garland
*** Ondrej Zara

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size
*** Ondrej Zara

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device

== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  

== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)

* returns whether the cursor is at the end of the IO stream.
** isEof():
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** eof()

* flushes buffers for an IO stream
** flush()

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= File Module =

The file module would export a copy of every property on &quot;environment.fs&quot;, for convenience.  Thus::

 require('file').open(foo)

Would be equivalent to:

 environment.fs.open(foo)


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= Inspiration =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>57</id>
      <timestamp>2009-03-26T06:38:53Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Reinserted etymologies.</comment>
      <text xml:space="preserve">
= API and Proposed Names =

The following sections are organized with a bullet point per function.  Each point includes a specification for the behavior of a given method, intended to be suitable for documentation.  Under each definition is a list of potential names for that function, and in bullets beneath that, everyone is encouraged to write their name under their preference.  Please feel to leave comments as well.

In the next section, &quot;General Preferences&quot;, there are several broad sweeping points about whether to use certain conventions in a consistent fashion.  All of the name options are intended to conform to the prevalent opinion among those elections.  For example, &quot;make&quot; and &quot;create&quot; and &quot;dir&quot; and &quot;directory&quot; are both general preference elections, so if you would prefer &quot;makeDir&quot; over &quot;createDirectory&quot;, please vote independently for &quot;make&quot; and &quot;dir&quot; in the general preferences.


== File System Object ==

The &quot;file&quot; module would conform to the File System API, as well as objects returned by &quot;chroot&quot;.  There is no definitive implementation of a FileSystem class, so &quot;chroot&quot; is the only way to construct new objects that conform to the FileSystem API.  In permissive environments, the &quot;file&quot; module may have direct access to ambient authority through a foreign function interface, or may itself be a dynamically loaded module.  In secured environments, the &quot;file&quot; module must copy the properties of &quot;environment.fs&quot; onto its exports.

In a secure sandbox, the following statements would be equivalent.

 require('file').open(foo)
 environment.fs.open(foo)

Since &quot;fs&quot; must be frozen to be secure, there is no need for the &quot;file&quot; module to assemble aparatus for late binding to &quot;fs&quot; methods.

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland
*** (Python: os.path.exists, Ruby: exist?, exists?, Java: exists, JSExt: access, Spidermonkey: Helma: v8cgi: JSExt: EJScript: Synchronet: exists, jslibs: exist)

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.path.lexists)

* moves a file from a source to a target path.  Both paths are joined on the current working directory.
** move(source, target):
** (Ruby: move, Python: shutil.move, Java: File.renameTo)

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal
** (Ruby: rename)

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
** (Ruby: copy, systemCopy, Python: copy, Unix: cp)

* copies a file and its recursive contents to a target path.  Both paths are joined on the current working directory.  If &quot;synbolicLinks&quot; is truthy, symbolic links in the source tree are represented as symbolic links in the new tree; if falsy, the contents of the linked files are copied to the new tree.  If ignore is given, it must be a relation that will receive as its arguments the directory being visited by copytree(), and a list of its contents. Since this is called recursively (or walking an equivalent iteration), the ignore relation will be called once for each directory that is copied. The relation must return a sequence of directory and file names relative to the current directory (i.e. a subset of the items in its second argument); these names will then be ignored in the copy process.
** copyTree(source, target, symbolicLinks = false, ignore = undefined)
** copy(source, target, &quot;recursive&quot;)
** copy(source, target, true)
** (Python: copytree)

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente
** (Unix: mkdir)

* creates recursive directories.  Makes all intermediate-level directories needed to contain the leaf directory. Throws an exception if the leaf directory already exists or cannot be created. The default mode is 0777 (octal). On some systems, mode is ignored. Where it is used, the current umask value is first masked out.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;recursive&quot;):
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)
** makeTree(path)
** (Unix: mkdir -p, Ruby: makedirs, mkpath, Python: os.makedirs) 

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland
** (Ruby: unlink, delete, Python: unlink, remove, Java: delete, Posix: unlink, Unix: rm, Spidermonkey: Helma: EJScript: Synchronet: remove, jslibs: Delete)

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)
** removeTree(path, ignoreErrors = false, onError = undefined)
** (Unix: rm -r, Python: rmtree)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested
** (Python: link, Ruby: link, Unix: ln)

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)
** (Ruby: symlink, Python: symlink, Unix: ln -s)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland
** (Java: createNewFile, Posix: creat, Unix: touch)

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
** omit entirely:
*** Kris Kowal
** (Ruby: truncate, Python: ftruncate applies to open files only)

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
*** Wes Garland
** update(path, stat):
** chstat(path, stat):
** setStat(path, stat):
** restat(path, stat):
** (a low-level alternative to Python's copy2 and copyStat)

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal
** (Unix: touch)

* locks the file at a given path with either an exclusive or shared advisory lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal
** lock(path, &quot;rw|&quot;)
** (Posix: lock, Python: lock)

* attempts to acquire an advisory lock a file at a given path but does not block.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
*** Wes Garland
** tryLock(path, &quot;shared|exclusive&quot;):
** lock(path, &quot;rw&quot;)
** (Python: lock)

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)
** lock(path, &quot;u&quot;)
** (Python: lock)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente
** (Python: os.stat, Ruby: File.stat, Posix: stat)

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.lstat, Ruby: File.lstat)

* returns the size of the corresponding file.
** size(path)
** (Python: size, Ruby: size?: Java: length, Posix: st_size)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.  The given permissions object may be a Unix numeric representation of permissions, a Stat object, or any object that provides the members of Stat regarding permissions.
** open(path, &quot;+arwxc&quot;, permissions, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)
** (Java: FileStream classes, Python: open, file, Ruby: File.new, universal precedent among SSJS frameworks)

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)
** (Python: os.listdir, Ruby: Dir)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)
** (Ruby: Dir[])

* returns whether a given path matches a glob pattern.
** match(pattern, path)
** (Ruby: fnmatch)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem object.

* a string directing a path up to the parent of the current directory, usually '..'.
** PARENT
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)
** (Python: pardir)

* a string directing a path back to itself, usually '.'.
** SELF
** (Python: curdir)

* a string that contains the path separator, usually '/', '\', or ':'.
** SEPARATOR
** (Python: sep, Spidermonkey: separator, Ruby: SEPARATOR, Separator)

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** ALTERNATE_SEPARATOR
** (Python: altsep, Ruby: ALT_SEPARATOR)

* a string that contains the extension separator, usually '.'.
** EXTENSION_SEPRATOR
** (Python: extsep)

* whether the file system supports unicode file names
** SUPPORTS_UNICODE_FILE_NAMES

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)
** (not precedented)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland
** (Python: Unix: dirname)

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland
** (Python: Unix: basename)

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland
** (Ruby: extname)

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)
** (Python: normpath)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to epxanding any user directory alias, joining the path to the current working directory, and normalizing the result.
** absolute(path)
** (Python: abspath)

* returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding an user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.
** canonical(path)
** (Python: realpath)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)
** (Python: isabs)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)


== Stat Object ==

* the Date that the file was last accessed.
** atime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastAccessed:
*** Kris Kowal
** (Python: getatime, Ruby: atime)

* the Date that the file was last modified.
** mtime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastModified:
*** Kris Kowal
*** Mario Valente
** (Python: getmtime, Ruby: mtime, Java: Spidermonkey: Helma: lastModified, jslibs: modifyTime, EJScript: modified, Synchronet: date)

* the Date that the file's stat/metadata was last modified.
** ctime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** (Ruby: ctime, Python: getctime)

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:
** omit entirely:
*** Kris Kowal
** (Spidermonkey: jslibs: creationTime, EJScript: create)

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** omit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory
** (Spidermonkey: isDir, Helma: isDir, JSExt: isdir)

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** omit entirely:
*** Wes Garland
*** Ondrej Zara

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size
*** Ondrej Zara
** (jslibs: size, Helma: getLength, Spidermonkey: wxJS: EJScript: Synchronet: length)

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner
** setuid

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner
** setgid

* whether the corresponding directory will permit anyone to create files in it, but only let the owner of a file delete it.
** sticky

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  


== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()
** (Python: JSExt: readline, Spidermonkey: Helma: Synchronet: readln)

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()
** (Python: readlines, JSExt: readlines, EJScript: getLines)

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)
** (universal precedent)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()
** (wxJS: JSExt: Python: Ruby: tell)

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)
** (Ruby: truncate, Python: ftruncate)

* returns whether the cursor is at the end of the IO stream.
** eof()
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** (Helma: wxJS: JSExt: Synchronet: eof)

* flushes buffers for an IO stream
** flush()
** (universal precedent)

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)
** (related to isOpen in many existing SSJS frameworks, but without a race condition hazard)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= General Preferences =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
#** Ondrej Zara
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#** Ondrej Zara
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#** Ondrej Zara
#** George Moschovitis
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#** expand:
#*** Ondrej Zara
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#** normalize:
#*** Ondrej Zara
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
#** Ondrej Zara
#** George Moschovitis
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#** Ondrej Zara
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal


= References =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>58</id>
      <timestamp>2009-03-26T06:42:47Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Reinserted etymologies.</comment>
      <text xml:space="preserve">

= API and Proposed Names =

The following sections are organized with a bullet point per function.  Each point includes a specification for the behavior of a given method, intended to be suitable for documentation.  Under each definition is a list of potential names for that function, and in bullets beneath that, everyone is encouraged to write their name under their preference.  Please feel to leave comments as well.

In the next section, &quot;General Preferences&quot;, there are several broad sweeping points about whether to use certain conventions in a consistent fashion.  All of the name options are intended to conform to the prevalent opinion among those elections.  For example, &quot;make&quot; and &quot;create&quot; and &quot;dir&quot; and &quot;directory&quot; are both general preference elections, so if you would prefer &quot;makeDir&quot; over &quot;createDirectory&quot;, please vote independently for &quot;make&quot; and &quot;dir&quot; in the general preferences.


== File System Object ==

The &quot;file&quot; module would conform to the File System API, as well as objects returned by &quot;chroot&quot;.  There is no definitive implementation of a FileSystem class, so &quot;chroot&quot; is the only way to construct new objects that conform to the FileSystem API.  In permissive environments, the &quot;file&quot; module may have direct access to ambient authority through a foreign function interface, or may itself be a dynamically loaded module.  In secured environments, the &quot;file&quot; module must copy the properties of &quot;environment.fs&quot; onto its exports.

In a secure sandbox, the following statements would be equivalent.

 require('file').open(foo)
 environment.fs.open(foo)

Since &quot;fs&quot; must be frozen to be secure, there is no need for the &quot;file&quot; module to assemble aparatus for late binding to &quot;fs&quot; methods.

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland
*** (Python: os.path.exists, Ruby: exist?, exists?, Java: exists, JSExt: access, Spidermonkey: Helma: v8cgi: JSExt: EJScript: Synchronet: exists, jslibs: exist)

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.path.lexists)

* moves a file from a source to a target path.  Both paths are joined on the current working directory.
** move(source, target):
** (Ruby: move, Python: shutil.move, Java: File.renameTo)

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal
** (Ruby: rename)

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
** (Ruby: copy, systemCopy, Python: copy, Unix: cp)

* copies a file and its recursive contents to a target path.  Both paths are joined on the current working directory.  If &quot;synbolicLinks&quot; is truthy, symbolic links in the source tree are represented as symbolic links in the new tree; if falsy, the contents of the linked files are copied to the new tree.  If ignore is given, it must be a relation that will receive as its arguments the directory being visited by copytree(), and a list of its contents. Since this is called recursively (or walking an equivalent iteration), the ignore relation will be called once for each directory that is copied. The relation must return a sequence of directory and file names relative to the current directory (i.e. a subset of the items in its second argument); these names will then be ignored in the copy process.
** copyTree(source, target, symbolicLinks = false, ignore = undefined)
** copy(source, target, &quot;recursive&quot;)
** copy(source, target, true)
** (Python: copytree)

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente
** (Unix: mkdir)

* creates recursive directories.  Makes all intermediate-level directories needed to contain the leaf directory. Throws an exception if the leaf directory already exists or cannot be created. The default mode is 0777 (octal). On some systems, mode is ignored. Where it is used, the current umask value is first masked out.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;recursive&quot;):
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)
** makeTree(path)
** (Unix: mkdir -p, Ruby: makedirs, mkpath, Python: os.makedirs) 

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland
** (Ruby: unlink, delete, Python: unlink, remove, Java: delete, Posix: unlink, Unix: rm, Spidermonkey: Helma: EJScript: Synchronet: remove, jslibs: Delete)

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)
** removeTree(path, ignoreErrors = false, onError = undefined)
** (Unix: rm -r, Python: rmtree)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested
** (Python: link, Ruby: link, Unix: ln)

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)
** (Ruby: symlink, Python: symlink, Unix: ln -s)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland
** (Java: createNewFile, Posix: creat, Unix: touch)

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
** omit entirely:
*** Kris Kowal
** (Ruby: truncate, Python: ftruncate applies to open files only)

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
*** Wes Garland
** update(path, stat):
** chstat(path, stat):
** setStat(path, stat):
** restat(path, stat):
** (a low-level alternative to Python's copy2 and copyStat)

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal
** (Unix: touch)

* locks the file at a given path with either an exclusive or shared advisory lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal
** lock(path, &quot;rw|&quot;)
** (Posix: lock, Python: lock)

* attempts to acquire an advisory lock a file at a given path but does not block.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
*** Wes Garland
** tryLock(path, &quot;shared|exclusive&quot;):
** lock(path, &quot;rw&quot;)
** (Python: lock)

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)
** lock(path, &quot;u&quot;)
** (Python: lock)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente
** (Python: os.stat, Ruby: File.stat, Posix: stat)

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.lstat, Ruby: File.lstat)

* returns the size of the corresponding file.
** size(path)
** (Python: size, Ruby: size?: Java: length, Posix: st_size)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.  The given permissions object may be a Unix numeric representation of permissions, a Stat object, or any object that provides the members of Stat regarding permissions.
** open(path, &quot;+arwxc&quot;, permissions, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)
** (Java: FileStream classes, Python: open, file, Ruby: File.new, universal precedent among SSJS frameworks)

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)
** (Python: os.listdir, Ruby: Dir)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)
** (Ruby: Dir[])

* returns whether a given path matches a glob pattern.
** match(pattern, path)
** (Ruby: fnmatch)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem object.

* a string directing a path up to the parent of the current directory, usually '..'.
** PARENT
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)
** (Python: pardir)

* a string directing a path back to itself, usually '.'.
** SELF
** (Python: curdir)

* a string that contains the path separator, usually '/', '\', or ':'.
** SEPARATOR
** (Python: sep, Spidermonkey: separator, Ruby: SEPARATOR, Separator)

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** ALTERNATE_SEPARATOR
** (Python: altsep, Ruby: ALT_SEPARATOR)

* a string that contains the extension separator, usually '.'.
** EXTENSION_SEPRATOR
** (Python: extsep)

* whether the file system supports unicode file names
** SUPPORTS_UNICODE_FILE_NAMES

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)
** (not precedented)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland
** (Python: Unix: dirname)

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland
** (Python: Unix: basename)

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland
** (Ruby: extname)

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)
** (Python: normpath)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to epxanding any user directory alias, joining the path to the current working directory, and normalizing the result.
** absolute(path)
** (Python: abspath)

* returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding an user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.
** canonical(path)
** (Python: realpath)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)
** (Python: isabs)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)


== Stat Object ==

* the Date that the file was last accessed.
** atime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastAccessed:
*** Kris Kowal
** (Python: getatime, Ruby: atime)

* the Date that the file was last modified.
** mtime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastModified:
*** Kris Kowal
*** Mario Valente
** (Python: getmtime, Ruby: mtime, Java: Spidermonkey: Helma: lastModified, jslibs: modifyTime, EJScript: modified, Synchronet: date)

* the Date that the file's stat/metadata was last modified.
** ctime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** (Ruby: ctime, Python: getctime)

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:
** omit entirely:
*** Kris Kowal
** (Spidermonkey: jslibs: creationTime, EJScript: create)

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** omit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory
** (Spidermonkey: isDir, Helma: isDir, JSExt: isdir)

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** omit entirely:
*** Wes Garland
*** Ondrej Zara

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size
*** Ondrej Zara
** (jslibs: size, Helma: getLength, Spidermonkey: wxJS: EJScript: Synchronet: length)

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner
** setuid

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner
** setgid

* whether the corresponding directory will permit anyone to create files in it, but only let the owner of a file delete it.
** sticky

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  


== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()
** (Python: JSExt: readline, Spidermonkey: Helma: Synchronet: readln)

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()
** (Python: readlines, JSExt: readlines, EJScript: getLines)

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)
** (universal precedent)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()
** (wxJS: JSExt: Python: Ruby: tell)

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)
** (Ruby: truncate, Python: ftruncate)

* returns whether the cursor is at the end of the IO stream.
** eof()
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** (Helma: wxJS: JSExt: Synchronet: eof)

* flushes buffers for an IO stream
** flush()
** (universal precedent)

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)
** (related to isOpen in many existing SSJS frameworks, but without a race condition hazard)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= General Preferences =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
#** Ondrej Zara
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#** Ondrej Zara
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#** Ondrej Zara
#** George Moschovitis
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#** expand:
#*** Ondrej Zara
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#** normalize:
#*** Ondrej Zara
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
#** Ondrej Zara
#** George Moschovitis
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#** Ondrej Zara
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal


= References =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>59</id>
      <timestamp>2009-03-29T03:50:37Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Added a proposal for a tier1 specification of the File API</comment>
      <text xml:space="preserve">= Tier 1 =

The require('file') module would provide support the File System API.  In turn, the File System API would provide all methods that deal with path strings.  File System API functions would return file stream objects, directory objects, and file stat objects.  File stream objects would, for securability, be unaware of their corresponding path, and keep their underlying file system connection, albeit a file descriptor or FILE*, and their parent directory link, secret.

The File System API would provide the following methods:

* normal: removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.

* absolute: returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to expanding any user directory alias, joining the path to the current working directory, and normalizing the result.

* canonical: returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding a user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.

* exists(path): whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.

* existsLink(path): whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.

* stat(path): returns an object that represents a snapshot of the information about given file.
*# The stat file must contain the following properties:
*## mtime: the time that the file was last modified
*## other properties will be specified in a future specification, including other times, ownership, permissions, and size.
*# The path is resolved relative to the current working directory.
*# Throws an error if the corresponding file does not exist or is inaccessible.

* statLink(path): returns the same object as stat, except for the symbolic link at the end of the path, if it is a symbolic link.

* list(path): returns a traversable, indexable representation of the names of files in a particular directory.
*# The returned object implements the Array API for indexing, and may in fact be an Array if the underlying implementation is not sophhisticated enough to do lazy indexing.  The prototype of the returned object contains all of the Array generics like &quot;push&quot;, &quot;pop&quot;, and such.
*# The returned object may be immutable.
*# The returned object must implement &quot;next&quot; and &quot;prev&quot;, which walk backward and forward among the file names in the directory.  Both throw an exception when they are beyond the bounds of the directory.
*# The path is resolved relative to the current working directory.
*# Throws an error if the directory does not exist or is inaccessible.

* open(path, mode, permissions, encoding): returns an IO stream object that supports the requested mode and encoding.
*# The encoding must be undefined, &quot;utf-8&quot;, or &quot;utf-16&quot;.  Other encodings may be specified in the future.
*## An undefined encoding means &quot;binary&quot;, and implies that read and write methods will operate on byte array objects (not yet specified) instead of strings.  The &quot;cookie&quot; returned by &quot;tell&quot; and accepted by &quot;seek&quot; can only be an integer for binary encoding (although this tier does not specify those methods).
*# The mode is a String and may contain:
*## &quot;r&quot; that means that the stream may be read, and implies that the &quot;read&quot;, &quot;readLine&quot;, &quot;readLines&quot;, &quot;next&quot;, and &quot;iter&quot; methods must be supported by the returned stream object.  &quot;readLine&quot; returns &quot;&quot; on EOF, and &quot;next&quot; throws an error instead.  &quot;iter&quot; returns the stream object itself.  &quot;readLine&quot; returns a string excluding the newline character.
*## &quot;w&quot; that means that the stream may be written to, and implies that the &quot;write&quot;, &quot;writeLine&quot;, and &quot;writeLines&quot; methods must be supported by the stream object.  Also implies that the file will be created or truncated if necessary, if not overridden by the &quot;a&quot; or &quot;+&quot; flags.
*## &quot;a&quot; that means that the stream's position will begin at the end of the stream, and that the file will be created but not truncated.
*## &quot;+&quot; that means that the stream will not be truncated.
*## other options may be added in the future for advisory locks.
*## the &quot;b&quot; option known in other languages will not be implemented since it is really an encoding argument.
*# The permissions must be an integer of Unix style permissions.  Other objects may be permitted in a later specification, like a Stat object or duck-type thereof.
*# The path is resolved relative to the current working directory.
*# Throws an error if the specified stream cannot be created.

= Tier 2 =

In progress.  More information about other potential additions, please refer to the [https://wiki.mozilla.org/ServerJS/API/file/Names|proposed names].</text>
    </revision>
    <revision>
      <id>60</id>
      <timestamp>2009-03-29T03:55:53Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>/* Tier 1 */ removed symlink variants for tier 1</comment>
      <text xml:space="preserve">= Tier 1 =

The require('file') module would provide support the File System API.  In turn, the File System API would provide all methods that deal with path strings.  File System API functions would return file stream objects, directory objects, and file stat objects.  File stream objects would, for securability, be unaware of their corresponding path, and keep their underlying file system connection, albeit a file descriptor or FILE*, and their parent directory link, secret.

The File System API would provide the following methods:

* normal: removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.

* absolute: returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to expanding any user directory alias, joining the path to the current working directory, and normalizing the result.

* canonical: returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding a user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.

* exists(path): whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.

* stat(path): returns an object that represents a snapshot of the information about given file.
*# The stat file must contain the following properties:
*## mtime: the time that the file was last modified
*## other properties will be specified in a future specification, including other times, ownership, permissions, and size.
*# The path is resolved relative to the current working directory.
*# Throws an error if the corresponding file does not exist or is inaccessible.

* list(path): returns a traversable, indexable representation of the names of files in a particular directory.
*# The returned object implements the Array API for indexing, and may in fact be an Array if the underlying implementation is not sophhisticated enough to do lazy indexing.  The prototype of the returned object contains all of the Array generics like &quot;push&quot;, &quot;pop&quot;, and such.
*# The returned object may be immutable.
*# The returned object must implement &quot;next&quot; and &quot;prev&quot;, which walk backward and forward among the file names in the directory.  Both throw an exception when they are beyond the bounds of the directory.
*# The path is resolved relative to the current working directory.
*# Throws an error if the directory does not exist or is inaccessible.

* open(path, mode, permissions, encoding): returns an IO stream object that supports the requested mode and encoding.
*# The encoding must be undefined, &quot;utf-8&quot;, or &quot;utf-16&quot;.  Other encodings may be specified in the future.
*## An undefined encoding means &quot;binary&quot;, and implies that read and write methods will operate on byte array objects (not yet specified) instead of strings.  The &quot;cookie&quot; returned by &quot;tell&quot; and accepted by &quot;seek&quot; can only be an integer for binary encoding (although this tier does not specify those methods).
*# The mode is a String and may contain:
*## &quot;r&quot; that means that the stream may be read, and implies that the &quot;read&quot;, &quot;readLine&quot;, &quot;readLines&quot;, &quot;next&quot;, and &quot;iter&quot; methods must be supported by the returned stream object.  &quot;readLine&quot; returns &quot;&quot; on EOF, and &quot;next&quot; throws an error instead.  &quot;iter&quot; returns the stream object itself.  &quot;readLine&quot; returns a string excluding the newline character.
*## &quot;w&quot; that means that the stream may be written to, and implies that the &quot;write&quot;, &quot;writeLine&quot;, and &quot;writeLines&quot; methods must be supported by the stream object.  Also implies that the file will be created or truncated if necessary, if not overridden by the &quot;a&quot; or &quot;+&quot; flags.
*## &quot;a&quot; that means that the stream's position will begin at the end of the stream, and that the file will be created but not truncated.
*## &quot;+&quot; that means that the stream will not be truncated.
*## other options may be added in the future for advisory locks.
*## the &quot;b&quot; option known in other languages will not be implemented since it is really an encoding argument.
*# The permissions must be an integer of Unix style permissions.  Other objects may be permitted in a later specification, like a Stat object or duck-type thereof.
*# The path is resolved relative to the current working directory.
*# Throws an error if the specified stream cannot be created.

= Tier 2 =

In progress.  More information about other potential additions, please refer to the [https://wiki.mozilla.org/ServerJS/API/file/Names|proposed names].</text>
    </revision>
    <revision>
      <id>61</id>
      <timestamp>2009-04-02T13:46:38Z</timestamp>
      <contributor>
        <ip>Jake123</ip>
      </contributor>
      <comment>/* Tier 1 */</comment>
      <text xml:space="preserve">= Tier 1 =

The require('file') module would provide support the File System API.  In turn, the File System API would provide all methods that deal with path strings.  File System API functions would return file stream objects, directory objects, and file stat objects.  File stream objects would, for securability, be unaware of their corresponding path, and keep their underlying file system connection, albeit a file descriptor or FILE*, and their parent directory link, secret.

The File System API would provide the following methods:

* normal: removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.

* absolute: returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to expanding any user directory alias, joining the path to the current working directory, and normalizing the result.

* canonical: returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding a user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.

* exists(path): whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.

* stat(path): returns an object that represents a snapshot of the information about given file.
*# The stat file must contain the following properties:
*## mtime: the time that the file was last modified
*## other properties will be specified in a future specification, including other times, ownership, permissions, and size.
*# The path is resolved relative to the current working directory.
*# Throws an error if the corresponding file does not exist or is inaccessible.

* list(path): returns a traversable, indexable representation of the names of files in a particular directory.
*# The returned object implements the Array API for indexing, and may in fact be an Array if the underlying implementation is not sophhisticated enough to do lazy indexing.  The prototype of the returned object contains all of the Array generics like &quot;push&quot;, &quot;pop&quot;, and such.
*# The returned object may be immutable.
*# The returned object must implement &quot;next&quot; and &quot;prev&quot;, which walk backward and forward among the file names in the directory.  Both throw an exception when they are beyond the bounds of the directory.
*# The path is resolved relative to the current working directory.
*# Throws an error if the directory does not exist or is inaccessible.

* open(path, mode, permissions, encoding): returns an IO stream object that supports the requested mode and encoding.
*# The encoding must be undefined, &quot;utf-8&quot;, or &quot;utf-16&quot;.  Other encodings may be specified in the future.
*## An undefined encoding means &quot;binary&quot;, and implies that read and write methods will operate on byte array objects (not yet specified) instead of strings.  The &quot;cookie&quot; returned by &quot;tell&quot; and accepted by &quot;seek&quot; can only be an integer for binary encoding (although this tier does not specify those methods).
*# The mode is a String and may contain:
*## &quot;r&quot; that means that the stream may be read, and implies that the &quot;read&quot;, &quot;readLine&quot;, &quot;readLines&quot;, &quot;next&quot;, and &quot;iter&quot; methods must be supported by the returned stream object.  &quot;readLine&quot; returns &quot;&quot; on EOF, and &quot;next&quot; throws an error instead.  &quot;iter&quot; returns the stream object itself.  &quot;readLine&quot; returns a string excluding the newline character.
*## &quot;w&quot; that means that the stream may be written to, and implies that the &quot;write&quot;, &quot;writeLine&quot;, and &quot;writeLines&quot; methods must be supported by the stream object.  Also implies that the file will be created or truncated if necessary, if not overridden by the &quot;a&quot; or &quot;+&quot; flags.
*## &quot;a&quot; that means that the stream's position will begin at the end of the stream, and that the file will be created but not truncated.
*## &quot;+&quot; that means that the stream will not be truncated.
*## other options may be added in the future for advisory locks.
*## the &quot;b&quot; option known in other languages will not be implemented since it is really an encoding argument.
*# The permissions must be an integer of Unix style permissions.  Other objects may be permitted in a later specification, like a Stat object or duck-type thereof.
*# The path is resolved relative to the current working directory.
*# Throws an error if the specified stream cannot be created.
* close(): Closes the file. Should be called automatically when the mode is changed, and when the garbage collector collects its last reference.

= Tier 2 =

In progress.  More information about other potential additions, please refer to the [https://wiki.mozilla.org/ServerJS/API/file/Names|proposed names].</text>
    </revision>
    <revision>
      <id>62</id>
      <timestamp>2009-04-04T17:29:14Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Moved close under open.</comment>
      <text xml:space="preserve">= Tier 1 =

The require('file') module would provide support the File System API.  In turn, the File System API would provide all methods that deal with path strings.  File System API functions would return file stream objects, directory objects, and file stat objects.  File stream objects would, for securability, be unaware of their corresponding path, and keep their underlying file system connection, albeit a file descriptor or FILE*, and their parent directory link, secret.

The File System API would provide the following methods:

* normal: removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.

* absolute: returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to expanding any user directory alias, joining the path to the current working directory, and normalizing the result.

* canonical: returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding a user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.

* exists(path): whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.

* stat(path): returns an object that represents a snapshot of the information about given file.
*# The stat file must contain the following properties:
*## mtime: the time that the file was last modified
*## other properties will be specified in a future specification, including other times, ownership, permissions, and size.
*# The path is resolved relative to the current working directory.
*# Throws an error if the corresponding file does not exist or is inaccessible.

* list(path): returns a traversable, indexable representation of the names of files in a particular directory.
*# The returned object implements the Array API for indexing, and may in fact be an Array if the underlying implementation is not sophhisticated enough to do lazy indexing.  The prototype of the returned object contains all of the Array generics like &quot;push&quot;, &quot;pop&quot;, and such.
*# The returned object may be immutable.
*# The returned object must implement &quot;next&quot; and &quot;prev&quot;, which walk backward and forward among the file names in the directory.  Both throw an exception when they are beyond the bounds of the directory.
*# The path is resolved relative to the current working directory.
*# Throws an error if the directory does not exist or is inaccessible.

* open(path, mode, permissions, encoding): returns an IO stream object that supports the requested mode and encoding.
*# The encoding must be undefined, &quot;utf-8&quot;, or &quot;utf-16&quot;.  Other encodings may be specified in the future.
*## An undefined encoding means &quot;binary&quot;, and implies that read and write methods will operate on byte array objects (not yet specified) instead of strings.  The &quot;cookie&quot; returned by &quot;tell&quot; and accepted by &quot;seek&quot; can only be an integer for binary encoding (although this tier does not specify those methods).
*# The mode is a String and may contain:
*## &quot;r&quot; that means that the stream may be read, and implies that the &quot;read&quot;, &quot;readLine&quot;, &quot;readLines&quot;, &quot;next&quot;, and &quot;iter&quot; methods must be supported by the returned stream object.  &quot;readLine&quot; returns &quot;&quot; on EOF, and &quot;next&quot; throws an error instead.  &quot;iter&quot; returns the stream object itself.  &quot;readLine&quot; returns a string excluding the newline character.
*## &quot;w&quot; that means that the stream may be written to, and implies that the &quot;write&quot;, &quot;writeLine&quot;, and &quot;writeLines&quot; methods must be supported by the stream object.  Also implies that the file will be created or truncated if necessary, if not overridden by the &quot;a&quot; or &quot;+&quot; flags.
*## &quot;a&quot; that means that the stream's position will begin at the end of the stream, and that the file will be created but not truncated.
*## &quot;+&quot; that means that the stream will not be truncated.
*## other options may be added in the future for advisory locks.
*## the &quot;b&quot; option known in other languages will not be implemented since it is really an encoding argument.
*# The permissions must be an integer of Unix style permissions.  Other objects may be permitted in a later specification, like a Stat object or duck-type thereof.
*# The path is resolved relative to the current working directory.
*# Throws an error if the specified stream cannot be created.
*# close(): Closes the stream. Should be called automatically when the mode is changed, and when the garbage collector collects its last reference.

= Tier 2 =

In progress.  More information about other potential additions, please refer to the [https://wiki.mozilla.org/ServerJS/API/file/Names|proposed names].</text>
    </revision>
    <revision>
      <id>63</id>
      <timestamp>2009-04-07T21:04:37Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>/* Tier 2 */ fixed a link.</comment>
      <text xml:space="preserve">= Tier 1 =

The require('file') module would provide support the File System API.  In turn, the File System API would provide all methods that deal with path strings.  File System API functions would return file stream objects, directory objects, and file stat objects.  File stream objects would, for securability, be unaware of their corresponding path, and keep their underlying file system connection, albeit a file descriptor or FILE*, and their parent directory link, secret.

The File System API would provide the following methods:

* normal: removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.

* absolute: returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to expanding any user directory alias, joining the path to the current working directory, and normalizing the result.

* canonical: returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding a user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.

* exists(path): whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.

* stat(path): returns an object that represents a snapshot of the information about given file.
*# The stat file must contain the following properties:
*## mtime: the time that the file was last modified
*## other properties will be specified in a future specification, including other times, ownership, permissions, and size.
*# The path is resolved relative to the current working directory.
*# Throws an error if the corresponding file does not exist or is inaccessible.

* list(path): returns a traversable, indexable representation of the names of files in a particular directory.
*# The returned object implements the Array API for indexing, and may in fact be an Array if the underlying implementation is not sophhisticated enough to do lazy indexing.  The prototype of the returned object contains all of the Array generics like &quot;push&quot;, &quot;pop&quot;, and such.
*# The returned object may be immutable.
*# The returned object must implement &quot;next&quot; and &quot;prev&quot;, which walk backward and forward among the file names in the directory.  Both throw an exception when they are beyond the bounds of the directory.
*# The path is resolved relative to the current working directory.
*# Throws an error if the directory does not exist or is inaccessible.

* open(path, mode, permissions, encoding): returns an IO stream object that supports the requested mode and encoding.
*# The encoding must be undefined, &quot;utf-8&quot;, or &quot;utf-16&quot;.  Other encodings may be specified in the future.
*## An undefined encoding means &quot;binary&quot;, and implies that read and write methods will operate on byte array objects (not yet specified) instead of strings.  The &quot;cookie&quot; returned by &quot;tell&quot; and accepted by &quot;seek&quot; can only be an integer for binary encoding (although this tier does not specify those methods).
*# The mode is a String and may contain:
*## &quot;r&quot; that means that the stream may be read, and implies that the &quot;read&quot;, &quot;readLine&quot;, &quot;readLines&quot;, &quot;next&quot;, and &quot;iter&quot; methods must be supported by the returned stream object.  &quot;readLine&quot; returns &quot;&quot; on EOF, and &quot;next&quot; throws an error instead.  &quot;iter&quot; returns the stream object itself.  &quot;readLine&quot; returns a string excluding the newline character.
*## &quot;w&quot; that means that the stream may be written to, and implies that the &quot;write&quot;, &quot;writeLine&quot;, and &quot;writeLines&quot; methods must be supported by the stream object.  Also implies that the file will be created or truncated if necessary, if not overridden by the &quot;a&quot; or &quot;+&quot; flags.
*## &quot;a&quot; that means that the stream's position will begin at the end of the stream, and that the file will be created but not truncated.
*## &quot;+&quot; that means that the stream will not be truncated.
*## other options may be added in the future for advisory locks.
*## the &quot;b&quot; option known in other languages will not be implemented since it is really an encoding argument.
*# The permissions must be an integer of Unix style permissions.  Other objects may be permitted in a later specification, like a Stat object or duck-type thereof.
*# The path is resolved relative to the current working directory.
*# Throws an error if the specified stream cannot be created.
*# close(): Closes the stream. Should be called automatically when the mode is changed, and when the garbage collector collects its last reference.

= Tier 2 =

In progress.  More information about other potential additions, please refer to the [https://wiki.mozilla.org/ServerJS/API/file/Names proposed names].</text>
    </revision>
    <revision>
      <id>64</id>
      <timestamp>2009-04-07T23:36:33Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>/* Tier 1 */ add keyword open thingie</comment>
      <text xml:space="preserve">= Tier 1 =

The require('file') module would provide support the File System API.  In turn, the File System API would provide all methods that deal with path strings.  File System API functions would return file stream objects, directory objects, and file stat objects.  File stream objects would, for securability, be unaware of their corresponding path, and keep their underlying file system connection, albeit a file descriptor or FILE*, and their parent directory link, secret.

The File System API would provide the following methods:

* normal: removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.

* absolute: returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to expanding any user directory alias, joining the path to the current working directory, and normalizing the result.

* canonical: returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding a user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.

* exists(path): whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.

* stat(path): returns an object that represents a snapshot of the information about given file.
*# The stat file must contain the following properties:
*## mtime: the time that the file was last modified
*## other properties will be specified in a future specification, including other times, ownership, permissions, and size.
*# The path is resolved relative to the current working directory.
*# Throws an error if the corresponding file does not exist or is inaccessible.

* list(path): returns a traversable, indexable representation of the names of files in a particular directory.
*# The returned object implements the Array API for indexing, and may in fact be an Array if the underlying implementation is not sophhisticated enough to do lazy indexing.  The prototype of the returned object contains all of the Array generics like &quot;push&quot;, &quot;pop&quot;, and such.
*# The returned object may be immutable.
*# The returned object must implement &quot;next&quot; and &quot;prev&quot;, which walk backward and forward among the file names in the directory.  Both throw an exception when they are beyond the bounds of the directory.
*# The path is resolved relative to the current working directory.
*# Throws an error if the directory does not exist or is inaccessible.

* open(path, mode, permissions, encoding) or open(path, {keywords}) or open({keywords}): returns an IO stream object that supports the requested mode and encoding.
*# The encoding must be undefined, &quot;utf-8&quot;, or &quot;utf-16&quot;.  Other encodings may be specified in the future.
*## An undefined encoding means &quot;binary&quot;, and implies that read and write methods will operate on byte array objects (not yet specified) instead of strings.  The &quot;cookie&quot; returned by &quot;tell&quot; and accepted by &quot;seek&quot; can only be an integer for binary encoding (although this tier does not specify those methods).
*# The mode is a String and may contain:
*## &quot;r&quot; that means that the stream may be read, and implies that the &quot;read&quot;, &quot;readLine&quot;, &quot;readLines&quot;, &quot;next&quot;, and &quot;iter&quot; methods must be supported by the returned stream object.  &quot;readLine&quot; returns &quot;&quot; on EOF, and &quot;next&quot; throws an error instead.  &quot;iter&quot; returns the stream object itself.  &quot;readLine&quot; returns a string excluding the newline character.
*## &quot;w&quot; that means that the stream may be written to, and implies that the &quot;write&quot;, &quot;writeLine&quot;, and &quot;writeLines&quot; methods must be supported by the stream object.  Also implies that the file will be created or truncated if necessary, if not overridden by the &quot;a&quot; or &quot;+&quot; flags.
*## &quot;a&quot; that means that the stream's position will begin at the end of the stream, and that the file will be created but not truncated.
*## &quot;+&quot; that means that the stream will not be truncated.
*## other options may be added in the future for advisory locks.
*## the &quot;b&quot; option known in other languages will not be implemented since it is really an encoding argument.
*# The permissions must be an integer of Unix style permissions.  Other objects may be permitted in a later specification, like a Stat object or duck-type thereof.
*# The path is resolved relative to the current working directory.
*# Throws an error if the specified stream cannot be created.
*# close(): Closes the stream. Should be called automatically when the mode is changed, and when the garbage collector collects its last reference.

= Tier 2 =

In progress.  More information about other potential additions, please refer to the [https://wiki.mozilla.org/ServerJS/API/file/Names proposed names].</text>
    </revision>
    <revision>
      <id>65</id>
      <timestamp>2009-04-07T23:51:28Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>/* Tier 1 */ added another open syntax option</comment>
      <text xml:space="preserve">= Tier 1 =

The require('file') module would provide support the File System API.  In turn, the File System API would provide all methods that deal with path strings.  File System API functions would return file stream objects, directory objects, and file stat objects.  File stream objects would, for securability, be unaware of their corresponding path, and keep their underlying file system connection, albeit a file descriptor or FILE*, and their parent directory link, secret.

The File System API would provide the following methods:

* normal: removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.

* absolute: returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to expanding any user directory alias, joining the path to the current working directory, and normalizing the result.

* canonical: returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding a user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.

* exists(path): whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.

* stat(path): returns an object that represents a snapshot of the information about given file.
*# The stat file must contain the following properties:
*## mtime: the time that the file was last modified
*## other properties will be specified in a future specification, including other times, ownership, permissions, and size.
*# The path is resolved relative to the current working directory.
*# Throws an error if the corresponding file does not exist or is inaccessible.

* list(path): returns a traversable, indexable representation of the names of files in a particular directory.
*# The returned object implements the Array API for indexing, and may in fact be an Array if the underlying implementation is not sophhisticated enough to do lazy indexing.  The prototype of the returned object contains all of the Array generics like &quot;push&quot;, &quot;pop&quot;, and such.
*# The returned object may be immutable.
*# The returned object must implement &quot;next&quot; and &quot;prev&quot;, which walk backward and forward among the file names in the directory.  Both throw an exception when they are beyond the bounds of the directory.
*# The path is resolved relative to the current working directory.
*# Throws an error if the directory does not exist or is inaccessible.

* open(path, mode, permissions, encoding) or open(path, mode, {keywords}) or open(path, {keywords}) or open({keywords}): returns an IO stream object that supports the requested mode and encoding.
*# The encoding must be undefined, &quot;utf-8&quot;, or &quot;utf-16&quot;.  Other encodings may be specified in the future.
*## An undefined encoding means &quot;binary&quot;, and implies that read and write methods will operate on byte array objects (not yet specified) instead of strings.  The &quot;cookie&quot; returned by &quot;tell&quot; and accepted by &quot;seek&quot; can only be an integer for binary encoding (although this tier does not specify those methods).
*# The mode is a String and may contain:
*## &quot;r&quot; that means that the stream may be read, and implies that the &quot;read&quot;, &quot;readLine&quot;, &quot;readLines&quot;, &quot;next&quot;, and &quot;iter&quot; methods must be supported by the returned stream object.  &quot;readLine&quot; returns &quot;&quot; on EOF, and &quot;next&quot; throws an error instead.  &quot;iter&quot; returns the stream object itself.  &quot;readLine&quot; returns a string excluding the newline character.
*## &quot;w&quot; that means that the stream may be written to, and implies that the &quot;write&quot;, &quot;writeLine&quot;, and &quot;writeLines&quot; methods must be supported by the stream object.  Also implies that the file will be created or truncated if necessary, if not overridden by the &quot;a&quot; or &quot;+&quot; flags.
*## &quot;a&quot; that means that the stream's position will begin at the end of the stream, and that the file will be created but not truncated.
*## &quot;+&quot; that means that the stream will not be truncated.
*## other options may be added in the future for advisory locks.
*## the &quot;b&quot; option known in other languages will not be implemented since it is really an encoding argument.
*# The permissions must be an integer of Unix style permissions.  Other objects may be permitted in a later specification, like a Stat object or duck-type thereof.
*# The path is resolved relative to the current working directory.
*# Throws an error if the specified stream cannot be created.
*# close(): Closes the stream. Should be called automatically when the mode is changed, and when the garbage collector collects its last reference.

= Tier 2 =

In progress.  More information about other potential additions, please refer to the [https://wiki.mozilla.org/ServerJS/API/file/Names proposed names].</text>
    </revision>
    <revision>
      <id>66</id>
      <timestamp>2009-04-25T05:44:18Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>New draft.</comment>
      <text xml:space="preserve">= Tier 1 =

This tier establishes a basis with binary IO and basic string manipulation for paths.

The require('file') module would provide support the File System API.  In turn, the File System API would provide all methods that deal with path strings.  File System API functions would return file stream objects, directory objects, and file stat objects.  File stream objects would, for securability, be unaware of their corresponding path, and keep their underlying file system connection, albeit a file descriptor or FILE*, and their parent directory link, secret.


The File System API would provide the following constants:

* SEPARATOR &quot;/&quot; or system specific analog, like &quot;:&quot; or &quot;\&quot;.
* PARENT &quot;..&quot; or system specific analog.
* SELF &quot;.&quot; or system specific analog.
* ROOT &quot;/&quot; or system specific analog, like &quot;C:\&quot;.


The File System API would provide the following methods:

* join(...paths:Strings...): takes a variadic list of path Strings, joins them on the directory separator, and normalizes the result.

* split(path:String): returns a string split on the file system's directory separator.

* resolve(...paths:Strings...): marches through a list of variadic absolute or relative path Strings, resolving the next path relative to the previous and returning the ultimate destination path.  This is analogous to navigating to the fully qualified URL of a relative URL on a given page.  Unlike &quot;join&quot;, which presumes that the base path is always a directory, &quot;resolve&quot; considers a directory separator at the end of a path an indication that the path must be resolved off of the directory rather than the leaf &quot;file&quot;.  For example, resolve(&quot;a&quot;, &quot;b&quot;) returns &quot;b&quot;, but resolve(&quot;a/&quot;, &quot;b&quot;) returns &quot;a/b&quot; on a system with &quot;/&quot; as its directory separator.  Resolving a fully qualified path relative to any base path returns the fully qualified path, like resolve(&quot;a&quot;, &quot;/&quot;) == &quot;/&quot;.  Resolve is purely a string manipulation routine and does not use information about the underlying file system.

* relative(from, to): returns the relative path from one path to another using only &quot;..&quot; to traverse up to the two paths' common ancestor.

* normal(path:String): removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.  &quot;normal&quot; may be implemented in terms of &quot;resolve&quot;.

* absolute(path:String): returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to expanding any user directory alias, joining the path to the current working directory, and normalizing the result.  &quot;absolute&quot; can be implemented in terms of &quot;resolve&quot; and &quot;cwd&quot;.

* canonical(path:String): returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding a user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.  &quot;canonical&quot; can be implemented in terms of &quot;cwd&quot;, &quot;resolve&quot;, and &quot;readlink&quot;.

* exists(path): whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.

* stat(path): returns an object that represents a snapshot of the information about given file.
*# The stat file must contain the following properties:
*## mtime: the time that the file was last modified
*## other properties will be specified in a future specification, including other times, ownership, permissions, and size.
*# The path is resolved relative to the current working directory.
*# Throws an error if the corresponding file does not exist or is inaccessible.

* list(path): returns an Array of file name strings.
*# The returned object may be immutable.
*# The path is resolved relative to the current working directory.
*# Throws an error if the directory does not exist or is inaccessible.

* open(path, mode) or open({options})
*# options may include {path, mode} and more in a later, more detailed specification.
*# The mode is a String and may contain:
*## &quot;r&quot; that means that the stream may be read, and implies that the &quot;read&quot;, &quot;readLine&quot;, &quot;readLines&quot;, &quot;next&quot;, and &quot;iter&quot; methods must be supported by the returned stream object.  &quot;readLine&quot; returns &quot;&quot; on EOF, and &quot;next&quot; throws an error instead.  &quot;iter&quot; returns the stream object itself.  &quot;readLine&quot; returns a string excluding the newline character.
*## &quot;w&quot; that means that the stream may be written to, and implies that the &quot;write&quot;, &quot;writeLine&quot;, and &quot;writeLines&quot; methods must be supported by the stream object.  Also implies that the file will be created or truncated if necessary, if not overridden by the &quot;a&quot; or &quot;+&quot; flags.
*## &quot;a&quot; that means that the stream's position will begin at the end of the stream, and that the file will be created but not truncated.
*## &quot;+&quot; that means that the stream will not be truncated.
*# The path is resolved relative to the current working directory.
*# Throws an error if the specified stream cannot be created.
*# close(): Closes the stream. Should be called automatically when the mode is changed, and when the garbage collector collects its last reference.

* read(path, [mode, [options]]): opens, reads, and closes a file, returning its content.

* write(path, content, [mode, [options]]): opens, writes, flushes, and closes a file with the given content.


= Tier 2 =

This tier adds support for encoded and buffered text IO and a chainable Path type.

* open(path, mode, {options}) or open({options})
*# options may include {path, mode, charset, recordSeparator, fieldSeparator} and more in a later, more detailed specification.
*# The mode is a String and may contain:
*## &quot;b&quot; for ByteArray and ByteString streams.
*## &quot;t&quot; for String and Array streams (default)
*# &quot;charset&quot; may be any IANA charset identifier, case-insensitive.  &quot;open&quot; may throw an error if the charset is not supported.  &quot;charset&quot; defaults to a system-specific encoding if the stream is in text mode with no charset provided.
*# returns a stream type.  While the type names need not correspond to these name, these are used as an interal reference in this document for what the minimum interface of those streams must contain.
*## Returns a BinaryReadStream for &quot;b&quot; and &quot;r&quot; modes.
*## Returns a BinaryWriteStream for &quot;b&quot; and &quot;w&quot; or &quot;a&quot; modes.
*## Returns a BinaryRandomStream for &quot;b&quot; and &quot;+&quot; modes.
*## Returns a TextReadStream wrapper for &quot;t&quot;  and &quot;r&quot; modes.
*## Returns a TextWriteStream wrapper for &quot;t&quot; and &quot;w&quot; modes.

* BinaryReadStream
** read() -&gt; all:ByteString
** read(max:Number) -&gt; actual:Number
** readInto(buffer:Array|ByteArray, [begin:Number, [end:Number]]) -&gt; actual:Number
* BinaryWriteStream
** write(buffer:Array|ByteArray|ByteString)
** flush()
* BinaryRandomStream &lt; BinaryReadStream &lt; BinaryWriteStream
** tell() -&gt; position:Number)
** seek(position:Number, whence:enumerated)
* TextReadStream
** raw -&gt; a BinaryReadStream
** readLine() -&gt; String -- returns &quot;&quot; if no data is available before EOF.  Otherwise, includes the &quot;recordSeparator&quot;.
** readLines() -&gt; Array * String
** next() -&gt; String -- throws a StopIteration if no data is available before EOF.
** input() -&gt; returns &quot;readLine&quot; without the &quot;recordSeparator&quot;.
* TextWriteStream
** raw -&gt; a BinaryWriteStream
** write(buffer:String)
** writeLine(buffer:String)
** print(...String...) -- writes a &quot;fieldSeparator&quot; delimited and &quot;recordSeparator&quot; terminated line.
** flush()

The File System API would provide the following additional methods:

* basename(path:String) -&gt; String
* copy(from:String, to:String) -&gt; copies a file by reading one and writing the other in binary modes.
* dirname(path:String) -&gt; String
* extname(path:String) -&gt; String
* isDirectory(path:String) -&gt; Boolean
* isFile(path:String) -&gt; Boolean
* isLink(path:String) -&gt; Boolean
* isReadable(path:String) -&gt; Boolean
* isWritable(path:String) -&gt; Boolean
* mkdir(path:String)
* mkdirs(path:String)
* move(from:String, to:String)
* mtime() -&gt; lastModification:Date|null
* remove(path:String)
* rename(path:String, name:String)
* rmdir(path:String)
* rmtree(path:String)
* same(from:String, to:String) -&gt; Boolean -- whether the two files are identical, in that they come from the same file system, same device, and have the same node and corresponding storage, such that modifying one would modify the other.
* size(path:String) -&gt; bytes:Number
* touch(path:String, [mtime:Date])

The Path object closes on both a file system and a path String.  The file system mediates all interaction with the underlying storage, so a Path only provides a convenient interface for chaining operations that manipulate a path string.  All of the methods of path are polymorphic (meaning late-bound) and curried (meaning the enclosed path String is passed to the corresponding file system method).

* path(path:String) -&gt; path:Path
* new Path(path:String, [fs:FileSystem]) -&gt; path:Path
*# absolute() -&gt; path:Path
*# basename() -&gt; path:Path
*# canonical() -&gt; path:Path
*# copy(to:Path)
*# dirname() -&gt; path:Path
*# exists() -&gt; Boolean
*# extname() -&gt; String
*# from(path:String|Path) -&gt; path:Path -- an alias for &quot;relative&quot; that finds the relative path from the given path to this one.
*# isDirectory() -&gt; Boolean
*# isFile() -&gt; Boolean
*# isLink() -&gt; Boolean
*# isReadable() -&gt; Boolean
*# isWritable() -&gt; Boolean
*# join(...paths...) -&gt; path:Path
*# list() -&gt; Array * Path
*# mkdir()
*# mkdirs()
*# move(to:String)
*# mtime() -&gt; Date
*# normal() -&gt; path:Path
*# open(mode, [options]) -&gt; stream:{Text,Binary}{Read,Write,RW,Random}Stream
*# read([mode, [options]]) -&gt; {Byte,}String
*# remove()
*# rename(name:String) -- rename is distinct from move only in that the new name is resolved relative to the former path, rather than the current working directory.
*# resolve(...paths...) -&gt; path:Path
*# rmdir()
*# rmtree()
*# same(as:Path|String) -&gt; Boolean
*# size() -&gt; Number
*# split() -&gt; parts:(Array * String)
*# stat() -&gt; stat:Object {mtime:Date, size:Number}
*# to(path:String|Path) -&gt; path:Path -- an alias for &quot;relative&quot; that finds the relative path from this path to the given one.
*# touch([mtime:Date])
*# write(data:ByteString|ByteArray|Array|String, [mode, [options]])


= Tier 3 =

This tier adds support for random access IO, locks, canonical IO (non-blocking), more comprehensive stat access and mutation, and temporary files and directories, and symbolic links.

* open(path, mode, {options}) or open({options})
*# options may include {path, mode, charset, permissions, owner, groupOwner} and more in a later, more detailed specification.
*# The permissions must be an integer of Unix style permissions.  Other objects may be permitted in a later specification, like a Stat object or duck-type thereof.

* copyStat(from:String, to:String)

Path:

* copyStat(to:String|Path)

In progress.  More information about other potential additions, please refer to the [https://wiki.mozilla.org/ServerJS/API/file/Names proposed names].</text>
    </revision>
    <revision>
      <id>67</id>
      <timestamp>2009-04-25T06:27:12Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <text xml:space="preserve">= Tier 1 =

This tier establishes a basis with binary IO and basic string manipulation for paths.

The require('file') module would provide support the File System API.  In turn, the File System API would provide all methods that deal with path strings.  File System API functions would return file stream objects, directory objects, and file stat objects.  File stream objects would, for securability, be unaware of their corresponding path, and keep their underlying file system connection, albeit a file descriptor or FILE*, and their parent directory link, secret.


The File System API would provide the following constants:

* SEPARATOR &quot;/&quot; or system specific analog, like &quot;:&quot; or &quot;\&quot;.
* PARENT &quot;..&quot; or system specific analog.
* SELF &quot;.&quot; or system specific analog.
* ROOT &quot;/&quot; or system specific analog, like &quot;C:\&quot;.


The File System API would provide the following methods:

* join(...paths:Strings...): takes a variadic list of path Strings, joins them on the directory separator, and normalizes the result.

* split(path:String): returns a string split on the file system's directory separator.

* resolve(...paths:Strings...): marches through a list of variadic absolute or relative path Strings, resolving the next path relative to the previous and returning the ultimate destination path.  This is analogous to navigating to the fully qualified URL of a relative URL on a given page.  Unlike &quot;join&quot;, which presumes that the base path is always a directory, &quot;resolve&quot; considers a directory separator at the end of a path an indication that the path must be resolved off of the directory rather than the leaf &quot;file&quot;.  For example, resolve(&quot;a&quot;, &quot;b&quot;) returns &quot;b&quot;, but resolve(&quot;a/&quot;, &quot;b&quot;) returns &quot;a/b&quot; on a system with &quot;/&quot; as its directory separator.  Resolving a fully qualified path relative to any base path returns the fully qualified path, like resolve(&quot;a&quot;, &quot;/&quot;) == &quot;/&quot;.  Resolve is purely a string manipulation routine and does not use information about the underlying file system.

* relative(from, to): returns the relative path from one path to another using only &quot;..&quot; to traverse up to the two paths' common ancestor.

* normal(path:String): removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.  &quot;normal&quot; may be implemented in terms of &quot;resolve&quot;.

* absolute(path:String): returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to expanding any user directory alias, joining the path to the current working directory, and normalizing the result.  &quot;absolute&quot; can be implemented in terms of &quot;resolve&quot; and &quot;cwd&quot;.

* canonical(path:String): returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding a user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.  &quot;canonical&quot; can be implemented in terms of &quot;cwd&quot;, &quot;resolve&quot;, and &quot;readlink&quot;.

* exists(path): whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.

* stat(path): returns an object that represents a snapshot of the information about given file.
*# The stat file must contain the following properties:
*## mtime: the time that the file was last modified
*## other properties will be specified in a future specification, including other times, ownership, permissions, and size.
*# The path is resolved relative to the current working directory.
*# Throws an error if the corresponding file does not exist or is inaccessible.

* list(path): returns an Array of file name strings.
*# The returned object may be immutable.
*# The path is resolved relative to the current working directory.
*# Throws an error if the directory does not exist or is inaccessible.

* open(path, mode) or open({options})
*# options may include {path, mode} and more in a later, more detailed specification.
*# The mode is a String and may contain:
*## &quot;r&quot; that means that the stream may be read, and implies that the &quot;read&quot;, &quot;readLine&quot;, &quot;readLines&quot;, &quot;next&quot;, and &quot;iter&quot; methods must be supported by the returned stream object.  &quot;readLine&quot; returns &quot;&quot; on EOF, and &quot;next&quot; throws an error instead.  &quot;iter&quot; returns the stream object itself.  &quot;readLine&quot; returns a string excluding the newline character.
*## &quot;w&quot; that means that the stream may be written to, and implies that the &quot;write&quot;, &quot;writeLine&quot;, and &quot;writeLines&quot; methods must be supported by the stream object.  Also implies that the file will be created or truncated if necessary, if not overridden by the &quot;a&quot; or &quot;+&quot; flags.
*## &quot;a&quot; that means that the stream's position will begin at the end of the stream, and that the file will be created but not truncated.
*## &quot;+&quot; that means that the stream will not be truncated.
*# The path is resolved relative to the current working directory.
*# Throws an error if the specified stream cannot be created.
*# close(): Closes the stream. Should be called automatically when the mode is changed, and when the garbage collector collects its last reference.

* read(path, [mode, [options]]): opens, reads, and closes a file, returning its content.

* write(path, content, [mode, [options]]): opens, writes, flushes, and closes a file with the given content.


= Tier 2 =

This tier adds support for encoded and buffered text IO and a chainable Path type.

* open(path, mode, {options}) or open({options})
*# options may include {path, mode, charset, recordSeparator, fieldSeparator} and more in a later, more detailed specification.
*# The mode is a String and may additionally contain:
*## &quot;b&quot; for ByteArray and ByteString streams.
*## &quot;t&quot; for String and Array streams (default)
*# &quot;charset&quot; may be any IANA charset identifier, case-insensitive.  &quot;open&quot; may throw an error if the charset is not supported.  &quot;charset&quot; defaults to a system-specific encoding if the stream is in text mode with no charset provided.
*# returns a stream type.  While the type names need not correspond to these name, these are used as an interal reference in this document for what the minimum interface of those streams must contain.
*## Returns a BinaryReadStream for &quot;b&quot; and &quot;r&quot; modes.
*## Returns a BinaryWriteStream for &quot;b&quot; and &quot;w&quot; or &quot;a&quot; modes.
*## Returns a BinaryRandomStream for &quot;b&quot; and &quot;+&quot; modes.
*## Returns a TextReadStream wrapper for &quot;t&quot;  and &quot;r&quot; modes.
*## Returns a TextWriteStream wrapper for &quot;t&quot; and &quot;w&quot; modes.

* BinaryReadStream
** read() -&gt; all:ByteString
** read(max:Number) -&gt; actual:Number
** readInto(buffer:Array|ByteArray, [begin:Number, [end:Number]]) -&gt; actual:Number
** available() -&gt; Number -- how many bytes are ready to be read (buffered) without blocking.
** skip(n:Number) -&gt; advance the read head past these bytes.
* BinaryWriteStream
** write(buffer:Array|ByteArray|ByteString)
** truncate(length:Number=0)
** flush()
* BinaryRandomStream &lt; BinaryReadStream &lt; BinaryWriteStream
** tell() -&gt; position:Number)
** seek(position:Number, whence:enumerated)
* TextReadStream
** raw -&gt; a BinaryReadStream
** readLine() -&gt; String -- returns &quot;&quot; if no data is available before EOF.  Otherwise, includes the &quot;recordSeparator&quot;.
** readLines() -&gt; Array * String
** next() -&gt; String -- throws a StopIteration if no data is available before EOF.
** input() -&gt; returns &quot;readLine&quot; without the &quot;recordSeparator&quot;.
** available() -&gt; Number -- how many characters are ready to be read (buffered) without blocking.
** skip(n:Number) -&gt; advance the read head past these characters.
* TextWriteStream
** raw -&gt; a BinaryWriteStream
** write(buffer:String)
** writeLine(buffer:String)
** print(...String...) -- writes a &quot;fieldSeparator&quot; delimited and &quot;recordSeparator&quot; terminated line.
** flush()

The File System API would provide the following additional methods:

* basename(path:String) -&gt; String
* copy(from:String, to:String) -&gt; copies a file by reading one and writing the other in binary modes.
* dirname(path:String) -&gt; String
* extname(path:String) -&gt; String
* isDirectory(path:String) -&gt; Boolean
* isFile(path:String) -&gt; Boolean
* isLink(path:String) -&gt; Boolean
* isReadable(path:String) -&gt; Boolean
* isWritable(path:String) -&gt; Boolean
* mkdir(path:String)
* mkdirs(path:String)
* move(from:String, to:String)
* mtime() -&gt; lastModification:Date|null
* remove(path:String)
* rename(path:String, name:String)
* rmdir(path:String)
* rmtree(path:String)
* same(from:String, to:String) -&gt; Boolean -- whether the two files are identical, in that they come from the same file system, same device, and have the same node and corresponding storage, such that modifying one would modify the other.
* size(path:String) -&gt; bytes:Number
* touch(path:String, [mtime:Date])

The Path object closes on both a file system and a path String.  The file system mediates all interaction with the underlying storage, so a Path only provides a convenient interface for chaining operations that manipulate a path string.  All of the methods of path are polymorphic (meaning late-bound) and curried (meaning the enclosed path String is passed to the corresponding file system method).

* path(path:String) -&gt; path:Path
* new Path(path:String, [fs:FileSystem]) -&gt; path:Path
*# absolute() -&gt; path:Path
*# basename() -&gt; path:Path
*# canonical() -&gt; path:Path
*# copy(to:Path)
*# dirname() -&gt; path:Path
*# exists() -&gt; Boolean
*# extname() -&gt; String
*# from(path:String|Path) -&gt; path:Path -- an alias for &quot;relative&quot; that finds the relative path from the given path to this one.
*# isDirectory() -&gt; Boolean
*# isFile() -&gt; Boolean
*# isLink() -&gt; Boolean
*# isReadable() -&gt; Boolean
*# isWritable() -&gt; Boolean
*# join(...paths...) -&gt; path:Path
*# list() -&gt; Array * Path
*# mkdir()
*# mkdirs()
*# move(to:String)
*# mtime() -&gt; Date
*# normal() -&gt; path:Path
*# open(mode, [options]) -&gt; stream:{Text,Binary}{Read,Write,RW,Random}Stream
*# read([mode, [options]]) -&gt; {Byte,}String
*# remove()
*# rename(name:String) -- rename is distinct from move only in that the new name is resolved relative to the former path, rather than the current working directory.
*# resolve(...paths...) -&gt; path:Path
*# rmdir()
*# rmtree()
*# same(as:Path|String) -&gt; Boolean
*# size() -&gt; Number
*# split() -&gt; parts:(Array * String)
*# stat() -&gt; stat:Object {mtime:Date, size:Number}
*# to(path:String|Path) -&gt; path:Path -- an alias for &quot;relative&quot; that finds the relative path from this path to the given one.
*# toString() -&gt; String
*# touch([mtime:Date])
*# write(data:ByteString|ByteArray|Array|String, [mode, [options]])


= Tier 3 =

This tier adds support for random access IO, locks, canonical IO (non-blocking), more comprehensive stat access and mutation, and temporary files and directories, and symbolic links.

* open(path, mode, {options}) or open({options})
*# options may include {path, mode, charset, permissions, owner, groupOwner} and more in a later, more detailed specification.
*# The permissions must be an integer of Unix style permissions.  Other objects may be permitted in a later specification, like a Stat object or duck-type thereof.

* copyStat(from:String, to:String)

Path:

* copyStat(to:String|Path)

In progress.  More information about other potential additions, please refer to the [https://wiki.mozilla.org/ServerJS/API/file/Names proposed names].</text>
    </revision>
    <revision>
      <id>68</id>
      <timestamp>2009-04-25T08:19:59Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Fixes pointed out by tlrobinson.</comment>
      <text xml:space="preserve">= Tier 1 =

This tier establishes a basis with binary IO and basic string manipulation for paths.

The require('file') module would provide support the File System API.  In turn, the File System API would provide all methods that deal with path strings.  File System API functions would return file stream objects, directory objects, and file stat objects.  File stream objects would, for securability, be unaware of their corresponding path, and keep their underlying file system connection, albeit a file descriptor or FILE*, and their parent directory link, secret.


The File System API would provide the following constants:

* SEPARATOR &quot;/&quot; or system specific analog, like &quot;:&quot; or &quot;\&quot;.
* PARENT &quot;..&quot; or system specific analog.
* SELF &quot;.&quot; or system specific analog.
* ROOT &quot;/&quot; or system specific analog, like &quot;C:\&quot;.


The File System API would provide the following methods:

* join(...paths:Strings...): takes a variadic list of path Strings, joins them on the directory separator, and normalizes the result.

* split(path:String): returns a string split on the file system's directory separator.

* resolve(...paths:Strings...): marches through a list of variadic absolute or relative path Strings, resolving the next path relative to the previous and returning the ultimate destination path.  This is analogous to navigating to the fully qualified URL of a relative URL on a given page.  Unlike &quot;join&quot;, which presumes that the base path is always a directory, &quot;resolve&quot; considers a directory separator at the end of a path an indication that the path must be resolved off of the directory rather than the leaf &quot;file&quot;.  For example, resolve(&quot;a&quot;, &quot;b&quot;) returns &quot;b&quot;, but resolve(&quot;a/&quot;, &quot;b&quot;) returns &quot;a/b&quot; on a system with &quot;/&quot; as its directory separator.  Resolving a fully qualified path relative to any base path returns the fully qualified path, like resolve(&quot;a&quot;, &quot;/&quot;) == &quot;/&quot;.  Resolve is purely a string manipulation routine and does not use information about the underlying file system.

* relative(from, to): returns the relative path from one path to another using only &quot;..&quot; to traverse up to the two paths' common ancestor.

* normal(path:String): removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.  &quot;normal&quot; may be implemented in terms of &quot;resolve&quot;.

* absolute(path:String): returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to expanding any user directory alias, joining the path to the current working directory, and normalizing the result.  &quot;absolute&quot; can be implemented in terms of &quot;resolve&quot; and &quot;cwd&quot;.

* canonical(path:String): returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding a user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.  &quot;canonical&quot; can be implemented in terms of &quot;cwd&quot;, &quot;resolve&quot;, and &quot;readlink&quot;.

* exists(path): whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.

* stat(path): returns an object that represents a snapshot of the information about given file.
*# The stat file must contain the following properties:
*## mtime: the time that the file was last modified
*## other properties will be specified in a future specification, including other times, ownership, permissions, and size.
*# The path is resolved relative to the current working directory.
*# Throws an error if the corresponding file does not exist or is inaccessible.

* list(path): returns an Array of file name strings.
*# The returned object may be immutable.
*# The path is resolved relative to the current working directory.
*# Throws an error if the directory does not exist or is inaccessible.

* open(path, mode) or open({options})
*# options may include {path, mode} and more in a later, more detailed specification.
*# The mode is a String and may contain:
*## &quot;r&quot; that means that the stream may be read, and implies that the &quot;read&quot;, &quot;readLine&quot;, &quot;readLines&quot;, &quot;next&quot;, and &quot;iter&quot; methods must be supported by the returned stream object.  &quot;readLine&quot; returns &quot;&quot; on EOF, and &quot;next&quot; throws an error instead.  &quot;iter&quot; returns the stream object itself.  &quot;readLine&quot; returns a string excluding the newline character.
*## &quot;w&quot; that means that the stream may be written to, and implies that the &quot;write&quot;, &quot;writeLine&quot;, and &quot;writeLines&quot; methods must be supported by the stream object.  Also implies that the file will be created or truncated if necessary, if not overridden by the &quot;a&quot; or &quot;+&quot; flags.
*## &quot;a&quot; that means that the stream's position will begin at the end of the stream, and that the file will be created but not truncated.
*## &quot;+&quot; that means that the stream will not be truncated.
*# The path is resolved relative to the current working directory.
*# Throws an error if the specified stream cannot be created.
*# close(): Closes the stream. Should be called automatically when the mode is changed, and when the garbage collector collects its last reference.

* read(path, [mode, [options]]): opens, reads, and closes a file, returning its content.

* write(path, content, [mode, [options]]): opens, writes, flushes, and closes a file with the given content.


= Tier 2 =

This tier adds support for encoded and buffered text IO and a chainable Path type.

* open(path, mode, {options}) or open({options})
*# options may include {path, mode, charset, recordSeparator, fieldSeparator} and more in a later, more detailed specification.
*# The mode is a String and may additionally contain:
*## &quot;b&quot; for ByteArray and ByteString streams.
*## &quot;t&quot; for String and Array streams (default)
*# &quot;charset&quot; may be any IANA charset identifier, case-insensitive.  &quot;open&quot; may throw an error if the charset is not supported.  &quot;charset&quot; defaults to a system-specific encoding if the stream is in text mode with no charset provided.
*# returns a stream type.  While the type names need not correspond to these name, these are used as an interal reference in this document for what the minimum interface of those streams must contain.
*## Returns a BinaryReadStream for &quot;b&quot; and &quot;r&quot; modes.
*## Returns a BinaryWriteStream for &quot;b&quot; and &quot;w&quot; or &quot;a&quot; modes.
*## Returns a BinaryRandomStream for &quot;b&quot; and &quot;+&quot; modes.
*## Returns a TextReadStream wrapper for &quot;t&quot;  and &quot;r&quot; modes.
*## Returns a TextWriteStream wrapper for &quot;t&quot; and &quot;w&quot; modes.

* BinaryReadStream
** read() -&gt; all:ByteString
** read(max:Number) -&gt; actual:ByteString
** readInto(buffer:Array|ByteArray, [begin:Number, [end:Number]]) -&gt; actual:Number
** available() -&gt; Number -- how many bytes are ready to be read (buffered) without blocking.
** skip(n:Number) -&gt; advance the read head past these bytes.
* BinaryWriteStream
** write(buffer:Array|ByteArray|ByteString)
** truncate(length:Number=0)
** flush()
* BinaryRandomStream &lt; BinaryReadStream &lt; BinaryWriteStream
** tell() -&gt; position:Number)
** seek(position:Number, whence:enumerated)
** rewind() -- returns the read/write head to the beginning of the file
** truncate([size:Number]) -- sets the length of the file.  size defaults to the current position as reported by tell().  If a size is explicated, truncate also seeks to the new end.
* TextReadStream
** raw -&gt; a BinaryReadStream
** read() -&gt; String -- returns all remaining characters
** read(max:Number) -&gt; String -- returns up to max characters, with the length of the returned string reflecting the actual number read.
** readLine() -&gt; String -- returns &quot;&quot; if no data is available before EOF.  Otherwise, includes the &quot;recordSeparator&quot;.
** readLines() -&gt; Array * String
** next() -&gt; String -- throws a StopIteration if no data is available before EOF.
** input() -&gt; returns &quot;readLine&quot; without the &quot;recordSeparator&quot;.
** available() -&gt; Number -- how many characters are ready to be read (buffered) without blocking.
** skip(n:Number) -&gt; advance the read head past these characters.
* TextWriteStream
** raw -&gt; a BinaryWriteStream
** write(buffer:String)
** writeLine(buffer:String)
** print(...String...) -- writes a &quot;fieldSeparator&quot; delimited and &quot;recordSeparator&quot; terminated line.
** flush()

The File System API would provide the following additional methods:

* basename(path:String) -&gt; String
* copy(from:String, to:String) -&gt; copies a file by reading one and writing the other in binary modes.
* dirname(path:String) -&gt; String
* extname(path:String) -&gt; String
* isDirectory(path:String) -&gt; Boolean
* isFile(path:String) -&gt; Boolean
* isLink(path:String) -&gt; Boolean
* isReadable(path:String) -&gt; Boolean
* isWritable(path:String) -&gt; Boolean
* mkdir(path:String)
* mkdirs(path:String)
* move(from:String, to:String)
* mtime() -&gt; lastModification:Date|null
* remove(path:String)
* rename(path:String, name:String)
* rmdir(path:String)
* rmtree(path:String)
* same(from:String, to:String) -&gt; Boolean -- whether the two files are identical, in that they come from the same file system, same device, and have the same node and corresponding storage, such that modifying one would modify the other.
* size(path:String) -&gt; bytes:Number
* touch(path:String, [mtime:Date])

The Path object closes on both a file system and a path String.  The file system mediates all interaction with the underlying storage, so a Path only provides a convenient interface for chaining operations that manipulate a path string.  All of the methods of path are polymorphic (meaning late-bound) and curried (meaning the enclosed path String is passed to the corresponding file system method).

* path(path:String) -&gt; path:Path
* new Path(path:String, [fs:FileSystem]) -&gt; path:Path
*# absolute() -&gt; path:Path
*# basename() -&gt; path:Path
*# canonical() -&gt; path:Path
*# copy(to:Path)
*# dirname() -&gt; path:Path
*# exists() -&gt; Boolean
*# extname() -&gt; String
*# from(path:String|Path) -&gt; path:Path -- an alias for &quot;relative&quot; that finds the relative path from the given path to this one.
*# isDirectory() -&gt; Boolean
*# isFile() -&gt; Boolean
*# isLink() -&gt; Boolean
*# isReadable() -&gt; Boolean
*# isWritable() -&gt; Boolean
*# join(...paths...) -&gt; path:Path
*# list() -&gt; Array * Path
*# mkdir()
*# mkdirs()
*# move(to:String)
*# mtime() -&gt; Date
*# normal() -&gt; path:Path
*# open(mode, [options]) -&gt; stream:{Text,Binary}{Read,Write,RW,Random}Stream
*# read([mode, [options]]) -&gt; {Byte,}String
*# remove()
*# rename(name:String) -- rename is distinct from move only in that the new name is resolved relative to the former path, rather than the current working directory.
*# resolve(...paths...) -&gt; path:Path
*# rmdir()
*# rmtree()
*# same(as:Path|String) -&gt; Boolean
*# size() -&gt; Number
*# split() -&gt; parts:(Array * String)
*# stat() -&gt; stat:Object {mtime:Date, size:Number}
*# to(path:String|Path) -&gt; path:Path -- an alias for &quot;relative&quot; that finds the relative path from this path to the given one.
*# toString() -&gt; String
*# touch([mtime:Date])
*# write(data:ByteString|ByteArray|Array|String, [mode, [options]])


= Tier 3 =

This tier adds support for random access IO, locks, canonical IO (non-blocking), more comprehensive stat access and mutation, and temporary files and directories, and symbolic links.

* open(path, mode, {options}) or open({options})
*# options may include {path, mode, charset, permissions, owner, groupOwner} and more in a later, more detailed specification.
*# The permissions must be an integer of Unix style permissions.  Other objects may be permitted in a later specification, like a Stat object or duck-type thereof.

* copyStat(from:String, to:String)

Path:

* copyStat(to:String|Path)

In progress.  More information about other potential additions, please refer to the [https://wiki.mozilla.org/ServerJS/API/file/Names proposed names].</text>
    </revision>
    <revision>
      <id>69</id>
      <timestamp>2009-04-26T21:43:35Z</timestamp>
      <contributor>
        <ip>Mob</ip>
      </contributor>
      <comment>/* Tier 1 */ Added some drive-path specific text. Removed ROOT.</comment>
      <text xml:space="preserve">= Tier 1 =

This tier establishes a basis with binary IO and basic string manipulation for paths.

The require('file') module would provide support the File System API.  In turn, the File System API would provide all methods that deal with path strings.  File System API functions would return file stream objects, directory objects, and file stat objects.  File stream objects would, for securability, be unaware of their corresponding path, and keep their underlying file system connection, albeit a file descriptor or FILE*, and their parent directory link, secret.


The File System API would provide the following constants:

* SEPARATOR &quot;/&quot; or system specific analog, like &quot;:&quot; or &quot;\&quot;.

The File System API would provide the following methods:

* join(...paths:Strings...): takes a variadic list of path Strings, joins them on the directory separator, and normalizes the result.

* split(path:String): returns a string split on the file system's directory separator. The split() method will return an empty string as the first element for absolute paths that do not contain drives. For file systems with drives (such as windows), the first element will be the drive with colon if the path contained a drive specification. The intent is so that join with the SEPARATOR will correctly join the elements to reconstitute the path. 

* resolve(...paths:Strings...): marches through a list of variadic absolute or relative path Strings, resolving the next path relative to the previous and returning the ultimate destination path.  This is analogous to navigating to the fully qualified URL of a relative URL on a given page.  Unlike &quot;join&quot;, which presumes that the base path is always a directory, &quot;resolve&quot; considers a directory separator at the end of a path an indication that the path must be resolved off of the directory rather than the leaf &quot;file&quot;.  For example, resolve(&quot;a&quot;, &quot;b&quot;) returns &quot;b&quot;, but resolve(&quot;a/&quot;, &quot;b&quot;) returns &quot;a/b&quot; on a system with &quot;/&quot; as its directory separator.  Resolving a fully qualified path relative to any base path returns the fully qualified path, like resolve(&quot;a&quot;, &quot;/&quot;) == &quot;/&quot;.  Resolve is purely a string manipulation routine and does not use information about the underlying file system.

* relative(from, to): returns the relative path from one path to another using only &quot;..&quot; to traverse up to the two paths' common ancestor.

* normal(path:String): removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.  &quot;normal&quot; may be implemented in terms of &quot;resolve&quot;.

* absolute(path:String): returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to expanding any user directory alias, joining the path to the current working directory, and normalizing the result.  &quot;absolute&quot; can be implemented in terms of &quot;resolve&quot; and &quot;cwd&quot;.

* canonical(path:String): returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding a user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.  &quot;canonical&quot; can be implemented in terms of &quot;cwd&quot;, &quot;resolve&quot;, and &quot;readlink&quot;.

* exists(path): whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.

* stat(path): returns an object that represents a snapshot of the information about given file.
*# The stat file must contain the following properties:
*## mtime: the time that the file was last modified
*## other properties will be specified in a future specification, including other times, ownership, permissions, and size.
*# The path is resolved relative to the current working directory.
*# Throws an error if the corresponding file does not exist or is inaccessible.

* list(path): returns an Array of file name strings.
*# The returned object may be immutable.
*# The path is resolved relative to the current working directory.
*# Throws an error if the directory does not exist or is inaccessible.

* open(path, mode) or open({options})
*# options may include {path, mode} and more in a later, more detailed specification.
*# The mode is a String and may contain:
*## &quot;r&quot; that means that the stream may be read, and implies that the &quot;read&quot;, &quot;readLine&quot;, &quot;readLines&quot;, &quot;next&quot;, and &quot;iter&quot; methods must be supported by the returned stream object.  &quot;readLine&quot; returns &quot;&quot; on EOF, and &quot;next&quot; throws an error instead.  &quot;iter&quot; returns the stream object itself.  &quot;readLine&quot; returns a string excluding the newline character.
*## &quot;w&quot; that means that the stream may be written to, and implies that the &quot;write&quot;, &quot;writeLine&quot;, and &quot;writeLines&quot; methods must be supported by the stream object.  Also implies that the file will be created or truncated if necessary, if not overridden by the &quot;a&quot; or &quot;+&quot; flags.
*## &quot;a&quot; that means that the stream's position will begin at the end of the stream, and that the file will be created but not truncated.
*## &quot;+&quot; that means that the stream will not be truncated.
*# The path is resolved relative to the current working directory.
*# Throws an error if the specified stream cannot be created.
*# close(): Closes the stream. Should be called automatically when the mode is changed, and when the garbage collector collects its last reference.

* read(path, [mode, [options]]): opens, reads, and closes a file, returning its content.

* write(path, content, [mode, [options]]): opens, writes, flushes, and closes a file with the given content.

= Tier 2 =

This tier adds support for encoded and buffered text IO and a chainable Path type.

* open(path, mode, {options}) or open({options})
*# options may include {path, mode, charset, recordSeparator, fieldSeparator} and more in a later, more detailed specification.
*# The mode is a String and may additionally contain:
*## &quot;b&quot; for ByteArray and ByteString streams.
*## &quot;t&quot; for String and Array streams (default)
*# &quot;charset&quot; may be any IANA charset identifier, case-insensitive.  &quot;open&quot; may throw an error if the charset is not supported.  &quot;charset&quot; defaults to a system-specific encoding if the stream is in text mode with no charset provided.
*# returns a stream type.  While the type names need not correspond to these name, these are used as an interal reference in this document for what the minimum interface of those streams must contain.
*## Returns a BinaryReadStream for &quot;b&quot; and &quot;r&quot; modes.
*## Returns a BinaryWriteStream for &quot;b&quot; and &quot;w&quot; or &quot;a&quot; modes.
*## Returns a BinaryRandomStream for &quot;b&quot; and &quot;+&quot; modes.
*## Returns a TextReadStream wrapper for &quot;t&quot;  and &quot;r&quot; modes.
*## Returns a TextWriteStream wrapper for &quot;t&quot; and &quot;w&quot; modes.

* BinaryReadStream
** read() -&gt; all:ByteString
** read(max:Number) -&gt; actual:ByteString
** readInto(buffer:Array|ByteArray, [begin:Number, [end:Number]]) -&gt; actual:Number
** available() -&gt; Number -- how many bytes are ready to be read (buffered) without blocking.
** skip(n:Number) -&gt; advance the read head past these bytes.
* BinaryWriteStream
** write(buffer:Array|ByteArray|ByteString)
** truncate(length:Number=0)
** flush()
* BinaryRandomStream &lt; BinaryReadStream &lt; BinaryWriteStream
** tell() -&gt; position:Number)
** seek(position:Number, whence:enumerated)
** rewind() -- returns the read/write head to the beginning of the file
** truncate([size:Number]) -- sets the length of the file.  size defaults to the current position as reported by tell().  If a size is explicated, truncate also seeks to the new end.
* TextReadStream
** raw -&gt; a BinaryReadStream
** read() -&gt; String -- returns all remaining characters
** read(max:Number) -&gt; String -- returns up to max characters, with the length of the returned string reflecting the actual number read.
** readLine() -&gt; String -- returns &quot;&quot; if no data is available before EOF.  Otherwise, includes the &quot;recordSeparator&quot;.
** readLines() -&gt; Array * String
** next() -&gt; String -- throws a StopIteration if no data is available before EOF.
** input() -&gt; returns &quot;readLine&quot; without the &quot;recordSeparator&quot;.
** available() -&gt; Number -- how many characters are ready to be read (buffered) without blocking.
** skip(n:Number) -&gt; advance the read head past these characters.
* TextWriteStream
** raw -&gt; a BinaryWriteStream
** write(buffer:String)
** writeLine(buffer:String)
** print(...String...) -- writes a &quot;fieldSeparator&quot; delimited and &quot;recordSeparator&quot; terminated line.
** flush()

The File System API would provide the following additional methods:

* basename(path:String) -&gt; String
* copy(from:String, to:String) -&gt; copies a file by reading one and writing the other in binary modes.
* dirname(path:String) -&gt; String
* extname(path:String) -&gt; String
* isDirectory(path:String) -&gt; Boolean
* isFile(path:String) -&gt; Boolean
* isLink(path:String) -&gt; Boolean
* isReadable(path:String) -&gt; Boolean
* isWritable(path:String) -&gt; Boolean
* mkdir(path:String)
* mkdirs(path:String)
* move(from:String, to:String)
* mtime() -&gt; lastModification:Date|null
* remove(path:String)
* rename(path:String, name:String)
* rmdir(path:String)
* rmtree(path:String)
* same(from:String, to:String) -&gt; Boolean -- whether the two files are identical, in that they come from the same file system, same device, and have the same node and corresponding storage, such that modifying one would modify the other.
* size(path:String) -&gt; bytes:Number
* touch(path:String, [mtime:Date])

The Path object closes on both a file system and a path String.  The file system mediates all interaction with the underlying storage, so a Path only provides a convenient interface for chaining operations that manipulate a path string.  All of the methods of path are polymorphic (meaning late-bound) and curried (meaning the enclosed path String is passed to the corresponding file system method).

* path(path:String) -&gt; path:Path
* new Path(path:String, [fs:FileSystem]) -&gt; path:Path
*# absolute() -&gt; path:Path
*# basename() -&gt; path:Path
*# canonical() -&gt; path:Path
*# copy(to:Path)
*# dirname() -&gt; path:Path
*# exists() -&gt; Boolean
*# extname() -&gt; String
*# from(path:String|Path) -&gt; path:Path -- an alias for &quot;relative&quot; that finds the relative path from the given path to this one.
*# isDirectory() -&gt; Boolean
*# isFile() -&gt; Boolean
*# isLink() -&gt; Boolean
*# isReadable() -&gt; Boolean
*# isWritable() -&gt; Boolean
*# join(...paths...) -&gt; path:Path
*# list() -&gt; Array * Path
*# mkdir()
*# mkdirs()
*# move(to:String)
*# mtime() -&gt; Date
*# normal() -&gt; path:Path
*# open(mode, [options]) -&gt; stream:{Text,Binary}{Read,Write,RW,Random}Stream
*# read([mode, [options]]) -&gt; {Byte,}String
*# remove()
*# rename(name:String) -- rename is distinct from move only in that the new name is resolved relative to the former path, rather than the current working directory.
*# resolve(...paths...) -&gt; path:Path
*# rmdir()
*# rmtree()
*# same(as:Path|String) -&gt; Boolean
*# size() -&gt; Number
*# split() -&gt; parts:(Array * String)
*# stat() -&gt; stat:Object {mtime:Date, size:Number}
*# to(path:String|Path) -&gt; path:Path -- an alias for &quot;relative&quot; that finds the relative path from this path to the given one.
*# toString() -&gt; String
*# touch([mtime:Date])
*# write(data:ByteString|ByteArray|Array|String, [mode, [options]])


= Tier 3 =

This tier adds support for random access IO, locks, canonical IO (non-blocking), more comprehensive stat access and mutation, and temporary files and directories, and symbolic links.

* open(path, mode, {options}) or open({options})
*# options may include {path, mode, charset, permissions, owner, groupOwner} and more in a later, more detailed specification.
*# The permissions must be an integer of Unix style permissions.  Other objects may be permitted in a later specification, like a Stat object or duck-type thereof.

* copyStat(from:String, to:String)

Path:

* copyStat(to:String|Path)

In progress.  More information about other potential additions, please refer to the [https://wiki.mozilla.org/ServerJS/API/file/Names proposed names].</text>
    </revision>
    <revision>
      <id>70</id>
      <timestamp>2009-05-17T23:25:49Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Moved to ServerJS/File/A</comment>
      <text xml:space="preserve">Moved to [[ServerJS/File]] and the original proposal at [[ServerJS/File/A]].</text>
    </revision>
    <revision>
      <id>71</id>
      <timestamp>2009-05-17T23:35:57Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <text xml:space="preserve">Moved to [[ServerJS/Filesystem_API]] and the original proposal at [[ServerJS/Filesystem_API/A]].</text>
    </revision>
    <revision>
      <id>72</id>
      <timestamp>2009-09-09T22:13:55Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>22 revisions:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve">Moved to [[ServerJS/Filesystem_API]] and the original proposal at [[ServerJS/Filesystem_API/A]].</text>
    </revision>
    <revision>
      <id>629</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/file]] to [[CommonJS/API/file]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve">Moved to [[ServerJS/Filesystem_API]] and the original proposal at [[ServerJS/Filesystem_API/A]].</text>
    </revision>
    <revision>
      <id>787</id>
      <timestamp>2009-09-09T22:40:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-ServerJS +CommonJS)</comment>
      <text xml:space="preserve">Moved to [[CommonJS/Filesystem_API]] and the original proposal at [[CommonJS/Filesystem_API/A]].</text>
    </revision>
    <revision>
      <id>979</id>
      <timestamp>2009-09-10T03:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/file]] to [[OldAPI/file]]</comment>
      <text xml:space="preserve">Moved to [[CommonJS/Filesystem_API]] and the original proposal at [[CommonJS/Filesystem_API/A]].</text>
    </revision>
    <revision>
      <id>1214</id>
      <timestamp>2009-09-12T02:31:22Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-CommonJS/ +)</comment>
      <text xml:space="preserve">Moved to [[Filesystem_API]] and the original proposal at [[Filesystem_API/A]].</text>
    </revision>
    <revision>
      <id>1231</id>
      <timestamp>2009-09-12T04:31:35Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-\[\[([^\]]*)_+([^\]]*)\]\] +[[\1 \2]])</comment>
      <text xml:space="preserve">Moved to [[Filesystem API]] and the original proposal at [[Filesystem API/A]].</text>
    </revision>
    <revision>
      <id>1239</id>
      <timestamp>2009-09-12T04:35:20Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-Filesystem API +Filesystem)</comment>
      <text xml:space="preserve">Moved to [[Filesystem]] and the original proposal at [[Filesystem/A]].</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/file/Names</title>
    <id>10</id>
    <revision>
      <id>73</id>
      <timestamp>2009-03-29T03:41:11Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Moved the function name discussion for the File API into a subpage.</comment>
      <text xml:space="preserve">
= API and Proposed Names =

The following sections are organized with a bullet point per function.  Each point includes a specification for the behavior of a given method, intended to be suitable for documentation.  Under each definition is a list of potential names for that function, and in bullets beneath that, everyone is encouraged to write their name under their preference.  Please feel to leave comments as well.

In the next section, &quot;General Preferences&quot;, there are several broad sweeping points about whether to use certain conventions in a consistent fashion.  All of the name options are intended to conform to the prevalent opinion among those elections.  For example, &quot;make&quot; and &quot;create&quot; and &quot;dir&quot; and &quot;directory&quot; are both general preference elections, so if you would prefer &quot;makeDir&quot; over &quot;createDirectory&quot;, please vote independently for &quot;make&quot; and &quot;dir&quot; in the general preferences.


== File System Object ==

The &quot;file&quot; module would conform to the File System API, as well as objects returned by &quot;chroot&quot;.  There is no definitive implementation of a FileSystem class, so &quot;chroot&quot; is the only way to construct new objects that conform to the FileSystem API.  In permissive environments, the &quot;file&quot; module may have direct access to ambient authority through a foreign function interface, or may itself be a dynamically loaded module.  In secured environments, the &quot;file&quot; module must copy the properties of &quot;environment.fs&quot; onto its exports.

In a secure sandbox, the following statements would be equivalent.

 require('file').open(foo)
 environment.fs.open(foo)

Since &quot;fs&quot; must be frozen to be secure, there is no need for the &quot;file&quot; module to assemble aparatus for late binding to &quot;fs&quot; methods.

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland
*** (Python: os.path.exists, Ruby: exist?, exists?, Java: exists, JSExt: access, Spidermonkey: Helma: v8cgi: JSExt: EJScript: Synchronet: exists, jslibs: exist)

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.path.lexists)

* moves a file from a source to a target path.  Both paths are joined on the current working directory.
** move(source, target):
** (Ruby: move, Python: shutil.move, Java: File.renameTo)

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal
** (Ruby: rename)

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
** (Ruby: copy, systemCopy, Python: copy, Unix: cp)

* copies a file and its recursive contents to a target path.  Both paths are joined on the current working directory.  If &quot;synbolicLinks&quot; is truthy, symbolic links in the source tree are represented as symbolic links in the new tree; if falsy, the contents of the linked files are copied to the new tree.  If ignore is given, it must be a relation that will receive as its arguments the directory being visited by copytree(), and a list of its contents. Since this is called recursively (or walking an equivalent iteration), the ignore relation will be called once for each directory that is copied. The relation must return a sequence of directory and file names relative to the current directory (i.e. a subset of the items in its second argument); these names will then be ignored in the copy process.
** copyTree(source, target, symbolicLinks = false, ignore = undefined)
** copy(source, target, &quot;recursive&quot;)
** copy(source, target, true)
** (Python: copytree)

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente
** (Unix: mkdir)

* creates recursive directories.  Makes all intermediate-level directories needed to contain the leaf directory. Throws an exception if the leaf directory already exists or cannot be created. The default mode is 0777 (octal). On some systems, mode is ignored. Where it is used, the current umask value is first masked out.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;recursive&quot;):
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)
** makeTree(path)
** (Unix: mkdir -p, Ruby: makedirs, mkpath, Python: os.makedirs) 

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland
** (Ruby: unlink, delete, Python: unlink, remove, Java: delete, Posix: unlink, Unix: rm, Spidermonkey: Helma: EJScript: Synchronet: remove, jslibs: Delete)

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)
** removeTree(path, ignoreErrors = false, onError = undefined)
** (Unix: rm -r, Python: rmtree)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested
** (Python: link, Ruby: link, Unix: ln)

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)
** (Ruby: symlink, Python: symlink, Unix: ln -s)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland
** (Java: createNewFile, Posix: creat, Unix: touch)

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
** omit entirely:
*** Kris Kowal
** (Ruby: truncate, Python: ftruncate applies to open files only)

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
*** Wes Garland
** update(path, stat):
** chstat(path, stat):
** setStat(path, stat):
** restat(path, stat):
** (a low-level alternative to Python's copy2 and copyStat)

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal
** (Unix: touch)

* locks the file at a given path with either an exclusive or shared advisory lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal
** lock(path, &quot;rw|&quot;)
** (Posix: lock, Python: lock)

* attempts to acquire an advisory lock a file at a given path but does not block.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
*** Wes Garland
** tryLock(path, &quot;shared|exclusive&quot;):
** lock(path, &quot;rw&quot;)
** (Python: lock)

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)
** lock(path, &quot;u&quot;)
** (Python: lock)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente
** (Python: os.stat, Ruby: File.stat, Posix: stat)

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.lstat, Ruby: File.lstat)

* returns the size of the corresponding file.
** size(path)
** (Python: size, Ruby: size?: Java: length, Posix: st_size)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.  The given permissions object may be a Unix numeric representation of permissions, a Stat object, or any object that provides the members of Stat regarding permissions.
** open(path, &quot;+arwxc&quot;, permissions, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)
** (Java: FileStream classes, Python: open, file, Ruby: File.new, universal precedent among SSJS frameworks)

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)
** (Python: os.listdir, Ruby: Dir)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)
** (Ruby: Dir[])

* returns whether a given path matches a glob pattern.
** match(pattern, path)
** (Ruby: fnmatch)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem object.

* a string directing a path up to the parent of the current directory, usually '..'.
** PARENT
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)
** (Python: pardir)

* a string directing a path back to itself, usually '.'.
** SELF
** (Python: curdir)

* a string that contains the path separator, usually '/', '\', or ':'.
** SEPARATOR
** (Python: sep, Spidermonkey: separator, Ruby: SEPARATOR, Separator)

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** ALTERNATE_SEPARATOR
** (Python: altsep, Ruby: ALT_SEPARATOR)

* a string that contains the extension separator, usually '.'.
** EXTENSION_SEPRATOR
** (Python: extsep)

* whether the file system supports unicode file names
** SUPPORTS_UNICODE_FILE_NAMES

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)
** (not precedented)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland
** (Python: Unix: dirname)

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland
** (Python: Unix: basename)

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland
** (Ruby: extname)

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)
** (Python: normpath)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to epxanding any user directory alias, joining the path to the current working directory, and normalizing the result.
** absolute(path)
** (Python: abspath)

* returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding an user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.
** canonical(path)
** (Python: realpath)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)
** (Python: isabs)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)


== Stat Object ==

* the Date that the file was last accessed.
** atime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastAccessed:
*** Kris Kowal
** (Python: getatime, Ruby: atime)

* the Date that the file was last modified.
** mtime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastModified:
*** Kris Kowal
*** Mario Valente
** (Python: getmtime, Ruby: mtime, Java: Spidermonkey: Helma: lastModified, jslibs: modifyTime, EJScript: modified, Synchronet: date)

* the Date that the file's stat/metadata was last modified.
** ctime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** (Ruby: ctime, Python: getctime)

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:
** omit entirely:
*** Kris Kowal
** (Spidermonkey: jslibs: creationTime, EJScript: create)

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** omit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory
** (Spidermonkey: isDir, Helma: isDir, JSExt: isdir)

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** omit entirely:
*** Wes Garland
*** Ondrej Zara

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size
*** Ondrej Zara
** (jslibs: size, Helma: getLength, Spidermonkey: wxJS: EJScript: Synchronet: length)

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner
** setuid

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner
** setgid

* whether the corresponding directory will permit anyone to create files in it, but only let the owner of a file delete it.
** sticky

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  


== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()
** (Python: JSExt: readline, Spidermonkey: Helma: Synchronet: readln)

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()
** (Python: readlines, JSExt: readlines, EJScript: getLines)

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)
** (universal precedent)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()
** (wxJS: JSExt: Python: Ruby: tell)

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)
** (Ruby: truncate, Python: ftruncate)

* returns whether the cursor is at the end of the IO stream.
** eof()
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** (Helma: wxJS: JSExt: Synchronet: eof)

* flushes buffers for an IO stream
** flush()
** (universal precedent)

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)
** (related to isOpen in many existing SSJS frameworks, but without a race condition hazard)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= General Preferences =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
#** Ondrej Zara
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#** Ondrej Zara
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#** Ondrej Zara
#** George Moschovitis
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#** expand:
#*** Ondrej Zara
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#** normalize:
#*** Ondrej Zara
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
#** Ondrej Zara
#** George Moschovitis
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#** Ondrej Zara
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal


= References =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>74</id>
      <timestamp>2009-04-07T23:34:25Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>add keyword-style open proposal</comment>
      <text xml:space="preserve">= API and Proposed Names =

The following sections are organized with a bullet point per function.  Each point includes a specification for the behavior of a given method, intended to be suitable for documentation.  Under each definition is a list of potential names for that function, and in bullets beneath that, everyone is encouraged to write their name under their preference.  Please feel to leave comments as well.

In the next section, &quot;General Preferences&quot;, there are several broad sweeping points about whether to use certain conventions in a consistent fashion.  All of the name options are intended to conform to the prevalent opinion among those elections.  For example, &quot;make&quot; and &quot;create&quot; and &quot;dir&quot; and &quot;directory&quot; are both general preference elections, so if you would prefer &quot;makeDir&quot; over &quot;createDirectory&quot;, please vote independently for &quot;make&quot; and &quot;dir&quot; in the general preferences.


== File System Object ==

The &quot;file&quot; module would conform to the File System API, as well as objects returned by &quot;chroot&quot;.  There is no definitive implementation of a FileSystem class, so &quot;chroot&quot; is the only way to construct new objects that conform to the FileSystem API.  In permissive environments, the &quot;file&quot; module may have direct access to ambient authority through a foreign function interface, or may itself be a dynamically loaded module.  In secured environments, the &quot;file&quot; module must copy the properties of &quot;environment.fs&quot; onto its exports.

In a secure sandbox, the following statements would be equivalent.

 require('file').open(foo)
 environment.fs.open(foo)

Since &quot;fs&quot; must be frozen to be secure, there is no need for the &quot;file&quot; module to assemble aparatus for late binding to &quot;fs&quot; methods.

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland
*** (Python: os.path.exists, Ruby: exist?, exists?, Java: exists, JSExt: access, Spidermonkey: Helma: v8cgi: JSExt: EJScript: Synchronet: exists, jslibs: exist)

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.path.lexists)

* moves a file from a source to a target path.  Both paths are joined on the current working directory.
** move(source, target):
** (Ruby: move, Python: shutil.move, Java: File.renameTo)

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal
** (Ruby: rename)

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
** (Ruby: copy, systemCopy, Python: copy, Unix: cp)

* copies a file and its recursive contents to a target path.  Both paths are joined on the current working directory.  If &quot;synbolicLinks&quot; is truthy, symbolic links in the source tree are represented as symbolic links in the new tree; if falsy, the contents of the linked files are copied to the new tree.  If ignore is given, it must be a relation that will receive as its arguments the directory being visited by copytree(), and a list of its contents. Since this is called recursively (or walking an equivalent iteration), the ignore relation will be called once for each directory that is copied. The relation must return a sequence of directory and file names relative to the current directory (i.e. a subset of the items in its second argument); these names will then be ignored in the copy process.
** copyTree(source, target, symbolicLinks = false, ignore = undefined)
** copy(source, target, &quot;recursive&quot;)
** copy(source, target, true)
** (Python: copytree)

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente
** (Unix: mkdir)

* creates recursive directories.  Makes all intermediate-level directories needed to contain the leaf directory. Throws an exception if the leaf directory already exists or cannot be created. The default mode is 0777 (octal). On some systems, mode is ignored. Where it is used, the current umask value is first masked out.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;recursive&quot;):
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)
** makeTree(path)
** (Unix: mkdir -p, Ruby: makedirs, mkpath, Python: os.makedirs) 

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland
** (Ruby: unlink, delete, Python: unlink, remove, Java: delete, Posix: unlink, Unix: rm, Spidermonkey: Helma: EJScript: Synchronet: remove, jslibs: Delete)

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)
** removeTree(path, ignoreErrors = false, onError = undefined)
** (Unix: rm -r, Python: rmtree)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested
** (Python: link, Ruby: link, Unix: ln)

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)
** (Ruby: symlink, Python: symlink, Unix: ln -s)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland
** (Java: createNewFile, Posix: creat, Unix: touch)

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
** omit entirely:
*** Kris Kowal
** (Ruby: truncate, Python: ftruncate applies to open files only)

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
*** Wes Garland
** update(path, stat):
** chstat(path, stat):
** setStat(path, stat):
** restat(path, stat):
** (a low-level alternative to Python's copy2 and copyStat)

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal
** (Unix: touch)

* locks the file at a given path with either an exclusive or shared advisory lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal
** lock(path, &quot;rw|&quot;)
** (Posix: lock, Python: lock)

* attempts to acquire an advisory lock a file at a given path but does not block.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
*** Wes Garland
** tryLock(path, &quot;shared|exclusive&quot;):
** lock(path, &quot;rw&quot;)
** (Python: lock)

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)
** lock(path, &quot;u&quot;)
** (Python: lock)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente
** (Python: os.stat, Ruby: File.stat, Posix: stat)

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.lstat, Ruby: File.lstat)

* returns the size of the corresponding file.
** size(path)
** (Python: size, Ruby: size?: Java: length, Posix: st_size)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.  The given permissions object may be a Unix numeric representation of permissions, a Stat object, or any object that provides the members of Stat regarding permissions.
** open(path, &quot;+arwxc&quot;, permissions, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)
** (Java: FileStream classes, Python: open, file, Ruby: File.new, universal precedent among SSJS frameworks)
** open([path,] {[path: path,] mode: &quot;+arxwc&quot;, permissions: permissions, encoding: encoding})&lt;br&gt;(keyword-style parameters, first parameter is path or keyword object containing path)
*** Aristid Breitkreuz

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)
** (Python: os.listdir, Ruby: Dir)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)
** (Ruby: Dir[])

* returns whether a given path matches a glob pattern.
** match(pattern, path)
** (Ruby: fnmatch)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem object.

* a string directing a path up to the parent of the current directory, usually '..'.
** PARENT
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)
** (Python: pardir)

* a string directing a path back to itself, usually '.'.
** SELF
** (Python: curdir)

* a string that contains the path separator, usually '/', '\', or ':'.
** SEPARATOR
** (Python: sep, Spidermonkey: separator, Ruby: SEPARATOR, Separator)

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** ALTERNATE_SEPARATOR
** (Python: altsep, Ruby: ALT_SEPARATOR)

* a string that contains the extension separator, usually '.'.
** EXTENSION_SEPRATOR
** (Python: extsep)

* whether the file system supports unicode file names
** SUPPORTS_UNICODE_FILE_NAMES

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)
** (not precedented)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland
** (Python: Unix: dirname)

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland
** (Python: Unix: basename)

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland
** (Ruby: extname)

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)
** (Python: normpath)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to epxanding any user directory alias, joining the path to the current working directory, and normalizing the result.
** absolute(path)
** (Python: abspath)

* returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding an user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.
** canonical(path)
** (Python: realpath)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)
** (Python: isabs)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)


== Stat Object ==

* the Date that the file was last accessed.
** atime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastAccessed:
*** Kris Kowal
** (Python: getatime, Ruby: atime)

* the Date that the file was last modified.
** mtime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastModified:
*** Kris Kowal
*** Mario Valente
** (Python: getmtime, Ruby: mtime, Java: Spidermonkey: Helma: lastModified, jslibs: modifyTime, EJScript: modified, Synchronet: date)

* the Date that the file's stat/metadata was last modified.
** ctime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** (Ruby: ctime, Python: getctime)

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:
** omit entirely:
*** Kris Kowal
** (Spidermonkey: jslibs: creationTime, EJScript: create)

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** omit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory
** (Spidermonkey: isDir, Helma: isDir, JSExt: isdir)

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** omit entirely:
*** Wes Garland
*** Ondrej Zara

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size
*** Ondrej Zara
** (jslibs: size, Helma: getLength, Spidermonkey: wxJS: EJScript: Synchronet: length)

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner
** setuid

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner
** setgid

* whether the corresponding directory will permit anyone to create files in it, but only let the owner of a file delete it.
** sticky

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  


== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()
** (Python: JSExt: readline, Spidermonkey: Helma: Synchronet: readln)

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()
** (Python: readlines, JSExt: readlines, EJScript: getLines)

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)
** (universal precedent)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()
** (wxJS: JSExt: Python: Ruby: tell)

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)
** (Ruby: truncate, Python: ftruncate)

* returns whether the cursor is at the end of the IO stream.
** eof()
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** (Helma: wxJS: JSExt: Synchronet: eof)

* flushes buffers for an IO stream
** flush()
** (universal precedent)

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)
** (related to isOpen in many existing SSJS frameworks, but without a race condition hazard)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= General Preferences =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
#** Ondrej Zara
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#** Ondrej Zara
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#** Ondrej Zara
#** George Moschovitis
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#** expand:
#*** Ondrej Zara
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#** normalize:
#*** Ondrej Zara
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
#** Ondrej Zara
#** George Moschovitis
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#** Ondrej Zara
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal


= References =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>75</id>
      <timestamp>2009-04-07T23:39:08Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Supported open with options</comment>
      <text xml:space="preserve">= API and Proposed Names =

The following sections are organized with a bullet point per function.  Each point includes a specification for the behavior of a given method, intended to be suitable for documentation.  Under each definition is a list of potential names for that function, and in bullets beneath that, everyone is encouraged to write their name under their preference.  Please feel to leave comments as well.

In the next section, &quot;General Preferences&quot;, there are several broad sweeping points about whether to use certain conventions in a consistent fashion.  All of the name options are intended to conform to the prevalent opinion among those elections.  For example, &quot;make&quot; and &quot;create&quot; and &quot;dir&quot; and &quot;directory&quot; are both general preference elections, so if you would prefer &quot;makeDir&quot; over &quot;createDirectory&quot;, please vote independently for &quot;make&quot; and &quot;dir&quot; in the general preferences.


== File System Object ==

The &quot;file&quot; module would conform to the File System API, as well as objects returned by &quot;chroot&quot;.  There is no definitive implementation of a FileSystem class, so &quot;chroot&quot; is the only way to construct new objects that conform to the FileSystem API.  In permissive environments, the &quot;file&quot; module may have direct access to ambient authority through a foreign function interface, or may itself be a dynamically loaded module.  In secured environments, the &quot;file&quot; module must copy the properties of &quot;environment.fs&quot; onto its exports.

In a secure sandbox, the following statements would be equivalent.

 require('file').open(foo)
 environment.fs.open(foo)

Since &quot;fs&quot; must be frozen to be secure, there is no need for the &quot;file&quot; module to assemble aparatus for late binding to &quot;fs&quot; methods.

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland
*** (Python: os.path.exists, Ruby: exist?, exists?, Java: exists, JSExt: access, Spidermonkey: Helma: v8cgi: JSExt: EJScript: Synchronet: exists, jslibs: exist)

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.path.lexists)

* moves a file from a source to a target path.  Both paths are joined on the current working directory.
** move(source, target):
** (Ruby: move, Python: shutil.move, Java: File.renameTo)

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal
** (Ruby: rename)

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
** (Ruby: copy, systemCopy, Python: copy, Unix: cp)

* copies a file and its recursive contents to a target path.  Both paths are joined on the current working directory.  If &quot;synbolicLinks&quot; is truthy, symbolic links in the source tree are represented as symbolic links in the new tree; if falsy, the contents of the linked files are copied to the new tree.  If ignore is given, it must be a relation that will receive as its arguments the directory being visited by copytree(), and a list of its contents. Since this is called recursively (or walking an equivalent iteration), the ignore relation will be called once for each directory that is copied. The relation must return a sequence of directory and file names relative to the current directory (i.e. a subset of the items in its second argument); these names will then be ignored in the copy process.
** copyTree(source, target, symbolicLinks = false, ignore = undefined)
** copy(source, target, &quot;recursive&quot;)
** copy(source, target, true)
** (Python: copytree)

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente
** (Unix: mkdir)

* creates recursive directories.  Makes all intermediate-level directories needed to contain the leaf directory. Throws an exception if the leaf directory already exists or cannot be created. The default mode is 0777 (octal). On some systems, mode is ignored. Where it is used, the current umask value is first masked out.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;recursive&quot;):
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)
** makeTree(path)
** (Unix: mkdir -p, Ruby: makedirs, mkpath, Python: os.makedirs) 

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland
** (Ruby: unlink, delete, Python: unlink, remove, Java: delete, Posix: unlink, Unix: rm, Spidermonkey: Helma: EJScript: Synchronet: remove, jslibs: Delete)

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)
** removeTree(path, ignoreErrors = false, onError = undefined)
** (Unix: rm -r, Python: rmtree)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested
** (Python: link, Ruby: link, Unix: ln)

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)
** (Ruby: symlink, Python: symlink, Unix: ln -s)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland
** (Java: createNewFile, Posix: creat, Unix: touch)

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
** omit entirely:
*** Kris Kowal
** (Ruby: truncate, Python: ftruncate applies to open files only)

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
*** Wes Garland
** update(path, stat):
** chstat(path, stat):
** setStat(path, stat):
** restat(path, stat):
** (a low-level alternative to Python's copy2 and copyStat)

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal
** (Unix: touch)

* locks the file at a given path with either an exclusive or shared advisory lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal
** lock(path, &quot;rw|&quot;)
** (Posix: lock, Python: lock)

* attempts to acquire an advisory lock a file at a given path but does not block.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
*** Wes Garland
** tryLock(path, &quot;shared|exclusive&quot;):
** lock(path, &quot;rw&quot;)
** (Python: lock)

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)
** lock(path, &quot;u&quot;)
** (Python: lock)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente
** (Python: os.stat, Ruby: File.stat, Posix: stat)

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.lstat, Ruby: File.lstat)

* returns the size of the corresponding file.
** size(path)
** (Python: size, Ruby: size?: Java: length, Posix: st_size)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.  The given permissions object may be a Unix numeric representation of permissions, a Stat object, or any object that provides the members of Stat regarding permissions.
** open(path, &quot;+arwxc&quot;, permissions, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)
** (Java: FileStream classes, Python: open, file, Ruby: File.new, universal precedent among SSJS frameworks)
** open([path,] [mode,] {[path: path,] mode: &quot;+arxwc&quot;, permissions: permissions, encoding: encoding})&lt;br&gt;(keyword-style parameters, first parameter is path or keyword object containing path)
*** Aristid Breitkreuz
*** Kris Kowal

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)
** (Python: os.listdir, Ruby: Dir)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)
** (Ruby: Dir[])

* returns whether a given path matches a glob pattern.
** match(pattern, path)
** (Ruby: fnmatch)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem object.

* a string directing a path up to the parent of the current directory, usually '..'.
** PARENT
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)
** (Python: pardir)

* a string directing a path back to itself, usually '.'.
** SELF
** (Python: curdir)

* a string that contains the path separator, usually '/', '\', or ':'.
** SEPARATOR
** (Python: sep, Spidermonkey: separator, Ruby: SEPARATOR, Separator)

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** ALTERNATE_SEPARATOR
** (Python: altsep, Ruby: ALT_SEPARATOR)

* a string that contains the extension separator, usually '.'.
** EXTENSION_SEPRATOR
** (Python: extsep)

* whether the file system supports unicode file names
** SUPPORTS_UNICODE_FILE_NAMES

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)
** (not precedented)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland
** (Python: Unix: dirname)

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland
** (Python: Unix: basename)

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland
** (Ruby: extname)

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)
** (Python: normpath)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to epxanding any user directory alias, joining the path to the current working directory, and normalizing the result.
** absolute(path)
** (Python: abspath)

* returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding an user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.
** canonical(path)
** (Python: realpath)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)
** (Python: isabs)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)


== Stat Object ==

* the Date that the file was last accessed.
** atime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastAccessed:
*** Kris Kowal
** (Python: getatime, Ruby: atime)

* the Date that the file was last modified.
** mtime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastModified:
*** Kris Kowal
*** Mario Valente
** (Python: getmtime, Ruby: mtime, Java: Spidermonkey: Helma: lastModified, jslibs: modifyTime, EJScript: modified, Synchronet: date)

* the Date that the file's stat/metadata was last modified.
** ctime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** (Ruby: ctime, Python: getctime)

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:
** omit entirely:
*** Kris Kowal
** (Spidermonkey: jslibs: creationTime, EJScript: create)

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** omit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory
** (Spidermonkey: isDir, Helma: isDir, JSExt: isdir)

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** omit entirely:
*** Wes Garland
*** Ondrej Zara

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size
*** Ondrej Zara
** (jslibs: size, Helma: getLength, Spidermonkey: wxJS: EJScript: Synchronet: length)

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner
** setuid

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner
** setgid

* whether the corresponding directory will permit anyone to create files in it, but only let the owner of a file delete it.
** sticky

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  


== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()
** (Python: JSExt: readline, Spidermonkey: Helma: Synchronet: readln)

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()
** (Python: readlines, JSExt: readlines, EJScript: getLines)

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)
** (universal precedent)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()
** (wxJS: JSExt: Python: Ruby: tell)

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)
** (Ruby: truncate, Python: ftruncate)

* returns whether the cursor is at the end of the IO stream.
** eof()
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** (Helma: wxJS: JSExt: Synchronet: eof)

* flushes buffers for an IO stream
** flush()
** (universal precedent)

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)
** (related to isOpen in many existing SSJS frameworks, but without a race condition hazard)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= General Preferences =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
#** Ondrej Zara
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#** Ondrej Zara
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#** Ondrej Zara
#** George Moschovitis
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#** expand:
#*** Ondrej Zara
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#** normalize:
#*** Ondrej Zara
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
#** Ondrej Zara
#** George Moschovitis
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#** Ondrej Zara
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal


= References =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>76</id>
      <timestamp>2009-04-16T07:08:38Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Noted Kevin's elections for mkdir and mkdirs (by way of him having implemented them in Narwhal by those names)</comment>
      <text xml:space="preserve">= API and Proposed Names =

The following sections are organized with a bullet point per function.  Each point includes a specification for the behavior of a given method, intended to be suitable for documentation.  Under each definition is a list of potential names for that function, and in bullets beneath that, everyone is encouraged to write their name under their preference.  Please feel to leave comments as well.

In the next section, &quot;General Preferences&quot;, there are several broad sweeping points about whether to use certain conventions in a consistent fashion.  All of the name options are intended to conform to the prevalent opinion among those elections.  For example, &quot;make&quot; and &quot;create&quot; and &quot;dir&quot; and &quot;directory&quot; are both general preference elections, so if you would prefer &quot;makeDir&quot; over &quot;createDirectory&quot;, please vote independently for &quot;make&quot; and &quot;dir&quot; in the general preferences.


== File System Object ==

The &quot;file&quot; module would conform to the File System API, as well as objects returned by &quot;chroot&quot;.  There is no definitive implementation of a FileSystem class, so &quot;chroot&quot; is the only way to construct new objects that conform to the FileSystem API.  In permissive environments, the &quot;file&quot; module may have direct access to ambient authority through a foreign function interface, or may itself be a dynamically loaded module.  In secured environments, the &quot;file&quot; module must copy the properties of &quot;environment.fs&quot; onto its exports.

In a secure sandbox, the following statements would be equivalent.

 require('file').open(foo)
 environment.fs.open(foo)

Since &quot;fs&quot; must be frozen to be secure, there is no need for the &quot;file&quot; module to assemble aparatus for late binding to &quot;fs&quot; methods.

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland
*** (Python: os.path.exists, Ruby: exist?, exists?, Java: exists, JSExt: access, Spidermonkey: Helma: v8cgi: JSExt: EJScript: Synchronet: exists, jslibs: exist)

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.path.lexists)

* moves a file from a source to a target path.  Both paths are joined on the current working directory.
** move(source, target):
** (Ruby: move, Python: shutil.move, Java: File.renameTo)

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal
** (Ruby: rename)

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
** (Ruby: copy, systemCopy, Python: copy, Unix: cp)

* copies a file and its recursive contents to a target path.  Both paths are joined on the current working directory.  If &quot;synbolicLinks&quot; is truthy, symbolic links in the source tree are represented as symbolic links in the new tree; if falsy, the contents of the linked files are copied to the new tree.  If ignore is given, it must be a relation that will receive as its arguments the directory being visited by copytree(), and a list of its contents. Since this is called recursively (or walking an equivalent iteration), the ignore relation will be called once for each directory that is copied. The relation must return a sequence of directory and file names relative to the current directory (i.e. a subset of the items in its second argument); these names will then be ignored in the copy process.
** copyTree(source, target, symbolicLinks = false, ignore = undefined)
** copy(source, target, &quot;recursive&quot;)
** copy(source, target, true)
** (Python: copytree)

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente
** mkdir(path)
*** Kevin Dangoor
** (Unix: mkdir)

* creates recursive directories.  Makes all intermediate-level directories needed to contain the leaf directory. Throws an exception if the leaf directory already exists or cannot be created. The default mode is 0777 (octal). On some systems, mode is ignored. Where it is used, the current umask value is first masked out.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;recursive&quot;):
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)
** makeTree(path)
** (Unix: mkdir -p, Ruby: makedirs, mkpath, Python: os.makedirs) 
** mkdirs(path)
*** Kevin Dangoor

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland
** (Ruby: unlink, delete, Python: unlink, remove, Java: delete, Posix: unlink, Unix: rm, Spidermonkey: Helma: EJScript: Synchronet: remove, jslibs: Delete)

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)
** removeTree(path, ignoreErrors = false, onError = undefined)
** (Unix: rm -r, Python: rmtree)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested
** (Python: link, Ruby: link, Unix: ln)

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)
** (Ruby: symlink, Python: symlink, Unix: ln -s)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland
** (Java: createNewFile, Posix: creat, Unix: touch)

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
** omit entirely:
*** Kris Kowal
** (Ruby: truncate, Python: ftruncate applies to open files only)

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
*** Wes Garland
** update(path, stat):
** chstat(path, stat):
** setStat(path, stat):
** restat(path, stat):
** (a low-level alternative to Python's copy2 and copyStat)

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal
** (Unix: touch)

* locks the file at a given path with either an exclusive or shared advisory lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal
** lock(path, &quot;rw|&quot;)
** (Posix: lock, Python: lock)

* attempts to acquire an advisory lock a file at a given path but does not block.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
*** Wes Garland
** tryLock(path, &quot;shared|exclusive&quot;):
** lock(path, &quot;rw&quot;)
** (Python: lock)

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)
** lock(path, &quot;u&quot;)
** (Python: lock)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente
** (Python: os.stat, Ruby: File.stat, Posix: stat)

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.lstat, Ruby: File.lstat)

* returns the size of the corresponding file.
** size(path)
** (Python: size, Ruby: size?: Java: length, Posix: st_size)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.  The given permissions object may be a Unix numeric representation of permissions, a Stat object, or any object that provides the members of Stat regarding permissions.
** open(path, &quot;+arwxc&quot;, permissions, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)
** (Java: FileStream classes, Python: open, file, Ruby: File.new, universal precedent among SSJS frameworks)
** open([path,] [mode,] {[path: path,] mode: &quot;+arxwc&quot;, permissions: permissions, encoding: encoding})&lt;br&gt;(keyword-style parameters, first parameter is path or keyword object containing path)
*** Aristid Breitkreuz
*** Kris Kowal

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)
** (Python: os.listdir, Ruby: Dir)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)
** (Ruby: Dir[])

* returns whether a given path matches a glob pattern.
** match(pattern, path)
** (Ruby: fnmatch)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)


== Paths ==

More properites of a FileSystem object.

* a string directing a path up to the parent of the current directory, usually '..'.
** PARENT
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)
** (Python: pardir)

* a string directing a path back to itself, usually '.'.
** SELF
** (Python: curdir)

* a string that contains the path separator, usually '/', '\', or ':'.
** SEPARATOR
** (Python: sep, Spidermonkey: separator, Ruby: SEPARATOR, Separator)

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** ALTERNATE_SEPARATOR
** (Python: altsep, Ruby: ALT_SEPARATOR)

* a string that contains the extension separator, usually '.'.
** EXTENSION_SEPRATOR
** (Python: extsep)

* whether the file system supports unicode file names
** SUPPORTS_UNICODE_FILE_NAMES

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)
** (not precedented)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland
** (Python: Unix: dirname)

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland
** (Python: Unix: basename)

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland
** (Ruby: extname)

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)
** (Python: normpath)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to epxanding any user directory alias, joining the path to the current working directory, and normalizing the result.
** absolute(path)
** (Python: abspath)

* returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding an user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.
** canonical(path)
** (Python: realpath)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)
** (Python: isabs)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)


== Stat Object ==

* the Date that the file was last accessed.
** atime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastAccessed:
*** Kris Kowal
** (Python: getatime, Ruby: atime)

* the Date that the file was last modified.
** mtime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastModified:
*** Kris Kowal
*** Mario Valente
** (Python: getmtime, Ruby: mtime, Java: Spidermonkey: Helma: lastModified, jslibs: modifyTime, EJScript: modified, Synchronet: date)

* the Date that the file's stat/metadata was last modified.
** ctime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** (Ruby: ctime, Python: getctime)

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:
** omit entirely:
*** Kris Kowal
** (Spidermonkey: jslibs: creationTime, EJScript: create)

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** omit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory
** (Spidermonkey: isDir, Helma: isDir, JSExt: isdir)

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** omit entirely:
*** Wes Garland
*** Ondrej Zara

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size
*** Ondrej Zara
** (jslibs: size, Helma: getLength, Spidermonkey: wxJS: EJScript: Synchronet: length)

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner
** setuid

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner
** setgid

* whether the corresponding directory will permit anyone to create files in it, but only let the owner of a file delete it.
** sticky

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  


== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()
** (Python: JSExt: readline, Spidermonkey: Helma: Synchronet: readln)

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()
** (Python: readlines, JSExt: readlines, EJScript: getLines)

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)
** (universal precedent)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()
** (wxJS: JSExt: Python: Ruby: tell)

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)
** (Ruby: truncate, Python: ftruncate)

* returns whether the cursor is at the end of the IO stream.
** eof()
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** (Helma: wxJS: JSExt: Synchronet: eof)

* flushes buffers for an IO stream
** flush()
** (universal precedent)

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)
** (related to isOpen in many existing SSJS frameworks, but without a race condition hazard)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= General Preferences =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
#** Ondrej Zara
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#** Ondrej Zara
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#** Ondrej Zara
#** George Moschovitis
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#** expand:
#*** Ondrej Zara
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#** normalize:
#*** Ondrej Zara
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
#** Ondrej Zara
#** George Moschovitis
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#** Ondrej Zara
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal


= References =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>77</id>
      <timestamp>2009-04-24T19:52:58Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>/* File System Object */ purged use of &quot;environment&quot; name.</comment>
      <text xml:space="preserve">= API and Proposed Names =

The following sections are organized with a bullet point per function.  Each point includes a specification for the behavior of a given method, intended to be suitable for documentation.  Under each definition is a list of potential names for that function, and in bullets beneath that, everyone is encouraged to write their name under their preference.  Please feel to leave comments as well.

In the next section, &quot;General Preferences&quot;, there are several broad sweeping points about whether to use certain conventions in a consistent fashion.  All of the name options are intended to conform to the prevalent opinion among those elections.  For example, &quot;make&quot; and &quot;create&quot; and &quot;dir&quot; and &quot;directory&quot; are both general preference elections, so if you would prefer &quot;makeDir&quot; over &quot;createDirectory&quot;, please vote independently for &quot;make&quot; and &quot;dir&quot; in the general preferences.


== File System Object ==

The &quot;file&quot; module would conform to the File System API, as well as objects returned by &quot;chroot&quot;.  There is no definitive implementation of a FileSystem class, so &quot;chroot&quot; is the only way to construct new objects that conform to the FileSystem API.  In permissive platforms, the &quot;file&quot; module may have direct access to ambient authority through a foreign function interface, or may itself be a dynamically loaded module.  In secured platform, the &quot;file&quot; module must copy the properties of &quot;system.fs&quot; onto its exports.

In a secure sandbox, the following statements would be equivalent.

 require('file').open(foo)
 system.fs.open(foo)

Since &quot;fs&quot; must be frozen to be secure, there is no need for the &quot;file&quot; module to assemble aparatus for late binding to &quot;fs&quot; methods.

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland
*** (Python: os.path.exists, Ruby: exist?, exists?, Java: exists, JSExt: access, Spidermonkey: Helma: v8cgi: JSExt: EJScript: Synchronet: exists, jslibs: exist)

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.path.lexists)

* moves a file from a source to a target path.  Both paths are joined on the current working directory.
** move(source, target):
** (Ruby: move, Python: shutil.move, Java: File.renameTo)

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal
** (Ruby: rename)

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
** (Ruby: copy, systemCopy, Python: copy, Unix: cp)

* copies a file and its recursive contents to a target path.  Both paths are joined on the current working directory.  If &quot;synbolicLinks&quot; is truthy, symbolic links in the source tree are represented as symbolic links in the new tree; if falsy, the contents of the linked files are copied to the new tree.  If ignore is given, it must be a relation that will receive as its arguments the directory being visited by copytree(), and a list of its contents. Since this is called recursively (or walking an equivalent iteration), the ignore relation will be called once for each directory that is copied. The relation must return a sequence of directory and file names relative to the current directory (i.e. a subset of the items in its second argument); these names will then be ignored in the copy process.
** copyTree(source, target, symbolicLinks = false, ignore = undefined)
** copy(source, target, &quot;recursive&quot;)
** copy(source, target, true)
** (Python: copytree)

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente
** mkdir(path)
*** Kevin Dangoor
** (Unix: mkdir)

* creates recursive directories.  Makes all intermediate-level directories needed to contain the leaf directory. Throws an exception if the leaf directory already exists or cannot be created. The default mode is 0777 (octal). On some systems, mode is ignored. Where it is used, the current umask value is first masked out.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;recursive&quot;):
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)
** makeTree(path)
** (Unix: mkdir -p, Ruby: makedirs, mkpath, Python: os.makedirs) 
** mkdirs(path)
*** Kevin Dangoor

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland
** (Ruby: unlink, delete, Python: unlink, remove, Java: delete, Posix: unlink, Unix: rm, Spidermonkey: Helma: EJScript: Synchronet: remove, jslibs: Delete)

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)
** removeTree(path, ignoreErrors = false, onError = undefined)
** (Unix: rm -r, Python: rmtree)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested
** (Python: link, Ruby: link, Unix: ln)

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)
** (Ruby: symlink, Python: symlink, Unix: ln -s)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland
** (Java: createNewFile, Posix: creat, Unix: touch)

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
** omit entirely:
*** Kris Kowal
** (Ruby: truncate, Python: ftruncate applies to open files only)

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
*** Wes Garland
** update(path, stat):
** chstat(path, stat):
** setStat(path, stat):
** restat(path, stat):
** (a low-level alternative to Python's copy2 and copyStat)

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal
** (Unix: touch)

* locks the file at a given path with either an exclusive or shared advisory lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal
** lock(path, &quot;rw|&quot;)
** (Posix: lock, Python: lock)

* attempts to acquire an advisory lock a file at a given path but does not block.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
*** Wes Garland
** tryLock(path, &quot;shared|exclusive&quot;):
** lock(path, &quot;rw&quot;)
** (Python: lock)

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)
** lock(path, &quot;u&quot;)
** (Python: lock)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente
** (Python: os.stat, Ruby: File.stat, Posix: stat)

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.lstat, Ruby: File.lstat)

* returns the size of the corresponding file.
** size(path)
** (Python: size, Ruby: size?: Java: length, Posix: st_size)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.  The given permissions object may be a Unix numeric representation of permissions, a Stat object, or any object that provides the members of Stat regarding permissions.
** open(path, &quot;+arwxc&quot;, permissions, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)
** (Java: FileStream classes, Python: open, file, Ruby: File.new, universal precedent among SSJS frameworks)
** open([path,] [mode,] {[path: path,] mode: &quot;+arxwc&quot;, permissions: permissions, encoding: encoding})&lt;br&gt;(keyword-style parameters, first parameter is path or keyword object containing path)
*** Aristid Breitkreuz
*** Kris Kowal

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)
** (Python: os.listdir, Ruby: Dir)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)
** (Ruby: Dir[])

* returns whether a given path matches a glob pattern.
** match(pattern, path)
** (Ruby: fnmatch)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)

== Paths ==

More properites of a FileSystem object.

* a string directing a path up to the parent of the current directory, usually '..'.
** PARENT
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)
** (Python: pardir)

* a string directing a path back to itself, usually '.'.
** SELF
** (Python: curdir)

* a string that contains the path separator, usually '/', '\', or ':'.
** SEPARATOR
** (Python: sep, Spidermonkey: separator, Ruby: SEPARATOR, Separator)

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** ALTERNATE_SEPARATOR
** (Python: altsep, Ruby: ALT_SEPARATOR)

* a string that contains the extension separator, usually '.'.
** EXTENSION_SEPRATOR
** (Python: extsep)

* whether the file system supports unicode file names
** SUPPORTS_UNICODE_FILE_NAMES

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)
** (not precedented)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland
** (Python: Unix: dirname)

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland
** (Python: Unix: basename)

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland
** (Ruby: extname)

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)
** (Python: normpath)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to epxanding any user directory alias, joining the path to the current working directory, and normalizing the result.
** absolute(path)
** (Python: abspath)

* returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding an user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.
** canonical(path)
** (Python: realpath)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)
** (Python: isabs)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)


== Stat Object ==

* the Date that the file was last accessed.
** atime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastAccessed:
*** Kris Kowal
** (Python: getatime, Ruby: atime)

* the Date that the file was last modified.
** mtime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastModified:
*** Kris Kowal
*** Mario Valente
** (Python: getmtime, Ruby: mtime, Java: Spidermonkey: Helma: lastModified, jslibs: modifyTime, EJScript: modified, Synchronet: date)

* the Date that the file's stat/metadata was last modified.
** ctime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastChanged:
*** Wes Garland
** lastStatModified:
*** Kris Kowal
** (Ruby: ctime, Python: getctime)

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:
** omit entirely:
*** Kris Kowal
** (Spidermonkey: jslibs: creationTime, EJScript: create)

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** omit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory
** (Spidermonkey: isDir, Helma: isDir, JSExt: isdir)

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** omit entirely:
*** Wes Garland
*** Ondrej Zara

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size
*** Ondrej Zara
** (jslibs: size, Helma: getLength, Spidermonkey: wxJS: EJScript: Synchronet: length)

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner
** setuid

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner
** setgid

* whether the corresponding directory will permit anyone to create files in it, but only let the owner of a file delete it.
** sticky

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  


== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()
** (Python: JSExt: readline, Spidermonkey: Helma: Synchronet: readln)

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()
** (Python: readlines, JSExt: readlines, EJScript: getLines)

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)
** (universal precedent)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()
** (wxJS: JSExt: Python: Ruby: tell)

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)
** (Ruby: truncate, Python: ftruncate)

* returns whether the cursor is at the end of the IO stream.
** eof()
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** (Helma: wxJS: JSExt: Synchronet: eof)

* flushes buffers for an IO stream
** flush()
** (universal precedent)

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)
** (related to isOpen in many existing SSJS frameworks, but without a race condition hazard)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= General Preferences =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
#** Ondrej Zara
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#** Ondrej Zara
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#** Ondrej Zara
#** George Moschovitis
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#** expand:
#*** Ondrej Zara
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#** normalize:
#*** Ondrej Zara
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
#** Ondrej Zara
#** George Moschovitis
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#** Ondrej Zara
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal


= References =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>78</id>
      <timestamp>2009-04-28T18:57:15Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Noted Daniel Friessen's election of lastModified.</comment>
      <text xml:space="preserve">= API and Proposed Names =

The following sections are organized with a bullet point per function.  Each point includes a specification for the behavior of a given method, intended to be suitable for documentation.  Under each definition is a list of potential names for that function, and in bullets beneath that, everyone is encouraged to write their name under their preference.  Please feel to leave comments as well.

In the next section, &quot;General Preferences&quot;, there are several broad sweeping points about whether to use certain conventions in a consistent fashion.  All of the name options are intended to conform to the prevalent opinion among those elections.  For example, &quot;make&quot; and &quot;create&quot; and &quot;dir&quot; and &quot;directory&quot; are both general preference elections, so if you would prefer &quot;makeDir&quot; over &quot;createDirectory&quot;, please vote independently for &quot;make&quot; and &quot;dir&quot; in the general preferences.


== File System Object ==

The &quot;file&quot; module would conform to the File System API, as well as objects returned by &quot;chroot&quot;.  There is no definitive implementation of a FileSystem class, so &quot;chroot&quot; is the only way to construct new objects that conform to the FileSystem API.  In permissive platforms, the &quot;file&quot; module may have direct access to ambient authority through a foreign function interface, or may itself be a dynamically loaded module.  In secured platform, the &quot;file&quot; module must copy the properties of &quot;system.fs&quot; onto its exports.

In a secure sandbox, the following statements would be equivalent.

 require('file').open(foo)
 system.fs.open(foo)

Since &quot;fs&quot; must be frozen to be secure, there is no need for the &quot;file&quot; module to assemble aparatus for late binding to &quot;fs&quot; methods.

* whether a file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file that exists.  If the file is a broken symbolic link, returns false.
** exists(path):
*** Kris Kowal
*** Wes Garland
*** (Python: os.path.exists, Ruby: exist?, exists?, Java: exists, JSExt: access, Spidermonkey: Helma: v8cgi: JSExt: EJScript: Synchronet: exists, jslibs: exist)

* whether a symbolic link or file exists at a given path: receives a path and returns whether that path, joined on the current working directory, corresponds to a file, albeit a broken symbolic link, that exists.
** exists(path, true):
*** Wes Garland
*** Mario Valente
** linkExists(path):
*** Kris Kowal
** exists(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.path.lexists)

* moves a file from a source to a target path.  Both paths are joined on the current working directory.
** move(source, target):
** (Ruby: move, Python: shutil.move, Java: File.renameTo)

* renames a file: receives two paths.  The first is a path, joined on the current working directory, that refers to the file to rename.  The second argument is a path relative to the former file's fully qualified path.
** rename(path, name):
** should not be included in the spec:
*** Kris Kowal
** (Ruby: rename)

* copies a file from a source to a target path.  Both paths are joined on the current working directory.
** copy(source, target):
** (Ruby: copy, systemCopy, Python: copy, Unix: cp)

* copies a file and its recursive contents to a target path.  Both paths are joined on the current working directory.  If &quot;synbolicLinks&quot; is truthy, symbolic links in the source tree are represented as symbolic links in the new tree; if falsy, the contents of the linked files are copied to the new tree.  If ignore is given, it must be a relation that will receive as its arguments the directory being visited by copytree(), and a list of its contents. Since this is called recursively (or walking an equivalent iteration), the ignore relation will be called once for each directory that is copied. The relation must return a sequence of directory and file names relative to the current directory (i.e. a subset of the items in its second argument); these names will then be ignored in the copy process.
** copyTree(source, target, symbolicLinks = false, ignore = undefined)
** copy(source, target, &quot;recursive&quot;)
** copy(source, target, true)
** (Python: copytree)

* makes a directory at a given path in the base directory implied by the given path.  Throws an exception if the base directory does not exist, or if the given path already exists.
** makeDirectory(path):
*** Kris Kowal
** createDirectory(path):
*** Mario Valente
** mkdir(path)
*** Kevin Dangoor
** (Unix: mkdir)

* creates recursive directories.  Makes all intermediate-level directories needed to contain the leaf directory. Throws an exception if the leaf directory already exists or cannot be created. The default mode is 0777 (octal). On some systems, mode is ignored. Where it is used, the current umask value is first masked out.
** makePath(path):
*** Kris Kowal
** makeDirectory(path, true):
*** Wes Garland
** makeDirectory(path, &quot;recursive&quot;):
** makeDirectory(path, &quot;path&quot;):
*** Kris Kowal (as a compromise)
** makeTree(path)
** (Unix: mkdir -p, Ruby: makedirs, mkpath, Python: os.makedirs) 
** mkdirs(path)
*** Kevin Dangoor

* removes a file.
** remove(path):
*** Kris Kowal
*** Tom Robinson
*** Kevin Dangoor
*** Wes Garland (as a compromise)
** unlink(path):
*** Wes Garland
** (Ruby: unlink, delete, Python: unlink, remove, Java: delete, Posix: unlink, Unix: rm, Spidermonkey: Helma: EJScript: Synchronet: remove, jslibs: Delete)

* removes a file or directory and its recursive contents.
** remove(path):
** remove(path, true):
** remove(path, &quot;recursive&quot;)
** removeRecursive(path)
** removeTree(path, ignoreErrors = false, onError = undefined)
** (Unix: rm -r, Python: rmtree)

* creates a hard link of the source path as the target path.  Both paths are joined on the current working directory.
** link(source, target):
*** uncontested
** (Python: link, Ruby: link, Unix: ln)

* creates a symbolic link on a given &quot;target&quot; file name.  The source path becomes the text of the symbolic link, which the underlying system will join on the containing directory when it's followed, while the target path is joined on the current working directory.
** symbolicLink(source, target):
*** Kris Kowal
** link(source, target, true):
*** Wes Garland
** link(source, target, &quot;symbolic&quot;):
*** Kris Kowal (as a compromise)
** (Ruby: symlink, Python: symlink, Unix: ln -s)

* creates an empty file at a given path in its implied base directory.  The path is resolved relative to the current working directory.  Accepts an optional ``Permissions`` object (or a duck-type thereof, or the, typically octal, numeric representation of permissions in Unix) that notes which permissions the file will be created with, assuming that those permissions are in the &quot;umask&quot;.
** create(path, [permissions]):
*** Mario Valente
** unnecessary:
*** Kris Kowal,
*** Wes Garland
** (Java: createNewFile, Posix: creat, Unix: touch)

* truncates a the file at a given path.  Accepts an optional length that default to zero.  The path is resolved on the current working directory.
** truncate(path, [length = 0]):
** omit entirely:
*** Kris Kowal
** (Ruby: truncate, Python: ftruncate applies to open files only)

* updates the stat/metadata of the file at a given path.  Accepts a stat object.  Implicitly updates the time that the file's metadata/stat was updated to the current time, regardless of the metadata modification time provided by the stat object.
*** Wes Garland
** update(path, stat):
** chstat(path, stat):
** setStat(path, stat):
** restat(path, stat):
** (a low-level alternative to Python's copy2 and copyStat)

* updates the modification time of the file at a given path.  Accepts an alternate modification time to set the file.  Also implicitly updates the time that the file's metadata/stat object was updated to the current time, regardless of the chosen modification time.
** touch(path, [date]):
*** Kris Kowal
** (Unix: touch)

* locks the file at a given path with either an exclusive or shared advisory lock.  The path is resolved on the current working directory.  Blocks until the lock is acquired, or if a timeout is defined, when that timeout occurs.
** lock(path, &quot;shared|exclusive&quot;, [timeout=undefined]):
*** Wes Garland
*** Kris Kowal
** lock(path, &quot;rw|&quot;)
** (Posix: lock, Python: lock)

* attempts to acquire an advisory lock a file at a given path but does not block.  The path is resolved relative to the current working directory.  Does not block if the file is not lockable.  Returns whether the lock was obtained.
*** Wes Garland
** tryLock(path, &quot;shared|exclusive&quot;):
** lock(path, &quot;rw&quot;)
** (Python: lock)

* releases a lock for a given path.
** unlock(path):
*** Kris Kowal
** lock(path, &quot;unlock&quot;)
** lock(path, &quot;u&quot;)
** (Python: lock)

* retrieves an object that represents the metadata of a distinct file, for a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path):
*** Mario Valente
** (Python: os.stat, Ruby: File.stat, Posix: stat)

* retrieves an object that represents the metadata of a distinct file or symbolic link to a file at a given path.  The path is resolved relative to the current working directory.  The returned object has the properties described in the Stat API.
** stat(path, true):
*** Wes Garland
** linkStat(path):
*** Kris Kowal
** stat(path, &quot;link&quot;):
*** Kris Kowal (as a compromise)
** (Python: os.lstat, Ruby: File.lstat)

* returns the size of the corresponding file.
** size(path)
** (Python: size, Ruby: size?: Java: length, Posix: st_size)

* returns the total size of a tree of files.
** size(path) // as a special case for a directory
** size(path, &quot;recursive&quot;)
** recursiveSize(path)

* returns an IO object for accessing or manipulating the data in a file at a given path.  The path is resolved relative to the current working directory.  The given permissions object may be a Unix numeric representation of permissions, a Stat object, or any object that provides the members of Stat regarding permissions.
** open(path, &quot;+arwxc&quot;, permissions, encoding):
*** Mario Valente
*** Kris Kowal
** Mode:
*** +, update
*** a, append
*** r, read
*** w, write
*** x, exclusive (lock)
*** c, canon (nonblocking)
** (Java: FileStream classes, Python: open, file, Ruby: File.new, universal precedent among SSJS frameworks)
** open([path,] [mode,] {[path: path,] mode: &quot;+arxwc&quot;, permissions: permissions, encoding: encoding})&lt;br&gt;(keyword-style parameters, first parameter is path or keyword object containing path)
*** Aristid Breitkreuz
*** Kris Kowal

* return a Dir object for a given directory path.  The path is resolved relative to the current working directory.  The Dir object is an bidirectional iterator of a snapshot of the contents of the directory, and may be either a lazy Array or genuine array, depending on whether the underlying implementation can retrieve indicies on demand.
** list(path)
** (Python: os.listdir, Ruby: Dir)

* returns an object that, like a Dir, supports the iterator protocol (next, prev) and the Array protocol (length, [index]) for all files that match a given glob pattern.
** The glob pattern may include any of the following productions:
*** ? - exactly one character in a path component
*** * - any number of characters in a path component
*** ** - any number of characters in a path
*** {a,b,c} - the letters a, b, or c, or any other union of paths.
** glob(pattern)
** (Ruby: Dir[])

* returns whether a given path matches a glob pattern.
** match(pattern, path)
** (Ruby: fnmatch)

* returns a new object that implements the file system API that uses the directory at the given path as its root.  Resolves the path relative to the current working directory.
** chroot(path)

== Paths ==

More properites of a FileSystem object.

* a string directing a path up to the parent of the current directory, usually '..'.
** PARENT
** (a function that gets an opaque reference to the actual parent node on the file system, as referenced by the directory's parent hard link, has been deliberately omitted to avoid leaking the capability to access that object from within a chroot file system)
** (Python: pardir)

* a string directing a path back to itself, usually '.'.
** SELF
** (Python: curdir)

* a string that contains the path separator, usually '/', '\', or ':'.
** SEPARATOR
** (Python: sep, Spidermonkey: separator, Ruby: SEPARATOR, Separator)

* a string that contains the alternate path separator, if it exists.  Otherwise, undefined.
** ALTERNATE_SEPARATOR
** (Python: altsep, Ruby: ALT_SEPARATOR)

* a string that contains the extension separator, usually '.'.
** EXTENSION_SEPRATOR
** (Python: extsep)

* whether the file system supports unicode file names
** SUPPORTS_UNICODE_FILE_NAMES

* accepts a variadic list of paths as arguments and follows each successive path from the current working directory, left to right, and returns the normalized path of the ultimate file or directory.  Paths that end with a directory separator refer to the contents of a directory as a place to continue resolving, whereas paths that do not end with a directory separator indicate that the next path should be followed from the directory containing that file.
** join([path, [path, [path, [...]]]])

* returns the path components for a given path
** split(path)

* takes a string and returns an escaped path component of that string, such that directory separators and other special characters do not partition it into multiple path components
** escape(string)
** (not precedented)

* returns the path of the directory containing a given path.
** dirName(path):
*** Kris Kowal
** dirname(path)
*** Wes Garland
** (Python: Unix: dirname)

* returns the last path component without its extension.  The extension begins after the first extension separator.
** baseName(path):
*** Kris Kowal
** basename(path):
*** Wes Garland
** (Python: Unix: basename)

* returns the extension of the given path.  The extension begins after the first extension separator.
** extension(path):
*** George Mosochovitis
*** Kris Kowal
*** Wes Garland
** (Ruby: extname)

* removes '.' path components and simplifies '..' paths, if possible for a given path.  If the file system is case sensitive, transforms all letters to lower-case to make them unambiguous.
** normal(path)
** (Python: normpath)

* returns the absolute path, starting with the root of this file system object, for the given path, resolved relative to the current working directory.  If the file system supports home directory aliases, absolute resolves those from the root of the file system.  The resulting path is in normal form.  On most systems, this is equivalent to epxanding any user directory alias, joining the path to the current working directory, and normalizing the result.
** absolute(path)
** (Python: abspath)

* returns the canonical path to a given abstract path.  Canonical paths are both absolute and intrinsic, such that all paths that refer to a given file (whether it exists or not) have the same corresponding canonical path.  This function may not communicate information about the true parent directories of files in chroot environments.  This function is equivalent to expanding an user directory alias, joining the given path to the current working directory, joining all symbolic links along the path, and normalizing the result.
** canonical(path)
** (Python: realpath)

* returns whether a given path has no self and parent path components.
** isNormal(path)

* returns whether the given path is normal and starts with the root of the file system.
** isAbsolute(path)
** (Python: isabs)

* returns whether the given path is the same as the corresponding cannonical path.
** isCanonical(path)

* returns whether the given paths both refer to the same intrinsic file.  Both paths are resolved relative to the working directory.
** same(path, path)


== Stat Object ==

* the Date that the file was last accessed.
** atime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastAccessed:
*** Kris Kowal
** (Python: getatime, Ruby: atime)

* the Date that the file was last modified.
** mtime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastModified:
*** Kris Kowal
*** Mario Valente
*** Daniel Friessen
** (Python: getmtime, Ruby: mtime, Java: Spidermonkey: Helma: lastModified, jslibs: modifyTime, EJScript: modified, Synchronet: date)

* the Date that the file's stat/metadata was last modified.
** ctime:
*** Tom Robinson
*** Kevin Dangoor
*** Ondrej Zara
** lastChanged:
*** Wes Garland
*** Kris Kowal
** (Ruby: ctime, Python: getctime)

* the Date that the file was created, if the underlying file system makes that datum available (most Unix systems do not store creation time, but Windows and some Unix varieties do).  Returns undefined if the underlying file system does not provide a time.
** created:
** creationTime:
** firstModified:
** omit entirely:
*** Kris Kowal
** (Spidermonkey: jslibs: creationTime, EJScript: create)

* a String name for the type of the file.  One of: &quot;file&quot;, &quot;directory&quot;, &quot;characterSpecial&quot;, &quot;blockSpecial&quot;, &quot;fifo&quot;, &quot;link&quot;, &quot;socket&quot;, or &quot;unknown&quot;
** type:
** kind:
** omit entirely:
*** Kris Kowal

* whether the corresponding object is a file (not a directory).
** isFile:
*** Kris Kowal

* whether the corresponding object is a directory
** isDirectory
** (Spidermonkey: isDir, Helma: isDir, JSExt: isdir)

* whether the corresponding object is a symbolic link
** isLink

* whether the corresponding object is a mount point
** isMountPoint:
** omit entirely:
*** Wes Garland
*** Ondrej Zara

* whether the corresponding object is a socket
** isSocket

* whether the corresponding object is a pipe
** isPipe
** isFifo

* whether the correpsonding object is a block device
** isBlockDevice

* the size of the corresponding object in bytes
** size
*** Ondrej Zara
** (jslibs: size, Helma: getLength, Spidermonkey: wxJS: EJScript: Synchronet: length)

* the name or id of the owner of the file (following symlinks)
** owner

* the name or id of the group owner of the file (following symlinks)
** groupOwner

* the name or id of the owner of the file or symbolic link
** linkOwner

* the name or id of the group owner of the file or symbolic link
** linkGroupOwner

* whether the owner of the process at the time of this stat object's construction is the same as the owner of this file.
** owned

* whether the corresponding object can be opened for reading by the current process owner
** isReadable

* whether the corresponding object can be opened for writing by the current process owner
** isWritable

* whether the corresponding object is an executable for the current process owner
** isExecutable

* whether the corresponding executable file will be forced to run as the owner of the file if any user executes it.
** executesAsOwner
** setuid

* whether the corresponding executable file wil be forced to run with its group owner if any user executes it.
** executesAsGroupOwner
** setgid

* whether the corresponding directory will permit anyone to create files in it, but only let the owner of a file delete it.
** sticky

* an object that represents the permissions granted to the owner of the file.
** This object would contain:
*** isReadable
*** isWritable
*** isExecutable
** ownerPermissions

* an object that represents the permissions granted to the group that owns the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** groupPermissions

* an object that represents the permissions granted to anyone who has no claim to the file.
** The object would contain:
*** isReadable
*** isWritable
*** isExecutable
** worldPermissions

* returns an object that represents the permissions granted to the user corresponding to a particular name or identifier.
** The returned object would contain:
*** isReadable
*** isWritable
*** isExecutable
** getPermissions(user)

* the inode/vnode number of the underlying object (optional)
** inode

* the device number of the underlying object (optional)
** device


== File Object ==

File objects can only be constructed by methods of FileSystem objects.  Different IO types might be returned for calls to open with different modes, generally following the protocol outlined in Python's PEP 3116.  


== IO Objects ==

* reads as many bytes as are available from an IO stream and returns the number of actually read bytes.
** read()

* reads as many bytes as are available but less than a given number from an IO stream and returns the number of actually read bytes.
** read(n)

* reads a line of characters from a line buffered IO object.  Returns a blank line on EOF.
** readLine()
** (Python: JSExt: readline, Spidermonkey: Helma: Synchronet: readln)

* returns an Array-like view of the lines in an IO stream, or simply an Array of Strings.
** readLines()
** (Python: readlines, JSExt: readlines, EJScript: getLines)

* returns the next line in the stream.  Throws a StopIteration exception on EOF.
** next()

* returns an iteration on the lines of the IO stream, which is simply itself since it implements &quot;next&quot;.
** iter()

* calls a relation with each line of input from the IO stream.
** forEach(relation)

* reads bytes into a buffer, up to as many as the length of the buffer, pending availablility.  Returns the number of bytes actually read.
** readInto(buffer)

* writes bytes to a stream.  Returns the number of bytes that were actually written.
** write(buffer)

* moves the position of the cursor in a random access IO stream.
** Accepts a code that determines whether to move the position relative to the beginning, end, or current position:
*** 0 or &quot;begin&quot;: beginning of file (default)
*** 1 or &quot;relative&quot;: current position
*** 2 or &quot;end&quot;: end of file
** seek(pos, whence)
** (universal precedent)

* returns the current position of the random access cursor for an IO stream.  The position may be a &quot;cookie&quot; object or a Number, depending on the IO type.
** tell()
** (wxJS: JSExt: Python: Ruby: tell)

* truncates the size of a file to the current cursor position or a given position, which must be either a &quot;cookie&quot; object or a Number, depending on the IO type.
** truncate(pos)
** (Ruby: truncate, Python: ftruncate)

* returns whether the cursor is at the end of the IO stream.
** eof()
*** Kris Kowal
** atEOF():
*** Wes Garland (non-commital)
** (Helma: wxJS: JSExt: Synchronet: eof)

* flushes buffers for an IO stream
** flush()
** (universal precedent)

* blocks until an advisory lock is acquired.  Throws an error if a lock cannot be acquired on the system.
** lock(&quot;exclusive|shared&quot;)

* tries to grab an advisory lock without blocking, and returns whether it succeeded.
** tryLock(&quot;exclusive|shared&quot;)
** (related to isOpen in many existing SSJS frameworks, but without a race condition hazard)

* releases an advisory lock.
** unlock()

* closes a stream
** close()

* whether the IO stream is readable
** isReadable

* whether the IO stream is writable
** isWritable

* whether the IO stream supports random access
** isSeekable

* whether the IO stream is attached to a virtual or real teletype.
** isTTY:
*** Wes Garland
** isTty:
*** Kris Kowal 

* the descriptor of the underlying file, an opaque reference to the file descriptor, or undefined if file descriptors are not supported.
** fileNo

* the underlying unbuffered IO stream, if it exists.  Otherwise undefined.
** raw

* creates a duplicate of the IO stream, with its own buffereing and cursor.
** copy()
*** Kris Kowal
** dup()


= Notes for Further Discussion =

* input, output, stdin, stdout, STDIN, STDOUT
* ...placed on environment or in a module?
* separation of knowledge of paths between file system and files
* currentDirectory, getCurrentDirectory
* temporary files and directories
* opening a temp file with an implied immediate exclusive lock
* dup and dup2 and other file-descriptor specific constructs for permissive environments.
* canRead, canWrite, poll, select
* taxonomy of IO classes
* default encoding for String, line-buffered IO


= General Preferences =

# make vs. create
#* make:
#** Mario Valente,
#** Wes Garland (but only for directories)
#* create:
#** George Moschovitis,
#** Wes Garland (but only for files)
#** Ondrej Zara
# dir vs. directory
#* directory:
#** Tom Robinson,
#** Kevin Dangoor,
#** George Mosochovitis,
#** Wes Garland
#** Ondrej Zara
#* dir:
#** Mario Valente
# cur vs. current
#* current:
#** Tom Robinson,
#** Kevin Dangoor,
#** Wes Garland,
#** Kris Kowal,
#** Mario Valente
#** Ondrej Zara
#** George Moschovitis
#* cur:
# canonize, realize, normalize, qualify, cannon, real, normal, qualified, absolute, cannonicalize
#* remove . and ..:
#** normalize:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis
#** qualify:
#*** Wes Garland
#** expand:
#*** Ondrej Zara
#* remove . and .., start at /:
#** absolute:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal,
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente
#** qualified:
#*** Wes Garland
#** normalize:
#*** Ondrej Zara
#* remove . and .., start at /, follow symlinks:
#** canonical:
#*** Tom Robinson,
#*** Kevin Dangoor,
#*** Kris Kowal
#** absolute:
#*** George Mosochovitis,
#*** Wes Garland,
#*** Mario Valente,
#** real:
#*** Tom Robinson,
#*** Kevin Dangoor
#** qualified:
#*** Wes Garland
# constantCase, CONSTANT_CASE, kConstantCase
#* CONSTANT_CASE:
#** Tom Robinson,
#** Kevin Dangoor
#** Ondrej Zara
#** George Moschovitis
#* constantCase:
#** Kris Kowal,
#** Wes Garland,
#** Mario Valente,
# &quot;static&quot; methods
#* require(module).staticMethod:
#** Kris Kowal
#** Wes Garland
#** Mario Valente
#** Ondrej Zara
#* require(module).Klass.staticMethod:
#** Tom Robinson
#** George Mosochovitis
# properties, accessors, mutators
#* foo.setX(x); foo.getX()
#** For:
#** Against:
#* foo.setX(x); foo.X()
#** For:
#** Against:
#* no convention
#** For:
#** Against:
#* foo.x = x; foo.x
#** For:
#*** Davey Waterson
#*** Wes Garland
#*** Daniel Friesen
#*** Sam Phillips
#** Against:
#*** Tom Robinson
#*** Kris Kowal


= References =

; http://www.python.org/dev/peps/pep-3116/: PEP on new File IO
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html: Java File API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileOutputStream.html: Java Output API
; http://java.sun.com/j2se/1.4.2/docs/api/java/io/FileInputStream.html: Java Input API
; http://www.erights.org/javadoc/java/io/File.html: E Secure File API
; http://www.cs.berkeley.edu/~daw/joe-e/api/org/joe_e/file/Filesystem.html: Joe-E Secure File System API
; http://docs.python.org/library/os.path.html: Python Path API
; http://www.ruby-doc.org/core/classes/File.html: Ruby File API
; http://www.ruby-doc.org/core/classes/IO.html: Ruby IO API
; http://spreadsheets.google.com/pub?key=p9uiX8MUHeTiP0kPT591RUw: A matrix of existing ServerJS File API nomenclature and support</text>
    </revision>
    <revision>
      <id>79</id>
      <timestamp>2009-05-17T23:35:44Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Moved to ServerJS/Filesystem_API/Names</comment>
      <text xml:space="preserve">Moved to [[ServerJS/Filesystem_API/Names]].</text>
    </revision>
    <revision>
      <id>80</id>
      <timestamp>2009-09-09T22:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>7 revisions:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve">Moved to [[ServerJS/Filesystem_API/Names]].</text>
    </revision>
    <revision>
      <id>631</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/file/Names]] to [[CommonJS/API/file/Names]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve">Moved to [[ServerJS/Filesystem_API/Names]].</text>
    </revision>
    <revision>
      <id>788</id>
      <timestamp>2009-09-09T22:40:39Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-ServerJS +CommonJS)</comment>
      <text xml:space="preserve">Moved to [[CommonJS/Filesystem_API/Names]].</text>
    </revision>
    <revision>
      <id>929</id>
      <timestamp>2009-09-10T03:04:06Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <comment>Redirected page to [[CommonJS/Filesystem API/Names]]</comment>
      <text xml:space="preserve">#REDIRECT [[CommonJS/Filesystem_API/Names]].</text>
    </revision>
    <revision>
      <id>930</id>
      <timestamp>2009-09-10T03:04:16Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <comment>`</comment>
      <text xml:space="preserve">#REDIRECT [[Filesystem/Names]].</text>
    </revision>
    <revision>
      <id>981</id>
      <timestamp>2009-09-10T03:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/file/Names]] to [[OldAPI/file/Names]]</comment>
      <text xml:space="preserve">#REDIRECT [[Filesystem/Names]].</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/file/ProposalK</title>
    <id>11</id>
    <revision>
      <id>81</id>
      <timestamp>2009-02-18T07:44:12Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>An rough initial proposal for a file module for ServerJS.</comment>
      <text xml:space="preserve"> 
 /**
 */
 
 /*** File
     - :isa:`io#Io`
 */
 
 /*** Stat
     - :isa:`Object`
     a representation of a file's metadata including permissions,
     ownership, time stamps, and other traits.
 */
 
 /*** Dir
 */
 
 /**** iter
 */
 
 /*** glob
     returns a `List` of file names for a given &quot;glob&quot; expression
     that may contain patterns:
 
       ===  ======================================================
       ?    matches any single character
   
       *    matches any pattern of characters
   
       **   matches any pattern of characters
            in the file names of a depth first traversal
            starting with the file names and directories
            that start with the file name characters before ``**``
            and ending with the file name characters after ``**``
       ===  ======================================================
   
 */
 
 /*** globIter
     returns an iteration of file names for a given &quot;glob&quot; expression
     that may contain patterns according to those documented
     in `glob`
 */
 
 /*** separator
     The path separator for the platform's file systems.
 */
 
 /*** resolve
     returns the real, absolute, fully-qualified path arrived
     at from a ``base`` path following an relative ``rel`` path.
     When no ``base`` is provided, resolves the ``rel`` path
     relative to the current working directory.
 
     - accepts ``rel``
     - accepts an optional ``base``
 
 */
 
 /*** relative
     returns the relative path between two fully-qualifed paths.
 */
 
 /*** baseName
 */
 
 /*** dirName
 */</text>
    </revision>
    <revision>
      <id>82</id>
      <timestamp>2009-09-09T22:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>1 revision:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve"> 
 /**
 */
 
 /*** File
     - :isa:`io#Io`
 */
 
 /*** Stat
     - :isa:`Object`
     a representation of a file's metadata including permissions,
     ownership, time stamps, and other traits.
 */
 
 /*** Dir
 */
 
 /**** iter
 */
 
 /*** glob
     returns a `List` of file names for a given &quot;glob&quot; expression
     that may contain patterns:
 
       ===  ======================================================
       ?    matches any single character
   
       *    matches any pattern of characters
   
       **   matches any pattern of characters
            in the file names of a depth first traversal
            starting with the file names and directories
            that start with the file name characters before ``**``
            and ending with the file name characters after ``**``
       ===  ======================================================
   
 */
 
 /*** globIter
     returns an iteration of file names for a given &quot;glob&quot; expression
     that may contain patterns according to those documented
     in `glob`
 */
 
 /*** separator
     The path separator for the platform's file systems.
 */
 
 /*** resolve
     returns the real, absolute, fully-qualified path arrived
     at from a ``base`` path following an relative ``rel`` path.
     When no ``base`` is provided, resolves the ``rel`` path
     relative to the current working directory.
 
     - accepts ``rel``
     - accepts an optional ``base``
 
 */
 
 /*** relative
     returns the relative path between two fully-qualifed paths.
 */
 
 /*** baseName
 */
 
 /*** dirName
 */</text>
    </revision>
    <revision>
      <id>633</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/file/ProposalK]] to [[CommonJS/API/file/ProposalK]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve"> 
 /**
 */
 
 /*** File
     - :isa:`io#Io`
 */
 
 /*** Stat
     - :isa:`Object`
     a representation of a file's metadata including permissions,
     ownership, time stamps, and other traits.
 */
 
 /*** Dir
 */
 
 /**** iter
 */
 
 /*** glob
     returns a `List` of file names for a given &quot;glob&quot; expression
     that may contain patterns:
 
       ===  ======================================================
       ?    matches any single character
   
       *    matches any pattern of characters
   
       **   matches any pattern of characters
            in the file names of a depth first traversal
            starting with the file names and directories
            that start with the file name characters before ``**``
            and ending with the file name characters after ``**``
       ===  ======================================================
   
 */
 
 /*** globIter
     returns an iteration of file names for a given &quot;glob&quot; expression
     that may contain patterns according to those documented
     in `glob`
 */
 
 /*** separator
     The path separator for the platform's file systems.
 */
 
 /*** resolve
     returns the real, absolute, fully-qualified path arrived
     at from a ``base`` path following an relative ``rel`` path.
     When no ``base`` is provided, resolves the ``rel`` path
     relative to the current working directory.
 
     - accepts ``rel``
     - accepts an optional ``base``
 
 */
 
 /*** relative
     returns the relative path between two fully-qualifed paths.
 */
 
 /*** baseName
 */
 
 /*** dirName
 */</text>
    </revision>
    <revision>
      <id>983</id>
      <timestamp>2009-09-10T03:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/file/ProposalK]] to [[OldAPI/file/ProposalK]]</comment>
      <text xml:space="preserve"> 
 /**
 */
 
 /*** File
     - :isa:`io#Io`
 */
 
 /*** Stat
     - :isa:`Object`
     a representation of a file's metadata including permissions,
     ownership, time stamps, and other traits.
 */
 
 /*** Dir
 */
 
 /**** iter
 */
 
 /*** glob
     returns a `List` of file names for a given &quot;glob&quot; expression
     that may contain patterns:
 
       ===  ======================================================
       ?    matches any single character
   
       *    matches any pattern of characters
   
       **   matches any pattern of characters
            in the file names of a depth first traversal
            starting with the file names and directories
            that start with the file name characters before ``**``
            and ending with the file name characters after ``**``
       ===  ======================================================
   
 */
 
 /*** globIter
     returns an iteration of file names for a given &quot;glob&quot; expression
     that may contain patterns according to those documented
     in `glob`
 */
 
 /*** separator
     The path separator for the platform's file systems.
 */
 
 /*** resolve
     returns the real, absolute, fully-qualified path arrived
     at from a ``base`` path following an relative ``rel`` path.
     When no ``base`` is provided, resolves the ``rel`` path
     relative to the current working directory.
 
     - accepts ``rel``
     - accepts an optional ``base``
 
 */
 
 /*** relative
     returns the relative path between two fully-qualifed paths.
 */
 
 /*** baseName
 */
 
 /*** dirName
 */</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/io/ProposalK</title>
    <id>12</id>
    <revision>
      <id>83</id>
      <timestamp>2009-02-18T07:13:27Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>An initial proposal for an IO module for ServerJS.</comment>
      <text xml:space="preserve"> 
 /**
 */
 
 /*** Io
     - :is:`iter#Iterable`
 */
 
 /**** input
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
     - returns a `String` decoded from reading
 */
 
 /**** print
     - accepts a `String` to encode and write
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
 */
 
 /**** read
     - accepts a maximum `Number` of bytes to read.
     - returns a `Binary` of however many bytes were actually read.
 */
 
 /**** write
     - returns a `Number` of however many bytes were actually
       written.
 */
 
 /**** readNonblock
     - accepts a maximum `Number` of bytes to read.
     - returns a `Binary` of however many bytes were read without
       blocking.
 */
 
 /**** writeNonblock
     - accepts a `Binary` of bytes to write.
     - returns a `Number` of however many bytes were actually
       written without blocking.
 */
 
 /**** isEof
     returns whether the read/write head is at or beyond the
     end of the stream.
 */
 
 /**** iter
     an alias for `linesIter`
 */
 
 /**** linesIter
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
     returns an iteration on lines (`String`) of the stream.
 */
 
 /**** charsIter
     - accepts an optional `String` encoding module identifier
     returns an iteration of characters (`String`) of the stream.
 */
 
 /**** bytesIter
     returns an iteration on bytes (`Binary`) of the stream.
 */
 
 /**** fcntl
 */
 
 /**** getFileNo
     returns an integer `Number` for the process stream number
     that the IO object is attached to.
 */
 
 /**** toNumber
     an alias for `getFileNo`
 */
 
 /**** getLineNo
     returns the current &quot;line&quot; number from the file.
     updated on read.
 */
 
 /**** isTty
     returns whether the stream is attached to a
     terminal device, a teletype, ``tty``.
 */
 
 /**** getPos
     get the current byte offset of the
     read/write head in the stream.
 */
 
 /**** setPos
     set the current byte offset of the
     read/write head in the stream.
 */
 
 /**** rewind
     Equivalent to ``setPos(0)``
 */
 
 /**** seek
     Seeks to a given integer `Number` offset in the
     stream relative to a given position:
 
     Accepts:
 
     - ``offset``, an integer `Number`
     - ``whence``, an enumerated integer `Number` supplied
       by one of the following constants.
     
     Whence:
 
       ========  ==================================
       SEEK_CUR  Seeks to current position
                 plus ``offset``
 
       SEEK_END  Seeks to the end of the stream
                 plus ``offset``, usually negative.
 
       SEEK_SET  Seeks to the beginning of the
                 stream plus ``offset``
       ========  ==================================
 
 
     Example::
 
         var file = require('file');
         var io = require('io');
         var f = file.File(&quot;testfile&quot;, &quot;utf-8&quot;);
         f.seek(-13, io.SEEK_END);
         var line = f.input()
         
 */
 
 /**** stat
 */
 
 /**** select
 */
 
 /**** fsync
 */
 
 /**** ioctl
 */</text>
    </revision>
    <revision>
      <id>84</id>
      <timestamp>2009-02-18T23:00:36Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <text xml:space="preserve"> 
This module and the file module in this proposal are a hybrid of mostly the Ruby API melded with Pythonic/Rhinocerous iteration, and liberated of the notion that certain things should be static methods as opposed to simply hosted by the module.

 /**
 */
 
 /*** Io
     - :is:`iter#Iterable`
 */
 
 /**** input
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
     - returns a `String` decoded from reading
 */
 
 /**** print
     - accepts a `String` to encode and write
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
 */
 
 /**** read
     - accepts a maximum `Number` of bytes to read.
     - returns a `Binary` of however many bytes were actually read.
 */
 
 /**** write
     - returns a `Number` of however many bytes were actually
       written.
 */
 
 /**** readNonblock
     - accepts a maximum `Number` of bytes to read.
     - returns a `Binary` of however many bytes were read without
       blocking.
 */
 
 /**** writeNonblock
     - accepts a `Binary` of bytes to write.
     - returns a `Number` of however many bytes were actually
       written without blocking.
 */
 
 /**** isEof
     returns whether the read/write head is at or beyond the
     end of the stream.
 */
 
 /**** iter
     an alias for `linesIter`
 */
 
 /**** linesIter
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
     returns an iteration on lines (`String`) of the stream.
 */
 
 /**** charsIter
     - accepts an optional `String` encoding module identifier
     returns an iteration of characters (`String`) of the stream.
 */
 
 /**** bytesIter
     returns an iteration on bytes (`Binary`) of the stream.
 */
 
 /**** fcntl
 */
 
 /**** getFileNo
     returns an integer `Number` for the process stream number
     that the IO object is attached to.
 */
 
 /**** toNumber
     an alias for `getFileNo`
 */
 
 /**** getLineNo
     returns the current &quot;line&quot; number from the file.
     updated on read.
 */
 
 /**** isTty
     returns whether the stream is attached to a
     terminal device, a teletype, ``tty``.
 */
 
 /**** getPos
     get the current byte offset of the
     read/write head in the stream.
 */
 
 /**** setPos
     set the current byte offset of the
     read/write head in the stream.
 */
 
 /**** rewind
     Equivalent to ``setPos(0)``
 */
 
 /**** seek
     Seeks to a given integer `Number` offset in the
     stream relative to a given position:
 
     Accepts:
 
     - ``offset``, an integer `Number`
     - ``whence``, an enumerated integer `Number` supplied
       by one of the following constants.
     
     Whence:
 
       ========  ==================================
       SEEK_CUR  Seeks to current position
                 plus ``offset``
 
       SEEK_END  Seeks to the end of the stream
                 plus ``offset``, usually negative.
 
       SEEK_SET  Seeks to the beginning of the
                 stream plus ``offset``
       ========  ==================================
 
 
     Example::
 
         var file = require('file');
         var io = require('io');
         var f = file.File(&quot;testfile&quot;, &quot;utf-8&quot;);
         f.seek(-13, io.SEEK_END);
         var line = f.input()
         
 */
 
 /**** stat
 */
 
 /**** select
 */
 
 /**** fsync
 */
 
 /**** ioctl
 */</text>
    </revision>
    <revision>
      <id>85</id>
      <timestamp>2009-09-09T22:13:58Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>2 revisions:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve"> 
This module and the file module in this proposal are a hybrid of mostly the Ruby API melded with Pythonic/Rhinocerous iteration, and liberated of the notion that certain things should be static methods as opposed to simply hosted by the module.

 /**
 */
 
 /*** Io
     - :is:`iter#Iterable`
 */
 
 /**** input
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
     - returns a `String` decoded from reading
 */
 
 /**** print
     - accepts a `String` to encode and write
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
 */
 
 /**** read
     - accepts a maximum `Number` of bytes to read.
     - returns a `Binary` of however many bytes were actually read.
 */
 
 /**** write
     - returns a `Number` of however many bytes were actually
       written.
 */
 
 /**** readNonblock
     - accepts a maximum `Number` of bytes to read.
     - returns a `Binary` of however many bytes were read without
       blocking.
 */
 
 /**** writeNonblock
     - accepts a `Binary` of bytes to write.
     - returns a `Number` of however many bytes were actually
       written without blocking.
 */
 
 /**** isEof
     returns whether the read/write head is at or beyond the
     end of the stream.
 */
 
 /**** iter
     an alias for `linesIter`
 */
 
 /**** linesIter
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
     returns an iteration on lines (`String`) of the stream.
 */
 
 /**** charsIter
     - accepts an optional `String` encoding module identifier
     returns an iteration of characters (`String`) of the stream.
 */
 
 /**** bytesIter
     returns an iteration on bytes (`Binary`) of the stream.
 */
 
 /**** fcntl
 */
 
 /**** getFileNo
     returns an integer `Number` for the process stream number
     that the IO object is attached to.
 */
 
 /**** toNumber
     an alias for `getFileNo`
 */
 
 /**** getLineNo
     returns the current &quot;line&quot; number from the file.
     updated on read.
 */
 
 /**** isTty
     returns whether the stream is attached to a
     terminal device, a teletype, ``tty``.
 */
 
 /**** getPos
     get the current byte offset of the
     read/write head in the stream.
 */
 
 /**** setPos
     set the current byte offset of the
     read/write head in the stream.
 */
 
 /**** rewind
     Equivalent to ``setPos(0)``
 */
 
 /**** seek
     Seeks to a given integer `Number` offset in the
     stream relative to a given position:
 
     Accepts:
 
     - ``offset``, an integer `Number`
     - ``whence``, an enumerated integer `Number` supplied
       by one of the following constants.
     
     Whence:
 
       ========  ==================================
       SEEK_CUR  Seeks to current position
                 plus ``offset``
 
       SEEK_END  Seeks to the end of the stream
                 plus ``offset``, usually negative.
 
       SEEK_SET  Seeks to the beginning of the
                 stream plus ``offset``
       ========  ==================================
 
 
     Example::
 
         var file = require('file');
         var io = require('io');
         var f = file.File(&quot;testfile&quot;, &quot;utf-8&quot;);
         f.seek(-13, io.SEEK_END);
         var line = f.input()
         
 */
 
 /**** stat
 */
 
 /**** select
 */
 
 /**** fsync
 */
 
 /**** ioctl
 */</text>
    </revision>
    <revision>
      <id>635</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/io/ProposalK]] to [[CommonJS/API/io/ProposalK]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve"> 
This module and the file module in this proposal are a hybrid of mostly the Ruby API melded with Pythonic/Rhinocerous iteration, and liberated of the notion that certain things should be static methods as opposed to simply hosted by the module.

 /**
 */
 
 /*** Io
     - :is:`iter#Iterable`
 */
 
 /**** input
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
     - returns a `String` decoded from reading
 */
 
 /**** print
     - accepts a `String` to encode and write
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
 */
 
 /**** read
     - accepts a maximum `Number` of bytes to read.
     - returns a `Binary` of however many bytes were actually read.
 */
 
 /**** write
     - returns a `Number` of however many bytes were actually
       written.
 */
 
 /**** readNonblock
     - accepts a maximum `Number` of bytes to read.
     - returns a `Binary` of however many bytes were read without
       blocking.
 */
 
 /**** writeNonblock
     - accepts a `Binary` of bytes to write.
     - returns a `Number` of however many bytes were actually
       written without blocking.
 */
 
 /**** isEof
     returns whether the read/write head is at or beyond the
     end of the stream.
 */
 
 /**** iter
     an alias for `linesIter`
 */
 
 /**** linesIter
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
     returns an iteration on lines (`String`) of the stream.
 */
 
 /**** charsIter
     - accepts an optional `String` encoding module identifier
     returns an iteration of characters (`String`) of the stream.
 */
 
 /**** bytesIter
     returns an iteration on bytes (`Binary`) of the stream.
 */
 
 /**** fcntl
 */
 
 /**** getFileNo
     returns an integer `Number` for the process stream number
     that the IO object is attached to.
 */
 
 /**** toNumber
     an alias for `getFileNo`
 */
 
 /**** getLineNo
     returns the current &quot;line&quot; number from the file.
     updated on read.
 */
 
 /**** isTty
     returns whether the stream is attached to a
     terminal device, a teletype, ``tty``.
 */
 
 /**** getPos
     get the current byte offset of the
     read/write head in the stream.
 */
 
 /**** setPos
     set the current byte offset of the
     read/write head in the stream.
 */
 
 /**** rewind
     Equivalent to ``setPos(0)``
 */
 
 /**** seek
     Seeks to a given integer `Number` offset in the
     stream relative to a given position:
 
     Accepts:
 
     - ``offset``, an integer `Number`
     - ``whence``, an enumerated integer `Number` supplied
       by one of the following constants.
     
     Whence:
 
       ========  ==================================
       SEEK_CUR  Seeks to current position
                 plus ``offset``
 
       SEEK_END  Seeks to the end of the stream
                 plus ``offset``, usually negative.
 
       SEEK_SET  Seeks to the beginning of the
                 stream plus ``offset``
       ========  ==================================
 
 
     Example::
 
         var file = require('file');
         var io = require('io');
         var f = file.File(&quot;testfile&quot;, &quot;utf-8&quot;);
         f.seek(-13, io.SEEK_END);
         var line = f.input()
         
 */
 
 /**** stat
 */
 
 /**** select
 */
 
 /**** fsync
 */
 
 /**** ioctl
 */</text>
    </revision>
    <revision>
      <id>985</id>
      <timestamp>2009-09-10T03:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/io/ProposalK]] to [[OldAPI/io/ProposalK]]</comment>
      <text xml:space="preserve"> 
This module and the file module in this proposal are a hybrid of mostly the Ruby API melded with Pythonic/Rhinocerous iteration, and liberated of the notion that certain things should be static methods as opposed to simply hosted by the module.

 /**
 */
 
 /*** Io
     - :is:`iter#Iterable`
 */
 
 /**** input
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
     - returns a `String` decoded from reading
 */
 
 /**** print
     - accepts a `String` to encode and write
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
 */
 
 /**** read
     - accepts a maximum `Number` of bytes to read.
     - returns a `Binary` of however many bytes were actually read.
 */
 
 /**** write
     - returns a `Number` of however many bytes were actually
       written.
 */
 
 /**** readNonblock
     - accepts a maximum `Number` of bytes to read.
     - returns a `Binary` of however many bytes were read without
       blocking.
 */
 
 /**** writeNonblock
     - accepts a `Binary` of bytes to write.
     - returns a `Number` of however many bytes were actually
       written without blocking.
 */
 
 /**** isEof
     returns whether the read/write head is at or beyond the
     end of the stream.
 */
 
 /**** iter
     an alias for `linesIter`
 */
 
 /**** linesIter
     - accepts an optional `String` line terminator
     - accepts an optional `String` encoding module identifier
     returns an iteration on lines (`String`) of the stream.
 */
 
 /**** charsIter
     - accepts an optional `String` encoding module identifier
     returns an iteration of characters (`String`) of the stream.
 */
 
 /**** bytesIter
     returns an iteration on bytes (`Binary`) of the stream.
 */
 
 /**** fcntl
 */
 
 /**** getFileNo
     returns an integer `Number` for the process stream number
     that the IO object is attached to.
 */
 
 /**** toNumber
     an alias for `getFileNo`
 */
 
 /**** getLineNo
     returns the current &quot;line&quot; number from the file.
     updated on read.
 */
 
 /**** isTty
     returns whether the stream is attached to a
     terminal device, a teletype, ``tty``.
 */
 
 /**** getPos
     get the current byte offset of the
     read/write head in the stream.
 */
 
 /**** setPos
     set the current byte offset of the
     read/write head in the stream.
 */
 
 /**** rewind
     Equivalent to ``setPos(0)``
 */
 
 /**** seek
     Seeks to a given integer `Number` offset in the
     stream relative to a given position:
 
     Accepts:
 
     - ``offset``, an integer `Number`
     - ``whence``, an enumerated integer `Number` supplied
       by one of the following constants.
     
     Whence:
 
       ========  ==================================
       SEEK_CUR  Seeks to current position
                 plus ``offset``
 
       SEEK_END  Seeks to the end of the stream
                 plus ``offset``, usually negative.
 
       SEEK_SET  Seeks to the beginning of the
                 stream plus ``offset``
       ========  ==================================
 
 
     Example::
 
         var file = require('file');
         var io = require('io');
         var f = file.File(&quot;testfile&quot;, &quot;utf-8&quot;);
         f.seek(-13, io.SEEK_END);
         var line = f.input()
         
 */
 
 /**** stat
 */
 
 /**** select
 */
 
 /**** fsync
 */
 
 /**** ioctl
 */</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/iter/ProposalK</title>
    <id>13</id>
    <revision>
      <id>86</id>
      <timestamp>2009-02-18T08:06:55Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Rough cut of an iteration module API for ServerJS</comment>
      <text xml:space="preserve"> 
 /*** Iterable
     a mixin that adds convenience functions to types
     that implement `iter`.
 */
 
 /**** iter
     a default ``iter`` that returns itself.
 */
 /**** added */
 /**** nextCatch */
 /**** len
     a default, destructive implementation
     of `len` that consumes the remaining elements
     of the iteration and returns how many were
     encountered.
 */
 /**** toObject */
 /**** toArray */
 /**** toList */
 /**** toDict */
 /**** toUnique
     returns a `Set` of the unique elements of the iterable.
 */
 /**** toString
     returns the concatenation of the elements of the 
     iterable coerced into `String` objects.
 */
 /**** toNumber
     a polymorphic alias of `len`.
 */
 /**** toBoolean
     returns whether `toNumber` is greater than 0.
 */
 /**** sliced */
 /**** forEach */
 /**** forEachApply */
 /**** each */
 /**** eachIter */
 /**** eachApply */
 /**** eachApplyIter */
 /**** where */
 /**** whereIter */
 /**** whereApply */
 /**** whereApplyIter */
 /**** zip */
 /**** zipIter */
 /**** transpose */
 /**** transposeIter */
 /**** enumerate */
 /**** enumerateIter */
 /**** reduce */
 /**** reduced */
 /**** flatten */
 /**** flattened */
 /**** group */
 /**** sorted */
 /**** reversed */
 /**** min */
 /**** mix */
 /**** sum */
 /**** product */
 /**** all */
 /**** any */
 /**** join */
 
 
 /*** Iter
     - :is:`Iterable`
 
     Accepts:
 
     - an optional ``next`` `Function`.  Without a ``next`` function,
       returns an empty iteration.
     - an optional ``hasNext`` `Function``.
 
 */
 /**** next */
 /**** hasNext */
 
 /*** iter
     Returns an iteration of a given object.  Attempts
     to call the polymorphic `iter` of a typed object.
     Otherwise, coerces to the first applicable of 
     `String`, `Array`, or `Object` types.
 */
 
 /*** objectIter */
 /*** arrayIter */
 /*** stringIter */
 
 
 /**
     Top Level Functions
     ===================
 
     Functions that operate on iterables, or objects
     coercible to iterables using the polymorphic `iter`
     function.
 */
 
 /*** forEach */
 /*** forEachApply */
 /*** each */
 /*** each */
 /*** eachIter */
 /*** eachApply */
 /*** eachApplyIter */
 /*** where */
 /*** whereIter */
 /*** whereApply */
 /*** whereApplyIter */
 /*** map */
 /*** mapIter */
 /*** forTimes */
 /*** timesIter */
 /*** times */
 /*** transpose */
 /*** transposeIter */
 /*** zip */
 /*** zipIter
 /*** enumerate */
 /*** enumerateIter */
 /*** reduce */
 /*** cycle */
 /*** chain */
 /*** repeat */
 /*** flatten */
 /*** compact */
 /*** compactIter */
 /*** without */
 /*** withoutIter */
 /*** group */
 /*** all */
 /*** any */
 /*** min */
 /*** max */</text>
    </revision>
    <revision>
      <id>87</id>
      <timestamp>2009-09-09T22:13:58Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>1 revision:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve"> 
 /*** Iterable
     a mixin that adds convenience functions to types
     that implement `iter`.
 */
 
 /**** iter
     a default ``iter`` that returns itself.
 */
 /**** added */
 /**** nextCatch */
 /**** len
     a default, destructive implementation
     of `len` that consumes the remaining elements
     of the iteration and returns how many were
     encountered.
 */
 /**** toObject */
 /**** toArray */
 /**** toList */
 /**** toDict */
 /**** toUnique
     returns a `Set` of the unique elements of the iterable.
 */
 /**** toString
     returns the concatenation of the elements of the 
     iterable coerced into `String` objects.
 */
 /**** toNumber
     a polymorphic alias of `len`.
 */
 /**** toBoolean
     returns whether `toNumber` is greater than 0.
 */
 /**** sliced */
 /**** forEach */
 /**** forEachApply */
 /**** each */
 /**** eachIter */
 /**** eachApply */
 /**** eachApplyIter */
 /**** where */
 /**** whereIter */
 /**** whereApply */
 /**** whereApplyIter */
 /**** zip */
 /**** zipIter */
 /**** transpose */
 /**** transposeIter */
 /**** enumerate */
 /**** enumerateIter */
 /**** reduce */
 /**** reduced */
 /**** flatten */
 /**** flattened */
 /**** group */
 /**** sorted */
 /**** reversed */
 /**** min */
 /**** mix */
 /**** sum */
 /**** product */
 /**** all */
 /**** any */
 /**** join */
 
 
 /*** Iter
     - :is:`Iterable`
 
     Accepts:
 
     - an optional ``next`` `Function`.  Without a ``next`` function,
       returns an empty iteration.
     - an optional ``hasNext`` `Function``.
 
 */
 /**** next */
 /**** hasNext */
 
 /*** iter
     Returns an iteration of a given object.  Attempts
     to call the polymorphic `iter` of a typed object.
     Otherwise, coerces to the first applicable of 
     `String`, `Array`, or `Object` types.
 */
 
 /*** objectIter */
 /*** arrayIter */
 /*** stringIter */
 
 
 /**
     Top Level Functions
     ===================
 
     Functions that operate on iterables, or objects
     coercible to iterables using the polymorphic `iter`
     function.
 */
 
 /*** forEach */
 /*** forEachApply */
 /*** each */
 /*** each */
 /*** eachIter */
 /*** eachApply */
 /*** eachApplyIter */
 /*** where */
 /*** whereIter */
 /*** whereApply */
 /*** whereApplyIter */
 /*** map */
 /*** mapIter */
 /*** forTimes */
 /*** timesIter */
 /*** times */
 /*** transpose */
 /*** transposeIter */
 /*** zip */
 /*** zipIter
 /*** enumerate */
 /*** enumerateIter */
 /*** reduce */
 /*** cycle */
 /*** chain */
 /*** repeat */
 /*** flatten */
 /*** compact */
 /*** compactIter */
 /*** without */
 /*** withoutIter */
 /*** group */
 /*** all */
 /*** any */
 /*** min */
 /*** max */</text>
    </revision>
    <revision>
      <id>637</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/iter/ProposalK]] to [[CommonJS/API/iter/ProposalK]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve"> 
 /*** Iterable
     a mixin that adds convenience functions to types
     that implement `iter`.
 */
 
 /**** iter
     a default ``iter`` that returns itself.
 */
 /**** added */
 /**** nextCatch */
 /**** len
     a default, destructive implementation
     of `len` that consumes the remaining elements
     of the iteration and returns how many were
     encountered.
 */
 /**** toObject */
 /**** toArray */
 /**** toList */
 /**** toDict */
 /**** toUnique
     returns a `Set` of the unique elements of the iterable.
 */
 /**** toString
     returns the concatenation of the elements of the 
     iterable coerced into `String` objects.
 */
 /**** toNumber
     a polymorphic alias of `len`.
 */
 /**** toBoolean
     returns whether `toNumber` is greater than 0.
 */
 /**** sliced */
 /**** forEach */
 /**** forEachApply */
 /**** each */
 /**** eachIter */
 /**** eachApply */
 /**** eachApplyIter */
 /**** where */
 /**** whereIter */
 /**** whereApply */
 /**** whereApplyIter */
 /**** zip */
 /**** zipIter */
 /**** transpose */
 /**** transposeIter */
 /**** enumerate */
 /**** enumerateIter */
 /**** reduce */
 /**** reduced */
 /**** flatten */
 /**** flattened */
 /**** group */
 /**** sorted */
 /**** reversed */
 /**** min */
 /**** mix */
 /**** sum */
 /**** product */
 /**** all */
 /**** any */
 /**** join */
 
 
 /*** Iter
     - :is:`Iterable`
 
     Accepts:
 
     - an optional ``next`` `Function`.  Without a ``next`` function,
       returns an empty iteration.
     - an optional ``hasNext`` `Function``.
 
 */
 /**** next */
 /**** hasNext */
 
 /*** iter
     Returns an iteration of a given object.  Attempts
     to call the polymorphic `iter` of a typed object.
     Otherwise, coerces to the first applicable of 
     `String`, `Array`, or `Object` types.
 */
 
 /*** objectIter */
 /*** arrayIter */
 /*** stringIter */
 
 
 /**
     Top Level Functions
     ===================
 
     Functions that operate on iterables, or objects
     coercible to iterables using the polymorphic `iter`
     function.
 */
 
 /*** forEach */
 /*** forEachApply */
 /*** each */
 /*** each */
 /*** eachIter */
 /*** eachApply */
 /*** eachApplyIter */
 /*** where */
 /*** whereIter */
 /*** whereApply */
 /*** whereApplyIter */
 /*** map */
 /*** mapIter */
 /*** forTimes */
 /*** timesIter */
 /*** times */
 /*** transpose */
 /*** transposeIter */
 /*** zip */
 /*** zipIter
 /*** enumerate */
 /*** enumerateIter */
 /*** reduce */
 /*** cycle */
 /*** chain */
 /*** repeat */
 /*** flatten */
 /*** compact */
 /*** compactIter */
 /*** without */
 /*** withoutIter */
 /*** group */
 /*** all */
 /*** any */
 /*** min */
 /*** max */</text>
    </revision>
    <revision>
      <id>987</id>
      <timestamp>2009-09-10T03:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/iter/ProposalK]] to [[OldAPI/iter/ProposalK]]</comment>
      <text xml:space="preserve"> 
 /*** Iterable
     a mixin that adds convenience functions to types
     that implement `iter`.
 */
 
 /**** iter
     a default ``iter`` that returns itself.
 */
 /**** added */
 /**** nextCatch */
 /**** len
     a default, destructive implementation
     of `len` that consumes the remaining elements
     of the iteration and returns how many were
     encountered.
 */
 /**** toObject */
 /**** toArray */
 /**** toList */
 /**** toDict */
 /**** toUnique
     returns a `Set` of the unique elements of the iterable.
 */
 /**** toString
     returns the concatenation of the elements of the 
     iterable coerced into `String` objects.
 */
 /**** toNumber
     a polymorphic alias of `len`.
 */
 /**** toBoolean
     returns whether `toNumber` is greater than 0.
 */
 /**** sliced */
 /**** forEach */
 /**** forEachApply */
 /**** each */
 /**** eachIter */
 /**** eachApply */
 /**** eachApplyIter */
 /**** where */
 /**** whereIter */
 /**** whereApply */
 /**** whereApplyIter */
 /**** zip */
 /**** zipIter */
 /**** transpose */
 /**** transposeIter */
 /**** enumerate */
 /**** enumerateIter */
 /**** reduce */
 /**** reduced */
 /**** flatten */
 /**** flattened */
 /**** group */
 /**** sorted */
 /**** reversed */
 /**** min */
 /**** mix */
 /**** sum */
 /**** product */
 /**** all */
 /**** any */
 /**** join */
 
 
 /*** Iter
     - :is:`Iterable`
 
     Accepts:
 
     - an optional ``next`` `Function`.  Without a ``next`` function,
       returns an empty iteration.
     - an optional ``hasNext`` `Function``.
 
 */
 /**** next */
 /**** hasNext */
 
 /*** iter
     Returns an iteration of a given object.  Attempts
     to call the polymorphic `iter` of a typed object.
     Otherwise, coerces to the first applicable of 
     `String`, `Array`, or `Object` types.
 */
 
 /*** objectIter */
 /*** arrayIter */
 /*** stringIter */
 
 
 /**
     Top Level Functions
     ===================
 
     Functions that operate on iterables, or objects
     coercible to iterables using the polymorphic `iter`
     function.
 */
 
 /*** forEach */
 /*** forEachApply */
 /*** each */
 /*** each */
 /*** eachIter */
 /*** eachApply */
 /*** eachApplyIter */
 /*** where */
 /*** whereIter */
 /*** whereApply */
 /*** whereApplyIter */
 /*** map */
 /*** mapIter */
 /*** forTimes */
 /*** timesIter */
 /*** times */
 /*** transpose */
 /*** transposeIter */
 /*** zip */
 /*** zipIter
 /*** enumerate */
 /*** enumerateIter */
 /*** reduce */
 /*** cycle */
 /*** chain */
 /*** repeat */
 /*** flatten */
 /*** compact */
 /*** compactIter */
 /*** without */
 /*** withoutIter */
 /*** group */
 /*** all */
 /*** any */
 /*** min */
 /*** max */</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/list/ProposalK</title>
    <id>14</id>
    <revision>
      <id>88</id>
      <timestamp>2009-02-18T22:15:15Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Added a proposal for a lists module for ServerJS</comment>
      <text xml:space="preserve"> 
 /*** List 
     is `Iterable`
 
     Different than Python:
 
     - append: `push`
     - extend: `add`
     - count: `len`
     - index: `find`
     - insert: `put`
     - remove: `del`
 
     Same as Python:
 
     - `pop`
     - `sort`
     - `reverse`
 
 */
 
     /**** toIter
         - `stateless`
     */
 
     /**** len
         - `stateless`
     */
 
     /**** push
         - `stateful`
         - `chainable`
     */
 
     /**** pop
         - `stateful`
     */
 
     /**** unshift
         - `stateful`
         - `chainable`
     */
 
     /**** shift
         - `stateful`
     */
 
     /**** reverse
         - `stateful`
         - `chainable`
     */
 
     /**** reversed
         - `stateless`
     */
 
     /**** reversedIter
         - `stateless`
     */
 
     /**** sort
         - `stateful`
         - `chainable`
     */
 
     /**** sorted
         - `stateless`
         - `chainable`
     */
 
     /**** slice
         - `stateful`
         - `chainable`
     */
 
     /**** sliced
         - `stateless`
         - `chainable`
     */
 
     /**** splice
         - `stateful`
     */
 
     /**** spliced
         - `stateless`
         - `chainable`
     */
 
     /**** clear
         - `stateful`
         - `chainable`
     */
 
     /**** first
         - `stateless`
     */
 
     /**** last
         - `stateless`
     */
 
     /**** begins
         returns whether the first elements of
         a given list-like-object are equal, by way of `eq`,
         the respective elements in this list.
 
         In Python, this function is called ``startswith``.
         This divergence from Python nomenclature is
         a matter of idealism.  Ideally the semantic group
         of `start`, `stop`, `pause`, `resume`,
         and `run` are all temporal verbs, whereas the
         semantic group `begins`, `ends`, `first`,
         `last`, and such all apply to the state of
         spatial segments or lists.
 
         - `stateless`
     */
 
     /**** ends
         returns whether the last elements of a given
         list-like-object are equal, by way of `eq`,
         the respective elements in this list.
 
         In Python, this function is called ``endsWith``.
         See ``startsWith`` for the rationale.
 
         - `stateless`
     */
 
     /**** reduce
         reduce is an in place operation.
         see reduced for a stateless variant
 
         - `stateful`
         - `chainable`
     */
 
     /**** keysIter
         - `stateless`
     */
 
     /**** keys
         - `stateless`
     */
 
     /**** valuesIter
         - `stateless`
     */
 
     /**** values
         an alias of `copy` so that lists can be used
         as dictionary like objects.
 
         - `stateless`
     */
 
     /**** itemsIter
         enumerates the values of the list.
 
         - `stateless`
     */
 
     /**** items
         returns a list of the enumerated values from 
         this list, using `itemsIter`.
 
         - `stateless`
     */
 
     /**** get
         gets a value by its offset.
 
         - `stateless`
     */
 
     /**** set
         sets a value at a particular offset.
 
         - `stateful`
         - `chainable`
     */
 
     /**** put
         displaces the item at a given index, sending
         successive elements down the line.
 
         - `stateful`
         - `chainable`
     */
 
     /**** cut
         gets the value at a given offset and delete
         the value from the list.
 
         - `stateful`
     */
 
     /**** del
         removes a value from the list, shifting all
         successive values into its void.
         
         - `stateful`
         - `chainable`
     */
 
     /**** has
         returns whether the list contains
         a given value.
 
         - `stateless`
     */
 
     /**** hasKey
         returns whether the list contains a value
         at a given index.
 
         - `stateless`
     */
 
     /**** hasValue
         retunrs whether the list contains
         a given value.
         Uses `has`.
 
         - `stateless`
     */
 
     /**** find
         returns the first index of a given value
         in the list, or throws a `ValueError`
         if none can be found.
 
         - `stateless`
     */
 
     /**** findReverse
         returns the last index of a given value
         in the list, or throws a `ValueError`
         if none can be found.
 
         - `stateless`
     */
 
 
     /**** insert
         an alias of `push`
     */
     /**** retrieve */
     /**** remove */
     /**** discard */
 
     /**** add
         - `stateful`
         - `chainable`
     */
 
     /**** added
         - `stateless`
         - `chainable`
     */
 
     /**** eq
         returns whether this list has the same cardinality, order,
         and respective values as another object.
 
         - `stateless`
     */
 
     /**** lt
         returns whether the the most significant, distinct
         value between the respective values of this list and another
         list-like object is less than the other.
 
         - `stateless`
     */
 
     /**** join
         returns a `String` of the joined string values of
         the values in this list, on a given delimiter or simply
         concatenated.
 
         - `stateless`
     */
 
     /**** repr
         - `stateless`
     */
 
     /**** toArray
         - `stateless`
     */
 
     /**** hash
         - `stateless`
     */
 
 /*** toList
     constructs a `List` from any given iterable.
     Defers to a `toList` or `toIter` method of the given
     object if it exists.
 
     - `poymorphic` on `toList` or `toIter`
 */
 
 /*** toArray
     constructs a native JavaScript `Array` from
     any iterable.
 
     - `polymorphic` on `toArray` or `toIter`
 */
 
 /*** len
     returns the length of a `List`, `Array`, `Object`,
     or any other object that provides a `len` member
     function.
 
     - `polymorphic`
 */
 
 /*** reversed
     returns a `List` of the values from an iterable
     in reversed order.
 
     - `stateless`
 */
 
 /*** sorted
     returns a `List` of the values in a given `Iteration` in
     sorted order.  Accepts an optional override of `compare`,
     a binary relation that returns a `Number` that has the same
     comparison relationship with ``0`` as the relationship between
     the given values.  For example, ``-1`` if the first is less
     than the second, or ``0`` if they are equal.
 
     - `stateless`
 */
 
 /*** slice
     - `polymorphic`
     - `not-curry`
     - `stateless`
 */
 
 /*** splice
 */</text>
    </revision>
    <revision>
      <id>89</id>
      <timestamp>2009-09-09T22:13:58Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>1 revision:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve"> 
 /*** List 
     is `Iterable`
 
     Different than Python:
 
     - append: `push`
     - extend: `add`
     - count: `len`
     - index: `find`
     - insert: `put`
     - remove: `del`
 
     Same as Python:
 
     - `pop`
     - `sort`
     - `reverse`
 
 */
 
     /**** toIter
         - `stateless`
     */
 
     /**** len
         - `stateless`
     */
 
     /**** push
         - `stateful`
         - `chainable`
     */
 
     /**** pop
         - `stateful`
     */
 
     /**** unshift
         - `stateful`
         - `chainable`
     */
 
     /**** shift
         - `stateful`
     */
 
     /**** reverse
         - `stateful`
         - `chainable`
     */
 
     /**** reversed
         - `stateless`
     */
 
     /**** reversedIter
         - `stateless`
     */
 
     /**** sort
         - `stateful`
         - `chainable`
     */
 
     /**** sorted
         - `stateless`
         - `chainable`
     */
 
     /**** slice
         - `stateful`
         - `chainable`
     */
 
     /**** sliced
         - `stateless`
         - `chainable`
     */
 
     /**** splice
         - `stateful`
     */
 
     /**** spliced
         - `stateless`
         - `chainable`
     */
 
     /**** clear
         - `stateful`
         - `chainable`
     */
 
     /**** first
         - `stateless`
     */
 
     /**** last
         - `stateless`
     */
 
     /**** begins
         returns whether the first elements of
         a given list-like-object are equal, by way of `eq`,
         the respective elements in this list.
 
         In Python, this function is called ``startswith``.
         This divergence from Python nomenclature is
         a matter of idealism.  Ideally the semantic group
         of `start`, `stop`, `pause`, `resume`,
         and `run` are all temporal verbs, whereas the
         semantic group `begins`, `ends`, `first`,
         `last`, and such all apply to the state of
         spatial segments or lists.
 
         - `stateless`
     */
 
     /**** ends
         returns whether the last elements of a given
         list-like-object are equal, by way of `eq`,
         the respective elements in this list.
 
         In Python, this function is called ``endsWith``.
         See ``startsWith`` for the rationale.
 
         - `stateless`
     */
 
     /**** reduce
         reduce is an in place operation.
         see reduced for a stateless variant
 
         - `stateful`
         - `chainable`
     */
 
     /**** keysIter
         - `stateless`
     */
 
     /**** keys
         - `stateless`
     */
 
     /**** valuesIter
         - `stateless`
     */
 
     /**** values
         an alias of `copy` so that lists can be used
         as dictionary like objects.
 
         - `stateless`
     */
 
     /**** itemsIter
         enumerates the values of the list.
 
         - `stateless`
     */
 
     /**** items
         returns a list of the enumerated values from 
         this list, using `itemsIter`.
 
         - `stateless`
     */
 
     /**** get
         gets a value by its offset.
 
         - `stateless`
     */
 
     /**** set
         sets a value at a particular offset.
 
         - `stateful`
         - `chainable`
     */
 
     /**** put
         displaces the item at a given index, sending
         successive elements down the line.
 
         - `stateful`
         - `chainable`
     */
 
     /**** cut
         gets the value at a given offset and delete
         the value from the list.
 
         - `stateful`
     */
 
     /**** del
         removes a value from the list, shifting all
         successive values into its void.
         
         - `stateful`
         - `chainable`
     */
 
     /**** has
         returns whether the list contains
         a given value.
 
         - `stateless`
     */
 
     /**** hasKey
         returns whether the list contains a value
         at a given index.
 
         - `stateless`
     */
 
     /**** hasValue
         retunrs whether the list contains
         a given value.
         Uses `has`.
 
         - `stateless`
     */
 
     /**** find
         returns the first index of a given value
         in the list, or throws a `ValueError`
         if none can be found.
 
         - `stateless`
     */
 
     /**** findReverse
         returns the last index of a given value
         in the list, or throws a `ValueError`
         if none can be found.
 
         - `stateless`
     */
 
 
     /**** insert
         an alias of `push`
     */
     /**** retrieve */
     /**** remove */
     /**** discard */
 
     /**** add
         - `stateful`
         - `chainable`
     */
 
     /**** added
         - `stateless`
         - `chainable`
     */
 
     /**** eq
         returns whether this list has the same cardinality, order,
         and respective values as another object.
 
         - `stateless`
     */
 
     /**** lt
         returns whether the the most significant, distinct
         value between the respective values of this list and another
         list-like object is less than the other.
 
         - `stateless`
     */
 
     /**** join
         returns a `String` of the joined string values of
         the values in this list, on a given delimiter or simply
         concatenated.
 
         - `stateless`
     */
 
     /**** repr
         - `stateless`
     */
 
     /**** toArray
         - `stateless`
     */
 
     /**** hash
         - `stateless`
     */
 
 /*** toList
     constructs a `List` from any given iterable.
     Defers to a `toList` or `toIter` method of the given
     object if it exists.
 
     - `poymorphic` on `toList` or `toIter`
 */
 
 /*** toArray
     constructs a native JavaScript `Array` from
     any iterable.
 
     - `polymorphic` on `toArray` or `toIter`
 */
 
 /*** len
     returns the length of a `List`, `Array`, `Object`,
     or any other object that provides a `len` member
     function.
 
     - `polymorphic`
 */
 
 /*** reversed
     returns a `List` of the values from an iterable
     in reversed order.
 
     - `stateless`
 */
 
 /*** sorted
     returns a `List` of the values in a given `Iteration` in
     sorted order.  Accepts an optional override of `compare`,
     a binary relation that returns a `Number` that has the same
     comparison relationship with ``0`` as the relationship between
     the given values.  For example, ``-1`` if the first is less
     than the second, or ``0`` if they are equal.
 
     - `stateless`
 */
 
 /*** slice
     - `polymorphic`
     - `not-curry`
     - `stateless`
 */
 
 /*** splice
 */</text>
    </revision>
    <revision>
      <id>639</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/list/ProposalK]] to [[CommonJS/API/list/ProposalK]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve"> 
 /*** List 
     is `Iterable`
 
     Different than Python:
 
     - append: `push`
     - extend: `add`
     - count: `len`
     - index: `find`
     - insert: `put`
     - remove: `del`
 
     Same as Python:
 
     - `pop`
     - `sort`
     - `reverse`
 
 */
 
     /**** toIter
         - `stateless`
     */
 
     /**** len
         - `stateless`
     */
 
     /**** push
         - `stateful`
         - `chainable`
     */
 
     /**** pop
         - `stateful`
     */
 
     /**** unshift
         - `stateful`
         - `chainable`
     */
 
     /**** shift
         - `stateful`
     */
 
     /**** reverse
         - `stateful`
         - `chainable`
     */
 
     /**** reversed
         - `stateless`
     */
 
     /**** reversedIter
         - `stateless`
     */
 
     /**** sort
         - `stateful`
         - `chainable`
     */
 
     /**** sorted
         - `stateless`
         - `chainable`
     */
 
     /**** slice
         - `stateful`
         - `chainable`
     */
 
     /**** sliced
         - `stateless`
         - `chainable`
     */
 
     /**** splice
         - `stateful`
     */
 
     /**** spliced
         - `stateless`
         - `chainable`
     */
 
     /**** clear
         - `stateful`
         - `chainable`
     */
 
     /**** first
         - `stateless`
     */
 
     /**** last
         - `stateless`
     */
 
     /**** begins
         returns whether the first elements of
         a given list-like-object are equal, by way of `eq`,
         the respective elements in this list.
 
         In Python, this function is called ``startswith``.
         This divergence from Python nomenclature is
         a matter of idealism.  Ideally the semantic group
         of `start`, `stop`, `pause`, `resume`,
         and `run` are all temporal verbs, whereas the
         semantic group `begins`, `ends`, `first`,
         `last`, and such all apply to the state of
         spatial segments or lists.
 
         - `stateless`
     */
 
     /**** ends
         returns whether the last elements of a given
         list-like-object are equal, by way of `eq`,
         the respective elements in this list.
 
         In Python, this function is called ``endsWith``.
         See ``startsWith`` for the rationale.
 
         - `stateless`
     */
 
     /**** reduce
         reduce is an in place operation.
         see reduced for a stateless variant
 
         - `stateful`
         - `chainable`
     */
 
     /**** keysIter
         - `stateless`
     */
 
     /**** keys
         - `stateless`
     */
 
     /**** valuesIter
         - `stateless`
     */
 
     /**** values
         an alias of `copy` so that lists can be used
         as dictionary like objects.
 
         - `stateless`
     */
 
     /**** itemsIter
         enumerates the values of the list.
 
         - `stateless`
     */
 
     /**** items
         returns a list of the enumerated values from 
         this list, using `itemsIter`.
 
         - `stateless`
     */
 
     /**** get
         gets a value by its offset.
 
         - `stateless`
     */
 
     /**** set
         sets a value at a particular offset.
 
         - `stateful`
         - `chainable`
     */
 
     /**** put
         displaces the item at a given index, sending
         successive elements down the line.
 
         - `stateful`
         - `chainable`
     */
 
     /**** cut
         gets the value at a given offset and delete
         the value from the list.
 
         - `stateful`
     */
 
     /**** del
         removes a value from the list, shifting all
         successive values into its void.
         
         - `stateful`
         - `chainable`
     */
 
     /**** has
         returns whether the list contains
         a given value.
 
         - `stateless`
     */
 
     /**** hasKey
         returns whether the list contains a value
         at a given index.
 
         - `stateless`
     */
 
     /**** hasValue
         retunrs whether the list contains
         a given value.
         Uses `has`.
 
         - `stateless`
     */
 
     /**** find
         returns the first index of a given value
         in the list, or throws a `ValueError`
         if none can be found.
 
         - `stateless`
     */
 
     /**** findReverse
         returns the last index of a given value
         in the list, or throws a `ValueError`
         if none can be found.
 
         - `stateless`
     */
 
 
     /**** insert
         an alias of `push`
     */
     /**** retrieve */
     /**** remove */
     /**** discard */
 
     /**** add
         - `stateful`
         - `chainable`
     */
 
     /**** added
         - `stateless`
         - `chainable`
     */
 
     /**** eq
         returns whether this list has the same cardinality, order,
         and respective values as another object.
 
         - `stateless`
     */
 
     /**** lt
         returns whether the the most significant, distinct
         value between the respective values of this list and another
         list-like object is less than the other.
 
         - `stateless`
     */
 
     /**** join
         returns a `String` of the joined string values of
         the values in this list, on a given delimiter or simply
         concatenated.
 
         - `stateless`
     */
 
     /**** repr
         - `stateless`
     */
 
     /**** toArray
         - `stateless`
     */
 
     /**** hash
         - `stateless`
     */
 
 /*** toList
     constructs a `List` from any given iterable.
     Defers to a `toList` or `toIter` method of the given
     object if it exists.
 
     - `poymorphic` on `toList` or `toIter`
 */
 
 /*** toArray
     constructs a native JavaScript `Array` from
     any iterable.
 
     - `polymorphic` on `toArray` or `toIter`
 */
 
 /*** len
     returns the length of a `List`, `Array`, `Object`,
     or any other object that provides a `len` member
     function.
 
     - `polymorphic`
 */
 
 /*** reversed
     returns a `List` of the values from an iterable
     in reversed order.
 
     - `stateless`
 */
 
 /*** sorted
     returns a `List` of the values in a given `Iteration` in
     sorted order.  Accepts an optional override of `compare`,
     a binary relation that returns a `Number` that has the same
     comparison relationship with ``0`` as the relationship between
     the given values.  For example, ``-1`` if the first is less
     than the second, or ``0`` if they are equal.
 
     - `stateless`
 */
 
 /*** slice
     - `polymorphic`
     - `not-curry`
     - `stateless`
 */
 
 /*** splice
 */</text>
    </revision>
    <revision>
      <id>989</id>
      <timestamp>2009-09-10T03:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/list/ProposalK]] to [[OldAPI/list/ProposalK]]</comment>
      <text xml:space="preserve"> 
 /*** List 
     is `Iterable`
 
     Different than Python:
 
     - append: `push`
     - extend: `add`
     - count: `len`
     - index: `find`
     - insert: `put`
     - remove: `del`
 
     Same as Python:
 
     - `pop`
     - `sort`
     - `reverse`
 
 */
 
     /**** toIter
         - `stateless`
     */
 
     /**** len
         - `stateless`
     */
 
     /**** push
         - `stateful`
         - `chainable`
     */
 
     /**** pop
         - `stateful`
     */
 
     /**** unshift
         - `stateful`
         - `chainable`
     */
 
     /**** shift
         - `stateful`
     */
 
     /**** reverse
         - `stateful`
         - `chainable`
     */
 
     /**** reversed
         - `stateless`
     */
 
     /**** reversedIter
         - `stateless`
     */
 
     /**** sort
         - `stateful`
         - `chainable`
     */
 
     /**** sorted
         - `stateless`
         - `chainable`
     */
 
     /**** slice
         - `stateful`
         - `chainable`
     */
 
     /**** sliced
         - `stateless`
         - `chainable`
     */
 
     /**** splice
         - `stateful`
     */
 
     /**** spliced
         - `stateless`
         - `chainable`
     */
 
     /**** clear
         - `stateful`
         - `chainable`
     */
 
     /**** first
         - `stateless`
     */
 
     /**** last
         - `stateless`
     */
 
     /**** begins
         returns whether the first elements of
         a given list-like-object are equal, by way of `eq`,
         the respective elements in this list.
 
         In Python, this function is called ``startswith``.
         This divergence from Python nomenclature is
         a matter of idealism.  Ideally the semantic group
         of `start`, `stop`, `pause`, `resume`,
         and `run` are all temporal verbs, whereas the
         semantic group `begins`, `ends`, `first`,
         `last`, and such all apply to the state of
         spatial segments or lists.
 
         - `stateless`
     */
 
     /**** ends
         returns whether the last elements of a given
         list-like-object are equal, by way of `eq`,
         the respective elements in this list.
 
         In Python, this function is called ``endsWith``.
         See ``startsWith`` for the rationale.
 
         - `stateless`
     */
 
     /**** reduce
         reduce is an in place operation.
         see reduced for a stateless variant
 
         - `stateful`
         - `chainable`
     */
 
     /**** keysIter
         - `stateless`
     */
 
     /**** keys
         - `stateless`
     */
 
     /**** valuesIter
         - `stateless`
     */
 
     /**** values
         an alias of `copy` so that lists can be used
         as dictionary like objects.
 
         - `stateless`
     */
 
     /**** itemsIter
         enumerates the values of the list.
 
         - `stateless`
     */
 
     /**** items
         returns a list of the enumerated values from 
         this list, using `itemsIter`.
 
         - `stateless`
     */
 
     /**** get
         gets a value by its offset.
 
         - `stateless`
     */
 
     /**** set
         sets a value at a particular offset.
 
         - `stateful`
         - `chainable`
     */
 
     /**** put
         displaces the item at a given index, sending
         successive elements down the line.
 
         - `stateful`
         - `chainable`
     */
 
     /**** cut
         gets the value at a given offset and delete
         the value from the list.
 
         - `stateful`
     */
 
     /**** del
         removes a value from the list, shifting all
         successive values into its void.
         
         - `stateful`
         - `chainable`
     */
 
     /**** has
         returns whether the list contains
         a given value.
 
         - `stateless`
     */
 
     /**** hasKey
         returns whether the list contains a value
         at a given index.
 
         - `stateless`
     */
 
     /**** hasValue
         retunrs whether the list contains
         a given value.
         Uses `has`.
 
         - `stateless`
     */
 
     /**** find
         returns the first index of a given value
         in the list, or throws a `ValueError`
         if none can be found.
 
         - `stateless`
     */
 
     /**** findReverse
         returns the last index of a given value
         in the list, or throws a `ValueError`
         if none can be found.
 
         - `stateless`
     */
 
 
     /**** insert
         an alias of `push`
     */
     /**** retrieve */
     /**** remove */
     /**** discard */
 
     /**** add
         - `stateful`
         - `chainable`
     */
 
     /**** added
         - `stateless`
         - `chainable`
     */
 
     /**** eq
         returns whether this list has the same cardinality, order,
         and respective values as another object.
 
         - `stateless`
     */
 
     /**** lt
         returns whether the the most significant, distinct
         value between the respective values of this list and another
         list-like object is less than the other.
 
         - `stateless`
     */
 
     /**** join
         returns a `String` of the joined string values of
         the values in this list, on a given delimiter or simply
         concatenated.
 
         - `stateless`
     */
 
     /**** repr
         - `stateless`
     */
 
     /**** toArray
         - `stateless`
     */
 
     /**** hash
         - `stateless`
     */
 
 /*** toList
     constructs a `List` from any given iterable.
     Defers to a `toList` or `toIter` method of the given
     object if it exists.
 
     - `poymorphic` on `toList` or `toIter`
 */
 
 /*** toArray
     constructs a native JavaScript `Array` from
     any iterable.
 
     - `polymorphic` on `toArray` or `toIter`
 */
 
 /*** len
     returns the length of a `List`, `Array`, `Object`,
     or any other object that provides a `len` member
     function.
 
     - `polymorphic`
 */
 
 /*** reversed
     returns a `List` of the values from an iterable
     in reversed order.
 
     - `stateless`
 */
 
 /*** sorted
     returns a `List` of the values in a given `Iteration` in
     sorted order.  Accepts an optional override of `compare`,
     a binary relation that returns a `Number` that has the same
     comparison relationship with ``0`` as the relationship between
     the given values.  For example, ``-1`` if the first is less
     than the second, or ``0`` if they are equal.
 
     - `stateless`
 */
 
 /*** slice
     - `polymorphic`
     - `not-curry`
     - `stateless`
 */
 
 /*** splice
 */</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/posix/ProposalK</title>
    <id>15</id>
    <revision>
      <id>90</id>
      <timestamp>2009-02-18T08:13:50Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Preliminary posix module API for ServerJS</comment>
      <text xml:space="preserve"> 
 /**
 */
 
 /*** open
 
     Accepts:
 
     - ``fileName``
     - ``mode``
 
     Returns a file descriptor of unspecified type.
 
     Modes
     =====
 
     Mode Meaning
     ==== ======================================================================
     &quot;r&quot;  read-only, starting at the beginning of the file
     &quot;r+&quot; read-write, starting at the beginning of the file
     &quot;w&quot;  write-only, truncates an existing file to empty or creates a new file
     &quot;w+&quot; read-write, truncates an existing file to empty or creates a new file
     &quot;a&quot;  write-only, starts at end of file if file exists or creates a new file
     &quot;a+&quot; read-write, starts at end of file if file exists or creates a new file
     &quot;b&quot;  binary file mode, may appear before any of the modes above
     
 
 */
 
 /*** close
 */
 
 /*** creat
 */
 
 /*** flush
 */
 
 /*** tell
 */
 
 /*** stat
 */
 
 /*** lstat
 */
 
 /*** unlink
 */
 
 /*** chown
 */
 
 /*** chmod
 */
 
 /*** dup
 */
 
 /*** dup2
 */
 
 /*** fctnl
 */
 
 /*** ioctl
 */
 
 /*** select
 */
 
 /*** getcwd
 */</text>
    </revision>
    <revision>
      <id>91</id>
      <timestamp>2009-02-18T23:02:38Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <text xml:space="preserve">The idea behind this module is that it would be implemented as a native module on each respective platform and hosted by the default loader.  Other IO modules would use these functions as a basis. 

 /**
 */
 
 /*** open
 
     Accepts:
 
     - ``fileName``
     - ``mode``
 
     Returns a file descriptor of unspecified type.
 
     Modes
     =====
 
     Mode Meaning
     ==== ======================================================================
     &quot;r&quot;  read-only, starting at the beginning of the file
     &quot;r+&quot; read-write, starting at the beginning of the file
     &quot;w&quot;  write-only, truncates an existing file to empty or creates a new file
     &quot;w+&quot; read-write, truncates an existing file to empty or creates a new file
     &quot;a&quot;  write-only, starts at end of file if file exists or creates a new file
     &quot;a+&quot; read-write, starts at end of file if file exists or creates a new file
     &quot;b&quot;  binary file mode, may appear before any of the modes above
     
 
 */
 
 /*** close
 */
 
 /*** creat
 */
 
 /*** flush
 */
 
 /*** tell
 */
 
 /*** stat
 */
 
 /*** lstat
 */
 
 /*** unlink
 */
 
 /*** chown
 */
 
 /*** chmod
 */
 
 /*** dup
 */
 
 /*** dup2
 */
 
 /*** fctnl
 */
 
 /*** ioctl
 */
 
 /*** select
 */
 
 /*** getcwd
 */</text>
    </revision>
    <revision>
      <id>92</id>
      <timestamp>2009-09-09T22:13:58Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>2 revisions:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve">The idea behind this module is that it would be implemented as a native module on each respective platform and hosted by the default loader.  Other IO modules would use these functions as a basis. 

 /**
 */
 
 /*** open
 
     Accepts:
 
     - ``fileName``
     - ``mode``
 
     Returns a file descriptor of unspecified type.
 
     Modes
     =====
 
     Mode Meaning
     ==== ======================================================================
     &quot;r&quot;  read-only, starting at the beginning of the file
     &quot;r+&quot; read-write, starting at the beginning of the file
     &quot;w&quot;  write-only, truncates an existing file to empty or creates a new file
     &quot;w+&quot; read-write, truncates an existing file to empty or creates a new file
     &quot;a&quot;  write-only, starts at end of file if file exists or creates a new file
     &quot;a+&quot; read-write, starts at end of file if file exists or creates a new file
     &quot;b&quot;  binary file mode, may appear before any of the modes above
     
 
 */
 
 /*** close
 */
 
 /*** creat
 */
 
 /*** flush
 */
 
 /*** tell
 */
 
 /*** stat
 */
 
 /*** lstat
 */
 
 /*** unlink
 */
 
 /*** chown
 */
 
 /*** chmod
 */
 
 /*** dup
 */
 
 /*** dup2
 */
 
 /*** fctnl
 */
 
 /*** ioctl
 */
 
 /*** select
 */
 
 /*** getcwd
 */</text>
    </revision>
    <revision>
      <id>641</id>
      <timestamp>2009-09-09T22:29:28Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/posix/ProposalK]] to [[CommonJS/API/posix/ProposalK]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve">The idea behind this module is that it would be implemented as a native module on each respective platform and hosted by the default loader.  Other IO modules would use these functions as a basis. 

 /**
 */
 
 /*** open
 
     Accepts:
 
     - ``fileName``
     - ``mode``
 
     Returns a file descriptor of unspecified type.
 
     Modes
     =====
 
     Mode Meaning
     ==== ======================================================================
     &quot;r&quot;  read-only, starting at the beginning of the file
     &quot;r+&quot; read-write, starting at the beginning of the file
     &quot;w&quot;  write-only, truncates an existing file to empty or creates a new file
     &quot;w+&quot; read-write, truncates an existing file to empty or creates a new file
     &quot;a&quot;  write-only, starts at end of file if file exists or creates a new file
     &quot;a+&quot; read-write, starts at end of file if file exists or creates a new file
     &quot;b&quot;  binary file mode, may appear before any of the modes above
     
 
 */
 
 /*** close
 */
 
 /*** creat
 */
 
 /*** flush
 */
 
 /*** tell
 */
 
 /*** stat
 */
 
 /*** lstat
 */
 
 /*** unlink
 */
 
 /*** chown
 */
 
 /*** chmod
 */
 
 /*** dup
 */
 
 /*** dup2
 */
 
 /*** fctnl
 */
 
 /*** ioctl
 */
 
 /*** select
 */
 
 /*** getcwd
 */</text>
    </revision>
    <revision>
      <id>991</id>
      <timestamp>2009-09-10T03:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/posix/ProposalK]] to [[OldAPI/posix/ProposalK]]</comment>
      <text xml:space="preserve">The idea behind this module is that it would be implemented as a native module on each respective platform and hosted by the default loader.  Other IO modules would use these functions as a basis. 

 /**
 */
 
 /*** open
 
     Accepts:
 
     - ``fileName``
     - ``mode``
 
     Returns a file descriptor of unspecified type.
 
     Modes
     =====
 
     Mode Meaning
     ==== ======================================================================
     &quot;r&quot;  read-only, starting at the beginning of the file
     &quot;r+&quot; read-write, starting at the beginning of the file
     &quot;w&quot;  write-only, truncates an existing file to empty or creates a new file
     &quot;w+&quot; read-write, truncates an existing file to empty or creates a new file
     &quot;a&quot;  write-only, starts at end of file if file exists or creates a new file
     &quot;a+&quot; read-write, starts at end of file if file exists or creates a new file
     &quot;b&quot;  binary file mode, may appear before any of the modes above
     
 
 */
 
 /*** close
 */
 
 /*** creat
 */
 
 /*** flush
 */
 
 /*** tell
 */
 
 /*** stat
 */
 
 /*** lstat
 */
 
 /*** unlink
 */
 
 /*** chown
 */
 
 /*** chmod
 */
 
 /*** dup
 */
 
 /*** dup2
 */
 
 /*** fctnl
 */
 
 /*** ioctl
 */
 
 /*** select
 */
 
 /*** getcwd
 */</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/set/ProposalK</title>
    <id>16</id>
    <revision>
      <id>93</id>
      <timestamp>2009-02-18T21:37:51Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Added a proposal for a sets module for ServerJS</comment>
      <text xml:space="preserve"> 
 
 /*** Set
     An unordered collection of unique values.
 
     Accepts:
 
     - optional ``values`` (may be ``undefined``, or any iterable object,
       by way of the polymorphic `toIter`)
     - optional custom ``hash`` relation.
     - optional custom ``eq`` binary equivalence relation.
 
     Inherits member functions from `Iterable`.
  
     `Set` operations operate in constant time best case,
     and linear for degenerate cases.
 
     If you insert an object in a set and modify that object
     in such a way that its ``hash`` result changes, it
     will be irrecoverable.
     Most other libraries enforce that only immutable
     objects should be inserted in sets for this reason,
     so be careful.
 
 */
 
     /*** insert
         inserts a value in the `Set`. 
         Position is not relevant.  Replaces
         an existing value if the value has the same
         `hash` key and is `eq` to an existing
         value.  The `hash` function and `eq` function
         can be overridden in the `Set` constructor.
 
          - `stateful`
          - `chainable`
     */
 
     /*** retrieve
         retrieves a value from the `Set` that has
         the same `hash` key and is `eq` to a given
         value.  `eq` and `hash` can be overridden
         in the `Set` constructor.
 
          - `stateless`
     */
 
     /**** remove
         removes a value from the `Set` if it has
         the same `hash` and is `eq` to the value.
         throws a `ValueError` if no matching value
         can be found.
 
          - `stateful`
          - `chainable`
     */
 
     /**** discard
         discards a value from the `Set` if it has
         the same `hash` and is `eq` to the value.
         Unlike `remove`, does not throw a `ValueError`
         if no matching value can be found.
 
          - `stateful`
          - `chainable`
     */
 
     /**** clear
         removes all values in this set.
 
          - `stateful`
          - `chainable`
     */
 
     /**** has
         returns whether a set contains a given value.
         uses `eq` and `hash` to attempt to find
         the value in the set.  These functions
         can be overridden in the `Set` constructor.
     */
 
     /**** find
         searches all of the values in set for one
         that is `eq` to a given value.  returns that
         value.  throws a `ValueError` if no value
         can be found.
 
          - accepts a value to find
          - accepts an optional override to the `eq` function
 
          - `stateless`
     */
 
     /**** toIter */
 
     /**** eq */
 
     /**** union
         augments itself with any values that exist in another
         iterable.
 
          - `stateful`
          - `chainable`
     */
 
     /**** intersect
          - `stateful`
          - `chainable`
     */
 
     /**** difference
          - `stateful`
          - `chainable`
     */
 
     /**** unioned
         returns all elements that are in itself and another iterable.
 
          - `stateless`
          - `chainable`
     */
 
     /**** intersected
         returns all values that are in
         this set and another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** differenced
         returns the set of all values that are
         in this set but not another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** symmetricDifferenced
         returns the set of all values that are exactly one
         set between itself and another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** isSuperSet
         returns whether this set contains all of the values
         in a given container.
 
          - `stateless`
     */
 
     /**** isSubSet
         returns whether a given container contains all of
         this set's values.
 
          - `stateless`
     */
 
     /**** added
         alias of `unioned`
 
          - `stateless`
          - `chainable`
     */
 
     /**** add
         alias of `union`
 
          - `stateful`
          - `chainable`
     */
 
     /**** muled
         alias of `intersected`
 
          - `stateless`
          - `chainable`
     */
 
     /**** mul
         alias of `intersect`
 
          - `stateful`
          - `chainable`
     */
 
     /**** subed
         alias of `differenced`
 
          - `stateless`
          - `chainable`
     */
 
     /**** sub
         alias of `difference`
 
          - `stateful`
          - `chainable`
     */
 
     /**** and
         alias of `intersect`
 
          - `stateful`
          - `chainable`
     */
 
     /**** anded
         alias of `intersected`
 
          - `stateless`
          - `chainable`
     */
 
     /**** or
         alias of `union`
 
          - `stateful`
          - `chainable`
     */
 
     /**** ored
         alias of `unioned`
 
          - `stateless`
          - `chainable`
     */
 
     /**** xor
         alias of `symmetricDifferenced`
 
          - `stateful`
          - `chainable`
     */
 
     /**** xored
         alias of `symmetricDifferenced`
 
          - `stateless`
          - `chainable`
     */
 
 /**
     Functions
     =========
 
     Functions that operate on sets, or arrays
     coercible to sets using the polymorphic
     `toSet` function.
 */
 
 /*** toSet */
 /*** insert */
 /*** retrieve */
 /*** remove */
 /*** discard */
 /*** clear */
 /*** has */
 /*** union */
 /*** intersect */
 /*** difference */
 /*** symetricDifference */
 /*** isSuperSet */
 /*** isSubSet */</text>
    </revision>
    <revision>
      <id>94</id>
      <timestamp>2009-09-09T22:13:58Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>1 revision:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve"> 
 
 /*** Set
     An unordered collection of unique values.
 
     Accepts:
 
     - optional ``values`` (may be ``undefined``, or any iterable object,
       by way of the polymorphic `toIter`)
     - optional custom ``hash`` relation.
     - optional custom ``eq`` binary equivalence relation.
 
     Inherits member functions from `Iterable`.
  
     `Set` operations operate in constant time best case,
     and linear for degenerate cases.
 
     If you insert an object in a set and modify that object
     in such a way that its ``hash`` result changes, it
     will be irrecoverable.
     Most other libraries enforce that only immutable
     objects should be inserted in sets for this reason,
     so be careful.
 
 */
 
     /*** insert
         inserts a value in the `Set`. 
         Position is not relevant.  Replaces
         an existing value if the value has the same
         `hash` key and is `eq` to an existing
         value.  The `hash` function and `eq` function
         can be overridden in the `Set` constructor.
 
          - `stateful`
          - `chainable`
     */
 
     /*** retrieve
         retrieves a value from the `Set` that has
         the same `hash` key and is `eq` to a given
         value.  `eq` and `hash` can be overridden
         in the `Set` constructor.
 
          - `stateless`
     */
 
     /**** remove
         removes a value from the `Set` if it has
         the same `hash` and is `eq` to the value.
         throws a `ValueError` if no matching value
         can be found.
 
          - `stateful`
          - `chainable`
     */
 
     /**** discard
         discards a value from the `Set` if it has
         the same `hash` and is `eq` to the value.
         Unlike `remove`, does not throw a `ValueError`
         if no matching value can be found.
 
          - `stateful`
          - `chainable`
     */
 
     /**** clear
         removes all values in this set.
 
          - `stateful`
          - `chainable`
     */
 
     /**** has
         returns whether a set contains a given value.
         uses `eq` and `hash` to attempt to find
         the value in the set.  These functions
         can be overridden in the `Set` constructor.
     */
 
     /**** find
         searches all of the values in set for one
         that is `eq` to a given value.  returns that
         value.  throws a `ValueError` if no value
         can be found.
 
          - accepts a value to find
          - accepts an optional override to the `eq` function
 
          - `stateless`
     */
 
     /**** toIter */
 
     /**** eq */
 
     /**** union
         augments itself with any values that exist in another
         iterable.
 
          - `stateful`
          - `chainable`
     */
 
     /**** intersect
          - `stateful`
          - `chainable`
     */
 
     /**** difference
          - `stateful`
          - `chainable`
     */
 
     /**** unioned
         returns all elements that are in itself and another iterable.
 
          - `stateless`
          - `chainable`
     */
 
     /**** intersected
         returns all values that are in
         this set and another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** differenced
         returns the set of all values that are
         in this set but not another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** symmetricDifferenced
         returns the set of all values that are exactly one
         set between itself and another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** isSuperSet
         returns whether this set contains all of the values
         in a given container.
 
          - `stateless`
     */
 
     /**** isSubSet
         returns whether a given container contains all of
         this set's values.
 
          - `stateless`
     */
 
     /**** added
         alias of `unioned`
 
          - `stateless`
          - `chainable`
     */
 
     /**** add
         alias of `union`
 
          - `stateful`
          - `chainable`
     */
 
     /**** muled
         alias of `intersected`
 
          - `stateless`
          - `chainable`
     */
 
     /**** mul
         alias of `intersect`
 
          - `stateful`
          - `chainable`
     */
 
     /**** subed
         alias of `differenced`
 
          - `stateless`
          - `chainable`
     */
 
     /**** sub
         alias of `difference`
 
          - `stateful`
          - `chainable`
     */
 
     /**** and
         alias of `intersect`
 
          - `stateful`
          - `chainable`
     */
 
     /**** anded
         alias of `intersected`
 
          - `stateless`
          - `chainable`
     */
 
     /**** or
         alias of `union`
 
          - `stateful`
          - `chainable`
     */
 
     /**** ored
         alias of `unioned`
 
          - `stateless`
          - `chainable`
     */
 
     /**** xor
         alias of `symmetricDifferenced`
 
          - `stateful`
          - `chainable`
     */
 
     /**** xored
         alias of `symmetricDifferenced`
 
          - `stateless`
          - `chainable`
     */
 
 /**
     Functions
     =========
 
     Functions that operate on sets, or arrays
     coercible to sets using the polymorphic
     `toSet` function.
 */
 
 /*** toSet */
 /*** insert */
 /*** retrieve */
 /*** remove */
 /*** discard */
 /*** clear */
 /*** has */
 /*** union */
 /*** intersect */
 /*** difference */
 /*** symetricDifference */
 /*** isSuperSet */
 /*** isSubSet */</text>
    </revision>
    <revision>
      <id>643</id>
      <timestamp>2009-09-09T22:29:29Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/set/ProposalK]] to [[CommonJS/API/set/ProposalK]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve"> 
 
 /*** Set
     An unordered collection of unique values.
 
     Accepts:
 
     - optional ``values`` (may be ``undefined``, or any iterable object,
       by way of the polymorphic `toIter`)
     - optional custom ``hash`` relation.
     - optional custom ``eq`` binary equivalence relation.
 
     Inherits member functions from `Iterable`.
  
     `Set` operations operate in constant time best case,
     and linear for degenerate cases.
 
     If you insert an object in a set and modify that object
     in such a way that its ``hash`` result changes, it
     will be irrecoverable.
     Most other libraries enforce that only immutable
     objects should be inserted in sets for this reason,
     so be careful.
 
 */
 
     /*** insert
         inserts a value in the `Set`. 
         Position is not relevant.  Replaces
         an existing value if the value has the same
         `hash` key and is `eq` to an existing
         value.  The `hash` function and `eq` function
         can be overridden in the `Set` constructor.
 
          - `stateful`
          - `chainable`
     */
 
     /*** retrieve
         retrieves a value from the `Set` that has
         the same `hash` key and is `eq` to a given
         value.  `eq` and `hash` can be overridden
         in the `Set` constructor.
 
          - `stateless`
     */
 
     /**** remove
         removes a value from the `Set` if it has
         the same `hash` and is `eq` to the value.
         throws a `ValueError` if no matching value
         can be found.
 
          - `stateful`
          - `chainable`
     */
 
     /**** discard
         discards a value from the `Set` if it has
         the same `hash` and is `eq` to the value.
         Unlike `remove`, does not throw a `ValueError`
         if no matching value can be found.
 
          - `stateful`
          - `chainable`
     */
 
     /**** clear
         removes all values in this set.
 
          - `stateful`
          - `chainable`
     */
 
     /**** has
         returns whether a set contains a given value.
         uses `eq` and `hash` to attempt to find
         the value in the set.  These functions
         can be overridden in the `Set` constructor.
     */
 
     /**** find
         searches all of the values in set for one
         that is `eq` to a given value.  returns that
         value.  throws a `ValueError` if no value
         can be found.
 
          - accepts a value to find
          - accepts an optional override to the `eq` function
 
          - `stateless`
     */
 
     /**** toIter */
 
     /**** eq */
 
     /**** union
         augments itself with any values that exist in another
         iterable.
 
          - `stateful`
          - `chainable`
     */
 
     /**** intersect
          - `stateful`
          - `chainable`
     */
 
     /**** difference
          - `stateful`
          - `chainable`
     */
 
     /**** unioned
         returns all elements that are in itself and another iterable.
 
          - `stateless`
          - `chainable`
     */
 
     /**** intersected
         returns all values that are in
         this set and another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** differenced
         returns the set of all values that are
         in this set but not another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** symmetricDifferenced
         returns the set of all values that are exactly one
         set between itself and another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** isSuperSet
         returns whether this set contains all of the values
         in a given container.
 
          - `stateless`
     */
 
     /**** isSubSet
         returns whether a given container contains all of
         this set's values.
 
          - `stateless`
     */
 
     /**** added
         alias of `unioned`
 
          - `stateless`
          - `chainable`
     */
 
     /**** add
         alias of `union`
 
          - `stateful`
          - `chainable`
     */
 
     /**** muled
         alias of `intersected`
 
          - `stateless`
          - `chainable`
     */
 
     /**** mul
         alias of `intersect`
 
          - `stateful`
          - `chainable`
     */
 
     /**** subed
         alias of `differenced`
 
          - `stateless`
          - `chainable`
     */
 
     /**** sub
         alias of `difference`
 
          - `stateful`
          - `chainable`
     */
 
     /**** and
         alias of `intersect`
 
          - `stateful`
          - `chainable`
     */
 
     /**** anded
         alias of `intersected`
 
          - `stateless`
          - `chainable`
     */
 
     /**** or
         alias of `union`
 
          - `stateful`
          - `chainable`
     */
 
     /**** ored
         alias of `unioned`
 
          - `stateless`
          - `chainable`
     */
 
     /**** xor
         alias of `symmetricDifferenced`
 
          - `stateful`
          - `chainable`
     */
 
     /**** xored
         alias of `symmetricDifferenced`
 
          - `stateless`
          - `chainable`
     */
 
 /**
     Functions
     =========
 
     Functions that operate on sets, or arrays
     coercible to sets using the polymorphic
     `toSet` function.
 */
 
 /*** toSet */
 /*** insert */
 /*** retrieve */
 /*** remove */
 /*** discard */
 /*** clear */
 /*** has */
 /*** union */
 /*** intersect */
 /*** difference */
 /*** symetricDifference */
 /*** isSuperSet */
 /*** isSubSet */</text>
    </revision>
    <revision>
      <id>993</id>
      <timestamp>2009-09-10T03:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/set/ProposalK]] to [[OldAPI/set/ProposalK]]</comment>
      <text xml:space="preserve"> 
 
 /*** Set
     An unordered collection of unique values.
 
     Accepts:
 
     - optional ``values`` (may be ``undefined``, or any iterable object,
       by way of the polymorphic `toIter`)
     - optional custom ``hash`` relation.
     - optional custom ``eq`` binary equivalence relation.
 
     Inherits member functions from `Iterable`.
  
     `Set` operations operate in constant time best case,
     and linear for degenerate cases.
 
     If you insert an object in a set and modify that object
     in such a way that its ``hash`` result changes, it
     will be irrecoverable.
     Most other libraries enforce that only immutable
     objects should be inserted in sets for this reason,
     so be careful.
 
 */
 
     /*** insert
         inserts a value in the `Set`. 
         Position is not relevant.  Replaces
         an existing value if the value has the same
         `hash` key and is `eq` to an existing
         value.  The `hash` function and `eq` function
         can be overridden in the `Set` constructor.
 
          - `stateful`
          - `chainable`
     */
 
     /*** retrieve
         retrieves a value from the `Set` that has
         the same `hash` key and is `eq` to a given
         value.  `eq` and `hash` can be overridden
         in the `Set` constructor.
 
          - `stateless`
     */
 
     /**** remove
         removes a value from the `Set` if it has
         the same `hash` and is `eq` to the value.
         throws a `ValueError` if no matching value
         can be found.
 
          - `stateful`
          - `chainable`
     */
 
     /**** discard
         discards a value from the `Set` if it has
         the same `hash` and is `eq` to the value.
         Unlike `remove`, does not throw a `ValueError`
         if no matching value can be found.
 
          - `stateful`
          - `chainable`
     */
 
     /**** clear
         removes all values in this set.
 
          - `stateful`
          - `chainable`
     */
 
     /**** has
         returns whether a set contains a given value.
         uses `eq` and `hash` to attempt to find
         the value in the set.  These functions
         can be overridden in the `Set` constructor.
     */
 
     /**** find
         searches all of the values in set for one
         that is `eq` to a given value.  returns that
         value.  throws a `ValueError` if no value
         can be found.
 
          - accepts a value to find
          - accepts an optional override to the `eq` function
 
          - `stateless`
     */
 
     /**** toIter */
 
     /**** eq */
 
     /**** union
         augments itself with any values that exist in another
         iterable.
 
          - `stateful`
          - `chainable`
     */
 
     /**** intersect
          - `stateful`
          - `chainable`
     */
 
     /**** difference
          - `stateful`
          - `chainable`
     */
 
     /**** unioned
         returns all elements that are in itself and another iterable.
 
          - `stateless`
          - `chainable`
     */
 
     /**** intersected
         returns all values that are in
         this set and another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** differenced
         returns the set of all values that are
         in this set but not another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** symmetricDifferenced
         returns the set of all values that are exactly one
         set between itself and another.
 
          - `stateless`
          - `chainable`
     */
 
     /**** isSuperSet
         returns whether this set contains all of the values
         in a given container.
 
          - `stateless`
     */
 
     /**** isSubSet
         returns whether a given container contains all of
         this set's values.
 
          - `stateless`
     */
 
     /**** added
         alias of `unioned`
 
          - `stateless`
          - `chainable`
     */
 
     /**** add
         alias of `union`
 
          - `stateful`
          - `chainable`
     */
 
     /**** muled
         alias of `intersected`
 
          - `stateless`
          - `chainable`
     */
 
     /**** mul
         alias of `intersect`
 
          - `stateful`
          - `chainable`
     */
 
     /**** subed
         alias of `differenced`
 
          - `stateless`
          - `chainable`
     */
 
     /**** sub
         alias of `difference`
 
          - `stateful`
          - `chainable`
     */
 
     /**** and
         alias of `intersect`
 
          - `stateful`
          - `chainable`
     */
 
     /**** anded
         alias of `intersected`
 
          - `stateless`
          - `chainable`
     */
 
     /**** or
         alias of `union`
 
          - `stateful`
          - `chainable`
     */
 
     /**** ored
         alias of `unioned`
 
          - `stateless`
          - `chainable`
     */
 
     /**** xor
         alias of `symmetricDifferenced`
 
          - `stateful`
          - `chainable`
     */
 
     /**** xored
         alias of `symmetricDifferenced`
 
          - `stateless`
          - `chainable`
     */
 
 /**
     Functions
     =========
 
     Functions that operate on sets, or arrays
     coercible to sets using the polymorphic
     `toSet` function.
 */
 
 /*** toSet */
 /*** insert */
 /*** retrieve */
 /*** remove */
 /*** discard */
 /*** clear */
 /*** has */
 /*** union */
 /*** intersect */
 /*** difference */
 /*** symetricDifference */
 /*** isSuperSet */
 /*** isSubSet */</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/system</title>
    <id>17</id>
    <revision>
      <id>95</id>
      <timestamp>2009-04-14T05:23:57Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Added a section for a potential &quot;system&quot; module.</comment>
      <text xml:space="preserve">See the [[ServerJS/System|System]] proposal.  It is as yet undecided whether the &quot;system&quot; object will be a free variable available to all modules, or a module that can be required.</text>
    </revision>
    <revision>
      <id>96</id>
      <timestamp>2009-09-09T22:13:59Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>1 revision:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve">See the [[ServerJS/System|System]] proposal.  It is as yet undecided whether the &quot;system&quot; object will be a free variable available to all modules, or a module that can be required.</text>
    </revision>
    <revision>
      <id>645</id>
      <timestamp>2009-09-09T22:29:29Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/system]] to [[CommonJS/API/system]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve">See the [[ServerJS/System|System]] proposal.  It is as yet undecided whether the &quot;system&quot; object will be a free variable available to all modules, or a module that can be required.</text>
    </revision>
    <revision>
      <id>789</id>
      <timestamp>2009-09-09T22:40:48Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-ServerJS +CommonJS)</comment>
      <text xml:space="preserve">See the [[CommonJS/System|System]] proposal.  It is as yet undecided whether the &quot;system&quot; object will be a free variable available to all modules, or a module that can be required.</text>
    </revision>
    <revision>
      <id>995</id>
      <timestamp>2009-09-10T03:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/system]] to [[OldAPI/system]]</comment>
      <text xml:space="preserve">See the [[CommonJS/System|System]] proposal.  It is as yet undecided whether the &quot;system&quot; object will be a free variable available to all modules, or a module that can be required.</text>
    </revision>
    <revision>
      <id>1215</id>
      <timestamp>2009-09-12T02:31:32Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-CommonJS/ +)</comment>
      <text xml:space="preserve">See the [[System|System]] proposal.  It is as yet undecided whether the &quot;system&quot; object will be a free variable available to all modules, or a module that can be required.</text>
    </revision>
    <revision>
      <id>1248</id>
      <timestamp>2009-09-12T04:41:08Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-\[\[(.+?)\|\1\]\] +[[\1]])</comment>
      <text xml:space="preserve">See the [[System]] proposal.  It is as yet undecided whether the &quot;system&quot; object will be a free variable available to all modules, or a module that can be required.</text>
    </revision>
  </page>
  <page>
    <title>OldAPI/url/ProposalK</title>
    <id>18</id>
    <revision>
      <id>97</id>
      <timestamp>2009-02-18T07:46:21Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Very early draft of an URL module for ServerJS.</comment>
      <text xml:space="preserve"> 
 /*** resolve
     returns the real, absolute, fully-qualified URL arrived
     at from a ``base`` URL following an relative ``rel`` URL.
     When no ``base`` is provided, resolves the ``rel`` URL
     relative to the current working directory.
 
     - accepts ``rel``
     - accepts an optional ``base``
 
 */
 
 /*** relative
     returns the relative URL between two fully-qualifed paths.
 */</text>
    </revision>
    <revision>
      <id>98</id>
      <timestamp>2009-09-09T22:13:59Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>1 revision:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve"> 
 /*** resolve
     returns the real, absolute, fully-qualified URL arrived
     at from a ``base`` URL following an relative ``rel`` URL.
     When no ``base`` is provided, resolves the ``rel`` URL
     relative to the current working directory.
 
     - accepts ``rel``
     - accepts an optional ``base``
 
 */
 
 /*** relative
     returns the relative URL between two fully-qualifed paths.
 */</text>
    </revision>
    <revision>
      <id>647</id>
      <timestamp>2009-09-09T22:29:29Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/API/url/ProposalK]] to [[CommonJS/API/url/ProposalK]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve"> 
 /*** resolve
     returns the real, absolute, fully-qualified URL arrived
     at from a ``base`` URL following an relative ``rel`` URL.
     When no ``base`` is provided, resolves the ``rel`` URL
     relative to the current working directory.
 
     - accepts ``rel``
     - accepts an optional ``base``
 
 */
 
 /*** relative
     returns the relative URL between two fully-qualifed paths.
 */</text>
    </revision>
    <revision>
      <id>997</id>
      <timestamp>2009-09-10T03:13:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/API/url/ProposalK]] to [[OldAPI/url/ProposalK]]</comment>
      <text xml:space="preserve"> 
 /*** resolve
     returns the real, absolute, fully-qualified URL arrived
     at from a ``base`` URL following an relative ``rel`` URL.
     When no ``base`` is provided, resolves the ``rel`` URL
     relative to the current working directory.
 
     - accepts ``rel``
     - accepts an optional ``base``
 
 */
 
 /*** relative
     returns the relative URL between two fully-qualifed paths.
 */</text>
    </revision>
  </page>
  <page>
    <title>Binary</title>
    <id>19</id>
    <revision>
      <id>99</id>
      <timestamp>2009-02-05T07:54:39Z</timestamp>
      <contributor>
        <ip>Ondras</ip>
      </contributor>
      <comment>New page: == Binary Data ==  JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/t...</comment>
      <text xml:space="preserve">== Binary Data ==

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/tt&gt; class.

=== Binary() object proposition ===

This is an interface of my proposed Binary object.

 /**
  * Creates a new variable holding binary data.
  * @param {number} initialData Variable amount if intial arguments. 
    Every number represents a byte.
  * @returns {Binary}
  */
 function Binary(initialData) {};

 /**
  * Converts the binary variable to string by UTF-8 encoding its contents.
  * @returns {string}
  */
 Binary.prototype.toString = function() {};

 /**
  * Returns a byte value from a given index.
  * @param {number} index
  * @returns {number}
  */
 Binary.prototype.getByte = function(index) {};

 /**
  * Sets a byte value at given index.
  * @param {number} index
  */
 Binary.prototype.setByte = function(index, value) {};

 /**
  * These are essentialy copied from the Array class.
  */
 Binary.prototype.pop = function() {};
 Binary.prototype.push = function() {};
 Binary.prototype.shift = function() {};
 Binary.prototype.unshift = function() {};

 /**
  * Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Calculates MD5 hash
  * @returns {string}
  */
 Binary.prototype.md5 = function() {};

 /**
  * Calculates SHA1 hash
  * @returns {string}
  */
 Binary.prototype.sha1 = function() {};

 /**
  * Decodes Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Decodes the Base64 encoded string
  * @returns {Binary}
  */
 String.prototype.base64decode = function() {};

 /**
  * Converts an UTF-8 encoded string into its binary (one byte per item) variant
  * @returns {Binary}
  */
 String.prototype.toBinary = function() {};</text>
    </revision>
    <revision>
      <id>100</id>
      <timestamp>2009-02-05T07:56:44Z</timestamp>
      <contributor>
        <ip>Ondras</ip>
      </contributor>
      <comment>/* Binary() object proposition */</comment>
      <text xml:space="preserve">== Binary Data ==

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/tt&gt; class.

=== Binary() object proposition ===

This is an interface of my proposed Binary object.

 /**
  * Creates a new variable holding binary data.
  * @param {number} initialData Variable amount if intial arguments. 
    Every number represents a byte.
  * @returns {Binary}
  */
 function Binary(initialData) {};

 /**
  * Returns the number of bytes stored in this structure.
  * This is intentionally named &quot;getLength&quot; instead of &quot;length&quot; to indicate a method (and not a property).
  * @returns {number}
  */
 Binary.prototype.getLength = function() {};

 /**
  * Converts the binary variable to string by UTF-8 encoding its contents.
  * @returns {string}
  */
 Binary.prototype.toString = function() {};

 /**
  * Returns a byte value from a given index.
  * @param {number} index
  * @returns {number}
  */
 Binary.prototype.getByte = function(index) {};

 /**
  * Sets a byte value at given index.
  * @param {number} index
  */
 Binary.prototype.setByte = function(index, value) {};

 /**
  * These are essentialy copied from the Array class.
  */
 Binary.prototype.pop = function() {};
 Binary.prototype.push = function() {};
 Binary.prototype.shift = function() {};
 Binary.prototype.unshift = function() {};

 /**
  * Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Calculates MD5 hash
  * @returns {string}
  */
 Binary.prototype.md5 = function() {};

 /**
  * Calculates SHA1 hash
  * @returns {string}
  */
 Binary.prototype.sha1 = function() {};

 /**
  * Decodes Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Decodes the Base64 encoded string
  * @returns {Binary}
  */
 String.prototype.base64decode = function() {};

 /**
  * Converts an UTF-8 encoded string into its binary (one byte per item) variant
  * @returns {Binary}
  */
 String.prototype.toBinary = function() {};</text>
    </revision>
    <revision>
      <id>101</id>
      <timestamp>2009-02-05T08:22:25Z</timestamp>
      <contributor>
        <ip>Ondras</ip>
      </contributor>
      <comment>/* Binary() object proposition */</comment>
      <text xml:space="preserve">== Binary Data ==

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/tt&gt; class.

=== Binary() object proposition ===

This is an interface of my proposed Binary object. I also created a sample implementation, see [[http://tmp.zarovi.cz/binary.js]].

 /**
  * Creates a new variable holding binary data.
  * @param {number} initialData Variable amount if intial arguments. 
    Every number represents a byte.
  * @returns {Binary}
  */
 function Binary(initialData) {};

 /**
  * Returns the number of bytes stored in this structure.
  * This is intentionally named &quot;getLength&quot; instead of &quot;length&quot; to indicate a method (and not a property).
  * @returns {number}
  */
 Binary.prototype.getLength = function() {};

 /**
  * Converts the binary variable to string by UTF-8 encoding its contents.
  * @returns {string}
  */
 Binary.prototype.toString = function() {};

 /**
  * Returns a byte value from a given index.
  * @param {number} index
  * @returns {number}
  */
 Binary.prototype.getByte = function(index) {};

 /**
  * Sets a byte value at given index.
  * @param {number} index
  */
 Binary.prototype.setByte = function(index, value) {};

 /**
  * These are essentialy copied from the Array class.
  */
 Binary.prototype.pop = function() {};
 Binary.prototype.push = function() {};
 Binary.prototype.shift = function() {};
 Binary.prototype.unshift = function() {};

 /**
  * Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Calculates MD5 hash
  * @returns {string}
  */
 Binary.prototype.md5 = function() {};

 /**
  * Calculates SHA1 hash
  * @returns {string}
  */
 Binary.prototype.sha1 = function() {};

 /**
  * Decodes Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Decodes the Base64 encoded string
  * @returns {Binary}
  */
 String.prototype.base64decode = function() {};

 /**
  * Converts an UTF-8 encoded string into its binary (one byte per item) variant
  * @returns {Binary}
  */
 String.prototype.toBinary = function() {};</text>
    </revision>
    <revision>
      <id>102</id>
      <timestamp>2009-02-05T08:24:28Z</timestamp>
      <contributor>
        <ip>Ondras</ip>
      </contributor>
      <comment>/* Binary() object proposition */</comment>
      <text xml:space="preserve">== Binary Data ==

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/tt&gt; class.

=== Binary() object proposition ===

This is an interface of my proposed Binary object. I also created a sample implementation, see http://tmp.zarovi.cz/binary.js.

 /**
  * Creates a new variable holding binary data.
  * @param {number} initialData Variable amount if intial arguments. 
    Every number represents a byte.
  * @returns {Binary}
  */
 function Binary(initialData) {};

 /**
  * Returns the number of bytes stored in this structure.
  * This is intentionally named &quot;getLength&quot; instead of &quot;length&quot; to indicate a method (and not a property).
  * @returns {number}
  */
 Binary.prototype.getLength = function() {};

 /**
  * Converts the binary variable to string by UTF-8 encoding its contents.
  * @returns {string}
  */
 Binary.prototype.toString = function() {};

 /**
  * Returns a byte value from a given index.
  * @param {number} index
  * @returns {number}
  */
 Binary.prototype.getByte = function(index) {};

 /**
  * Sets a byte value at given index.
  * @param {number} index
  */
 Binary.prototype.setByte = function(index, value) {};

 /**
  * These are essentialy copied from the Array class.
  */
 Binary.prototype.pop = function() {};
 Binary.prototype.push = function() {};
 Binary.prototype.shift = function() {};
 Binary.prototype.unshift = function() {};

 /**
  * Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Calculates MD5 hash
  * @returns {string}
  */
 Binary.prototype.md5 = function() {};

 /**
  * Calculates SHA1 hash
  * @returns {string}
  */
 Binary.prototype.sha1 = function() {};

 /**
  * Decodes Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Decodes the Base64 encoded string
  * @returns {Binary}
  */
 String.prototype.base64decode = function() {};

 /**
  * Converts an UTF-8 encoded string into its binary (one byte per item) variant
  * @returns {Binary}
  */
 String.prototype.toBinary = function() {};

[[User:Ondras|Ondras]] 08:24, 5 February 2009 (UTC)</text>
    </revision>
    <revision>
      <id>103</id>
      <timestamp>2009-02-05T08:28:35Z</timestamp>
      <contributor>
        <ip>Ondras</ip>
      </contributor>
      <comment>/* Binary() object proposition */</comment>
      <text xml:space="preserve">== Binary Data ==

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/tt&gt; class.

=== Binary() object proposition ===

This is an interface of my proposed Binary object. I also created a sample implementation, see http://tmp.zarovi.cz/binary.js.

 /**
  * Creates a new variable holding binary data.
  * @param {number} initialData Variable amount if initial arguments. 
    Every number represents a byte.
  * @returns {Binary}
  */
 function Binary(initialData) {};

 /**
  * Returns the number of bytes stored in this structure.
  * This is intentionally named &quot;getLength&quot; instead of &quot;length&quot; to indicate a method (and not a property).
  * @returns {number}
  */
 Binary.prototype.getLength = function() {};

 /**
  * Converts the binary variable to string by UTF-8 encoding its contents.
  * @returns {string}
  */
 Binary.prototype.toString = function() {};

 /**
  * Returns a byte value from a given index.
  * @param {number} index
  * @returns {number}
  */
 Binary.prototype.getByte = function(index) {};

 /**
  * Sets a byte value at given index.
  * @param {number} index
  */
 Binary.prototype.setByte = function(index, value) {};

 /**
  * These are essentialy copied from the Array class.
  */
 Binary.prototype.pop = function() {};
 Binary.prototype.push = function() {};
 Binary.prototype.shift = function() {};
 Binary.prototype.unshift = function() {};

 /**
  * Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Calculates MD5 hash
  * @returns {string}
  */
 Binary.prototype.md5 = function() {};

 /**
  * Calculates SHA1 hash
  * @returns {string}
  */
 Binary.prototype.sha1 = function() {};

 /**
  * Decodes Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Decodes the Base64 encoded string
  * @returns {Binary}
  */
 String.prototype.base64decode = function() {};

 /**
  * Converts an UTF-8 encoded string into its binary (one byte per item) variant
  * @returns {Binary}
  */
 String.prototype.toBinary = function() {};

[[User:Ondras|Ondras]] 08:24, 5 February 2009 (UTC)</text>
    </revision>
    <revision>
      <id>104</id>
      <timestamp>2009-03-05T01:00:49Z</timestamp>
      <contributor>
        <ip>Atesgoral</ip>
      </contributor>
      <comment>Removed duplicate base64encode</comment>
      <text xml:space="preserve">== Binary Data ==

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/tt&gt; class.

=== Binary() object proposition ===

This is an interface of my proposed Binary object. I also created a sample implementation, see http://tmp.zarovi.cz/binary.js.

 /**
  * Creates a new variable holding binary data.
  * @param {number} initialData Variable amount if initial arguments. 
    Every number represents a byte.
  * @returns {Binary}
  */
 function Binary(initialData) {};

 /**
  * Returns the number of bytes stored in this structure.
  * This is intentionally named &quot;getLength&quot; instead of &quot;length&quot; to indicate a method (and not a property).
  * @returns {number}
  */
 Binary.prototype.getLength = function() {};

 /**
  * Converts the binary variable to string by UTF-8 encoding its contents.
  * @returns {string}
  */
 Binary.prototype.toString = function() {};

 /**
  * Returns a byte value from a given index.
  * @param {number} index
  * @returns {number}
  */
 Binary.prototype.getByte = function(index) {};

 /**
  * Sets a byte value at given index.
  * @param {number} index
  */
 Binary.prototype.setByte = function(index, value) {};

 /**
  * These are essentialy copied from the Array class.
  */
 Binary.prototype.pop = function() {};
 Binary.prototype.push = function() {};
 Binary.prototype.shift = function() {};
 Binary.prototype.unshift = function() {};

 /**
  * Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Calculates MD5 hash
  * @returns {string}
  */
 Binary.prototype.md5 = function() {};

 /**
  * Calculates SHA1 hash
  * @returns {string}
  */
 Binary.prototype.sha1 = function() {};

 /**
  * Decodes the Base64 encoded string
  * @returns {Binary}
  */
 String.prototype.base64decode = function() {};

 /**
  * Converts an UTF-8 encoded string into its binary (one byte per item) variant
  * @returns {Binary}
  */
 String.prototype.toBinary = function() {};

[[User:Ondras|Ondras]] 08:24, 5 February 2009 (UTC)</text>
    </revision>
    <revision>
      <id>105</id>
      <timestamp>2009-04-08T06:47:59Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Reorganized the binary type discussion page to include information from the mailing list and make room for more proposals.</comment>
      <text xml:space="preserve">= Proposals =

# [[ServerJS/Binary/A]] Proposal A from Ondras
# [[ServerJS/Binary/B]] Proposal B from Kris Kowal

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/serverjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]</text>
    </revision>
    <revision>
      <id>106</id>
      <timestamp>2009-04-08T08:02:42Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[ServerJS/Binary/A]] Proposal A from Ondras
# [[ServerJS/Binary/B]] Proposal B from Kris Kowal

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/serverjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]</text>
    </revision>
    <revision>
      <id>107</id>
      <timestamp>2009-04-11T08:12:01Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>/* Relevant Discussions */ added discussion links</comment>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[ServerJS/Binary/A]] Proposal A from Ondras
# [[ServerJS/Binary/B]] Proposal B from Kris Kowal

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/serverjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[ServerJS/Encodings|Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>108</id>
      <timestamp>2009-04-22T22:39:58Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>/* Prior Art */</comment>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[ServerJS/Binary/A]] Proposal A from Ondras
# [[ServerJS/Binary/B]] Proposal B from Kris Kowal

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob]

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/serverjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[ServerJS/Encodings|Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>109</id>
      <timestamp>2009-07-30T19:46:15Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[ServerJS/Binary/A]] Proposal A from Ondras
# [[ServerJS/Binary/B]] Proposal B from Kris Kowal
# [[ServerJS/Binary/C]] Proposal C from Daniel Friesen

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob]

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/serverjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[ServerJS/Encodings|Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>110</id>
      <timestamp>2009-07-30T22:09:58Z</timestamp>
      <contributor>
        <username>Ashb</username>
        <id>7</id>
      </contributor>
      <minor/>
      <comment>/* Prior Art */</comment>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[ServerJS/Binary/A]] Proposal A from Ondras
# [[ServerJS/Binary/B]] Proposal B from Kris Kowal
# [[ServerJS/Binary/C]] Proposal C from Daniel Friesen

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/serverjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[ServerJS/Encodings|Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>111</id>
      <timestamp>2009-09-09T22:14:00Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>12 revisions:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[ServerJS/Binary/A]] Proposal A from Ondras
# [[ServerJS/Binary/B]] Proposal B from Kris Kowal
# [[ServerJS/Binary/C]] Proposal C from Daniel Friesen

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/serverjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[ServerJS/Encodings|Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>649</id>
      <timestamp>2009-09-09T22:29:29Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/Binary]] to [[CommonJS/Binary]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[ServerJS/Binary/A]] Proposal A from Ondras
# [[ServerJS/Binary/B]] Proposal B from Kris Kowal
# [[ServerJS/Binary/C]] Proposal C from Daniel Friesen

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/serverjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[ServerJS/Encodings|Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>790</id>
      <timestamp>2009-09-09T22:40:59Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-ServerJS +CommonJS)</comment>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[CommonJS/Binary/A]] Proposal A from Ondras
# [[CommonJS/Binary/B]] Proposal B from Kris Kowal
# [[CommonJS/Binary/C]] Proposal C from Daniel Friesen

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/serverjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[CommonJS/Encodings|Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>827</id>
      <timestamp>2009-09-10T02:10:08Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>Robot: Automated text replacement  (-serverjs +commonjs)</comment>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[CommonJS/Binary/A]] Proposal A from Ondras
# [[CommonJS/Binary/B]] Proposal B from Kris Kowal
# [[CommonJS/Binary/C]] Proposal C from Daniel Friesen

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

= Relevant Discussions =

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[CommonJS/Encodings|Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>860</id>
      <timestamp>2009-09-10T02:45:57Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/Binary]] to [[Binary]]</comment>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[CommonJS/Binary/A]] Proposal A from Ondras
# [[CommonJS/Binary/B]] Proposal B from Kris Kowal
# [[CommonJS/Binary/C]] Proposal C from Daniel Friesen

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

= Relevant Discussions =

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[CommonJS/Encodings|Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>862</id>
      <timestamp>2009-09-10T02:46:36Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal
# [[Binary/C]] Proposal C from Daniel Friesen

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

= Relevant Discussions =

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>867</id>
      <timestamp>2009-09-10T02:47:55Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[Binary]] to [[CommonJS/Binary]] over redirect</comment>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal
# [[Binary/C]] Proposal C from Daniel Friesen

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

= Relevant Discussions =

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>869</id>
      <timestamp>2009-09-10T02:48:08Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/Binary]] to [[Binary]] over redirect</comment>
      <text xml:space="preserve">JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

= Proposals =

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal
# [[Binary/C]] Proposal C from Daniel Friesen

= Prior Art =

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

= Relevant Discussions =

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
*  [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>1194</id>
      <timestamp>2009-09-12T01:32:30Z</timestamp>
      <contributor>
        <username>KrisKowal</username>
        <id>6</id>
      </contributor>
      <minor/>
      <comment>Cataloged relevant discussions.</comment>
      <text xml:space="preserve">'''STATUS: PROPOSALS, DISCUSSION'''

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

== Proposals ==

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal
# [[Binary/C]] Proposal C from Daniel Friesen

== Prior Art ==

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

== Relevant Discussions ==

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
* [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B
* [http://groups.google.com/group/commonjs/browse_thread/thread/0680b464e775726c Binary/C - range for memcopy]
* [http://groups.google.com/group/commonjs/browse_thread/thread/8a0d9db68e81baae ByteString / ByteArray duality]
* [http://groups.google.com/group/commonjs/browse_thread/thread/3b0a3a20a67987d8 Alternate binary proposal] regarding [[Binary/C]]

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>1540</id>
      <timestamp>2009-10-03T15:56:26Z</timestamp>
      <contributor>
        <username>Ashb</username>
        <id>7</id>
      </contributor>
      <minor/>
      <text xml:space="preserve">'''STATUS: PROPOSALS, DISCUSSION'''

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

== Proposals ==

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal (implemented by a few platforms)
# [[Binary/C]] Proposal C from Daniel Friesen

== Prior Art ==

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

== Relevant Discussions ==

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
* [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B
* [http://groups.google.com/group/commonjs/browse_thread/thread/0680b464e775726c Binary/C - range for memcopy]
* [http://groups.google.com/group/commonjs/browse_thread/thread/8a0d9db68e81baae ByteString / ByteArray duality]
* [http://groups.google.com/group/commonjs/browse_thread/thread/3b0a3a20a67987d8 Alternate binary proposal] regarding [[Binary/C]]

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>1763</id>
      <timestamp>2009-11-25T09:27:14Z</timestamp>
      <contributor>
        <username>KrisKowal</username>
        <id>6</id>
      </contributor>
      <comment>first draft of binary/d posted</comment>
      <text xml:space="preserve">'''STATUS: PROPOSALS, DISCUSSION'''

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

== Proposals ==

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal (implemented by a few platforms)
# [[Binary/C]] Proposal C from Daniel Friesen
# [[Binary/D]] Proposal D from Kris Kowal (based on [[Binary/B]], -array-comprehsiveness, +bits, +radix-encoding)

== Prior Art ==

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)

== Relevant Discussions ==

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
* [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B
* [http://groups.google.com/group/commonjs/browse_thread/thread/0680b464e775726c Binary/C - range for memcopy]
* [http://groups.google.com/group/commonjs/browse_thread/thread/8a0d9db68e81baae ByteString / ByteArray duality]
* [http://groups.google.com/group/commonjs/browse_thread/thread/3b0a3a20a67987d8 Alternate binary proposal] regarding [[Binary/C]]

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>1765</id>
      <timestamp>2009-11-26T21:29:30Z</timestamp>
      <contributor>
        <username>Alexandre Morgaut</username>
        <id>40</id>
      </contributor>
      <comment>/* Prior Art */</comment>
      <text xml:space="preserve">'''STATUS: PROPOSALS, DISCUSSION'''

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

== Proposals ==

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal (implemented by a few platforms)
# [[Binary/C]] Proposal C from Daniel Friesen
# [[Binary/D]] Proposal D from Kris Kowal (based on [[Binary/B]], -array-comprehsiveness, +bits, +radix-encoding)

== Prior Art ==

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)
* [http://www.w3.org/TR/FileAPI/ W3C File API]

== Relevant Discussions ==

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
* [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B
* [http://groups.google.com/group/commonjs/browse_thread/thread/0680b464e775726c Binary/C - range for memcopy]
* [http://groups.google.com/group/commonjs/browse_thread/thread/8a0d9db68e81baae ByteString / ByteArray duality]
* [http://groups.google.com/group/commonjs/browse_thread/thread/3b0a3a20a67987d8 Alternate binary proposal] regarding [[Binary/C]]

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>1767</id>
      <timestamp>2009-11-27T12:32:00Z</timestamp>
      <contributor>
        <username>Alexandre Morgaut</username>
        <id>40</id>
      </contributor>
      <comment>/* Prior Art */</comment>
      <text xml:space="preserve">'''STATUS: PROPOSALS, DISCUSSION'''

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

== Proposals ==

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal (implemented by a few platforms)
# [[Binary/C]] Proposal C from Daniel Friesen
# [[Binary/D]] Proposal D from Kris Kowal (based on [[Binary/B]], -array-comprehsiveness, +bits, +radix-encoding)

== Prior Art ==

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)
* [http://www.w3.org/TR/FileAPI/ W3C File API] (blob, FileBlob, readAsBinaryString, readAsDateUrl)

== Relevant Discussions ==

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
* [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B
* [http://groups.google.com/group/commonjs/browse_thread/thread/0680b464e775726c Binary/C - range for memcopy]
* [http://groups.google.com/group/commonjs/browse_thread/thread/8a0d9db68e81baae ByteString / ByteArray duality]
* [http://groups.google.com/group/commonjs/browse_thread/thread/3b0a3a20a67987d8 Alternate binary proposal] regarding [[Binary/C]]

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>1768</id>
      <timestamp>2009-11-27T12:32:19Z</timestamp>
      <contributor>
        <username>Alexandre Morgaut</username>
        <id>40</id>
      </contributor>
      <minor/>
      <comment>/* Prior Art */</comment>
      <text xml:space="preserve">'''STATUS: PROPOSALS, DISCUSSION'''

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

== Proposals ==

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal (implemented by a few platforms)
# [[Binary/C]] Proposal C from Daniel Friesen
# [[Binary/D]] Proposal D from Kris Kowal (based on [[Binary/B]], -array-comprehsiveness, +bits, +radix-encoding)

== Prior Art ==

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/gen/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)
* [http://www.w3.org/TR/FileAPI/ W3C File API] (blob, FileBlob, readAsBinaryString, readAsDataUrl)

== Relevant Discussions ==

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
* [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B
* [http://groups.google.com/group/commonjs/browse_thread/thread/0680b464e775726c Binary/C - range for memcopy]
* [http://groups.google.com/group/commonjs/browse_thread/thread/8a0d9db68e81baae ByteString / ByteArray duality]
* [http://groups.google.com/group/commonjs/browse_thread/thread/3b0a3a20a67987d8 Alternate binary proposal] regarding [[Binary/C]]

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>1949</id>
      <timestamp>2010-01-07T07:34:50Z</timestamp>
      <contributor>
        <username>Mob</username>
        <id>56</id>
      </contributor>
      <minor/>
      <comment>/* Prior Art */</comment>
      <text xml:space="preserve">'''STATUS: PROPOSALS, DISCUSSION'''

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

== Proposals ==

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal (implemented by a few platforms)
# [[Binary/C]] Proposal C from Daniel Friesen
# [[Binary/D]] Proposal D from Kris Kowal (based on [[Binary/B]], -array-comprehsiveness, +bits, +radix-encoding)

== Prior Art ==

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)
* [http://www.w3.org/TR/FileAPI/ W3C File API] (blob, FileBlob, readAsBinaryString, readAsDataUrl)

== Relevant Discussions ==

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
* [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B
* [http://groups.google.com/group/commonjs/browse_thread/thread/0680b464e775726c Binary/C - range for memcopy]
* [http://groups.google.com/group/commonjs/browse_thread/thread/8a0d9db68e81baae ByteString / ByteArray duality]
* [http://groups.google.com/group/commonjs/browse_thread/thread/3b0a3a20a67987d8 Alternate binary proposal] regarding [[Binary/C]]

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>1997</id>
      <timestamp>2010-01-17T08:09:21Z</timestamp>
      <contributor>
        <username>KrisKowal</username>
        <id>6</id>
      </contributor>
      <comment>/* Proposals */ added Binary/E</comment>
      <text xml:space="preserve">'''STATUS: PROPOSALS, DISCUSSION'''

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

== Proposals ==

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal (implemented by a few platforms)
# [[Binary/C]] Proposal C from Daniel Friesen
# [[Binary/D]] Proposal D from Kris Kowal (based on [[Binary/B]], -array-comprehsiveness, +bits, +radix-encoding)
# [[Binary/E]] Proposal E (based on [[Binary/D]] with byte string &lt;nowiki&gt;[[Get]]&lt;/nowiki&gt; returning Number instead of ByteString, +Binary base type, -bits, -radix-encoding, -patching)

== Prior Art ==

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)
* [http://www.w3.org/TR/FileAPI/ W3C File API] (blob, FileBlob, readAsBinaryString, readAsDataUrl)

== Relevant Discussions ==

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
* [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B
* [http://groups.google.com/group/commonjs/browse_thread/thread/0680b464e775726c Binary/C - range for memcopy]
* [http://groups.google.com/group/commonjs/browse_thread/thread/8a0d9db68e81baae ByteString / ByteArray duality]
* [http://groups.google.com/group/commonjs/browse_thread/thread/3b0a3a20a67987d8 Alternate binary proposal] regarding [[Binary/C]]

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>2033</id>
      <timestamp>2010-01-25T12:57:25Z</timestamp>
      <contributor>
        <username>Aristid</username>
        <id>46</id>
      </contributor>
      <comment>/* Proposals */ add Lite</comment>
      <text xml:space="preserve">'''STATUS: PROPOSALS, DISCUSSION'''

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

== Proposals ==

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal (implemented by a few platforms)
# [[Binary/C]] Proposal C from Daniel Friesen
# [[Binary/D]] Proposal D from Kris Kowal (based on [[Binary/B]], -array-comprehsiveness, +bits, +radix-encoding)
# [[Binary/E]] Proposal E (based on [[Binary/D]] with byte string &lt;nowiki&gt;[[Get]]&lt;/nowiki&gt; returning Number instead of ByteString, +Binary base type, -bits, -radix-encoding, -patching)
# [[Binary/Lite]] Proposal &quot;Lite&quot; from Ondras

== Prior Art ==

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)
* [http://www.w3.org/TR/FileAPI/ W3C File API] (blob, FileBlob, readAsBinaryString, readAsDataUrl)

== Relevant Discussions ==

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
* [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B
* [http://groups.google.com/group/commonjs/browse_thread/thread/0680b464e775726c Binary/C - range for memcopy]
* [http://groups.google.com/group/commonjs/browse_thread/thread/8a0d9db68e81baae ByteString / ByteArray duality]
* [http://groups.google.com/group/commonjs/browse_thread/thread/3b0a3a20a67987d8 Alternate binary proposal] regarding [[Binary/C]]

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>2126</id>
      <timestamp>2010-02-22T00:07:51Z</timestamp>
      <contributor>
        <username>KrisKowal</username>
        <id>6</id>
      </contributor>
      <comment>/* Proposals */ added Binary/F to the index</comment>
      <text xml:space="preserve">'''STATUS: PROPOSALS, DISCUSSION'''

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

== Proposals ==

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal (implemented by a few platforms)
# [[Binary/C]] Proposal C from Daniel Friesen
# [[Binary/D]] Proposal D from Kris Kowal (based on [[Binary/B]], -array-comprehsiveness, +bits, +radix-encoding)
# [[Binary/E]] Proposal E (based on [[Binary/D]] with byte string &lt;nowiki&gt;[[Get]]&lt;/nowiki&gt; returning Number instead of ByteString, +Binary base type, -bits, -radix-encoding, -patching)
# [[Binary/Lite]] Proposal &quot;Lite&quot; from Ondras (single Binary type -charsets)
# [[Binary/F]] Proposal F (based on [[Binary/E]] but viciously trimmed, -ByteString, s/ByteArray/Buffer/ -flexible length)

== Prior Art ==

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)
* [http://www.w3.org/TR/FileAPI/ W3C File API] (blob, FileBlob, readAsBinaryString, readAsDataUrl)

== Relevant Discussions ==

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
* [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B
* [http://groups.google.com/group/commonjs/browse_thread/thread/0680b464e775726c Binary/C - range for memcopy]
* [http://groups.google.com/group/commonjs/browse_thread/thread/8a0d9db68e81baae ByteString / ByteArray duality]
* [http://groups.google.com/group/commonjs/browse_thread/thread/3b0a3a20a67987d8 Alternate binary proposal] regarding [[Binary/C]]

[[Encodings]] are a related topic.</text>
    </revision>
    <revision>
      <id>2772</id>
      <timestamp>2010-05-13T19:12:31Z</timestamp>
      <contributor>
        <username>Markm</username>
        <id>54</id>
      </contributor>
      <comment>/* Relevant Discussions */</comment>
      <text xml:space="preserve">'''STATUS: PROPOSALS, DISCUSSION'''

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working byte or binary array or string class.

== Proposals ==

# [[Binary/A]] Proposal A from Ondras
# [[Binary/B]] Proposal B from Kris Kowal (implemented by a few platforms)
# [[Binary/C]] Proposal C from Daniel Friesen
# [[Binary/D]] Proposal D from Kris Kowal (based on [[Binary/B]], -array-comprehsiveness, +bits, +radix-encoding)
# [[Binary/E]] Proposal E (based on [[Binary/D]] with byte string &lt;nowiki&gt;[[Get]]&lt;/nowiki&gt; returning Number instead of ByteString, +Binary base type, -bits, -radix-encoding, -patching)
# [[Binary/Lite]] Proposal &quot;Lite&quot; from Ondras (single Binary type -charsets)
# [[Binary/F]] Proposal F (based on [[Binary/E]] but viciously trimmed, -ByteString, s/ByteArray/Buffer/ -flexible length)

== Prior Art ==

* [http://help.adobe.com/en_US/AIR/1.1/jslr/flash/utils/ByteArray.html Adobe AIR's ByteArray]
* [https://developer.mozilla.org/En/NsIBinaryInputStream Mozilla's nsIBinaryInputStream]
* [https://developer.mozilla.org/En/NsIBinaryOutputStream Mozilla's nsIBinaryOutputStream]
* [http://www.ejscript.org/products/ejs/doc/api/ejscript/intrinsic-ByteArray.html EJScript ByteArray]
* [http://code.google.com/apis/gears/api_blob.html Google Gears Blob]
* [http://code.google.com/p/jslibs/wiki/jslang#jslang::Blob_class  JSlibs Blob]
* [http://flusspferd.org/docs/js/Blob Flusspferd Blob] [http://github.com/ruediger/flusspferd/blob/1ead764aca33aca6926b6ac85871d1482c465616/src/core/blob.jsdoc repository link] (since it has been removed, the docs might go away at some point)
* [http://www.w3.org/TR/FileAPI/ W3C File API] (blob, FileBlob, readAsBinaryString, readAsDataUrl)

== Relevant Discussions ==

* [http://groups.google.com/group/commonjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First Proposal]
* [http://groups.google.com/group/commonjs/browse_thread/thread/da076076c965d069/2cd8ac336387ceb3?lnk=gst Comments on Binary object]
* [http://groups.google.com/group/commonjs/browse_thread/thread/e866544eb3aff182/16ed57b3c78b86e1?lnk=gst Binary API Brouhaha]
* [http://groups.google.com/group/commonjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal] regarding proposal B
* [http://groups.google.com/group/commonjs/browse_thread/thread/0680b464e775726c Binary/C - range for memcopy]
* [http://groups.google.com/group/commonjs/browse_thread/thread/8a0d9db68e81baae ByteString / ByteArray duality]
* [http://groups.google.com/group/commonjs/browse_thread/thread/3b0a3a20a67987d8 Alternate binary proposal] regarding [[Binary/C]]
* [http://wiki.ecmascript.org/doku.php?id=strawman:typed_arrays Typed Arrays strawman on the EcmaScript wiki]  which cites Khronos's proposed [https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/TypedArray-spec.html TypedArray spec] as its primary source.

[[Encodings]] are a related topic.</text>
    </revision>
  </page>
  <page>
    <title>Binary/A</title>
    <id>20</id>
    <revision>
      <id>112</id>
      <timestamp>2009-04-08T02:22:40Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Movied first proposal for the binary API to a subpage.</comment>
      <text xml:space="preserve">== Binary Data ==

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/tt&gt; class.

=== Binary() object proposition ===

This is an interface of my proposed Binary object. I also created a sample implementation, see http://tmp.zarovi.cz/binary.js.

 /**
  * Creates a new variable holding binary data.
  * @param {number} initialData Variable amount if initial arguments. 
    Every number represents a byte.
  * @returns {Binary}
  */
 function Binary(initialData) {};

 /**
  * Returns the number of bytes stored in this structure.
  * This is intentionally named &quot;getLength&quot; instead of &quot;length&quot; to indicate a method (and not a property).
  * @returns {number}
  */
 Binary.prototype.getLength = function() {};

 /**
  * Converts the binary variable to string by UTF-8 encoding its contents.
  * @returns {string}
  */
 Binary.prototype.toString = function() {};

 /**
  * Returns a byte value from a given index.
  * @param {number} index
  * @returns {number}
  */
 Binary.prototype.getByte = function(index) {};

 /**
  * Sets a byte value at given index.
  * @param {number} index
  */
 Binary.prototype.setByte = function(index, value) {};

 /**
  * These are essentialy copied from the Array class.
  */
 Binary.prototype.pop = function() {};
 Binary.prototype.push = function() {};
 Binary.prototype.shift = function() {};
 Binary.prototype.unshift = function() {};

 /**
  * Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Calculates MD5 hash
  * @returns {string}
  */
 Binary.prototype.md5 = function() {};

 /**
  * Calculates SHA1 hash
  * @returns {string}
  */
 Binary.prototype.sha1 = function() {};

 /**
  * Decodes the Base64 encoded string
  * @returns {Binary}
  */
 String.prototype.base64decode = function() {};

 /**
  * Converts an UTF-8 encoded string into its binary (one byte per item) variant
  * @returns {Binary}
  */
 String.prototype.toBinary = function() {};

[[User:Ondras|Ondras]] 08:24, 5 February 2009 (UTC)</text>
    </revision>
    <revision>
      <id>113</id>
      <timestamp>2009-09-09T22:14:00Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>1 revision:&amp;#32;Import from https://wiki.mozilla.org/ServerJS</comment>
      <text xml:space="preserve">== Binary Data ==

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/tt&gt; class.

=== Binary() object proposition ===

This is an interface of my proposed Binary object. I also created a sample implementation, see http://tmp.zarovi.cz/binary.js.

 /**
  * Creates a new variable holding binary data.
  * @param {number} initialData Variable amount if initial arguments. 
    Every number represents a byte.
  * @returns {Binary}
  */
 function Binary(initialData) {};

 /**
  * Returns the number of bytes stored in this structure.
  * This is intentionally named &quot;getLength&quot; instead of &quot;length&quot; to indicate a method (and not a property).
  * @returns {number}
  */
 Binary.prototype.getLength = function() {};

 /**
  * Converts the binary variable to string by UTF-8 encoding its contents.
  * @returns {string}
  */
 Binary.prototype.toString = function() {};

 /**
  * Returns a byte value from a given index.
  * @param {number} index
  * @returns {number}
  */
 Binary.prototype.getByte = function(index) {};

 /**
  * Sets a byte value at given index.
  * @param {number} index
  */
 Binary.prototype.setByte = function(index, value) {};

 /**
  * These are essentialy copied from the Array class.
  */
 Binary.prototype.pop = function() {};
 Binary.prototype.push = function() {};
 Binary.prototype.shift = function() {};
 Binary.prototype.unshift = function() {};

 /**
  * Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Calculates MD5 hash
  * @returns {string}
  */
 Binary.prototype.md5 = function() {};

 /**
  * Calculates SHA1 hash
  * @returns {string}
  */
 Binary.prototype.sha1 = function() {};

 /**
  * Decodes the Base64 encoded string
  * @returns {Binary}
  */
 String.prototype.base64decode = function() {};

 /**
  * Converts an UTF-8 encoded string into its binary (one byte per item) variant
  * @returns {Binary}
  */
 String.prototype.toBinary = function() {};

[[User:Ondras|Ondras]] 08:24, 5 February 2009 (UTC)</text>
    </revision>
    <revision>
      <id>651</id>
      <timestamp>2009-09-09T22:29:29Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[ServerJS/Binary/A]] to [[CommonJS/Binary/A]]:&amp;#32;Subpages needed to be enabled</comment>
      <text xml:space="preserve">== Binary Data ==

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/tt&gt; class.

=== Binary() object proposition ===

This is an interface of my proposed Binary object. I also created a sample implementation, see http://tmp.zarovi.cz/binary.js.

 /**
  * Creates a new variable holding binary data.
  * @param {number} initialData Variable amount if initial arguments. 
    Every number represents a byte.
  * @returns {Binary}
  */
 function Binary(initialData) {};

 /**
  * Returns the number of bytes stored in this structure.
  * This is intentionally named &quot;getLength&quot; instead of &quot;length&quot; to indicate a method (and not a property).
  * @returns {number}
  */
 Binary.prototype.getLength = function() {};

 /**
  * Converts the binary variable to string by UTF-8 encoding its contents.
  * @returns {string}
  */
 Binary.prototype.toString = function() {};

 /**
  * Returns a byte value from a given index.
  * @param {number} index
  * @returns {number}
  */
 Binary.prototype.getByte = function(index) {};

 /**
  * Sets a byte value at given index.
  * @param {number} index
  */
 Binary.prototype.setByte = function(index, value) {};

 /**
  * These are essentialy copied from the Array class.
  */
 Binary.prototype.pop = function() {};
 Binary.prototype.push = function() {};
 Binary.prototype.shift = function() {};
 Binary.prototype.unshift = function() {};

 /**
  * Encodes the data in Base64
  * @returns {string}
  */
 Binary.prototype.base64encode = function() {};

 /**
  * Calculates MD5 hash
  * @returns {string}
  */
 Binary.prototype.md5 = function() {};

 /**
  * Calculates SHA1 hash
  * @returns {string}
  */
 Binary.prototype.sha1 = function() {};

 /**
  * Decodes the Base64 encoded string
  * @returns {Binary}
  */
 String.prototype.base64decode = function() {};

 /**
  * Converts an UTF-8 encoded string into its binary (one byte per item) variant
  * @returns {Binary}
  */
 String.prototype.toBinary = function() {};

[[User:Ondras|Ondras]] 08:24, 5 February 2009 (UTC)</text>
    </revision>
    <revision>
      <id>826</id>
      <timestamp>2009-09-09T23:29:25Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <text xml:space="preserve">== Binary Data ==

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/tt&gt; class.

=== Binary() object proposition ===

This is an interface of my proposed Binary object. I also created a sample implementation, see http://tmp.zarovi.cz/binary.js.
&lt;source&gt;
/**
 * Creates a new variable holding binary data.
 * @param {number} initialData Variable amount if initial arguments. 
   Every number represents a byte.
 * @returns {Binary}
 */
function Binary(initialData) {};

/**
 * Returns the number of bytes stored in this structure.
 * This is intentionally named &quot;getLength&quot; instead of &quot;length&quot; to indicate a method (and not a property).
 * @returns {number}
 */
Binary.prototype.getLength = function() {};

/**
 * Converts the binary variable to string by UTF-8 encoding its contents.
 * @returns {string}
 */
Binary.prototype.toString = function() {};

/**
 * Returns a byte value from a given index.
 * @param {number} index
 * @returns {number}
 */
Binary.prototype.getByte = function(index) {};

/**
 * Sets a byte value at given index.
 * @param {number} index
 */
Binary.prototype.setByte = function(index, value) {};

/**
 * These are essentialy copied from the Array class.
 */
Binary.prototype.pop = function() {};
Binary.prototype.push = function() {};
Binary.prototype.shift = function() {};
Binary.prototype.unshift = function() {};

/**
 * Encodes the data in Base64
 * @returns {string}
 */
Binary.prototype.base64encode = function() {};

/**
 * Calculates MD5 hash
 * @returns {string}
 */
Binary.prototype.md5 = function() {};

/**
 * Calculates SHA1 hash
 * @returns {string}
 */
Binary.prototype.sha1 = function() {};

/**
 * Decodes the Base64 encoded string
 * @returns {Binary}
 */
String.prototype.base64decode = function() {};

/**
 * Converts an UTF-8 encoded string into its binary (one byte per item) variant
 * @returns {Binary}
 */
String.prototype.toBinary = function() {};

[[User:Ondras|Ondras]] 08:24, 5 February 2009 (UTC)</text>
    </revision>
    <revision>
      <id>871</id>
      <timestamp>2009-09-10T02:48:08Z</timestamp>
      <contributor>
        <username>Dantman</username>
        <id>1</id>
      </contributor>
      <minor/>
      <comment>moved [[CommonJS/Binary/A]] to [[Binary/A]]</comment>
      <text xml:space="preserve">== Binary Data ==

JavaScript does not have a binary data type. However, in server-side scenarios, binary data needs to be often processed. That is why we need some working &lt;tt&gt;Binary()&lt;/tt&gt; class.

=== Binary() object proposition ===

This is an interface of my proposed Binary object. I also created a sample implementation, see http://tmp.zarovi.cz/binary.js.
&lt;source&gt;
/**
 * Creates a new variable holding binary data.
 * @param {number} initialData Variable amount if initial arguments. 
   Every number represents a byte.
 * @returns {Binary}
 */
function Binary(initialData) {};

/**
 * Returns the number of bytes stored in this structure.
 * This is intentionally named &quot;getLength&quot; instead of &quot;length&quot; to indicate a method (and not a property).
 * @returns {number}
 */
Binary.prototype.getLength = function() {};

/**
 * Converts the binary variable to string by UTF-8 encoding its contents.
 * @returns {string}
 */
Binary.prototype.toString = function() {};

/**
 * Returns a byte value from a given index.
 * @param {number} index
 * @returns {number}
 */
Binary.prototype.getByte = function(index) {};

/**
 * Sets a byte value at given index.
 * @param {number} index
 */
Binary.prototype.setByte = function(index, value) {};

/**
 * These are essentialy copied from the Array class.
 */
Binary.prototype.pop = function() {};
Binary.prototype.push = function() {};
Binary.prototype.shift = function() {};
Binary.prototype.unshift = function() {};

/**
 * Encodes the data in Base64
 * @returns {string}
 */
Binary.prototype.base64encode = function() {};

/**
 * Calculates MD5 hash
 * @returns {string}
 */
Binary.prototype.md5 = function() {};

/**
 * Calculates SHA1 hash
 * @returns {string}
 */
Binary.prototype.sha1 = function() {};

/**
 * Decodes the Base64 encoded string
 * @returns {Binary}
 */
String.prototype.base64decode = function() {};

/**
 * Converts an UTF-8 encoded string into its binary (one byte per item) variant
 * @returns {Binary}
 */
String.prototype.toBinary = function() {};

[[User:Ondras|Ondras]] 08:24, 5 February 2009 (UTC)</text>
    </revision>
  </page>
  <page>
    <title>Binary/B</title>
    <id>21</id>
    <revision>
      <id>114</id>
      <timestamp>2009-04-08T07:54:04Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Created a proposal for binary data.</comment>
      <text xml:space="preserve">= Proposal B =

All platforms support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, or undefined.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

== Philosophy ==

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

The ByteString constructor accepts:

* ByteString()
* ByteString(byteString)
* ByteString(byteArray)
* ByteString(array)
* ByteString(string, codecModuleId)

The ByteString object has the following methods:

* encode(string, codecModuleId)

ByteString instances support the following:

* immutable length property
* toByteArray()
* toArray()
* toString(codecModuleId)
* decode(codecModuleId)
* hash(digestModuleId)
* compress(compressionModuleId)
* indexOf(Number or ByteString)
* lastIndexOf(Number or ByteString)
* charAt(offset) -&gt; ByteString
* charCodeAt(offset) -&gt; Number
* byteAt(offset) -&gt; Number (same as charCodeAt)
* split(Number or ByteString) -&gt; Array of ByteStrings
* substring(first, last) or substring(first) to the end
* substr(first, length) or substr(length)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf() returns itself


ByteString does not implement toUpperCase() or toLowerCase().

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

The ByteArray constructor has the following forms:

* ByteArray()
* ByteArray(length)
* ByteArray(byteArray)
* ByteArray(byteString)
* ByteArray(array)
* ByteString(string, codecModuleId)

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

The ByteArray object has the following methods:

* encode(string, codecModuleId)

ByteArray instances support the following:

* mutable length property
** extending a byte array fills the new entries with 0.
* toByteString()
* toArray()
* toString(codecModuleId)
* decode(codecModuleId) returns String
* hash(digestModuleId)
* compress(compressionModuleId)
* concat(iterable)
* join(byteString byteArray or Number)
* pop()
* push(…variadic Numbers…)
* shift()
* unshift(…variadic Numbers…)
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf() returns itself
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

* toByteArray(codecModuleId)
* toByteString(codecModuleId)

== Array ==

The Array prototype will be extended with the following members:

* toByteArray(codecModuleId)
* toByteString(codecModuleId)

== Conventions ==

&quot;codecModuleId&quot; always defaults to &quot;utf8&quot;.  Codec modules must always export at least &quot;encode&quot;, and &quot;decode&quot; methods to support byte strings and arrays.  Digest modules must always export a &quot;hash&quot; method that accepts Array, ByteArray, or ByteString objects as their argument.  Compression modules must always export a &quot;compress&quot; method.</text>
    </revision>
    <revision>
      <id>115</id>
      <timestamp>2009-04-08T07:54:52Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <text xml:space="preserve">
All platforms support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, or undefined.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

== Philosophy ==

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

The ByteString constructor accepts:

* ByteString()
* ByteString(byteString)
* ByteString(byteArray)
* ByteString(array)
* ByteString(string, codecModuleId)

The ByteString object has the following methods:

* encode(string, codecModuleId)

ByteString instances support the following:

* immutable length property
* toByteArray()
* toArray()
* toString(codecModuleId)
* decode(codecModuleId)
* hash(digestModuleId)
* compress(compressionModuleId)
* indexOf(Number or ByteString)
* lastIndexOf(Number or ByteString)
* charAt(offset) -&gt; ByteString
* charCodeAt(offset) -&gt; Number
* byteAt(offset) -&gt; Number (same as charCodeAt)
* split(Number or ByteString) -&gt; Array of ByteStrings
* substring(first, last) or substring(first) to the end
* substr(first, length) or substr(length)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf() returns itself


ByteString does not implement toUpperCase() or toLowerCase().

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

The ByteArray constructor has the following forms:

* ByteArray()
* ByteArray(length)
* ByteArray(byteArray)
* ByteArray(byteString)
* ByteArray(array)
* ByteString(string, codecModuleId)

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

The ByteArray object has the following methods:

* encode(string, codecModuleId)

ByteArray instances support the following:

* mutable length property
** extending a byte array fills the new entries with 0.
* toByteString()
* toArray()
* toString(codecModuleId)
* decode(codecModuleId) returns String
* hash(digestModuleId)
* compress(compressionModuleId)
* concat(iterable)
* join(byteString byteArray or Number)
* pop()
* push(…variadic Numbers…)
* shift()
* unshift(…variadic Numbers…)
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf() returns itself
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

* toByteArray(codecModuleId)
* toByteString(codecModuleId)

== Array ==

The Array prototype will be extended with the following members:

* toByteArray(codecModuleId)
* toByteString(codecModuleId)

== Conventions ==

&quot;codecModuleId&quot; always defaults to &quot;utf8&quot;.  Codec modules must always export at least &quot;encode&quot;, and &quot;decode&quot; methods to support byte strings and arrays.  Digest modules must always export a &quot;hash&quot; method that accepts Array, ByteArray, or ByteString objects as their argument.  Compression modules must always export a &quot;compress&quot; method.</text>
    </revision>
    <revision>
      <id>116</id>
      <timestamp>2009-04-11T06:14:58Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Updated according to feedback from the list.</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

== Philosophy ==

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a codec manager module, and may in turn use a system level codec or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

The ByteString constructor accepts:

* ByteString()
* ByteString(byteString)
* ByteString(byteArray)
* ByteString(array)
* ByteString(string, codec)

ByteString instances support the following:

* immutable length property
* toByteArray() -&gt; byte for byte
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; copy
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* toArray() -&gt; byte value array
* toArray(codec) -&gt; decoded code point array
* toString() -&gt; a representation like &quot;[ByteString 10]&quot;
* toString(codec) -&gt; decoded
* indexOf(byte:Number|ByteString|ByteArray)
* indexOf(byte:Number|ByteString|ByteArray, start:Number)
* indexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* byteAt(offset) -&gt; Number (same as charCodeAt)
* charCodeAt(offset:Number) -&gt; Number
* charAt(offset:Number) -&gt; byte:ByteString
* split(delimiter:Number|ByteString) -&gt; Array of ByteStrings
* split(delimiter:Number|ByteString, count:Number) -&gt; Array of ByteStrings
* slice()
* slice(begin)
* slice(begin, end)
* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a codec.


== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

The ByteArray constructor has the following forms:

* ByteArray()
* ByteArray(length)
* ByteArray(byteArray)
* ByteArray(byteString)
* ByteArray(array)
* ByteString(string, codec)

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

ByteArray instances support the following:

* mutable length property
** extending a byte array fills the new entries with 0.
* toArray() -&gt; an array of the byte values
* toArray(codec) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* toString(codec) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

* toByteArray(codec)
* toByteString(codec)
* charCodes() -&gt; Array of charcode:Number

== Array ==

The Array prototype will be extended with the following members:

* toByteArray(codec)
* toByteString(codec)

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.</text>
    </revision>
    <revision>
      <id>117</id>
      <timestamp>2009-04-11T08:13:24Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>Added a link to the corresponding discussion and organized the headings.</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a codec manager module, and may in turn use a system level codec or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

= Specification =

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

The ByteString constructor accepts:

* ByteString()
* ByteString(byteString)
* ByteString(byteArray)
* ByteString(array)
* ByteString(string, codec)

ByteString instances support the following:

* immutable length property
* toByteArray() -&gt; byte for byte
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; copy
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* toArray() -&gt; byte value array
* toArray(codec) -&gt; decoded code point array
* toString() -&gt; a representation like &quot;[ByteString 10]&quot;
* toString(codec) -&gt; decoded
* indexOf(byte:Number|ByteString|ByteArray)
* indexOf(byte:Number|ByteString|ByteArray, start:Number)
* indexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* byteAt(offset) -&gt; Number (same as charCodeAt)
* charCodeAt(offset:Number) -&gt; Number
* charAt(offset:Number) -&gt; byte:ByteString
* split(delimiter:Number|ByteString) -&gt; Array of ByteStrings
* split(delimiter:Number|ByteString, count:Number) -&gt; Array of ByteStrings
* slice()
* slice(begin)
* slice(begin, end)
* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a codec.


== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

The ByteArray constructor has the following forms:

* ByteArray()
* ByteArray(length)
* ByteArray(byteArray)
* ByteArray(byteString)
* ByteArray(array)
* ByteString(string, codec)

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

ByteArray instances support the following:

* mutable length property
** extending a byte array fills the new entries with 0.
* toArray() -&gt; an array of the byte values
* toArray(codec) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* toString(codec) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

* toByteArray(codec)
* toByteString(codec)
* charCodes() -&gt; Array of charcode:Number

== Array ==

The Array prototype will be extended with the following members:

* toByteArray(codec)
* toByteString(codec)

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]</text>
    </revision>
    <revision>
      <id>118</id>
      <timestamp>2009-04-11T12:15:08Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>/* ByteString */ use definition list for constructors</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a codec manager module, and may in turn use a system level codec or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

= Specification =

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

The ByteString constructor:

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, codec)
: Convert a string. The ByteString will contain string encoded with codec.

ByteString instances support the following:

* immutable length property
* toByteArray() -&gt; byte for byte
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; copy
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* toArray() -&gt; byte value array
* toArray(codec) -&gt; decoded code point array
* toString() -&gt; a representation like &quot;[ByteString 10]&quot;
* toString(codec) -&gt; decoded
* indexOf(byte:Number|ByteString|ByteArray)
* indexOf(byte:Number|ByteString|ByteArray, start:Number)
* indexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* byteAt(offset) -&gt; Number (same as charCodeAt)
* charCodeAt(offset:Number) -&gt; Number
* charAt(offset:Number) -&gt; byte:ByteString
* split(delimiter:Number|ByteString) -&gt; Array of ByteStrings
* split(delimiter:Number|ByteString, count:Number) -&gt; Array of ByteStrings
* slice()
* slice(begin)
* slice(begin, end)
* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a codec.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

The ByteArray constructor has the following forms:

* ByteArray()
* ByteArray(length)
* ByteArray(byteArray)
* ByteArray(byteString)
* ByteArray(array)
* ByteString(string, codec)

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

ByteArray instances support the following:

* mutable length property
** extending a byte array fills the new entries with 0.
* toArray() -&gt; an array of the byte values
* toArray(codec) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* toString(codec) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

* toByteArray(codec)
* toByteString(codec)
* charCodes() -&gt; Array of charcode:Number

== Array ==

The Array prototype will be extended with the following members:

* toByteArray(codec)
* toByteString(codec)

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]</text>
    </revision>
    <revision>
      <id>119</id>
      <timestamp>2009-04-11T12:31:31Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <minor/>
      <comment>/* Specification */ add sub-headings</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a codec manager module, and may in turn use a system level codec or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

= Specification =

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, codec)
: Convert a string. The ByteString will contain string encoded with codec.

=== Instance properties ===

* immutable length property

=== Instance methods (in prototype) ===

* toByteArray() -&gt; byte for byte
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; copy
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* toArray() -&gt; byte value array
* toArray(codec) -&gt; decoded code point array
* toString() -&gt; a representation like &quot;[ByteString 10]&quot;
* toString(codec) -&gt; decoded
* indexOf(byte:Number|ByteString|ByteArray)
* indexOf(byte:Number|ByteString|ByteArray, start:Number)
* indexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* byteAt(offset) -&gt; Number (same as charCodeAt)
* charCodeAt(offset:Number) -&gt; Number
* charAt(offset:Number) -&gt; byte:ByteString
* split(delimiter:Number|ByteString) -&gt; Array of ByteStrings
* split(delimiter:Number|ByteString, count:Number) -&gt; Array of ByteStrings
* slice()
* slice(begin)
* slice(begin, end)
* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a codec.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

* ByteArray()
* ByteArray(length)
* ByteArray(byteArray)
* ByteArray(byteString)
* ByteArray(array)
* ByteString(string, codec)

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

* mutable length property
** extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

* toArray() -&gt; an array of the byte values
* toArray(codec) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* toString(codec) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

* toByteArray(codec)
* toByteString(codec)
* charCodes() -&gt; Array of charcode:Number

== Array ==

The Array prototype will be extended with the following members:

* toByteArray(codec)
* toByteString(codec)

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]</text>
    </revision>
    <revision>
      <id>120</id>
      <timestamp>2009-04-11T12:42:15Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>/* Specification */ convert more methods to a definition list (ultimately all methods should be converted like this)</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a codec manager module, and may in turn use a system level codec or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

= Specification =

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, codec)
: Convert a string. The ByteString will contain string encoded with codec.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCodec, targetCodec)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Copy.
; toByteString(sourceCodec, targetCodec)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(codec)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array.
; toString(codec)
: ''CONTROVERSIAL'' Returns the decoded ByteArray as a string.



* indexOf(byte:Number|ByteString|ByteArray)
* indexOf(byte:Number|ByteString|ByteArray, start:Number)
* indexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* byteAt(offset) -&gt; Number (same as charCodeAt)
* charCodeAt(offset:Number) -&gt; Number
* charAt(offset:Number) -&gt; byte:ByteString
* split(delimiter:Number|ByteString) -&gt; Array of ByteStrings
* split(delimiter:Number|ByteString, count:Number) -&gt; Array of ByteStrings
* slice()
* slice(begin)
* slice(begin, end)
* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a codec.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

* ByteArray()
* ByteArray(length)
* ByteArray(byteArray)
* ByteArray(byteString)
* ByteArray(array)
* ByteString(string, codec)

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

* mutable length property
** extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

* toArray() -&gt; an array of the byte values
* toArray(codec) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* toString(codec) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

* toByteArray(codec)
* toByteString(codec)
* charCodes() -&gt; Array of charcode:Number

== Array ==

The Array prototype will be extended with the following members:

* toByteArray(codec)
* toByteString(codec)

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]</text>
    </revision>
    <revision>
      <id>121</id>
      <timestamp>2009-04-11T13:20:34Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <minor/>
      <comment>/* Specification */ more definition lists</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a codec manager module, and may in turn use a system level codec or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

= Specification =

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, codec)
: Convert a string. The ByteString will contain string encoded with codec.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCodec, targetCodec)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Copy.
; toByteString(sourceCodec, targetCodec)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(codec)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array.
; toString(codec)
: ''CONTROVERSIAL'' Returns the decoded ByteArray as a string.



* indexOf(byte:Number|ByteString|ByteArray)
* indexOf(byte:Number|ByteString|ByteArray, start:Number)
* indexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* byteAt(offset) -&gt; Number (same as charCodeAt)
* charCodeAt(offset:Number) -&gt; Number
* charAt(offset:Number) -&gt; byte:ByteString
* split(delimiter:Number|ByteString) -&gt; Array of ByteStrings
* split(delimiter:Number|ByteString, count:Number) -&gt; Array of ByteStrings
* slice()
* slice(begin)
* slice(begin, end)
* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a codec.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

* ByteArray()
* ByteArray(length)
* ByteArray(byteArray)
* ByteArray(byteString)
* ByteArray(array)
* ByteString(string, codec)

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

* mutable length property
** extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

* toArray() -&gt; an array of the byte values
* toArray(codec) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* toString(codec) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(codec)
: Converts a string to a ByteArray encoded in codec.
; toByteString(codec)
: Converts a string to a ByteString encoded in codec.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(codec)
: Converts an array of Unicode code points to a ByteArray encoded in codec.
; toByteString(codec)
: Converts an array of Unicode code points to a ByteString encoded in codec.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]</text>
    </revision>
    <revision>
      <id>122</id>
      <timestamp>2009-04-11T15:39:50Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <minor/>
      <comment>/* Constructor */</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a codec manager module, and may in turn use a system level codec or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

= Specification =

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, codec)
: Convert a string. The ByteString will contain string encoded with codec.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCodec, targetCodec)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Copy.
; toByteString(sourceCodec, targetCodec)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(codec)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array.
; toString(codec)
: ''CONTROVERSIAL'' Returns the decoded ByteArray as a string.



* indexOf(byte:Number|ByteString|ByteArray)
* indexOf(byte:Number|ByteString|ByteArray, start:Number)
* indexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number)
* lastIndexOf(byte:Number|ByteString|ByteArray, start:Number, stop:Number)
* byteAt(offset) -&gt; Number (same as charCodeAt)
* charCodeAt(offset:Number) -&gt; Number
* charAt(offset:Number) -&gt; byte:ByteString
* split(delimiter:Number|ByteString) -&gt; Array of ByteStrings
* split(delimiter:Number|ByteString, count:Number) -&gt; Array of ByteStrings
* slice()
* slice(begin)
* slice(begin, end)
* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a codec.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, codec)
: Create a ByteArray from a Javascript string, the result being encoded with codec.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

* mutable length property
** extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

* toArray() -&gt; an array of the byte values
* toArray(codec) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* toString(codec) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(codec)
: Converts a string to a ByteArray encoded in codec.
; toByteString(codec)
: Converts a string to a ByteString encoded in codec.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(codec)
: Converts an array of Unicode code points to a ByteArray encoded in codec.
; toByteString(codec)
: Converts an array of Unicode code points to a ByteString encoded in codec.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]</text>
    </revision>
    <revision>
      <id>123</id>
      <timestamp>2009-04-11T16:01:23Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>/* Specification */ definition lists + more doc for indexOf stuff</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a codec manager module, and may in turn use a system level codec or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

= Specification =

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, codec)
: Convert a string. The ByteString will contain string encoded with codec.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCodec, targetCodec)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Copy.
; toByteString(sourceCodec, targetCodec)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(codec)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array.
; toString(codec)
: ''CONTROVERSIAL'' Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; byteAt(offset)
; charCodeAt(offset)
: Return the byte at offset as a Number.
; charAt(offset)
: Return the byte at offset as a ByteString.


* split(delimiter:Number|ByteString) -&gt; Array of ByteStrings
* split(delimiter:Number|ByteString, count:Number) -&gt; Array of ByteStrings
* slice()
* slice(begin)
* slice(begin, end)
* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a codec.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, codec)
: Create a ByteArray from a Javascript string, the result being encoded with codec.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

* mutable length property
** extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

* toArray() -&gt; an array of the byte values
* toArray(codec) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* toString(codec) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(codec)
: Converts a string to a ByteArray encoded in codec.
; toByteString(codec)
: Converts a string to a ByteString encoded in codec.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(codec)
: Converts an array of Unicode code points to a ByteArray encoded in codec.
; toByteString(codec)
: Converts an array of Unicode code points to a ByteString encoded in codec.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]</text>
    </revision>
    <revision>
      <id>124</id>
      <timestamp>2009-04-11T23:59:14Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>/* Specification */ split and slice</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a codec manager module, and may in turn use a system level codec or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

= Specification =

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, codec)
: Convert a string. The ByteString will contain string encoded with codec.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCodec, targetCodec)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Copy.
; toByteString(sourceCodec, targetCodec)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(codec)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array.
; toString(codec)
: ''CONTROVERSIAL'' Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; byteAt(offset)
; charCodeAt(offset)
: Return the byte at offset as a Number.
; charAt(offset)
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters).
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a codec.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, codec)
: Create a ByteArray from a Javascript string, the result being encoded with codec.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

* mutable length property
** extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

* toArray() -&gt; an array of the byte values
* toArray(codec) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* toString(codec) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(codec)
: Converts a string to a ByteArray encoded in codec.
; toByteString(codec)
: Converts a string to a ByteString encoded in codec.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(codec)
: Converts an array of Unicode code points to a ByteArray encoded in codec.
; toByteString(codec)
: Converts an array of Unicode code points to a ByteString encoded in codec.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]</text>
    </revision>
    <revision>
      <id>125</id>
      <timestamp>2009-04-12T00:01:12Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>/* Specification */ toString(codec) -&gt; decodeToString(codec)</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a codec manager module, and may in turn use a system level codec or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

= Specification =

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, codec)
: Convert a string. The ByteString will contain string encoded with codec.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCodec, targetCodec)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Copy.
; toByteString(sourceCodec, targetCodec)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(codec)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array.
; decodeToString(codec)
: ''CONTROVERSIAL'' Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; byteAt(offset)
; charCodeAt(offset)
: Return the byte at offset as a Number.
; charAt(offset)
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters).
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a codec.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, codec)
: Create a ByteArray from a Javascript string, the result being encoded with codec.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

* mutable length property
** extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

* toArray() -&gt; an array of the byte values
* toArray(codec) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* decodeToString(codec) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(codec)
: Converts a string to a ByteArray encoded in codec.
; toByteString(codec)
: Converts a string to a ByteString encoded in codec.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(codec)
: Converts an array of Unicode code points to a ByteArray encoded in codec.
; toByteString(codec)
: Converts an array of Unicode code points to a ByteString encoded in codec.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]</text>
    </revision>
    <revision>
      <id>126</id>
      <timestamp>2009-04-12T00:03:01Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <minor/>
      <comment>/* Instance methods (in prototype) */</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible codecs or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a codec manager module, and may in turn use a system level codec or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

= Specification =

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, codec)
: Convert a string. The ByteString will contain string encoded with codec.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCodec, targetCodec)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Copy.
; toByteString(sourceCodec, targetCodec)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(codec)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array.
; decodeToString(codec)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; byteAt(offset)
; charCodeAt(offset)
: Return the byte at offset as a Number.
; charAt(offset)
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters).
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a codec.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, codec)
: Create a ByteArray from a Javascript string, the result being encoded with codec.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

* mutable length property
** extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

* toArray() -&gt; an array of the byte values
* toArray(codec) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* decodeToString(codec) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(codec)
: Converts a string to a ByteArray encoded in codec.
; toByteString(codec)
: Converts a string to a ByteString encoded in codec.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(codec)
: Converts an array of Unicode code points to a ByteArray encoded in codec.
; toByteString(codec)
: Converts an array of Unicode code points to a ByteString encoded in codec.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]</text>
    </revision>
    <revision>
      <id>127</id>
      <timestamp>2009-05-15T05:58:04Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>s/codec/charset/ in most places, and noted that ByteString().toByteString() can return itself instead of making a copy since it is immutable.</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named codec or digest module, assuming that the given module exports the specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.

= Specification =

== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCodec, targetCodec)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCodec, targetCodec)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; byteAt(offset)
; charCodeAt(offset)
: Return the byte at offset as a Number.
; charAt(offset)
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters).
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


* substr(start)
* substr(start, length)
* substring(first)
* substring(first, last)
* The + operator returning new ByteStrings
* The immutable [] operator returning ByteStrings
* toSource() which would return &quot;ByteString([])&quot; for a null byte string
* valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

* mutable length property
** extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

* toArray() -&gt; an array of the byte values
* toArray(charset) -&gt; an array of the code points, decoded
* toString() -&gt; a string representation like &quot;[ByteArray 10]&quot;
* decodeToString(charset) - decoded
* toByteArray() -&gt; just a copy
* toByteArray(sourceCodec, targetCodec) -&gt; transcoded
* toByteString() -&gt; byte for byte
* toByteString(sourceCodec, targetCodec) -&gt; transcoded
* concat(other:ByteArray|ByteString|Array)
* join(delimiter:ByteArray|ByteString|Array)
* pop() -&gt; byte:Number
* push(...variadic Numbers...)-&gt; count:Number
* shift() -&gt; byte:Number
* unshift(...variadic Numbers...) -&gt; count:Number
* reverse() in place reversal
* slice()
* sort()
* splice()
* toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
* valueOf()
* The + operator returning new ByteArrays
* The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

Codec strings are as defined by IANA http://www.iana.org/assignments/character-sets.

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]</text>
    </revision>
    <revision>
      <id>128</id>
      <timestamp>2009-05-17T23:22:16Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Edits in response to byteAt thread.</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; byteAt(offset)
; charCodeAt(offset)
: Return the byte at offset as a Number.
; charAt(offset)
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters).
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
; substr(start, length)
; substring(first)
; substring(first, last)
; The + operator returning new ByteStrings
; The immutable [] operator returning ByteStrings
; toSource() which would return &quot;ByteString([])&quot; for a null byte string
; valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: a string representation like &quot;[ByteArray 10]&quot;
; &lt;u&gt;toString(charset)&lt;/u&gt;
: &lt;u&gt;an alias for decodeToString(charset)&lt;/u&gt;
; decodeToString()
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.  If no charset is provided, or if the charset is &quot;undefined&quot;, assumes the default system encoding.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset)&lt;/u&gt;
; concat(other:ByteArray|ByteString|Array)
; &lt;strike&gt;join(delimiter:ByteArray|ByteString|Array)&lt;/strike&gt;
: &lt;u&gt;deemed unnecessary and semantically unclear&lt;/u&gt;
; pop() -&gt; byte:Number
; push(...variadic Numbers...)-&gt; count:Number
; shift() -&gt; byte:Number
; unshift(...variadic Numbers...) -&gt; count:Number
; reverse() in place reversal
; slice()
; sort()
; splice()
; toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; valueOf()
; The + operator returning new ByteArrays
; The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.
; &lt;u&gt;join(delimiter)&lt;/u&gt;
: &lt;u&gt;Overridden to distinguish its behavior on whether the delimiter is a ByteString, ByteArray, or String.  Defaults to usual behavior for Strings.  Coerces items to ByteString or ByteArray and joins them on the delimiter for delimiters with their respective types.&lt;/u&gt;

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]</text>
    </revision>
    <revision>
      <id>129</id>
      <timestamp>2009-05-18T12:50:56Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>export Binary too!</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;Binary&quot;, &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; byteAt(offset)
; charCodeAt(offset)
: Return the byte at offset as a Number.
; charAt(offset)
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters).
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
; substr(start, length)
; substring(first)
; substring(first, last)
; The + operator returning new ByteStrings
; The immutable [] operator returning ByteStrings
; toSource() which would return &quot;ByteString([])&quot; for a null byte string
; valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: a string representation like &quot;[ByteArray 10]&quot;
; &lt;u&gt;toString(charset)&lt;/u&gt;
: &lt;u&gt;an alias for decodeToString(charset)&lt;/u&gt;
; decodeToString()
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.  If no charset is provided, or if the charset is &quot;undefined&quot;, assumes the default system encoding.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset)&lt;/u&gt;
; concat(other:ByteArray|ByteString|Array)
; &lt;strike&gt;join(delimiter:ByteArray|ByteString|Array)&lt;/strike&gt;
: &lt;u&gt;deemed unnecessary and semantically unclear&lt;/u&gt;
; pop() -&gt; byte:Number
; push(...variadic Numbers...)-&gt; count:Number
; shift() -&gt; byte:Number
; unshift(...variadic Numbers...) -&gt; count:Number
; reverse() in place reversal
; slice()
; sort()
; splice()
; toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; valueOf()
; The + operator returning new ByteArrays
; The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.
; &lt;u&gt;join(delimiter)&lt;/u&gt;
: &lt;u&gt;Overridden to distinguish its behavior on whether the delimiter is a ByteString, ByteArray, or String.  Defaults to usual behavior for Strings.  Coerces items to ByteString or ByteArray and joins them on the delimiter for delimiters with their respective types.&lt;/u&gt;

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]</text>
    </revision>
    <revision>
      <id>130</id>
      <timestamp>2009-05-18T14:07:20Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>move join the ByteString constructor, remove toString(charset)</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;Binary&quot;, &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Constructor methods ===

; &lt;u&gt;join(array, delimiter)&lt;/u&gt;
: Like Array.prototype.join, but for Binarys. Returns a ByteString.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; byteAt(offset)
; charCodeAt(offset)
: Return the byte at offset as a Number.
; charAt(offset)
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters).
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
; substr(start, length)
; substring(first)
; substring(first, last)
; The + operator returning new ByteStrings
; The immutable [] operator returning ByteStrings
; toSource() which would return &quot;ByteString([])&quot; for a null byte string
; valueOf()

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: A string debug representation like &quot;[ByteArray 10]&quot;. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString()
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.  If no charset is provided, or if the charset is &quot;undefined&quot;, assumes the default system encoding.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset)&lt;/u&gt;
; concat(other:ByteArray|ByteString|Array)
; pop() -&gt; byte:Number
; push(...variadic Numbers...)-&gt; count:Number
; shift() -&gt; byte:Number
; unshift(...variadic Numbers...) -&gt; count:Number
; reverse() in place reversal
; slice()
; sort()
; splice()
; toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; valueOf()
; The + operator returning new ByteArrays
; The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]</text>
    </revision>
    <revision>
      <id>131</id>
      <timestamp>2009-05-21T12:37:44Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>remove + operator and valueOf (the first not being implementable and the second being ununderstood)</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;Binary&quot;, &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Constructor methods ===

; &lt;u&gt;join(array, delimiter)&lt;/u&gt;
: Like Array.prototype.join, but for Binarys. Returns a ByteString.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; byteAt(offset)
; charCodeAt(offset)
: Return the byte at offset as a Number.
; charAt(offset)
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters).
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
; substr(start, length)
; substring(first)
; substring(first, last)
; The immutable [] operator returning ByteStrings
; toSource() which would return &quot;ByteString([])&quot; for a null byte string

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: A string debug representation like &quot;[ByteArray 10]&quot;. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString()
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.  If no charset is provided, or if the charset is &quot;undefined&quot;, assumes the default system encoding.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset)&lt;/u&gt;
; concat(other:ByteArray|ByteString|Array)
; pop() -&gt; byte:Number
; push(...variadic Numbers...)-&gt; count:Number
; shift() -&gt; byte:Number
; unshift(...variadic Numbers...) -&gt; count:Number
; reverse() in place reversal
; slice()
; sort()
; splice()
; toSource() returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]</text>
    </revision>
    <revision>
      <id>132</id>
      <timestamp>2009-05-24T23:01:10Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <comment>Formatting and explication of byteAt, charAt, and their types.</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;Binary&quot;, &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Constructor methods ===

; &lt;u&gt;join(array, delimiter)&lt;/u&gt;
: Like Array.prototype.join, but for Binarys. Returns a ByteString.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; charCodeAt(offset)
: Return the byte at offset as a Number.
; byteAt(offset) ByteString
; charAt(offset) ByteString
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters).
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
:
; substr(start, length)
:
; substring(first)
:
; substring(first, last)

; [] ByteString
: the immutable [] operator returning ByteStrings
; toSource()
: which would return &quot;ByteString([])&quot; for a null byte string

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: A string debug representation like &quot;[ByteArray 10]&quot;. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString()
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.  If no charset is provided, or if the charset is &quot;undefined&quot;, assumes the default system encoding.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset) ByteString&lt;/u&gt;
; &lt;u&gt;charAt(offset) ByteString&lt;/u&gt;
:
; concat(other:ByteArray|ByteString|Array)
; pop() byte:Number
:
; push(...variadic Numbers...) count:Number
:
; shift() byte:Number
:
; unshift(...variadic Numbers...) count:Number
:
; reverse() in place reversal
:
; slice()
:
; sort()
:
; splice()
:
; toSource()
: returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; [] Number
: The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]</text>
    </revision>
    <revision>
      <id>133</id>
      <timestamp>2009-05-25T08:20:10Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>/* Relevant Discussions */ add new discussion</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;Binary&quot;, &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Constructor methods ===

; &lt;u&gt;join(array, delimiter)&lt;/u&gt;
: Like Array.prototype.join, but for Binarys. Returns a ByteString.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; charCodeAt(offset)
: Return the byte at offset as a Number.
; byteAt(offset) ByteString
; charAt(offset) ByteString
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters).
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
:
; substr(start, length)
:
; substring(first)
:
; substring(first, last)

; [] ByteString
: the immutable [] operator returning ByteStrings
; toSource()
: which would return &quot;ByteString([])&quot; for a null byte string

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: A string debug representation like &quot;[ByteArray 10]&quot;. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString()
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.  If no charset is provided, or if the charset is &quot;undefined&quot;, assumes the default system encoding.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset) ByteString&lt;/u&gt;
; &lt;u&gt;charAt(offset) ByteString&lt;/u&gt;
:
; concat(other:ByteArray|ByteString|Array)
; pop() byte:Number
:
; push(...variadic Numbers...) count:Number
:
; shift() byte:Number
:
; unshift(...variadic Numbers...) count:Number
:
; reverse() in place reversal
:
; slice()
:
; sort()
:
; splice()
:
; toSource()
: returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; [] Number
: The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]
* [http://groups.google.com/group/serverjs/browse_thread/thread/45190ac89d7b422a Binary/B Extension Proposals and Implementation Notes]</text>
    </revision>
    <revision>
      <id>134</id>
      <timestamp>2009-05-25T12:01:00Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>/* Specification */ add some results from the discussion</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;Binary&quot;, &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Constructor methods ===

; join(array, delimiter)
: Like Array.prototype.join, but for Binarys. Returns a ByteString.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; charCodeAt(offset)
; &lt;u&gt;get(offset)&lt;/u&gt;
: Return the byte at offset as a Number.
; byteAt(offset) ByteString
; charAt(offset) ByteString
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters, i.e., &quot;split at any of these delimiters&quot;). Delimiters can have arbitrary size.
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements (ignoring delimiters) to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
:
; substr(start, length)
:
; substring(first)
:
; substring(first, last)

; [] ByteString
: the immutable [] operator returning ByteStrings
; toSource()
: which would return &quot;ByteString([])&quot; for a null byte string

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: A string debug representation like &quot;[ByteArray 10]&quot;. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString()
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.  If no charset is provided, or if the charset is &quot;undefined&quot;, assumes the default system encoding.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset) ByteString&lt;/u&gt;
: Return the byte at offset as a ByteString.
; &lt;u&gt;get(offset) Number&lt;/u&gt;
: Return the byte at offset as a Number.
; concat(other:ByteArray|ByteString|Array)
; pop() byte:Number
:
; push(...variadic Numbers...) -&gt; count(Number)
:
; &lt;u&gt;extendRight(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; shift() byte:Number
:
; unshift(...variadic Numbers...) count:Number
:
; &lt;u&gt;extendLeft(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; reverse() in place reversal
:
; slice()
:
; sort()
:
; splice()
:
; &lt;u&gt;indexOf()&lt;/u&gt;
:
; &lt;u&gt;lastIndexOf()&lt;/u&gt;
:
; &lt;u&gt;split()&lt;/u&gt; 
: Returns an array of ByteArrays instead of ByteStrings.
; &lt;u&gt;filter()/u&gt;
:
; &lt;u&gt;forEach()/u&gt;
:
; &lt;u&gt;every()/u&gt;
:
; &lt;u&gt;some()/u&gt;
:
; &lt;u&gt;map()/u&gt;
:
; &lt;u&gt;reduce()/u&gt;
:
; &lt;u&gt;reduceRight()/u&gt;
:
; &lt;u&gt;displace(begin, end, values/ByteStrings/ByteArrays/Arrays...) -&gt; length&lt;/u&gt;
: begin/end are specified like for slice. Can be used like splice but does not return the removed elements.
; toSource()
: Returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; [] Number
: The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]
* [http://groups.google.com/group/serverjs/browse_thread/thread/45190ac89d7b422a Binary/B Extension Proposals and Implementation Notes]</text>
    </revision>
    <revision>
      <id>135</id>
      <timestamp>2009-05-26T23:10:48Z</timestamp>
      <contributor>
        <ip>KrisKowal</ip>
      </contributor>
      <minor/>
      <comment>markup errors</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;Binary&quot;, &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Constructor methods ===

; join(array, delimiter)
: Like Array.prototype.join, but for Binarys. Returns a ByteString.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; charCodeAt(offset)
; &lt;u&gt;get(offset)&lt;/u&gt;
: Return the byte at offset as a Number.
; byteAt(offset) ByteString
; charAt(offset) ByteString
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters, i.e., &quot;split at any of these delimiters&quot;). Delimiters can have arbitrary size.
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements (ignoring delimiters) to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
:
; substr(start, length)
:
; substring(first)
:
; substring(first, last)

; [] ByteString
: the immutable [] operator returning ByteStrings
; toSource()
: which would return &quot;ByteString([])&quot; for a null byte string

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: A string debug representation like &quot;[ByteArray 10]&quot;. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString()
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.  If no charset is provided, or if the charset is &quot;undefined&quot;, assumes the default system encoding.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset) ByteString&lt;/u&gt;
: Return the byte at offset as a ByteString.
; &lt;u&gt;get(offset) Number&lt;/u&gt;
: Return the byte at offset as a Number.
; concat(other:ByteArray|ByteString|Array)
; pop() byte:Number
:
; push(...variadic Numbers...) -&gt; count(Number)
:
; &lt;u&gt;extendRight(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; shift() byte:Number
:
; unshift(...variadic Numbers...) count:Number
:
; &lt;u&gt;extendLeft(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; reverse() in place reversal
:
; slice()
:
; sort()
:
; splice()
:
; &lt;u&gt;indexOf()&lt;/u&gt;
:
; &lt;u&gt;lastIndexOf()&lt;/u&gt;
:
; &lt;u&gt;split()&lt;/u&gt; 
: Returns an array of ByteArrays instead of ByteStrings.
; &lt;u&gt;filter()&lt;/u&gt;
:
; &lt;u&gt;forEach()&lt;/u&gt;
:
; &lt;u&gt;every()&lt;/u&gt;
:
; &lt;u&gt;some()&lt;/u&gt;
:
; &lt;u&gt;map()&lt;/u&gt;
:
; &lt;u&gt;reduce()&lt;/u&gt;
:
; &lt;u&gt;reduceRight()&lt;/u&gt;
:
; &lt;u&gt;displace(begin, end, values/ByteStrings/ByteArrays/Arrays...) -&gt; length&lt;/u&gt;
: begin/end are specified like for slice. Can be used like splice but does not return the removed elements.
; toSource()
: Returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; [] Number
: The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]
* [http://groups.google.com/group/serverjs/browse_thread/thread/45190ac89d7b422a Binary/B Extension Proposals and Implementation Notes]</text>
    </revision>
    <revision>
      <id>136</id>
      <timestamp>2009-06-05T19:28:44Z</timestamp>
      <contributor>
        <ip>Tlrobinson</ip>
      </contributor>
      <comment>Added link to tests</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;Binary&quot;, &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Constructor methods ===

; join(array, delimiter)
: Like Array.prototype.join, but for Binarys. Returns a ByteString.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; charCodeAt(offset)
; &lt;u&gt;get(offset)&lt;/u&gt;
: Return the byte at offset as a Number.
; byteAt(offset) ByteString
; charAt(offset) ByteString
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters, i.e., &quot;split at any of these delimiters&quot;). Delimiters can have arbitrary size.
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements (ignoring delimiters) to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
:
; substr(start, length)
:
; substring(first)
:
; substring(first, last)

; [] ByteString
: the immutable [] operator returning ByteStrings
; toSource()
: which would return &quot;ByteString([])&quot; for a null byte string

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: A string debug representation like &quot;[ByteArray 10]&quot;. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString()
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.  If no charset is provided, or if the charset is &quot;undefined&quot;, assumes the default system encoding.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset) ByteString&lt;/u&gt;
: Return the byte at offset as a ByteString.
; &lt;u&gt;get(offset) Number&lt;/u&gt;
: Return the byte at offset as a Number.
; concat(other:ByteArray|ByteString|Array)
; pop() byte:Number
:
; push(...variadic Numbers...) -&gt; count(Number)
:
; &lt;u&gt;extendRight(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; shift() byte:Number
:
; unshift(...variadic Numbers...) count:Number
:
; &lt;u&gt;extendLeft(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; reverse() in place reversal
:
; slice()
:
; sort()
:
; splice()
:
; &lt;u&gt;indexOf()&lt;/u&gt;
:
; &lt;u&gt;lastIndexOf()&lt;/u&gt;
:
; &lt;u&gt;split()&lt;/u&gt; 
: Returns an array of ByteArrays instead of ByteStrings.
; &lt;u&gt;filter()&lt;/u&gt;
:
; &lt;u&gt;forEach()&lt;/u&gt;
:
; &lt;u&gt;every()&lt;/u&gt;
:
; &lt;u&gt;some()&lt;/u&gt;
:
; &lt;u&gt;map()&lt;/u&gt;
:
; &lt;u&gt;reduce()&lt;/u&gt;
:
; &lt;u&gt;reduceRight()&lt;/u&gt;
:
; &lt;u&gt;displace(begin, end, values/ByteStrings/ByteArrays/Arrays...) -&gt; length&lt;/u&gt;
: begin/end are specified like for slice. Can be used like splice but does not return the removed elements.
; toSource()
: Returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; [] Number
: The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Tests =

* [http://github.com/tlrobinson/narwhal/tree/master/tests/serverjs ServerJS tests] compatible with [http://github.com/tlrobinson/narwhal/tree/master/lib/test this test framework].

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]
* [http://groups.google.com/group/serverjs/browse_thread/thread/45190ac89d7b422a Binary/B Extension Proposals and Implementation Notes]</text>
    </revision>
    <revision>
      <id>137</id>
      <timestamp>2009-06-06T15:40:56Z</timestamp>
      <contributor>
        <ip>MrN</ip>
      </contributor>
      <comment>/* Instance methods (in prototype) */ There is no &quot;default charset&quot;. And there should be none.</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;Binary&quot;, &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Constructor methods ===

; join(array, delimiter)
: Like Array.prototype.join, but for Binarys. Returns a ByteString.

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; charCodeAt(offset)
; &lt;u&gt;get(offset)&lt;/u&gt;
: Return the byte at offset as a Number.
; byteAt(offset) ByteString
; charAt(offset) ByteString
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters, i.e., &quot;split at any of these delimiters&quot;). Delimiters can have arbitrary size.
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements (ignoring delimiters) to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
:
; substr(start, length)
:
; substring(first)
:
; substring(first, last)

; [] ByteString
: the immutable [] operator returning ByteStrings
; toSource()
: which would return &quot;ByteString([])&quot; for a null byte string

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: A string debug representation like &quot;[ByteArray 10]&quot;. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset) ByteString&lt;/u&gt;
: Return the byte at offset as a ByteString.
; &lt;u&gt;get(offset) Number&lt;/u&gt;
: Return the byte at offset as a Number.
; concat(other:ByteArray|ByteString|Array)
; pop() byte:Number
:
; push(...variadic Numbers...) -&gt; count(Number)
:
; &lt;u&gt;extendRight(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; shift() byte:Number
:
; unshift(...variadic Numbers...) count:Number
:
; &lt;u&gt;extendLeft(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; reverse() in place reversal
:
; slice()
:
; sort()
:
; splice()
:
; &lt;u&gt;indexOf()&lt;/u&gt;
:
; &lt;u&gt;lastIndexOf()&lt;/u&gt;
:
; &lt;u&gt;split()&lt;/u&gt; 
: Returns an array of ByteArrays instead of ByteStrings.
; &lt;u&gt;filter()&lt;/u&gt;
:
; &lt;u&gt;forEach()&lt;/u&gt;
:
; &lt;u&gt;every()&lt;/u&gt;
:
; &lt;u&gt;some()&lt;/u&gt;
:
; &lt;u&gt;map()&lt;/u&gt;
:
; &lt;u&gt;reduce()&lt;/u&gt;
:
; &lt;u&gt;reduceRight()&lt;/u&gt;
:
; &lt;u&gt;displace(begin, end, values/ByteStrings/ByteArrays/Arrays...) -&gt; length&lt;/u&gt;
: begin/end are specified like for slice. Can be used like splice but does not return the removed elements.
; toSource()
: Returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; [] Number
: The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Tests =

* [http://github.com/tlrobinson/narwhal/tree/master/tests/serverjs ServerJS tests] compatible with [http://github.com/tlrobinson/narwhal/tree/master/lib/test this test framework].

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]
* [http://groups.google.com/group/serverjs/browse_thread/thread/45190ac89d7b422a Binary/B Extension Proposals and Implementation Notes]</text>
    </revision>
    <revision>
      <id>138</id>
      <timestamp>2009-07-10T01:25:03Z</timestamp>
      <contributor>
        <ip>Tlrobinson</ip>
      </contributor>
      <comment>/* Constructor methods */</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;Binary&quot;, &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Constructor methods ===

; join(array, delimiter)
: Like Array.prototype.join, but for Binarys. Returns a ByteString.

(TODO: clarify usage)

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; charCodeAt(offset)
; &lt;u&gt;get(offset)&lt;/u&gt;
: Return the byte at offset as a Number.
; byteAt(offset) ByteString
; charAt(offset) ByteString
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters, i.e., &quot;split at any of these delimiters&quot;). Delimiters can have arbitrary size.
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements (ignoring delimiters) to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
:
; substr(start, length)
:
; substring(first)
:
; substring(first, last)

; [] ByteString
: the immutable [] operator returning ByteStrings
; toSource()
: which would return &quot;ByteString([])&quot; for a null byte string

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: A string debug representation like &quot;[ByteArray 10]&quot;. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset) ByteString&lt;/u&gt;
: Return the byte at offset as a ByteString.
; &lt;u&gt;get(offset) Number&lt;/u&gt;
: Return the byte at offset as a Number.
; concat(other:ByteArray|ByteString|Array)
; pop() byte:Number
:
; push(...variadic Numbers...) -&gt; count(Number)
:
; &lt;u&gt;extendRight(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; shift() byte:Number
:
; unshift(...variadic Numbers...) count:Number
:
; &lt;u&gt;extendLeft(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; reverse() in place reversal
:
; slice()
:
; sort()
:
; splice()
:
; &lt;u&gt;indexOf()&lt;/u&gt;
:
; &lt;u&gt;lastIndexOf()&lt;/u&gt;
:
; &lt;u&gt;split()&lt;/u&gt; 
: Returns an array of ByteArrays instead of ByteStrings.
; &lt;u&gt;filter()&lt;/u&gt;
:
; &lt;u&gt;forEach()&lt;/u&gt;
:
; &lt;u&gt;every()&lt;/u&gt;
:
; &lt;u&gt;some()&lt;/u&gt;
:
; &lt;u&gt;map()&lt;/u&gt;
:
; &lt;u&gt;reduce()&lt;/u&gt;
:
; &lt;u&gt;reduceRight()&lt;/u&gt;
:
; &lt;u&gt;displace(begin, end, values/ByteStrings/ByteArrays/Arrays...) -&gt; length&lt;/u&gt;
: begin/end are specified like for slice. Can be used like splice but does not return the removed elements.
; toSource()
: Returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; [] Number
: The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Tests =

* [http://github.com/tlrobinson/narwhal/tree/master/tests/serverjs ServerJS tests] compatible with [http://github.com/tlrobinson/narwhal/tree/master/lib/test this test framework].

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]
* [http://groups.google.com/group/serverjs/browse_thread/thread/45190ac89d7b422a Binary/B Extension Proposals and Implementation Notes]</text>
    </revision>
    <revision>
      <id>139</id>
      <timestamp>2009-07-12T07:07:49Z</timestamp>
      <contributor>
        <ip>Tlrobinson</ip>
      </contributor>
      <comment>Added args for some ByteArray methods</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and with the possibility of eventually employing a system of modular extensions for other codecs or digests, requiring that the given module exports a specified interface. (As supported originally by Robert Schultz, Davey Waterson, Ross Boucher, and tacitly myself, Kris Kowal, on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst First proposition] thread on the mailing list).  This proposal does not address the need for stream objects to support pipelined codecs and hash digests (mentioned by Tom Robinson and Robert Schultz in the same conversation).

This proposal also reflects both group sentiment and a pragmatic point about properties.  This isn't a decree that properties like &quot;length&quot; should be consistently used throughout the ServerJS APIs.  However, given that all platforms support properties at the native level (to host String and Array objects) and that byte strings and arrays will require support at the native level, pursuing client-side interoperability is beyond the scope of this proposal and therefore properties have been specified.  (See comments by Kris Zyp about the implementability of properties in all platforms, comments by Davey Waterson from Aptana about the counter-productivity of attempting to support this API in browsers, and support properties over accessor and mutator functions by Ionut Gabriel Stand and Cameron McCormack on the [http://groups.google.com/group/serverjs/browse_thread/thread/be72ef3d8146731d/06c27162b698eef5?lnk=gst mailing list]).

The byte types provide functions for encoding, decoding, and transcoding, but they are all shallow interfaces that defer to a charset manager module, and may in turn use a system level charset or use a pair of pure JavaScript modules to transcode through an array or stream of canonical Unicode code points.  This behavior may be specified further in the future.

= Specification =

The &quot;binary&quot; top-level module must export &quot;Binary&quot;, &quot;ByteArray&quot; and &quot;ByteString&quot;.


== ByteString ==

A ByteString is an immutable, fixed-width representation of a C unsigned char (byte) array.  ByteString supports the String API, and indexing returns a byte substring of length 1.

=== Constructor ===

; ByteString()
: Construct an empty byte string.
; ByteString(byteString)
: Copies byteString.
; ByteString(byteArray)
: Use the contents of byteArray.
; ByteString(arrayOfNumbers)
: Use the numbers in arrayOfNumbers as the bytes.
: If any element is outside the range 0...255, an exception (''TODO'') is thrown.
; ByteString(string, charset)
: Convert a string. The ByteString will contain string encoded with charset.

=== Constructor methods ===

; join(array, delimiter)
: Like Array.prototype.join, but for Binarys. Returns a ByteString.

(TODO: clarify usage)

=== Instance properties ===

; length
: The length in bytes. Immutable.

=== Instance methods (in prototype) ===

; toByteArray()
: Returns a byte for byte copy in a ByteArray.
; toByteArray(sourceCharset, targetCharset)
: Returns a transcoded copy in a ByteArray.
; toByteString()
: Returns itself, since there's no need to copy an immutable ByteString.
; toByteString(sourceCharset, targetCharset)
: Returns a transcoded copy.
; toArray()
: Returns an array containing the bytes as numbers.
; toArray(charset)
: Returns an array containing the decoded Unicode code points.
; toString()
: Returns a debug representation like &quot;[ByteString 10]&quot;, where 10 is the length of the Array. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: Returns the decoded ByteArray as a string.
; indexOf(byte)
; indexOf(byte, start)
; indexOf(byte, start, stop)
: Returns the index of the first occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; lastIndexOf(byte)
; lastIndexOf(byte, start)
; lastIndexOf(byte, start, stop)
: Returns the index of the last occurance of byte (a Number or a single element ByteString or ByteArray) or -1 if none was found. If start and/or stop are specified, only elements between the the indexes start and stop are searched.
; charCodeAt(offset)
; &lt;u&gt;get(offset)&lt;/u&gt;
: Return the byte at offset as a Number.
; byteAt(offset) ByteString
; charAt(offset) ByteString
: Return the byte at offset as a ByteString.
; split(delimiter, [options])
: Split at delimiter, which can by a Number, a ByteString, a ByteArray or an Array of the prior (containing multiple delimiters, i.e., &quot;split at any of these delimiters&quot;). Delimiters can have arbitrary size.
: Options is an optional object parameter with the following optional properties:
* ''count'' - Maximum number of elements (ignoring delimiters) to return. The last returned element may contain delimiters.
* ''includeDelimiter'' - Whether the delimiter should be included in the result.
: Returns an array of ByteStrings.
; slice()
; slice(begin)
; slice(begin, end)
: See [https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/slice Array.prototype.slice]


; substr(start)
:
; substr(start, length)
:
; substring(first)
:
; substring(first, last)

; [] ByteString
: the immutable [] operator returning ByteStrings
; toSource()
: which would return &quot;ByteString([])&quot; for a null byte string

ByteString does not implement toUpperCase() or toLowerCase() since they are not meaningful without the context of a charset.

== ByteArray ==

A ByteArray is a mutable, flexible representation of a C unsigned char (byte) array.

=== Constructor ===

; ByteArray()
: New, empty ByteArray.
; ByteArray(length)
: New ByteArray filled with length zero bytes.
; ByteArray(byteArray)
: Copy byteArray.
; ByteArray(byteString)
: Copy contents of byteString.
; ByteArray(arrayOfBytes)
: Use numbers in arrayOfBytes as contents.
: Throws an exception if any element is outside the range 0...255 (''TODO'').
; ByteArray(string, charset)
: Create a ByteArray from a Javascript string, the result being encoded with charset.

Unlike the Array, the ByteArray is not variadic so that its initial length constructor is not ambiguous with its copy constructor.

All values within the length of the array are numbers stored as bytes that default to 0 if they have not been explicitly set.  Assigning beyond the bounds of a ByteArray implicitly grows the array, just like an Array.  Retrieving a value from an index that is out of the bounds of the Array, lower than 0 or at or beyond the length, the returned value is &quot;undefined&quot;.  Assigning an index with a value that is larger than fits in a byte will be implicitly and silently masked against 0xFF.  Negative numbers will be bit extended to a byte in two's complement form and likewise masked.

=== Instance properties ===

; mutable length property
: extending a byte array fills the new entries with 0.

=== Instance methods (in prototype) ===

; toArray()
: n array of the byte values
; toArray(charset)
: an array of the code points, decoded
; toString()
: A string debug representation like &quot;[ByteArray 10]&quot;. Alternative debug representations are valid too, as long as (1) this method will never fail, (2) the length is included.
; decodeToString(charset)
: returns a String from its decoded bytes in a given charset.
; toByteArray()
: just a copy
; toByteArray(sourceCharset, targetCharset)
: transcoded
; toByteString()
: byte for byte copy
; toByteString(sourceCharset, targetCharset)
: transcoded
; &lt;u&gt;byteAt(offset) ByteString&lt;/u&gt;
: Return the byte at offset as a ByteString.
; &lt;u&gt;get(offset) Number&lt;/u&gt;
: Return the byte at offset as a Number.
; concat(other:ByteArray|ByteString|Array)
; pop() byte:Number
:
; push(...variadic Numbers...) -&gt; count(Number)
:
; &lt;u&gt;extendRight(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; shift() byte:Number
:
; unshift(...variadic Numbers...) count:Number
:
; &lt;u&gt;extendLeft(...variadic Numbers / Arrays / ByteArrays / ByteStrings ...)&lt;/u&gt;
: 
; reverse() in place reversal
:
; slice()
:
; sort()
:
; splice()
:
; &lt;u&gt;indexOf()&lt;/u&gt;
:
; &lt;u&gt;lastIndexOf()&lt;/u&gt;
:
; &lt;u&gt;split()&lt;/u&gt; 
: Returns an array of ByteArrays instead of ByteStrings.
; &lt;u&gt;filter(callback[, thisObject])&lt;/u&gt;
:
; &lt;u&gt;forEach(callback[, thisObject])&lt;/u&gt;
:
; &lt;u&gt;every(callback[, thisObject])&lt;/u&gt;
:
; &lt;u&gt;some(callback[, thisObject])&lt;/u&gt;
:
; &lt;u&gt;map(callback[, thisObject])&lt;/u&gt;
:
; &lt;u&gt;reduce(callback[, initialValue])&lt;/u&gt;
:
; &lt;u&gt;reduceRight(callback[, initialValue])&lt;/u&gt;
:
; &lt;u&gt;displace(begin, end, values/ByteStrings/ByteArrays/Arrays...) -&gt; length&lt;/u&gt;
: begin/end are specified like for slice. Can be used like splice but does not return the removed elements.
; toSource()
: Returns a string like &quot;ByteArray([])&quot; for a null byte-array.
; [] Number
: The mutable [] operator for numbers

== String ==

The String prototype will be extended with the following members:

; toByteArray(charset)
: Converts a string to a ByteArray encoded in charset.
; toByteString(charset)
: Converts a string to a ByteString encoded in charset.
; charCodes()
: Returns an array of Unicode code points (as numbers).

== Array ==

The Array prototype will be extended with the following members:

; toByteArray(charset)
: Converts an array of Unicode code points to a ByteArray encoded in charset.
; toByteString(charset)
: Converts an array of Unicode code points to a ByteString encoded in charset.

== General Requirements ==

None of the specified prototypes or augmentations to existing prototypes are enumerable.

&lt;u&gt;Any operation that requires encoding, decoding, or transcoding among charsets may throw an error if that charset is not supported by the implementation.  All implementations MUST support &quot;us-ascii&quot; and &quot;utf-8&quot;.&lt;/u&gt;

Charset strings are as defined by IANA http://www.iana.org/assignments/character-sets.

&lt;u&gt;Charsets are case insensitive.&lt;/u&gt;

= Tests =

* [http://github.com/tlrobinson/narwhal/tree/master/tests/serverjs ServerJS tests] compatible with [http://github.com/tlrobinson/narwhal/tree/master/lib/test this test framework].

= Relevant Discussions =

* [http://groups.google.com/group/serverjs/browse_thread/thread/f8ad81201f7b121b ByteArray and ByteString proposal]
* [http://groups.google.com/group/serverjs/browse_thread/thread/a8d3a91af37fd355 ByteArray: byteAt method]
* [http://groups.google.com/group/serverjs/browse_thread/thread/45190ac89d7b422a Binary/B Extension Proposals and Implementation Notes]</text>
    </revision>
    <revision>
      <id>140</id>
      <timestamp>2009-09-05T12:34:08Z</timestamp>
      <contributor>
        <ip>Hannesw</ip>
      </contributor>
      <comment>Added notes section</comment>
      <text xml:space="preserve">All platforms must support two types for interacting with binary data: ByteArray and ByteString.  The ByteArray type resembles the interface of Array in that it is mutable, extensible, and indexing will return number values for the byte in the given position, zero by default, or undefined if the index is out of bounds.  The ByteString type resembles the interface of String in that it is immutable and indexing returns a ByteString of length 1.  These types are exported by the 'binary' top-level module and both types are subtypes of Binary, which is not instantiable but exists only for the convenience of referring to both ByteArray and ByteString.  (The idea of using these particular two types and their respective names originated with Jason Orendorff in the [http://groups.google.com/group/serverjs/msg/89808c05d46b92d0 Binary API Brouhaha] discussion.)

= Philosophy =

This proposal is not an object oriented variation on pack and unpack with notions of inherent endianness, read/write head position, or intrinsic codec or charset information.  The objects described in this proposal are merely for the storage and direct manipulation of strings and arrays of byte data.  Some object oriented conveniences are made, but the exercise of implementing pack, unpack, or an object-oriented analog thereof are left as an exercise for a future proposal of a more abstract type or a 'struct' module (as mentioned by Ionut Gabriel Stan on [http://groups.google.com/group/serverjs/msg/592442ba98c6c70e the list]).  This goes against most mentioned [[ServerJS/Binary|prior art]].

This proposal also does not provide named member functions for any particular subset of the possible charsets, codecs, compression algorithms, or consistent hash digests that might operate on a byte string or array.  Instead, convenience member functions are provided for interfacing with any named charset, with the IANA charset name space, and wi