syntax-detection.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /**
  2. * 浏览器兼容性,特性检查
  3. * 参考列表: http://kangax.github.io/compat-table/es6/
  4. * 同内核的不同的浏览器需要处理,比如qq浏览器登陆成功后,ie浏览器登陆页面会自动跳转到项目管理页面。因此项目管理页面也需要检测
  5. */
  6. function checkSyntax() {
  7. 'use strict';
  8. try {
  9. // 一些在词法、语法分析阶段就会报错的代码,必须要用window.Function或者eval包裹,否则直接报错且无法被捕获
  10. // 不使用eval的原因:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval
  11. if (typeof window.Function === 'undefined') {
  12. return false;
  13. }
  14. // 声明
  15. Function('let a = 1;')();
  16. Function('const b = 1;')();
  17. Function('class A {}')();
  18. // 模板字符串
  19. Function('var a = 1; var str = `${a}`;')();
  20. // 对象简单表示
  21. Function("var foo = 'foo'; var simple = { foo, t() {} };")();
  22. // 对象属性表示
  23. Function("var attr = 'a'; var obj = {[attr]: 1}")();
  24. // 对象super
  25. Function('var proto = { p: 1 }; var obj = { superF() { return super.p } }; Object.setPrototypeOf(obj, proto)')();
  26. // 对象getter setter
  27. Function('var tObj = { get a() {}, set a(v) {} }')();
  28. // 扩展运算符
  29. Function('var obj = { foo: 1 }; var obj1 = { ...obj }; var arr = [1]; var arr1 = [...arr];')();
  30. // 解构
  31. Function('var obj = { foo: 1 }; var { foo } = obj; var arr = [1]; var [one] = arr;')();
  32. // 可选链 ?. es2020
  33. //Function('var obj = { a: { b: 1 } }; obj?.a?.b')();
  34. // of迭代
  35. Function('for (var i of [1]) {}')();
  36. // 默认参数
  37. Function('function defaultParams(a = 1) {}')();
  38. // rest参数
  39. Function('function restParams(...args) {}')();
  40. // arrow function
  41. Function('var arrowF = () => {};')();
  42. // generator function
  43. Function('function* gen() {}')();
  44. // async function es2017
  45. Function('async function tAsync() {}')();
  46. // Symbol Promise Set Map Proxy Reflect
  47. if (typeof Symbol === 'undefined' ||
  48. typeof Promise === 'undefined' ||
  49. typeof Set === 'undefined' ||
  50. typeof Map === 'undefined' ||
  51. typeof Proxy === 'undefined' ||
  52. typeof Reflect === 'undefined') {
  53. return false;
  54. }
  55. // buffer相关
  56. if (typeof ArrayBuffer === 'undefined' ||
  57. typeof Uint8Array === 'undefined' ||
  58. typeof DataView === 'undefined') {
  59. return false;
  60. }
  61. // 部分字符串方法
  62. var stringPrototypeFuncs = [
  63. 'includes',
  64. 'codePointAt',
  65. 'normalize',
  66. 'repeat',
  67. //'matchAll', es2020
  68. 'padStart',
  69. 'padEnd',
  70. //'trimStart', es2019
  71. //'trimEnd'
  72. ];
  73. var stringStaticFuncs = [
  74. 'fromCodePoint',
  75. 'raw'
  76. ];
  77. for (var i = 0; i < stringPrototypeFuncs.length; i++) {
  78. var f = stringPrototypeFuncs[i];
  79. if (!String.prototype[f]) {
  80. throw new SyntaxError('String.prototype ' + f);
  81. }
  82. }
  83. for (var i = 0; i < stringStaticFuncs.length; i++) {
  84. var f = stringStaticFuncs[i];
  85. if (!String[f]) {
  86. throw new SyntaxError('String ' + f);
  87. }
  88. }
  89. // 部分数组方法
  90. var arrayPrototypeFuncs = [
  91. 'find',
  92. 'findIndex',
  93. 'fill',
  94. 'keys',
  95. 'values',
  96. 'entries',
  97. //'flat', // es2019
  98. //'flatMap',
  99. 'includes'
  100. ];
  101. var arrayStaticFuncs = [
  102. 'from',
  103. 'of'
  104. ];
  105. for (var i = 0; i < arrayPrototypeFuncs.length; i++) {
  106. var f = arrayPrototypeFuncs[i];
  107. if (!Array.prototype[f]) {
  108. throw new SyntaxError('Array.prototyp ' + f);
  109. }
  110. }
  111. for (var i = 0; i < arrayStaticFuncs.length; i++) {
  112. var f = arrayStaticFuncs[i];
  113. if (!Array[f]) {
  114. throw new SyntaxError('Array ' + f);
  115. }
  116. }
  117. // 对象部分方法
  118. var objectStaticFuncs = [
  119. 'is',
  120. 'assign',
  121. 'getOwnPropertyDescriptors',
  122. 'setPrototypeOf',
  123. 'values',
  124. 'entries',
  125. //'fromEntries' // es2020
  126. ];
  127. for (var i = 0; i < objectStaticFuncs.length; i++) {
  128. var f = objectStaticFuncs[i];
  129. if (!Object[f]) {
  130. throw new SyntaxError('Object ' + f);
  131. }
  132. }
  133. // DOM
  134. if (typeof document.documentElement.requestFullscreen !== 'function') {
  135. throw new TypeError('document.documentElement.requestFullscreen is not a function');
  136. }
  137. } catch (err) {
  138. console.log(err);
  139. return false;
  140. }
  141. return true;
  142. }
  143. function showBrowserTip() {
  144. var html = '<div class="modal fade" id="browser" data-backdrop="static">' +
  145. '<div class="modal-dialog modal-lg" role="document">' +
  146. '<div class="modal-content">' +
  147. '<div class="modal-body">' +
  148. '<h5>浏览器版本过低,可能会有安全风险;</h5>' +
  149. '<h5>请更新 「浏览器」 或者 使用 「纵横Z+造价工作平台」 登录。</h5>' +
  150. '<div class="row my-4">' +
  151. '<div class="col-6">' +
  152. '<div class="text-center"><a href="https://www.microsoft.com/zh-cn/edge" class="btn btn-primary" target="_blank">下载 Microsoft Edge</a></div>' +
  153. '</div>' +
  154. '<div class="col-6">' +
  155. '<div class="text-center"><a href="https://smartcost.com.cn/downloadzplus" class="btn btn-primary" target="_blank">下载 纵横Z+造价工作平台</a></div>' +
  156. '</div></div></div></div></div></div>';
  157. $('body').append(html);
  158. $('#browser').modal('show');
  159. }
  160. $(document).ready(function () {
  161. // 浏览器兼容性
  162. var isCompat = checkSyntax();
  163. if (!isCompat) {
  164. $('#inputEmail').blur();
  165. showBrowserTip();
  166. return false;
  167. }
  168. });