1/*
2 * Copyright 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18import { IS_LOG, IS_PROFILE } from './flags';
19
20export function log(message: string, ...args: any[]) {
21  if (IS_LOG) {
22    let length = args ? args.length : 0;
23    if (length > 0) {
24      console.log(message, ...args);
25    } else {
26      console.log(message);
27    }
28  }
29};
30
31export function logError(message: string, ...args: any[]) {
32  let length = args ? args.length : 0;
33  if (length > 0) {
34    console.error(message, ...args);
35  } else {
36    console.error(message);
37  }
38};
39
40// check to see if native support for profiling is available.
41const NATIVE_PROFILE_SUPPORT =
42  typeof window !== 'undefined' && !!window.performance && !!console.profile;
43
44/**
45 * A decorator that can profile a function.
46 */
47export function profile(
48  target: any, propertyKey: string, descriptor: PropertyDescriptor) {
49  if (IS_PROFILE) {
50    return performProfile(target, propertyKey, descriptor);
51  } else {
52    // return as-is
53    return descriptor;
54  }
55}
56
57function performProfile(
58  target: any, propertyKey: string,
59  descriptor: PropertyDescriptor): PropertyDescriptor {
60  let originalCallable = descriptor.value;
61  // name must exist
62  let name = originalCallable.name;
63  if (!name) {
64    name = 'anonymous function';
65  }
66  if (NATIVE_PROFILE_SUPPORT) {
67    descriptor.value = function (...args: any[]) {
68      console.profile(name);
69      let startTime = window.performance.now();
70      let result = originalCallable.call(this || window, ...args);
71      let duration = window.performance.now() - startTime;
72      console.log(`${name} took ${duration} ms`);
73      console.profileEnd();
74      return result;
75    };
76  } else {
77    descriptor.value = function (...args: any[]) {
78      log(`Profile start ${name}`);
79      let start = Date.now();
80      let result = originalCallable.call(this || window, ...args);
81      let duration = Date.now() - start;
82      log(`Profile end ${name} took ${duration} ms.`);
83      return result;
84    };
85  }
86  return descriptor;
87}
88