// This file was automatically generated by "compat-table.js"

package compat

type Engine uint8

const (
	Chrome Engine = iota
	Edge
	ES
	Firefox
	IOS
	Node
	Safari
)

type JSFeature uint64

const (
	ArraySpread JSFeature = 1 << iota
	Arrow
	AsyncAwait
	AsyncGenerator
	BigInt
	Class
	ClassField
	ClassPrivateAccessor
	ClassPrivateField
	ClassPrivateMethod
	ClassPrivateStaticAccessor
	ClassPrivateStaticField
	ClassPrivateStaticMethod
	ClassStaticField
	Const
	DefaultArgument
	Destructuring
	ExponentOperator
	ExportStarAs
	ForAwait
	ForOf
	Generator
	Hashbang
	ImportMeta
	Let
	LogicalAssignment
	NestedRestBinding
	NewTarget
	NullishCoalescing
	ObjectAccessors
	ObjectExtensions
	ObjectRestSpread
	OptionalCatchBinding
	OptionalChain
	RestArgument
	TemplateLiteral
	TopLevelAwait
	UnicodeEscapes
)

func (features JSFeature) Has(feature JSFeature) bool {
	return (features & feature) != 0
}

var jsTable = map[JSFeature]map[Engine][]int{
	ArraySpread: {
		Chrome:  {46},
		Edge:    {12},
		ES:      {2015},
		Firefox: {27},
		IOS:     {8},
		Node:    {5},
		Safari:  {7, 1},
	},
	Arrow: {
		Chrome:  {45},
		Edge:    {12},
		ES:      {2015},
		Firefox: {22},
		IOS:     {10},
		Node:    {4},
		Safari:  {10},
	},
	AsyncAwait: {
		Chrome:  {55},
		Edge:    {15},
		ES:      {2017},
		Firefox: {52},
		IOS:     {10, 3},
		Node:    {7, 6},
		Safari:  {10, 1},
	},
	AsyncGenerator: {
		Chrome:  {63},
		Edge:    {79},
		ES:      {2018},
		Firefox: {57},
		IOS:     {12},
		Node:    {10, 0},
		Safari:  {12},
	},
	BigInt: {
		Chrome:  {67},
		Edge:    {79},
		ES:      {2020},
		Firefox: {68},
		Node:    {10, 4},
		Safari:  {14},
	},
	Class: {
		Chrome:  {49},
		Edge:    {13},
		ES:      {2015},
		Firefox: {45},
		IOS:     {9},
		Node:    {6},
		Safari:  {9},
	},
	ClassField: {
		Chrome:  {72},
		Edge:    {79},
		Firefox: {69},
		Node:    {12, 0},
		Safari:  {14},
	},
	ClassPrivateAccessor: {
		Chrome: {84},
		Edge:   {84},
	},
	ClassPrivateField: {
		Chrome: {74},
		Edge:   {79},
		Node:   {12, 0},
	},
	ClassPrivateMethod: {
		Chrome: {84},
		Edge:   {84},
	},
	ClassPrivateStaticAccessor: {
		Chrome: {84},
		Edge:   {84},
	},
	ClassPrivateStaticField: {
		Chrome: {74},
		Edge:   {79},
		Node:   {12, 0},
	},
	ClassPrivateStaticMethod: {
		Chrome: {84},
		Edge:   {84},
	},
	ClassStaticField: {
		Chrome:  {72},
		Edge:    {79},
		Firefox: {75},
		Node:    {12, 0},
	},
	Const: {
		Chrome:  {5},
		Edge:    {12},
		ES:      {2015},
		Firefox: {3},
		IOS:     {6},
		Node:    {0, 12},
		Safari:  {3, 1},
	},
	DefaultArgument: {
		Chrome:  {49},
		Edge:    {14},
		ES:      {2015},
		Firefox: {15},
		IOS:     {10},
		Node:    {6},
		Safari:  {10},
	},
	Destructuring: {
		Chrome:  {49},
		Edge:    {14},
		ES:      {2015},
		Firefox: {2},
		IOS:     {8},
		Node:    {6},
		Safari:  {7, 1},
	},
	ExponentOperator: {
		Chrome:  {52},
		Edge:    {14},
		ES:      {2016},
		Firefox: {52},
		IOS:     {10, 3},
		Node:    {7},
		Safari:  {10, 1},
	},
	ExportStarAs: {
		Chrome:  {72},
		Edge:    {79},
		ES:      {2020},
		Firefox: {80},
		Node:    {12},
	},
	ForAwait: {
		Chrome:  {63},
		Edge:    {79},
		ES:      {2018},
		Firefox: {57},
		IOS:     {12},
		Node:    {10, 0},
		Safari:  {12},
	},
	ForOf: {
		Chrome:  {38},
		Edge:    {12},
		ES:      {2015},
		Firefox: {13},
		IOS:     {8},
		Node:    {0, 12},
		Safari:  {7, 1},
	},
	Generator: {
		Chrome:  {39},
		Edge:    {13},
		ES:      {2015},
		Firefox: {27},
		IOS:     {10},
		Node:    {4},
		Safari:  {10},
	},
	Hashbang: {
		Chrome:  {74},
		Edge:    {79},
		Firefox: {67},
		IOS:     {13, 4},
		Node:    {12, 0},
		Safari:  {13, 1},
	},
	ImportMeta: {
		Chrome:  {64},
		Edge:    {79},
		ES:      {2020},
		Firefox: {62},
		IOS:     {12},
		Safari:  {11, 1},
	},
	Let: {
		Chrome:  {49},
		Edge:    {12},
		ES:      {2015},
		Firefox: {44},
		IOS:     {10},
		Node:    {6},
		Safari:  {10},
	},
	LogicalAssignment: {
		Chrome:  {85},
		Firefox: {79},
		Safari:  {14},
	},
	NestedRestBinding: {
		Chrome:  {49},
		Edge:    {14},
		ES:      {2016},
		Firefox: {47},
		IOS:     {10, 3},
		Node:    {6},
		Safari:  {10, 1},
	},
	NewTarget: {
		Chrome:  {46},
		Edge:    {13},
		ES:      {2015},
		Firefox: {41},
		IOS:     {10},
		Node:    {5},
		Safari:  {10},
	},
	NullishCoalescing: {
		Chrome:  {80},
		Edge:    {80},
		ES:      {2020},
		Firefox: {72},
		IOS:     {13, 4},
		Node:    {14, 0},
		Safari:  {13, 1},
	},
	ObjectAccessors: {
		Chrome:  {5},
		Edge:    {12},
		ES:      {5},
		Firefox: {2},
		IOS:     {6},
		Node:    {0, 10},
		Safari:  {3, 1},
	},
	ObjectExtensions: {
		Chrome:  {44},
		Edge:    {12},
		ES:      {2015},
		Firefox: {34},
		IOS:     {8},
		Node:    {4},
		Safari:  {7, 1},
	},
	ObjectRestSpread: {
		Chrome:  {60},
		Edge:    {79},
		ES:      {2018},
		Firefox: {55},
		IOS:     {11, 3},
		Node:    {8, 3},
		Safari:  {11, 1},
	},
	OptionalCatchBinding: {
		Chrome:  {66},
		Edge:    {79},
		ES:      {2019},
		Firefox: {58},
		IOS:     {11, 3},
		Node:    {10, 0},
		Safari:  {11, 1},
	},
	OptionalChain: {
		Chrome:  {80},
		Edge:    {80},
		ES:      {2020},
		Firefox: {74},
		IOS:     {13, 4},
		Node:    {14, 0},
		Safari:  {13, 1},
	},
	RestArgument: {
		Chrome:  {47},
		Edge:    {12},
		ES:      {2015},
		Firefox: {15},
		IOS:     {10},
		Node:    {6},
		Safari:  {10},
	},
	TemplateLiteral: {
		Chrome:  {41},
		Edge:    {12},
		ES:      {2015},
		Firefox: {34},
		IOS:     {9},
		Node:    {4},
		Safari:  {9},
	},
	TopLevelAwait: {},
	UnicodeEscapes: {
		Chrome:  {44},
		Edge:    {12},
		ES:      {2015},
		Firefox: {40},
		IOS:     {9},
		Node:    {4},
		Safari:  {9},
	},
}

func isVersionLessThan(a []int, b []int) bool {
	for i := 0; i < len(a) && i < len(b); i++ {
		if a[i] > b[i] {
			return false
		}
		if a[i] < b[i] {
			return true
		}
	}
	return len(a) < len(b)
}

// Return all features that are not available in at least one environment
func UnsupportedJSFeatures(constraints map[Engine][]int) (unsupported JSFeature) {
	for feature, engines := range jsTable {
		for engine, version := range constraints {
			if minVersion, ok := engines[engine]; !ok || isVersionLessThan(version, minVersion) {
				unsupported |= feature
			}
		}
	}
	return
}
