Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

util: expose the WHATWG Encoding API globally #20662

4 changes: 2 additions & 2 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -764,13 +764,13 @@ The stack trace is extended to include the point in time at which the
<a id="ERR_ENCODING_INVALID_ENCODED_DATA"></a>
### ERR_ENCODING_INVALID_ENCODED_DATA

Data provided to `util.TextDecoder()` API was invalid according to the encoding
Data provided to `TextDecoder()` API was invalid according to the encoding
provided.

<a id="ERR_ENCODING_NOT_SUPPORTED"></a>
### ERR_ENCODING_NOT_SUPPORTED

Encoding provided to `util.TextDecoder()` API was not one of the
Encoding provided to `TextDecoder()` API was not one of the
[WHATWG Supported Encodings][].

<a id="ERR_FALSY_VALUE_REJECTION"></a>
Expand Down
20 changes: 20 additions & 0 deletions doc/api/globals.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,24 @@ added: v10.0.0

The WHATWG `URLSearchParams` class. See the [`URLSearchParams`][] section.

## TextEncoder
<!-- YAML
added: REPLACEME
-->

<!-- type=global -->

The WHATWG `TextEncoder` class. See the [`TextEncoder`][] section.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If what we're doing is migrating from util to a global, I think it'd be better to have the reverse: document here and have util.TextEncoder link to the definition here.


## TextDecoder
<!-- YAML
added: REPLACEME
-->

<!-- type=global -->

The WHATWG `TextDecoder` class. See the [`TextDecoder`][] section.

[`__dirname`]: modules.html#modules_dirname
[`__filename`]: modules.html#modules_filename
[`clearImmediate`]: timers.html#timers_clearimmediate_immediate
Expand All @@ -171,6 +189,8 @@ The WHATWG `URLSearchParams` class. See the [`URLSearchParams`][] section.
[`setTimeout`]: timers.html#timers_settimeout_callback_delay_args
[`URL`]: url.html#url_class_url
[`URLSearchParams`]: url.html#url_class_urlsearchparams
[`TextEncoder`]: util.html#util_class_textencoder
[`TextDecoder`]: util.html#util_class_textdecoder
[buffer section]: buffer.html
[built-in objects]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects
[module system documentation]: modules.html
Expand Down
12 changes: 10 additions & 2 deletions doc/api/util.md
Original file line number Diff line number Diff line change
Expand Up @@ -771,9 +771,13 @@ added: v8.0.0
* {symbol} that can be used to declare custom promisified variants of functions,
see [Custom promisified functions][].

## Class: util.TextDecoder
## Class: TextDecoder
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is confusing if util.TextDecoder is still accessible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mscdex I did this for consistency since, in the url docs, the class heading is URL instead of url.URL: https://nodejs.org/dist/latest-v10.x/docs/api/url.html#url_class_url

But I agree with you that this is confusing. In the case of URL, it fits the url docs. In the case of TextDecoder, it doesn't intrinsically fit the util docs.

So I'm gonna change this here, and also follow your suggestion of moving the TextDecoder and TextEncoder docs from util to globals (see: #20662 (comment)).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mscdex Actually, I'm not quite sure about this. All the globals in globals.md link to other docs, so globals is, in effect, some kind of meta documentation. If I'd move the encoding docs to globals, 90% of the globals documentation would be about encoding, which might be confusing, too. So I don't think is a clear-cut issue.

In fact, I think there are 3 possibilities here:

[1.] Keep the encoding documentation in util and link to it from globals.

  • pro: Keeps the old documentation structure so people that know the docs already won't be surprised.
  • con: When searching for "encoding", "text encoding" or similar terms, people are less likely to find the documentation (since the words "globals" and "utilities" are not semantically related to "encoding").

[2.] Move the encoding documentation to globals and link to it from util.

  • con: The globals docs are currently "meta documentation" in that they only link to other, more detailed documentation. Moving the encoding documentation into this section would break with that.
  • con: As explained in [1.], when searching for "encoding", less experienced people might not look in the "globals" documentation, making it less likely for them to find the correct documentation.
  • con (maybe): This could possibly make navigating the globals docs harder in the future, for example, if new globals are introduced that would occur below the lengthy encoding documentation.

[3.] Move the encoding documentation to a new documentation section, e.g. encoding / "Encoding" or text-encoding / "Text Encoding", and link to it from util and globals.

  • pro: This would perhaps make finding the correct documentation easier for less experienced people.
  • con (maybe): Documentation-table-of-contents-bloat (if such a thing exists). 😄

In any case, I'm not sure what's a good way to proceed with this. So I'd greatly appreciate more feedback regarding this issue.

PS: When I go to https://nodejs.org/dist/latest-v10.x/docs/api/, I sorely miss a tiny search-box in the top-right corner - I think that would help a lot.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For overall doc search, you can use "View on single page" variant, there is a link at the top of each doc.

Copy link
Contributor Author

@MarkTiedemann MarkTiedemann May 13, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vsemozhetbyt True, but I don't think that's a friendly UX/DX. (Especially on mobile, loading the whole documentation on a single page might not be the best option. But then again, I think this is off-topic here.)

<!-- YAML
added: v8.3.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/20662
description: The class is now available on the global object.
-->

An implementation of the [WHATWG Encoding Standard][] `TextDecoder` API.
Expand Down Expand Up @@ -908,9 +912,13 @@ thrown.
The value will be `true` if the decoding result will include the byte order
mark.

## Class: util.TextEncoder
## Class: TextEncoder
<!-- YAML
added: v8.3.0
changes:
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/20662
description: The class is now available on the global object.
-->

An implementation of the [WHATWG Encoding Standard][] `TextEncoder` API. All
Expand Down
19 changes: 19 additions & 0 deletions lib/internal/bootstrap/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
setupGlobalTimeouts();
setupGlobalConsole();
setupGlobalURL();
setupGlobalTextEncoderDecoder();
}

// Ensure setURLConstructor() is called before the native
Expand Down Expand Up @@ -381,6 +382,24 @@
});
}

function setupGlobalTextEncoderDecoder() {
const { TextEncoder, TextDecoder } = NativeModule.require('internal/util');
Object.defineProperties(global, {
TextEncoder: {
value: TextEncoder,
writable: true,
configurable: true,
enumerable: false
},
TextDecoder: {
value: TextDecoder,
writable: true,
configurable: true,
enumerable: false
}
});
}

function setupInspector(originalConsole, wrappedConsole, CJSModule) {
if (!process.config.variables.v8_enable_inspector) {
return;
Expand Down
4 changes: 3 additions & 1 deletion test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,9 @@ let knownGlobals = [
process,
setImmediate,
setInterval,
setTimeout
setTimeout,
TextDecoder,
TextEncoder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a mistake in my review earlier. By adding these non-enumerable values we actually do exactly the opposite of what is required in this test. Please remove them and just keep the common files as they were therefore. See #20717 for further details.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@BridgeAR Thanks, will do!

];

if (global.gc) {
Expand Down
4 changes: 3 additions & 1 deletion test/common/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ let knownGlobals = [
process,
setImmediate,
setInterval,
setTimeout
setTimeout,
TextDecoder,
TextEncoder
];

if (process.env.NODE_TEST_KNOWN_GLOBALS) {
Expand Down
25 changes: 25 additions & 0 deletions test/parallel/test-whatwg-encoding-global.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
'use strict';

require('../common');
const assert = require('assert');
const { TextEncoder, TextDecoder } = require('util');

assert.deepStrictEqual(
Object.getOwnPropertyDescriptor(global, 'TextEncoder'),
{
value: TextEncoder,
writable: true,
configurable: true,
enumerable: false
}
);

assert.deepStrictEqual(
Object.getOwnPropertyDescriptor(global, 'TextDecoder'),
{
value: TextDecoder,
writable: true,
configurable: true,
enumerable: false
}
);