How GitHub Copilot can help you with updating your js

October 22, 2023

Here I would like to share some findings about GitHub copilot I saw with current version.

Don’t ask for ES6, ask for latest EcmaScript version/feature set

Let’s take this function from jQuery as sample: https://github.com/jquery/jquery/blob/main/src/core/parseXML.js

function( data ) {
	var xml, parserErrorElem;
	if ( !data || typeof data !== "string" ) {
		return null;
	}

	// Support: IE 9 - 11+
	// IE throws on parseFromString with invalid input.
	try {
		xml = (new window.DOMParser()).parseFromString( data, "text/xml" );
	} catch ( e ) {}

	parserErrorElem = xml && xml.getElementsByTagName("parsererror")[0];
	if ( !xml || parserErrorElem ) {
		jQuery.error( "Invalid XML: " + (
			parserErrorElem ?
				jQuery.map(parserErrorElem.childNodes, function( el ) {
					return el.textContent;
				}).join("\n"): data
		) );
	}
	return xml;
};

My question: can you use latest ecmascript features in this code?

Answer:

const parseXML = data => {
  let xml, parserErrorElem
  if (!data || typeof data !== "string") {
    return null
  }

  // Support: IE 9 - 11+
  // IE throws on parseFromString with invalid input.
  try {
    xml = new window.DOMParser().parseFromString(data, "text/xml")
  } catch (e) {}

  parserErrorElem = xml?.getElementsByTagName("parsererror")[0]
  if (!xml || parserErrorElem) {
    throw new Error(
      "Invalid XML: " +
        (parserErrorElem
          ? Array.from(parserErrorElem.childNodes, el => el.textContent).join(
              "\n",
            )
          : data),
    )
  }
  return xml
}

My question: can you use es6 features in this code?

Answer:

const parseXML = data => {
  let xml, parserErrorElem
  if (!data || typeof data !== "string") {
    return null
  }

  // Support: IE 9 - 11+
  // IE throws on parseFromString with invalid input.
  try {
    xml = new window.DOMParser().parseFromString(data, "text/xml")
  } catch (e) {}

  parserErrorElem = xml && xml.getElementsByTagName("parsererror")[0]
  if (!xml || parserErrorElem) {
    throw new Error(
      "Invalid XML: " +
        (parserErrorElem
          ? Array.from(parserErrorElem.childNodes, el => el.textContent).join(
              "\n",
            )
          : data),
    )
  }
  return xml
}

To save your eyes in latest ES Copilot used https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining and in both he switched to Array.from. Type of changes you will see depends heavily on code you try to update to latest ES but I would advices to update to latest ES directly in Copilot prompt.

BTW short list of things ES added from version to version:

  • ES7 (ES2016): Includes Array.prototype.includes for checking if an array includes a certain value and exponentiation operator (**).
  • ES8 (ES2017): Introduces async functions, shared memory, and atomics.
  • ES9 (ES2018): Adds rest/spread properties, asynchronous iteration, and Promise.finally.
  • ES10 (ES2019): Includes Array.prototype.flat and Array.prototype.flatMap, and Object.fromEntries.
  • ES11 (ES2020): Introduces optional chaining (?.), nullish coalescing operator (??), and BigInt for working with arbitrary precision integers.
  • ES12 (ES2021): Includes logical assignment operators (&&=, ||=, ??=) and numeric separators.

Making code use latest ES features will help readability but might hurt performance

You probably didn’t wanted to hear this but it seems to be true for now and - it depends on JS engine you use heavily. It seems that Chrome is optimizing latest ES features so on Chrome (and on NodeJS too) you will (maybe) not see any (little) difference. This might be different if you are in browser world and you want to have fast UI on all browsers equally.

Let’s evaluate sample function:

function concatenateAndFilter(arr1, arr2) {
  var result = arr1.concat(arr2)
  var filteredResult = result.filter(function (item) {
    return item !== null && item !== undefined
  })
  return filteredResult
}

This function doesn’t do anything particularly useful but we can see difference between ES6 and latest ES in more things we can do with Arrays (https://www3.ntu.edu.sg/home/ehchua/programming/webprogramming/JavaScript_Introduction.html) among other nice things.

My question : can you make this function use es6 features where makes sense?

const concatenateAndFilter = (arr1, arr2) => {
  const result = [...arr1, ...arr2]
  const filteredResult = result.filter(
    item => item !== null && item !== undefined,
  )
  return filteredResult
}

My question : can you make this function use latest es features where makes sense?

const concatenateAndFilter = (arr1, arr2) => {
  const result = [...arr1, ...arr2]
  const filteredResult = result.filter(item => item != null)
  return filteredResult
}

Tests to try on your machine here: https://jsbench.me/8qlo1u6d9b/1

Results in Firefox 118.0.2: results in FireFox 118.0.2 vs Results in Chrome 118.0.5993.89 results in FireFox 118.0.2 Quite a difference, right?

Have a good time updating your codebase with Copilot.


Profile picture

Written by Dušan Roštár - the "mr edge case" guy
my twitter : rostacik, my linkedin : rostar, drop me an email : here