zuzu-js 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cli.js CHANGED
@@ -254,7 +254,7 @@ function stripShebang( source ) {
254
254
  }
255
255
 
256
256
  function printVersion( runtime, verbose ) {
257
- process.stdout.write( 'zuzu-js version 0.1.0\n' );
257
+ process.stdout.write( 'zuzu-js version 0.1.1\n' );
258
258
  if ( verbose ) {
259
259
  process.stdout.write( '\nlib search paths:\n' );
260
260
  for ( const p of runtime.getModuleSearchRoots() ) {
@@ -37,15 +37,18 @@ class ZuzuBinary {
37
37
  }
38
38
 
39
39
  slice( start, end ) {
40
- return new ZuzuBinary( this.bytes.slice( start, end ) );
40
+ return new this.constructor( this.bytes.slice( start, end ) );
41
41
  }
42
42
 
43
43
  at( index ) {
44
- const idx = Number( index );
44
+ let idx = Number( index );
45
+ if ( idx < 0 ) {
46
+ idx = this.bytes.length + idx;
47
+ }
45
48
  if ( idx < 0 || idx >= this.bytes.length ) {
46
49
  return null;
47
50
  }
48
- return new ZuzuBinary( [ this.bytes[idx] ] );
51
+ return new this.constructor( [ this.bytes[idx] ] );
49
52
  }
50
53
 
51
54
  to_String() {
package/lib/runtime.js CHANGED
@@ -1573,10 +1573,11 @@ function zuzuGetIndex( target, index ) {
1573
1573
  if ( typeof target === 'string' || Array.isArray( target ) ) {
1574
1574
  let resolved = Number( index );
1575
1575
  if ( Number.isFinite( resolved ) ) {
1576
+ const indexed = typeof target === 'string' ? [ ...target ] : target;
1576
1577
  if ( resolved < 0 ) {
1577
- resolved = target.length + resolved;
1578
+ resolved = indexed.length + resolved;
1578
1579
  }
1579
- return resolveWeakValue( target[resolved] );
1580
+ return resolveWeakValue( indexed[resolved] ?? null );
1580
1581
  }
1581
1582
  }
1582
1583
  if (
@@ -1592,24 +1593,62 @@ function zuzuGetIndex( target, index ) {
1592
1593
  return resolveWeakValue( target[index] );
1593
1594
  }
1594
1595
 
1596
+ function zuzuSliceBounds( size, from, length ) {
1597
+ let start = Number( from ?? 0 );
1598
+ if ( !Number.isFinite( start ) ) {
1599
+ start = 0;
1600
+ }
1601
+ if ( start < 0 ) {
1602
+ start = size + start;
1603
+ }
1604
+ start = Math.max( 0, Math.min( size, start ) );
1605
+ if ( length == null ) {
1606
+ return [ start, size ];
1607
+ }
1608
+ const span = Number( length );
1609
+ if ( !Number.isFinite( span ) ) {
1610
+ return [ start, start ];
1611
+ }
1612
+ const end = span < 0
1613
+ ? Math.max( 0, Math.min( size, size + span ) )
1614
+ : Math.max( 0, Math.min( size, start + span ) );
1615
+ return [ Math.min( start, end ), Math.max( start, end ) ];
1616
+ }
1617
+
1618
+ function zuzuGetSlice( target, from, length ) {
1619
+ target = resolveWeakValue( target );
1620
+ if ( target == null ) {
1621
+ return null;
1622
+ }
1623
+ if ( typeof target === 'string' ) {
1624
+ const chars = [ ...target ];
1625
+ const [ start, end ] = zuzuSliceBounds( chars.length, from, length );
1626
+ return chars.slice( start, end ).join( '' );
1627
+ }
1628
+ if ( target instanceof ZuzuBinary ) {
1629
+ const [ start, end ] = zuzuSliceBounds( target.length, from, length );
1630
+ return target.slice( start, end );
1631
+ }
1632
+ if ( Array.isArray( target ) ) {
1633
+ const [ start, end ] = zuzuSliceBounds( target.length, from, length );
1634
+ return target.slice( start, end );
1635
+ }
1636
+ return target.slice( from, length == null ? undefined : Number( from ) + Number( length ) );
1637
+ }
1638
+
1595
1639
  function zuzuAssignSlice( target, from, length, value ) {
1596
1640
  const hasLength = length != null;
1597
- const span = hasLength ? Number( length ) : null;
1598
1641
  const replacement = value == null ? '' : value;
1599
1642
  if ( typeof target === 'string' ) {
1600
- let start = Number( from );
1601
- if ( start < 0 ) {
1602
- start = target.length + start;
1603
- }
1604
- start = Math.max( 0, Math.min( target.length, start ) );
1605
- const end = hasLength
1606
- ? Math.max( 0, Math.min( target.length, span >= 0 ? start + span : target.length + span ) )
1607
- : target.length;
1608
- return target.slice( 0, start ) + String( replacement ) + target.slice( end );
1643
+ const chars = [ ...target ];
1644
+ const [ start, end ] = zuzuSliceBounds( chars.length, from, length );
1645
+ chars.splice( start, end - start, ...[ ...String( replacement ) ] );
1646
+ return chars.join( '' );
1609
1647
  }
1610
1648
  const start = Number( from );
1611
1649
  if ( Array.isArray( target ) ) {
1612
1650
  const items = Array.isArray( replacement ) ? replacement : [ replacement ];
1651
+ const span = hasLength ? Number( length ) : null;
1613
1652
  if ( hasLength ) {
1614
1653
  target.splice( start, span, ...items );
1615
1654
  }
@@ -1619,7 +1658,16 @@ function zuzuAssignSlice( target, from, length, value ) {
1619
1658
  return target;
1620
1659
  }
1621
1660
  if ( target instanceof ZuzuBinary ) {
1622
- throw new Error( 'Exception: BinaryString slice assignment is not supported' );
1661
+ if ( !( value instanceof ZuzuBinary ) ) {
1662
+ throw new Error( `TypeException: BinaryString slice assignment expects BinaryString, got ${zuzuTypeof( value )}` );
1663
+ }
1664
+ const [ byteStart, byteEnd ] = zuzuSliceBounds( target.length, from, length );
1665
+ const next = new Uint8Array( target.length - ( byteEnd - byteStart ) + value.bytes.length );
1666
+ next.set( target.bytes.slice( 0, byteStart ), 0 );
1667
+ next.set( value.bytes, byteStart );
1668
+ next.set( target.bytes.slice( byteEnd ), byteStart + value.bytes.length );
1669
+ target.bytes = next;
1670
+ return target;
1623
1671
  }
1624
1672
  throw new Error( `TypeException: slice assignment expects String or Array, got ${zuzuTypeof( target )}` );
1625
1673
  }
@@ -1641,18 +1689,27 @@ function assignIndexedValue( target, index, value, isWeakWrite = false, assignTa
1641
1689
  throw new Error( 'TypeException: cannot assign to null' );
1642
1690
  }
1643
1691
  if ( target instanceof ZuzuBinary ) {
1644
- throw new Error( 'Exception: BinaryString index assignment is not supported' );
1692
+ if ( !( value instanceof ZuzuBinary ) ) {
1693
+ throw new Error( `TypeException: BinaryString index assignment expects BinaryString, got ${zuzuTypeof( value )}` );
1694
+ }
1695
+ zuzuAssignSlice( target, index, 1, value );
1696
+ if ( typeof assignTarget === 'function' ) {
1697
+ assignTarget( target );
1698
+ }
1699
+ return target;
1645
1700
  }
1646
1701
  if ( typeof target === 'string' ) {
1647
1702
  let resolved = Number( index );
1648
1703
  if ( !Number.isFinite( resolved ) ) {
1649
1704
  throw new Error( 'TypeException: String index assignment expects numeric index' );
1650
1705
  }
1706
+ const chars = [ ...target ];
1651
1707
  if ( resolved < 0 ) {
1652
- resolved = target.length + resolved;
1708
+ resolved = chars.length + resolved;
1653
1709
  }
1654
- resolved = Math.max( 0, Math.min( target.length, resolved ) );
1655
- const updated = target.slice( 0, resolved ) + String( value ?? '' ) + target.slice( resolved + 1 );
1710
+ resolved = Math.max( 0, Math.min( chars.length, resolved ) );
1711
+ chars.splice( resolved, resolved < chars.length ? 1 : 0, ...[ ...String( value ?? '' ) ] );
1712
+ const updated = chars.join( '' );
1656
1713
  return typeof assignTarget === 'function' ? assignTarget( updated ) : updated;
1657
1714
  }
1658
1715
  if ( isPairListLike( target ) ) {
@@ -1673,16 +1730,10 @@ function refSlice( target, from, length ) {
1673
1730
  const hasLength = length != null;
1674
1731
  const span = hasLength ? Number( length ) : null;
1675
1732
  if ( arguments.length === 0 ) {
1676
- const end = hasLength
1677
- ? ( span >= 0 ? start + span : span )
1678
- : undefined;
1679
- if ( target instanceof ZuzuBinary ) {
1680
- return target.slice( start, end );
1681
- }
1682
- return target.slice( start, end );
1733
+ return zuzuGetSlice( target, start, hasLength ? span : null );
1683
1734
  }
1684
- if ( target instanceof ZuzuBinary ) {
1685
- throw new Error( 'Exception: BinaryString slice assignment is not supported' );
1735
+ if ( target instanceof ZuzuBinary || typeof target === 'string' ) {
1736
+ return zuzuAssignSlice( target, start, hasLength ? span : null, maybeValue );
1686
1737
  }
1687
1738
  if ( !hasLength ) {
1688
1739
  target.splice( start, target.length - start, ...maybeValue );
@@ -2981,6 +3032,7 @@ class ZuzuScript {
2981
3032
  },
2982
3033
  __zuzu_ref_index( target, index ) { return refIndex( target, index ); },
2983
3034
  __zuzu_ref_key( target, key ) { return refKey( target, key ); },
3035
+ __zuzu_get_slice( target, from, length ) { return zuzuGetSlice( target, from, length ); },
2984
3036
  __zuzu_ref_slice( target, from, length ) { return refSlice( target, from, length ); },
2985
3037
  __zuzu_assign_slice( target, from, length, value ) { return zuzuAssignSlice( target, from, length, value ); },
2986
3038
  Pair,
@@ -2164,14 +2164,8 @@ function emitAssignmentTarget( node ) {
2164
2164
  function emitSliceExpression( node ) {
2165
2165
  const object = emitExpression( node.object );
2166
2166
  const start = node.start ? emitExpression( node.start ) : '0';
2167
- if ( node.length == null ) {
2168
- return `${object}.slice( ${start} )`;
2169
- }
2170
- const length = emitExpression( node.length );
2171
- const end = isNegativeNumericLiteral( node.length )
2172
- ? length
2173
- : `__zuzu_add( ${start}, ${length} )`;
2174
- return `${object}.slice( ${start}, ${end} )`;
2167
+ const length = node.length == null ? 'null' : emitExpression( node.length );
2168
+ return `__zuzu_get_slice( ${object}, ${start}, ${length} )`;
2175
2169
  }
2176
2170
 
2177
2171
  function unwrapGroupedExpression( node ) {
@@ -2182,16 +2176,6 @@ function unwrapGroupedExpression( node ) {
2182
2176
  return current;
2183
2177
  }
2184
2178
 
2185
- function isNegativeNumericLiteral( node ) {
2186
- return !!(
2187
- node
2188
- && node.type === 'UnaryExpression'
2189
- && node.operator === '-'
2190
- && node.argument
2191
- && node.argument.type === 'NumericLiteral'
2192
- );
2193
- }
2194
-
2195
2179
  function emitRegexReplaceExpression( node ) {
2196
2180
  const leftTarget = unwrapGroupedExpression( node.left );
2197
2181
  if (
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zuzu-js",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "JavaScript runtime, compiler, and browser bundle for ZuzuScript.",
5
5
  "main": "lib/zuzu.js",
6
6
  "bin": {