tc39_test.go 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822
  1. package goja
  2. import (
  3. "errors"
  4. "fmt"
  5. "io"
  6. "os"
  7. "path"
  8. "sort"
  9. "strings"
  10. "sync"
  11. "testing"
  12. "time"
  13. "gopkg.in/yaml.v2"
  14. )
  15. const (
  16. tc39BASE = "testdata/test262"
  17. )
  18. var (
  19. invalidFormatError = errors.New("Invalid file format")
  20. ignorableTestError = newSymbol(stringEmpty)
  21. )
  22. var (
  23. skipPrefixes prefixList
  24. skipList = map[string]bool{
  25. // out-of-date (https://github.com/tc39/test262/issues/3407)
  26. "test/language/expressions/prefix-increment/S11.4.4_A6_T3.js": true,
  27. "test/language/expressions/prefix-increment/S11.4.4_A6_T2.js": true,
  28. "test/language/expressions/prefix-increment/S11.4.4_A6_T1.js": true,
  29. "test/language/expressions/prefix-decrement/S11.4.5_A6_T3.js": true,
  30. "test/language/expressions/prefix-decrement/S11.4.5_A6_T2.js": true,
  31. "test/language/expressions/prefix-decrement/S11.4.5_A6_T1.js": true,
  32. "test/language/expressions/postfix-increment/S11.3.1_A6_T3.js": true,
  33. "test/language/expressions/postfix-increment/S11.3.1_A6_T2.js": true,
  34. "test/language/expressions/postfix-increment/S11.3.1_A6_T1.js": true,
  35. "test/language/expressions/postfix-decrement/S11.3.2_A6_T3.js": true,
  36. "test/language/expressions/postfix-decrement/S11.3.2_A6_T2.js": true,
  37. "test/language/expressions/postfix-decrement/S11.3.2_A6_T1.js": true,
  38. "test/language/expressions/compound-assignment/S11.13.2_A7.1_T4.js": true,
  39. "test/language/expressions/compound-assignment/S11.13.2_A7.1_T2.js": true,
  40. "test/language/expressions/compound-assignment/S11.13.2_A7.1_T1.js": true,
  41. "test/language/expressions/compound-assignment/S11.13.2_A7.11_T4.js": true,
  42. "test/language/expressions/compound-assignment/S11.13.2_A7.11_T2.js": true,
  43. "test/language/expressions/compound-assignment/S11.13.2_A7.11_T1.js": true,
  44. "test/language/expressions/compound-assignment/S11.13.2_A7.10_T4.js": true,
  45. "test/language/expressions/compound-assignment/S11.13.2_A7.10_T2.js": true,
  46. "test/language/expressions/compound-assignment/S11.13.2_A7.10_T1.js": true,
  47. "test/language/expressions/compound-assignment/S11.13.2_A7.9_T4.js": true,
  48. "test/language/expressions/compound-assignment/S11.13.2_A7.9_T2.js": true,
  49. "test/language/expressions/compound-assignment/S11.13.2_A7.9_T1.js": true,
  50. "test/language/expressions/compound-assignment/S11.13.2_A7.8_T4.js": true,
  51. "test/language/expressions/compound-assignment/S11.13.2_A7.8_T2.js": true,
  52. "test/language/expressions/compound-assignment/S11.13.2_A7.8_T1.js": true,
  53. "test/language/expressions/compound-assignment/S11.13.2_A7.7_T4.js": true,
  54. "test/language/expressions/compound-assignment/S11.13.2_A7.7_T2.js": true,
  55. "test/language/expressions/compound-assignment/S11.13.2_A7.7_T1.js": true,
  56. "test/language/expressions/compound-assignment/S11.13.2_A7.6_T4.js": true,
  57. "test/language/expressions/compound-assignment/S11.13.2_A7.6_T2.js": true,
  58. "test/language/expressions/compound-assignment/S11.13.2_A7.6_T1.js": true,
  59. "test/language/expressions/compound-assignment/S11.13.2_A7.5_T4.js": true,
  60. "test/language/expressions/compound-assignment/S11.13.2_A7.5_T2.js": true,
  61. "test/language/expressions/compound-assignment/S11.13.2_A7.5_T1.js": true,
  62. "test/language/expressions/compound-assignment/S11.13.2_A7.4_T4.js": true,
  63. "test/language/expressions/compound-assignment/S11.13.2_A7.4_T2.js": true,
  64. "test/language/expressions/compound-assignment/S11.13.2_A7.4_T1.js": true,
  65. "test/language/expressions/compound-assignment/S11.13.2_A7.3_T4.js": true,
  66. "test/language/expressions/compound-assignment/S11.13.2_A7.3_T2.js": true,
  67. "test/language/expressions/compound-assignment/S11.13.2_A7.3_T1.js": true,
  68. "test/language/expressions/compound-assignment/S11.13.2_A7.2_T4.js": true,
  69. "test/language/expressions/compound-assignment/S11.13.2_A7.2_T2.js": true,
  70. "test/language/expressions/compound-assignment/S11.13.2_A7.2_T1.js": true,
  71. "test/language/expressions/assignment/S11.13.1_A7_T3.js": true,
  72. // timezone
  73. "test/built-ins/Date/prototype/toISOString/15.9.5.43-0-8.js": true,
  74. "test/built-ins/Date/prototype/toISOString/15.9.5.43-0-9.js": true,
  75. "test/built-ins/Date/prototype/toISOString/15.9.5.43-0-10.js": true,
  76. // floating point date calculations
  77. "test/built-ins/Date/UTC/fp-evaluation-order.js": true,
  78. // quantifier integer limit in regexp
  79. "test/built-ins/RegExp/quantifier-integer-limit.js": true,
  80. // GetFunctionRealm
  81. "test/built-ins/Function/internals/Construct/base-ctor-revoked-proxy.js": true,
  82. // Uses deprecated __lookupGetter__/__lookupSetter__
  83. "test/language/expressions/class/elements/private-getter-is-not-a-own-property.js": true,
  84. "test/language/expressions/class/elements/private-setter-is-not-a-own-property.js": true,
  85. "test/language/statements/class/elements/private-setter-is-not-a-own-property.js": true,
  86. "test/language/statements/class/elements/private-getter-is-not-a-own-property.js": true,
  87. // restricted unicode regexp syntax
  88. "test/built-ins/RegExp/unicode_restricted_quantifiable_assertion.js": true,
  89. "test/built-ins/RegExp/unicode_restricted_octal_escape.js": true,
  90. "test/built-ins/RegExp/unicode_restricted_incomple_quantifier.js": true,
  91. "test/built-ins/RegExp/unicode_restricted_incomplete_quantifier.js": true,
  92. "test/built-ins/RegExp/unicode_restricted_identity_escape_x.js": true,
  93. "test/built-ins/RegExp/unicode_restricted_identity_escape_u.js": true,
  94. "test/built-ins/RegExp/unicode_restricted_identity_escape_c.js": true,
  95. "test/built-ins/RegExp/unicode_restricted_identity_escape_alpha.js": true,
  96. "test/built-ins/RegExp/unicode_restricted_identity_escape.js": true,
  97. "test/built-ins/RegExp/unicode_restricted_brackets.js": true,
  98. "test/built-ins/RegExp/unicode_restricted_character_class_escape.js": true,
  99. "test/annexB/built-ins/RegExp/prototype/compile/pattern-string-invalid-u.js": true,
  100. // Because goja parser works in UTF-8 it is not possible to pass strings containing invalid UTF-16 code points.
  101. // This is mitigated by escaping them as \uXXXX, however because of this the RegExp source becomes
  102. // `\uXXXX` instead of `<the actual UTF-16 code point of XXXX>`.
  103. // The resulting RegExp will work exactly the same, but it causes these two tests to fail.
  104. "test/annexB/built-ins/RegExp/RegExp-leading-escape-BMP.js": true,
  105. "test/annexB/built-ins/RegExp/RegExp-trailing-escape-BMP.js": true,
  106. "test/language/literals/regexp/S7.8.5_A1.4_T2.js": true,
  107. "test/language/literals/regexp/S7.8.5_A1.1_T2.js": true,
  108. "test/language/literals/regexp/S7.8.5_A2.1_T2.js": true,
  109. "test/language/literals/regexp/S7.8.5_A2.4_T2.js": true,
  110. // generators
  111. "test/annexB/built-ins/RegExp/RegExp-control-escape-russian-letter.js": true,
  112. "test/language/statements/switch/scope-lex-generator.js": true,
  113. "test/language/expressions/in/rhs-yield-present.js": true,
  114. "test/language/expressions/object/cpn-obj-lit-computed-property-name-from-yield-expression.js": true,
  115. "test/language/expressions/object/cpn-obj-lit-computed-property-name-from-generator-function-declaration.js": true,
  116. "test/built-ins/TypedArrayConstructors/ctors/object-arg/as-generator-iterable-returns.js": true,
  117. "test/built-ins/Object/seal/seal-generatorfunction.js": true,
  118. "test/language/statements/class/syntax/class-declaration-computed-method-generator-definition.js": true,
  119. "test/language/statements/class/cpn-class-decl-fields-methods-computed-property-name-from-yield-expression.js": true,
  120. "test/language/statements/class/cpn-class-decl-fields-methods-computed-property-name-from-generator-function-declaration.js": true,
  121. "test/language/statements/class/cpn-class-decl-fields-computed-property-name-from-yield-expression.js": true,
  122. "test/language/statements/class/cpn-class-decl-fields-computed-property-name-from-generator-function-declaration.js": true,
  123. "test/language/statements/class/cpn-class-decl-computed-property-name-from-yield-expression.js": true,
  124. "test/language/statements/class/cpn-class-decl-computed-property-name-from-generator-function-declaration.js": true,
  125. "test/language/statements/class/cpn-class-decl-accessors-computed-property-name-from-yield-expression.js": true,
  126. "test/language/statements/class/cpn-class-decl-accessors-computed-property-name-from-generator-function-declaration.js": true,
  127. "test/language/expressions/class/cpn-class-expr-fields-computed-property-name-from-yield-expression.js": true,
  128. "test/language/expressions/class/cpn-class-expr-fields-computed-property-name-from-generator-function-declaration.js": true,
  129. "test/language/expressions/class/cpn-class-expr-computed-property-name-from-yield-expression.js": true,
  130. "test/language/expressions/class/cpn-class-expr-computed-property-name-from-generator-function-declaration.js": true,
  131. "test/language/expressions/class/cpn-class-expr-accessors-computed-property-name-from-yield-expression.js": true,
  132. "test/language/expressions/class/cpn-class-expr-fields-methods-computed-property-name-from-yield-expression.js": true,
  133. "test/language/expressions/class/cpn-class-expr-accessors-computed-property-name-from-generator-function-declaration.js": true,
  134. "test/language/expressions/class/cpn-class-expr-fields-methods-computed-property-name-from-generator-function-declaration.js": true,
  135. "test/language/statements/class/static-init-arguments-methods.js": true,
  136. "test/language/statements/class/static-init-arguments-functions.js": true,
  137. "test/language/expressions/object/method-definition/static-init-await-reference-generator.js": true,
  138. "test/language/expressions/generators/static-init-await-binding.js": true,
  139. "test/language/expressions/generators/static-init-await-reference.js": true,
  140. "test/language/expressions/optional-chaining/member-expression.js": true,
  141. "test/language/expressions/class/elements/private-generator-method-name.js": true,
  142. "test/language/statements/class/elements/private-generator-method-name.js": true,
  143. "test/language/expressions/in/private-field-rhs-yield-present.js": true,
  144. "test/language/expressions/class/elements/private-static-generator-method-name.js": true,
  145. "test/language/expressions/class/elements/private-static-async-generator-method-name.js": true,
  146. "test/language/computed-property-names/class/static/generator-prototype.js": true,
  147. "test/language/computed-property-names/class/method/constructor-can-be-generator.js": true,
  148. "test/language/computed-property-names/class/static/generator-constructor.js": true,
  149. "test/language/computed-property-names/class/method/generator.js": true,
  150. "test/language/computed-property-names/object/method/generator.js": true,
  151. "test/language/destructuring/binding/syntax/destructuring-object-parameters-function-arguments-length.js": true,
  152. "test/language/destructuring/binding/syntax/destructuring-array-parameters-function-arguments-length.js": true,
  153. // async
  154. "test/language/eval-code/direct/async-func-decl-a-preceding-parameter-is-named-arguments-declare-arguments-and-assign.js": true,
  155. "test/language/statements/switch/scope-lex-async-generator.js": true,
  156. "test/language/statements/switch/scope-lex-async-function.js": true,
  157. "test/language/statements/for-of/head-lhs-async-invalid.js": true,
  158. "test/language/expressions/object/cpn-obj-lit-computed-property-name-from-async-arrow-function-expression.js": true,
  159. "test/language/expressions/object/cpn-obj-lit-computed-property-name-from-await-expression.js": true,
  160. "test/language/statements/async-function/evaluation-body.js": true,
  161. "test/language/expressions/object/method-definition/object-method-returns-promise.js": true,
  162. "test/language/expressions/object/method-definition/async-super-call-param.js": true,
  163. "test/language/expressions/object/method-definition/async-super-call-body.js": true,
  164. "test/built-ins/Object/seal/seal-asyncgeneratorfunction.js": true,
  165. "test/built-ins/Object/seal/seal-asyncfunction.js": true,
  166. "test/built-ins/Object/seal/seal-asyncarrowfunction.js": true,
  167. "test/language/statements/for/head-init-async-of.js": true,
  168. "test/language/reserved-words/await-module.js": true,
  169. "test/language/expressions/optional-chaining/optional-chain-async-square-brackets.js": true,
  170. "test/language/expressions/optional-chaining/optional-chain-async-optional-chain-square-brackets.js": true,
  171. "test/language/expressions/optional-chaining/member-expression-async-this.js": true,
  172. "test/language/expressions/optional-chaining/member-expression-async-literal.js": true,
  173. "test/language/expressions/optional-chaining/member-expression-async-identifier.js": true,
  174. "test/language/expressions/optional-chaining/iteration-statement-for-await-of.js": true,
  175. "test/language/statements/class/cpn-class-decl-fields-methods-computed-property-name-from-async-arrow-function-expression.js": true,
  176. "test/language/statements/class/cpn-class-decl-fields-computed-property-name-from-async-arrow-function-expression.js": true,
  177. "test/language/statements/class/cpn-class-decl-computed-property-name-from-async-arrow-function-expression.js": true,
  178. "test/language/statements/class/cpn-class-decl-accessors-computed-property-name-from-async-arrow-function-expression.js": true,
  179. "test/language/expressions/class/cpn-class-expr-fields-computed-property-name-from-async-arrow-function-expression.js": true,
  180. "test/language/expressions/class/cpn-class-expr-computed-property-name-from-async-arrow-function-expression.js": true,
  181. "test/language/expressions/class/cpn-class-expr-accessors-computed-property-name-from-async-arrow-function-expression.js": true,
  182. "test/language/expressions/class/cpn-class-expr-fields-methods-computed-property-name-from-async-arrow-function-expression.js": true,
  183. "test/language/statements/let/static-init-await-binding-invalid.js": true,
  184. "test/language/statements/labeled/static-init-invalid-await.js": true,
  185. "test/language/statements/variable/dstr/obj-ptrn-elem-id-static-init-await-invalid.js": true,
  186. "test/language/statements/variable/static-init-await-binding-invalid.js": true,
  187. "test/language/statements/variable/dstr/ary-ptrn-elem-id-static-init-await-invalid.js": true,
  188. "test/language/statements/try/static-init-await-binding-invalid.js": true,
  189. "test/language/statements/function/static-init-await-binding-invalid.js": true,
  190. "test/language/statements/const/static-init-await-binding-invalid.js": true,
  191. "test/language/statements/class/static-init-await-binding-invalid.js": true,
  192. "test/language/identifier-resolution/static-init-invalid-await.js": true,
  193. "test/language/expressions/class/static-init-await-binding.js": true,
  194. "test/language/expressions/class/heritage-async-arrow-function.js": true,
  195. "test/language/expressions/arrow-function/static-init-await-reference.js": true,
  196. "test/language/expressions/arrow-function/static-init-await-binding.js": true,
  197. "test/language/expressions/object/method-definition/static-init-await-binding-generator.js": true,
  198. "test/language/expressions/object/identifier-shorthand-static-init-await-invalid.js": true,
  199. "test/language/expressions/class/heritage-arrow-function.js": true,
  200. "test/language/expressions/class/elements/private-async-generator-method-name.js": true,
  201. "test/language/expressions/class/elements/private-async-method-name.js": true,
  202. "test/language/statements/class/elements/private-async-generator-method-name.js": true,
  203. "test/language/statements/class/elements/private-async-method-name.js": true,
  204. "test/language/expressions/in/private-field-rhs-await-present.js": true,
  205. "test/language/expressions/class/elements/private-static-async-method-name.js": true,
  206. "test/language/comments/hashbang/function-constructor.js": true,
  207. // legacy number literals
  208. "test/language/literals/numeric/non-octal-decimal-integer.js": true,
  209. "test/language/literals/string/S7.8.4_A4.3_T2.js": true,
  210. "test/language/literals/string/S7.8.4_A4.3_T1.js": true,
  211. // integer separators
  212. "test/language/expressions/object/cpn-obj-lit-computed-property-name-from-integer-separators.js": true,
  213. "test/language/expressions/class/cpn-class-expr-accessors-computed-property-name-from-integer-separators.js": true,
  214. "test/language/statements/class/cpn-class-decl-fields-computed-property-name-from-integer-separators.js": true,
  215. "test/language/statements/class/cpn-class-decl-computed-property-name-from-integer-separators.js": true,
  216. "test/language/statements/class/cpn-class-decl-accessors-computed-property-name-from-integer-separators.js": true,
  217. "test/language/statements/class/cpn-class-decl-fields-methods-computed-property-name-from-integer-separators.js": true,
  218. "test/language/expressions/class/cpn-class-expr-fields-computed-property-name-from-integer-separators.js": true,
  219. "test/language/expressions/class/cpn-class-expr-computed-property-name-from-integer-separators.js": true,
  220. "test/language/expressions/class/cpn-class-expr-fields-methods-computed-property-name-from-integer-separators.js": true,
  221. // BigInt
  222. "test/built-ins/Object/seal/seal-biguint64array.js": true,
  223. "test/built-ins/Object/seal/seal-bigint64array.js": true,
  224. // Regexp
  225. "test/language/literals/regexp/invalid-range-negative-lookbehind.js": true,
  226. "test/language/literals/regexp/invalid-range-lookbehind.js": true,
  227. "test/language/literals/regexp/invalid-optional-negative-lookbehind.js": true,
  228. "test/language/literals/regexp/invalid-optional-lookbehind.js": true,
  229. // FIXME bugs
  230. // 'in' in a branch
  231. "test/language/expressions/conditional/in-branch-1.js": true,
  232. // Left-hand side as a CoverParenthesizedExpression
  233. "test/language/expressions/assignment/fn-name-lhs-cover.js": true,
  234. }
  235. featuresBlackList = []string{
  236. "async-iteration",
  237. "Symbol.asyncIterator",
  238. "async-functions",
  239. "BigInt",
  240. "generators",
  241. "String.prototype.replaceAll",
  242. "resizable-arraybuffer",
  243. "array-find-from-last",
  244. "regexp-named-groups",
  245. "regexp-dotall",
  246. "regexp-unicode-property-escapes",
  247. "regexp-match-indices",
  248. "legacy-regexp",
  249. "tail-call-optimization",
  250. "Temporal",
  251. "import-assertions",
  252. "dynamic-import",
  253. "logical-assignment-operators",
  254. "import.meta",
  255. "Atomics",
  256. "Atomics.waitAsync",
  257. "FinalizationRegistry",
  258. "WeakRef",
  259. "numeric-separator-literal",
  260. "Object.fromEntries",
  261. "Object.hasOwn",
  262. "__getter__",
  263. "__setter__",
  264. "ShadowRealm",
  265. "SharedArrayBuffer",
  266. "error-cause",
  267. "decorators",
  268. "regexp-v-flag",
  269. }
  270. )
  271. func init() {
  272. skip := func(prefixes ...string) {
  273. for _, prefix := range prefixes {
  274. skipPrefixes.Add(prefix)
  275. }
  276. }
  277. skip(
  278. // Go 1.16 only supports unicode 13
  279. "test/language/identifiers/start-unicode-14.",
  280. "test/language/identifiers/part-unicode-14.",
  281. // async
  282. "test/language/eval-code/direct/async-",
  283. "test/language/expressions/async-",
  284. "test/language/expressions/await/",
  285. "test/language/statements/async-function/",
  286. "test/built-ins/Async",
  287. "test/language/statements/class/elements/private-static-async-",
  288. "test/language/statements/class/elements/wrapped-in-sc-rs-static-async-",
  289. "test/language/expressions/class/elements/wrapped-in-sc-rs-static-async-",
  290. "test/language/statements/class/elements/after-same-line-static-method-rs-static-async-",
  291. "test/language/expressions/class/elements/after-same-line-static-method-rs-static-async-",
  292. "test/language/statements/class/elements/after-same-line-method-rs-static-async-",
  293. "test/language/expressions/class/elements/after-same-line-method-rs-static-async-",
  294. "test/language/statements/class/elements/new-sc-line-method-rs-static-async-",
  295. "test/language/expressions/class/elements/new-sc-line-method-rs-static-async-",
  296. "test/language/statements/class/elements/new-no-sc-line-method-rs-static-async-",
  297. "test/language/expressions/class/elements/new-no-sc-line-method-rs-static-async-",
  298. "test/language/statements/class/elements/same-line-method-rs-static-async-",
  299. "test/language/expressions/class/elements/same-line-method-rs-static-async-",
  300. "test/language/statements/class/elements/regular-definitions-rs-static-async-",
  301. "test/language/expressions/class/elements/regular-definitions-rs-static-async-",
  302. "test/language/statements/class/elements/multiple-stacked-definitions-rs-static-async-",
  303. "test/language/expressions/class/elements/multiple-stacked-definitions-rs-static-async-",
  304. "test/language/statements/class/elements/multiple-definitions-rs-static-async-",
  305. "test/language/expressions/class/elements/multiple-definitions-rs-static-async-",
  306. // generators
  307. "test/language/eval-code/direct/gen-",
  308. "test/built-ins/GeneratorFunction/",
  309. "test/built-ins/Function/prototype/toString/generator-",
  310. "test/language/statements/class/elements/private-static-generator-",
  311. "test/language/statements/class/subclass/builtin-objects/GeneratorFunction/",
  312. "test/language/statements/class/elements/wrapped-in-sc-rs-static-generator-",
  313. "test/language/expressions/class/elements/wrapped-in-sc-rs-static-generator-",
  314. "test/language/statements/class/elements/after-same-line-method-rs-static-generator-",
  315. "test/language/expressions/class/elements/after-same-line-method-rs-static-generator-",
  316. "test/language/statements/class/elements/after-same-line-static-method-rs-static-generator-",
  317. "test/language/expressions/class/elements/after-same-line-static-method-rs-static-generator-",
  318. "test/language/statements/class/elements/new-sc-line-method-rs-static-generator-",
  319. "test/language/expressions/class/elements/new-sc-line-method-rs-static-generator-",
  320. "test/language/statements/class/elements/new-no-sc-line-method-rs-static-generator-",
  321. "test/language/expressions/class/elements/new-no-sc-line-method-rs-static-generator-",
  322. "test/language/statements/class/elements/same-line-method-rs-static-generator-",
  323. "test/language/expressions/class/elements/same-line-method-rs-static-generator-",
  324. "test/language/statements/class/elements/regular-definitions-rs-static-generator-",
  325. "test/language/expressions/class/elements/regular-definitions-rs-static-generator-",
  326. "test/language/statements/class/elements/multiple-stacked-definitions-rs-static-generator-",
  327. "test/language/expressions/class/elements/multiple-stacked-definitions-rs-static-generator-",
  328. "test/language/statements/class/elements/multiple-definitions-rs-static-generator-",
  329. "test/language/expressions/class/elements/multiple-definitions-rs-static-generator-",
  330. // BigInt
  331. "test/built-ins/TypedArrayConstructors/BigUint64Array/",
  332. "test/built-ins/TypedArrayConstructors/BigInt64Array/",
  333. // restricted unicode regexp syntax
  334. "test/language/literals/regexp/u-",
  335. // legacy octal escape in strings in strict mode
  336. "test/language/literals/string/legacy-octal-",
  337. "test/language/literals/string/legacy-non-octal-",
  338. // modules
  339. "test/language/export/",
  340. "test/language/import/",
  341. "test/language/module-code/",
  342. )
  343. }
  344. type tc39Test struct {
  345. name string
  346. f func(t *testing.T)
  347. }
  348. type tc39BenchmarkItem struct {
  349. name string
  350. duration time.Duration
  351. }
  352. type tc39BenchmarkData []tc39BenchmarkItem
  353. type tc39TestCtx struct {
  354. base string
  355. t *testing.T
  356. prgCache map[string]*Program
  357. prgCacheLock sync.Mutex
  358. enableBench bool
  359. benchmark tc39BenchmarkData
  360. benchLock sync.Mutex
  361. sabStub *Program
  362. //lint:ignore U1000 Only used with race
  363. testQueue []tc39Test
  364. }
  365. type TC39MetaNegative struct {
  366. Phase, Type string
  367. }
  368. type tc39Meta struct {
  369. Negative TC39MetaNegative
  370. Includes []string
  371. Flags []string
  372. Features []string
  373. Es5id string
  374. Es6id string
  375. Esid string
  376. }
  377. type prefixList struct {
  378. prefixes map[int]map[string]struct{}
  379. }
  380. func (pl *prefixList) Add(prefix string) {
  381. l := pl.prefixes[len(prefix)]
  382. if l == nil {
  383. l = make(map[string]struct{})
  384. if pl.prefixes == nil {
  385. pl.prefixes = make(map[int]map[string]struct{})
  386. }
  387. pl.prefixes[len(prefix)] = l
  388. }
  389. l[prefix] = struct{}{}
  390. }
  391. func (pl *prefixList) Match(s string) bool {
  392. for l, prefixes := range pl.prefixes {
  393. if len(s) >= l {
  394. if _, exists := prefixes[s[:l]]; exists {
  395. return true
  396. }
  397. }
  398. }
  399. return false
  400. }
  401. func (m *tc39Meta) hasFlag(flag string) bool {
  402. for _, f := range m.Flags {
  403. if f == flag {
  404. return true
  405. }
  406. }
  407. return false
  408. }
  409. func parseTC39File(name string) (*tc39Meta, string, error) {
  410. f, err := os.Open(name)
  411. if err != nil {
  412. return nil, "", err
  413. }
  414. defer f.Close()
  415. b, err := io.ReadAll(f)
  416. if err != nil {
  417. return nil, "", err
  418. }
  419. str := string(b)
  420. metaStart := strings.Index(str, "/*---")
  421. if metaStart == -1 {
  422. return nil, "", invalidFormatError
  423. } else {
  424. metaStart += 5
  425. }
  426. metaEnd := strings.Index(str, "---*/")
  427. if metaEnd == -1 || metaEnd <= metaStart {
  428. return nil, "", invalidFormatError
  429. }
  430. var meta tc39Meta
  431. err = yaml.Unmarshal([]byte(str[metaStart:metaEnd]), &meta)
  432. if err != nil {
  433. return nil, "", err
  434. }
  435. if meta.Negative.Type != "" && meta.Negative.Phase == "" {
  436. return nil, "", errors.New("negative type is set, but phase isn't")
  437. }
  438. return &meta, str, nil
  439. }
  440. func (*tc39TestCtx) detachArrayBuffer(call FunctionCall) Value {
  441. if obj, ok := call.Argument(0).(*Object); ok {
  442. if buf, ok := obj.self.(*arrayBufferObject); ok {
  443. buf.detach()
  444. return _undefined
  445. }
  446. }
  447. panic(typeError("detachArrayBuffer() is called with incompatible argument"))
  448. }
  449. func (*tc39TestCtx) throwIgnorableTestError(FunctionCall) Value {
  450. panic(ignorableTestError)
  451. }
  452. func (ctx *tc39TestCtx) runTC39Test(name, src string, meta *tc39Meta, t testing.TB) {
  453. defer func() {
  454. if x := recover(); x != nil {
  455. panic(fmt.Sprintf("panic while running %s: %v", name, x))
  456. }
  457. }()
  458. vm := New()
  459. _262 := vm.NewObject()
  460. _262.Set("detachArrayBuffer", ctx.detachArrayBuffer)
  461. _262.Set("createRealm", ctx.throwIgnorableTestError)
  462. _262.Set("evalScript", func(call FunctionCall) Value {
  463. script := call.Argument(0).String()
  464. result, err := vm.RunString(script)
  465. if err != nil {
  466. panic(err)
  467. }
  468. return result
  469. })
  470. vm.Set("$262", _262)
  471. vm.Set("IgnorableTestError", ignorableTestError)
  472. vm.RunProgram(ctx.sabStub)
  473. var out []string
  474. async := meta.hasFlag("async")
  475. if async {
  476. err := ctx.runFile(ctx.base, path.Join("harness", "doneprintHandle.js"), vm)
  477. if err != nil {
  478. t.Fatal(err)
  479. }
  480. vm.Set("print", func(msg string) {
  481. out = append(out, msg)
  482. })
  483. } else {
  484. vm.Set("print", t.Log)
  485. }
  486. err, early := ctx.runTC39Script(name, src, meta.Includes, vm)
  487. if err != nil {
  488. if meta.Negative.Type == "" {
  489. if err, ok := err.(*Exception); ok {
  490. if err.Value() == ignorableTestError {
  491. t.Skip("Test threw IgnorableTestError")
  492. }
  493. }
  494. t.Fatalf("%s: %v", name, err)
  495. } else {
  496. if (meta.Negative.Phase == "early" || meta.Negative.Phase == "parse") && !early || meta.Negative.Phase == "runtime" && early {
  497. t.Fatalf("%s: error %v happened at the wrong phase (expected %s)", name, err, meta.Negative.Phase)
  498. }
  499. var errType string
  500. switch err := err.(type) {
  501. case *Exception:
  502. if o, ok := err.Value().(*Object); ok {
  503. if c := o.Get("constructor"); c != nil {
  504. if c, ok := c.(*Object); ok {
  505. errType = c.Get("name").String()
  506. } else {
  507. t.Fatalf("%s: error constructor is not an object (%v)", name, o)
  508. }
  509. } else {
  510. t.Fatalf("%s: error does not have a constructor (%v)", name, o)
  511. }
  512. } else {
  513. t.Fatalf("%s: error is not an object (%v)", name, err.Value())
  514. }
  515. case *CompilerSyntaxError:
  516. errType = "SyntaxError"
  517. case *CompilerReferenceError:
  518. errType = "ReferenceError"
  519. default:
  520. t.Fatalf("%s: error is not a JS error: %v", name, err)
  521. }
  522. if errType != meta.Negative.Type {
  523. vm.vm.prg.dumpCode(t.Logf)
  524. t.Fatalf("%s: unexpected error type (%s), expected (%s)", name, errType, meta.Negative.Type)
  525. }
  526. }
  527. } else {
  528. if meta.Negative.Type != "" {
  529. vm.vm.prg.dumpCode(t.Logf)
  530. t.Fatalf("%s: Expected error: %v", name, err)
  531. }
  532. }
  533. if vm.vm.sp != 0 {
  534. t.Fatalf("sp: %d", vm.vm.sp)
  535. }
  536. if l := len(vm.vm.iterStack); l > 0 {
  537. t.Fatalf("iter stack is not empty: %d", l)
  538. }
  539. if async {
  540. complete := false
  541. for _, line := range out {
  542. if strings.HasPrefix(line, "Test262:AsyncTestFailure:") {
  543. t.Fatal(line)
  544. } else if line == "Test262:AsyncTestComplete" {
  545. complete = true
  546. }
  547. }
  548. if !complete {
  549. for _, line := range out {
  550. t.Log(line)
  551. }
  552. t.Fatal("Test262:AsyncTestComplete was not printed")
  553. }
  554. }
  555. }
  556. func (ctx *tc39TestCtx) runTC39File(name string, t testing.TB) {
  557. if skipList[name] {
  558. t.Skip("Excluded")
  559. }
  560. if skipPrefixes.Match(name) {
  561. t.Skip("Excluded")
  562. }
  563. p := path.Join(ctx.base, name)
  564. meta, src, err := parseTC39File(p)
  565. if err != nil {
  566. //t.Fatalf("Could not parse %s: %v", name, err)
  567. t.Errorf("Could not parse %s: %v", name, err)
  568. return
  569. }
  570. if meta.hasFlag("module") {
  571. t.Skip("module")
  572. }
  573. if meta.Es5id == "" {
  574. for _, feature := range meta.Features {
  575. for _, bl := range featuresBlackList {
  576. if feature == bl {
  577. t.Skip("Blacklisted feature")
  578. }
  579. }
  580. }
  581. }
  582. var startTime time.Time
  583. if ctx.enableBench {
  584. startTime = time.Now()
  585. }
  586. hasRaw := meta.hasFlag("raw")
  587. if hasRaw || !meta.hasFlag("onlyStrict") {
  588. //log.Printf("Running normal test: %s", name)
  589. t.Logf("Running normal test: %s", name)
  590. ctx.runTC39Test(name, src, meta, t)
  591. }
  592. if !hasRaw && !meta.hasFlag("noStrict") {
  593. //log.Printf("Running strict test: %s", name)
  594. t.Logf("Running strict test: %s", name)
  595. ctx.runTC39Test(name, "'use strict';\n"+src, meta, t)
  596. }
  597. if ctx.enableBench {
  598. ctx.benchLock.Lock()
  599. ctx.benchmark = append(ctx.benchmark, tc39BenchmarkItem{
  600. name: name,
  601. duration: time.Since(startTime),
  602. })
  603. ctx.benchLock.Unlock()
  604. }
  605. }
  606. func (ctx *tc39TestCtx) init() {
  607. ctx.prgCache = make(map[string]*Program)
  608. ctx.sabStub = MustCompile("sabStub.js", `
  609. Object.defineProperty(this, "SharedArrayBuffer", {
  610. get: function() {
  611. throw IgnorableTestError;
  612. }
  613. });`,
  614. false)
  615. }
  616. func (ctx *tc39TestCtx) compile(base, name string) (*Program, error) {
  617. ctx.prgCacheLock.Lock()
  618. defer ctx.prgCacheLock.Unlock()
  619. prg := ctx.prgCache[name]
  620. if prg == nil {
  621. fname := path.Join(base, name)
  622. f, err := os.Open(fname)
  623. if err != nil {
  624. return nil, err
  625. }
  626. defer f.Close()
  627. b, err := io.ReadAll(f)
  628. if err != nil {
  629. return nil, err
  630. }
  631. str := string(b)
  632. prg, err = Compile(name, str, false)
  633. if err != nil {
  634. return nil, err
  635. }
  636. ctx.prgCache[name] = prg
  637. }
  638. return prg, nil
  639. }
  640. func (ctx *tc39TestCtx) runFile(base, name string, vm *Runtime) error {
  641. prg, err := ctx.compile(base, name)
  642. if err != nil {
  643. return err
  644. }
  645. _, err = vm.RunProgram(prg)
  646. return err
  647. }
  648. func (ctx *tc39TestCtx) runTC39Script(name, src string, includes []string, vm *Runtime) (err error, early bool) {
  649. early = true
  650. err = ctx.runFile(ctx.base, path.Join("harness", "assert.js"), vm)
  651. if err != nil {
  652. return
  653. }
  654. err = ctx.runFile(ctx.base, path.Join("harness", "sta.js"), vm)
  655. if err != nil {
  656. return
  657. }
  658. for _, include := range includes {
  659. err = ctx.runFile(ctx.base, path.Join("harness", include), vm)
  660. if err != nil {
  661. return
  662. }
  663. }
  664. var p *Program
  665. p, err = Compile(name, src, false)
  666. if err != nil {
  667. return
  668. }
  669. early = false
  670. _, err = vm.RunProgram(p)
  671. return
  672. }
  673. func (ctx *tc39TestCtx) runTC39Tests(name string) {
  674. files, err := os.ReadDir(path.Join(ctx.base, name))
  675. if err != nil {
  676. ctx.t.Fatal(err)
  677. }
  678. for _, file := range files {
  679. if file.Name()[0] == '.' {
  680. continue
  681. }
  682. if file.IsDir() {
  683. ctx.runTC39Tests(path.Join(name, file.Name()))
  684. } else {
  685. fileName := file.Name()
  686. if strings.HasSuffix(fileName, ".js") && !strings.HasSuffix(fileName, "_FIXTURE.js") {
  687. name := path.Join(name, fileName)
  688. ctx.runTest(name, func(t *testing.T) {
  689. ctx.runTC39File(name, t)
  690. })
  691. }
  692. }
  693. }
  694. }
  695. func TestTC39(t *testing.T) {
  696. if testing.Short() {
  697. t.Skip()
  698. }
  699. if _, err := os.Stat(tc39BASE); err != nil {
  700. t.Skipf("If you want to run tc39 tests, download them from https://github.com/tc39/test262 and put into %s. See .tc39_test262_checkout.sh for the latest working commit id. (%v)", tc39BASE, err)
  701. }
  702. ctx := &tc39TestCtx{
  703. base: tc39BASE,
  704. }
  705. ctx.init()
  706. //ctx.enableBench = true
  707. t.Run("tc39", func(t *testing.T) {
  708. ctx.t = t
  709. //ctx.runTC39File("test/language/types/number/8.5.1.js", t)
  710. ctx.runTC39Tests("test/language")
  711. ctx.runTC39Tests("test/built-ins")
  712. ctx.runTC39Tests("test/annexB/built-ins/String/prototype/substr")
  713. ctx.runTC39Tests("test/annexB/built-ins/String/prototype/trimLeft")
  714. ctx.runTC39Tests("test/annexB/built-ins/String/prototype/trimRight")
  715. ctx.runTC39Tests("test/annexB/built-ins/escape")
  716. ctx.runTC39Tests("test/annexB/built-ins/unescape")
  717. ctx.runTC39Tests("test/annexB/built-ins/RegExp")
  718. ctx.flush()
  719. })
  720. if ctx.enableBench {
  721. sort.Slice(ctx.benchmark, func(i, j int) bool {
  722. return ctx.benchmark[i].duration > ctx.benchmark[j].duration
  723. })
  724. bench := ctx.benchmark
  725. if len(bench) > 50 {
  726. bench = bench[:50]
  727. }
  728. for _, item := range bench {
  729. fmt.Printf("%s\t%d\n", item.name, item.duration/time.Millisecond)
  730. }
  731. }
  732. }