TextDecoder.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. "use strict";
  2. const conversions = require("webidl-conversions");
  3. const utils = require("./utils.js");
  4. const TextDecoderOptions = require("./TextDecoderOptions.js");
  5. const TextDecodeOptions = require("./TextDecodeOptions.js");
  6. const implSymbol = utils.implSymbol;
  7. const ctorRegistrySymbol = utils.ctorRegistrySymbol;
  8. const interfaceName = "TextDecoder";
  9. exports.is = value => {
  10. return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
  11. };
  12. exports.isImpl = value => {
  13. return utils.isObject(value) && value instanceof Impl.implementation;
  14. };
  15. exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
  16. if (exports.is(value)) {
  17. return utils.implForWrapper(value);
  18. }
  19. throw new globalObject.TypeError(`${context} is not of type 'TextDecoder'.`);
  20. };
  21. function makeWrapper(globalObject, newTarget) {
  22. let proto;
  23. if (newTarget !== undefined) {
  24. proto = newTarget.prototype;
  25. }
  26. if (!utils.isObject(proto)) {
  27. proto = globalObject[ctorRegistrySymbol]["TextDecoder"].prototype;
  28. }
  29. return Object.create(proto);
  30. }
  31. exports.create = (globalObject, constructorArgs, privateData) => {
  32. const wrapper = makeWrapper(globalObject);
  33. return exports.setup(wrapper, globalObject, constructorArgs, privateData);
  34. };
  35. exports.createImpl = (globalObject, constructorArgs, privateData) => {
  36. const wrapper = exports.create(globalObject, constructorArgs, privateData);
  37. return utils.implForWrapper(wrapper);
  38. };
  39. exports._internalSetup = (wrapper, globalObject) => {};
  40. exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
  41. privateData.wrapper = wrapper;
  42. exports._internalSetup(wrapper, globalObject);
  43. Object.defineProperty(wrapper, implSymbol, {
  44. value: new Impl.implementation(globalObject, constructorArgs, privateData),
  45. configurable: true
  46. });
  47. wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
  48. if (Impl.init) {
  49. Impl.init(wrapper[implSymbol]);
  50. }
  51. return wrapper;
  52. };
  53. exports.new = (globalObject, newTarget) => {
  54. const wrapper = makeWrapper(globalObject, newTarget);
  55. exports._internalSetup(wrapper, globalObject);
  56. Object.defineProperty(wrapper, implSymbol, {
  57. value: Object.create(Impl.implementation.prototype),
  58. configurable: true
  59. });
  60. wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
  61. if (Impl.init) {
  62. Impl.init(wrapper[implSymbol]);
  63. }
  64. return wrapper[implSymbol];
  65. };
  66. const exposed = new Set(["Window"]);
  67. exports.install = (globalObject, globalNames) => {
  68. if (!globalNames.some(globalName => exposed.has(globalName))) {
  69. return;
  70. }
  71. const ctorRegistry = utils.initCtorRegistry(globalObject);
  72. class TextDecoder {
  73. constructor() {
  74. const args = [];
  75. {
  76. let curArg = arguments[0];
  77. if (curArg !== undefined) {
  78. curArg = conversions["DOMString"](curArg, {
  79. context: "Failed to construct 'TextDecoder': parameter 1",
  80. globals: globalObject
  81. });
  82. } else {
  83. curArg = "utf-8";
  84. }
  85. args.push(curArg);
  86. }
  87. {
  88. let curArg = arguments[1];
  89. curArg = TextDecoderOptions.convert(globalObject, curArg, {
  90. context: "Failed to construct 'TextDecoder': parameter 2"
  91. });
  92. args.push(curArg);
  93. }
  94. return exports.setup(Object.create(new.target.prototype), globalObject, args);
  95. }
  96. decode() {
  97. const esValue = this !== null && this !== undefined ? this : globalObject;
  98. if (!exports.is(esValue)) {
  99. throw new globalObject.TypeError("'decode' called on an object that is not a valid instance of TextDecoder.");
  100. }
  101. const args = [];
  102. {
  103. let curArg = arguments[0];
  104. if (curArg !== undefined) {
  105. if (utils.isArrayBuffer(curArg)) {
  106. curArg = conversions["ArrayBuffer"](curArg, {
  107. context: "Failed to execute 'decode' on 'TextDecoder': parameter 1",
  108. globals: globalObject
  109. });
  110. } else if (utils.isSharedArrayBuffer(curArg)) {
  111. curArg = conversions["SharedArrayBuffer"](curArg, {
  112. context: "Failed to execute 'decode' on 'TextDecoder': parameter 1",
  113. globals: globalObject
  114. });
  115. } else if (ArrayBuffer.isView(curArg)) {
  116. curArg = conversions["ArrayBufferView"](curArg, {
  117. context: "Failed to execute 'decode' on 'TextDecoder': parameter 1",
  118. globals: globalObject,
  119. allowShared: true
  120. });
  121. } else {
  122. throw new globalObject.TypeError(
  123. "Failed to execute 'decode' on 'TextDecoder': parameter 1" + " is not of any supported type."
  124. );
  125. }
  126. }
  127. args.push(curArg);
  128. }
  129. {
  130. let curArg = arguments[1];
  131. curArg = TextDecodeOptions.convert(globalObject, curArg, {
  132. context: "Failed to execute 'decode' on 'TextDecoder': parameter 2"
  133. });
  134. args.push(curArg);
  135. }
  136. return esValue[implSymbol].decode(...args);
  137. }
  138. get encoding() {
  139. const esValue = this !== null && this !== undefined ? this : globalObject;
  140. if (!exports.is(esValue)) {
  141. throw new globalObject.TypeError(
  142. "'get encoding' called on an object that is not a valid instance of TextDecoder."
  143. );
  144. }
  145. return esValue[implSymbol]["encoding"];
  146. }
  147. get fatal() {
  148. const esValue = this !== null && this !== undefined ? this : globalObject;
  149. if (!exports.is(esValue)) {
  150. throw new globalObject.TypeError(
  151. "'get fatal' called on an object that is not a valid instance of TextDecoder."
  152. );
  153. }
  154. return esValue[implSymbol]["fatal"];
  155. }
  156. get ignoreBOM() {
  157. const esValue = this !== null && this !== undefined ? this : globalObject;
  158. if (!exports.is(esValue)) {
  159. throw new globalObject.TypeError(
  160. "'get ignoreBOM' called on an object that is not a valid instance of TextDecoder."
  161. );
  162. }
  163. return esValue[implSymbol]["ignoreBOM"];
  164. }
  165. }
  166. Object.defineProperties(TextDecoder.prototype, {
  167. decode: { enumerable: true },
  168. encoding: { enumerable: true },
  169. fatal: { enumerable: true },
  170. ignoreBOM: { enumerable: true },
  171. [Symbol.toStringTag]: { value: "TextDecoder", configurable: true }
  172. });
  173. ctorRegistry[interfaceName] = TextDecoder;
  174. Object.defineProperty(globalObject, interfaceName, {
  175. configurable: true,
  176. writable: true,
  177. value: TextDecoder
  178. });
  179. };
  180. const Impl = require("../../jsdom/living/encoding/TextDecoder-impl.js");