plugin-babel-cached.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /* Copyright 2017 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. /* eslint-disable no-var */
  16. var babel = require("plugin-babel");
  17. var cacheExpiration = 60 /* min */ * 60 * 1000;
  18. var dbVersion = 1;
  19. var dbName = "babelcache";
  20. var dbCacheTable = "translated";
  21. var dbPromise;
  22. function getDb() {
  23. if (!dbPromise) {
  24. dbPromise = new Promise(function (resolve, reject) {
  25. var request = indexedDB.open(dbName, dbVersion);
  26. request.onupgradeneeded = function () {
  27. var db = request.result;
  28. db.createObjectStore(dbCacheTable, { keyPath: "address" });
  29. };
  30. request.onsuccess = function () {
  31. var db = request.result;
  32. resolve(db);
  33. };
  34. request.onerror = function () {
  35. console.warn("getDb: " + request.error);
  36. reject(request.error);
  37. };
  38. });
  39. }
  40. return dbPromise;
  41. }
  42. function storeCache(address, hashCode, translated, format, sourceMap) {
  43. return getDb().then(function (db) {
  44. var tx = db.transaction(dbCacheTable, "readwrite");
  45. var store = tx.objectStore(dbCacheTable);
  46. store.put({
  47. address,
  48. hashCode,
  49. translated,
  50. expires: Date.now() + cacheExpiration,
  51. format,
  52. sourceMap,
  53. });
  54. return new Promise(function (resolve, reject) {
  55. tx.oncomplete = function () {
  56. resolve();
  57. };
  58. tx.onerror = function () {
  59. resolve();
  60. };
  61. });
  62. });
  63. }
  64. function loadCache(address, hashCode) {
  65. return getDb().then(function (db) {
  66. var tx = db.transaction(dbCacheTable, "readonly");
  67. var store = tx.objectStore(dbCacheTable);
  68. var getAddress = store.get(address);
  69. return new Promise(function (resolve, reject) {
  70. tx.oncomplete = function () {
  71. var found = getAddress.result;
  72. var isValid =
  73. found && found.hashCode === hashCode && Date.now() < found.expires;
  74. resolve(
  75. isValid
  76. ? {
  77. translated: found.translated,
  78. format: found.format,
  79. sourceMap: found.sourceMap,
  80. }
  81. : null
  82. );
  83. };
  84. tx.onerror = function () {
  85. resolve(null);
  86. };
  87. });
  88. });
  89. }
  90. var encoder = new TextEncoder("utf-8");
  91. function sha256(str) {
  92. var buffer = encoder.encode(str);
  93. return crypto.subtle.digest("SHA-256", buffer).then(function (hash) {
  94. var data = new Int32Array(hash);
  95. return (
  96. data[0].toString(36) +
  97. "-" +
  98. data[1].toString(36) +
  99. "-" +
  100. data[2].toString(36) +
  101. "-" +
  102. data[3].toString(36)
  103. );
  104. });
  105. }
  106. exports.translate = function (load, opt) {
  107. var savedHashCode, babelTranslateError;
  108. return sha256(load.source)
  109. .then(function (hashCode) {
  110. savedHashCode = hashCode;
  111. return loadCache(load.address, hashCode);
  112. })
  113. .then(
  114. function (cache) {
  115. if (cache) {
  116. load.metadata.format = cache.format;
  117. return cache.translated;
  118. }
  119. return babel.translate.call(this, load, opt).then(
  120. function (translated) {
  121. return storeCache(
  122. load.address,
  123. savedHashCode,
  124. translated,
  125. load.metadata.format,
  126. load.metadata.sourceMap
  127. ).then(function () {
  128. return translated;
  129. });
  130. },
  131. function (reason) {
  132. throw (babelTranslateError = reason);
  133. }
  134. );
  135. }.bind(this)
  136. )
  137. .catch(
  138. function (reason) {
  139. if (babelTranslateError) {
  140. throw babelTranslateError;
  141. }
  142. return babel.translate.call(this, load, opt);
  143. }.bind(this)
  144. );
  145. };