FileReader.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. "use strict";
  2. const conversions = require("webidl-conversions");
  3. const utils = require("./utils.js");
  4. const Blob = require("./Blob.js");
  5. const EventHandlerNonNull = require("./EventHandlerNonNull.js");
  6. const implSymbol = utils.implSymbol;
  7. const ctorRegistrySymbol = utils.ctorRegistrySymbol;
  8. const EventTarget = require("./EventTarget.js");
  9. const interfaceName = "FileReader";
  10. exports.is = value => {
  11. return utils.isObject(value) && Object.hasOwn(value, implSymbol) && value[implSymbol] instanceof Impl.implementation;
  12. };
  13. exports.isImpl = value => {
  14. return utils.isObject(value) && value instanceof Impl.implementation;
  15. };
  16. exports.convert = (globalObject, value, { context = "The provided value" } = {}) => {
  17. if (exports.is(value)) {
  18. return utils.implForWrapper(value);
  19. }
  20. throw new globalObject.TypeError(`${context} is not of type 'FileReader'.`);
  21. };
  22. function makeWrapper(globalObject, newTarget) {
  23. let proto;
  24. if (newTarget !== undefined) {
  25. proto = newTarget.prototype;
  26. }
  27. if (!utils.isObject(proto)) {
  28. proto = globalObject[ctorRegistrySymbol]["FileReader"].prototype;
  29. }
  30. return Object.create(proto);
  31. }
  32. exports.create = (globalObject, constructorArgs, privateData) => {
  33. const wrapper = makeWrapper(globalObject);
  34. return exports.setup(wrapper, globalObject, constructorArgs, privateData);
  35. };
  36. exports.createImpl = (globalObject, constructorArgs, privateData) => {
  37. const wrapper = exports.create(globalObject, constructorArgs, privateData);
  38. return utils.implForWrapper(wrapper);
  39. };
  40. exports._internalSetup = (wrapper, globalObject) => {
  41. EventTarget._internalSetup(wrapper, globalObject);
  42. };
  43. exports.setup = (wrapper, globalObject, constructorArgs = [], privateData = {}) => {
  44. privateData.wrapper = wrapper;
  45. exports._internalSetup(wrapper, globalObject);
  46. Object.defineProperty(wrapper, implSymbol, {
  47. value: new Impl.implementation(globalObject, constructorArgs, privateData),
  48. configurable: true
  49. });
  50. wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
  51. if (Impl.init) {
  52. Impl.init(wrapper[implSymbol]);
  53. }
  54. return wrapper;
  55. };
  56. exports.new = (globalObject, newTarget) => {
  57. const wrapper = makeWrapper(globalObject, newTarget);
  58. exports._internalSetup(wrapper, globalObject);
  59. Object.defineProperty(wrapper, implSymbol, {
  60. value: Object.create(Impl.implementation.prototype),
  61. configurable: true
  62. });
  63. wrapper[implSymbol][utils.wrapperSymbol] = wrapper;
  64. if (Impl.init) {
  65. Impl.init(wrapper[implSymbol]);
  66. }
  67. return wrapper[implSymbol];
  68. };
  69. const exposed = new Set(["Window", "Worker"]);
  70. exports.install = (globalObject, globalNames) => {
  71. if (!globalNames.some(globalName => exposed.has(globalName))) {
  72. return;
  73. }
  74. const ctorRegistry = utils.initCtorRegistry(globalObject);
  75. class FileReader extends globalObject.EventTarget {
  76. constructor() {
  77. return exports.setup(Object.create(new.target.prototype), globalObject, undefined);
  78. }
  79. readAsArrayBuffer(blob) {
  80. const esValue = this !== null && this !== undefined ? this : globalObject;
  81. if (!exports.is(esValue)) {
  82. throw new globalObject.TypeError(
  83. "'readAsArrayBuffer' called on an object that is not a valid instance of FileReader."
  84. );
  85. }
  86. if (arguments.length < 1) {
  87. throw new globalObject.TypeError(
  88. `Failed to execute 'readAsArrayBuffer' on 'FileReader': 1 argument required, but only ${arguments.length} present.`
  89. );
  90. }
  91. const args = [];
  92. {
  93. let curArg = arguments[0];
  94. curArg = Blob.convert(globalObject, curArg, {
  95. context: "Failed to execute 'readAsArrayBuffer' on 'FileReader': parameter 1"
  96. });
  97. args.push(curArg);
  98. }
  99. return esValue[implSymbol].readAsArrayBuffer(...args);
  100. }
  101. readAsBinaryString(blob) {
  102. const esValue = this !== null && this !== undefined ? this : globalObject;
  103. if (!exports.is(esValue)) {
  104. throw new globalObject.TypeError(
  105. "'readAsBinaryString' called on an object that is not a valid instance of FileReader."
  106. );
  107. }
  108. if (arguments.length < 1) {
  109. throw new globalObject.TypeError(
  110. `Failed to execute 'readAsBinaryString' on 'FileReader': 1 argument required, but only ${arguments.length} present.`
  111. );
  112. }
  113. const args = [];
  114. {
  115. let curArg = arguments[0];
  116. curArg = Blob.convert(globalObject, curArg, {
  117. context: "Failed to execute 'readAsBinaryString' on 'FileReader': parameter 1"
  118. });
  119. args.push(curArg);
  120. }
  121. return esValue[implSymbol].readAsBinaryString(...args);
  122. }
  123. readAsText(blob) {
  124. const esValue = this !== null && this !== undefined ? this : globalObject;
  125. if (!exports.is(esValue)) {
  126. throw new globalObject.TypeError(
  127. "'readAsText' called on an object that is not a valid instance of FileReader."
  128. );
  129. }
  130. if (arguments.length < 1) {
  131. throw new globalObject.TypeError(
  132. `Failed to execute 'readAsText' on 'FileReader': 1 argument required, but only ${arguments.length} present.`
  133. );
  134. }
  135. const args = [];
  136. {
  137. let curArg = arguments[0];
  138. curArg = Blob.convert(globalObject, curArg, {
  139. context: "Failed to execute 'readAsText' on 'FileReader': parameter 1"
  140. });
  141. args.push(curArg);
  142. }
  143. {
  144. let curArg = arguments[1];
  145. if (curArg !== undefined) {
  146. curArg = conversions["DOMString"](curArg, {
  147. context: "Failed to execute 'readAsText' on 'FileReader': parameter 2",
  148. globals: globalObject
  149. });
  150. }
  151. args.push(curArg);
  152. }
  153. return esValue[implSymbol].readAsText(...args);
  154. }
  155. readAsDataURL(blob) {
  156. const esValue = this !== null && this !== undefined ? this : globalObject;
  157. if (!exports.is(esValue)) {
  158. throw new globalObject.TypeError(
  159. "'readAsDataURL' called on an object that is not a valid instance of FileReader."
  160. );
  161. }
  162. if (arguments.length < 1) {
  163. throw new globalObject.TypeError(
  164. `Failed to execute 'readAsDataURL' on 'FileReader': 1 argument required, but only ${arguments.length} present.`
  165. );
  166. }
  167. const args = [];
  168. {
  169. let curArg = arguments[0];
  170. curArg = Blob.convert(globalObject, curArg, {
  171. context: "Failed to execute 'readAsDataURL' on 'FileReader': parameter 1"
  172. });
  173. args.push(curArg);
  174. }
  175. return esValue[implSymbol].readAsDataURL(...args);
  176. }
  177. abort() {
  178. const esValue = this !== null && this !== undefined ? this : globalObject;
  179. if (!exports.is(esValue)) {
  180. throw new globalObject.TypeError("'abort' called on an object that is not a valid instance of FileReader.");
  181. }
  182. return esValue[implSymbol].abort();
  183. }
  184. get readyState() {
  185. const esValue = this !== null && this !== undefined ? this : globalObject;
  186. if (!exports.is(esValue)) {
  187. throw new globalObject.TypeError(
  188. "'get readyState' called on an object that is not a valid instance of FileReader."
  189. );
  190. }
  191. return esValue[implSymbol]["readyState"];
  192. }
  193. get result() {
  194. const esValue = this !== null && this !== undefined ? this : globalObject;
  195. if (!exports.is(esValue)) {
  196. throw new globalObject.TypeError(
  197. "'get result' called on an object that is not a valid instance of FileReader."
  198. );
  199. }
  200. return utils.tryWrapperForImpl(esValue[implSymbol]["result"]);
  201. }
  202. get error() {
  203. const esValue = this !== null && this !== undefined ? this : globalObject;
  204. if (!exports.is(esValue)) {
  205. throw new globalObject.TypeError("'get error' called on an object that is not a valid instance of FileReader.");
  206. }
  207. return utils.tryWrapperForImpl(esValue[implSymbol]["error"]);
  208. }
  209. get onloadstart() {
  210. const esValue = this !== null && this !== undefined ? this : globalObject;
  211. if (!exports.is(esValue)) {
  212. throw new globalObject.TypeError(
  213. "'get onloadstart' called on an object that is not a valid instance of FileReader."
  214. );
  215. }
  216. return utils.tryWrapperForImpl(esValue[implSymbol]["onloadstart"]);
  217. }
  218. set onloadstart(V) {
  219. const esValue = this !== null && this !== undefined ? this : globalObject;
  220. if (!exports.is(esValue)) {
  221. throw new globalObject.TypeError(
  222. "'set onloadstart' called on an object that is not a valid instance of FileReader."
  223. );
  224. }
  225. if (!utils.isObject(V)) {
  226. V = null;
  227. } else {
  228. V = EventHandlerNonNull.convert(globalObject, V, {
  229. context: "Failed to set the 'onloadstart' property on 'FileReader': The provided value"
  230. });
  231. }
  232. esValue[implSymbol]["onloadstart"] = V;
  233. }
  234. get onprogress() {
  235. const esValue = this !== null && this !== undefined ? this : globalObject;
  236. if (!exports.is(esValue)) {
  237. throw new globalObject.TypeError(
  238. "'get onprogress' called on an object that is not a valid instance of FileReader."
  239. );
  240. }
  241. return utils.tryWrapperForImpl(esValue[implSymbol]["onprogress"]);
  242. }
  243. set onprogress(V) {
  244. const esValue = this !== null && this !== undefined ? this : globalObject;
  245. if (!exports.is(esValue)) {
  246. throw new globalObject.TypeError(
  247. "'set onprogress' called on an object that is not a valid instance of FileReader."
  248. );
  249. }
  250. if (!utils.isObject(V)) {
  251. V = null;
  252. } else {
  253. V = EventHandlerNonNull.convert(globalObject, V, {
  254. context: "Failed to set the 'onprogress' property on 'FileReader': The provided value"
  255. });
  256. }
  257. esValue[implSymbol]["onprogress"] = V;
  258. }
  259. get onload() {
  260. const esValue = this !== null && this !== undefined ? this : globalObject;
  261. if (!exports.is(esValue)) {
  262. throw new globalObject.TypeError(
  263. "'get onload' called on an object that is not a valid instance of FileReader."
  264. );
  265. }
  266. return utils.tryWrapperForImpl(esValue[implSymbol]["onload"]);
  267. }
  268. set onload(V) {
  269. const esValue = this !== null && this !== undefined ? this : globalObject;
  270. if (!exports.is(esValue)) {
  271. throw new globalObject.TypeError(
  272. "'set onload' called on an object that is not a valid instance of FileReader."
  273. );
  274. }
  275. if (!utils.isObject(V)) {
  276. V = null;
  277. } else {
  278. V = EventHandlerNonNull.convert(globalObject, V, {
  279. context: "Failed to set the 'onload' property on 'FileReader': The provided value"
  280. });
  281. }
  282. esValue[implSymbol]["onload"] = V;
  283. }
  284. get onabort() {
  285. const esValue = this !== null && this !== undefined ? this : globalObject;
  286. if (!exports.is(esValue)) {
  287. throw new globalObject.TypeError(
  288. "'get onabort' called on an object that is not a valid instance of FileReader."
  289. );
  290. }
  291. return utils.tryWrapperForImpl(esValue[implSymbol]["onabort"]);
  292. }
  293. set onabort(V) {
  294. const esValue = this !== null && this !== undefined ? this : globalObject;
  295. if (!exports.is(esValue)) {
  296. throw new globalObject.TypeError(
  297. "'set onabort' called on an object that is not a valid instance of FileReader."
  298. );
  299. }
  300. if (!utils.isObject(V)) {
  301. V = null;
  302. } else {
  303. V = EventHandlerNonNull.convert(globalObject, V, {
  304. context: "Failed to set the 'onabort' property on 'FileReader': The provided value"
  305. });
  306. }
  307. esValue[implSymbol]["onabort"] = V;
  308. }
  309. get onerror() {
  310. const esValue = this !== null && this !== undefined ? this : globalObject;
  311. if (!exports.is(esValue)) {
  312. throw new globalObject.TypeError(
  313. "'get onerror' called on an object that is not a valid instance of FileReader."
  314. );
  315. }
  316. return utils.tryWrapperForImpl(esValue[implSymbol]["onerror"]);
  317. }
  318. set onerror(V) {
  319. const esValue = this !== null && this !== undefined ? this : globalObject;
  320. if (!exports.is(esValue)) {
  321. throw new globalObject.TypeError(
  322. "'set onerror' called on an object that is not a valid instance of FileReader."
  323. );
  324. }
  325. if (!utils.isObject(V)) {
  326. V = null;
  327. } else {
  328. V = EventHandlerNonNull.convert(globalObject, V, {
  329. context: "Failed to set the 'onerror' property on 'FileReader': The provided value"
  330. });
  331. }
  332. esValue[implSymbol]["onerror"] = V;
  333. }
  334. get onloadend() {
  335. const esValue = this !== null && this !== undefined ? this : globalObject;
  336. if (!exports.is(esValue)) {
  337. throw new globalObject.TypeError(
  338. "'get onloadend' called on an object that is not a valid instance of FileReader."
  339. );
  340. }
  341. return utils.tryWrapperForImpl(esValue[implSymbol]["onloadend"]);
  342. }
  343. set onloadend(V) {
  344. const esValue = this !== null && this !== undefined ? this : globalObject;
  345. if (!exports.is(esValue)) {
  346. throw new globalObject.TypeError(
  347. "'set onloadend' called on an object that is not a valid instance of FileReader."
  348. );
  349. }
  350. if (!utils.isObject(V)) {
  351. V = null;
  352. } else {
  353. V = EventHandlerNonNull.convert(globalObject, V, {
  354. context: "Failed to set the 'onloadend' property on 'FileReader': The provided value"
  355. });
  356. }
  357. esValue[implSymbol]["onloadend"] = V;
  358. }
  359. }
  360. Object.defineProperties(FileReader.prototype, {
  361. readAsArrayBuffer: { enumerable: true },
  362. readAsBinaryString: { enumerable: true },
  363. readAsText: { enumerable: true },
  364. readAsDataURL: { enumerable: true },
  365. abort: { enumerable: true },
  366. readyState: { enumerable: true },
  367. result: { enumerable: true },
  368. error: { enumerable: true },
  369. onloadstart: { enumerable: true },
  370. onprogress: { enumerable: true },
  371. onload: { enumerable: true },
  372. onabort: { enumerable: true },
  373. onerror: { enumerable: true },
  374. onloadend: { enumerable: true },
  375. [Symbol.toStringTag]: { value: "FileReader", configurable: true },
  376. EMPTY: { value: 0, enumerable: true },
  377. LOADING: { value: 1, enumerable: true },
  378. DONE: { value: 2, enumerable: true }
  379. });
  380. Object.defineProperties(FileReader, {
  381. EMPTY: { value: 0, enumerable: true },
  382. LOADING: { value: 1, enumerable: true },
  383. DONE: { value: 2, enumerable: true }
  384. });
  385. ctorRegistry[interfaceName] = FileReader;
  386. Object.defineProperty(globalObject, interfaceName, {
  387. configurable: true,
  388. writable: true,
  389. value: FileReader
  390. });
  391. };
  392. const Impl = require("../../jsdom/living/file-api/FileReader-impl.js");