The Bug
Blocks destroyed by the creeper and the wither will drop the items, but blocks destroyed by the ender dragon doesn't.
Steps to Reproduce
Place a bunch of blocks that can be destroyed by the ender dragon
Have the ender dragon destroy the blocks
The blocks won't drop even when /gamerule doTileDrops is set to true.
Code Analysis
Code analysis by @unknown can be found in this comment.
Linked issues
Comments

Can confirm. As stated above, this may be intentional.
Can confirm in 21w11a.
Can confirm in 21w13a.
I can also confirm this behavior in 1.18.1 and 22w06a.
Here's a code analysis regarding this issue.
Code Analysis:
The following is based on a decompiled version of Minecraft 1.18.1 using MCP-Reborn.
net.minecraft.world.entity.boss.enderdragon.EnderDragon.java
public class EnderDragon extends Mob implements Enemy {
...
private boolean checkWalls(AABB $aabb) {
int i = Mth.floor($aabb.minX);
int j = Mth.floor($aabb.minY);
int k = Mth.floor($aabb.minZ);
int l = Mth.floor($aabb.maxX);
int i1 = Mth.floor($aabb.maxY);
int j1 = Mth.floor($aabb.maxZ);
boolean flag = false;
boolean flag1 = false;
for(int k1 = i; k1 <= l; ++k1) {
for(int l1 = j; l1 <= i1; ++l1) {
for(int i2 = k; i2 <= j1; ++i2) {
BlockPos blockpos = new BlockPos(k1, l1, i2);
BlockState blockstate = this.level.getBlockState(blockpos);
if (!blockstate.isAir() && blockstate.getMaterial() != Material.FIRE) {
if (this.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING) && !blockstate.is(BlockTags.DRAGON_IMMUNE)) {
flag1 = this.level.removeBlock(blockpos, false) || flag1;
} else {
flag = true;
}
}
}
}
}
...
If we look at the above class, we can see that the removeBlock()
method is called and is responsible for removing blocks that can be destroyed by the ender dragon, if this boss were to get close to them. This is evident through the following line of code:
flag1 = this.level.removeBlock(blockpos, false) || flag1;
The problem here is that the removeBlock()
method is simply designed to remove the desired block and not drop it. In other words, because the block is removed and not destroyed, no block drops are created.
This might be intended.