<commit_before>import { alias, bool } from '@ember/object/computed';
import Service from '@ember/service';

import { task } from 'ember-concurrency';

import { ignoreCancellation } from '../utils/concurrency';

export default class GoogleChartsService extends Service {
  @alias('loadTask.lastSuccessful.value') visualization;
  @bool('visualization') loaded;

  async load() {
    await this.loadTask.perform().catch(ignoreCancellation);
  }

  @(task(function* () {
    let api = yield loadJsApi();
    yield loadCoreChart(api);
    return api.visualization;
  }).keepLatest())
  loadTask;
}

async function loadScript(src) {
  await new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = src;
    script.onload = resolve;
    script.onerror = reject;
    document.body.appendChild(script);
  });
}

async function loadJsApi() {
  if (!window.google) {
    await loadScript('https://www.google.com/jsapi');<commit_msg>services/google-charts: Ensure that `loadScript()` rejects with an `Error` instance<commit_after>import { alias, bool } from '@ember/object/computed';
import Service from '@ember/service';

import { task } from 'ember-concurrency';

import { ignoreCancellation } from '../utils/concurrency';

export default class GoogleChartsService extends Service {
  @alias('loadTask.lastSuccessful.value') visualization;
  @bool('visualization') loaded;

  async load() {
    await this.loadTask.perform().catch(ignoreCancellation);
  }

  @(task(function* () {
    let api = yield loadJsApi();
    yield loadCoreChart(api);
    return api.visualization;
  }).keepLatest())
  loadTask;
}

async function loadScript(src) {
  await new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = src;
    script.onload = resolve;
    script.onerror = event => {
      reject(new ExternalScriptError(event.target.src));
    };
    document.body.appendChild(script);
  });
}

class ExternalScriptError extends Error {
  constructor(url) {
    let message = `Failed to load script at ${url}`;
    super(message);
    this.name = 'ExternalScriptError';
    this.url = url;
  }
}

async function loadJsApi() {
  if (!window.google) {
    await loadScript('https://www.google.com/jsapi');
{'fraction_non_alphanumeric': 0.13953488372093023, 'fraction_numerical': 0.0, 'mean_word_length': 4.158371040723982, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 6, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '749556', 'n_tokens_mistral': 684, 'n_tokens_neox': 676, 'n_words': 159}