← 输入框|github.com|刷新
Skip to content

Strange behavior when using TextDecoder #9941

Open

Description

@abdallahkadour

Issue Description

The textDecoder has strange behavior when working with cbor data.
In node, it is working as expected but in nativescript the TextDecoder returns a strange format:

const buffer = ArrayBuffer.isView(input) ? input.buffer : input;

More info:

Issue in node-cbor

Reproduction

https://github.com/abdallahkadour/cbor-node-ns-example

A code snippet will be executed in the app component.

clone and

$ns run ios

It executes the code:

import * as process from "process";
global.process = process;
import * as prereqs from "cbor-rn-prereqs";
import * as cbor from "cbor";

    let object = {
      "1": "DE",
      "6": 1622316073,
      "4": 1643356073,
    };

    console.log(
      "The object ",
      object,
      " Will be encoded and decoded using cbor"
    );

    let encoded = cbor.encode(object);

    console.log("The encode object hex ", encoded.toString("hex"));
    console.log("The encode object ", encoded);

    let decoded = cbor.decode(encoded);
    let decodedString = JSON.stringify(decoded);
    console.log("the decoded string", decodedString);

Relevant log output (if applicable)

The decoded object should be `{
      "1": "DE",
      "6": 1622316073,
      "4": 1643356073,
    };`

Activity

  1. CatchABus commented on Jul 27, 2022

    @CatchABus
    Contributor

    Thanks a lot for reporting this. I have also taken a look in cbor repo discussion about it and I can confirm NS polyfill for these 2 classes is incomplete or outdated. There is already been a small discussion with another member and I believe we'll look into this.
    Until then, I suggest that you use a 3rd-party polyfill for those if possible.

  2. self-assigned this
    on Jul 27, 2022
  3. abdallahkadour commented on Dec 9, 2022

    @abdallahkadour
    Author

    As a workaround, the library cbor-sync could be used.

  4. kjeib commented on Oct 14, 2026

    @kjeib

    I believe the root cause of this (and of a failure we hit with libp2p) is that TextDecoder.decode() ignores a view's byteOffset and byteLength.

    packages/core/text/text-common.ts, still the case on main:

    public decode(input: BufferSource): string {
    	const buffer = ArrayBuffer.isView(input) ? input.buffer : input;
    	...
    	const inputAs8 = new Uint8Array(buffer);

    For a typed-array view, input.buffer is the whole underlying ArrayBuffer, so the decoder decodes bytes outside the view.

    Minimal reproduction

    const bytes = new Uint8Array([0x78, 0x78, 0x68, 0x69]); // "xxhi"
    new TextDecoder().decode(bytes.subarray(2));             // expected "hi"; decodes the whole buffer instead

    Libraries that decode from sub-arrays of a larger buffer — CBOR parsers, protobuf, length-prefixed protocols — break silently. In our case, libp2p's multistream-select decodes protocol names from sub-arrays, so every stream negotiation on NativeScript failed ("did not read multistream-select header", and the remote's protocol read as an empty string): no identify and no circuit-relay reservation, while the same code works in Node, browsers and React Native.

    Suggested fix

    const bytes = ArrayBuffer.isView(input)
    	? new Uint8Array(input.buffer, input.byteOffset, input.byteLength)
    	: new Uint8Array(input);

    Environment: @nativescript/core 8.9.9 (the same code is in 9.1.3 / main), NativeScript Android runtime 8.9.2, V8 10.3, Galaxy S7 (Android 8).

    Workaround until it is fixed — wrap decode so views are copied first:

    const original = TextDecoder.prototype.decode;
    TextDecoder.prototype.decode = function (input, options) {
      if (input && ArrayBuffer.isView(input) && (input.byteOffset !== 0 || input.byteLength !== input.buffer.byteLength)) {
        input = new Uint8Array(input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength));
      }
      return original.call(this, input, options);
    };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions