profile
viewpoint
Mathias Bynens mathiasbynens @Google Germany https://mathiasbynens.be/ Web standards fanatic. JavaScript, HTML, CSS, HTTP, performance, security, Bash, Unicode, macOS.

domchristie/turndown 4429

🛏 An HTML to Markdown converter written in JavaScript

kangax/html-minifier 4120

Javascript-based HTML compressor/minifier (with Node.js support)

GoogleChromeLabs/jsvu 971

JavaScript (engine) Version Updater

GoogleChromeLabs/jsbi 550

JSBI is a pure-JavaScript implementation of the official ECMAScript BigInt proposal.

bramus/mixed-content-scan 503

Scan your HTTPS-enabled website for Mixed Content

googlesamples/web-fundamentals 281

Google Web Fundamentals

konklone/shaaaaaaaaaaaaa 208

Check if a website has weak SHA-1 TLS certificates.

gf3/WAT 102

LOLWAT?

GoogleChromeLabs/json-parse-benchmark 77

Benchmark comparing JSON.parse vs. equivalent JavaScript literals across JavaScript engines.

joliss/js-string-escape 61

Escape strings for use as JavaScript string literals

issue commentbestiejs/punycode.js

SyntaxError: Invalid character: '\0'

\0 is a valid escape sequence for U+0000 within string literals, template literals, and regular expression literals. Which JS engine are you seeing this issue in?

mikoSTAR

comment created time in 5 minutes

pull request commentv8/v8.dev

Add Intl.DisplayNames feature explainer

I'd suggest spacing things out a bit. Publishing #334 on Wednesday sounds great!

syg

comment created time in an hour

issue commentGoogleChromeLabs/jsbi

asIntN and asUintN should both throw RangeError when `n` is less than zero

I agree we should be consistent and either add validation everywhere (which would be bad for performance) or continue to assume that the user knows what they're doing. Perhaps the way forward here is to document this philosophy a little bit more clearly, and provide a list of examples such as the one in OP's post. WDYT?

AnyhowStep

comment created time in 8 hours

Pull request review commenttc39/test262

Test \b escape inside CharacterClass in Unicode RegExp

+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.+// This code is governed by the BSD license found in the LICENSE file.++/*---+esid: prod-ClassEscapes+description: >+  \b escape inside CharacterClass is valid in Unicode patterns (unlike \B).+info: |+  ClassEscape[U] ::+    b++  Static Semantics: CharacterValue++  ClassEscape :: b++  1. Return the code point value of U+0008 (BACKSPACE).+---*/++assert(/[\b]/u.test('\b'));

You could imagine a broken engine that treats \b as b both in string literals and in u RegExps. Such an engine would still pass this test. How about:

const backspace = '\b';
assert(backspace.charCodeAt() === 0x08);
assert(/[\b]/u.test(backspace));
shvaikalesh

comment created time in 2 days

issue openedGoogleChrome/devsummit

Leverage `timezonechange` event

This is a tracking bug for leveraging the timezonechange event for the schedule, as prototyped in #335 and #336, once timezonechange gains stable browser support.

References:

created time in 3 days

push eventgoogle/WebFundamentals

Mathias Bynens

commit sha 9579380a724b6038ce4ef446d15528a5866e250e

Fix typo

view details

push time in 3 days

pull request commenttc39/test262

Add coverage for astral ID_Start and ID_Continue in identifiers

The changes in test/language/identifiers/* LGTM. For the changes in test/built-ins/RegExp/named-groups/*, my earlier comment still stands. Adding tests for .groups['STRING'] is great, but it should not come at the cost of deleting the tests for .groups.IDENTIFIER.

shvaikalesh

comment created time in 3 days

Pull request review commentv8/v8.dev

Add Intl.DisplayNames feature explainer

+---+title: '`Intl.DisplayNames`'+author: 'Shu-yu Guo ([@_shu](https://twitter.com/_shu)) and Frank Tang'+avatars:+  - 'shu-yu-guo'+  - 'frank-tang'+date: 2020-02-13+tags:+  - Intl+  - Node.js 14+description: 'The Intl.DisplayNames API enables localized names of languages, regions, scripts, and currencies.'+---+Web applications that reach a global audience need to show the display names of languages, regions, scripts, and currencies in many different languages. The translations of those names require data, which is available in the [Unicode CLDR](http://cldr.unicode.org/translation/). Packaging the data as part of the application incurs a cost on developer time. Users are likely to prefer consistent translations of language and region names, and keeping that data up to date with the world's geopolitical happenings requires constant maintenance.++Luckily, most JavaScript runtimes already ship and keep up-to-date that very same translation data. The new `Intl.DisplayNames` API gives JavaScript developers direct access to those translations, allowing applications to more easily display localized names.++## Usage examples++The following example shows how to create an `Intl.DisplayNames` object to get region names in English using [ISO-3166 2-letter country codes](https://www.iso.org/iso-3166-country-codes.html).++```js+const regionNames = new Intl.DisplayNames(['en'], { type: 'region' });+regionNames.of('US');+// → 'United States'+regionNames.of('BA');+// → 'Bosnia & Herzegovina'+regionNames.of('MM');+// → 'Myanmar (Burma)'+```++The following example gets language names in Traditional Chinese using [Unicode's language identifier grammar](http://unicode.org/reports/tr35/#Unicode_language_identifier).++```js+const languageNames = new Intl.DisplayNames(['zh-Hant'], { type: 'language' });+languageNames.of('fr');+// → '法文'+languageNames.of('zh');+// → '中文'+languageNames.of('de');+// → '德文'+```++The following example gets currency names in Simplified Chinese using [ISO-4217 3-letter currency codes](https://www.iso.org/iso-4217-currency-codes.html). In languages that have distinct singular and plural forms, the currency names are singular. For plural forms, [`Intl.NumberFormat`](https://v8.dev/features/intl-numberformat) may be used.++```js+const currencyNames = new Intl.DisplayNames(['zh-Hans'], {type: 'currency'});+currencyNames.of('USD');+// → '美元'+currencyNames.of('EUR');+// → '欧元'+currencyNames.of('JPY');+// → '日元'+currencyNames.of('CNY');+// → '人民币'+```++The following example shows the final supported type, scripts, in English, using [ISO-15924 4-letter script codes](http://unicode.org/iso15924/iso15924-codes.html).++```js+const scriptNames = new Intl.DisplayNames(['en'], { type: 'script' });+scriptNames.of('Latn');+// → 'Latin'+scriptNames.of('Arab');+// → 'Arabic'+scriptNames.of('Kana');+// → 'Katakana'+```++For more advanced usage, the second `options` parameter also supports the `style` property. The `style` property corresponds to the width of the display name and may be either `"long"`, `"short"`, or `"narrow"`. The values for different styles do not always differ. The default is `"long"`.++```js+const longLanguageNames = new Intl.DisplayNames(['en'], { type: 'language' });+longLanguageNames.of('en-US');+// → 'American English'+const shortLanguageNames = new Intl.DisplayNames(['en'], { type: 'language', style: 'short' });+shortLanguageNames.of('en-US');+// → 'US English'+const narrowLanguageNames = new Intl.DisplayNames(['en'], { type: 'language', style: 'narrow' });+narrowLanguageNames.of('en-US');+// → 'US English'+```++## Full API++The full API for `Intl.DisplayNames` is as follows.++```js+Intl.DisplayNames([ locales [ , options ]])+Intl.DisplayNames.prototype.of( code )+```++The constructor is consistent with other `Intl` APIs. Its first argument is a [list of locales](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation), and its second parameter is an `options` parameter that takes `localeMatcher`, `type`, and `style` properties.++The `"localeMatcher"` property is treated the same as in [other `Intl` APIs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation). The `type` property may be `"region"`, `"language"`, `"currency"`, or `"script"`. The `style` property may be `"long"`, `"short"`, or `"narrow"`, with `"long"` being the default.++`Intl.DisplayNames.prototype.of( code )` expects the following formats depending on the `type` of how the instance is constructed.++- When `type` is `"region"`, `code` must be either an [ISO-3166 2-letter country code](https://www.iso.org/iso-3166-country-codes.html) or a [UN M49 3-digit region code](https://unstats.un.org/unsd/methodology/m49/).+- When `type` is `"language"`, `code` must be conform to [Unicode's language identifier grammar](https://unicode.org/reports/tr35/#Unicode_language_identifier).+- When `type` is `"currency"`, `code` must be a [ISO-4217 3-letter currency code](https://www.iso.org/iso-4217-currency-codes.html).+- When `type` is `"script"`, `code` must be a [ISO-15924 4-letter script code](https://unicode.org/iso15924/iso15924-codes.html).++## Conclusion++Like other `Intl` APIs, as `Intl.DisplayNames` become more widely available, libraries and applications will opt to drop packaging and shipping their own translation data in favor of using the native functionality.++## `Intl.DisplayNames` support { #support }++<feature-support chrome="81 /blog/v8-release-81#intl.displaynames"

Note that the V8 v8.1 release blog post hasn't happened yet. @natorion What's the status on that?

syg

comment created time in 4 days

push eventpuppeteer/puppeteer

Maja Frydrychowicz

commit sha 0b1a9ceee2f05f534f0d50079ece172d627a93c7

chore: Replace Juggler with Firefox Nightly in CI (#5395) Fixes #5150.

view details

push time in 4 days

PR merged puppeteer/puppeteer

chore: Replace Juggler with Firefox Nightly in CI cla: yes

Fixes #5150

+259 -286

7 comments

33 changed files

mjzffr

pr closed time in 4 days

issue closedpuppeteer/puppeteer

[CI] Run unit tests against Firefox Nightly

(This depends on https://github.com/GoogleChrome/puppeteer/pull/5137)

Currently unit tests are run against the "Juggler" Firefox build together with the experimental puppeteer-firefox package. Let's also run the same unit tests against Firefox Nightly to test its remote agent, which is in active development.

closed time in 4 days

mjzffr

Pull request review commentv8/v8.dev

Add `:::ecmascript-algorithm` wrapper with styles

 If an algorithm throws an exception, it means returning a Completion Record with  [`ReturnIfAbrupt(argument)`](https://tc39.es/ecma262/#sec-returnifabrupt) means taking the following steps: +:::ecmascript-algorithm+<!-- markdownlint-disable blanks-around-lists -->

Not that I know of. I don't think we want it for all of them though.

mathiasbynens

comment created time in 5 days

issue commentmathiasbynens/regexpu-core

rewritePattern('}', 'u') should throw, but it doesn't

Thanks for the upstream fix!

pygy

comment created time in 5 days

Pull request review commentv8/v8.dev

Add a blog post: Understanding the ECMAScript spec, part 2

+---+title: 'Understanding the ECMAScript spec, part 2'+author: '[Marja Hölttä](https://twitter.com/marjakh), speculative specification spectator'+avatars:+  - marja-holtta+date: 2020-02-11 13:33:37+tags:+  - ECMAScript+description: 'Tutorial on reading the ECMAScript specification'+tweet: ''+---++... where we practice our awesome spec reading skills some more.++## Previous episodes++If you haven't had a look at the previous episodes, now it's a good time to do so!++In [part 1](https://v8.dev/blog/understanding-ecmascript-part-1) we read through a simple method, `Object.prorotype.hasOwnProperty`, and other **abstract operations** it invokes. We familiarized ourselves with the shorhands `?` and `!`related to error handling. We encountered **language types**, **specification types**, **internal slots** and **internal methods**.++## Ready for part 2?++A fun way to get to know the spec is to start with a JavaScript feature we know is there, and find out how it's specified.++We know that properties are looked up in the prototype chain: if an object doesn't have the property we're trying to read, we walk up the prototype chain until we find it (or find an object which no longer has a prototype).++For example:++```javascript+const o1 = {'foo' : 2511};+const o2 = {};+console.log(o2.foo); // undefined+Object.setPrototypeOf(o2, o1);+console.log(o2.foo); // 2511+```++## Where's the prototype walk defined?++Let's try to find out where this behavior is defined. A good place to start is a list of [Object Internal Methods](https://tc39.es/ecma262/#sec-object-internal-methods-and-internal-slots).++There's both `[[GetOwnProperty]]` and `[[Get]]` &mdash; now we're interested in the version that isn't restricted to _own_ properties, so we'll go with `[[Get]]`.++Unfortunately, the [Property Descriptor specification type](https://tc39.es/ecma262/#sec-property-descriptor-specification-type) also has a field called `[[Get]]`, so while browsing the spec for `[[Get]]`, we need to carefully distinguish between the two independent usages.++The internal method `[[Get]]` delegates to `OrdinaryGet`:++> [`[[Get]] ( P, Receiver )`](https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-get-p-receiver)+>+> When the `[[Get]]` internal method of `O` is called with property key `P` and ECMAScript language value `Receiver`, the following steps are taken:+>+> 1. Return `? OrdinaryGet(O, P, Receiver)`.++We'll see shortly that `Receiver` is the value which is used as the **this value** when calling a getter function of an accessor property.++`OrdinaryGet` is defined like this:++> [`OrdinaryGet ( O, P, Receiver )`](https://tc39.es/ecma262/#sec-ordinaryget)+>+> When the abstract operation `OrdinaryGet` is called with Object `O`, property key `P`, and ECMAScript language value `Receiver`, the following steps are taken:+>+> 1. Assert: `IsPropertyKey(P)` is `true`.+> 2. Let `desc` be `? O.[[GetOwnProperty]](P)`.+> 3. If `desc` is `undefined`, then+> a. Let `parent` be `? O.[[GetPrototypeOf]]()`.+> b. If `parent` is `null`, return `undefined`.+> c. Return `? parent.[[Get]](P, Receiver)`.+> 4. If `IsDataDescriptor(desc)` is `true`, return `desc.[[Value]]`.+> 5. Assert: `IsAccessorDescriptor(desc)` is `true`.+> 6. Let `getter` be `desc.[[Get]]`.+> 7. If `getter` is `undefined`, return `undefined`.+> 8. Return `? Call(getter, Receiver)`.++The prototype chain walk is inside step 3: if we don't find the property as an own property, we recurse into the prototype's `[[Get]]` method.++## What's `Receiver` and where is it coming from?++The `Receiver` parameter is only used in the case of accessor properties in step 8. It's passed as the **this value** when calling the getter function of an accessor property.++`OrdinaryGet` passes the original `Receiver` throughout the recursion, unchanged (step 3 c). Let's find out where the `Receiver` is originally coming from!++Searching for places where `[[Get]]` is called we find an abstract operation `GetValue` which operates on References. Reference is a specification type, consisting of a base value, the reference name and a strict reference flag. In the case of `o2.foo`, the base value is the Object `o2`, the reference name is the String `"foo"` and the strict reference flag is `false`, since the example code is sloppy.++### Side track: References++Side track: A Reference is not a Record, even though it sounds like it could be. It contains three components, which could equally well be expressed as three fixed named values. Here the spec takes a different approach, and defines References as a higher-level data type. This is because of historical reasons.++### Back to `GetValue`++Let's look at how `GetValue` is defined:++> [`GetValue ( V )`](https://tc39.es/ecma262/#sec-getvalue)+>+> 1. `ReturnIfAbrupt(V)`.+> 2. If `Type(V)` is not `Reference`, return `V`.+> 3. Let `base` be `GetBase(V)`.+> 4. If `IsUnresolvableReference(V)` is `true`, throw a `ReferenceError` exception.+> 5. If `IsPropertyReference(V)` is `true`, then+> a. If `HasPrimitiveBase(V)` is `true`, then+> i. Assert: In this case, `base` will never be `undefined` or `null`.+> ii. Set `base` to `! ToObject(base)`.+> b. Return `? base.[[Get]](GetReferencedName(V), GetThisValue(V))`.+> 6. Else,+> a. Assert: `base` is an Environment Record.+> b. Return `? base.GetBindingValue(GetReferencedName(V), IsStrictReference(V))`++The reference in our example is `o2.foo` which is a property reference. So we take branch 5. We don't take the branch in 5 a, since the base (`o2`) is not a primitive value (a Boolean, String, Symbol, BigInt or Number).++Then we call `[[Get]]` in step 5 b. The `Receiver` we pass is `GetThisValue(V)`. In this case, it's just the basevalue of the Reference:++> [`GetThisValue( V )`](https://tc39.es/ecma262/#sec-getthisvalue)+>+> 1. Assert: `IsPropertyReference(V)` is `true`.+> 2. If `IsSuperReference(V)` is `true`, then+> a. Return the value of the `thisValue` component of the reference `V`.+> 3. Return `GetBase(V)`.++For `o2.foo`, we don't take the branch in step 2, since it's not a super reference (such as `super.foo`), but we take step 3 and return the base value of the reference which is `o2`.++Piecing everything together, we find out that we set the `Receiver` to be the base of the original reference, and then we keep it unchanged during the prototype chain walk. Finally, if the property we find is an accessor property, we use the `Receiver` as the **this value** when calling it.++In particular, the **this value** inside a getter refers to the original object where we tried to get the property from, not the one where we found the property during the prototype chain walk.++Let's try it out!++```javascript+const o1 = { x: 10, get foo() { return this.x; } };+let o2 = {};+Object.setPrototypeOf(o2, o1);+o2.x = 50;+o2.foo; // will return 50+```++In this example, we have an accessor property called `foo` and we define a getter for it. The getter returns `this.x`.++Then we access `o2.foo` - what does the getter return?++We found out that when we call the getter, the **this value** is the object where we originally tried to get the property from, not the object where we found it. In this case the **this value** is `o2`, not `o1`. We can verify that by checking whether the getter returns `o2.x` or `o1.x`, and indeed, it returns `o2.x`.++(Note that setting `o2.x = 50` adds a property called `x` in `o2` and doesn't overwrite the property `x` in `o1`.)++It works! We were able to predict the behavior of this code snippet based on what we read in the spec.++## Accessing properties - why does it invoke `[[Get]]`?++But where does the spec say that the Object internal method `[[Get]]` will get invoked when accessing a property like `o2.foo`? Surely that has to be defined somewhere. Don't take my word for it!++We found out that the Object internal method `[[Get]]` is called from the abstract operation `GetValue` which operates on References. But where is `GetValue` called from?++### Runtime Semantics++The grammar rules of the spec define the syntax of the language. [Runtime semantics](https://tc39.es/ecma262/#sec-runtime-semantics) define what the syntactic constructs "mean" (how to evaluate them at runtime).++We'll take a deeper look into the grammar rules in a later episode, let's keep it simple for now! In particular, we can ignore the subscripts (`Yield`, `Await` and so on) in the productions for this episode.++(If you're not familiar with [context-free grammars](https://en.wikipedia.org/wiki/Context-free_grammar), it's a good idea to have a look now!)++The following productions describe how a `MemberExpression` looks like:++> [`MemberExpression :`](https://tc39.es/ecma262/#prod-MemberExpression)+>+> `PrimaryExpression`+> `MemberExpression [ Expression ]`+> `MemberExpression . IdentifierName`+> `MemberExpression TemplateLiteral`+> `SuperProperty`+> `MetaProperty`+> `new MemberExpression Arguments`++Here we have 8 productions for `MemberExpression`. A `MemberExpression` can be just a `PrimaryExpression`. Alternatively, a `MemberExpression` can be constructed from another `MemberExpression` and `Expression` by piecing them together: `MemberExpression [ Expression ]`, for example `o2['foo']`. Or it can be `MemberExpression . IdentifierName`, for example `o2.foo` &mdash; this is the production relevant for our example.++Runtime semantics for the production `MemberExpression : MemberExpression . IdentifierName` define the set of steps to take when evaluating it:++> [Runtime Semantics: Evaluation for `MemberExpression : MemberExpression . IdentifierName`](https://tc39.es/ecma262/#sec-property-accessors-runtime-semantics-evaluation)+>+> 1. Let `baseReference` be the result of evaluating `MemberExpression`.+> 2. Let `baseValue` be `? GetValue(baseReference)`.+> 3. If the code matched by this `MemberExpression` is strict mode code, let `strict` be `true`; else let `strict` be `false`.+> 4. Return `? EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)`.++The algorithm delegates to the abstract operation `EvaluatePropertyAccessWithIdentifierKey`, so we need to read it too:++> [`EvaluatePropertyAccessWithIdentifierKey( baseValue, identifierName, strict )`](https://tc39.es/ecma262/#sec-evaluate-property-access-with-identifier-key)+>+> The abstract operation `EvaluatePropertyAccessWithIdentifierKey` takes as arguments a value `baseValue`, a Parse Node `identifierName`, and a Boolean argument `strict`. It performs the following steps:+>+> 1. Assert: `identifierName` is an `IdentifierName`+> 2. Let `bv` be `? RequireObjectCoercible(baseValue)`.+> 3. Let `propertyNameString` be `StringValue` of `identifierName`.+> 4. Return a value of type Reference whose base value component is `bv`, whose referenced name component is `propertyNameString`, and whose strict reference flag is `strict`.++That is: `EvaluatePropertyAccessWithIdentifierKey` constructs a Reference which uses the provided `baseValue` as the base, the string value of `identifierName` as the property name, and `strict` as the strict mode flag.++Eventually this Reference gets passed to `GetValue`. This is defined in several places in the spec, depending on how the Reference ends up being used.++### Property access as a parameter++For example, we can use the property access as a parameter.++```javascript+console.log(o2.foo);+```++In this case, the behavior is defined in the runtime semantics of `ArgumentList` production which calls `GetValue` on the argument:++> [Runtime Semantics: ArgumentListEvaluation](https://tc39.es/ecma262/#sec-argument-lists-runtime-semantics-argumentlistevaluation)+>+> `ArgumentList : AssignmentExpression`+>+> 1. Let `ref` be the result of evaluating `AssignmentExpression`.+> 2. Let `arg` be `? GetValue(ref)`.+> 3. Return a List whose sole item is `arg`.++`o2.foo` doesn't look like an `AssignmentExpression` but it is one, so this production is applicable. (Why `o2.foo` is an `AssignmentExpression` will be explained later in this post.)++So, the `AssignmentExpression` is `o2.foo`. `ref`, the result of evaluating `o2.foo`, is the above mentioned Reference. Now we call `GetValue` on it.++### Property access as the right hand side of an assignment++We can also use the property access as a right hand side of an assignment:++```javascript+x = o2.foo;+```++In this case, the behavior is defined in the runtime semantics for the `AssignmentExpression : LeftHandSide = AssignmentExpression` production. Also this ends up calling `GetValue` on the result of evaluating the right hand side `AssignmentExpression`.++> [Runtime Semantics: Evaluation for `AssignmentExpression : LeftHandSideExpression = AssignmentExpression`](https://tc39.es/ecma262/#sec-assignment-operators-runtime-semantics-evaluation)+>+> 1. If `LeftHandSideExpression` is neither an `ObjectLiteral` nor an `ArrayLiteral`, then+>     1. Let `lref` be the result of evaluating `LeftHandSideExpression`.+>     1. `ReturnIfAbrupt(lref)`.+>     1. If `IsAnonymousFunctionDefinition(AssignmentExpression)` and `IsIdentifierRef` of `LeftHandSideExpression` are both `true`, then+>         1. Let `rval` be `NamedEvaluation` of `AssignmentExpression` with argument `GetReferencedName(lref)`.+>     1. Else,+>         1. Let `rref` be the result of evaluating `AssignmentExpression`.+>         1. Let `rval` be `? GetValue(rref)`.+>     1. Perform `? PutValue(lref, rval)`.+>     1. Return `rval`.+> 1. Let `assignmentPattern` be the `AssignmentPattern` that is covered by `LeftHandSideExpression`.+> 1. Let `rref` be the result of evaluating `AssignmentExpression`.+> 1. Let `rval` be `? GetValue(rref)`.+> 1. Perform `? DestructuringAssignmentEvaluation` of `assignmentPattern` using `rval` as the argument.+> 1. Return `rval`.++Now the `LeftHandSideExpression` (`x`) is not an object literal or an array literal, so we take the if branch in step 1. In step 1 a, we evaluate the left-hand side (`x`) and store the result into `lref`. `o2.foo` is not a function definition, so we don't take the if branch in 1 c, but the else branch in 1 d. There we evaluate `o2.foo` and call `GetValue` on it.

PR: https://github.com/v8/v8.dev/pull/332

marjakh

comment created time in 5 days

Pull request review commentv8/v8.dev

Add `:::ecmascript-algorithm` wrapper with styles

 If an algorithm throws an exception, it means returning a Completion Record with  [`ReturnIfAbrupt(argument)`](https://tc39.es/ecma262/#sec-returnifabrupt) means taking the following steps: +:::ecmascript-algorithm+<!-- markdownlint-disable blanks-around-lists -->

We only need these when :::ecmascript-algorithm contains nothing but a list.

mathiasbynens

comment created time in 5 days

PR opened v8/v8.dev

Reviewers
Add `:::ecmascript-algorithm` wrapper with styles

Ref. https://github.com/v8/v8.dev/pull/331#discussion_r380717839.

cc @marjakh

+55 -18

0 comment

3 changed files

pr created time in 5 days

create barnchv8/v8.dev

branch : ecmascript-algorithm

created branch time in 5 days

issue commentv8/v8.dev

Set up travis-size-report

https://github.com/marketplace/actions/compressed-size-action

mathiasbynens

comment created time in 5 days

startedpreactjs/compressed-size-action

started time in 5 days

Pull request review commentv8/v8.dev

Add a blog post: Understanding the ECMAScript spec, part 2

+---+title: 'Understanding the ECMAScript spec, part 2'+author: '[Marja Hölttä](https://twitter.com/marjakh), speculative specification spectator'+avatars:+  - marja-holtta+date: 2020-02-11 13:33:37+tags:+  - ECMAScript+description: 'Tutorial on reading the ECMAScript specification'+tweet: ''+---++... where we practice our awesome spec reading skills some more.++## Previous episodes++If you haven't had a look at the previous episodes, now it's a good time to do so!++In [part 1](https://v8.dev/blog/understanding-ecmascript-part-1) we read through a simple method, `Object.prorotype.hasOwnProperty`, and other **abstract operations** it invokes. We familiarized ourselves with the shorhands `?` and `!`related to error handling. We encountered **language types**, **specification types**, **internal slots** and **internal methods**.++## Ready for part 2?++A fun way to get to know the spec is to start with a JavaScript feature we know is there, and find out how it's specified.++We know that properties are looked up in the prototype chain: if an object doesn't have the property we're trying to read, we walk up the prototype chain until we find it (or find an object which no longer has a prototype).++For example:++```javascript+const o1 = {'foo' : 2511};+const o2 = {};+console.log(o2.foo); // undefined+Object.setPrototypeOf(o2, o1);+console.log(o2.foo); // 2511+```++## Where's the prototype walk defined?++Let's try to find out where this behavior is defined. A good place to start is a list of [Object Internal Methods](https://tc39.es/ecma262/#sec-object-internal-methods-and-internal-slots).++There's both `[[GetOwnProperty]]` and `[[Get]]` &mdash; now we're interested in the version that isn't restricted to _own_ properties, so we'll go with `[[Get]]`.++Unfortunately, the [Property Descriptor specification type](https://tc39.es/ecma262/#sec-property-descriptor-specification-type) also has a field called `[[Get]]`, so while browsing the spec for `[[Get]]`, we need to carefully distinguish between the two independent usages.++The internal method `[[Get]]` delegates to `OrdinaryGet`:++> [`[[Get]] ( P, Receiver )`](https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-get-p-receiver)+>+> When the `[[Get]]` internal method of `O` is called with property key `P` and ECMAScript language value `Receiver`, the following steps are taken:+>+> 1. Return `? OrdinaryGet(O, P, Receiver)`.++We'll see shortly that `Receiver` is the value which is used as the **this value** when calling a getter function of an accessor property.++`OrdinaryGet` is defined like this:++> [`OrdinaryGet ( O, P, Receiver )`](https://tc39.es/ecma262/#sec-ordinaryget)+>+> When the abstract operation `OrdinaryGet` is called with Object `O`, property key `P`, and ECMAScript language value `Receiver`, the following steps are taken:+>+> 1. Assert: `IsPropertyKey(P)` is `true`.+> 2. Let `desc` be `? O.[[GetOwnProperty]](P)`.+> 3. If `desc` is `undefined`, then+> a. Let `parent` be `? O.[[GetPrototypeOf]]()`.+> b. If `parent` is `null`, return `undefined`.+> c. Return `? parent.[[Get]](P, Receiver)`.+> 4. If `IsDataDescriptor(desc)` is `true`, return `desc.[[Value]]`.+> 5. Assert: `IsAccessorDescriptor(desc)` is `true`.+> 6. Let `getter` be `desc.[[Get]]`.+> 7. If `getter` is `undefined`, return `undefined`.+> 8. Return `? Call(getter, Receiver)`.++The prototype chain walk is inside step 3: if we don't find the property as an own property, we recurse into the prototype's `[[Get]]` method.++## What's `Receiver` and where is it coming from?++The `Receiver` parameter is only used in the case of accessor properties in step 8. It's passed as the **this value** when calling the getter function of an accessor property.++`OrdinaryGet` passes the original `Receiver` throughout the recursion, unchanged (step 3 c). Let's find out where the `Receiver` is originally coming from!++Searching for places where `[[Get]]` is called we find an abstract operation `GetValue` which operates on References. Reference is a specification type, consisting of a base value, the reference name and a strict reference flag. In the case of `o2.foo`, the base value is the Object `o2`, the reference name is the String `"foo"` and the strict reference flag is `false`, since the example code is sloppy.++### Side track: References++Side track: A Reference is not a Record, even though it sounds like it could be. It contains three components, which could equally well be expressed as three fixed named values. Here the spec takes a different approach, and defines References as a higher-level data type. This is because of historical reasons.++### Back to `GetValue`++Let's look at how `GetValue` is defined:++> [`GetValue ( V )`](https://tc39.es/ecma262/#sec-getvalue)+>+> 1. `ReturnIfAbrupt(V)`.+> 2. If `Type(V)` is not `Reference`, return `V`.+> 3. Let `base` be `GetBase(V)`.+> 4. If `IsUnresolvableReference(V)` is `true`, throw a `ReferenceError` exception.+> 5. If `IsPropertyReference(V)` is `true`, then+> a. If `HasPrimitiveBase(V)` is `true`, then+> i. Assert: In this case, `base` will never be `undefined` or `null`.+> ii. Set `base` to `! ToObject(base)`.+> b. Return `? base.[[Get]](GetReferencedName(V), GetThisValue(V))`.+> 6. Else,+> a. Assert: `base` is an Environment Record.+> b. Return `? base.GetBindingValue(GetReferencedName(V), IsStrictReference(V))`++The reference in our example is `o2.foo` which is a property reference. So we take branch 5. We don't take the branch in 5 a, since the base (`o2`) is not a primitive value (a Boolean, String, Symbol, BigInt or Number).++Then we call `[[Get]]` in step 5 b. The `Receiver` we pass is `GetThisValue(V)`. In this case, it's just the basevalue of the Reference:++> [`GetThisValue( V )`](https://tc39.es/ecma262/#sec-getthisvalue)+>+> 1. Assert: `IsPropertyReference(V)` is `true`.+> 2. If `IsSuperReference(V)` is `true`, then+> a. Return the value of the `thisValue` component of the reference `V`.+> 3. Return `GetBase(V)`.++For `o2.foo`, we don't take the branch in step 2, since it's not a super reference (such as `super.foo`), but we take step 3 and return the base value of the reference which is `o2`.++Piecing everything together, we find out that we set the `Receiver` to be the base of the original reference, and then we keep it unchanged during the prototype chain walk. Finally, if the property we find is an accessor property, we use the `Receiver` as the **this value** when calling it.++In particular, the **this value** inside a getter refers to the original object where we tried to get the property from, not the one where we found the property during the prototype chain walk.++Let's try it out!++```javascript+const o1 = { x: 10, get foo() { return this.x; } };+let o2 = {};+Object.setPrototypeOf(o2, o1);+o2.x = 50;+o2.foo; // will return 50+```++In this example, we have an accessor property called `foo` and we define a getter for it. The getter returns `this.x`.++Then we access `o2.foo` - what does the getter return?++We found out that when we call the getter, the **this value** is the object where we originally tried to get the property from, not the object where we found it. In this case the **this value** is `o2`, not `o1`. We can verify that by checking whether the getter returns `o2.x` or `o1.x`, and indeed, it returns `o2.x`.++(Note that setting `o2.x = 50` adds a property called `x` in `o2` and doesn't overwrite the property `x` in `o1`.)++It works! We were able to predict the behavior of this code snippet based on what we read in the spec.++## Accessing properties - why does it invoke `[[Get]]`?++But where does the spec say that the Object internal method `[[Get]]` will get invoked when accessing a property like `o2.foo`? Surely that has to be defined somewhere. Don't take my word for it!++We found out that the Object internal method `[[Get]]` is called from the abstract operation `GetValue` which operates on References. But where is `GetValue` called from?++### Runtime Semantics++The grammar rules of the spec define the syntax of the language. [Runtime semantics](https://tc39.es/ecma262/#sec-runtime-semantics) define what the syntactic constructs "mean" (how to evaluate them at runtime).++We'll take a deeper look into the grammar rules in a later episode, let's keep it simple for now! In particular, we can ignore the subscripts (`Yield`, `Await` and so on) in the productions for this episode.++(If you're not familiar with [context-free grammars](https://en.wikipedia.org/wiki/Context-free_grammar), it's a good idea to have a look now!)++The following productions describe how a `MemberExpression` looks like:++> [`MemberExpression :`](https://tc39.es/ecma262/#prod-MemberExpression)+>+> `PrimaryExpression`+> `MemberExpression [ Expression ]`+> `MemberExpression . IdentifierName`+> `MemberExpression TemplateLiteral`+> `SuperProperty`+> `MetaProperty`+> `new MemberExpression Arguments`++Here we have 8 productions for `MemberExpression`. A `MemberExpression` can be just a `PrimaryExpression`. Alternatively, a `MemberExpression` can be constructed from another `MemberExpression` and `Expression` by piecing them together: `MemberExpression [ Expression ]`, for example `o2['foo']`. Or it can be `MemberExpression . IdentifierName`, for example `o2.foo` &mdash; this is the production relevant for our example.++Runtime semantics for the production `MemberExpression : MemberExpression . IdentifierName` define the set of steps to take when evaluating it:++> [Runtime Semantics: Evaluation for `MemberExpression : MemberExpression . IdentifierName`](https://tc39.es/ecma262/#sec-property-accessors-runtime-semantics-evaluation)+>+> 1. Let `baseReference` be the result of evaluating `MemberExpression`.+> 2. Let `baseValue` be `? GetValue(baseReference)`.+> 3. If the code matched by this `MemberExpression` is strict mode code, let `strict` be `true`; else let `strict` be `false`.+> 4. Return `? EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)`.++The algorithm delegates to the abstract operation `EvaluatePropertyAccessWithIdentifierKey`, so we need to read it too:++> [`EvaluatePropertyAccessWithIdentifierKey( baseValue, identifierName, strict )`](https://tc39.es/ecma262/#sec-evaluate-property-access-with-identifier-key)+>+> The abstract operation `EvaluatePropertyAccessWithIdentifierKey` takes as arguments a value `baseValue`, a Parse Node `identifierName`, and a Boolean argument `strict`. It performs the following steps:+>+> 1. Assert: `identifierName` is an `IdentifierName`+> 2. Let `bv` be `? RequireObjectCoercible(baseValue)`.+> 3. Let `propertyNameString` be `StringValue` of `identifierName`.+> 4. Return a value of type Reference whose base value component is `bv`, whose referenced name component is `propertyNameString`, and whose strict reference flag is `strict`.++That is: `EvaluatePropertyAccessWithIdentifierKey` constructs a Reference which uses the provided `baseValue` as the base, the string value of `identifierName` as the property name, and `strict` as the strict mode flag.++Eventually this Reference gets passed to `GetValue`. This is defined in several places in the spec, depending on how the Reference ends up being used.++### Property access as a parameter++For example, we can use the property access as a parameter.++```javascript+console.log(o2.foo);+```++In this case, the behavior is defined in the runtime semantics of `ArgumentList` production which calls `GetValue` on the argument:++> [Runtime Semantics: ArgumentListEvaluation](https://tc39.es/ecma262/#sec-argument-lists-runtime-semantics-argumentlistevaluation)+>+> `ArgumentList : AssignmentExpression`+>+> 1. Let `ref` be the result of evaluating `AssignmentExpression`.+> 2. Let `arg` be `? GetValue(ref)`.+> 3. Return a List whose sole item is `arg`.++`o2.foo` doesn't look like an `AssignmentExpression` but it is one, so this production is applicable. (Why `o2.foo` is an `AssignmentExpression` will be explained later in this post.)++So, the `AssignmentExpression` is `o2.foo`. `ref`, the result of evaluating `o2.foo`, is the above mentioned Reference. Now we call `GetValue` on it.++### Property access as the right hand side of an assignment++We can also use the property access as a right hand side of an assignment:++```javascript+x = o2.foo;+```++In this case, the behavior is defined in the runtime semantics for the `AssignmentExpression : LeftHandSide = AssignmentExpression` production. Also this ends up calling `GetValue` on the result of evaluating the right hand side `AssignmentExpression`.++> [Runtime Semantics: Evaluation for `AssignmentExpression : LeftHandSideExpression = AssignmentExpression`](https://tc39.es/ecma262/#sec-assignment-operators-runtime-semantics-evaluation)+>+> 1. If `LeftHandSideExpression` is neither an `ObjectLiteral` nor an `ArrayLiteral`, then+>     1. Let `lref` be the result of evaluating `LeftHandSideExpression`.+>     1. `ReturnIfAbrupt(lref)`.+>     1. If `IsAnonymousFunctionDefinition(AssignmentExpression)` and `IsIdentifierRef` of `LeftHandSideExpression` are both `true`, then+>         1. Let `rval` be `NamedEvaluation` of `AssignmentExpression` with argument `GetReferencedName(lref)`.+>     1. Else,+>         1. Let `rref` be the result of evaluating `AssignmentExpression`.+>         1. Let `rval` be `? GetValue(rref)`.+>     1. Perform `? PutValue(lref, rval)`.+>     1. Return `rval`.+> 1. Let `assignmentPattern` be the `AssignmentPattern` that is covered by `LeftHandSideExpression`.+> 1. Let `rref` be the result of evaluating `AssignmentExpression`.+> 1. Let `rval` be `? GetValue(rref)`.+> 1. Perform `? DestructuringAssignmentEvaluation` of `assignmentPattern` using `rval` as the argument.+> 1. Return `rval`.++Now the `LeftHandSideExpression` (`x`) is not an object literal or an array literal, so we take the if branch in step 1. In step 1 a, we evaluate the left-hand side (`x`) and store the result into `lref`. `o2.foo` is not a function definition, so we don't take the if branch in 1 c, but the else branch in 1 d. There we evaluate `o2.foo` and call `GetValue` on it.

I was thinking an explicit wrapper a la :::ecmascript-algorithm (like :::table-wrapper) would be the best solution. We could then scope the styles to that wrapper, and we'd still be free to change the global styles. WDYT?

marjakh

comment created time in 6 days

Pull request review commentv8/v8.dev

Add Intl.DisplayNames feature explainer

+---+title: '`Intl.DisplayNames`'+author: 'Shu-yu Guo ([@_shu](https://twitter.com/_shu)) and Frank Tang'+avatars:+  - 'shu-yu-guo'+  - 'frank-tang'+date: 2020-02-13+tags:+  - Intl+  - Node.js 14

This is not a bug, in fact we have special logic just to achieve this: https://github.com/v8/v8.dev/blob/b93cbfc168b4b19ecebf5a8c93ada7ec8cf3bdd2/src/_includes/features.njk#L7 We don't want #io and Node.js tags to show up on the overview, but we do want to be able to link to them.

syg

comment created time in 6 days

Pull request review commentv8/v8.dev

Add Intl.DisplayNames feature explainer

+---+title: '`Intl.DisplayNames`'+author: 'Shu-yu Guo ([@_shu](https://twitter.com/_shu)) and Frank Tang'+avatars:+  - 'shu-yu-guo'+  - 'frank-tang'+date: 2020-02-13+tags:+  - Intl+  - Node.js 14

It's a valid tag (search for Node.js 12, for example). But generally we only add these tags for Node.js versions that have been released already.

syg

comment created time in 6 days

push eventv8/v8.dev

Mathias Bynens

commit sha b93cbfc168b4b19ecebf5a8c93ada7ec8cf3bdd2

Fix nit: use sentence case

view details

push time in 6 days

push eventmathiasbynens/css-dbg-stories

Mathias Bynens

commit sha c9199250decd0c73cdd5b39bc96616e521d032fa

Add CSS + SVG filter demo

view details

push time in 7 days

push eventmathiasbynens/css-dbg-stories

Mathias Bynens

commit sha 287c5ee3ce75598c7754c573d935c3629647211b

Add CSS + SVG filter demo

view details

push time in 7 days

PR opened WICG/compression

Fix compressArrayBuffer code example

Ref. #26.

+30 -21

0 comment

3 changed files

pr created time in 7 days

push eventmathiasbynens/compression

Mathias Bynens

commit sha 44d0ec1e24befaec701d433815435d960c97ca17

Fix compressArrayBuffer code example Ref. #26.

view details

push time in 7 days

create barnchmathiasbynens/compression

branch : fix

created branch time in 7 days

fork mathiasbynens/compression

Standard text for CompressionStream and DecompressionStream API

fork in 7 days

push eventtibiamaps/tibia-map-data

mathiasbynens

commit sha f18889390fa734c67069269128d28746212f9997

Update generated map data @ ea04668ed41d5e266474e956b04a195a3f9bf262

view details

push time in 8 days

push eventtibiamaps/tibia-map-data

mathiasbynens

commit sha ccaf3e633c8a797a1387ba3e025232076a4bd5c7

Update generated map data @ 547acf46aa478d21bdb106808a61d023039af1fd

view details

push time in 8 days

push eventtibiamaps/tibia-map-data

Mathias Bynens

commit sha ea04668ed41d5e266474e956b04a195a3f9bf262

Import marker changes from client

view details

push time in 8 days

push eventtibiamaps/tibia-map-data

Mathias Bynens

commit sha 547acf46aa478d21bdb106808a61d023039af1fd

Import marker changes from client

view details

push time in 8 days

push eventtibiamaps/tibia-map-data

mathiasbynens

commit sha f5df3aa811d3de023988dc1add573e0586676118

Update generated map data @ 61dd1b70f0bcba4ac6a8c1c486ec21dbb8f992eb

view details

push time in 10 days

push eventtibiamaps/tibia-map-data

Mathias Bynens

commit sha 61dd1b70f0bcba4ac6a8c1c486ec21dbb8f992eb

Import marker changes from client

view details

push time in 10 days

delete branch google/WebFundamentals

delete branch : timezone-emulation-79

delete time in 10 days

push eventgoogle/WebFundamentals

Mathias Bynens

commit sha 6f045165fcb9e11b6a8faab71b1322d07bc29f6f

Update devtools.md

view details

push time in 11 days

PR opened google/WebFundamentals

Reviewers
Mention timezone emulation

Ideally this would get a screenshot and https://developers.google.com/web/tools/chrome-devtools/device-mode/geolocation would be updated as well. @kaycebasques could you PTAL?

+10 -1

0 comment

1 changed file

pr created time in 11 days

create barnchgoogle/WebFundamentals

branch : timezone-emulation-79

created branch time in 11 days

push eventtc39/notes

azu

commit sha 425ab0e16a32f8199b5521a1cf7439d10d4c8a83

Fix link in 2019-12/december-3.md (#32) Co-authored-by: Sergey Rubanov <chi187@gmail.com>

view details

push time in 12 days

PR merged tc39/notes

Fix link in 2019-12/december-3.md

Add http: schema

+1 -2

0 comment

1 changed file

azu

pr closed time in 12 days

push eventv8/v8.dev

Mathias Bynens

commit sha 98ad7e2f6283fa18aa83e01763128c417611b319

Fix minor nits

view details

push time in 12 days

push eventtibiamaps/tibia-map-data

mathiasbynens

commit sha 3c664997e140ca52d99de357595a6f9ef9996b76

Update generated map data @ c02db3da4dfb37a6cc9f94b490b7c66ad619ec1f

view details

push time in 13 days

push eventtibiamaps/tibia-map-data

Mathias Bynens

commit sha c02db3da4dfb37a6cc9f94b490b7c66ad619ec1f

Import marker changes from client

view details

push time in 13 days

issue commentWICG/native-file-system

Set initial directory to be opened with chooseFileSystemEntries

+1 to this. My use case is an “installer”, which lets the user select a directory on their machine, to which the installer then writes a (large) number of files. The thing is, the desired location is always one of three paths, depending on the operating system (navigator.platform).

As a workaround, I currently note down these three locations, so that the user can copy-paste them into the directory picker manually… but most users probably won’t realize they can do that.

EricSimons

comment created time in 13 days

issue commentWICG/native-file-system

Set initial directory to be opened with chooseFileSystemEntries

+1 to this. My use case is an “installer”, which lets the user select a directory on their machine, to which the installer then writes a (large) number of files.

AFAICT there is currently no way to do this other than by…

  1. letting the user select a directory first, resulting in a directoryHandle, and then
  2. using await directoryHandle.getFile(fileName, { create: true }) to get a fileHandle for each file.

This currently triggers two permission requests: one for 1, and one for 2. (Thankfully, not 1 for every single file in 2.) I’d much prefer being able to just ask for write permission to a user-specified directory upfront.

EricSimons

comment created time in 13 days

pull request commenttc39/ecma262

Normative: Use CharacterValue for RegExpUnicodeEscapeSequence

Thanks for fixing the spec bug that accidentally made \u{1D49C} illegal!

As explained in #1861, I'd prefer making /(?<\uD835\uDC9C>.)/u remain illegal, since group names are thought of as IdentifierNames, and because var \uD835\uDC9C or groups.\uD835\uDC9C aren't valid either.

bakkot

comment created time in 15 days

issue commenttc39/ecma262

`SV(RegExpUnicodeEscapeSequence)` is used but not defined

Note that to maintain symmetry between MemberExpressions a la groups.bar (where bar must be a valid IdentifierName) and the regexp pattern source itself, we’d have to ban /(?<\uD835\uDC9C>.)/u. Then, we get the following:

'x'.match(/(?<𝒜>.)/u).groups.𝒜;
// → does not throw
'x'.match(/(?<\uD835\uDC9C>.)/u).groups.𝒜;
// → throws
'x'.match(/(?<𝒜>.)/u).groups.\uD835\uDC9C;
// → throws
var \uD835\uDC9C;
// → throws

…which IMHO makes sense.

bakkot

comment created time in 17 days

Pull request review commenttc39/test262

Add coverage for astral ID_Start and ID_Continue in identifiers

+// Copyright (C) 2020 Alexey Shvayka. All rights reserved.+// This code is governed by the BSD license found in the LICENSE file.++/*---+esid: sec-names-and-keywords+description: Test grandfathered astral characters of ID_Continue.

“grandfathered” is the opposite of what happened here: astral characters were not valid in identifiers prior to ES2015. (Same in the other file.)

shvaikalesh

comment created time in 17 days

pull request commentpuppeteer/puppeteer

chore: Replace Juggler with Firefox Nightly in CI

Let me know if there's a specific deprecation message/link you'd like to add to puppeteer-firefox.

mjzffr

comment created time in 17 days

Pull request review commentpuppeteer/puppeteer

chore: Replace Juggler with Firefox Nightly in CI

 before_install:   - "sysctl kernel.unprivileged_userns_clone=1"   - "export DISPLAY=:99.0"   - "sh -e /etc/init.d/xvfb start"+  - 'if [ "$FIREFOX" = "true" ]; then pyenv shell 3.6; pip3 install --user mozdownload; fi'+  - 'if [ "$FIREFOX" = "true" ]; then rm -rf $FIREFOX_HOME; mozdownload -t daily -d $FIREFOX_HOME/latest.tar.bz --log-level DEBUG; fi'+  - 'if [ "$FIREFOX" = "true" ]; then cd $FIREFOX_HOME; tar -xvf latest.tar.bz; cd -; ls $FIREFOX_HOME/firefox/firefox; fi'

ack

mjzffr

comment created time in 17 days

Pull request review commentv8/v8.dev

Minor fixes to the blog post Understanding ECMAScript part 1.

 That is, we inspect a Completion Record; if it’s an abrupt completion, we retu > 2. `ReturnIfAbrupt(obj)` > 3. `Bar(obj)`. (If we’re still here, `obj` is the value extracted from the Completion Record.) -And now [the question mark](https://tc39.es/ecma262/#sec-returnifabrupt-shorthands) comes into play: `? Foo()` is equivalent to `ReturnIfAbrupt(Foo())`.+And now [the question mark](https://tc39.es/ecma262/#sec-returnifabrupt-shorthands) comes into play: `? Foo()` is equivalent to `ReturnIfAbrupt(Foo())`. Using a shorthand is practical, so that we don't need to write the error handling code explicitly each time.
And now [the question mark](https://tc39.es/ecma262/#sec-returnifabrupt-shorthands) comes into play: `? Foo()` is equivalent to `ReturnIfAbrupt(Foo())`. Using a shorthand is practical: we don’t need to write the error handling code explicitly each time.
marjakh

comment created time in 18 days

Pull request review commentv8/v8.dev

Minor fixes to the blog post Understanding ECMAScript part 1.

 To describe how `Object.prototype.hasOwnProperty` works, the spec uses pseudocod > 2. Let `O` be `? ToObject(this value)`. > 3. Return `? HasOwnProperty(O, P)`. -…and…+and

Why remove these?

…and…	
marjakh

comment created time in 18 days

Pull request review commentv8/v8.dev

Add a blog post: Understanding the ECMAScript spec, part 2

+---+title: 'Understanding the ECMAScript spec, part 2'+author: '[Marja Hölttä](https://twitter.com/marjakh), speculative specification spectator'+avatars:+  - marja-holtta+date: 2020-02-05 13:33:37+tags:+  - ECMAScript+description: 'Tutorial on reading the ECMAScript specification'+tweet: ''+---++... where we practice our awesome spec reading skills some more.++## Previous episodes++If you haven't had a look at the previous episodes, now it's a good time to do so!++[Part 1](https://v8.dev/blog/understanding-ecmascript-part-1)++## Ready for part 2?++A fun way to get to know the spec is to start with a JavaScript feature we know is there, and find out how it's specified.++We know that properties are looked up in the prototype chain: if an object doesn't have the property we're trying to read, we walk up the prototype chain until we find it (or find an object which no longer has a prototype).++For example:++```javascript+const o1 = {'foo' : 2511};+const o2 = {};+console.log(o2.foo); // undefined+o2.__proto__ = o1;

Let's use Object.setPrototypeOf instead of __proto__ (throughout the entire article). __proto__ is a legacy web compat wart, and Object.setPrototypeOf is more readable.

marjakh

comment created time in 18 days

Pull request review commentv8/v8.dev

Add a blog post: Understanding the ECMAScript spec, part 2

+---+title: 'Understanding the ECMAScript spec, part 2'+author: '[Marja Hölttä](https://twitter.com/marjakh), speculative specification spectator'+avatars:+  - marja-holtta+date: 2020-02-05 13:33:37+tags:+  - ECMAScript+description: 'Tutorial on reading the ECMAScript specification'+tweet: ''+---++... where we practice our awesome spec reading skills some more.++## Previous episodes++If you haven't had a look at the previous episodes, now it's a good time to do so!++[Part 1](https://v8.dev/blog/understanding-ecmascript-part-1)++## Ready for part 2?++A fun way to get to know the spec is to start with a JavaScript feature we know is there, and find out how it's specified.++We know that properties are looked up in the prototype chain: if an object doesn't have the property we're trying to read, we walk up the prototype chain until we find it (or find an object which no longer has a prototype).++For example:++```javascript+const o1 = {'foo' : 2511};+const o2 = {};+console.log(o2.foo); // undefined+o2.__proto__ = o1;+console.log(o2.foo); // 2511+```++## Where's the prototype walk defined?++Let's try to find out where this behavior is defined. A good place to start is a list of [Object Internal Methods](https://tc39.es/ecma262/#sec-object-internal-methods-and-internal-slots).++There's both `[[GetOwnProperty]]` and `[[Get]]` &mdash; now we're interested in the version that isn't restricted to _own_ properties, so we'll go with `[[Get]]`.++Unfortunately, the [Property Descriptor specification type](https://tc39.es/ecma262/#sec-property-descriptor-specification-type) also has a field called `[[Get]]`, so while browsing the spec for `[[Get]]`, we need to carefully distinguish between the two independent usages.++The internal method `[[Get]]` delegates to `OrdinaryGet`:++> [`[[Get]] ( P, Receiver )`](https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-get-p-receiver)+>+> When the `[[Get]]` internal method of `O` is called with property key `P` and ECMAScript language value `Receiver`, the following steps are taken:+>+> 1. Return `? OrdinaryGet(O, P, Receiver)`.++`OrdinaryGet` is defined like this:++> [`OrdinaryGet ( O, P, Receiver )`](https://tc39.es/ecma262/#sec-ordinaryget)+>+> When the abstract operation `OrdinaryGet` is called with Object `O`, property key `P`, and ECMAScript language value `Receiver`, the following steps are taken:+>+> 1. Assert: `IsPropertyKey(P)` is `true`.+> 2. Let `desc` be `? O.[[GetOwnProperty]](P)`.+> 3. If `desc` is `undefined`, then+> a. Let `parent` be `? O.[[GetPrototypeOf]]()`.+> b. If `parent` is `null`, return `undefined`.+> c. Return `? parent.[[Get]](P, Receiver)`.+> 4. If `IsDataDescriptor(desc)` is `true`, return `desc.[[Value]]`.+> 5. Assert: `IsAccessorDescriptor(desc)` is `true`.+> 6. Let `getter` be `desc.[[Get]]`.+> 7. If `getter` is `undefined`, return `undefined`.+> 8. Return `? Call(getter, Receiver)`.++The prototype chain walk is inside step 3: if we don't find the property as an own property, we recurse into the prototype's `[[Get]]` method.++## Where's the Receiver coming from?

+1 I don't think many JS devs use (or understand) the term "receiver". Let's briefly explain it.

marjakh

comment created time in 18 days

push eventtibiamaps/tibia-map-data

mathiasbynens

commit sha 49c3145ff4875c70d6a64ac947f3fa08d55cc358

Update generated map data @ c0532fb62e7c30523e5028515e3c84461d9406d1

view details

push time in 18 days

issue closedtibiamaps/tibia-map-data

Add Issavi markers

The spreadsheet is open for submissions!

https://docs.google.com/spreadsheets/d/1K6hEPmxUCFj293yCkMAphX2UvJRgTaLqt465J48hJO4/edit

closed time in 18 days

mathiasbynens

push eventtibiamaps/tibia-map-data

Mathias Bynens

commit sha c0532fb62e7c30523e5028515e3c84461d9406d1

Import marker changes from client

view details

push time in 18 days

pull request commenttc39/tc39.github.io

Fix #173, add tc39-ntoes folder for old link redirection

Let's get this merged and deployed asap please :)

othree

comment created time in 19 days

pull request commentpuppeteer/puppeteer

Emit change event on uploadFile calls

Thanks for the patch! Could you add a test for this as well please?

phihag

comment created time in 19 days

push eventtibiamaps/tibia-map-data

mathiasbynens

commit sha 8215422244579c13683dc7be2a40945102a808be

Update generated map data @ 18c5ef12948079c71c3b27ece3b20a1968a9f21b

view details

push time in 19 days

push eventtibiamaps/tibia-map-data

Mathias Bynens

commit sha 18c5ef12948079c71c3b27ece3b20a1968a9f21b

Import marker changes from client

view details

push time in 19 days

push eventv8/v8.dev

Mathias Bynens

commit sha 774b7446092b679fc2c8bb99d00e8d67b9d9533d

Fix nit

view details

push time in 20 days

startedljharb/publishers

started time in 20 days

push eventv8/v8.dev

Mathias Bynens

commit sha fd247896a1b5b6df0862dfd5ea25b5b338c70c87

Fix nits

view details

Mathias Bynens

commit sha deb3ff46cc35cfca68f5778a20a93bfc91c88dcf

Publish “Understanding the ECMAScript spec”

view details

push time in 21 days

PR merged v8/v8.dev

Add a blog post: Understanding the ECMAScript spec, part 1 blog cla: yes
+230 -0

4 comments

2 changed files

marjakh

pr closed time in 21 days

push eventv8/v8.dev

Marja Hölttä

commit sha b8c4955561aefd23ebb246dfa652e952601769d6

Add “Understanding the ECMAScript spec, part 1” (#321)

view details

push time in 21 days

Pull request review commentv8/v8.dev

Add a blog post: Understanding the ECMAScript spec, part 1

+---+title: 'Understanding the ECMAScript spec, part 1'+author: '[Marja Hölttä](https://twitter.com/marjakh), speculative specification spectator'+avatars:+  - marja-holtta+date: 2020-02-03 13:33:37+tags:+  - ECMAScript+description: 'Tutorial on reading the ECMAScript specification'+tweet: ''+---++... where we take a simple function in the spec and try to understand the notation.++## Preface++Even if you know JavaScript, reading its language specification, [ECMAScript Language specification, or the ECMAScript spec for short](https://tc39.es/ecma262/), can be pretty daunting. At least that's how I felt when I started reading it for the first time.++Let's start with a concrete example and walk through the spec to understand it. The following code demonstrates usage of `Object.prototype.hasOwnProperty`:++```javascript+const o = {'foo': 1};+o.hasOwnProperty('foo'); // true+o.hasOwnProperty('bar'); // false+```++In the example, `o` doesn't have a property called `hasOwnProperty`, so we walk up the prototype chain and look for it. We find it in `o`'s prototype, which is `Object.prototype`.++To describe how `Object.prototype.hasOwnProperty` works, the spec uses pseudocode-like descriptions like this:++> `Object.prototype.hasOwnProperty(V)`+>+> When the `hasOwnProperty` method is called with argument `V`, the following steps are taken:+>+> 1. Let `P` be `? ToPropertyKey(V)`.+> 2. Let `O` be `? ToObject(this value)`.+> 3. Return `? HasOwnProperty(O, P)`.++[Spec: Object.prototype.hasOwnProperty](https://tc39.es/ecma262#sec-object.prototype.hasownproperty)++and++> `HasOwnProperty(O, P)`+>+>The abstract operation `HasOwnProperty` is used to determine whether an object has an own property with the specified property key. A Boolean value is returned. The operation is called with arguments `O` and `P` where `O` is the object and `P` is the property key. This abstract operation performs the following steps:+>+> 1. Assert: `Type(O)` is `Object`.+> 2. Assert: `IsPropertyKey(P)` is `true`.+> 3. Let `desc` be `? O.[[GetOwnProperty]](P)`.+> 4. If `desc` is `undefined`, return `false`.+> 5. Return `true`.++[Spec: HasOwnProperty](https://tc39.es/ecma262#sec-hasownproperty)++But what's an "abstract operation"? What are the things inside \[\[ \]\]? Why is there a "?" in front of a function? What do the asserts mean?++Let's find out!++## Language Types and Specification Types++Let's start with something that looks familiar. The spec uses values such as `undefined`, `true`, and `false`, which we already know from JavaScript. They all are **language values**, values of **language types** which the spec also defines.++The spec also uses language values internally, for example, an internal data type might contain a field whose possible values are `true` and `false`. In contrast, JavaScript engines don't typically use language values internally. For example, if the JavaScript engine is written in C++, it would typically use the C++ `true` and `false` (and not its internal representations of the JavaScript `true` and `false`).++[Spec: ECMAScript language types](https://tc39.es/ecma262/#sec-ecmascript-language-types)++In addition to language types, the spec also uses **specification types**, which are types that occur only in the spec, but not in the JavaScript language. The JavaScript engine does not need to (but is free to) implement them. In this blog post, we'll get to know the specification type Record (and its subtype Completion Record).++[Spec: ECMAScript specification types](https://tc39.es/ecma262/#sec-ecmascript-specification-types)++## Abstract operations++**Abstract operations** are functions defined in the ECMAScript spec; they are defined for the purpose of writing the spec concisely. A JavaScript engine doesn't have to implement them as separate functions inside the engine. They cannot be directly called from JavaScript.++[Spec: Abstract Operations](https://tc39.es/ecma262/#sec-abstract-operations)++## Internal slots and internal methods++**Internal slots** and **internal methods** use names enclosed in \[\[ \]\].++Internal slots are data members of a JavaScript object or a specification type. They are used for storing the state of the object. Internal methods are member functions of a JavaScript object.++[Spec: Object internal methods and internal slots](https://tc39.es/ecma262/#sec-object-internal-methods-and-internal-slots)++For example, every JavaScript object has an internal slot `[[Prototype]]` and an internal method `[[GetOwnProperty]]`.++Internal slots and methods are not accessible from JavaScript. For example, you cannot access `o.[[Prototype]]` or call `o.[[GetOwnProperty]]()`. A JavaScript engine can implement them for their own internal use, but doesn't have to.++Sometimes internal methods delegate to similarly-named abstract operations, such as in the case of ordinary objects' `[[GetOwnProperty]]:`++> `[[GetOwnProperty]](P)`+>+> When the `[[GetOwnProperty]]` internal method of `O` is called with property key `P`, the following steps are taken:+>+> Return `! OrdinaryGetOwnProperty(O, P)`.++[Spec: \[\[GetOwnProperty\]\]](https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getownproperty-p)++(We'll find out what the exclamation mark means in the next chapter.)++`OrdinaryGetOwnProperty` is not an internal method, since it's not associated with any object; instead, the object it operates on is passed as a parameter.++`OrdinaryGetOwnProperty` is called "ordinary" since it operates on ordinary objects. ECMAScript objects can be either **ordinary** or **exotic**. Ordinary objects must have the default behavior for a set of methods called **essential internal methods**. If an object deviates from the default behavior, it's exotic.++The most well-known exotic object is the `Array`, since its length property behaves in a non-default way: setting the length property can remove elements from the `Array`.++Essential internal methods are the methods listed [here](https://tc39.es/ecma262/#table-5).++## Completion Records++What about the question marks and exclamation marks? To understand them, we need to look into **Completion Records**!++Completion Record is a specification type (only defined for spec purposes). A JavaScript engine doesn't have to have a corresponding internal data type.++A Completion Record is a "record" &mdash; a data type which has a fixed set of named fields. A Completion Record has three fields:++:::table-wrapper+| Name | Description |+--- | ---+| `[[Type]]` | One of: `normal`, `break`, `continue`, `return`, or `throw`. All other types except `normal` are referred to as **abrupt completions**.|+| `[[Value]]` | The value that was produced when the completion occurred, for example, the return value of a function or the exception (if one is thrown).|+| `[[Target]]` | Used for directed control transfers (not relevant for this blog post).|+:::++[Spec: Completion Record](https://tc39.es/ecma262/#sec-completion-record-specification-type)++Every abstract operation implicitly returns a Completion Record. Even if it looks like an abstract operation would return a simple type such as Boolean, it's implicitly wrapped into a Completion Record with the type `normal` (see [Implicit Completion Values](https://www.ecma-international.org/ecma-262/index.html#sec-implicit-completion-values)).++Note 1: The spec is not fully consitent in this regard; there are some helper functions which return bare values and whose return values are used as is, without extracting the value from the Completion Record. This is usually clear from the context.++Note 2: The spec editors are looking into making the Completion Record handling more explicit.++If an algorithm throws an exception, it means returning a Completion Record with `[[Type]]` `throw` whose `[[Value]]` is the exception object. We'll ignore the `break`, `continue` and `return` types for now.++`ReturnIfAbrupt(argument)` means taking the following steps:++> 1. If `argument` is abrupt, return `argument`+> 2. Set `argument` to `argument.[[Value]]`++That is, we inspect a Completion Record; if it's an abrupt completion, we return immediately. Otherwise, we extract the value from the Completion Record.++[Spec: ReturnIfAbrupt](https://tc39.es/ecma262/#sec-returnifabrupt)++`ReturnIfAbrupt` might look like a function call, but it's not. It causes the function where `ReturnIfAbrupt()` occurs to return, not the `ReturnIfAbrupt` function itself. It behaves more like a macro in C-like languages.++`ReturnIfAbrupt` can be used like this:++> 1. Let `obj` be `Foo()` // `obj` is a Completion Record+> 2. `ReturnIfAbrupt(obj)`+> 3. `Bar(obj)` // If we're still here, `obj` is the value extracted from the Completion Record++And now the question mark comes into play: `? Foo()` is equivalent to `ReturnIfAbrupt(Foo())`.++Similarly, `Let val be ! Foo()` is equivalent to:++> 1. Let `val` be `Foo()`+> 2. Assert: `val` is not an abrupt completion+> 3. Set `val` to `val.[[Value]]`.++[Spec: ReturnIfAbrupt shorthands](https://tc39.es/ecma262/#sec-returnifabrupt-shorthands)++Using this knowledge, we can rewrite `Object.prototype.hasOwnProperty` like this:++> `Object.prototype.hasOwnProperty(P)`+>+> 1. Let `P` be `ToPropertyKey(V)`.+> 2. If `P` is an abrupt completion, return `P`+> 3. Set `P` to `P.[[Value]]`+> 4. Let `O` be `ToObject(this value)`.+> 5. If `O` is an abrupt completion, return `O`+> 6. Set `O` to `O.[[Value]]`+> 7. Let `temp` be `HasOwnProperty(O, P)`.+> 8. If `temp` is an abrupt completion, return `temp`+> 9. Let `temp` be `temp.[[Value]]`+> 10. Return `NormalCompletion(temp)`++and `HasOwnProperty` like this:++> `HasOwnProperty(O, P)`+>+> 1. Assert: `Type(O)` is `Object`.+> 2. Assert: `IsPropertyKey(P)` is `true`.+> 3. Let `desc` be `O.[[GetOwnProperty]](P)`.+> 4. If `desc` is an abrupt completion, return `desc`+> 5. Set `desc` to `desc.[[Value]]`+> 6. If `desc` is `undefined`, return `NormalCompletion(false)`.+> 7. Return `NormalCompletion(true)`.++We can also rewrite the `[[GetOwnProperty]]` internal method without the exclamation mark like this:++> `O.[[GetOwnProperty]]`+>+> 1. Let `temp` be `OrdinaryGetOwnProperty(O, P)`+> 2. Assert: `temp` is not an abrupt completion+> 3. Let `temp` be `temp.[[Value]]`+> 4. Return `NormalCompletion(temp)`++Here we assume that `temp` is a brand new temporary variable which doesn't collide with anything else.++We've also used the knowledge that when a return statement returns something else than a Completion Record, it's implicitly wrapped inside a `NormalCompletion`.++### Side track: Return ? Foo()++The spec uses the notation `Return ? Foo()` &mdash; why the question mark?++`Return ? Foo()` expands to:++> 1. Let `temp` be `Foo()`+> 2. If `temp` is an abrupt completion, return `temp`+> 3. Set `temp` to `temp.[[Value]]`+> 4. Return `NormalCompletion(temp)`++Which is the same as `Return Foo()`; it behaves the same way for both abrupt and normal completions.++## Asserts++Asserts in the spec assert invariant conditions of the algorithms. They are added for clarity, but don't add any requirements to the implementation &mdash; the implementation doesn't need to check them.++## Moving on++We have built the understanding needed for reading the spec for simple methods like `Object.prototype.hasOwnProperty` and abstract operations like `HasOwnProperty`. They still delegate to other abstract operations, but based on this blog post we should be able to figure out what they do. We'll encounter Property Descriptors, which is just another specification type.++<figure>+  <img src="/_img/understanding-ecma-part-1-1.svg" height="306" width="1082" alt="Function call graph starting from Object.prototype.hasOwnProperty">

this needs loading=lazy (npm run img)

marjakh

comment created time in 21 days

Pull request review commentv8/v8.dev

Add a blog post: Understanding the ECMAScript spec, part 1

+---+title: 'Understanding the ECMAScript spec, part 1'+author: '[Marja Hölttä](https://twitter.com/marjakh), speculative specification spectator'+avatars:+  - marja-holtta+date: 2020-02-03 13:33:37+tags:+  - ECMAScript+description: 'Tutorial on reading the ECMAScript specification'+tweet: ''+---++... where we take a simple function in the spec and try to understand the notation.++## Preface++Even if you know JavaScript, reading its language specification, [ECMAScript Language specification, or the ECMAScript spec for short](https://tc39.es/ecma262/), can be pretty daunting. At least that's how I felt when I started reading it for the first time.++Let's start with a concrete example and walk through the spec to understand it. The following code demonstrates usage of `Object.prototype.hasOwnProperty`:++```javascript+const o = {'foo': 1};+o.hasOwnProperty('foo'); // true+o.hasOwnProperty('bar'); // false+```++In the example, `o` doesn't have a property called `hasOwnProperty`, so we walk up the prototype chain and look for it. We find it in `o`'s prototype, which is `Object.prototype`.++To describe how `Object.prototype.hasOwnProperty` works, the spec uses pseudocode-like descriptions like this:++> `Object.prototype.hasOwnProperty(V)`+>+> When the `hasOwnProperty` method is called with argument `V`, the following steps are taken:+>+> 1. Let `P` be `? ToPropertyKey(V)`.+> 2. Let `O` be `? ToObject(this value)`.+> 3. Return `? HasOwnProperty(O, P)`.++[Spec: Object.prototype.hasOwnProperty](https://tc39.es/ecma262#sec-object.prototype.hasownproperty)++and++> `HasOwnProperty(O, P)`+>+>The abstract operation `HasOwnProperty` is used to determine whether an object has an own property with the specified property key. A Boolean value is returned. The operation is called with arguments `O` and `P` where `O` is the object and `P` is the property key. This abstract operation performs the following steps:+>+> 1. Assert: `Type(O)` is `Object`.+> 2. Assert: `IsPropertyKey(P)` is `true`.+> 3. Let `desc` be `? O.[[GetOwnProperty]](P)`.+> 4. If `desc` is `undefined`, return `false`.+> 5. Return `true`.++[Spec: HasOwnProperty](https://tc39.es/ecma262#sec-hasownproperty)++But what's an "abstract operation"? What are the things inside \[\[ \]\]? Why is there a "?" in front of a function? What do the asserts mean?++Let's find out!++## Language Types and Specification Types++Let's start with something that looks familiar. The spec uses values such as `undefined`, `true`, and `false`, which we already know from JavaScript. They all are **language values**, values of **language types** which the spec also defines.++The spec also uses language values internally, for example, an internal data type might contain a field whose possible values are `true` and `false`. In contrast, JavaScript engines don't typically use language values internally. For example, if the JavaScript engine is written in C++, it would typically use the C++ `true` and `false` (and not its internal representations of the JavaScript `true` and `false`).++[Spec: ECMAScript language types](https://tc39.es/ecma262/#sec-ecmascript-language-types)++In addition to language types, the spec also uses **specification types**, which are types that occur only in the spec, but not in the JavaScript language. The JavaScript engine does not need to (but is free to) implement them. In this blog post, we'll get to know the specification type Record (and its subtype Completion Record).++[Spec: ECMAScript specification types](https://tc39.es/ecma262/#sec-ecmascript-specification-types)++## Abstract operations++**Abstract operations** are functions defined in the ECMAScript spec; they are defined for the purpose of writing the spec concisely. A JavaScript engine doesn't have to implement them as separate functions inside the engine. They cannot be directly called from JavaScript.++[Spec: Abstract Operations](https://tc39.es/ecma262/#sec-abstract-operations)++## Internal slots and internal methods++**Internal slots** and **internal methods** use names enclosed in \[\[ \]\].++Internal slots are data members of a JavaScript object or a specification type. They are used for storing the state of the object. Internal methods are member functions of a JavaScript object.++[Spec: Object internal methods and internal slots](https://tc39.es/ecma262/#sec-object-internal-methods-and-internal-slots)++For example, every JavaScript object has an internal slot `[[Prototype]]` and an internal method `[[GetOwnProperty]]`.++Internal slots and methods are not accessible from JavaScript. For example, you cannot access `o.[[Prototype]]` or call `o.[[GetOwnProperty]]()`. A JavaScript engine can implement them for their own internal use, but doesn't have to.++Sometimes internal methods delegate to similarly-named abstract operations, such as in the case of ordinary objects' `[[GetOwnProperty]]:`++> `[[GetOwnProperty]](P)`+>+> When the `[[GetOwnProperty]]` internal method of `O` is called with property key `P`, the following steps are taken:+>+> Return `! OrdinaryGetOwnProperty(O, P)`.++[Spec: \[\[GetOwnProperty\]\]](https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-getownproperty-p)++(We'll find out what the exclamation mark means in the next chapter.)++`OrdinaryGetOwnProperty` is not an internal method, since it's not associated with any object; instead, the object it operates on is passed as a parameter.++`OrdinaryGetOwnProperty` is called "ordinary" since it operates on ordinary objects. ECMAScript objects can be either **ordinary** or **exotic**. Ordinary objects must have the default behavior for a set of methods called **essential internal methods**. If an object deviates from the default behavior, it's exotic.++The most well-known exotic object is the `Array`, since its length property behaves in a non-default way: setting the length property can remove elements from the `Array`.++Essential internal methods are the methods listed [here](https://tc39.es/ecma262/#table-5).++## Completion Records++What about the question marks and exclamation marks? To understand them, we need to look into **Completion Records**!++Completion Record is a specification type (only defined for spec purposes). A JavaScript engine doesn't have to have a corresponding internal data type.++A Completion Record is a "record" &mdash; a data type which has a fixed set of named fields. A Completion Record has three fields:++:::table-wrapper+| Name | Description |+--- | ---+| `[[Type]]` | One of: `normal`, `break`, `continue`, `return`, or `throw`. All other types except `normal` are referred to as **abrupt completions**.|+| `[[Value]]` | The value that was produced when the completion occurred, for example, the return value of a function or the exception (if one is thrown).|+| `[[Target]]` | Used for directed control transfers (not relevant for this blog post).|+:::++[Spec: Completion Record](https://tc39.es/ecma262/#sec-completion-record-specification-type)++Every abstract operation implicitly returns a Completion Record. Even if it looks like an abstract operation would return a simple type such as Boolean, it's implicitly wrapped into a Completion Record with the type `normal` (see [Implicit Completion Values](https://www.ecma-international.org/ecma-262/index.html#sec-implicit-completion-values)).++Note 1: The spec is not fully consitent in this regard; there are some helper functions which return bare values and whose return values are used as is, without extracting the value from the Completion Record. This is usually clear from the context.++Note 2: The spec editors are looking into making the Completion Record handling more explicit.++If an algorithm throws an exception, it means returning a Completion Record with `[[Type]]` `throw` whose `[[Value]]` is the exception object. We'll ignore the `break`, `continue` and `return` types for now.++`ReturnIfAbrupt(argument)` means taking the following steps:++> 1. If `argument` is abrupt, return `argument`+> 2. Set `argument` to `argument.[[Value]]`++That is, we inspect a Completion Record; if it's an abrupt completion, we return immediately. Otherwise, we extract the value from the Completion Record.++[Spec: ReturnIfAbrupt](https://tc39.es/ecma262/#sec-returnifabrupt)++`ReturnIfAbrupt` might look like a function call, but it's not. It causes the function where `ReturnIfAbrupt()` occurs to return, not the `ReturnIfAbrupt` function itself. It behaves more like a macro in C-like languages.++`ReturnIfAbrupt` can be used like this:++> 1. Let `obj` be `Foo()` // `obj` is a Completion Record+> 2. `ReturnIfAbrupt(obj)`+> 3. `Bar(obj)` // If we're still here, `obj` is the value extracted from the Completion Record++And now the question mark comes into play: `? Foo()` is equivalent to `ReturnIfAbrupt(Foo())`.++Similarly, `Let val be ! Foo()` is equivalent to:++> 1. Let `val` be `Foo()`+> 2. Assert: `val` is not an abrupt completion+> 3. Set `val` to `val.[[Value]]`.++[Spec: ReturnIfAbrupt shorthands](https://tc39.es/ecma262/#sec-returnifabrupt-shorthands)++Using this knowledge, we can rewrite `Object.prototype.hasOwnProperty` like this:++> `Object.prototype.hasOwnProperty(P)`+>+> 1. Let `P` be `ToPropertyKey(V)`.+> 2. If `P` is an abrupt completion, return `P`+> 3. Set `P` to `P.[[Value]]`+> 4. Let `O` be `ToObject(this value)`.+> 5. If `O` is an abrupt completion, return `O`+> 6. Set `O` to `O.[[Value]]`+> 7. Let `temp` be `HasOwnProperty(O, P)`.+> 8. If `temp` is an abrupt completion, return `temp`+> 9. Let `temp` be `temp.[[Value]]`+> 10. Return `NormalCompletion(temp)`++and `HasOwnProperty` like this:++> `HasOwnProperty(O, P)`+>+> 1. Assert: `Type(O)` is `Object`.+> 2. Assert: `IsPropertyKey(P)` is `true`.+> 3. Let `desc` be `O.[[GetOwnProperty]](P)`.+> 4. If `desc` is an abrupt completion, return `desc`+> 5. Set `desc` to `desc.[[Value]]`+> 6. If `desc` is `undefined`, return `NormalCompletion(false)`.+> 7. Return `NormalCompletion(true)`.++We can also rewrite the `[[GetOwnProperty]]` internal method without the exclamation mark like this:++> `O.[[GetOwnProperty]]`+>+> 1. Let `temp` be `OrdinaryGetOwnProperty(O, P)`+> 2. Assert: `temp` is not an abrupt completion+> 3. Let `temp` be `temp.[[Value]]`+> 4. Return `NormalCompletion(temp)`++Here we assume that `temp` is a brand new temporary variable which doesn't collide with anything else.++We've also used the knowledge that when a return statement returns something else than a Completion Record, it's implicitly wrapped inside a `NormalCompletion`.++### Side track: Return ? Foo()
### Side track: `Return ? Foo()`
marjakh

comment created time in 21 days

Pull request review commentv8/v8.dev

Add a blog post: Understanding the ECMAScript spec, part 1

+---+title: 'Understanding the ECMAScript spec, part 1'+author: '[Marja Hölttä](https://twitter.com/marjakh), speculative specification spectator'+avatars:+  - marja-holtta+date: 2020-02-03 13:33:37+tags:+  - ECMAScript+description: 'Tutorial on reading the ECMAScript specification'+tweet: ''+---++... where we take a simple function in the spec and try to understand the notation.++## Preface++Even if you know JavaScript, reading its language specification, [ECMAScript Language specification, or the ECMAScript spec for short](https://tc39.es/ecma262/), can be pretty daunting. At least that's how I felt when I started reading it for the first time.++Let's start with a concrete example and walk through the spec to understand it. The following code demonstrates usage of `Object.prototype.hasOwnProperty`:++```javascript+const o = {'foo': 1};+o.hasOwnProperty('foo'); // true+o.hasOwnProperty('bar'); // false+```++In the example, `o` doesn't have a property called `hasOwnProperty`, so we walk up the prototype chain and look for it. We find it in `o`'s prototype, which is `Object.prototype`.++To describe how `Object.prototype.hasOwnProperty` works, the spec uses pseudocode-like descriptions like this:++> `Object.prototype.hasOwnProperty(V)`+>+> When the `hasOwnProperty` method is called with argument `V`, the following steps are taken:+>+> 1. Let `P` be `? ToPropertyKey(V)`.+> 2. Let `O` be `? ToObject(this value)`.+> 3. Return `? HasOwnProperty(O, P)`.++[Spec: Object.prototype.hasOwnProperty](https://tc39.es/ecma262#sec-object.prototype.hasownproperty)++and++> `HasOwnProperty(O, P)`+>+>The abstract operation `HasOwnProperty` is used to determine whether an object has an own property with the specified property key. A Boolean value is returned. The operation is called with arguments `O` and `P` where `O` is the object and `P` is the property key. This abstract operation performs the following steps:+>+> 1. Assert: `Type(O)` is `Object`.+> 2. Assert: `IsPropertyKey(P)` is `true`.+> 3. Let `desc` be `? O.[[GetOwnProperty]](P)`.+> 4. If `desc` is `undefined`, return `false`.+> 5. Return `true`.++[Spec: HasOwnProperty](https://tc39.es/ecma262#sec-hasownproperty)++But what's an "abstract operation"? What are the things inside \[\[ \]\]? Why is there a "?" in front of a function? What do the asserts mean?++Let's find out!++## Language Types and Specification Types++Let's start with something that looks familiar. The spec uses values such as `undefined`, `true`, and `false`, which we already know from JavaScript. They all are **language values**, values of **language types** which the spec also defines.++The spec also uses language values internally, for example, an internal data type might contain a field whose possible values are `true` and `false`. In contrast, JavaScript engines don't typically use language values internally. For example, if the JavaScript engine is written in C++, it would typically use the C++ `true` and `false` (and not its internal representations of the JavaScript `true` and `false`).++[Spec: ECMAScript language types](https://tc39.es/ecma262/#sec-ecmascript-language-types)++In addition to language types, the spec also uses **specification types**, which are types that occur only in the spec, but not in the JavaScript language. The JavaScript engine does not need to (but is free to) implement them. In this blog post, we'll get to know the specification type Record (and its subtype Completion Record).++[Spec: ECMAScript specification types](https://tc39.es/ecma262/#sec-ecmascript-specification-types)++## Abstract operations++**Abstract operations** are functions defined in the ECMAScript spec; they are defined for the purpose of writing the spec concisely. A JavaScript engine doesn't have to implement them as separate functions inside the engine. They cannot be directly called from JavaScript.++[Spec: Abstract Operations](https://tc39.es/ecma262/#sec-abstract-operations)++## Internal slots and internal methods++**Internal slots** and **internal methods** use names enclosed in \[\[ \]\].
**Internal slots** and **internal methods** use names enclosed in `[[ ]]`.
marjakh

comment created time in 21 days

Pull request review commentv8/v8.dev

Add a blog post: Understanding the ECMAScript spec, part 1

+---+title: 'Understanding the ECMAScript spec, part 1'+author: '[Marja Hölttä](https://twitter.com/marjakh), speculative specification spectator'+avatars:+  - marja-holtta+date: 2020-02-03 13:33:37+tags:+  - ECMAScript+description: 'Tutorial on reading the ECMAScript specification'+tweet: ''+---++... where we take a simple function in the spec and try to understand the notation.++## Preface++Even if you know JavaScript, reading its language specification, [ECMAScript Language specification, or the ECMAScript spec for short](https://tc39.es/ecma262/), can be pretty daunting. At least that's how I felt when I started reading it for the first time.++Let's start with a concrete example and walk through the spec to understand it. The following code demonstrates usage of `Object.prototype.hasOwnProperty`:++```javascript+const o = {'foo': 1};+o.hasOwnProperty('foo'); // true+o.hasOwnProperty('bar'); // false+```++In the example, `o` doesn't have a property called `hasOwnProperty`, so we walk up the prototype chain and look for it. We find it in `o`'s prototype, which is `Object.prototype`.++To describe how `Object.prototype.hasOwnProperty` works, the spec uses pseudocode-like descriptions like this:++> `Object.prototype.hasOwnProperty(V)`+>+> When the `hasOwnProperty` method is called with argument `V`, the following steps are taken:+>+> 1. Let `P` be `? ToPropertyKey(V)`.+> 2. Let `O` be `? ToObject(this value)`.+> 3. Return `? HasOwnProperty(O, P)`.++[Spec: Object.prototype.hasOwnProperty](https://tc39.es/ecma262#sec-object.prototype.hasownproperty)++and++> `HasOwnProperty(O, P)`+>+>The abstract operation `HasOwnProperty` is used to determine whether an object has an own property with the specified property key. A Boolean value is returned. The operation is called with arguments `O` and `P` where `O` is the object and `P` is the property key. This abstract operation performs the following steps:+>+> 1. Assert: `Type(O)` is `Object`.+> 2. Assert: `IsPropertyKey(P)` is `true`.+> 3. Let `desc` be `? O.[[GetOwnProperty]](P)`.+> 4. If `desc` is `undefined`, return `false`.+> 5. Return `true`.++[Spec: HasOwnProperty](https://tc39.es/ecma262#sec-hasownproperty)++But what's an "abstract operation"? What are the things inside \[\[ \]\]? Why is there a "?" in front of a function? What do the asserts mean?

same for other inline code spans below

marjakh

comment created time in 21 days

Pull request review commentv8/v8.dev

Add a blog post: Understanding the ECMAScript spec, part 1

+---+title: 'Understanding the ECMAScript spec, part 1'+author: '[Marja Hölttä](https://twitter.com/marjakh), speculative specification spectator'+avatars:+  - marja-holtta+date: 2020-02-03 13:33:37+tags:+  - ECMAScript+description: 'Tutorial on reading the ECMAScript specification'+tweet: ''+---++... where we take a simple function in the spec and try to understand the notation.++## Preface++Even if you know JavaScript, reading its language specification, [ECMAScript Language specification, or the ECMAScript spec for short](https://tc39.es/ecma262/), can be pretty daunting. At least that's how I felt when I started reading it for the first time.++Let's start with a concrete example and walk through the spec to understand it. The following code demonstrates usage of `Object.prototype.hasOwnProperty`:++```javascript+const o = {'foo': 1};+o.hasOwnProperty('foo'); // true+o.hasOwnProperty('bar'); // false+```++In the example, `o` doesn't have a property called `hasOwnProperty`, so we walk up the prototype chain and look for it. We find it in `o`'s prototype, which is `Object.prototype`.++To describe how `Object.prototype.hasOwnProperty` works, the spec uses pseudocode-like descriptions like this:++> `Object.prototype.hasOwnProperty(V)`+>+> When the `hasOwnProperty` method is called with argument `V`, the following steps are taken:+>+> 1. Let `P` be `? ToPropertyKey(V)`.+> 2. Let `O` be `? ToObject(this value)`.+> 3. Return `? HasOwnProperty(O, P)`.++[Spec: Object.prototype.hasOwnProperty](https://tc39.es/ecma262#sec-object.prototype.hasownproperty)++and++> `HasOwnProperty(O, P)`+>+>The abstract operation `HasOwnProperty` is used to determine whether an object has an own property with the specified property key. A Boolean value is returned. The operation is called with arguments `O` and `P` where `O` is the object and `P` is the property key. This abstract operation performs the following steps:+>+> 1. Assert: `Type(O)` is `Object`.+> 2. Assert: `IsPropertyKey(P)` is `true`.+> 3. Let `desc` be `? O.[[GetOwnProperty]](P)`.+> 4. If `desc` is `undefined`, return `false`.+> 5. Return `true`.++[Spec: HasOwnProperty](https://tc39.es/ecma262#sec-hasownproperty)++But what's an "abstract operation"? What are the things inside \[\[ \]\]? Why is there a "?" in front of a function? What do the asserts mean?
But what's an "abstract operation"? What are the things inside `[[ ]]`? Why is there a `?` in front of a function? What do the asserts mean?
marjakh

comment created time in 21 days

startedWICG/aom

started time in 21 days

push eventtibiamaps/tibia-map-data

mathiasbynens

commit sha 93a24fd4abbc59f0133cca30d0777f59546ca817

Update generated map data @ d606fe50597b03a2df6d8bc856b833ca488c7b23

view details

push time in 22 days

push eventtibiamaps/tibia-map-data

Mathias Bynens

commit sha d606fe50597b03a2df6d8bc856b833ca488c7b23

Import marker changes from client

view details

push time in 22 days

push eventtibiamaps/tibia-map-data

mathiasbynens

commit sha b4e96f63719002dbd8bae453b1169a074f5dbcb5

Update generated map data @ 6cbf8dc1ba08210a4b71e44e6d8f0378b3a50db4

view details

push time in 23 days

push eventtibiamaps/tibia-map-data

Mathias Bynens

commit sha 6cbf8dc1ba08210a4b71e44e6d8f0378b3a50db4

Import marker changes from client

view details

push time in 23 days

issue commenttc39/ecma262

`SV(RegExpUnicodeEscapeSequence)` is used but not defined

(FYI: I don’t feel strongly on this at all; just explaining my interpretation. I don’t believe the choice we make here really matters in practice.)

bakkot

comment created time in 23 days

issue commenttc39/ecma262

`SV(RegExpUnicodeEscapeSequence)` is used but not defined

It boils down to https://tc39.es/ecma262/#sec-identifier-names-static-semantics-early-errors, which operates on a single \uXXXX escape sequence at a time. That is, it never treats a pair of escaped surrogates as a single code point. Thus, outside of regular expressions:

var 𐊧; // U+102A7 CARIAN LETTER A2
// → valid
var \u{102A7}; // U+102A7 CARIAN LETTER A2
// → valid
var \uD800\uDEA7; // U+102A7 represented as a surrogate pair
// → invalid

When Dan said:

If we do this splitting out, we need to make sure to maintain the errors for bad identifiers.

…it seems these errors fall under that.

bakkot

comment created time in 23 days

issue commenttc39/ecma262

`SV(RegExpUnicodeEscapeSequence)` is used but not defined

The intention was to preserve the errors for (non-RegExp) Identifiers. Since var \uD835\uDC9C is invalid, I’d expect /(?<\uD835\uDC9C>.)/u to be invalid too.

bakkot

comment created time in 23 days

Pull request review commentv8/v8.dev

Automatically add video dimensions

+const fs = require('fs');++const glob = require('glob');+const imageSize = require('image-size');+const videoSize = require('get-video-dimensions');++(async () => {+  const files = glob.sync('src/**/*.{html,md}');+  for (const file of files) {+    const contents = fs.readFileSync(file, 'utf8').toString();+    let updatedContents = contents;+    const images = contents.matchAll(/^\s*<img.*$/gm);+    if (!images) continue;+    for (const result of images) {+      const oldLine = result[0];+      if (oldLine.includes(' width="')) continue;+      const fileName = 'src/' + oldLine.match(/src="\/([^"]+)"/)[1];+      const { width, height } = imageSize(fileName);+      const updatedLine = oldLine.replace(' alt="', ` width="${width}" height="${height}" alt="`);+      console.log(oldLine);+      console.log('>>');+      console.log(updatedLine);+      console.log('------------');+      updatedContents = updatedContents.replace(oldLine, updatedLine);+    }++    // TODO: This needs updating once we use `<source>`.+    const videos = contents.matchAll(/^\s*<video.*$/gm);+    if (!videos) continue;+    for await (const result of videos) {
    for (const result of videos) {
tomayac

comment created time in 24 days

push eventv8/v8.dev

Mathias Bynens

commit sha f9265aa858d827084863983b0c8466c6af93f830

Update add-image-and-video-dimensions.js

view details

push time in 24 days

Pull request review commentv8/v8.dev

Automatically add video dimensions

+const fs = require('fs');++const glob = require('glob');+const imageSize = require('image-size');+const videoSize = require('get-video-dimensions');++(async () => {+  const files = glob.sync('src/**/*.{html,md}');+  console.log(files)

tomayac

comment created time in 24 days

pull request commentv8/v8.dev

Make sure figures never get too wide

This patch just needs the width/height attributes on the <video> elements, like #324 did.

tomayac

comment created time in 24 days

delete branch v8/v8.dev

delete branch : fix-videos

delete time in 24 days

pull request commentv8/v8.dev

Fix video styling

Note that we'd still want to add width/height to the <video>. #323 doesn't do that, currently.

mathiasbynens

comment created time in 24 days

pull request commentv8/v8.dev

Make sure figures never get too wide

Oh right, because we only need the fallback for the iframes, all of which are already wrapped. Got it!

tomayac

comment created time in 24 days

pull request commentv8/v8.dev

Make sure figures never get too wide

Ooh never mind, it's only for iframes, for which the wrappers are already present. Ignore me! :P

tomayac

comment created time in 24 days

pull request commentv8/v8.dev

Make sure figures never get too wide

@tomayac I might be misunderstanding something. From your latest patch, the code path for @supports not (aspect-ratio: attr(width) / 1) clearly relies on the wrappers, so... we need to add them for the fallback to work.

tomayac

comment created time in 24 days

pull request commentv8/v8.dev

Make sure figures never get too wide

I see. We'd still need the changes to the Markdown to add the wrappers (like in #324) then.

tomayac

comment created time in 24 days

issue closedtc39/proposal-well-formed-stringify

Update status to finished/accepted

Update the status of this proposal in the readme, to reflect that it has been included in the spec.

Documents like https://github.com/tc39/proposals/blob/master/finished-proposals.md link to this repo and it is confusing that the status is still listed as "Stage 4" here.

closed time in 24 days

ght

issue commenttc39/proposal-well-formed-stringify

Update status to finished/accepted

Stage 4 === Finished. See https://tc39.es/process-document/.

ght

comment created time in 24 days

pull request commentv8/v8.dev

Fix video styling

@tomayac Do you want to update your PR #323 to remove the wrappers then?

mathiasbynens

comment created time in 24 days

Pull request review commentv8/v8.dev

Fix video styling

 As per their description, MediaPipe is a framework for building multimodal (eg. One of the most visually appealing demos where it’s easy to observe the difference in performance SIMD makes, is a following hand-tracking system. Without SIMD, you can get only around 3 frames per second on a modern laptop, while with SIMD enabled you get a much smoother experience at 15-16 frames per second.  <figure>-  <video autoplay muted playsinline loop src="/_img/simd/hand.mp4"></video>+  <div class="video video-25:9">+    <video autoplay muted playsinline loop width="600" height="216" src="/_img/simd/hand.mp4"></video>+  </div> </figure>  Visit the [link](https://pursuit.page.link/MediaPipeHandTrackingSimd) in Chrome Canary with SIMD enabled to try it! -Another interesting set of demos that makes use of SIMD for smooth experience, come from OpenCV - a popular computer vision library that can also be compiled to WebAssembly. They’re available by [link](https://bit.ly/opencv-camera-demos), or you can check out the pre-recorded versions below:+Another interesting set of demos that makes use of SIMD for smooth experience come from OpenCV, a popular computer vision library that can also be compiled to WebAssembly. They’re available by [link](https://bit.ly/opencv-camera-demos), or you can check out the pre-recorded versions below:  <figure>-  <video autoplay muted playsinline loop src="/_img/simd/credit-card.mp4"></video>+  <div class="video video-25:9">+    <video autoplay muted playsinline loop width="256" height="512" src="/_img/simd/credit-card.mp4"></video>

I never liked that wrapper! Excited that we'll be able to drop it soon :)

mathiasbynens

comment created time in 24 days

pull request commentv8/v8.dev

Fix video styling

I love keeping it simple! :) This patch just builds upon what is already there for v8.dev.

I'm definitely open to dropping the hacky aspect ratio CSS + removes the wrappers, once stable browsers support it natively. IMHO that's separate to this patch which only aims to address the currently broken layout.

mathiasbynens

comment created time in 24 days

push eventv8/v8.dev

Mathias Bynens

commit sha eb685e05cef027144323ecc39e8d7f1a32252dd1

Fix video styling This makes sure that https://v8.dev/features/simd renders correctly on narrow viewports, but also that the embedded videos are responsive while maintaining their aspect ratio (similar to other videos on v8.dev, which previously were all YouTube embeds). Closes #323.

view details

push time in 24 days

Pull request review commentv8/v8.dev

Fix video styling

 As per their description, MediaPipe is a framework for building multimodal (eg. One of the most visually appealing demos where it’s easy to observe the difference in performance SIMD makes, is a following hand-tracking system. Without SIMD, you can get only around 3 frames per second on a modern laptop, while with SIMD enabled you get a much smoother experience at 15-16 frames per second.  <figure>-  <video autoplay muted playsinline loop src="/_img/simd/hand.mp4"></video>+  <div class="video video-25:9">+    <video autoplay muted playsinline loop width="600" height="216" src="/_img/simd/hand.mp4"></video>+  </div> </figure>  Visit the [link](https://pursuit.page.link/MediaPipeHandTrackingSimd) in Chrome Canary with SIMD enabled to try it! -Another interesting set of demos that makes use of SIMD for smooth experience, come from OpenCV - a popular computer vision library that can also be compiled to WebAssembly. They’re available by [link](https://bit.ly/opencv-camera-demos), or you can check out the pre-recorded versions below:+Another interesting set of demos that makes use of SIMD for smooth experience come from OpenCV, a popular computer vision library that can also be compiled to WebAssembly. They’re available by [link](https://bit.ly/opencv-camera-demos), or you can check out the pre-recorded versions below:  <figure>-  <video autoplay muted playsinline loop src="/_img/simd/credit-card.mp4"></video>+  <div class="video video-25:9">+    <video autoplay muted playsinline loop width="256" height="512" src="/_img/simd/credit-card.mp4"></video>

Side note: we should make these available in open formats, too. I can't view them in my custom Chromium build, for example.

mathiasbynens

comment created time in 24 days

pull request commentv8/v8.dev

Make sure figures never get too wide

Here's the fix I had in mind: https://github.com/v8/v8.dev/pull/324

tomayac

comment created time in 24 days

PR opened v8/v8.dev

Reviewers
Fix video styling
+22 -16

0 comment

2 changed files

pr created time in 24 days

create barnchv8/v8.dev

branch : fix-videos

created branch time in 24 days

more