diff --git a/core/includes/common.inc b/core/includes/common.inc
index 0099008..7855022 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -2474,7 +2474,7 @@ function drupal_pre_render_scripts($elements) {
  *   FALSE if there were any missing library dependencies; TRUE if all library
  *   dependencies were met.
  *
- * @see drupal_add_library()
+ * @see _drupal_add_library()
  * @see _drupal_add_js()
  * @see _drupal_add_css()
  * @see drupal_render()
@@ -2490,7 +2490,7 @@ function drupal_process_attached($elements, $dependency_check = FALSE) {
   // Add the libraries first.
   $success = TRUE;
   foreach ($elements['#attached']['library'] as $library) {
-    if (drupal_add_library($library[0], $library[1]) === FALSE) {
+    if (_drupal_add_library($library[0], $library[1]) === FALSE) {
       $success = FALSE;
       // Exit if the dependency is missing.
       if ($dependency_check) {
@@ -2692,7 +2692,7 @@ function drupal_process_states(&$elements) {
  * @see hook_library_info()
  * @see hook_library_info_alter()
  */
-function drupal_add_library($module, $name, $every_page = NULL) {
+function _drupal_add_library($module, $name, $every_page = NULL) {
   $added = &drupal_static(__FUNCTION__, array());
 
   // Only process the library if it exists and it was not added already.
@@ -2752,7 +2752,7 @@ function drupal_add_library($module, $name, $every_page = NULL) {
  *   or FALSE if it does not exist. If no $name was passed, an associative array
  *   of libraries registered by $module is returned (which may be empty).
  *
- * @see drupal_add_library()
+ * @see _drupal_add_library()
  * @see hook_library_info()
  * @see hook_library_info_alter()
  *
diff --git a/core/includes/form.inc b/core/includes/form.inc
index 87f8edf..c53912c 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -1566,7 +1566,8 @@ function theme_tableselect($variables) {
     // checkboxes/radios in the first table column.
     if ($element['#js_select']) {
       // Add a "Select all" checkbox.
-      drupal_add_library('system', 'drupal.tableselect');
+      $attached['#attached']['library'][] = array('system', 'drupal.tableselect');
+      drupal_render($attached);
       array_unshift($header, array('class' => array('select-all')));
     }
     else {
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 46113c6..ec208ef 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1558,7 +1558,8 @@ function theme_table($variables) {
 
   // Add sticky headers, if applicable.
   if (count($header) && $sticky) {
-    drupal_add_library('system', 'drupal.tableheader');
+    $attached['#attached']['library'][] = array('system', 'drupal.tableheader');
+    drupal_render($attached);
     // Add 'sticky-enabled' class to the table to identify it for JS.
     // This is needed to target tables constructed by this function.
     $attributes['class'][] = 'sticky-enabled';
@@ -1567,7 +1568,8 @@ function theme_table($variables) {
   // with the classes represented by the constants RESPONSIVE_PRIORITY_MEDIUM
   // and RESPONSIVE_PRIORITY_LOW, add the tableresponsive behaviors.
   if (count($header) && $responsive) {
-    drupal_add_library('system', 'drupal.tableresponsive');
+    $attached['#attached']['library'][] = array('system', 'drupal.tableresponsive');
+    drupal_render($attached);
     // Add 'responsive-enabled' class to the table to identify it for JS.
     // This is needed to target tables constructed by this function.
     $attributes['class'][] = 'responsive-enabled';
@@ -2160,7 +2162,8 @@ function template_preprocess_html(&$variables) {
     drupal_add_html_head($element, $name);
   }
 
-  drupal_add_library('system', 'html5shiv', TRUE);
+  $attached['#attached']['library'][] = array('system', 'html5shiv');
+  drupal_render($attached);
 
   $variables['page_top'][] = array('#markup' => $page->getBodyTop());
   $variables['page_bottom'][] = array('#markup' => $page->getBodyBottom());
diff --git a/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php b/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php
index 45115df..2f09464 100644
--- a/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php
+++ b/core/lib/Drupal/Core/Ajax/OpenDialogCommand.php
@@ -124,7 +124,9 @@ public function setDialogTitle($title) {
    */
   public function render() {
     // Add the library for handling the dialog in the response.
-    drupal_add_library('system', 'drupal.dialog.ajax');
+    $attached['#attached']['library'][] = array('system', 'drupal.dialog.ajax');
+    drupal_render($attached);
+
 
     // For consistency ensure the modal option is set to TRUE or FALSE.
     $this->dialogOptions['modal'] = isset($this->dialogOptions['modal']) && $this->dialogOptions['modal'];
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php
index d77fdc2..c0ceb05 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleExportTest.php
@@ -121,9 +121,9 @@ function testExportTranslation() {
    * Test exportation of translation template file.
    */
   function testExportTranslationTemplateFile() {
-    // Load an admin page with JavaScript so drupal_add_library() fires at least
-    // once and _locale_parse_js_file() gets to run at least once so that the
-    // locales_source table gets populated with something.
+    // Load an admin page with JavaScript so _drupal_add_library() fires at
+    // least once and _locale_parse_js_file() gets to run at least once so that
+    // the locales_source table gets populated with something.
     $this->drupalGet('admin/config/regional/language');
     // Get the translation template file.
     $this->drupalPostForm('admin/config/regional/translate/export', array(), t('Export'));
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php
index 912d657..4344441 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleLibraryInfoAlterTest.php
@@ -36,7 +36,8 @@ public static function getInfo() {
      * @see locale_library_info_alter()
      */
   public function testLibraryInfoAlter() {
-    drupal_add_library('system', 'jquery.ui.datepicker');
+    $attached['#attached']['library'][] = array('system', 'jquery.ui.datepicker');
+    drupal_render($attached);
     $scripts = drupal_get_js();
     $this->assertTrue(strpos($scripts, 'locale.datepicker.js'), 'locale.datepicker.js added to scripts.');
   }
diff --git a/core/modules/simpletest/simpletest.theme.inc b/core/modules/simpletest/simpletest.theme.inc
index 1743b74..072ac65 100644
--- a/core/modules/simpletest/simpletest.theme.inc
+++ b/core/modules/simpletest/simpletest.theme.inc
@@ -17,8 +17,6 @@
 function theme_simpletest_test_table($variables) {
   $table = $variables['table'];
 
-  drupal_add_library('simpletest', 'drupal.simpletest');
-
   // Create header for test selection table.
   $header = array(
     array('class' => array('select-all')),
@@ -133,6 +131,7 @@ function theme_simpletest_test_table($variables) {
 
   // Add js array of settings.
   $attached = array();
+  $attached['#attached']['library'][] = array('simpletest', 'drupal.simpletest');
   $attached['#attached']['js'][] = array(
     'data' => array('simpleTest' => $js),
     'type' => 'setting',
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
index 2e529e4..360b153 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/JavaScriptTest.php
@@ -47,9 +47,8 @@ function setUp() {
     $config->set('js.preprocess', 0);
     $config->save();
 
-    // Reset _drupal_add_js() and drupal_add_library() statics before each test.
+    // Reset _drupal_add_js() statics before each test.
     drupal_static_reset('_drupal_add_js');
-    drupal_static_reset('drupal_add_library');
   }
 
   function tearDown() {
@@ -71,7 +70,9 @@ function testDefault() {
    * Tests adding a JavaScript file.
    */
   function testAddFile() {
-    $javascript = _drupal_add_js('core/misc/collapse.js');
+    $attached['#attached']['js']['core/misc/collapse.js'] = array();
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertTrue(array_key_exists('core/misc/collapse.js', $javascript), 'JavaScript files are correctly added.');
   }
 
@@ -80,7 +81,8 @@ function testAddFile() {
    */
   function testAddSetting() {
     // Add a file in order to test default settings.
-    drupal_add_library('system', 'drupalSettings');
+    $attached['#attached']['library'][] = array('system', 'drupalSettings');
+    drupal_render($attached);
     $javascript = _drupal_add_js();
     $last_settings = reset($javascript['settings']['data']);
     $this->assertTrue(array_key_exists('currentPath', $last_settings), 'The current path JavaScript setting is set correctly.');
@@ -95,8 +97,9 @@ function testAddSetting() {
    * Tests adding an external JavaScript File.
    */
   function testAddExternal() {
-    $path = 'http://example.com/script.js';
-    $javascript = _drupal_add_js($path, 'external');
+    $attached['#attached']['js']['http://example.com/script.js'] = array('type' => 'external');
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertTrue(array_key_exists('http://example.com/script.js', $javascript), 'Added an external JavaScript file.');
   }
 
@@ -106,12 +109,18 @@ function testAddExternal() {
   function testAttributes() {
     $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
 
-    drupal_add_library('system', 'drupal');
-    _drupal_add_js('http://example.com/script.js', array('attributes' => array('defer' => 'defer')));
-    _drupal_add_js('core/misc/collapse.js', array('attributes' => array('defer' => 'defer')));
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js']['http://example.com/script.js'] = array(
+      'type' => 'external',
+      'attributes' => array('defer' => 'defer'),
+    );
+    $attached['#attached']['js']['core/misc/collapse.js'] = array(
+      'attributes' => array('defer' => 'defer'),
+    );
+    drupal_render($attached);
     $javascript = drupal_get_js();
 
-    $expected_1 = '<script src="http://example.com/script.js?' . $default_query_string . '" defer="defer"></script>';
+    $expected_1 = '<script src="http://example.com/script.js" defer="defer"></script>';
     $expected_2 = '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '" defer="defer"></script>';
 
     $this->assertTrue(strpos($javascript, $expected_1) > 0, 'Rendered external JavaScript with correct defer attribute.');
@@ -127,12 +136,18 @@ function testAggregatedAttributes() {
 
     $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
 
-    drupal_add_library('system', 'drupal');
-    _drupal_add_js('http://example.com/script.js', array('attributes' => array('defer' => 'defer')));
-    _drupal_add_js('core/misc/collapse.js', array('attributes' => array('defer' => 'defer')));
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js']['http://example.com/script.js'] = array(
+      'type' => 'external',
+      'attributes' => array('defer' => 'defer'),
+    );
+    $attached['#attached']['js']['core/misc/collapse.js'] = array(
+      'attributes' => array('defer' => 'defer'),
+    );
+    drupal_render($attached);
     $javascript = drupal_get_js();
 
-    $expected_1 = '<script src="http://example.com/script.js?' . $default_query_string . '" defer="defer"></script>';
+    $expected_1 = '<script src="http://example.com/script.js" defer="defer"></script>';
     $expected_2 = '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '" defer="defer"></script>';
 
     $this->assertTrue(strpos($javascript, $expected_1) > 0, 'Rendered external JavaScript with correct defer attribute with aggregation enabled.');
@@ -143,7 +158,9 @@ function testAggregatedAttributes() {
    * Tests drupal_get_js() for JavaScript settings.
    */
   function testHeaderSetting() {
-    drupal_add_library('system', 'drupalSettings');
+    $attached = array();
+    $attached['#attached']['library'][] = array('system', 'drupalSettings');
+    drupal_render($attached);
 
     $javascript = drupal_get_js('header');
     $this->assertTrue(strpos($javascript, 'basePath') > 0, 'Rendered JavaScript header returns basePath setting.');
@@ -152,25 +169,57 @@ function testHeaderSetting() {
     $this->assertTrue(strpos($javascript, 'currentPath') > 0, 'Rendered JavaScript header returns currentPath setting.');
 
     // Only the second of these two entries should appear in drupalSettings.
-    _drupal_add_js(array('commonTest' => 'commonTestShouldNotAppear'), 'setting');
-    _drupal_add_js(array('commonTest' => 'commonTestShouldAppear'), 'setting');
+    $attached = array();
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTest' => 'commonTestShouldNotAppear'),
+    );
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTest' => 'commonTestShouldAppear'),
+    );
     // Only the second of these entries should appear in drupalSettings.
-    _drupal_add_js(array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralOldValue')), 'setting');
-    _drupal_add_js(array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralNewValue')), 'setting');
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralOldValue')),
+    );
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestJsArrayLiteral' => array('commonTestJsArrayLiteralNewValue')),
+    );
     // Only the second of these two entries should appear in drupalSettings.
-    _drupal_add_js(array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralOldValue')), 'setting');
-    _drupal_add_js(array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralNewValue')), 'setting');
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralOldValue')),
+    );
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestJsObjectLiteral' => array('key' => 'commonTestJsObjectLiteralNewValue')),
+    );
     // Real world test case: multiple elements in a render array are adding the
     // same (or nearly the same) JavaScript settings. When merged, they should
     // contain all settings and not duplicate some settings.
     $settings_one = array('moduleName' => array('ui' => array('button A', 'button B'), 'magical flag' => 3.14159265359));
-    _drupal_add_js(array('commonTestRealWorldIdentical' => $settings_one), 'setting');
-    _drupal_add_js(array('commonTestRealWorldIdentical' => $settings_one), 'setting');
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestRealWorldIdentical' => $settings_one),
+    );
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestRealWorldIdentical' => $settings_one),
+    );
     $settings_two = array('moduleName' => array('ui' => array('button A', 'button B'), 'magical flag' => 3.14159265359, 'thingiesOnPage' => array('id1' => array())));
-    _drupal_add_js(array('commonTestRealWorldAlmostIdentical' => $settings_two), 'setting');
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestRealWorldAlmostIdentical' => $settings_two),
+    );
     $settings_two = array('moduleName' => array('ui' => array('button C', 'button D'), 'magical flag' => 3.14, 'thingiesOnPage' => array('id2' => array())));
-    _drupal_add_js(array('commonTestRealWorldAlmostIdentical' => $settings_two), 'setting');
+    $attached['#attached']['js'][] = array(
+      'type' => 'setting',
+      'data' => array('commonTestRealWorldAlmostIdentical' => $settings_two),
+    );
 
+    drupal_render($attached);
     $javascript = drupal_get_js('header');
 
     // Test whether _drupal_add_js can be used to override a previous setting.
@@ -205,8 +254,9 @@ function testHeaderSetting() {
    * Tests to see if resetting the JavaScript empties the cache.
    */
   function testReset() {
-    drupal_add_library('system', 'drupal');
-    _drupal_add_js('core/misc/collapse.js');
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js']['core/misc/collapse.js'] = array();
+    drupal_render($attached);
     drupal_static_reset('_drupal_add_js');
     $this->assertEqual(array(), _drupal_add_js(), 'Resetting the JavaScript correctly empties the cache.');
   }
@@ -215,9 +265,15 @@ function testReset() {
    * Tests adding inline scripts.
    */
   function testAddInline() {
-    drupal_add_library('system', 'jquery');
     $inline = 'jQuery(function () { });';
-    $javascript = _drupal_add_js($inline, array('type' => 'inline', 'scope' => 'footer'));
+    $attached['#attached']['library'][] = array('system', 'jquery');
+    $attached['#attached']['js'][] = array(
+      'type' => 'inline',
+      'data' => $inline,
+      'attributes' => array('defer' => 'defer'),
+    );
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertTrue(array_key_exists('core/assets/vendor/jquery/jquery.js', $javascript), 'jQuery is added when inline scripts are added.');
     $data = end($javascript);
     $this->assertEqual($inline, $data['data'], 'Inline JavaScript is correctly added to the footer.');
@@ -227,9 +283,14 @@ function testAddInline() {
    * Tests rendering an external JavaScript file.
    */
   function testRenderExternal() {
-    drupal_add_library('system', 'drupal');
     $external = 'http://example.com/example.js';
-    _drupal_add_js($external, 'external');
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js'][] = array(
+      'type' => 'external',
+      'data' => $external,
+    );
+    drupal_render($attached);
+
     $javascript = drupal_get_js();
     // Local files have a base_path() prefix, external files should not.
     $this->assertTrue(strpos($javascript, 'src="' . $external) > 0, 'Rendering an external JavaScript file.');
@@ -239,9 +300,16 @@ function testRenderExternal() {
    * Tests drupal_get_js() with a footer scope.
    */
   function testFooterHTML() {
-    drupal_add_library('system', 'drupal');
     $inline = 'jQuery(function () { });';
-    _drupal_add_js($inline, array('type' => 'inline', 'scope' => 'footer'));
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js'][] = array(
+      'type' => 'inline',
+      'data' => $inline,
+      'scope' => 'footer',
+      'attributes' => array('defer' => 'defer'),
+    );
+    drupal_render($attached);
+
     $javascript = drupal_get_js('footer');
     $this->assertTrue(strpos($javascript, $inline) > 0, 'Rendered JavaScript footer returns the inline code.');
   }
@@ -250,8 +318,10 @@ function testFooterHTML() {
    * Tests _drupal_add_js() sets preproccess to FALSE when cache is also FALSE.
    */
   function testNoCache() {
-    drupal_add_library('system', 'drupal');
-    $javascript = _drupal_add_js('core/misc/collapse.js', array('cache' => FALSE));
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('cache' => FALSE);
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertFalse($javascript['core/misc/collapse.js']['preprocess'], 'Setting cache to FALSE sets proprocess to FALSE when adding JavaScript.');
   }
 
@@ -259,8 +329,10 @@ function testNoCache() {
    * Tests adding a JavaScript file with a different group.
    */
   function testDifferentGroup() {
-    drupal_add_library('system', 'drupal');
-    $javascript = _drupal_add_js('core/misc/collapse.js', array('group' => JS_THEME));
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('group' => JS_THEME);
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertEqual($javascript['core/misc/collapse.js']['group'], JS_THEME, 'Adding a JavaScript file with a different group caches the given group.');
   }
 
@@ -268,7 +340,9 @@ function testDifferentGroup() {
    * Tests adding a JavaScript file with a different weight.
    */
   function testDifferentWeight() {
-    $javascript = _drupal_add_js('core/misc/collapse.js', array('weight' => 2));
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('weight' => 2);
+    drupal_render($attached);
+    $javascript = _drupal_add_js();
     $this->assertEqual($javascript['core/misc/collapse.js']['weight'], 2, 'Adding a JavaScript file with a different weight caches the given weight.');
   }
 
@@ -280,9 +354,16 @@ function testDifferentWeight() {
   function testBrowserConditionalComments() {
     $default_query_string = $this->container->get('state')->get('system.css_js_query_string') ?: '0';
 
-    drupal_add_library('system', 'drupal');
-    _drupal_add_js('core/misc/collapse.js', array('browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE)));
-    _drupal_add_js('jQuery(function () { });', array('type' => 'inline', 'browsers' => array('IE' => FALSE)));
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js']['core/misc/collapse.js'] = array(
+      'browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE),
+    );
+    $attached['#attached']['js'][] = array(
+      'type' => 'inline',
+      'data' => 'jQuery(function () { });',
+      'browsers' => array('IE' => FALSE),
+    );
+    drupal_render($attached);
     $javascript = drupal_get_js();
 
     $expected_1 = "<!--[if lte IE 8]>\n" . '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '"></script>' . "\n<![endif]-->";
@@ -296,9 +377,10 @@ function testBrowserConditionalComments() {
    * Tests JavaScript versioning.
    */
   function testVersionQueryString() {
-    drupal_add_library('system', 'drupal');
-    _drupal_add_js('core/misc/collapse.js', array('version' => 'foo'));
-    _drupal_add_js('core/misc/ajax.js', array('version' => 'bar'));
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('version' => 'foo');
+    $attached['#attached']['js']['core/misc/ajax.js'] = array('version' => 'bar');
+    drupal_render($attached);
     $javascript = drupal_get_js();
     $this->assertTrue(strpos($javascript, 'core/misc/collapse.js?v=foo') > 0 && strpos($javascript, 'core/misc/ajax.js?v=bar') > 0 , 'JavaScript version identifiers correctly appended to URLs');
   }
@@ -313,11 +395,13 @@ function testAggregation() {
     // ahead of ones without. The order of JavaScript execution must be the
     // same regardless of whether aggregation is enabled, so ensure this
     // expected order, first with aggregation off.
-    drupal_add_library('system', 'drupal');
-    _drupal_add_js('core/misc/ajax.js');
-    _drupal_add_js('core/misc/collapse.js', array('every_page' => TRUE));
-    _drupal_add_js('core/misc/autocomplete.js');
-    _drupal_add_js('core/misc/batch.js', array('every_page' => TRUE));
+    $attached = array();
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js']['core/misc/ajax.js'] = array();
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('every_page' => TRUE);
+    $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
+    $attached['#attached']['js']['core/misc/batch.js'] = array('every_page' => TRUE);
+    drupal_render($attached);
     $javascript = drupal_get_js();
     $expected = implode("\n", array(
       '<script src="' . file_create_url('core/misc/collapse.js') . '?' . $default_query_string . '"></script>',
@@ -333,11 +417,13 @@ function testAggregation() {
     $config = \Drupal::config('system.performance');
     $config->set('js.preprocess', 1);
     $config->save();
-    drupal_add_library('system', 'drupal');
-    _drupal_add_js('core/misc/ajax.js');
-    _drupal_add_js('core/misc/collapse.js', array('every_page' => TRUE));
-    _drupal_add_js('core/misc/autocomplete.js');
-    _drupal_add_js('core/misc/batch.js', array('every_page' => TRUE));
+    $attached = array();
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js']['core/misc/ajax.js'] = array();
+    $attached['#attached']['js']['core/misc/collapse.js'] = array('every_page' => TRUE);
+    $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
+    $attached['#attached']['js']['core/misc/batch.js'] = array('every_page' => TRUE);
+    drupal_render($attached);
     $js_items = _drupal_add_js();
     $javascript = drupal_get_js();
     $expected = implode("\n", array(
@@ -356,9 +442,11 @@ function testAggregationOrder() {
     drupal_static_reset('_drupal_add_js');
 
     // Add two JavaScript files to the current request and build the cache.
-    drupal_add_library('system', 'drupal');
-    _drupal_add_js('core/misc/ajax.js');
-    _drupal_add_js('core/misc/autocomplete.js');
+    $attached = array();
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js']['core/misc/ajax.js'] = array();
+    $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
+    drupal_render($attached);
 
     $js_items = _drupal_add_js();
     $scripts_html = array(
@@ -377,10 +465,12 @@ function testAggregationOrder() {
     // Reset variables and add a file in a different scope first.
     \Drupal::state()->delete('system.js_cache_files');
     drupal_static_reset('_drupal_add_js');
-    drupal_add_library('system', 'drupal');
-    _drupal_add_js('some/custom/javascript_file.js', array('scope' => 'footer'));
-    _drupal_add_js('core/misc/ajax.js');
-    _drupal_add_js('core/misc/autocomplete.js');
+    $attached = array();
+    $attached['#attached']['library'][] = array('system', 'drupal');
+    $attached['#attached']['js']['some/custom/javascript_file.js'] = array('scope' => 'footer');
+    $attached['#attached']['js']['core/misc/ajax.js'] = array();
+    $attached['#attached']['js']['core/misc/autocomplete.js'] = array();
+    drupal_render($attached);
 
     // Rebuild the cache.
     $js_items = _drupal_add_js();
@@ -403,17 +493,50 @@ function testAggregationOrder() {
    * Tests JavaScript ordering.
    */
   function testRenderOrder() {
+    $shared_options = array(
+      'type' => 'inline',
+      'scope' => 'footer',
+    );
     // Add a bunch of JavaScript in strange ordering.
-    _drupal_add_js('(function($){alert("Weight 5 #1");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => 5));
-    _drupal_add_js('(function($){alert("Weight 0 #1");})(jQuery);', array('type' => 'inline', 'scope' => 'footer'));
-    _drupal_add_js('(function($){alert("Weight 0 #2");})(jQuery);', array('type' => 'inline', 'scope' => 'footer'));
-    _drupal_add_js('(function($){alert("Weight -8 #1");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8));
-    _drupal_add_js('(function($){alert("Weight -8 #2");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8));
-    _drupal_add_js('(function($){alert("Weight -8 #3");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8));
-    _drupal_add_js('http://example.com/example.js?Weight -5 #1', array('type' => 'external', 'scope' => 'footer', 'weight' => -5));
-    _drupal_add_js('(function($){alert("Weight -8 #4");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => -8));
-    _drupal_add_js('(function($){alert("Weight 5 #2");})(jQuery);', array('type' => 'inline', 'scope' => 'footer', 'weight' => 5));
-    _drupal_add_js('(function($){alert("Weight 0 #3");})(jQuery);', array('type' => 'inline', 'scope' => 'footer'));
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight 5 #1");})(jQuery);',
+      'weight' => 5,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight 0 #1");})(jQuery);',
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight 0 #2");})(jQuery);',
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight -8 #1");})(jQuery);',
+      'weight' => -8,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight -8 #2");})(jQuery);',
+      'weight' => -8,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight -8 #3");})(jQuery);',
+      'weight' => -8,
+    );
+    $attached['#attached']['js']['http://example.com/example.js?Weight -5 #1'] = array(
+      'type' => 'external',
+      'scope' => 'footer',
+      'weight' => -5,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight -8 #4");})(jQuery);',
+      'weight' => -8,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight 5 #2");})(jQuery);',
+      'weight' => 5,
+    );
+    $attached['#attached']['js'][] = $shared_options + array(
+      'data' => '(function($){alert("Weight 0 #3");})(jQuery);',
+    );
+    drupal_render($attached);
 
     // Construct the expected result from the regex.
     $expected = array(
@@ -448,8 +571,13 @@ function testRenderDifferentWeight() {
     // JavaScript files are sorted first by group, then by the 'every_page'
     // flag, then by weight (see drupal_sort_css_js()), so to test the effect of
     // weight, we need the other two options to be the same.
-    drupal_add_library('system', 'jquery');
-    _drupal_add_js('core/misc/collapse.js', array('group' => JS_LIBRARY, 'every_page' => TRUE, 'weight' => -21));
+    $attached['#attached']['library'][] = array('system', 'jquery');
+    $attached['#attached']['js']['core/misc/collapse.js'] = array(
+      'group' => JS_LIBRARY,
+      'every_page' => TRUE,
+      'weight' => -21,
+    );
+    drupal_render($attached);
     $javascript = drupal_get_js();
     $this->assertTrue(strpos($javascript, 'core/misc/collapse.js') < strpos($javascript, 'core/assets/vendor/jquery/jquery.js'), 'Rendering a JavaScript file above jQuery.');
   }
@@ -461,8 +589,9 @@ function testRenderDifferentWeight() {
    */
   function testAlter() {
     // Add both tableselect.js and simpletest.js, with a larger weight on SimpleTest.
-    _drupal_add_js('core/misc/tableselect.js');
-    _drupal_add_js(drupal_get_path('module', 'simpletest') . '/simpletest.js', array('weight' => 9999));
+    $attached['#attached']['js']['core/misc/tableselect.js'] = array();
+    $attached['#attached']['js'][drupal_get_path('module', 'simpletest') . '/simpletest.js'] = array('weight' => 9999);
+    drupal_render($attached);
 
     // Render the JavaScript, testing if simpletest.js was altered to be before
     // tableselect.js. See simpletest_js_alter() to see where this alteration
@@ -475,14 +604,17 @@ function testAlter() {
    * Adds a library to the page and tests for both its JavaScript and its CSS.
    */
   function testLibraryRender() {
-    $result = drupal_add_library('system', 'jquery.farbtastic');
-    $this->assertTrue($result !== FALSE, 'Library was added without errors.');
+    $attached = array();
+    $attached['#attached']['library'][] = array('system', 'jquery.farbtastic');
+    drupal_render($attached);
     $scripts = drupal_get_js();
     $styles = drupal_get_css();
     $this->assertTrue(strpos($scripts, 'core/assets/vendor/farbtastic/farbtastic.js'), 'JavaScript of library was added to the page.');
     $this->assertTrue(strpos($styles, 'core/assets/vendor/farbtastic/farbtastic.css'), 'Stylesheet of library was added to the page.');
 
-    drupal_add_library('common_test', 'shorthand.plugin');
+    $attached = array();
+    $attached['#attached']['library'][] = array('common_test', 'shorthand.plugin');
+    drupal_render($attached);
     $path = drupal_get_path('module', 'common_test') . '/js/shorthand.js?v=0.8.3.37';
     $scripts = drupal_get_js();
     $this->assertTrue(strpos($scripts, $path), 'JavaScript specified in hook_library_info() using shorthand format (without any options) was added to the page.');
@@ -500,7 +632,8 @@ function testLibraryAlter() {
     $this->assertEqual($library['title'], 'Farbtastic: Altered Library', 'Registered libraries were altered.');
 
     // common_test_library_info_alter() also added a dependency on jQuery Form.
-    drupal_add_library('system', 'jquery.farbtastic');
+    $attached['#attached']['library'][] = array('system', 'jquery.farbtastic');
+    drupal_render($attached);
     $scripts = drupal_get_js();
     $this->assertTrue(strpos($scripts, 'core/assets/vendor/jquery-form/jquery.form.js'), 'Altered library dependencies are added to the page.');
   }
@@ -523,8 +656,8 @@ function testLibraryUnknown() {
     $this->assertFalse($result, 'Unknown library returned FALSE.');
     drupal_static_reset('drupal_get_library');
 
-    $result = drupal_add_library('unknown', 'unknown');
-    $this->assertFalse($result, 'Unknown library returned FALSE.');
+    $attached['#attached']['library'][] = array('unknown', 'unknown');
+    drupal_render($attached);
     $scripts = drupal_get_js();
     $this->assertTrue(strpos($scripts, 'unknown') === FALSE, 'Unknown library was not added to the page.');
   }
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 1de6b15..ae1b38e 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -311,7 +311,7 @@ function hook_js_alter(&$javascript) {
  *   An array defining libraries associated with a module.
  *
  * @see system_library_info()
- * @see drupal_add_library()
+ * @see _drupal_add_library()
  * @see drupal_get_library()
  */
 function hook_library_info() {
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index fc6f61c..1afa5e2 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -1260,6 +1260,7 @@ function system_library_info() {
     'version' => '3.6.2',
     'js' => array(
       'core/assets/vendor/html5shiv/html5.js' => array(
+        'every_page' => TRUE,
         'group' => JS_LIBRARY,
         'weight' => -22,
         'browsers' => array('IE' => 'lte IE 8', '!IE' => FALSE),
@@ -2183,7 +2184,7 @@ function system_user_timezone(&$form, &$form_state) {
   if (!$account->getTimezone() && $account->id() == $user->id() && empty($form_state['input']['timezone'])) {
     $form['timezone']['#description'] = t('Your time zone setting will be automatically detected if possible. Confirm the selection and click save.');
     $form['timezone']['timezone']['#attributes'] = array('class' => array('timezone-detect'));
-    drupal_add_library('system', 'drupal.timezone');
+    $form['#attached']['library'][] = array('system', 'drupal.timezone');
   }
 }
 
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index fe427b0..c30c940 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -360,7 +360,8 @@ function views_preprocess_page(&$variables) {
       unset($class[$key]);
       $attributes['class'] = $class;
       $attributes['data-views-page-contextual-id'] = $variables['title_suffix']['contextual_links']['#id'];
-      drupal_add_library('views', 'views.contextual-links');
+      $attached['#attached']['library'][] = array('views', 'views.contextual-links');
+      drupal_render($attached);
     }
   }
 }
diff --git a/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php b/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php
index 188c042..bd6b27d 100644
--- a/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php
+++ b/core/tests/Drupal/Tests/Core/Ajax/AjaxCommandsTest.php
@@ -5,7 +5,7 @@
  * Contains \Drupal\Tests\Core\Ajax\AjaxCommandsTest.
  */
 
-namespace Drupal\Tests\Core\Ajax {
+namespace Drupal\Tests\Core\Ajax;
 
 use Drupal\Tests\UnitTestCase;
 use Drupal\Core\Ajax\AddCssCommand;
@@ -424,13 +424,3 @@ public function testRedirectCommand() {
   }
 
 }
-
-}
-
-namespace {
-  if (!function_exists('drupal_add_library')) {
-    function drupal_add_library() {
-      return TRUE;
-    }
-  }
-}
