0

my attempts to build a module wrapping a collection fail

i have something like:

// topic: chess gaming
// file: src/core/Refs.js

const COLS = 'abcdefgh'.split('')
const ROWS = '12345678'.split('')
const ALL = new Map()

class Ref {
  constructor (col, row) {
    this.col = col
    this.row = row
    this.key = String(col + row)
  }

  // translate to ref to obtain another
  // or null, if off-board
  //
  // ref.translate(0, 0) === ref (ok ?)
  //
  translate (dcol, drow) {
    // compute something for dcol and drow
    // ...
    return ALL.get( COLS[colIdx] + ROWS[rowIdx] )
  }
}

// the code which seems to not work propertly
for(let c of COLS) {
  for(let r of ROWS) {
    ALL.set(String(c + r), new Ref(c, r))
  }
}

export default {
  COLS, ROWS, ALL,

  has (ref) {
    return ALL.has(ref)
  },

  get (ref) {
    return ALL.get(ref)
  },

  // trying to grant/warrant "immutability"
  // for the "ALL" collection inside the module
  keys() {
    return [...ALL.keys()]
  }
}

After I complie the module with Buble with correct flags (dangerousForOf, ..) and objectAssign

Then I test with karma + jasmine, the first test :

it ('should be 64-length array', function () {
  expect (Refs.keys().length).toEqual(64)
})

will faim with 'expects 1 to equal 64', and a log of Refs.ALL seems to show an empty Map althougth Refs.COLS and Refs.ROWS are properly initialized.

What's happening and how to fix it ?

EDIT:

@Bergi: of course, exposing Refs.ALL breaks the immutability, it was rather for debugging purposes

I'm not exactly sure how to capture test bundle output, but looking at gulp+rollup developpement bundle, the method keys() line :

return [...ALL.keys()]

was replaced by:

return [].concat(ALL.keys())

which produces an 1-element array containing a MapIterator, this breaking tests. putting something like :

return Array.from( ALL.keys() )

will fix the problem, but risks not to work properky in legacy browsers !

I have pushed the code on my repo : https://github.com/hefeust/colorchess-v2

Hoping this could help to fix the bug : how to convert spread (...) operator in source code to have a bundle with the correct Object.assign polyfill ?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Hefeust
  • 501
  • 1
  • 5
  • 14
  • Try logging the value of `String(c + r)` in the loop that sets values? – Ry- Aug 18 '17 at 13:33
  • *compile with buble* ? – Jonas Wilms Aug 18 '17 at 13:55
  • c +r gives me "a1" to "h8", of course ... transpiling with Bublé, I mean. to convert from ES2015 + stage-2 to classic browser JS, using karma, and rollup-plugin-buble (not babel) since Bublé's faster – Hefeust Aug 18 '17 at 14:51
  • Hint: although `.keys()` looks like it would grant immutability, exporting the `.ALL` Map directly opens up the whole thing. Are your other tests messing with it? – Bergi Aug 18 '17 at 17:42
  • Can you please post the transpiled module, and your whole test suite (or at least the tests that fail when executed on their own)? That would help us a lot to explain what is happening. – Bergi Aug 18 '17 at 17:43

1 Answers1

2

Bublé does not support iterators, which is why it transpiles array literals with spread syntax to concatenations. Use Array.from instead (which is more descriptive anyway).

return Array.from( ALL.keys() ) will fix the problem, but risks not to work properly in legacy browsers!

That should be of no concern - you are using Map objects and their keys() method that returns an iterator, which won't work in legacy browsers either. If you plan to support them, you have to use a polyfill anyway - and you just would get a polyfill for Array.from as well.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375